@gavana.ai/cli 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +8 -2
- package/guides/generated-assets.md +1 -1
- package/guides/paid-action-safety.md +1 -1
- package/package.json +1 -1
- package/src/canvas-agent-guide.mjs +2 -2
- package/src/commands.mjs +3 -3
- package/src/guide-sources.mjs +2 -2
- package/src/mcp-targets.mjs +1 -1
- package/src/runner.mjs +14 -19
- package/src/tools/image_tool.mjs +1 -1
- package/src/tools/schemas.mjs +1 -1
- package/src/version.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog — @gavana.ai/cli
|
|
2
2
|
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Image commands and MCP tools now return immediately after the durable Canvas
|
|
8
|
+
targets and Run are queued. Use `--wait` in the CLI or `wait: true` in an MCP
|
|
9
|
+
call when the completed image is required in the same interaction.
|
|
10
|
+
- Distinct local image references upload concurrently while their original
|
|
11
|
+
reference order and duplicate-upload reuse remain stable.
|
|
12
|
+
|
|
3
13
|
## 0.2.1
|
|
4
14
|
|
|
5
15
|
### Fixed
|
package/README.md
CHANGED
|
@@ -114,6 +114,7 @@ gavana action list
|
|
|
114
114
|
gavana action get action:resize
|
|
115
115
|
gavana action run action:resize --input ./product.png --destination agent-canvas --width 1080 --height 1350
|
|
116
116
|
gavana image generate --destination agent-canvas --model model:OPAQUE_MODEL_KEY --prompt "A studio product photograph"
|
|
117
|
+
gavana image generate --destination agent-canvas --prompt "A studio product photograph" --wait
|
|
117
118
|
gavana model list --capability video.generate
|
|
118
119
|
gavana video generate --model model:OPAQUE_MODEL_KEY --prompt "A slow product turntable" --duration 15 --aspect-ratio 9:16 --download ./turntable.mp4
|
|
119
120
|
gavana video generate --model model:OPAQUE_MODEL_KEY --prompt "Animate the fabric naturally" --first-frame ./product.png --no-wait
|
|
@@ -179,8 +180,13 @@ text-only Recipes.
|
|
|
179
180
|
|
|
180
181
|
Recipe, image, and Action work returns a shared `run:` handle with typed outputs,
|
|
181
182
|
duration estimates, observed queue/execution timing, and stable retry guidance.
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
Image commands return as soon as Gavana has created the durable Canvas targets
|
|
184
|
+
and queued the Run, so the caller can continue while generation proceeds. Add
|
|
185
|
+
`--wait` only when the completed image is needed in the same command. `--no-wait`
|
|
186
|
+
remains accepted for existing image scripts. Recipe and Action commands retain
|
|
187
|
+
their existing wait-by-default behavior. Waiting and `run get|wait|cancel`
|
|
188
|
+
require `job:manage`; a start-only token can queue image work directly or use
|
|
189
|
+
`--no-wait` with a signed webhook.
|
|
184
190
|
The legacy `job:` handle remains an image and Action compatibility alias; it is
|
|
185
191
|
never used for Recipes. Image and Action `run:` and `job:` handles point to the
|
|
186
192
|
same temporary record and expire together:
|
|
@@ -25,7 +25,7 @@ order: 6
|
|
|
25
25
|
|
|
26
26
|
## Paid execution
|
|
27
27
|
|
|
28
|
-
Generation is allowed only after explicit current-turn user intent. Start one run with one caller-stable idempotency key.
|
|
28
|
+
Generation is allowed only after explicit current-turn user intent. Start one run with one caller-stable idempotency key. Image tools return durable queued progress by default; report that progress immediately and do not automatically call `run_wait`. Call `run_wait` only when the current user explicitly needs the completed asset in this same interaction. Otherwise, a later `run_get` or Canvas read can observe progress and the durable output. Do not start another run while one is pending. A terminal failure must be reported without automatic retry.
|
|
29
29
|
|
|
30
30
|
## Completion
|
|
31
31
|
|
|
@@ -15,7 +15,7 @@ Start paid work only when the current user message explicitly asks to run or gen
|
|
|
15
15
|
## Retry boundary
|
|
16
16
|
|
|
17
17
|
- Use one stable idempotency key for one intended paid operation.
|
|
18
|
-
-
|
|
18
|
+
- Return an image Run's durable queued progress immediately. Do not call `run_wait` unless the current user explicitly needs the completed asset in this same interaction; otherwise observe it later with `run_get` or a Canvas read.
|
|
19
19
|
- Never automatically retry a terminal failure, timeout, disconnect, or ambiguous provider response with a new key.
|
|
20
20
|
- Ask for new user intent before any new paid attempt.
|
|
21
21
|
|
package/package.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
// ./canvas-agent-validation.mjs in guide version 1.5.0.
|
|
5
5
|
import { GAVANA_CANVAS_GUIDE_SOURCES } from "./guide-sources.mjs";
|
|
6
6
|
|
|
7
|
-
export const GAVANA_CANVAS_GUIDE_VERSION = "1.5.
|
|
7
|
+
export const GAVANA_CANVAS_GUIDE_VERSION = "1.5.1";
|
|
8
8
|
export const GAVANA_CANVAS_GUIDE_INDEX_URI = `gavana://guides/canvas/v${GAVANA_CANVAS_GUIDE_VERSION.split(".")[0]}/index`;
|
|
9
9
|
export const GAVANA_CANVAS_GUIDE_WORKFLOW_INSTRUCTION =
|
|
10
|
-
"For the first canvas task in a session, and before any unfamiliar canvas operation, inspect the relevant guide through MCP resources or call guide_search then guide_get. Before changing an existing canvas, call canvas_get. For spatial, multi-node, or destructive work, call canvas_validate with the proposed operations, apply one revision-safe atomic batch, then call canvas_validate again. Campaign work must read creative-canvas and use a reference-led concept before image output. Before image or video generation, call model_list for the required capability and use its exact model: handle; a bare model name does not select a saved connection. If no matching model is returned, report that the agent account cannot access the connection instead of asking the user to add a key again. When a standalone image fallback uses visual references, forward every exact node:/asset: handle (and each known role) in the image request; never reduce that work to a prompt-only generation. After an image or workflow finishes, read completionReview. Never claim Done while completionReview.doneClaimAllowed is false, delivery is pending, failed, or non-durable, or blocking findings remain. Render campaign compositions for visual inspection. Treat legacy warnings as review items, not permission to rewrite unrelated work.";
|
|
10
|
+
"For the first canvas task in a session, and before any unfamiliar canvas operation, inspect the relevant guide through MCP resources or call guide_search then guide_get. Before changing an existing canvas, call canvas_get. For spatial, multi-node, or destructive work, call canvas_validate with the proposed operations, apply one revision-safe atomic batch, then call canvas_validate again. Campaign work must read creative-canvas and use a reference-led concept before image output. Before image or video generation, call model_list for the required capability and use its exact model: handle; a bare model name does not select a saved connection. If no matching model is returned, report that the agent account cannot access the connection instead of asking the user to add a key again. When a standalone image fallback uses visual references, forward every exact node:/asset: handle (and each known role) in the image request; never reduce that work to a prompt-only generation. Image tools return durable queued progress by default; report it immediately and call run_wait only when the current user explicitly needs the completed asset in the same interaction. A later run_get or Canvas read can observe progress. After an image or workflow finishes, read completionReview. Never claim Done while completionReview.doneClaimAllowed is false, delivery is pending, failed, or non-durable, or blocking findings remain. Render campaign compositions for visual inspection. Treat legacy warnings as review items, not permission to rewrite unrelated work.";
|
|
11
11
|
export const GAVANA_CANVAS_GUIDE_READ_ONLY_INSTRUCTION =
|
|
12
12
|
"For the first canvas task in a session, and before any unfamiliar canvas review, inspect the relevant guide through MCP resources or call guide_search then guide_get. Call canvas_get before reasoning about an existing canvas, and use canvas_validate to audit its current graph. Treat validation warnings as review items and never claim to mutate the canvas.";
|
|
13
13
|
|
package/src/commands.mjs
CHANGED
|
@@ -144,9 +144,9 @@ export const GAVANA_CLI_COMMANDS = Object.freeze([
|
|
|
144
144
|
"gavana action run action:side-by-side-composite --input node:<id> --input asset:<id> --destination canvas:<id>",
|
|
145
145
|
],
|
|
146
146
|
},
|
|
147
|
-
{ group: "image", action: "generate", usage: ["gavana image generate --destination agent-canvas --prompt \"...\" [--element element:<id>@v<n>]"] },
|
|
148
|
-
{ group: "image", action: "edit", usage: ["gavana image edit --destination canvas:<id> --reference path/to/image.png --prompt \"...\""] },
|
|
149
|
-
{ group: "image", action: "variations", usage: ["gavana image variations --destination new-canvas --canvas-title \"Variations\" --reference path/to/source.png --prompt \"...\""] },
|
|
147
|
+
{ group: "image", action: "generate", usage: ["gavana image generate --destination agent-canvas --prompt \"...\" [--element element:<id>@v<n>] [--wait]"] },
|
|
148
|
+
{ group: "image", action: "edit", usage: ["gavana image edit --destination canvas:<id> --reference path/to/image.png --prompt \"...\" [--wait]"] },
|
|
149
|
+
{ group: "image", action: "variations", usage: ["gavana image variations --destination new-canvas --canvas-title \"Variations\" --reference path/to/source.png --prompt \"...\" [--wait]"] },
|
|
150
150
|
{ group: "video", action: "generate", usage: ["gavana video generate --model model:<id> --prompt \"...\" --duration 15", "gavana video generate --model model:<id> --prompt \"...\" --first-frame path/to/start.png --no-wait", "gavana video generate --model model:<id> --prompt \"...\" --download output.mp4"] },
|
|
151
151
|
{ group: "video", action: "download", usage: ["gavana video download job:<id> --file output.mp4 [--yes]"] },
|
|
152
152
|
{ group: "job", action: "get", usage: ["gavana job get job:<id>"] },
|
package/src/guide-sources.mjs
CHANGED
|
@@ -49,7 +49,7 @@ export const GAVANA_CANVAS_GUIDE_SOURCES = Object.freeze([
|
|
|
49
49
|
description: "Prepare media nodes, start only explicit generation, and preserve output lineage.",
|
|
50
50
|
keywords: Object.freeze(["generated","generation","image","video","output","asset","durable","lineage","placeholder","job"]),
|
|
51
51
|
order: 6,
|
|
52
|
-
markdown: "\n## Before generation\n\n- Read the destination canvas and relevant source nodes.\n- Use exact source `node:` or `asset:` handles.\n- Before image or video generation, call `model_list` for the required capability and pass its exact `model:` handle. A bare model name does not select a saved connection. If no matching model is returned, report that the agent account cannot access that connection; do not ask the user to add a key again.\n- For a standalone image request, pass every visual source in `references`.\n Use `{ \"handle\": \"node:...\", \"role\": \"identity\" }` when its\n responsibility is known; valid roles are `identity`, `construction`,\n `texture`, `fit`, and `style`. Do not flatten multi-reference work\n into prompt prose or omit a source during fallback.\n- Reuse existing Canvas `node:` or `asset:` handles directly. Do not download\n and re-upload a generated Canvas image merely to use it as the next\n generation's reference. State whether a style reference establishes the\n brand-world or typography/layout direction in the prompt.\n- Create an empty image or video target only through supported operations. Do not write media bytes, storage keys, or arbitrary output URLs into metadata.\n- Connect prompts, products, references, Lists, and frame inputs to their target with the correct direction and mode.\n\n## Paid execution\n\nGeneration is allowed only after explicit current-turn user intent. Start one run with one caller-stable idempotency key.
|
|
52
|
+
markdown: "\n## Before generation\n\n- Read the destination canvas and relevant source nodes.\n- Use exact source `node:` or `asset:` handles.\n- Before image or video generation, call `model_list` for the required capability and pass its exact `model:` handle. A bare model name does not select a saved connection. If no matching model is returned, report that the agent account cannot access that connection; do not ask the user to add a key again.\n- For a standalone image request, pass every visual source in `references`.\n Use `{ \"handle\": \"node:...\", \"role\": \"identity\" }` when its\n responsibility is known; valid roles are `identity`, `construction`,\n `texture`, `fit`, and `style`. Do not flatten multi-reference work\n into prompt prose or omit a source during fallback.\n- Reuse existing Canvas `node:` or `asset:` handles directly. Do not download\n and re-upload a generated Canvas image merely to use it as the next\n generation's reference. State whether a style reference establishes the\n brand-world or typography/layout direction in the prompt.\n- Create an empty image or video target only through supported operations. Do not write media bytes, storage keys, or arbitrary output URLs into metadata.\n- Connect prompts, products, references, Lists, and frame inputs to their target with the correct direction and mode.\n\n## Paid execution\n\nGeneration is allowed only after explicit current-turn user intent. Start one run with one caller-stable idempotency key. Image tools return durable queued progress by default; report that progress immediately and do not automatically call `run_wait`. Call `run_wait` only when the current user explicitly needs the completed asset in this same interaction. Otherwise, a later `run_get` or Canvas read can observe progress and the durable output. Do not start another run while one is pending. A terminal failure must be reported without automatic retry.\n\n## Completion\n\nDo not claim a generated image is durable until the result returns a target `node:`, durable `asset:`, and the final canvas read shows server-owned media fields. A video Job may return a protected download without materializing a native video node; report exactly what the server returned and do not invent durability.\n\nKeep generated output spatially near its input stage and connected to its source, prompt, List, or workflow. After finalization, run `canvas_validate` and read `completionReview`: it reports overlap, full-frame Section containment, reference lineage, and delivery state. Do not claim Done while it says `doneClaimAllowed: false`, including when delivery is pending, failed, or non-durable. Render the Canvas for visual inspection when the request includes a campaign, poster, banner, or multi-direction composition. Reference provenance is not a user workflow state and never requires a Keep action. Never create another paid provider call automatically.\n",
|
|
53
53
|
}),
|
|
54
54
|
Object.freeze({
|
|
55
55
|
id: "existing-canvases",
|
|
@@ -65,7 +65,7 @@ export const GAVANA_CANVAS_GUIDE_SOURCES = Object.freeze([
|
|
|
65
65
|
description: "Separate preparation from execution and prevent accidental or repeated provider charges.",
|
|
66
66
|
keywords: Object.freeze(["paid","credits","cost","generate","run","retry","failure","prepare","setup","explicit"]),
|
|
67
67
|
order: 8,
|
|
68
|
-
markdown: "\n## Intent boundary\n\n\"Build\", \"prepare\", \"set up\", \"connect\", \"draft\", and \"make ready\" authorize graph edits only. They do not authorize Recipe, image, video, or Action execution.\n\nStart paid work only when the current user message explicitly asks to run or generate it. Do not infer authorization from an older message, a node label, an unfinished placeholder, or nearby content.\n\n## Retry boundary\n\n- Use one stable idempotency key for one intended paid operation.\n-
|
|
68
|
+
markdown: "\n## Intent boundary\n\n\"Build\", \"prepare\", \"set up\", \"connect\", \"draft\", and \"make ready\" authorize graph edits only. They do not authorize Recipe, image, video, or Action execution.\n\nStart paid work only when the current user message explicitly asks to run or generate it. Do not infer authorization from an older message, a node label, an unfinished placeholder, or nearby content.\n\n## Retry boundary\n\n- Use one stable idempotency key for one intended paid operation.\n- Return an image Run's durable queued progress immediately. Do not call `run_wait` unless the current user explicitly needs the completed asset in this same interaction; otherwise observe it later with `run_get` or a Canvas read.\n- Never automatically retry a terminal failure, timeout, disconnect, or ambiguous provider response with a new key.\n- Ask for new user intent before any new paid attempt.\n\nDeterministic Actions may be described as credit-free only when `action_get` confirms that contract. Inspect an Action before running it.\n",
|
|
69
69
|
}),
|
|
70
70
|
Object.freeze({
|
|
71
71
|
id: "validation-recovery",
|
package/src/mcp-targets.mjs
CHANGED
|
@@ -49,7 +49,7 @@ export function gavanaMcpClientDefinition(clientName, baseUrl, readOnly = false)
|
|
|
49
49
|
transport: "stdio",
|
|
50
50
|
serverName,
|
|
51
51
|
command: "npx",
|
|
52
|
-
args: ["-y", "@gavana.ai/mcp@0.2.
|
|
52
|
+
args: ["-y", "@gavana.ai/mcp@0.2.1"],
|
|
53
53
|
env: readOnly ? { GAVANA_MCP_READ_ONLY: "true" } : {},
|
|
54
54
|
credentialSource: "Reads the active Gavana CLI profile or inherited GAVANA_BASE_URL and GAVANA_AGENT_TOKEN environment variables.",
|
|
55
55
|
};
|
package/src/runner.mjs
CHANGED
|
@@ -504,11 +504,11 @@ async function executeCommand(client, group, action, args, options, runtime) {
|
|
|
504
504
|
}
|
|
505
505
|
|
|
506
506
|
if (group === "image" && (action === "generate" || action === "edit" || action === "variations")) {
|
|
507
|
+
if (options.wait === true && options["no-wait"] === true) throw usageError("--wait and --no-wait cannot be combined.");
|
|
507
508
|
const prepared = await imageInput(client, action, args, options, runtime);
|
|
508
509
|
const { __destination, ...input } = prepared;
|
|
509
510
|
const queued = await client.startImage(action, input);
|
|
510
|
-
|
|
511
|
-
if (!shouldWait) return { ...queued, destination: __destination };
|
|
511
|
+
if (options.wait !== true) return { ...queued, destination: __destination };
|
|
512
512
|
const result = await client.waitForRun(queued.run || queued.id, {
|
|
513
513
|
timeoutMs: secondsOption(options.timeout, 15 * 60) * 1000,
|
|
514
514
|
intervalMs: secondsOption(options.interval, 1.5, true) * 1000,
|
|
@@ -1580,23 +1580,17 @@ function ensureUniqueVideoReferences(references) {
|
|
|
1580
1580
|
}
|
|
1581
1581
|
|
|
1582
1582
|
async function uploadLocalReferenceInputs(client, references, canvasReference) {
|
|
1583
|
-
const handles = [];
|
|
1584
1583
|
const uploads = new Map();
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
}
|
|
1594
|
-
|
|
1595
|
-
if (!uploads.has(fingerprint)) uploads.set(fingerprint, client.uploadAsset({ ...reference, canvasReference }));
|
|
1596
|
-
const uploaded = await uploads.get(fingerprint);
|
|
1597
|
-
handles.push(uploaded.asset.handle);
|
|
1598
|
-
}
|
|
1599
|
-
return handles;
|
|
1584
|
+
return Promise.all(
|
|
1585
|
+
references.map(async (reference) => {
|
|
1586
|
+
if (reference.kind === "handle") return reference.handle;
|
|
1587
|
+
if (reference.kind === "url") return reference.url;
|
|
1588
|
+
const fingerprint = crypto.createHash("sha256").update(reference.bytes).digest("base64url");
|
|
1589
|
+
if (!uploads.has(fingerprint)) uploads.set(fingerprint, client.uploadAsset({ ...reference, canvasReference }));
|
|
1590
|
+
const uploaded = await uploads.get(fingerprint);
|
|
1591
|
+
return uploaded.asset.handle;
|
|
1592
|
+
}),
|
|
1593
|
+
);
|
|
1600
1594
|
}
|
|
1601
1595
|
|
|
1602
1596
|
async function readMacClipboardImage() {
|
|
@@ -2052,7 +2046,8 @@ Global options:
|
|
|
2052
2046
|
--webhook-url URL Send one signed callback when a Run finishes
|
|
2053
2047
|
--webhook-secret-env VAR Read the signing secret from VAR (default: GAVANA_WEBHOOK_SECRET)
|
|
2054
2048
|
--canvas-title VALUE Title used when --destination is new-canvas
|
|
2055
|
-
--
|
|
2049
|
+
--wait Wait for an image Run to finish instead of returning after queueing
|
|
2050
|
+
--no-wait Return immediately after queueing Recipe, video, or Action work (legacy image alias)
|
|
2056
2051
|
--progress Write Run or video Job state transitions to stderr
|
|
2057
2052
|
|
|
2058
2053
|
Video options:
|
package/src/tools/image_tool.mjs
CHANGED
|
@@ -48,7 +48,7 @@ export function imageToolDefinition(operation, client) {
|
|
|
48
48
|
idempotencyKey: input.idempotencyKey,
|
|
49
49
|
});
|
|
50
50
|
const destinationResult = { requested: destination, canvasId: prepared.canvasId, targetNodeIds: prepared.targetNodeIds };
|
|
51
|
-
if (input.wait
|
|
51
|
+
if (input.wait !== true) return { ...queued, destination: destinationResult };
|
|
52
52
|
const result = await client.waitForRun(queued.run || queued.id, withProgress({ timeoutMs: (input.timeoutSeconds || 900) * 1000 }, extra));
|
|
53
53
|
return { ...result, destination: destinationResult };
|
|
54
54
|
},
|
package/src/tools/schemas.mjs
CHANGED
|
@@ -166,7 +166,7 @@ function imageSchema() {
|
|
|
166
166
|
size: z.string().max(80).optional(),
|
|
167
167
|
quality: z.string().max(80).optional(),
|
|
168
168
|
count: z.number().int().min(1).max(4).optional(),
|
|
169
|
-
wait: z.boolean().default(true),
|
|
169
|
+
wait: z.boolean().default(false).describe("Return after queueing by default. Set true to wait for the completed Run."),
|
|
170
170
|
timeoutSeconds: z.number().min(1).max(3_600).default(900),
|
|
171
171
|
});
|
|
172
172
|
}
|
package/src/version.mjs
CHANGED