@wji.ai/cli 0.1.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/README.md +242 -0
- package/dist/commands/agent.js +274 -0
- package/dist/commands/asset.js +241 -0
- package/dist/commands/auth.js +216 -0
- package/dist/commands/canvas.js +915 -0
- package/dist/commands/config.js +113 -0
- package/dist/commands/fsnode.js +252 -0
- package/dist/commands/gen.js +366 -0
- package/dist/commands/model.js +134 -0
- package/dist/commands/org.js +85 -0
- package/dist/commands/preset.js +176 -0
- package/dist/commands/profile.js +129 -0
- package/dist/commands/skill.js +272 -0
- package/dist/commands/workspace.js +305 -0
- package/dist/core/client.js +252 -0
- package/dist/core/config.js +95 -0
- package/dist/core/output.js +143 -0
- package/dist/core/prompt.js +118 -0
- package/dist/core/zip.js +87 -0
- package/dist/index.js +94 -0
- package/package.json +49 -0
- package/skill/wji/SKILL.md +398 -0
- package/skill/wji/reference/canvas-recipes.md +179 -0
- package/skill/wji/reference/commands.md +381 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# wji CLI — full command reference
|
|
2
|
+
|
|
3
|
+
Global flags (accepted before any subcommand):
|
|
4
|
+
|
|
5
|
+
| Flag | Meaning |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| `--profile <name>` | config profile to use |
|
|
8
|
+
| `--endpoint <url>` | API base URL (default `https://api.wji.ai`) |
|
|
9
|
+
| `--token <token>` | bearer token or `sk_` key for this call only |
|
|
10
|
+
| `--org <orgId>` | organization context (`X-Org-Id`) |
|
|
11
|
+
| `--no-org` | force personal context for this call |
|
|
12
|
+
| `--locale <locale>` | response language: `cht`, `chs`, `en` |
|
|
13
|
+
| `--json` | print the raw API response instead of tables |
|
|
14
|
+
|
|
15
|
+
Value conventions: `@file` reads a file, `-` reads stdin, `--set key=value`
|
|
16
|
+
repeats and nests on dots, references are `assetId[:label[:weight]]`.
|
|
17
|
+
|
|
18
|
+
Exit codes: `0` ok, `1` error, `77` auth/permission failure.
|
|
19
|
+
|
|
20
|
+
Destructive commands — marked `[-y]` below — ask `[y/N]` with the target's
|
|
21
|
+
name. Without a terminal they refuse to run unless `-y/--yes` is passed.
|
|
22
|
+
`canvas gen` asks the same way, showing the credit cost.
|
|
23
|
+
|
|
24
|
+
Token rotation: every refresh issues a new refresh token and invalidates the
|
|
25
|
+
old one. Presenting an already-used refresh token makes the server revoke
|
|
26
|
+
**all** of that user's sessions. The CLI takes a lock file next to the config
|
|
27
|
+
(`.refresh-<profile>.lock`) and re-reads the config before refreshing, so
|
|
28
|
+
parallel commands share one refresh. Access tokens are not revoked by logout;
|
|
29
|
+
they stay valid until they expire.
|
|
30
|
+
|
|
31
|
+
## auth
|
|
32
|
+
|
|
33
|
+
| Command | API |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `auth login [-e email] [-p password]` | `POST /auth/signin` |
|
|
36
|
+
| `auth signup -e -n -c [-p]` | `POST /auth/signup` (needs an emailed code) |
|
|
37
|
+
| `auth token` | prints the active bearer token |
|
|
38
|
+
| `auth whoami` | `GET /user/me` + local context |
|
|
39
|
+
| `auth refresh` | `POST /auth/refresh` `{refreshToken}` — rotates the pair |
|
|
40
|
+
| `auth logout` | `POST /auth/signout` `{refreshToken}` (best effort) and clears local credentials |
|
|
41
|
+
| `auth key list` | `GET /api-key/search` |
|
|
42
|
+
| `auth key create <name> [--expires] [--save]` | `POST /api-key/create` — secret shown once |
|
|
43
|
+
| `auth key revoke <id> [-y]` | `POST /api-key/list/:id/revoke` — immediate; anything using the key breaks |
|
|
44
|
+
| `auth key rm <id> [-y]` | `DELETE /api-key/list/:id` |
|
|
45
|
+
| `auth key use <secret>` | stores an existing `sk_` key |
|
|
46
|
+
|
|
47
|
+
## config
|
|
48
|
+
|
|
49
|
+
`config show` · `config set <key> <value>` · `config unset <key>` ·
|
|
50
|
+
`config profiles` · `config use <profile>` · `config rm <profile> [-y]` · `config path`
|
|
51
|
+
|
|
52
|
+
Settable keys: `endpoint`, `orgId`, `workspace`, `locale`, `apiKey`, `email`, `name`.
|
|
53
|
+
|
|
54
|
+
## org
|
|
55
|
+
|
|
56
|
+
`org list` · `org use <orgId>` · `org personal` · `org current` ·
|
|
57
|
+
`org members` · `org create <name>` (at most 3 organizations per account; name ≤200)
|
|
58
|
+
|
|
59
|
+
Maps to `GET /organization/mine`, `/organization/me`, `/organization/members`,
|
|
60
|
+
`POST /organization/create`. Context is the `X-Org-Id` header; there is no
|
|
61
|
+
switch endpoint.
|
|
62
|
+
|
|
63
|
+
## ws (workspace)
|
|
64
|
+
|
|
65
|
+
| Command | API |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `ws list [-k keyword] [-s all\|me\|shared\|favorite] [--page] [--limit]` | `GET /workspace/search` — `--limit` max 100, `-1` returns at most 500 |
|
|
68
|
+
| `ws get [id]` | `GET /workspace/list/:id` |
|
|
69
|
+
| `ws use <id>` | stores the default workspace locally |
|
|
70
|
+
| `ws create <name> [-d] [-r ratio] [-l lang] [-t type] [-a app...]` | `POST /workspace/create` |
|
|
71
|
+
| `ws update [id] [-n] [-d] [-r] [-l] [--set]` | `PUT /workspace/list/:id` |
|
|
72
|
+
| `ws rm <id> [-y]` | `DELETE /workspace/list/:id` (owner only) |
|
|
73
|
+
| `ws favorite <id> [--off]` | `PUT /workspace/list/:id/favorite` |
|
|
74
|
+
| `ws fs [id] [-a appId]` | `GET /workspace/list/:id/fs[/:appid]` |
|
|
75
|
+
| `ws app list\|add <app> [-n]\|rm <appId> [-y]` | `POST/DELETE /workspace/list/:id/apps` |
|
|
76
|
+
| `ws member list\|add <userId> [-r role]\|role <memberId> <role>\|rm <memberId> [-y]` | `/workspace/list/:id/member/*` |
|
|
77
|
+
| `ws quota [id] [--set k=v]` | `GET .../quota-usage`, `PUT .../quota` |
|
|
78
|
+
| `ws stats [id]` | `GET /workspace/list/:id/stats` |
|
|
79
|
+
| `ws templates` / `ws clone <templateId>` | `GET /workspace/start/templates`, `POST /workspace/create/:id` |
|
|
80
|
+
|
|
81
|
+
Caps: 50 workspaces per account (`ws create` and `ws clone`), names ≤200
|
|
82
|
+
characters, descriptions ≤5,000.
|
|
83
|
+
|
|
84
|
+
App tokens for `-a` / `ws app add`: `dataset`, `datasetimagegeneration`,
|
|
85
|
+
`canvas` (InfiniteCanvas), `document`, `draw`, `files`, `playscript`, `batch`,
|
|
86
|
+
`digitalhost`.
|
|
87
|
+
|
|
88
|
+
Restriction from the backend: `Dataset`, `Draw`, `DatasetImageGeneration` and
|
|
89
|
+
`Files` may exist at most once per workspace.
|
|
90
|
+
|
|
91
|
+
## fs (fsnode)
|
|
92
|
+
|
|
93
|
+
| Command | API |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| `fs root [key] [-d depth]` | `GET /fsnode/root[/:key]` — key defaults to your drive; pass a workspace id for its root |
|
|
96
|
+
| `fs ls <id> [--limit] [--scope]` | `GET /fsnode/list/:id/children` |
|
|
97
|
+
| `fs tree <id> [-d depth]` | `GET /fsnode/list/:id/tree` |
|
|
98
|
+
| `fs get <id> [--scope]` | `GET /fsnode/list/:id` (comma-separated ids allowed) |
|
|
99
|
+
| `fs path <id>` | `GET /fsnode/list/:id/path` |
|
|
100
|
+
| `fs mkdir <parent> <name> [--nickname] [--content]` | `POST /fsnode/create` type=folder |
|
|
101
|
+
| `fs touch <parent> <name> [--mimetype] [--asset] [--content]` | `POST /fsnode/create` type=file |
|
|
102
|
+
| `fs set <id> [-n] [--nickname] [--content] [--tags] [--images] [--icon] [--asset] [--sort] [--set]` | `PATCH /fsnode/list/:id` |
|
|
103
|
+
| `fs describe <id> <text>` | merges `content.description` |
|
|
104
|
+
| `fs rm <id> [-y]` | `DELETE /fsnode/list/:id` (soft delete, whole subtree) |
|
|
105
|
+
| `fs sort <parent> <ids...>` | `PATCH /fsnode/list/:id/children/sort` |
|
|
106
|
+
| `fs batch <json>` | `PATCH /fsnode/batch` — `[{id, name?, content?, sort?, file?}]` |
|
|
107
|
+
| `fs used-space` | `GET /fsnode/drive/used-space` |
|
|
108
|
+
|
|
109
|
+
`--content` replaces the entire content object. Names are capped at 500
|
|
110
|
+
characters, nicknames at 200, and `fs batch` at 100 items per call.
|
|
111
|
+
|
|
112
|
+
## dataset
|
|
113
|
+
|
|
114
|
+
| Command | Notes |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| `dataset new <parent> <name> [-t type] [-d description] [--images] [--nickname]` | creates an fsnode with mimetype `workspace/dataset` |
|
|
117
|
+
| `dataset list <folderId>` | dataset nodes in a folder |
|
|
118
|
+
| `dataset get <key>` | `GET /dataset/list/:key` (vector-store record) |
|
|
119
|
+
| `dataset rm <key> [-y]` | `DELETE /dataset/list/:key` |
|
|
120
|
+
|
|
121
|
+
Types (as the web app defines them): `outline`, `screenplay`, `character`,
|
|
122
|
+
`location`, `prop`, `outfit`, `scene`, `shot`, `other`. A character dataset
|
|
123
|
+
should carry a headshot, a character sheet and a voice sample (see SKILL.md).
|
|
124
|
+
|
|
125
|
+
Semantic dataset folders created with the Dataset app: `story`, `character`,
|
|
126
|
+
`location`, `prop`, `shot`, `other` (identified by `content.semanticKey`).
|
|
127
|
+
|
|
128
|
+
## asset
|
|
129
|
+
|
|
130
|
+
| Command | API |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| `asset upload <file...> [-w] [--store] [--vectorize] [--width] [--height] [--duration]` | `POST /assets/v2/upload` (multipart) |
|
|
133
|
+
| `asset import <url> [-w] [-n] [--type] [--raw]` | `POST /assets/create-from-url` (or `/import-from-url`) — http/https only; private, loopback, link-local and metadata hosts are rejected, including via redirect |
|
|
134
|
+
| `asset list [--store] [--page] [--limit]` | `GET /assets/search` — only `store` filters server-side; the endpoint otherwise returns your own assets |
|
|
135
|
+
| `asset get <id>` | `GET /assets/list/:id` |
|
|
136
|
+
| `asset status <ids...>` | `POST /assets/check-status` — batched 100 per request; returns only assets you created or in your workspaces |
|
|
137
|
+
| `asset update <id> [-n] [--tags]` | `PATCH /assets/list/:id` |
|
|
138
|
+
| `asset rm <id> [-y]` | `DELETE /assets/list/:id` |
|
|
139
|
+
| `asset download <ids...> [-o path]` | fetches `asset.url`; into a directory, each file is named after the asset and keeps the URL's extension |
|
|
140
|
+
| `asset resolve <url> [-w]` | `GET /assets/resolve-by-url` |
|
|
141
|
+
| `asset summary <id...>` | `POST /assets/list/:id/summary` or `/assets/summary/batch` — at most 100 ids, your own assets only |
|
|
142
|
+
|
|
143
|
+
Asset states: `0` pending, `1` ready, `-1` cancelled.
|
|
144
|
+
|
|
145
|
+
Uploads of `.html`, `.xhtml`, `.svg`, `.js` and `.xml` are stored as
|
|
146
|
+
`application/octet-stream` with `Content-Disposition: attachment`.
|
|
147
|
+
|
|
148
|
+
## canvas
|
|
149
|
+
|
|
150
|
+
Targets the canvas linked from the browser (top-bar link button) unless
|
|
151
|
+
`-c/--canvas <id>` is given. Every write is a plain fsnode call; an open canvas
|
|
152
|
+
updates live.
|
|
153
|
+
|
|
154
|
+
| Command | API / behaviour |
|
|
155
|
+
| --- | --- |
|
|
156
|
+
| `canvas status` (`link`) | `GET /canvas-link`, then the selected nodes read fresh from the canvas |
|
|
157
|
+
| `canvas unlink` | `DELETE /canvas-link`; the tab turns its button off at its next heartbeat (≤ 60s) |
|
|
158
|
+
| `canvas list [-w]` | canvases under each InfiniteCanvas app: `GET /workspace/list/:id/fs/:appId` → `workspace-v2/canvases` children |
|
|
159
|
+
| `canvas nodes [-c] [-k kind]` | `GET /fsnode/list/:canvasId/children?limit=-1` + `POST /assets/check-status` |
|
|
160
|
+
| `canvas get <nodeId> [-c]` | same load; one node with references (`@image1 ← id`) and frame slots |
|
|
161
|
+
| `canvas edges [-c] [--node]` | the `canvas/edge` children |
|
|
162
|
+
| `canvas add <kind> [-c] [-n] [-t\|--text-file] [--asset] [-p\|--prompt-file] [-m] [-r] [--resolution] [-d] [--set] [--from ids…] [--at x,y]` | `POST /fsnode/create` (`canvas/node/<kind>`), then one `canvas/edge` per `--from`. Kinds: text, title, comment, image, video, audio |
|
|
163
|
+
| `canvas set <nodeId> [-c] [-n] [-t] [--move x,y] [-p] [-m] [-r] [--resolution] [-d] [--set]` | read → merge → `PATCH /fsnode/list/:id` |
|
|
164
|
+
| `canvas connect <from> <to> [-c]` | `POST /fsnode/create` (`canvas/edge`); a first/last-frame video model gets `videoFrameSlot` start, then end |
|
|
165
|
+
| `canvas disconnect <from> <to> [-c]` | `DELETE /fsnode/list/:edgeId` |
|
|
166
|
+
| `canvas rm <nodeIds...> [-c] [-y]` | deletes the nodes' edges, then the nodes; refuses nodes still generating |
|
|
167
|
+
| `canvas gen <nodeId> [-c] [-y] [-w] [--timeout] [--interval]` | `POST /ai/assets/preComputeCost` → confirm → `POST /ai/assets/history/<kind>/generations` (`fsnode`, `scope: canvas`, `scopeId`) → PATCH the node's `file` and `generate.historyId/pendingAssetId` |
|
|
168
|
+
|
|
169
|
+
Storage format (what the web canvas writes):
|
|
170
|
+
|
|
171
|
+
- Node: `mimetype canvas/node/<kind>`, `content.position {x,y}`; text kinds
|
|
172
|
+
`content.text`; media `content.mode` `display` (asset in `file`) or
|
|
173
|
+
`generate` with `content.generate {prompt, model, ratio, resolution,
|
|
174
|
+
duration, values, improvePromptEnabled, historyId?, pendingAssetId?}`. Width
|
|
175
|
+
and height are not stored.
|
|
176
|
+
- Edge: `mimetype canvas/edge`, name `连线`, `content {fromNodeId, toNodeId,
|
|
177
|
+
sourceHandle, targetHandle, videoFrameSlot?}`. References are incoming edges
|
|
178
|
+
sorted by `sort` then id, numbered per source kind.
|
|
179
|
+
- `PATCH` replaces `content` whole, so the CLI always reads and merges first.
|
|
180
|
+
- Canvas apps skip the unique-sibling-name check, so names may repeat.
|
|
181
|
+
|
|
182
|
+
`add`/`set` validate ratio, resolution, duration and `--set` keys against the
|
|
183
|
+
model's form, fill its defaults, drop unknown parameters with a warning, and
|
|
184
|
+
set `autoDuration=false` when `-d` is passed. `-p` and `-t` are literal text
|
|
185
|
+
(`@image1` is not a file).
|
|
186
|
+
|
|
187
|
+
`canvas gen` builds the same request as the canvas Generate button: image,
|
|
188
|
+
video and audio references in order; text-node references prefixed to the
|
|
189
|
+
prompt as `[name]\ntext`; `startImage`/`endImage` from frame slots; Seedance
|
|
190
|
+
ref auto-duration sent as `-1`. References to dataset, bundle, table, YouTube,
|
|
191
|
+
sprite, layer or panorama nodes are refused — generate those from the browser.
|
|
192
|
+
|
|
193
|
+
Link state (`/canvas-link`, one per user, Redis TTL 300s): the tab `PUT`s
|
|
194
|
+
`{sessionId, takeover?, workspaceId, canvasId, selectedNodeIds, selectedNodes,
|
|
195
|
+
viewport, url}` on toggle (`takeover: true`), on selection change and every
|
|
196
|
+
60s. A non-takeover `PUT` from a tab that no longer owns the link gets
|
|
197
|
+
`409 canvas-link-gone`, which switches that tab's button off.
|
|
198
|
+
|
|
199
|
+
## gen
|
|
200
|
+
|
|
201
|
+
Shared flags: `-m/--model` (required), `-p/--prompt`, `-n/--n`, `-w/--workspace`,
|
|
202
|
+
`--fsnode`, `--scope`, `--scope-id`, `-r/--ratio`, `--tags`, `--values`,
|
|
203
|
+
`--set`, `--no-history`, `--wait`, `--timeout` (seconds, default 900),
|
|
204
|
+
`--interval` (seconds, default 5).
|
|
205
|
+
|
|
206
|
+
| Command | Extra flags | API |
|
|
207
|
+
| --- | --- | --- |
|
|
208
|
+
| `gen image` | `--ref`, `--omni`, `--style-ref`, `--reference-weight`, `--stylize`, `--model-options` | `POST /ai/assets/history/image/generations` |
|
|
209
|
+
| `gen video` | `-d/--duration`, `--start-image`, `--end-image`, `--ref`, `--ref-video`, `--ref-audio` | `POST /ai/assets/history/video/generations` |
|
|
210
|
+
| `gen audio` | `-d/--duration`, `--ref-audio` | `POST /ai/assets/history/audio/generations` |
|
|
211
|
+
| `gen cost -t <type> -m <model>` | `-n`, `-p`, `-d`, `-r`, `--refs`, `--values` | `POST /ai/assets/preComputeCost` |
|
|
212
|
+
|
|
213
|
+
`--no-history` calls `/ai/assets/<type>/generations`, which returns assets
|
|
214
|
+
directly and cannot be polled by history id.
|
|
215
|
+
|
|
216
|
+
Admission limits, per user and API key (changing IP does not reset them):
|
|
217
|
+
|
|
218
|
+
- Submissions: image 30/min, video 10/min, audio 20/min → HTTP 429.
|
|
219
|
+
- Queued + running jobs: FREE 3, VIP 10, SVIP 25 (admins can override per user)
|
|
220
|
+
→ HTTP 429 `排隊中的任務已達上限(N),請等待現有任務完成後再試`. Checked before anything is charged.
|
|
221
|
+
- Insufficient balance is rejected up front; there is no partial charge.
|
|
222
|
+
|
|
223
|
+
Server-owned `values` keys are stripped before billing: `num_images`,
|
|
224
|
+
`referenceImageCount`, `referenceVideoTotalDuration`, `hasReferenceVideo`,
|
|
225
|
+
`output_resolution`, `output_billing_key` and every `*Info` key. Numeric form
|
|
226
|
+
parameters are range-checked against the model's `min`/`max`.
|
|
227
|
+
|
|
228
|
+
`gen cost` validation: `n` 1–32, `duration` −1–600 (−1 = automatic),
|
|
229
|
+
`prompt` ≤10,000 characters, `aspectRatio` ≤32 characters,
|
|
230
|
+
`referenceImageCount` 0–64.
|
|
231
|
+
|
|
232
|
+
## history
|
|
233
|
+
|
|
234
|
+
`history list [-w] [--mode image|video|audio] [--fsnode] [--scope] [--scope-id] [--tags] [--bookmarked]` →
|
|
235
|
+
`GET /ai/assets/history/search`
|
|
236
|
+
|
|
237
|
+
`history get <id> [--wait] [--timeout] [--interval]` ·
|
|
238
|
+
`history bookmark <id> [--off]` · `history rm <id> [-y]` ·
|
|
239
|
+
`history download <id> [-o dir]`
|
|
240
|
+
|
|
241
|
+
## models
|
|
242
|
+
|
|
243
|
+
`models list [-f feature...] [-w] [-k keyword] [--all]` →
|
|
244
|
+
`GET /ai/model/list/:features`
|
|
245
|
+
|
|
246
|
+
The endpoint matches with `features.some(...)`, so an empty feature list returns
|
|
247
|
+
nothing; with no `-f` the CLI asks for every feature instead.
|
|
248
|
+
|
|
249
|
+
The response is a curated view — no `id`, `rate`, `tags` or `protocol` — and it
|
|
250
|
+
is de-duplicated by **`nickname`**, which is therefore the unique selector.
|
|
251
|
+
`name` is not unique (`seedance-2.0` exists twice under different providers).
|
|
252
|
+
Pass the `MODEL` column (the nickname) to `-m`.
|
|
253
|
+
|
|
254
|
+
`models get <name>` matches nickname first, then name, and warns when several
|
|
255
|
+
models share the name. It prints ratios, batch range, reference support,
|
|
256
|
+
duration range, accepted/required props, and the `form.other` parameters
|
|
257
|
+
reachable through `--set`.
|
|
258
|
+
`models features` lists the flags accepted by `-f`.
|
|
259
|
+
|
|
260
|
+
Features: `text`, `image`, `video`, `audio`, `tts`, `web`, `thinking`,
|
|
261
|
+
`function_calling`, `image_vision`, `video_vision`, `structured_output`,
|
|
262
|
+
`digital_host`, `upscale_video`.
|
|
263
|
+
|
|
264
|
+
## agent
|
|
265
|
+
|
|
266
|
+
`agent list` (public marketplace) · `agent mine` · `agent get <id>` ·
|
|
267
|
+
`agent create <name> -d [-i instructions] [-m model] [--visibility] [-c] [-t] [--greeting]` ·
|
|
268
|
+
`agent update <id> …` · `agent rm <id> [-y]` · `agent files <id>` ·
|
|
269
|
+
`agent categories [--mine]` · `agent tags [--mine]` · `agent recommend`
|
|
270
|
+
|
|
271
|
+
Skills & versions:
|
|
272
|
+
`agent skills <id>` · `agent skill-add <id> <ref...>` · `agent skill-remove <id> <ref...>` ·
|
|
273
|
+
`agent versions <id>` · `agent restore <id> <versionId>`. `agent create` also
|
|
274
|
+
takes `--skill <ref...>`.
|
|
275
|
+
|
|
276
|
+
- Skill refs: `system:<key>` (e.g. `system:image`) or `user:<skillId>` (a bare
|
|
277
|
+
value is treated as `user:`). They map to the agent's `skills: SkillRef[]`.
|
|
278
|
+
- Any edit that changes the agent's snapshot auto-records a version
|
|
279
|
+
(`GET /ai/agent/list/:id/versions`); `restore`
|
|
280
|
+
(`POST /ai/agent/list/:id/versions/:versionId/restore`) reverts to one and
|
|
281
|
+
itself records a new version.
|
|
282
|
+
|
|
283
|
+
Visibility: `private`, `unlist`, `public`. Instructions are only returned to
|
|
284
|
+
the agent's creator.
|
|
285
|
+
|
|
286
|
+
Field caps: name ≤200, model ≤100, description and greeting ≤5,000,
|
|
287
|
+
instructions ≤200,000 characters.
|
|
288
|
+
|
|
289
|
+
`-n/--name`, `-c/--category` and `-t/--tag` are **exact** server-side matches,
|
|
290
|
+
not fuzzy search — `--tag` matches agents whose tag array contains that tag.
|
|
291
|
+
There is no keyword search on agents; filter client-side with `--json | jq` if
|
|
292
|
+
you need substring matching.
|
|
293
|
+
|
|
294
|
+
## preset
|
|
295
|
+
|
|
296
|
+
`preset list` (usable) · `preset mine` · `preset public` ·
|
|
297
|
+
`preset workspace [id]` — all take `-k`, `-t tags`, `-s sort`, `--page`, `--limit`.
|
|
298
|
+
|
|
299
|
+
`preset get <id>` · `preset create <name> -p prompt [-d] [-c category] [-t] [--visibility] [-w]` ·
|
|
300
|
+
`preset update <id> …` · `preset rm <id> [-y]` · `preset fork <id>` ·
|
|
301
|
+
`preset copy <id> [workspaceId]` · `preset tags -s my|public|workspace`
|
|
302
|
+
|
|
303
|
+
`PUT /prompt-preset/list/:id` rebuilds every field from the body, so an omitted
|
|
304
|
+
field arrives as `undefined` and the request 500s. `preset update` therefore
|
|
305
|
+
reads the current preset (bypassing the 10s cache) and merges, which keeps
|
|
306
|
+
partial updates working.
|
|
307
|
+
|
|
308
|
+
Field caps: name ≤200, prompt ≤50,000, description ≤5,000 characters; at most
|
|
309
|
+
50 tags of ≤64 characters each.
|
|
310
|
+
|
|
311
|
+
Categories: `character`, `storyboard`, `multi_angle`, `composition`, `utility`.
|
|
312
|
+
Sorts: `weight`, `popular`, `latest`, `updated`. `-t` takes comma-separated
|
|
313
|
+
tags that must all match.
|
|
314
|
+
|
|
315
|
+
## skill
|
|
316
|
+
|
|
317
|
+
Skills are SKILL.md bundles stored server-side as `files: [{path, content}]`.
|
|
318
|
+
Only `.md` files persist (the importer drops everything else); scripts belong to
|
|
319
|
+
*system* skills, which are built-in and read-only.
|
|
320
|
+
|
|
321
|
+
| Command | API |
|
|
322
|
+
| --- | --- |
|
|
323
|
+
| `skill system` | `GET /ai/skill/system` — built-in skills `{kind:'system', key, name, description, runtime, script}` |
|
|
324
|
+
| `skill list [--page] [--limit]` | `GET /ai/skill/search` — your user skills |
|
|
325
|
+
| `skill get <id>` | `GET /ai/skill/:id` — metadata + file list (full content with `--json`) |
|
|
326
|
+
| `skill cat <id> [path]` | prints one file (defaults to SKILL.md) from the `get` response |
|
|
327
|
+
| `skill import <zip>` | `POST /ai/skill/import` (multipart `file`) — a zip whose root holds SKILL.md |
|
|
328
|
+
| `skill push <dir>` | zips a local folder's `.md` files and imports it (ergonomic `import`) |
|
|
329
|
+
| `skill pull <id> [dir] [-f]` | writes the bundle's files to disk |
|
|
330
|
+
| `skill update <id> [-n] [-d] [--visibility] [--dir] [-y]` | `PUT /ai/skill/:id` — metadata, or replace **all** files from `--dir` (confirms first) |
|
|
331
|
+
| `skill rm <id> [-y]` | `DELETE /ai/skill/:id` |
|
|
332
|
+
|
|
333
|
+
Import rules: the zip must contain `SKILL.md` at its root (or one folder deep — a
|
|
334
|
+
single common root folder is stripped). `SKILL.md` frontmatter `name:` is
|
|
335
|
+
required; `description:` is read too. Visibility is `private` (default) or
|
|
336
|
+
`unlist`.
|
|
337
|
+
|
|
338
|
+
Import limits (checked locally by `skill push` / `skill import` before upload):
|
|
339
|
+
zip ≤5MB, ≤200 entries, each `.md` ≤2MB uncompressed, ≤20MB total; 50 user
|
|
340
|
+
skills per account.
|
|
341
|
+
|
|
342
|
+
`skill update --dir` sends `files` in the JSON body instead, where the entity
|
|
343
|
+
caps each file at **200,000 characters** and a path at 512 (≤200 files; name
|
|
344
|
+
≤200, description ≤5,000). Use `skill push` for larger files.
|
|
345
|
+
|
|
346
|
+
## profile
|
|
347
|
+
|
|
348
|
+
`profile show` · `profile update [-n] [--handle] [--bio] [--email] [--contact-email] [--phone] [--website] [--avatar] [--banner]` ·
|
|
349
|
+
`profile password [-p]` · `profile logins` · `profile wallet [--limit]` ·
|
|
350
|
+
`profile search <keyword>`
|
|
351
|
+
|
|
352
|
+
`profile search` needs a keyword of 2–64 characters and `--limit` 1–20. It
|
|
353
|
+
fuzzy-matches name and handle, matches an email only exactly, and never
|
|
354
|
+
returns email addresses.
|
|
355
|
+
|
|
356
|
+
Handle rules: 3–24 chars, starts with a letter, lowercase letters/digits/underscore.
|
|
357
|
+
Pass `null` to clear a nullable field. Password minimum is 6 characters.
|
|
358
|
+
|
|
359
|
+
## API notes
|
|
360
|
+
|
|
361
|
+
- Responses are unwrapped JSON. Errors are `{ message, path, method, timestamp }`
|
|
362
|
+
with a matching HTTP status.
|
|
363
|
+
- An image history's `images` array carries **only `{id}`** — no status, no url.
|
|
364
|
+
Real state comes from `POST /assets/check-status`; the CLI does this for you
|
|
365
|
+
in `gen --wait`, `history get` and `history download`. Polling the history
|
|
366
|
+
alone would report success the moment the entry exists.
|
|
367
|
+
- Asset states: `status` `0` pending, `1` ready, `-1` cancelled; a `Completed`
|
|
368
|
+
asset carrying `error` is also a failure.
|
|
369
|
+
- Some GETs are cached per user for 10s, keyed on the full URL including the
|
|
370
|
+
query string.
|
|
371
|
+
- Paginated endpoints return `{ data, pagination: { total, page, limit, next,
|
|
372
|
+
hasNext, hasPrev, totalPages } }`. An explicit `limit` is capped at **100**.
|
|
373
|
+
`limit: -1` returns everything only on endpoints that opt in (`fs ls` does);
|
|
374
|
+
everywhere else it returns at most **500**. Check `pagination.hasNext`.
|
|
375
|
+
- Batch id arrays (`check-status`, `summary/batch`, `fs batch`) accept at most
|
|
376
|
+
100 entries, and a single malformed id fails the whole request.
|
|
377
|
+
- Anonymous auth routes are rate-limited per client IP: signin and refresh
|
|
378
|
+
10/min, signup 5/min, forgot-password 5/min. Authenticated routes are limited
|
|
379
|
+
per user or API key (default 200/min per route).
|
|
380
|
+
- Query strings use `qs` with `allowDots`, so `--set a.b=1` becomes `a.b=1`.
|
|
381
|
+
- Ids are Mongo ObjectIds.
|