octwin-cli 0.1.16 → 0.1.21
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 +136 -0
- package/README.md +33 -25
- package/dist/index.js +637 -179
- package/dist/lib/args-check.js +110 -0
- package/dist/lib/pack-source.js +68 -0
- package/dist/lib/rename.js +12 -41
- package/dist/lib/render-check.js +85 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,142 @@ Format: [Keep a Changelog](https://keepachangelog.com/) — newest first, bucket
|
|
|
5
5
|
**Added · Changed · Deprecated · Removed · Fixed · Security**. The platform-wide view lives in the
|
|
6
6
|
repo root [`CHANGELOG.md`](../../CHANGELOG.md); this file is the CLI-only cut that ships with the package.
|
|
7
7
|
|
|
8
|
+
## [0.1.21] - 2026-07-30
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`deploy` and `status` report the marketplace-listing verdict.** A manifest carrying
|
|
12
|
+
`listing.public: true` put the pack into an operator review queue, and the state existed only in
|
|
13
|
+
the console — so an author working from the CLI got no acknowledgement that the request had
|
|
14
|
+
registered, and never saw a rejection note (which the platform *requires* precisely because it is
|
|
15
|
+
their only feedback). Both commands now print it via `printPublicListing`, and stay silent for a
|
|
16
|
+
pack that never asked. `status` also distinguishes *approved* from *actually public*: an approval
|
|
17
|
+
pins the content sha it reviewed, so any edit returns the pack to the queue on its own.
|
|
18
|
+
- **`octwin pull` is discoverable.** It was implemented and answered `--help`, but appeared in
|
|
19
|
+
neither `octwin help` nor the README — the one command that recovers a deployed pack's only source
|
|
20
|
+
copy was invisible unless you already knew its name. Also added to the scope-requirement table, so
|
|
21
|
+
a 403 names `pack:deploy` instead of printing the generic hint.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- **The capability-reference drift check no longer fails silently on a narrow token.** The `?meta=1`
|
|
25
|
+
poll needs `pack:deploy`, but it rides on every networked command — so an author inspecting data
|
|
26
|
+
with a `records:read`-only token got no drift signal at all, and a stale reference is exactly what
|
|
27
|
+
leads to inventing a primitive from memory. A 401/403 there now says so once.
|
|
28
|
+
- **README: casework is declared in `worklist.yaml`, not a `cases.yaml`.** That grammar was retired;
|
|
29
|
+
following the README produced a pack whose casework silently never loaded. `octwin media generate`
|
|
30
|
+
was also missing from the command table.
|
|
31
|
+
- **`records` no longer blames the plan for a route the plan does not gate.** `GET /xrm/entities`
|
|
32
|
+
carries only the scope guard, so a 403 on the entity list wrongly cited the `records` plan feature.
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
- **Unreachable rename branches in `init`.** The agent-id and `main`-flow renames sat behind
|
|
36
|
+
`--agent` / `--flow` options the CLI never parsed, against a template that ships no `main` flow —
|
|
37
|
+
both branches could never fire, and their patterns would have matched nothing if they had.
|
|
38
|
+
|
|
39
|
+
## [0.1.20] - 2026-07-29
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
- **`octwin validate` catches primitive arguments the platform would drop — offline, no token.** A
|
|
43
|
+
primitive takes the arguments it declares and silently ignored the rest, so an invented or
|
|
44
|
+
misspelled `args:` key deployed clean, ran clean, and simply did nothing: `record_list args: {
|
|
45
|
+
order: … }` (the argument is `sort`) never ordered, and `booking_cancel args: { booking_record_id:
|
|
46
|
+
… }` meant the REQUIRED `record_id` never arrived, so cancelling just failed. Validate now replays
|
|
47
|
+
the platform's contract from the pulled KB (`primitives/*.json` → `inputSchema`) and names the bad
|
|
48
|
+
argument, what the primitive takes, and any required argument that is missing. Scanning the 21
|
|
49
|
+
shipped marketplace packs found **ten** such errors across five packs. Keys are checked, values are
|
|
50
|
+
not — an `args:` value is normally an expression string resolved at runtime.
|
|
51
|
+
[`args-check.ts`](src/lib/args-check.ts).
|
|
52
|
+
- Silently skipped when the KB has not been pulled yet, like the render-intent check beside it.
|
|
53
|
+
- It cannot see inside a `use:` template body (expanding one is the platform's job) — `octwin
|
|
54
|
+
validate --remote` covers that case, and now also reports unreachable `$bind.<path>` reads and
|
|
55
|
+
`outputs:` port typos, which have no offline equivalent.
|
|
56
|
+
|
|
57
|
+
## [0.1.19] - 2026-07-29
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
- **`octwin validate` catches render-intent fields the platform would drop — offline, no token.** Each
|
|
61
|
+
render intent takes a fixed field set; a key outside it used to be swallowed at load and dropped at
|
|
62
|
+
render, with no error anywhere — just a card missing what the author wrote. Validate now replays the
|
|
63
|
+
platform's own contract from the pulled KB (`render-intents/*.json` → `allowed_keys`) and names the
|
|
64
|
+
bad field, the intent, and what is allowed. Scanning the 21 shipped marketplace packs found two real
|
|
65
|
+
instances in 223 intents: a `text_card` carrying `buttons` (the fallback's only escape button never
|
|
66
|
+
rendered) and a `list_picker` carrying a non-existent `group_by` (a whole mapper step feeding a
|
|
67
|
+
fabricated parameter). Silently skipped when the KB has not been pulled yet.
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
- **`octwin platform-kb pull` now explodes the reference and writes an `INDEX.md`.** A pull used to
|
|
71
|
+
write ~787 KB across 34 flat files — about 225k tokens, more than the pack being authored — so
|
|
72
|
+
finding one primitive meant reading a 122 KB catalog. Catalogs the platform describes as
|
|
73
|
+
enumerable are now written **one file per entry** (`primitives/record_list.json`,
|
|
74
|
+
`render-intents/carousel.json`, `declarations/xrm.json`, …), with `INDEX.md` mapping every doc and
|
|
75
|
+
all 171 entries to its file with a one-line summary. Reading one primitive went from ~38k tokens to
|
|
76
|
+
~700. The layout comes from the platform (an `entries` descriptor on the bundle index) rather than
|
|
77
|
+
being hardcoded here, so this CLI keeps working against any platform version and a platform that
|
|
78
|
+
adds a catalog needs no CLI release. The pulled directory is cleared each pull, so a withdrawn
|
|
79
|
+
capability cannot linger as a file the authoring agent reads as current — its *contents* are
|
|
80
|
+
cleared rather than the directory itself, since on Windows a directory that is any shell's working
|
|
81
|
+
directory cannot be removed.
|
|
82
|
+
|
|
83
|
+
## [0.1.18] - 2026-07-29
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
- **The bundle collector and the platform's repo import disagreed about what a pack directory
|
|
87
|
+
contains.** `collectBundleFiles` had its own rule and kept three things the operator's GitHub
|
|
88
|
+
import drops: `*.ts`/`*.tsx`, `__snapshots__/` and `*.example`. Because the server rejects a
|
|
89
|
+
`.ts` outright, the same directory imported cleanly from GitHub and failed to deploy from
|
|
90
|
+
disk with `'…': executable code is not allowed` — an error blaming a file that was never
|
|
91
|
+
meant to ship (a snapshot test beside a flow, or the documented `xrm.yaml.example` template).
|
|
92
|
+
The rule now lives in a vendored `lib/pack-source.ts` beside the vendored validator, and a
|
|
93
|
+
parity test in the platform drives both copies over one table.
|
|
94
|
+
|
|
95
|
+
### Removed
|
|
96
|
+
- **`pack.json` is gone — the saved login IS the deploy target.** The file had eroded to a single
|
|
97
|
+
field, `platform_url`, which `octwin login --url … --token …` already states; `tenant`/`project`
|
|
98
|
+
became optional overrides once deploy tokens started carrying their own tenant and project pin.
|
|
99
|
+
So it was a second home for a fact `login` knew, and it cost real things: a machine-specific file
|
|
100
|
+
committed into every pack repo, a four-link config-precedence chain to document, and an
|
|
101
|
+
exclusion rule duplicated in the bundler and the server (which had already drifted apart).
|
|
102
|
+
`octwin init` and `octwin pull` no longer write one, and nothing reads one. **A pack directory is
|
|
103
|
+
now pack content and nothing else** — the same repo deploys from any machine, and a pulled pack
|
|
104
|
+
redeploys with no flags.
|
|
105
|
+
|
|
106
|
+
### Changed
|
|
107
|
+
- **`octwin login` now sets the default deploy target**, not just the token: it writes a
|
|
108
|
+
`default_url` key alongside the token in `~/.octwin/credentials.json`. Every command resolves
|
|
109
|
+
**flags → env (`PACK_PLATFORM_URL`/`PACK_TENANT`/`PACK_PROJECT`/`PACK_TOKEN`) → saved login**.
|
|
110
|
+
An existing credentials file simply has no `default_url` until the next `octwin login` — which is
|
|
111
|
+
exactly what the "no platform url" error now tells you to run. CI is unaffected (it passes
|
|
112
|
+
`PACK_PLATFORM_URL` + `PACK_TOKEN` as env and never had a `pack.json`).
|
|
113
|
+
|
|
114
|
+
## [0.1.17] - 2026-07-27
|
|
115
|
+
|
|
116
|
+
### Added
|
|
117
|
+
- **`octwin pull <packId>` — write a DEPLOYED pack's source back to disk.** The inverse of
|
|
118
|
+
`deploy`. A pack pushed with the CLI lived on the platform as an artifact the runtime served
|
|
119
|
+
but nothing could hand back, so its only source copy was the machine that pushed it. Pull it,
|
|
120
|
+
fix it, redeploy it. Writes a `pack.json` (retired in 0.1.18 — the saved login is now the
|
|
121
|
+
target) so the pulled directory redeploys where it came from; `--version` picks a version,
|
|
122
|
+
`--force` overwrites a non-empty dir. You may pull a pack
|
|
123
|
+
your tenant OWNS (an operator token pulls any) — a pack you merely installed is not yours to
|
|
124
|
+
read.
|
|
125
|
+
- **`octwin chat --script <file>` — drive a whole conversation from one invocation.** One turn per
|
|
126
|
+
line, in order, in a single process over a single SSE connection, waiting for each turn to settle
|
|
127
|
+
before sending the next. Blank lines and `#` comments are skipped; `tap:<id>` presses a rendered
|
|
128
|
+
row/button (the rest of the line is kept verbatim, since a tap id is itself colon-delimited),
|
|
129
|
+
`media:<path>` uploads a file, and `media:<path> | caption` attaches one.
|
|
130
|
+
|
|
131
|
+
This exists because **chaining invocations races the agent loop.** A turn ends on a quiet gap
|
|
132
|
+
(`TURN_SETTLE_MS`), which can arrive while the server-side loop is still running — so
|
|
133
|
+
`chat A && chat B` lets B's inbound land mid-turn, and the agent fills required fields with
|
|
134
|
+
placeholder text (`service_id: "service-id"`) or starts a second workflow run. Those look exactly
|
|
135
|
+
like flow bugs and cost a field author three separate investigations. The one-turn-per-invocation
|
|
136
|
+
rule is now stated in `chat --help` and the header usage as well.
|
|
137
|
+
|
|
138
|
+
### Changed
|
|
139
|
+
- **`octwin deploy` reports the suspended runs it invalidated.** A redeploy rebuilds the pack's
|
|
140
|
+
tools, and in-flight flow runs live in those tools — so every suspended conversation is dropped.
|
|
141
|
+
The deploy prints `ⓘ N suspended run(s) invalidated` when N > 0, instead of leaving the author to
|
|
142
|
+
discover it as a `workflow_resume_stale` on the next tap.
|
|
143
|
+
|
|
8
144
|
## [0.1.16] - 2026-07-26
|
|
9
145
|
|
|
10
146
|
### Added
|
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ git init && git add -A && git commit -m "init pack"
|
|
|
43
43
|
# 2. Author it — edit manifest.yaml, flows/tools/main.flow.yaml (+ its locale),
|
|
44
44
|
# and prompts/identity.md. Everything is pure YAML.
|
|
45
45
|
|
|
46
|
-
# 3. Point it at your platform
|
|
46
|
+
# 3. Point it at your platform — one command, no config file
|
|
47
47
|
# (Octwin console → your workspace → API tokens → Generate)
|
|
48
48
|
octwin login --url https://your-octwin.example.com --token oct_…
|
|
49
49
|
|
|
@@ -60,12 +60,13 @@ octwin status # "✓ live and current" once it's warm
|
|
|
60
60
|
|
|
61
61
|
| Command | What it does |
|
|
62
62
|
| --- | --- |
|
|
63
|
-
| `octwin init <dir>` | Scaffold a new pure-YAML pack into `<dir>` (writes a starter `manifest.yaml`, flow, prompt, and `
|
|
63
|
+
| `octwin init <dir>` | Scaffold a new pure-YAML pack into `<dir>` (writes a starter `manifest.yaml`, flow, prompt, `.gitignore` and `README.md` — pack content only). Options: `--id`, `--description`, `--display-name`. |
|
|
64
64
|
| `octwin validate` | Check the pack locally (structure + pure-YAML rules). The platform re-validates the full manifest/flow schema on deploy. |
|
|
65
|
-
| `octwin login` | Save a deploy token for a platform URL (stored in `~/.octwin/credentials.json`). `--url`, `--token`. |
|
|
65
|
+
| `octwin login` | Save a deploy token for a platform URL **and make that URL the default target** (both stored in `~/.octwin/credentials.json`). `--url`, `--token`. |
|
|
66
66
|
| `octwin whoami` | Verify the saved/passed token is valid for a tenant. `--url`, `--tenant`. |
|
|
67
|
-
| `octwin deploy` | Upload + install the pack onto your tenant's project. `--seed` also runs the pack's demo seed. |
|
|
68
|
-
| `octwin status` | Report what the platform has live for this pack — installed version, the **content sha** the instance loaded vs. the one the catalog holds (a redeploy of the *same* version changes it), and
|
|
67
|
+
| `octwin deploy` | Upload + install the pack onto your tenant's project. `--seed` also runs the pack's demo seed. Reports the **marketplace-listing verdict** when the manifest carries `listing.public: true`. |
|
|
68
|
+
| `octwin status` | Report what the platform has live for this pack — installed version, the **content sha** the instance loaded vs. the one the catalog holds (a redeploy of the *same* version changes it), its flows, and whether it is live on the public marketplace. |
|
|
69
|
+
| `octwin pull <packId>` | Write a **deployed** pack's source back to disk — the inverse of `deploy`, and how a pack pushed from one machine is recovered. Defaults to the version installed on the target project; `--version` overrides, `--dir` defaults to `./<packId>`, a non-empty dir needs `--force`. You may pull a pack your tenant **owns**. |
|
|
69
70
|
| `octwin chat "msg"` | Drive a turn through the dev web channel and print **every render with its tap ids**. `--as <handle>` picks the test user; `--tap "<tap-id>"` presses a rendered button/list row; `--json` dumps the raw envelopes. |
|
|
70
71
|
| `octwin logs` | List recent conversations (handle, status, last activity; `--as` filters), or show one conversation's full event timeline — including what each turn rendered. `--json` for raw payloads. |
|
|
71
72
|
| `octwin records` | Inspect the pack's XRM data (needs a `records:read` token). No args = list entities. |
|
|
@@ -75,7 +76,8 @@ octwin status # "✓ live and current" once it's warm
|
|
|
75
76
|
| `octwin analytics` | Stage-by-stage conversion for **any** entity declared with a `pipeline:` (`--overview` / `--milestones` / `--trends` / `--cost`; `--stage <id>` lists the records currently at a stage). Needs `records:read`. |
|
|
76
77
|
| `octwin catalog` | Commerce products with price / availability / stock, plus the WhatsApp catalog binding. `--readiness` runs the Meta Graph checklist. Needs `catalog:read` + the `catalog` plan feature. |
|
|
77
78
|
| `octwin scheduling` | The scheduling engine's state, or `--slots <resourceRecordId>` for the slots one bookable resource actually computes — how you verify the availability rules `deploy --seed` created. Needs `scheduling:read`. |
|
|
78
|
-
| `octwin
|
|
79
|
+
| `octwin media generate "<prompt>"` | AI-generate an image, store it as a public asset, and print its `MEDIA-` handle + serve URL. `--out` downloads the bytes (WhatsApp renders only `.png`/`.jpg`); `--size`; `--json`. Pairs with `octwin chat --media` to drive media-collect flows. Needs `media:generate`. |
|
|
80
|
+
| `octwin platform-kb pull` | Pull the platform's capability reference into `.octwin/platform-kb/` for the **`octwin-pack`** Claude Code authoring plugin: guides as markdown, plus **one JSON file per capability** (`primitives/record_list.json`, `render-intents/carousel.json`, `declarations/xrm.json`, …) and an **`INDEX.md`** mapping every entry to its file — so a lookup is a small targeted read, not a whole catalog. |
|
|
79
81
|
| `octwin test` | Alias for `octwin validate --remote` — the platform's full manifest + flow-DSL check. |
|
|
80
82
|
| `octwin help` | Show usage. Every subcommand also answers `--help`. |
|
|
81
83
|
|
|
@@ -121,33 +123,37 @@ Three things worth knowing when you read the output:
|
|
|
121
123
|
|
|
122
124
|
## Configuration
|
|
123
125
|
|
|
124
|
-
|
|
125
|
-
pack
|
|
126
|
+
**`octwin login` is the configuration.** There is no config file in your pack — a pack directory
|
|
127
|
+
holds pack content and nothing else, so the same repo deploys from any machine:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
octwin login --url https://your-octwin.example.com --token oct_…
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
That stores the token *and* makes the URL your default target, in `~/.octwin/credentials.json`:
|
|
126
134
|
|
|
127
135
|
```jsonc
|
|
128
|
-
// pack.json — created by `octwin init`
|
|
129
136
|
{
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"project": "main" // defaults to "main"
|
|
137
|
+
"default_url": "https://your-octwin.example.com", // set by the last `octwin login`
|
|
138
|
+
"https://your-octwin.example.com": "oct_…" // token, keyed by platform url
|
|
133
139
|
}
|
|
134
140
|
```
|
|
135
141
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
142
|
+
Tenant and project need no setting at all — the **token carries its own tenant**, plus an optional
|
|
143
|
+
project pin. `--tenant` / `--project` exist only as overrides (a multi-workspace human, or an
|
|
144
|
+
unpinned token that must name a project).
|
|
139
145
|
|
|
140
|
-
Each setting resolves
|
|
146
|
+
Each setting resolves **flag → environment variable → saved login**:
|
|
141
147
|
|
|
142
|
-
| Setting | Flag | Env var |
|
|
148
|
+
| Setting | Flag | Env var | Saved login |
|
|
143
149
|
| --- | --- | --- | --- |
|
|
144
|
-
| Platform URL | `--url` | `PACK_PLATFORM_URL` | `
|
|
145
|
-
|
|
|
146
|
-
|
|
|
147
|
-
|
|
|
150
|
+
| Platform URL | `--url` | `PACK_PLATFORM_URL` | `default_url` |
|
|
151
|
+
| Deploy token | `--token` | `PACK_TOKEN` | token for that URL |
|
|
152
|
+
| Tenant slug *(override)* | `--tenant` | `PACK_TENANT` | — *(from the token)* |
|
|
153
|
+
| Project slug *(override)* | `--project` | `PACK_PROJECT` | — *(from the token's pin)* |
|
|
148
154
|
|
|
149
|
-
For **CI**, skip `
|
|
150
|
-
|
|
155
|
+
For **CI**, skip `login` entirely and pass `PACK_PLATFORM_URL` + `PACK_TOKEN` as environment
|
|
156
|
+
variables (add `PACK_PROJECT` only if the token isn't pinned).
|
|
151
157
|
|
|
152
158
|
## Authentication
|
|
153
159
|
|
|
@@ -166,8 +172,10 @@ A pack is **pure declarative data** — `.yaml` / `.yml` / `.md` / `.sql` / `.js
|
|
|
166
172
|
code (`.ts`/`.js`), HTTP routes, DB clients, and custom primitives are **not** allowed (this is what
|
|
167
173
|
makes an external pack safe to run on a shared platform; the server enforces it on deploy). For
|
|
168
174
|
domain records, use Octwin's first-class storage modules — **XRM** (records with stage pipelines),
|
|
169
|
-
**catalog** (products), or **casework** (tickets) — declared in `xrm.yaml`
|
|
170
|
-
needs **no database of its own**.
|
|
175
|
+
**catalog** (products), or **casework** (tickets) — declared in `xrm.yaml` and `worklist.yaml`, so a
|
|
176
|
+
pack needs **no database of its own**. (Casework rides `worklist.yaml`'s `work.<entity>` block;
|
|
177
|
+
there is no ~~`cases.yaml`~~ grammar. `octwin platform-kb pull` ships the authoritative list of
|
|
178
|
+
declaration files — read its `INDEX.md` rather than this paragraph.)
|
|
171
179
|
|
|
172
180
|
## Links
|
|
173
181
|
|