octwin-cli 0.1.9 → 0.1.10
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 +83 -0
- package/README.md +2 -1
- package/dist/index.js +82 -2
- package/package.json +2 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Changelog — octwin-cli
|
|
2
|
+
|
|
3
|
+
All notable changes to the `octwin` CLI (npm package [`octwin-cli`](https://www.npmjs.com/package/octwin-cli)).
|
|
4
|
+
Format: [Keep a Changelog](https://keepachangelog.com/) — newest first, bucketed into
|
|
5
|
+
**Added · Changed · Deprecated · Removed · Fixed · Security**. The platform-wide view lives in the
|
|
6
|
+
repo root [`CHANGELOG.md`](../../CHANGELOG.md); this file is the CLI-only cut that ships with the package.
|
|
7
|
+
|
|
8
|
+
## [0.1.10] - 2026-07-21
|
|
9
|
+
|
|
10
|
+
The capability reference is now **pulled, never bundled** — the authoring skill dropped its committed KB
|
|
11
|
+
snapshot, so `octwin platform-kb pull` is the single source of truth, and the CLI watches it for drift.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- **KB-drift nudge** — after any command that already talks to the platform (`deploy` / `status` /
|
|
15
|
+
`test` / `validate --remote` / `records` / `cases` / `logs` / `whoami`), the CLI does one tiny
|
|
16
|
+
`octwin-platform-kb?meta=1` GET and prints a one-line "the platform capability reference changed —
|
|
17
|
+
`octwin platform-kb pull`" when the platform's `content_hash` no longer matches your last pull.
|
|
18
|
+
Fail-silent + TTY-only + no-op until you've pulled once — the sibling of the existing CLI-upgrade notice.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- **`octwin platform-kb pull`** now records the reference's `content_hash` in `.octwin/platform-kb/index.json`
|
|
22
|
+
(the fingerprint the drift check compares against).
|
|
23
|
+
|
|
24
|
+
The conversation-debugging release — driven by the second author-feedback round (xpeng-egypt),
|
|
25
|
+
which found the author→validate→deploy loop solid but multi-turn debugging impossible from the CLI.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- **`octwin chat --tap "<tap-id>"`** — press a rendered button / list row (sends the web channel's
|
|
29
|
+
`type:'interactive'` inbound). Paired with full render printing, any tap-driven flow is now drivable headlessly.
|
|
30
|
+
- **Full render printing** — every reply prints its complete interactive content: list sections/rows,
|
|
31
|
+
buttons, and carousel cards, each with its **tap id**; header/footer/list-button text included.
|
|
32
|
+
- **`--json` on `chat` / `logs` / `cases`** — raw SSE envelopes (chat) or raw event/case payloads.
|
|
33
|
+
- **`octwin cases [caseId] [--queues]`** — inspect casework (support tickets): the inbox, one case +
|
|
34
|
+
timeline + applicable decisions, or queue keys with open counts. Casework packs previously had zero
|
|
35
|
+
data-inspection path (`records case` was a dead end).
|
|
36
|
+
- **Per-subcommand `--help`/`-h`** — intercepted before any network or auth work (previously
|
|
37
|
+
`octwin logs --help` made a network call and could die with a 401).
|
|
38
|
+
- Multi-message turns: `chat` now collects **all** of a turn's renders (quiet-gap detection) instead
|
|
39
|
+
of cutting at the first one.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- **`octwin logs`**: the conversation list shows contact handle + last activity and filters with
|
|
43
|
+
`--as <handle>`; the timeline prints **full** event text (no more 240-char truncation) plus the
|
|
44
|
+
renders each turn actually sent; footer points at `--json` / `mastra-messages` for verbatim payloads.
|
|
45
|
+
- **Network failures name the target URL** (`platform unreachable at <url>`), and 401s explain
|
|
46
|
+
invalid-token vs one-off transient instead of a bare status code.
|
|
47
|
+
- `octwin records` on an unknown entity now surfaces the server's error body, and for `case`/`cases`
|
|
48
|
+
points at `octwin cases`.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
- **Multi-turn chat actually works.** Two bugs made consecutive `octwin chat` calls look like "every
|
|
52
|
+
call starts fresh": (1) the idempotency `local_id` was a **constant** per handle, so the platform's
|
|
53
|
+
5-minute inbound dedup silently dropped the second message — a fresh id is now minted per call;
|
|
54
|
+
(2) a fresh SSE connect **replays** recent history and the CLI printed the first render frame — i.e.
|
|
55
|
+
the *previous* turn's greeting — as the reply; the CLI now drains the replay and only accepts frames
|
|
56
|
+
newer than the connect boundary. The platform always kept one open conversation per `--as` handle —
|
|
57
|
+
the same handle genuinely continues the same conversation now.
|
|
58
|
+
|
|
59
|
+
## [0.1.8] - 2026-07-21
|
|
60
|
+
- Global-first install guidance (`npm i -g octwin-cli`); upgrade notice suppressed under `npx`.
|
|
61
|
+
|
|
62
|
+
## [0.1.7] - 2026-07-21
|
|
63
|
+
- `--version`/`-v` flag; daily fail-silent, TTY-only "newer version available" notice.
|
|
64
|
+
|
|
65
|
+
## [0.1.6] - 2026-07-21
|
|
66
|
+
- `octwin init` scaffolds a home-hub menu (`home` list_picker + example `browse` tool) instead of a bare greeting.
|
|
67
|
+
|
|
68
|
+
## [0.1.5] - 2026-07-20
|
|
69
|
+
- `octwin validate --remote` (the platform's FULL manifest + flow-DSL check, all errors at once);
|
|
70
|
+
headless debugging commands `octwin records` / `octwin logs` / `octwin chat`; `octwin test` became
|
|
71
|
+
an alias for `validate --remote`. First author-feedback round.
|
|
72
|
+
|
|
73
|
+
## [0.1.4] - 2026-07-20
|
|
74
|
+
- Authoring reliability + DX fixes from the first end-to-end external-pack test.
|
|
75
|
+
|
|
76
|
+
## [0.1.3] - 2026-07-20
|
|
77
|
+
- `octwin platform-kb pull` — pull the platform capability reference for the authoring skill.
|
|
78
|
+
|
|
79
|
+
## [0.1.2] - 2026-07-20
|
|
80
|
+
- Proper npm README.
|
|
81
|
+
|
|
82
|
+
## [0.1.1] - 2026-07-20
|
|
83
|
+
- Initial npm publish: `init` / `validate` / `login` / `whoami` / `deploy` / `status`, `oct_` deploy tokens.
|
package/README.md
CHANGED
|
@@ -143,7 +143,8 @@ needs **no database of its own**.
|
|
|
143
143
|
## Links
|
|
144
144
|
|
|
145
145
|
- **npm:** <https://www.npmjs.com/package/octwin-cli>
|
|
146
|
-
- **Command help:** `octwin help`
|
|
146
|
+
- **Command help:** `octwin help` (each subcommand also answers `--help`)
|
|
147
|
+
- **Changelog:** [CHANGELOG.md](./CHANGELOG.md)
|
|
147
148
|
|
|
148
149
|
## License
|
|
149
150
|
|
package/dist/index.js
CHANGED
|
@@ -236,6 +236,66 @@ async function notifyIfOutdated() {
|
|
|
236
236
|
}
|
|
237
237
|
catch { /* a version check must never break the CLI */ }
|
|
238
238
|
}
|
|
239
|
+
// ── platform-KB drift check (observe the pulled reference, TTY-only, fail-silent) ──
|
|
240
|
+
/** The `content_hash` of a previously-pulled KB in `<packDir>/.octwin/platform-kb/`,
|
|
241
|
+
* or null if nothing has been pulled yet. */
|
|
242
|
+
function readLocalKbHash(packDir) {
|
|
243
|
+
try {
|
|
244
|
+
const idx = JSON.parse(readFileSync(join(packDir, '.octwin', 'platform-kb', 'index.json'), 'utf8'));
|
|
245
|
+
return typeof idx.content_hash === 'string' ? idx.content_hash : null;
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/** Nudge (to stderr) when the platform's capability KB has changed since the last
|
|
252
|
+
* `octwin platform-kb pull`. The sibling of `notifyIfOutdated`, for the KB instead
|
|
253
|
+
* of the CLI: run only after commands that already hit the platform, so this adds
|
|
254
|
+
* a single tiny `?meta=1` GET on top of work that was networked anyway. Never
|
|
255
|
+
* throws — observing must never break a command. No-op until the author has pulled
|
|
256
|
+
* once (nothing to compare) or if the target/token can't be resolved. */
|
|
257
|
+
async function notifyIfKbStale(flags) {
|
|
258
|
+
if (!process.stdout.isTTY)
|
|
259
|
+
return;
|
|
260
|
+
try {
|
|
261
|
+
const packDir = resolve(flags.dir ?? '.');
|
|
262
|
+
const localHash = readLocalKbHash(packDir);
|
|
263
|
+
if (!localHash)
|
|
264
|
+
return; // never pulled → the skill already says to pull
|
|
265
|
+
const t = resolveTargetOrNull(flags, packDir);
|
|
266
|
+
if (!t)
|
|
267
|
+
return;
|
|
268
|
+
const ctrl = new AbortController();
|
|
269
|
+
const timer = setTimeout(() => ctrl.abort(), 2_000);
|
|
270
|
+
const res = await fetch(`${t.url}/api/admin/tenants/${t.tenant}/octwin-platform-kb?meta=1`, {
|
|
271
|
+
headers: { authorization: `Bearer ${t.token}` }, signal: ctrl.signal,
|
|
272
|
+
});
|
|
273
|
+
clearTimeout(timer);
|
|
274
|
+
if (!res.ok)
|
|
275
|
+
return;
|
|
276
|
+
const meta = await res.json();
|
|
277
|
+
if (meta.content_hash && meta.content_hash !== localHash) {
|
|
278
|
+
console.error('\n⬆ the platform capability reference changed since you last pulled it.');
|
|
279
|
+
console.error(' Refresh it: octwin platform-kb pull');
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch { /* a KB check must never break the CLI */ }
|
|
283
|
+
}
|
|
284
|
+
/** Which commands already made an authed platform call, so the trailing KB-drift
|
|
285
|
+
* poll rides on existing network work (never on offline `validate` / `init`). */
|
|
286
|
+
function commandTouchesPlatform(command, flags) {
|
|
287
|
+
switch (command) {
|
|
288
|
+
case 'validate': return flags.remote === true; // offline validate stays offline
|
|
289
|
+
case 'deploy':
|
|
290
|
+
case 'status':
|
|
291
|
+
case 'test':
|
|
292
|
+
case 'records':
|
|
293
|
+
case 'cases':
|
|
294
|
+
case 'logs':
|
|
295
|
+
case 'whoami': return true;
|
|
296
|
+
default: return false;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
239
299
|
// ── commands ────────────────────────────────────────────────────────────────
|
|
240
300
|
function cmdInit(flags) {
|
|
241
301
|
const target = flags._[0] ?? die('usage: octwin init <dir> [--id my-pack]');
|
|
@@ -364,6 +424,19 @@ function resolveTarget(flags, packDir) {
|
|
|
364
424
|
die('no token — generate a deploy token in the console (Settings → API tokens), then `octwin login --url <url> --token oct_…` or pass --token');
|
|
365
425
|
return { url, tenant, project, token };
|
|
366
426
|
}
|
|
427
|
+
/** Non-fatal `resolveTarget`: returns null (never dies) when any of url/tenant/token
|
|
428
|
+
* is missing. Used by the fail-silent KB-staleness observer, which must never
|
|
429
|
+
* interrupt a command over a config gap. */
|
|
430
|
+
function resolveTargetOrNull(flags, packDir) {
|
|
431
|
+
const cfg = readPackConfig(packDir);
|
|
432
|
+
const url = (flags.url ?? process.env.PACK_PLATFORM_URL ?? cfg.platform_url ?? '').replace(/\/$/, '');
|
|
433
|
+
const tenant = flags.tenant ?? process.env.PACK_TENANT ?? cfg.tenant ?? '';
|
|
434
|
+
const project = flags.project ?? process.env.PACK_PROJECT ?? cfg.project ?? 'main';
|
|
435
|
+
const token = flags.token ?? process.env.PACK_TOKEN ?? readCreds()[url] ?? '';
|
|
436
|
+
if (!url || !tenant || !token)
|
|
437
|
+
return null;
|
|
438
|
+
return { url, tenant, project, token };
|
|
439
|
+
}
|
|
367
440
|
async function cmdWhoami(flags) {
|
|
368
441
|
const packDir = resolve(flags.dir ?? '.');
|
|
369
442
|
const { url, tenant, token } = resolveTarget(flags, packDir);
|
|
@@ -561,7 +634,9 @@ async function cmdPlatformKb(flags) {
|
|
|
561
634
|
writeFileSync(join(outDir, `${key}.json`), JSON.stringify(val, null, 2) + '\n', 'utf8');
|
|
562
635
|
jsonCount++;
|
|
563
636
|
}
|
|
564
|
-
|
|
637
|
+
// Persist `content_hash` too — the staleness observer (`notifyIfKbStale`) reads
|
|
638
|
+
// it back and compares against the platform's current hash to nudge a re-pull.
|
|
639
|
+
writeFileSync(join(outDir, 'index.json'), JSON.stringify({ version: bundle.version, content_hash: bundle.content_hash, generated_at: bundle.generated_at, index: bundle.index }, null, 2) + '\n', 'utf8');
|
|
565
640
|
console.log(`✓ Pulled the Octwin platform KB → ${outDir}`);
|
|
566
641
|
console.log(` ${mdCount} markdown docs + ${jsonCount} JSON catalogs (reference version ${bundle.version ?? '?'})`);
|
|
567
642
|
console.log(' The octwin-pack authoring skill reads these as the source of truth for what the platform supports.');
|
|
@@ -1114,6 +1189,11 @@ async function main() {
|
|
|
1114
1189
|
break;
|
|
1115
1190
|
default: die(`unknown command '${command}' — run \`octwin help\``);
|
|
1116
1191
|
}
|
|
1117
|
-
|
|
1192
|
+
// Trailing, fail-silent, TTY-only notices. KB-drift only after commands that
|
|
1193
|
+
// already hit the platform (so it's one extra tiny GET, never a new call on
|
|
1194
|
+
// offline paths); CLI-upgrade always.
|
|
1195
|
+
if (commandTouchesPlatform(command, flags))
|
|
1196
|
+
await notifyIfKbStale(flags);
|
|
1197
|
+
await notifyIfOutdated();
|
|
1118
1198
|
}
|
|
1119
1199
|
main().catch((err) => die(err?.message ?? String(err)));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "octwin-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Octwin external-pack developer CLI (by CEQUENS) — scaffold, validate, deploy, and check pure-YAML packs on your tenant.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"dist",
|
|
11
11
|
"templates",
|
|
12
12
|
"README.md",
|
|
13
|
+
"CHANGELOG.md",
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"engines": {
|