Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changesets/1791385567-923326e3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
id: 1791385567-923326e3
features:
- cliCommands
targets:
- cli
type: fix
bump: patch
description: resume async intents with their polling and artifact output and preserve raw JSON on stream-capable operations
author: ThomasRooney
date: "2026-10-07"
1 change: 1 addition & 0 deletions internal/extensions/cli_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ var cliReservedFlagNames = map[string]bool{
// adding an async recipe cannot turn a previously valid flag into a
// generated pflag collision.
"async": true,
"resume": true,
"poll-interval": true,
"poll-timeout": true,
}
Expand Down
2 changes: 1 addition & 1 deletion internal/extensions/cli_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2759,7 +2759,7 @@ commands:
out: {to: $.engine}
`, `flag name "out" is reserved`)

for _, name := range []string{"async", "poll-interval", "poll-timeout"} {
for _, name := range []string{"async", "resume", "poll-interval", "poll-timeout"} {
t.Run("reserved async flag "+name, func(t *testing.T) {
requireDecodeError(t, fmt.Sprintf(`
version: 1
Expand Down
25 changes: 25 additions & 0 deletions templates/templates/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,8 @@ Operation-declared names are checked against generated parameter/body/security f

The projection annotation is attached only to the operation command. SSE-overload operations need no decode-time branch: `StreamResult` projects a real stream and already falls back to normal `Result` output when `--stream=false` produces JSON (including completed-interaction replay APIs). Generated long help explains raw projection, `--stream=false`, and `-o json`; static KDL and live `--usage` include operation-declared flags, and Cobra-generated docs inherit the same flags/help.

Explicit JSON/jq output prepares raw response handling before calling stream-capable operations, so a JSON response can be printed even when its known fields no longer match the generated schema. Actual SSE and JSONL responses still use their streaming decoders.

Ordinary typed `Result` extraction never treats a value with `Next` and `Value` methods as renderable response content; stream wrappers belong exclusively to `StreamResult`. This also keeps a streaming dry-run silent in implicit pretty mode when the dry-run client creates an empty synthetic stream. Explicit JSON dry-runs print the `{"dry_run":true,"request":{...}}` preview object like every other operation.

#### Artifact intent output (`output.artifact`)
Expand Down Expand Up @@ -1073,6 +1075,29 @@ Artifact intents register `--out` and `--raw-response`. When a missing required

The returned MIME type controls a file destination's extension. A matching extension stays unchanged; a missing extension is appended silently; a conflicting extension is rewritten and stderr receives one line such as `Note: wrote image/png as photo.png (requested photo.jpg)`. Like the human-only `Wrote image to ...` status, the note is suppressed in machine modes (agent mode, `--jq`, non-pretty/table formats): the envelope already carries the final path and success keeps stderr silent there. `--out` is output routing only and never participates in request-body source/merge rules.

### Resuming async intents

`intentcmd.go.stmpl` registers `--resume <id>` for commands with an async recipe.
It polls the existing operation using the recipe's parameters, states and timing,
then uses the same output and artifact handling as a normal create-and-wait call.
It never creates another operation. Create arguments, request flags and `--async`
are incompatible with resume; body files and stdin are not read, and create-input
forms are not opened. Authentication, server selection, output flags,
`--poll-interval` and `--poll-timeout` remain available.

`auxiliary/internal/output/async.go.stmpl` shares the polling loop between creation
and resume. `--dry-run --resume <id>` previews one poll request without network
calls or artifact writes. Human `--async` output prints the handle on stdout and
a resume command on stderr. Structured modes retain their existing payload and
silent stderr. Timeout/error hints also name the original intent with `--resume`
and shell-quote the handle. Output paths are not retained in hints: pass `--out`
again when resuming to select the destination.

Artifact output supports inline base64 content. URI-only content retains the
explicit unsupported-download error and does not create an artifact file.
`--raw-response` prints the terminal payload instead of writing an artifact.
The `--resume` flag description in help and static/live `--usage` describes polling an existing operation by ID instead of creating one. Conflict errors explain incompatible inputs.

### Binary Downloads

**Files**: `opcmd.go.stmpl` (flag registration + branching), `auxiliary/internal/output/output.go.stmpl` (binary detection in `Result()`), `auxiliary/internal/output/binary.go.stmpl` (`WriteToFile`, TTY detection), `includes/templating.ts` (`hasBinaryResponse`, `isOnlyBinaryResponse`, `anyOperationHasBinary`)
Expand Down
Loading
Loading