@wji.ai/cli 0.1.0 → 0.1.1

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.
@@ -2,7 +2,6 @@ import { Command } from 'commander';
2
2
  import { WjiClient } from '../core/client.js';
3
3
  import { confirm, parseKeyValues, readJson, readValue } from '../core/prompt.js';
4
4
  import { color, detail, info, isJsonMode, printJson, render, success, table, truncate, warn } from '../core/output.js';
5
- const PENDING = 0;
6
5
  const READY = 1;
7
6
  const CANCELLED = -1;
8
7
  /** `--ref abc123`, `--ref abc123:hero`, `--ref abc123:hero:0.6` */
@@ -81,22 +80,9 @@ export function reportHistory(history, assets) {
81
80
  ]);
82
81
  }
83
82
  async function submit(client, kind, body, opts) {
84
- const path = opts.history
85
- ? `/ai/assets/history/${kind}/generations`
86
- : `/ai/assets/${kind}/generations`;
87
- const result = await client.post(path, body);
88
- if (!opts.history) {
89
- // Raw mode returns Asset[] directly; there is no history to poll.
90
- return render(result, (assets) => {
91
- if (!Array.isArray(assets))
92
- return detail(Object.entries(assets || {}));
93
- table(assets, [
94
- { header: 'assetId', value: (a) => a.id },
95
- { header: 'state', value: (a) => (a.status === PENDING ? 'pending' : 'ready') },
96
- { header: 'url', value: (a) => a.url },
97
- ]);
98
- });
99
- }
83
+ // Always the history endpoint: the raw one silently drops fsnode, scope,
84
+ // scopeId and tags, and returns no id to poll with.
85
+ const result = await client.post(`/ai/assets/history/${kind}/generations`, body);
100
86
  if (!opts.wait) {
101
87
  if (isJsonMode())
102
88
  return printJson(result);
@@ -121,14 +107,13 @@ function withCommonOptions(cmd) {
121
107
  .option('-p, --prompt <text>', 'prompt text (@file / - for stdin)')
122
108
  .option('-n, --n <count>', 'number of outputs', '1')
123
109
  .option('-w, --workspace <id>', 'workspace to bill and file the result under')
124
- .option('--fsnode <id>', 'attach the result to an fsnode')
110
+ .option('--fsnode <id>', 'file the history entry under an fsnode (does not add the asset to its images)')
125
111
  .option('--scope <scope>', 'history scope, e.g. workspace | canvas')
126
112
  .option('--scope-id <id>', 'history scope id')
127
113
  .option('-r, --ratio <ratio>', 'aspect ratio, e.g. 16:9')
128
114
  .option('--tags <tag...>', 'tags for the history entry')
129
115
  .option('--values <json>', 'model-specific form values (@file / - supported)')
130
116
  .option('--set <key=value...>', 'model-specific form values as key=value')
131
- .option('--no-history', 'call the raw endpoint and return assets instead of a history')
132
117
  .option('--wait', 'block until the task finishes')
133
118
  .option('--timeout <seconds>', 'wait timeout', '900')
134
119
  .option('--interval <seconds>', 'poll interval', '5');
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
2
3
  import { Command } from 'commander';
3
4
  import { ApiError } from './core/client.js';
4
5
  import { color, setJsonMode } from './core/output.js';
@@ -15,7 +16,9 @@ import { profileCommand } from './commands/profile.js';
15
16
  import { presetCommand } from './commands/preset.js';
16
17
  import { skillCommand } from './commands/skill.js';
17
18
  import { canvasCommand } from './commands/canvas.js';
18
- const VERSION = '0.1.0';
19
+ // Read from package.json so `wji --version` cannot drift from the published
20
+ // version — the skill compares the two to detect a stale install.
21
+ const VERSION = createRequire(import.meta.url)('../package.json').version;
19
22
  const program = new Command();
20
23
  program
21
24
  .name('wji')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wji.ai/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Command line interface for the WJI AI platform",
5
5
  "license": "UNLICENSED",
6
6
  "author": "WJI AI",
@@ -15,6 +15,18 @@ and the human table output when you are showing the user a result.
15
15
  wji auth whoami --json # confirms endpoint, credential, org context
16
16
  ```
17
17
 
18
+ - **Check for a CLI update first.** The skill documents the newest commands, so
19
+ an old binary fails in confusing ways:
20
+
21
+ ```bash
22
+ wji --version && npm view @wji.ai/cli version
23
+ ```
24
+
25
+ If the installed version is lower, tell the user to run
26
+ `npm i -g @wji.ai/cli@latest` (or `pnpm add -g` / `yarn global add`) before
27
+ continuing. A dev checkout linked into PATH updates with `pnpm build`
28
+ instead. If the registry check fails (offline, proxy), carry on — don't
29
+ block the task on it.
18
30
  - `wji: command not found`: the CLI is not on PATH. From the `wji-cli` repo,
19
31
  `npm run build`, then link it where the user can write without sudo —
20
32
  `ln -s "$PWD/dist/index.js" ~/.local/bin/wji` (if `~/.local/bin` is on
@@ -28,6 +40,9 @@ wji auth whoami --json # confirms endpoint, credential, org context
28
40
  - `wji config show` reveals which endpoint and profile are active. A local
29
41
  backend is `wji config set endpoint http://localhost:3002` — `:3000` is the
30
42
  web frontend, not the API.
43
+ - **Scan the user's message for `-auto`.** It is not a CLI flag — it is the
44
+ user telling you to generate everything this request needs without stopping
45
+ to confirm the spend. See *Rules* for what it does and does not waive.
31
46
  - **Running several `wji` commands in parallel? Prefer an API key**
32
47
  (`WJI_API_KEY`, or `wji auth key create <name> --save`). A JWT login rotates
33
48
  its refresh token, and the server revokes *every* session if a refresh token
@@ -115,11 +130,19 @@ wji gen video -m <modelName> -p "slow pan" -d 5 --start-image <assetId> --wait -
115
130
  wji gen audio -m <modelName> -p "rain on a tin roof" --wait
116
131
  ```
117
132
 
133
+ - **Check the spending policy in *Rules* before you submit:** a single image
134
+ just runs; video, audio and anything with `-n` above 1 need a yes in the
135
+ chat first — unless the user's message carried `-auto`.
118
136
  - References are `assetId[:label[:weight]]`: `--ref 65f0…:hero:0.6`. Reference
119
137
  *assets*, not file paths — upload first with `wji asset upload`.
120
138
  - Model-specific parameters go through `--set` (`--set quality=high`); read the
121
139
  valid keys from `wji models get`.
122
- - `--fsnode <id>` files the result onto a node; `--tags` labels the history.
140
+ - `--fsnode <id>` files the *history entry* under a node — it does **not** add
141
+ the asset to that node's `images`. Recover them later with
142
+ `wji history list --fsnode <id>`. To make a generated image part of a dataset
143
+ you must attach it yourself, and `fs set --images` replaces the whole array:
144
+ read the current ids first, then write old + new together.
145
+ - `--tags` labels the history entry.
123
146
  - Video can take minutes. Without `--wait` you get a history id back:
124
147
  `wji history get <id> --wait` resumes polling, and `--timeout` is in seconds.
125
148
  - On timeout the task is usually still running — re-poll rather than
@@ -142,6 +165,18 @@ confirm with `wji models list --feature <image|video>` and `wji models get`.
142
165
  and big changes such as character sheets; `gpt-image-2.5-flare` for edits that
143
166
  keep the composition), **Nano Banana 2** or **Nano Banana Pro**.
144
167
 
168
+ Two image jobs have one right model each:
169
+
170
+ - **Transparent background** (logos, cut-outs, overlays, sprites) → GPT Image
171
+ 2.5 with `--set background=transparent`; the result comes back as PNG with
172
+ alpha. `opaque` forces a filled background, `auto` lets the model decide.
173
+ - **Split a picture into layers** (subject separated from background, for
174
+ compositing) → `bytedance-seedream-5-pro` with
175
+ `--set layer_decomposition=true`. It needs **exactly one** reference image,
176
+ a size tier (`--set size=1K|2K`, not pixel dimensions), and returns several
177
+ PNG layers as separate assets. On a canvas, run it in the browser's layer
178
+ editor instead — a CLI generate node keeps only one asset per node.
179
+
145
180
  **Video — reference models over first/last-frame models.** A family usually
146
181
  has both:
147
182
 
@@ -379,12 +414,34 @@ wji org list && wji org use <orgId>
379
414
  `--tags`, and the update commands' tag options, replace the whole value.
380
415
  Read the current value first, and check with the user before replacing
381
416
  anything they did not ask to change.
382
- - **Generation costs credits.** Run `wji gen cost` first for anything large
383
- (high `-n`, long video), show the user the number, and get agreement before
384
- submitting a batch. `wji canvas gen` prints its exact cost and refuses
385
- without `--yes`: run it once without `--yes` to get the number, tell the
386
- user, and pass `--yes` only after they agree. Creating or editing a generate
387
- node (`canvas add` / `canvas set`) costs nothing.
417
+ - **Generation costs credits — one image just runs; video and batches ask
418
+ first.** This is the user's standing policy. Follow it without asking them
419
+ to restate it:
420
+
421
+ | About to run | Do this |
422
+ | --- | --- |
423
+ | **One image** — `gen image` with `-n 1`, or `canvas gen` on an image node | **Go ahead.** Pass `--yes`, then report the `credits` line from the result. |
424
+ | **Any video or audio** | **Ask first.** Get the number, tell the user, wait for a yes. |
425
+ | **More than one generation in one step** — `-n 2` or higher, several nodes, a storyboard fan-out, an A×B matrix | **Ask first, with the total** — not the per-item price. |
426
+
427
+ Splitting a batch does not make it single: what needs approval is the total
428
+ you are about to spend in this step, however many commands it takes.
429
+
430
+ To get the number before asking, both of these are free: `wji gen cost -t
431
+ video -m <model> -d 8`, or run `wji canvas gen <nodeId>` *without* `--yes` —
432
+ it refuses to run and the error names the exact credits.
433
+
434
+ **`-auto` in the user's message overrides the table.** Generate everything
435
+ that request needs without asking — video and batches included — and report
436
+ the total actually charged when you are done. It covers that request and the
437
+ follow-ups continuing it; when the user moves to a different task, the table
438
+ above applies again. `-auto` never waives the confirmations for *destructive*
439
+ commands above, only the spending ones.
440
+
441
+ Creating or editing a generate node (`canvas add` / `canvas set`) costs
442
+ nothing, and neither does `gen cost`. Actual spend is in the result's
443
+ `credits` field (`history.chargedCredits`), so quote that rather than the
444
+ estimate once a job has finished.
388
445
  - **Never invent ids.** Look up workspace, node, asset and model ids with the
389
446
  list commands; ids are Mongo ObjectIds, not names.
390
447
  - **Stay inside the generation queue.** See *Limits* above — batch to the cap
@@ -110,6 +110,18 @@ its defaults; check with `wji canvas get <node>` and tell the user what changed.
110
110
 
111
111
  > "Go ahead and generate it."
112
112
 
113
+ **An image node just runs** (see the spending policy in SKILL.md *Rules*):
114
+
115
+ ```bash
116
+ wji canvas gen <node> --yes --wait
117
+ ```
118
+
119
+ Report the `credits` line from the result so the user sees what it actually
120
+ cost.
121
+
122
+ **A video or audio node needs a yes first** — so does any batch of nodes, and
123
+ `-auto` in the user's message waives both:
124
+
113
125
  ```bash
114
126
  wji canvas gen <node> # prints the cost and refuses (no terminal)
115
127
  ```
@@ -147,8 +159,10 @@ Never resubmit a node whose status is `generating` — that charges twice.
147
159
  wji canvas add video -n "Shot 2" --from <char1> <char2> -m <model> -r 16:9 -d 5 -p "…shot 2…"
148
160
  ```
149
161
 
150
- 4. Total the cost (`wji canvas gen <node>` for each, without `--yes`) before
151
- offering to generate them all.
162
+ 4. Total the cost (`wji canvas gen <node>` for each, without `--yes`) and get a
163
+ yes on that total before generating any of them. A fan-out is a batch, so
164
+ this applies even when every node is an image — unless the request carried
165
+ `-auto`, in which case generate them all and report the total charged.
152
166
 
153
167
  ## 6. Fix which image is `@image1`
154
168
 
@@ -142,6 +142,11 @@ Semantic dataset folders created with the Dataset app: `story`, `character`,
142
142
 
143
143
  Asset states: `0` pending, `1` ready, `-1` cancelled.
144
144
 
145
+ Model parameters worth knowing (`--set`, see `wji models get`):
146
+ `gpt-image-2.5-*` `background=transparent` returns a PNG with alpha;
147
+ `bytedance-seedream-5-pro` `layer_decomposition=true` splits one reference
148
+ image into separate PNG layer assets (exactly 1 reference, `size=1K|2K`).
149
+
145
150
  Uploads of `.html`, `.xhtml`, `.svg`, `.js` and `.xml` are stored as
146
151
  `application/octet-stream` with `Content-Disposition: attachment`.
147
152
 
@@ -200,7 +205,7 @@ viewport, url}` on toggle (`takeover: true`), on selection change and every
200
205
 
201
206
  Shared flags: `-m/--model` (required), `-p/--prompt`, `-n/--n`, `-w/--workspace`,
202
207
  `--fsnode`, `--scope`, `--scope-id`, `-r/--ratio`, `--tags`, `--values`,
203
- `--set`, `--no-history`, `--wait`, `--timeout` (seconds, default 900),
208
+ `--set`, `--wait`, `--timeout` (seconds, default 900),
204
209
  `--interval` (seconds, default 5).
205
210
 
206
211
  | Command | Extra flags | API |
@@ -210,8 +215,11 @@ Shared flags: `-m/--model` (required), `-p/--prompt`, `-n/--n`, `-w/--workspace`
210
215
  | `gen audio` | `-d/--duration`, `--ref-audio` | `POST /ai/assets/history/audio/generations` |
211
216
  | `gen cost -t <type> -m <model>` | `-n`, `-p`, `-d`, `-r`, `--refs`, `--values` | `POST /ai/assets/preComputeCost` |
212
217
 
213
- `--no-history` calls `/ai/assets/<type>/generations`, which returns assets
214
- directly and cannot be polled by history id.
218
+ Every generation goes through the history endpoint — there is no raw mode. The
219
+ backend also exposes `/ai/assets/<type>/generations`, which skips the history
220
+ record, but the CLI never calls it: without a history there is no id to poll,
221
+ and `fsnode`, `scope`, `scopeId` and `tags` are silently dropped (they are
222
+ written only inside `if (toHistory)`).
215
223
 
216
224
  Admission limits, per user and API key (changing IP does not reset them):
217
225