@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.
- package/dist/commands/gen.js +4 -19
- package/dist/index.js +4 -1
- package/package.json +1 -1
- package/skill/wji/SKILL.md +64 -7
- package/skill/wji/reference/canvas-recipes.md +16 -2
- package/skill/wji/reference/commands.md +11 -3
package/dist/commands/gen.js
CHANGED
|
@@ -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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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>', '
|
|
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
|
-
|
|
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
package/skill/wji/SKILL.md
CHANGED
|
@@ -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
|
|
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
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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`)
|
|
151
|
-
|
|
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`, `--
|
|
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
|
-
|
|
214
|
-
|
|
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
|
|