feat(cli): --stdin piped JSON payloads for structured commands (T-315)

The C client slurps stdin when it sees --stdin, strips the flag, and ships
the payload alongside the argv; the Dart unwrap folds it into the request
as a `stdin` arg (undeclared keys pass the schema untouched). icon.show and
image.show now read that payload as the peer of --file (stdin wins). Bounded
slurp + the envelope's existing size guard keep a huge payload from
corrupting the wire. C client builds clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-29 23:56:33 +02:00
co-authored by Claude Opus 4.8
parent 1f6d31ac73
commit 64410e8047
10 changed files with 160 additions and 21 deletions
+15 -1
View File
@@ -36,7 +36,21 @@ ArgvParseResult unwrapArgvRequest(IpcRequest outer) {
),
);
}
return parseArgv(raw.cast<String>(), requestId: outer.id);
final result = parseArgv(raw.cast<String>(), requestId: outer.id);
// A piped `--stdin` payload (T-315): the C client slurps stdin and ships it
// alongside the argv. Fold it into the inner request as a `stdin` flag so it
// surfaces as a named arg (undeclared keys pass the schema untouched) — the
// handler reads it as the structured payload, the piped peer of `--file`.
final stdin = outer.args['stdin'];
if (result is ArgvParsed && stdin is String) {
final req = result.request;
final args = Map<String, Object?>.from(req.args);
final flags = Map<String, Object?>.from((args['flags'] as Map?) ?? const {});
flags['stdin'] = stdin;
args['flags'] = flags;
return ArgvParsed(IpcRequest(id: req.id, cmd: req.cmd, args: args));
}
return result;
}
/// Wire the `_argv` sentinel handler onto [dispatcher]. The handler