@gavana.ai/cli 0.2.0
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 +54 -0
- package/LICENSE.md +7 -0
- package/README.md +237 -0
- package/bin/craftboard.mjs +5 -0
- package/bin/gavana.mjs +5 -0
- package/guides/connections.md +35 -0
- package/guides/examples-common-mistakes.md +29 -0
- package/guides/existing-canvases.md +19 -0
- package/guides/generated-assets.md +29 -0
- package/guides/getting-started.md +26 -0
- package/guides/notes-text-sections.md +44 -0
- package/guides/paid-action-safety.md +22 -0
- package/guides/prompt-lists.md +20 -0
- package/guides/sections-layout.md +43 -0
- package/guides/validation-recovery.md +33 -0
- package/package.json +44 -0
- package/src/canvas-agent-guide.mjs +133 -0
- package/src/canvas-agent-validation.mjs +554 -0
- package/src/canvas-layout.mjs +287 -0
- package/src/capabilities.mjs +61 -0
- package/src/client.mjs +1141 -0
- package/src/commands.mjs +259 -0
- package/src/config.mjs +197 -0
- package/src/guide-sources.mjs +86 -0
- package/src/runner.mjs +1968 -0
- package/src/tools/action_get.mjs +16 -0
- package/src/tools/action_list.mjs +21 -0
- package/src/tools/action_run.mjs +60 -0
- package/src/tools/agent_canvas_get.mjs +15 -0
- package/src/tools/asset_get.mjs +16 -0
- package/src/tools/asset_list.mjs +17 -0
- package/src/tools/asset_upload.mjs +24 -0
- package/src/tools/campaign_cancel.mjs +16 -0
- package/src/tools/campaign_get.mjs +16 -0
- package/src/tools/campaign_plan.mjs +31 -0
- package/src/tools/campaign_review.mjs +24 -0
- package/src/tools/campaign_start.mjs +19 -0
- package/src/tools/canvas_apply_batch.mjs +35 -0
- package/src/tools/canvas_create.mjs +15 -0
- package/src/tools/canvas_get.mjs +16 -0
- package/src/tools/canvas_list.mjs +17 -0
- package/src/tools/canvas_render.mjs +34 -0
- package/src/tools/canvas_validate.mjs +34 -0
- package/src/tools/connection_create.mjs +38 -0
- package/src/tools/connection_delete.mjs +31 -0
- package/src/tools/definitions.mjs +111 -0
- package/src/tools/guide_get.mjs +16 -0
- package/src/tools/guide_search.mjs +16 -0
- package/src/tools/helpers.mjs +66 -0
- package/src/tools/image_edit.mjs +8 -0
- package/src/tools/image_generate.mjs +8 -0
- package/src/tools/image_tool.mjs +56 -0
- package/src/tools/image_variations.mjs +8 -0
- package/src/tools/job_cancel.mjs +16 -0
- package/src/tools/job_get.mjs +17 -0
- package/src/tools/job_wait.mjs +18 -0
- package/src/tools/model_get.mjs +16 -0
- package/src/tools/model_list.mjs +23 -0
- package/src/tools/node_create.mjs +36 -0
- package/src/tools/node_delete.mjs +31 -0
- package/src/tools/node_get.mjs +16 -0
- package/src/tools/node_move.mjs +37 -0
- package/src/tools/node_resize.mjs +37 -0
- package/src/tools/node_update.mjs +36 -0
- package/src/tools/progress.mjs +101 -0
- package/src/tools/provider_list.mjs +17 -0
- package/src/tools/recipe_fork.mjs +32 -0
- package/src/tools/recipe_get.mjs +19 -0
- package/src/tools/recipe_run.mjs +61 -0
- package/src/tools/recipe_search.mjs +17 -0
- package/src/tools/registry.mjs +550 -0
- package/src/tools/run_cancel.mjs +16 -0
- package/src/tools/run_get.mjs +17 -0
- package/src/tools/run_wait.mjs +18 -0
- package/src/tools/schemas.mjs +165 -0
- package/src/tools/video_generate.mjs +37 -0
- package/src/version.mjs +12 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Changelog — @gavana.ai/cli
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
First release published to npm. Version 0.1.0 existed in this repository but was
|
|
6
|
+
never published, so there is no upgrade path to describe — everything below is
|
|
7
|
+
what shipped between the two internal versions, kept here because the package
|
|
8
|
+
exports (`@gavana.ai/cli/client`, `@gavana.ai/cli/capabilities`) are consumed
|
|
9
|
+
inside the repository and by the MCP server.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **One command table.** `src/commands.mjs` declares every `gavana` command
|
|
14
|
+
once. Root help, per-group help, and the zsh/bash/fish completion scripts are
|
|
15
|
+
all generated from it, and dispatch is gated on it. Before, those four things
|
|
16
|
+
were four hand-maintained copies of the same list, and they had drifted.
|
|
17
|
+
- **Shell completions complete sub-commands.** `gavana completion zsh|bash|fish`
|
|
18
|
+
previously offered only the top-level groups; it now offers each group's
|
|
19
|
+
actions too. Deprecated and alias commands stay dispatchable and stay out of
|
|
20
|
+
completions.
|
|
21
|
+
- **Tool registry export.** `src/tools/registry.mjs` carries every tool
|
|
22
|
+
definition shared by the stdio MCP server and the hosted endpoint, with each
|
|
23
|
+
tool's schema in `src/tools/schemas.mjs`.
|
|
24
|
+
- **Progress helper.** `src/tools/progress.mjs` turns the client's existing
|
|
25
|
+
`onProgress` polling callback into MCP `notifications/progress` messages.
|
|
26
|
+
- **Guides as markdown.** The Canvas Agent Guide is now
|
|
27
|
+
`packages/cli/guides/*.md` rather than string literals, and ships in the
|
|
28
|
+
package.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- An unknown command is now rejected wherever it appears. `gavana version bogus`
|
|
33
|
+
and `gavana capabilities bogus` used to print a result and exit 0, because
|
|
34
|
+
both commands answered before anything checked whether the command existed.
|
|
35
|
+
They now exit 2 with `Unknown command`. `gavana --version` still answers, as
|
|
36
|
+
it carries no command at all.
|
|
37
|
+
|
|
38
|
+
### Deprecated
|
|
39
|
+
|
|
40
|
+
Still callable; nothing is removed in 0.2.0.
|
|
41
|
+
|
|
42
|
+
- **`gavana campaign *`** — `plan`, `start`, `get`, `review`, `cancel`. Hidden
|
|
43
|
+
from help and completions, and rejected unless
|
|
44
|
+
`GAVANA_ENABLE_LEGACY_CAMPAIGN_COMMANDS=true`. Existing `gavana recipe *`
|
|
45
|
+
commands remain API compatibility operations; this does not expose the
|
|
46
|
+
production Recipe UI.
|
|
47
|
+
- **`gavana ai-connection list`** — a compatibility alias for
|
|
48
|
+
`gavana provider list`. Dispatches identically, no longer advertised.
|
|
49
|
+
|
|
50
|
+
### Compatibility
|
|
51
|
+
|
|
52
|
+
- The `craftboard` and `craftboard-canvas` binaries, and the
|
|
53
|
+
`CRAFTBOARD_*` environment variables, continue to work as aliases. They are
|
|
54
|
+
not deprecated.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Gavana Customer Package License
|
|
2
|
+
|
|
3
|
+
Copyright 2026 Gavana. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This package is proprietary software. Permission to install and use it is
|
|
6
|
+
governed by the current [Gavana Terms of Service](https://app.gavana.ai/terms).
|
|
7
|
+
No rights are granted beyond those terms.
|
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Gavana CLI
|
|
2
|
+
|
|
3
|
+
The Gavana CLI is a JSON-first command-line client for the Gavana
|
|
4
|
+
Canvas API. It can read and change canvases, work with assets, explicitly run
|
|
5
|
+
Recipes, run deterministic Image Actions, and observe every execution through
|
|
6
|
+
shared Run and Job interfaces without opening the browser. It also queues
|
|
7
|
+
model-aware video generation with local or durable frame references.
|
|
8
|
+
|
|
9
|
+
## Install from npm
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install --global @gavana.ai/cli
|
|
13
|
+
gavana --help
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The npm command works after the package owner publishes this release. For local
|
|
17
|
+
package verification from the Gavana repository, run
|
|
18
|
+
`npm run test:canvas-cli-package`.
|
|
19
|
+
|
|
20
|
+
Use of the published CLI is subject to the current
|
|
21
|
+
[Gavana Terms of Service](https://app.gavana.ai/terms). Its customer package
|
|
22
|
+
license incorporates those terms by reference.
|
|
23
|
+
|
|
24
|
+
Node.js 20 or newer is required. `craftboard` and `craftboard-canvas` remain
|
|
25
|
+
available as compatibility aliases.
|
|
26
|
+
|
|
27
|
+
## Sign in
|
|
28
|
+
|
|
29
|
+
Browser OAuth is the default:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
gavana auth login
|
|
33
|
+
gavana auth status
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The CLI opens Gavana, asks the user to approve exact scopes, and returns through
|
|
37
|
+
a loopback callback. On macOS the resulting revocable token is stored in
|
|
38
|
+
Keychain; custom config paths and other platforms use the mode-`0600` config
|
|
39
|
+
file. Use `--read-only` for a browse-only profile.
|
|
40
|
+
|
|
41
|
+
Named profiles keep accounts and environments separate:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
gavana auth login --profile work
|
|
45
|
+
gavana auth login --profile staging --base-url https://staging.example.com
|
|
46
|
+
gavana config list
|
|
47
|
+
gavana config use work
|
|
48
|
+
gavana canvas list --profile staging
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Manual Agent Access tokens remain supported for automation and compatibility.
|
|
52
|
+
|
|
53
|
+
Create an Agent Access token in Gavana, then save it without putting the
|
|
54
|
+
secret in shell history. On zsh (the default shell on current macOS):
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
read -rs 'GAVANA_AGENT_TOKEN?Paste Agent Access token: '; printf '\n'; printf '%s' "$GAVANA_AGENT_TOKEN" | gavana auth login --base-url 'https://app.gavana.ai' --token-stdin; unset GAVANA_AGENT_TOKEN
|
|
58
|
+
gavana auth status
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
On Bash:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
read -rsp 'Paste Agent Access token: ' GAVANA_AGENT_TOKEN; printf '\n'; printf '%s' "$GAVANA_AGENT_TOKEN" | gavana auth login --base-url 'https://app.gavana.ai' --token-stdin; unset GAVANA_AGENT_TOKEN
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
On PowerShell:
|
|
68
|
+
|
|
69
|
+
```powershell
|
|
70
|
+
$secureToken = Read-Host 'Paste Agent Access token' -AsSecureString
|
|
71
|
+
$token = [System.Net.NetworkCredential]::new('', $secureToken).Password
|
|
72
|
+
$token | gavana auth login --base-url 'https://app.gavana.ai' --token-stdin
|
|
73
|
+
Remove-Variable token, secureToken
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The saved configuration lives at
|
|
77
|
+
`~/.config/gavana/agent.json` with file mode `0600`. Environment variables
|
|
78
|
+
`GAVANA_BASE_URL` and `GAVANA_AGENT_TOKEN` override saved values. Existing
|
|
79
|
+
`~/.config/craftboard/agent.json` and `CRAFTBOARD_*` aliases remain readable.
|
|
80
|
+
|
|
81
|
+
## Discover and diagnose
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
gavana doctor
|
|
85
|
+
gavana version
|
|
86
|
+
gavana completion zsh
|
|
87
|
+
gavana canvas --help
|
|
88
|
+
gavana api GET /canvases --field limit=10
|
|
89
|
+
gavana mcp install codex
|
|
90
|
+
gavana mcp install codex --read-only
|
|
91
|
+
gavana mcp config cursor
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
JSON remains the stable scripting default. Use `--output human` for a compact
|
|
95
|
+
terminal view, or `jsonl`, `markdown`, `raw`, and `--jq` for composition.
|
|
96
|
+
Transient network errors and `429/502/503/504` responses are retried only for
|
|
97
|
+
safe GET requests, respecting `Retry-After`; paid generation writes are never
|
|
98
|
+
retried automatically.
|
|
99
|
+
|
|
100
|
+
## Examples
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
gavana canvas list
|
|
104
|
+
gavana canvas list --limit 25 --jq '.canvases[].handle' -r
|
|
105
|
+
gavana asset get asset:OWNER_UID:ASSET_ID
|
|
106
|
+
gavana recipe search "product visual"
|
|
107
|
+
gavana recipe run recipe:product-visual-direction --input product-context="A matte black travel bottle" --destination agent-canvas
|
|
108
|
+
gavana model list --capability image.generate
|
|
109
|
+
gavana model get model:OPAQUE_MODEL_KEY
|
|
110
|
+
gavana action list
|
|
111
|
+
gavana action get action:resize
|
|
112
|
+
gavana action run action:resize --input ./product.png --destination agent-canvas --width 1080 --height 1350
|
|
113
|
+
gavana image generate --destination agent-canvas --model model:OPAQUE_MODEL_KEY --prompt "A studio product photograph"
|
|
114
|
+
gavana model list --capability video.generate
|
|
115
|
+
gavana video generate --model model:OPAQUE_MODEL_KEY --prompt "A slow product turntable" --duration 15 --aspect-ratio 9:16 --download ./turntable.mp4
|
|
116
|
+
gavana video generate --model model:OPAQUE_MODEL_KEY --prompt "Animate the fabric naturally" --first-frame ./product.png --no-wait
|
|
117
|
+
gavana video download job:JOB_ID --file ./result.mp4
|
|
118
|
+
gavana run wait run:RUN_ID --output markdown
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`video generate` validates duration, aspect ratio, resolution, audio, and frame
|
|
122
|
+
capabilities against the selected model before starting paid work. Use
|
|
123
|
+
`gavana model get model:OPAQUE_MODEL_KEY` to inspect its exact values.
|
|
124
|
+
First frame, last frame, and repeatable `--reference` inputs accept image
|
|
125
|
+
`node:` or `asset:` handles, public HTTPS URLs, local image paths, stdin (`-`),
|
|
126
|
+
or the macOS clipboard. Local images upload privately first. Pass
|
|
127
|
+
`--canvas canvas:<id>` when any input is a `node:` handle. A last frame requires
|
|
128
|
+
a first frame.
|
|
129
|
+
|
|
130
|
+
Video generation returns a `job:` handle. By default the CLI waits up to 30
|
|
131
|
+
minutes and returns the completed job with its authenticated video download
|
|
132
|
+
path. Add `--download ./output.mp4` to stream the successful result directly to
|
|
133
|
+
disk, or use `video download job:<id> --file ./output.mp4` later. Existing files
|
|
134
|
+
are preserved unless `--yes` is supplied. Use `--no-wait` to return after
|
|
135
|
+
queueing, then use `job get`, `job wait`, or `job cancel`. Waiting, downloading,
|
|
136
|
+
and cancellation require `job:manage`; generation requires `canvas:read`,
|
|
137
|
+
`asset:read`, and `video:generate`.
|
|
138
|
+
|
|
139
|
+
Image Actions resize, crop, reframe, composite, add text, overlay, color grade,
|
|
140
|
+
or rotate existing images. They are deterministic and do not spend AI credits.
|
|
141
|
+
Use `action get` to inspect the exact input order, valid fields, defaults, and
|
|
142
|
+
limits. `action run` accepts `node:` and `asset:` handles, local image paths,
|
|
143
|
+
stdin (`-`), or the macOS clipboard.
|
|
144
|
+
Local, stdin, and clipboard inputs are privately uploaded first and therefore
|
|
145
|
+
also require the token's `image:generate` scope; existing handles do not.
|
|
146
|
+
|
|
147
|
+
For reference-aware image generation, repeat `--reference` for every durable
|
|
148
|
+
visual and repeat `--reference-role` in the same order when the role is known:
|
|
149
|
+
`identity`, `construction`, `texture`, `fit`, or `style`. Gavana records the
|
|
150
|
+
exact handles and roles in the job result and target-node provenance, and sends
|
|
151
|
+
the request through the reference/edit backend rather than dropping inputs into
|
|
152
|
+
a prompt-only fallback.
|
|
153
|
+
|
|
154
|
+
`recipe run` takes repeatable named inputs such as
|
|
155
|
+
`--input product-context="A matte black travel bottle"` and
|
|
156
|
+
`--input offer-brief=@brief.md`. Use the exact keys returned by `recipe get`.
|
|
157
|
+
For distinct product variants, use a Prompt List: connect the product image
|
|
158
|
+
once to the List, make one explicit direction per row, and connect the List to
|
|
159
|
+
an image generator. Each row inherits the same reference; agents should state
|
|
160
|
+
that the exact product must be preserved and never substituted. For a style
|
|
161
|
+
that belongs to only one row, use that row's `referenceBindings` with the
|
|
162
|
+
durable image handle (`{ "nodeId": "node:<id>", "role": "style" }`), rather
|
|
163
|
+
than inserting a copied image name into prompt text. Gavana preserves the
|
|
164
|
+
shared Product -> Prompt List -> output path and draws the row Style -> output
|
|
165
|
+
edge separately.
|
|
166
|
+
Written ports accept text, text/sticky `node:` handles, and image handles when
|
|
167
|
+
the Recipe asks for “an image or written note.” Image ports may also use local
|
|
168
|
+
raster paths, stdin, or the clipboard and are uploaded privately first. Upload
|
|
169
|
+
a local visual first and pass its `asset:` handle when using it on a written
|
|
170
|
+
reference port; `@path` on that port reads the file as text. Starting a Recipe
|
|
171
|
+
creates a private instance when needed, materializes its declared outputs on
|
|
172
|
+
the destination canvas, and returns their durable `node:` and `asset:` handles.
|
|
173
|
+
`recipe fork` remains setup-only and never starts a Run. All Recipe starts
|
|
174
|
+
currently require `image:generate` and its dependent scopes, including
|
|
175
|
+
text-only Recipes.
|
|
176
|
+
|
|
177
|
+
Recipe, image, and Action work returns a shared `run:` handle with typed outputs,
|
|
178
|
+
duration estimates, observed queue/execution timing, and stable retry guidance.
|
|
179
|
+
Default waiting and `run get|wait|cancel` require `job:manage`; a start-only
|
|
180
|
+
token can use `--no-wait` with a signed webhook.
|
|
181
|
+
The legacy `job:` handle remains an image and Action compatibility alias; it is
|
|
182
|
+
never used for Recipes. Image and Action `run:` and `job:` handles point to the
|
|
183
|
+
same temporary record and expire together:
|
|
184
|
+
the default retention is 24 hours while unacknowledged, 15 minutes after the
|
|
185
|
+
first successful server finalization (from a Run GET or callback), and seven
|
|
186
|
+
days for the expired tombstone. Recipe Run records currently persist without
|
|
187
|
+
that temporary TTL. Persist the returned durable asset and node handles.
|
|
188
|
+
For a signed terminal
|
|
189
|
+
callback, provide the endpoint and read the secret from an environment
|
|
190
|
+
variable:
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
read -rs 'GAVANA_WEBHOOK_SECRET?Webhook signing secret: '; printf '\n'
|
|
194
|
+
export GAVANA_WEBHOOK_SECRET
|
|
195
|
+
gavana image generate \
|
|
196
|
+
--destination agent-canvas \
|
|
197
|
+
--prompt "A studio product photograph" \
|
|
198
|
+
--webhook-url 'https://automation.example.com/hooks/gavana' \
|
|
199
|
+
--no-wait
|
|
200
|
+
unset GAVANA_WEBHOOK_SECRET
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Use `--webhook-secret-env NAME` to select a different variable. The CLI never
|
|
204
|
+
prints the secret. Successful Image and Action callbacks are sent only after
|
|
205
|
+
Gavana has stored the durable canvas, node, and asset results. Failed,
|
|
206
|
+
canceled, or expired callbacks describe the terminal state without requiring
|
|
207
|
+
images; Recipe callbacks contain their typed terminal outputs. A start-only token remains revocable while
|
|
208
|
+
Gavana's worker resumes the Run independently of the original CLI process.
|
|
209
|
+
If the token expires or is revoked first, the Recipe stops with
|
|
210
|
+
`delegation_revoked` and sends its signed failed callback.
|
|
211
|
+
|
|
212
|
+
Commands emit one JSON result to stdout by default. Progress and errors go to
|
|
213
|
+
stderr, making the CLI safe to compose in scripts and agent workflows. List
|
|
214
|
+
commands for canvases, recipes, assets, Actions, models, and providers accept `--limit` and
|
|
215
|
+
`--cursor`; responses return the continuation at `page.nextCursor`. Use
|
|
216
|
+
`--output jsonl` for line-oriented output. The built-in
|
|
217
|
+
`--jq` selector supports property paths, array indexes, and `[]` projections
|
|
218
|
+
without requiring a separate jq installation.
|
|
219
|
+
|
|
220
|
+
## JavaScript client
|
|
221
|
+
|
|
222
|
+
The same dependency-free client is exported for Node.js applications:
|
|
223
|
+
|
|
224
|
+
```js
|
|
225
|
+
import { createCanvasAgentClient } from "@gavana.ai/cli";
|
|
226
|
+
|
|
227
|
+
const client = createCanvasAgentClient({
|
|
228
|
+
baseUrl: process.env.GAVANA_BASE_URL,
|
|
229
|
+
token: process.env.GAVANA_AGENT_TOKEN,
|
|
230
|
+
surface: "api",
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const result = await client.listCanvases();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Remote servers must use HTTPS. Plain HTTP is accepted only for local loopback
|
|
237
|
+
development.
|
package/bin/gavana.mjs
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: connections
|
|
3
|
+
title: Connections
|
|
4
|
+
description: Create directed, persistent relationships with valid endpoint semantics.
|
|
5
|
+
keywords: ["connection","connect","edge","direction","input","output","reference","list","first-frame","last-frame","prompt"]
|
|
6
|
+
order: 4
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Direction
|
|
10
|
+
|
|
11
|
+
A connection goes from source to target. Use source input or instruction -> transformation or generator -> output. Never connect a node to itself, and never connect a Section as if it were a workflow step.
|
|
12
|
+
|
|
13
|
+
## Modes
|
|
14
|
+
|
|
15
|
+
- Omit `mode` for a normal dependency or transformation flow.
|
|
16
|
+
- `prompt`: a text or sticky note whose content is the generation prompt for the target image node. One prompt connection per target; image generation reads the prompt from this node when the request omits a prompt.
|
|
17
|
+
- `reference`: an image reference that guides another node.
|
|
18
|
+
- `list`: a Prompt List or Image List flow.
|
|
19
|
+
- `first-frame`: an image used as the first frame of a video node.
|
|
20
|
+
- `last-frame`: an image used as the last frame of a video node.
|
|
21
|
+
|
|
22
|
+
Use exact `node:` handles or batch-local `client:` references. Connections remain attached when nodes move. Avoid duplicate edges with the same source, target, and mode.
|
|
23
|
+
|
|
24
|
+
## Batch-local example
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"type": "connection.create",
|
|
29
|
+
"clientId": "brief-to-generator",
|
|
30
|
+
"from": "client:brief",
|
|
31
|
+
"to": "client:generator"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Do not rely on spatial proximity to imply a relationship. If a relationship matters to execution or later understanding, connect it.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: examples-common-mistakes
|
|
3
|
+
title: Examples and Common Mistakes
|
|
4
|
+
description: Compact patterns to copy and anti-patterns agents must avoid.
|
|
5
|
+
keywords: ["example","examples","mistake","mistakes","anti-pattern","section","note","text","generated","connection"]
|
|
6
|
+
order: 10
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Good patterns
|
|
10
|
+
|
|
11
|
+
- Research cluster: one Section, several Sticky observations, one Text synthesis, and directed observation -> synthesis connections.
|
|
12
|
+
- Creative workflow: source image -> Prompt List -> empty generator -> generated outputs.
|
|
13
|
+
- Video workflow: first image -[first-frame]-> video target and optional last image -[last-frame]-> video target.
|
|
14
|
+
- Existing-canvas addition: new contained Section outside the current bounds, with no existing-node mutations.
|
|
15
|
+
|
|
16
|
+
## Common mistakes
|
|
17
|
+
|
|
18
|
+
- Using long Text or Sticky nodes as fake headers instead of Sections.
|
|
19
|
+
- Creating every node at `{ "x": 0, "y": 0 }` or stacking nodes on top of one another.
|
|
20
|
+
- Leaving generated outputs disconnected from their prompt, List, source, or stage.
|
|
21
|
+
- Connecting a Section to workflow nodes.
|
|
22
|
+
- Treating nearby objects as implicit inputs without explicit handles or connections.
|
|
23
|
+
- Copying a style image name into prompt text instead of using a row-level reference binding.
|
|
24
|
+
- Writing generated media content directly into node metadata.
|
|
25
|
+
- Reorganizing or deleting existing work when the user asked only to add something.
|
|
26
|
+
- Starting generation when the user asked only to prepare a workflow.
|
|
27
|
+
- Retrying a failed paid operation automatically.
|
|
28
|
+
- Reporting a temporary Job or Run handle as a durable Canvas output.
|
|
29
|
+
- Passing `force: true` to push a batch past error-severity findings instead of fixing the operations. Force is for explicit, user-approved exceptions only.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: existing-canvases
|
|
3
|
+
title: Editing Existing Canvases Safely
|
|
4
|
+
description: Preserve user structure, concurrent edits, and unrelated content while making scoped changes.
|
|
5
|
+
keywords: ["existing","preserve","concurrent","revision","conflict","409","idempotency","unrelated","delete","scope"]
|
|
6
|
+
order: 7
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Preservation contract
|
|
10
|
+
|
|
11
|
+
- Call `canvas_get` and retain the exact revision before planning a write.
|
|
12
|
+
- Make the smallest requested delta. Do not move, resize, retitle, reconnect, delete, or rewrite an existing node outside the requested scope.
|
|
13
|
+
- Prefer one atomic batch for related nodes and connections so a malformed operation leaves no partial graph.
|
|
14
|
+
- Pass the read revision as `baseRevision`.
|
|
15
|
+
- On `409`, read again and rebase the intended additions around the newer graph. Preserve the concurrent user change.
|
|
16
|
+
- Reuse an idempotency key only for an identical intended payload. If the intended payload changes, use a new key.
|
|
17
|
+
- Pass proposed delete operations to `canvas_validate` and report their node and connection impact before applying them.
|
|
18
|
+
|
|
19
|
+
An agent-authored addition should be removable without damaging surrounding user work. Exact returned handles are the audit trail.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: generated-assets
|
|
3
|
+
title: Generated Images, Videos, and Durable Outputs
|
|
4
|
+
description: Prepare media nodes, start only explicit generation, and preserve output lineage.
|
|
5
|
+
keywords: ["generated","generation","image","video","output","asset","durable","lineage","placeholder","job"]
|
|
6
|
+
order: 6
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Before generation
|
|
10
|
+
|
|
11
|
+
- Read the destination canvas and relevant source nodes.
|
|
12
|
+
- Use exact source `node:` or `asset:` handles.
|
|
13
|
+
- For a standalone image request, pass every visual source in `references`.
|
|
14
|
+
Use `{ "handle": "node:...", "role": "identity" }` when its
|
|
15
|
+
responsibility is known; valid roles are `identity`, `construction`,
|
|
16
|
+
`texture`, `fit`, and `style`. Do not flatten multi-reference work
|
|
17
|
+
into prompt prose or omit a source during fallback.
|
|
18
|
+
- Create an empty image or video target only through supported operations. Do not write media bytes, storage keys, or arbitrary output URLs into metadata.
|
|
19
|
+
- Connect prompts, products, references, Lists, and frame inputs to their target with the correct direction and mode.
|
|
20
|
+
|
|
21
|
+
## Paid execution
|
|
22
|
+
|
|
23
|
+
Generation is allowed only after explicit current-turn user intent. Start one run with one caller-stable idempotency key. Poll the returned Run or Job; do not start another run while waiting. A terminal failure must be reported without automatic retry.
|
|
24
|
+
|
|
25
|
+
## Completion
|
|
26
|
+
|
|
27
|
+
Do 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.
|
|
28
|
+
|
|
29
|
+
Keep 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, durable output count, and product-fidelity review state. Do not claim Done while it says `doneClaimAllowed: false`. Product-fidelity uncertainty requires human review; never create another paid provider call automatically.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: getting-started
|
|
3
|
+
title: Canvas Agent Workflow
|
|
4
|
+
description: The required inspect, guide, validate, edit, and review sequence for every canvas task.
|
|
5
|
+
keywords: ["start","workflow","inspect","read","validate","edit","review","revision","idempotency"]
|
|
6
|
+
order: 1
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Required sequence
|
|
10
|
+
|
|
11
|
+
1. Identify one exact canvas handle. Never guess between candidates.
|
|
12
|
+
2. Call `canvas_get` before reasoning about or changing an existing canvas.
|
|
13
|
+
3. Read the guide topics relevant to the requested operation.
|
|
14
|
+
4. Plan the smallest graph change that satisfies the request. Preserve unrelated nodes, connections, positions, metadata, and the user's current structure.
|
|
15
|
+
5. Call `canvas_validate` with the proposed operations before a large, spatial, or destructive batch.
|
|
16
|
+
6. Apply related changes atomically with `canvas_apply_batch`, the current `baseRevision`, and one caller-stable idempotency key.
|
|
17
|
+
7. If a write returns revision conflict `409`, read the canvas again, preserve the newer user change, and retry the same intent. Reuse the same idempotency key only for the same payload.
|
|
18
|
+
8. Call `canvas_validate` after editing. Report exact changed handles and unresolved warnings.
|
|
19
|
+
|
|
20
|
+
## Non-negotiable safety
|
|
21
|
+
|
|
22
|
+
- Building or preparing a workflow does not mean running it.
|
|
23
|
+
- Never start image, video, Action, or Recipe generation unless the user explicitly requested that paid action in the current conversation.
|
|
24
|
+
- Never automatically retry a failed paid action.
|
|
25
|
+
- Never delete, disconnect, overwrite, or reorganize existing work unless the user explicitly requested that scope.
|
|
26
|
+
- Generated media content is server-owned. Use generation or import tools; do not place bytes or arbitrary media URLs into node metadata.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: notes-text-sections
|
|
3
|
+
title: Notes, Text, and Sections
|
|
4
|
+
description: Choose the correct native canvas object for observations, durable copy, headings, and spatial groups.
|
|
5
|
+
keywords: ["note","notes","sticky","text","heading","header","section","frame","content","annotation"]
|
|
6
|
+
order: 2
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Object grammar
|
|
10
|
+
|
|
11
|
+
- Sticky note: one short observation, idea, decision, question, or human annotation. Create a `sticky` node and put the readable value in `metadata.content`.
|
|
12
|
+
- Text: a paragraph, prompt, brief, instruction, caption, or durable written output. Create a `text` node and put the body in `metadata.content`.
|
|
13
|
+
- Section: a labeled spatial container and navigation landmark. Create a `text` node with `metadata.isSection: true`. Put the section title in `title`; keep `metadata.content` empty unless the user asked for a section description.
|
|
14
|
+
- Heading: use the title of a real Section. Do not stretch an ordinary Text or Sticky node across the canvas to imitate a section header.
|
|
15
|
+
|
|
16
|
+
## Section example
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"type": "node.create",
|
|
21
|
+
"clientId": "research-section",
|
|
22
|
+
"node": {
|
|
23
|
+
"type": "text",
|
|
24
|
+
"title": "Customer objections",
|
|
25
|
+
"position": { "x": 1200, "y": 200 },
|
|
26
|
+
"width": 1040,
|
|
27
|
+
"height": 720,
|
|
28
|
+
"metadata": { "isSection": true }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Place each child's complete frame inside the Section bounds; a centered but
|
|
34
|
+
overflowing frame is not contained. A Section may overlap its children by
|
|
35
|
+
design; ordinary nodes should not overlap one another. A child whose frame
|
|
36
|
+
crosses its Section boundary receives a `section_content_overflow` finding.
|
|
37
|
+
|
|
38
|
+
## Stored membership
|
|
39
|
+
|
|
40
|
+
Membership is stored: the server keeps `metadata.sectionId` on every node
|
|
41
|
+
whose complete frame fits inside a Section, recomputing it after each batch on
|
|
42
|
+
create, move, resize, and delete. When Sections nest or overlap, the smallest
|
|
43
|
+
containing Section wins. Do not set `sectionId` yourself — geometry is the
|
|
44
|
+
source of truth and caller-supplied values are corrected.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: paid-action-safety
|
|
3
|
+
title: Paid Action Safety
|
|
4
|
+
description: Separate preparation from execution and prevent accidental or repeated provider charges.
|
|
5
|
+
keywords: ["paid","credits","cost","generate","run","retry","failure","prepare","setup","explicit"]
|
|
6
|
+
order: 8
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Intent boundary
|
|
10
|
+
|
|
11
|
+
"Build", "prepare", "set up", "connect", "draft", and "make ready" authorize graph edits only. They do not authorize Recipe, image, video, or Action execution.
|
|
12
|
+
|
|
13
|
+
Start 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.
|
|
14
|
+
|
|
15
|
+
## Retry boundary
|
|
16
|
+
|
|
17
|
+
- Use one stable idempotency key for one intended paid operation.
|
|
18
|
+
- Poll the returned handle with status tools.
|
|
19
|
+
- Never automatically retry a terminal failure, timeout, disconnect, or ambiguous provider response with a new key.
|
|
20
|
+
- Ask for new user intent before any new paid attempt.
|
|
21
|
+
|
|
22
|
+
Deterministic Actions may be described as credit-free only when `action_get` confirms that contract. Inspect an Action before running it.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: prompt-lists
|
|
3
|
+
title: Prompt Lists and Repeated Directions
|
|
4
|
+
description: Represent several editable creative directions as one native Prompt List with shared and row-specific references.
|
|
5
|
+
keywords: ["prompt","list","directions","rows","referenceBindings","product","style","batch","generator"]
|
|
6
|
+
order: 5
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prompt List shape
|
|
10
|
+
|
|
11
|
+
Use one `text` node with:
|
|
12
|
+
|
|
13
|
+
- `metadata.isList: true`
|
|
14
|
+
- `metadata.listType: "prompt"`
|
|
15
|
+
- `metadata.listExecutionMode: "batch"` for separate outputs
|
|
16
|
+
- one checked `metadata.listItems` entry per direction
|
|
17
|
+
|
|
18
|
+
Connect a shared product image to the List once. Connect the List to one empty image generator. For a row-specific style, store the exact style image in that row's `referenceBindings` as `{ "nodeId": "node:<id>", "role": "style" }`. Do not copy a filename into prompt prose as a substitute for a binding.
|
|
19
|
+
|
|
20
|
+
Every product-variant row should explicitly say to preserve the exact connected product and not substitute it. Building the List and generator prepares the workflow only; it must not start generation.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sections-layout
|
|
3
|
+
title: Sections and Layout
|
|
4
|
+
description: Place native objects in readable groups without hiding or rearranging existing work.
|
|
5
|
+
keywords: ["section","layout","position","overlap","spacing","grid","right","below","contain","navigation"]
|
|
6
|
+
order: 3
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Layout rules
|
|
10
|
+
|
|
11
|
+
- Treat the current canvas as user-owned. Preserve existing coordinates unless reorganization was explicitly requested.
|
|
12
|
+
- For additions to an existing canvas, compute its visible bounding box and place the new Section to the right with at least 160 canvas units of outer spacing. If right-side placement would make the canvas excessively wide, place it below with the same spacing.
|
|
13
|
+
- Use 48 units of inner Section padding, 32 units between sibling nodes, and at least 80 units between major stages.
|
|
14
|
+
- Keep workflow direction consistent, normally left to right. Keep inputs before transformations and outputs after them.
|
|
15
|
+
- Use compact rows or columns. Avoid extremely long, thin canvases that become unreadable at Fit Canvas.
|
|
16
|
+
- For 2-8 generated image outputs, reserve each requested final aspect frame before work begins and pack the complete result cluster as a grid. The usual four-image photoshoot is a 2x2 grid; do not stack it as a tall output column that can overlap when images finalize.
|
|
17
|
+
- Size Sections after their contents. Do not use Section overlap as a substitute for node placement.
|
|
18
|
+
- Run `canvas_validate` before and after a multi-node layout change.
|
|
19
|
+
|
|
20
|
+
## One task = one Section
|
|
21
|
+
|
|
22
|
+
Group each task's output in a titled Section sized to its contents plus 48
|
|
23
|
+
units of padding. Workflow creation and multi-output image generation wrap
|
|
24
|
+
their clusters in a Section automatically (multi-output wrapping applies to
|
|
25
|
+
automatic placement; passing explicit target coordinates opts out and leaves
|
|
26
|
+
placement fully caller-controlled); do the same for hand-built
|
|
27
|
+
clusters. Agent-created nodes left outside every Section raise an info-level
|
|
28
|
+
`unsectioned_node` finding. Membership is stored server-side as
|
|
29
|
+
`metadata.sectionId`, recomputed from complete-frame geometry after every
|
|
30
|
+
batch. Agent-created Sections receive an owned auto-fit contract; after a
|
|
31
|
+
generated child changes size, Gavana refits only that still-owned Section to
|
|
32
|
+
the full child bounds plus 48 units. Do not use this as permission to move or
|
|
33
|
+
resize a user-controlled Section.
|
|
34
|
+
|
|
35
|
+
For a newly proposed agent cluster, ordinary-node overlap and full-frame
|
|
36
|
+
Section overflow are write-blocking errors. On an existing Canvas, historical
|
|
37
|
+
user-created overlap or overflow remains advisory so an unrelated scoped edit
|
|
38
|
+
can still proceed. Agent-owned task findings still block completion review
|
|
39
|
+
until they are corrected.
|
|
40
|
+
|
|
41
|
+
## Existing canvas rule
|
|
42
|
+
|
|
43
|
+
When the user says "add", do not interpret it as "reorganize". New work should be distinguishable, spatially contained, and reversible without moving unrelated content.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: validation-recovery
|
|
3
|
+
title: Validation and Recovery
|
|
4
|
+
description: Interpret structural findings, correct invalid batches, and finish with an evidence-based review.
|
|
5
|
+
keywords: ["validate","lint","overlap","orphan","header","connection","destructive","recovery","error","atomic","blocked","force"]
|
|
6
|
+
order: 9
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Use `canvas_validate`
|
|
10
|
+
|
|
11
|
+
Call it with only `canvasId` to audit the current graph. Pass the proposed `operations` to inspect the planned post-batch graph and destructive impact before writing.
|
|
12
|
+
|
|
13
|
+
Warning- and info-level findings are advisory. Error-severity findings caused by the proposed agent write have teeth: `canvas_apply_batch` rejects that batch and writes nothing. Historical findings remain visible for review but do not turn an unrelated scoped write into a forced cleanup. Validation never mutates the canvas or consumes an idempotency key.
|
|
14
|
+
|
|
15
|
+
`summary.passed` means there is no structural error. `summary.reviewRequired` is true when errors, warnings, or truncated findings still require agent or human review. `completionReview` is the finalization-ready structured view: it names overlap, containment, reference lineage, output count, and product-fidelity state. Never claim Done unless `completionReview.doneClaimAllowed` is true.
|
|
16
|
+
|
|
17
|
+
## Blocked writes
|
|
18
|
+
|
|
19
|
+
When a batch is rejected with error-severity findings:
|
|
20
|
+
|
|
21
|
+
- Nothing was written and the idempotency key was not consumed — the same key retries the corrected batch of the same intent.
|
|
22
|
+
- The rejection lists the blocking findings. Fix the listed operations, then confirm with `canvas_validate` using the same `operations` before applying again.
|
|
23
|
+
- `force: true` applies the batch despite error findings. Use it only after validating, and only when the user explicitly accepts the listed findings — never as a routine retry shortcut.
|
|
24
|
+
|
|
25
|
+
## Recovery
|
|
26
|
+
|
|
27
|
+
- If an operation is rejected, the atomic batch makes no partial change.
|
|
28
|
+
- Read the finding's exact handles and linked guide topic.
|
|
29
|
+
- Correct unsupported object types, metadata, endpoint modes, positions, or references instead of guessing repeatedly.
|
|
30
|
+
- Use a new idempotency key if the corrected payload represents a changed intent.
|
|
31
|
+
- Read and validate again after a successful write.
|
|
32
|
+
|
|
33
|
+
Common findings include ordinary-node overlap, Section content overflow, generated output without an incoming relationship, text imitating a Section header, broken lineage handles, unclear media connections, and proposed deletions. Product-fidelity uncertainty is a review state, not authorization to regenerate.
|