@paneui/cli 0.0.6 → 0.0.8
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 +9 -9
- package/dist/commands/agent.js +17 -4
- package/dist/commands/attachment-delete.js +37 -0
- package/dist/commands/{blob-download.js → attachment-download.js} +15 -11
- package/dist/commands/{blob-list.js → attachment-list.js} +9 -9
- package/dist/commands/{blob-show.js → attachment-show.js} +11 -11
- package/dist/commands/{blob-token.js → attachment-token.js} +31 -31
- package/dist/commands/{blob-upload.js → attachment-upload.js} +20 -20
- package/dist/commands/{blob.js → attachment.js} +40 -40
- package/dist/commands/claim.js +68 -0
- package/dist/commands/create.js +71 -71
- package/dist/commands/delete.js +12 -12
- package/dist/commands/feedback.js +5 -5
- package/dist/commands/list.js +23 -23
- package/dist/commands/participant.js +38 -38
- package/dist/commands/send.js +33 -27
- package/dist/commands/state.js +12 -12
- package/dist/commands/{session.js → surface.js} +24 -24
- package/dist/commands/taste.js +14 -14
- package/dist/commands/{artifact.js → template.js} +76 -76
- package/dist/commands/watch.js +22 -22
- package/dist/index.js +17 -17
- package/dist/input.js +2 -2
- package/dist/output.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/commands/blob-delete.js +0 -37
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// `pane
|
|
1
|
+
// `pane template` — manage reusable, versioned templates.
|
|
2
2
|
//
|
|
3
|
-
// Flat command namespace: `
|
|
3
|
+
// Flat command namespace: `template` is one top-level command that branches on
|
|
4
4
|
// a positional subcommand (create / version / update / search / list / show /
|
|
5
5
|
// delete).
|
|
6
|
-
// An
|
|
7
|
-
// schema); a
|
|
8
|
-
// once and instancing it via `pane
|
|
6
|
+
// An template is a reusable UI template (HTML + event schema + optional input
|
|
7
|
+
// schema); a surface is one *use* of one version of it. Authoring an template
|
|
8
|
+
// once and instancing it via `pane surface create --template-id` removes the
|
|
9
9
|
// per-use cost of regenerating the same HTML.
|
|
10
10
|
import { createArtifactSchema, createArtifactVersionSchema, patchArtifactMetadataSchema, } from "@paneui/core";
|
|
11
11
|
import { assertKnownFlags } from "../argv.js";
|
|
@@ -17,14 +17,14 @@ const CREATE_FLAGS = [
|
|
|
17
17
|
"slug",
|
|
18
18
|
"description",
|
|
19
19
|
"tags",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"template",
|
|
21
|
+
"template-type",
|
|
22
22
|
"event-schema",
|
|
23
23
|
"input-schema",
|
|
24
24
|
];
|
|
25
25
|
const VERSION_FLAGS = [
|
|
26
|
-
"
|
|
27
|
-
"
|
|
26
|
+
"template",
|
|
27
|
+
"template-type",
|
|
28
28
|
"event-schema",
|
|
29
29
|
"input-schema",
|
|
30
30
|
];
|
|
@@ -32,70 +32,70 @@ const UPDATE_FLAGS = ["name", "slug", "description", "tags"];
|
|
|
32
32
|
const NO_FLAGS = [];
|
|
33
33
|
const NO_BOOLS = [];
|
|
34
34
|
const DELETE_BOOLS = ["yes"];
|
|
35
|
-
export const artifactHelp = `pane
|
|
35
|
+
export const artifactHelp = `pane template — manage reusable, versioned templates
|
|
36
36
|
|
|
37
|
-
An
|
|
38
|
-
input schema. A
|
|
39
|
-
once, then instance it many times with 'pane
|
|
40
|
-
instead of regenerating the HTML on every
|
|
37
|
+
An template is a reusable UI template: HTML + an event schema + an optional
|
|
38
|
+
input schema. A surface is one use of one version of it. Author an template
|
|
39
|
+
once, then instance it many times with 'pane surface create --template-id <id|slug>'
|
|
40
|
+
instead of regenerating the HTML on every surface.
|
|
41
41
|
|
|
42
42
|
Usage:
|
|
43
|
-
pane
|
|
43
|
+
pane template <subcommand> [options]
|
|
44
44
|
|
|
45
45
|
Subcommands:
|
|
46
|
-
create Create a named, reusable
|
|
47
|
-
version Append a new version to an existing
|
|
48
|
-
update Update an
|
|
49
|
-
search Search the agent's named
|
|
50
|
-
list List the agent's named
|
|
51
|
-
show Show a full
|
|
52
|
-
delete Permanently delete an
|
|
53
|
-
--yes. Refused with 409 conflict if any
|
|
54
|
-
closed) still references the
|
|
46
|
+
create Create a named, reusable template (its v1).
|
|
47
|
+
version Append a new version to an existing template.
|
|
48
|
+
update Update an template's head metadata (name/slug/description/tags).
|
|
49
|
+
search Search the agent's named templates (lean — no HTML).
|
|
50
|
+
list List the agent's named templates (search with no query).
|
|
51
|
+
show Show a full template: head metadata + its version list.
|
|
52
|
+
delete Permanently delete an template and ALL its versions. Requires
|
|
53
|
+
--yes. Refused with 409 conflict if any surface (open or
|
|
54
|
+
closed) still references the template — delete those first.
|
|
55
55
|
|
|
56
|
-
pane
|
|
56
|
+
pane template create --name <n> --template <path|inline>
|
|
57
57
|
[--event-schema <path|json>] [--slug <s>]
|
|
58
58
|
[--description <d>] [--tags <t1,t2>]
|
|
59
|
-
[--input-schema <path|json>] [--
|
|
60
|
-
Creates a named
|
|
59
|
+
[--input-schema <path|json>] [--template-type <t>]
|
|
60
|
+
Creates a named template. Prints { template_id, slug, version }.
|
|
61
61
|
|
|
62
|
-
pane
|
|
62
|
+
pane template version <id|slug> --template <path|inline>
|
|
63
63
|
[--event-schema <path|json>]
|
|
64
|
-
[--input-schema <path|json>] [--
|
|
65
|
-
Appends a new immutable version. Prints {
|
|
64
|
+
[--input-schema <path|json>] [--template-type <t>]
|
|
65
|
+
Appends a new immutable version. Prints { template_id, version }.
|
|
66
66
|
|
|
67
|
-
pane
|
|
67
|
+
pane template update <id|slug> [--name <n>] [--slug <s>]
|
|
68
68
|
[--description <d>] [--tags <t1,t2>]
|
|
69
69
|
Updates head metadata only (never the content). Prints the lean summary.
|
|
70
70
|
|
|
71
|
-
pane
|
|
71
|
+
pane template search [query]
|
|
72
72
|
Text search over name + description + tags, ranked by last_used_at.
|
|
73
73
|
Prints an array of { id, slug, name, description, tags,
|
|
74
74
|
latest_version, last_used_at }.
|
|
75
75
|
|
|
76
|
-
pane
|
|
77
|
-
Alias of 'search' with no query — lists all the agent's
|
|
76
|
+
pane template list
|
|
77
|
+
Alias of 'search' with no query — lists all the agent's templates.
|
|
78
78
|
|
|
79
|
-
pane
|
|
80
|
-
Prints the full
|
|
79
|
+
pane template show <id|slug>
|
|
80
|
+
Prints the full template: head metadata + every version's content.
|
|
81
81
|
|
|
82
|
-
pane
|
|
83
|
-
Permanently deletes the
|
|
84
|
-
(409 conflict) if any
|
|
85
|
-
of the
|
|
82
|
+
pane template delete <id|slug> --yes
|
|
83
|
+
Permanently deletes the template and all its versions. Refused
|
|
84
|
+
(409 conflict) if any surface in any state still references one
|
|
85
|
+
of the template's versions — run 'pane surface delete <surface-id>' on
|
|
86
86
|
each first, or wait for the relay's TTL sweeper to reclaim them.
|
|
87
|
-
Prints {
|
|
87
|
+
Prints { template, deleted: true } on success.
|
|
88
88
|
|
|
89
89
|
Options:
|
|
90
|
-
--name <n>
|
|
90
|
+
--name <n> Template display name (required for 'create').
|
|
91
91
|
--slug <s> Stable, agent-chosen handle (unique per agent). The
|
|
92
|
-
durable way to reference the
|
|
93
|
-
--description <d> Prose: what the
|
|
92
|
+
durable way to reference the template later.
|
|
93
|
+
--description <d> Prose: what the template is and does. Read by an agent
|
|
94
94
|
deciding whether to reuse it.
|
|
95
95
|
--tags <t1,t2,...> Comma-separated keywords for search.
|
|
96
|
-
--
|
|
96
|
+
--template <v> HTML template body — a file path, or inline HTML.
|
|
97
97
|
--event-schema <v> Event schema — a .json file path, or inline JSON.
|
|
98
|
-
Optional: omit for a view-only
|
|
98
|
+
Optional: omit for a view-only template (a
|
|
99
99
|
report/dashboard the human only views — no page/agent
|
|
100
100
|
events).
|
|
101
101
|
|
|
@@ -117,27 +117,27 @@ Options:
|
|
|
117
117
|
emittedBy is any non-empty subset of ["page", "agent"].
|
|
118
118
|
payload is a JSON Schema; the relay validates every
|
|
119
119
|
emit against it. See docs/SPEC.md for the full grammar.
|
|
120
|
-
--input-schema <v> JSON Schema for this
|
|
120
|
+
--input-schema <v> JSON Schema for this template's per-surface input_data —
|
|
121
121
|
a file path, or inline JSON. Optional.
|
|
122
|
-
--
|
|
122
|
+
--template-type <t> "html-inline" (default) or "html-ref".
|
|
123
123
|
--url <url> Relay base URL (overrides PANE_URL).
|
|
124
124
|
--api-key <key> Agent API key (overrides PANE_API_KEY).
|
|
125
125
|
-h, --help Show this help.
|
|
126
126
|
|
|
127
127
|
Output: stdout is machine-readable JSON.`;
|
|
128
|
-
/** Resolve --
|
|
128
|
+
/** Resolve --template-type, defaulting to html-inline. */
|
|
129
129
|
function resolveArtifactType(args) {
|
|
130
|
-
const t = (args.flags.get("
|
|
130
|
+
const t = (args.flags.get("template-type") ?? "html-inline");
|
|
131
131
|
if (t !== "html-inline" && t !== "html-ref") {
|
|
132
|
-
fail("--
|
|
132
|
+
fail("--template-type must be 'html-inline' or 'html-ref'", "invalid_args");
|
|
133
133
|
}
|
|
134
134
|
return t;
|
|
135
135
|
}
|
|
136
|
-
/** Resolve the
|
|
136
|
+
/** Resolve the template HTML body (file or inline; verbatim URL for html-ref). */
|
|
137
137
|
function resolveSource(args, type) {
|
|
138
|
-
const artifactVal = args.flags.get("
|
|
138
|
+
const artifactVal = args.flags.get("template");
|
|
139
139
|
if (!artifactVal)
|
|
140
|
-
fail("missing --
|
|
140
|
+
fail("missing --template", "invalid_args");
|
|
141
141
|
try {
|
|
142
142
|
return type === "html-ref" ? artifactVal : resolveText(artifactVal);
|
|
143
143
|
}
|
|
@@ -148,7 +148,7 @@ function resolveSource(args, type) {
|
|
|
148
148
|
/**
|
|
149
149
|
* Resolve --event-schema — file path or inline JSON. --event-schema is
|
|
150
150
|
* optional: when absent this returns `undefined`, which makes a view-only
|
|
151
|
-
*
|
|
151
|
+
* template (no event vocabulary — the human only views it). The caller must
|
|
152
152
|
* omit `event_schema` from the request entirely when this returns `undefined`.
|
|
153
153
|
*/
|
|
154
154
|
function resolveEventSchema(args) {
|
|
@@ -190,7 +190,7 @@ function resolveTags(args) {
|
|
|
190
190
|
return tags.length > 0 ? tags : undefined;
|
|
191
191
|
}
|
|
192
192
|
async function runArtifactCreate(args) {
|
|
193
|
-
assertKnownFlags(args, CREATE_FLAGS, NO_BOOLS, "pane
|
|
193
|
+
assertKnownFlags(args, CREATE_FLAGS, NO_BOOLS, "pane template create");
|
|
194
194
|
const name = args.flags.get("name");
|
|
195
195
|
if (!name)
|
|
196
196
|
fail("missing --name", "invalid_args");
|
|
@@ -207,7 +207,7 @@ async function runArtifactCreate(args) {
|
|
|
207
207
|
type,
|
|
208
208
|
};
|
|
209
209
|
// event_schema is OMITTED entirely when --event-schema is absent — a view-only
|
|
210
|
-
//
|
|
210
|
+
// template. Setting it to `undefined` would still add the key.
|
|
211
211
|
if (eventSchema !== undefined)
|
|
212
212
|
candidate["event_schema"] = eventSchema;
|
|
213
213
|
if (slug !== undefined)
|
|
@@ -222,14 +222,14 @@ async function runArtifactCreate(args) {
|
|
|
222
222
|
if (!parsed.success) {
|
|
223
223
|
const issue = parsed.error.issues[0];
|
|
224
224
|
const where = issue && issue.path.length > 0 ? issue.path.join(".") : "request";
|
|
225
|
-
fail(`invalid
|
|
225
|
+
fail(`invalid template: ${where}: ${issue ? issue.message : "validation failed"}`, "invalid_args", parsed.error.flatten());
|
|
226
226
|
}
|
|
227
227
|
const req = parsed.data;
|
|
228
228
|
const client = makeClient(args);
|
|
229
229
|
try {
|
|
230
230
|
const res = await client.createArtifact(req);
|
|
231
231
|
printJson({
|
|
232
|
-
|
|
232
|
+
template_id: res.template_id,
|
|
233
233
|
slug: slug ?? null,
|
|
234
234
|
version: res.version,
|
|
235
235
|
});
|
|
@@ -239,10 +239,10 @@ async function runArtifactCreate(args) {
|
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
async function runArtifactVersion(args) {
|
|
242
|
-
assertKnownFlags(args, VERSION_FLAGS, NO_BOOLS, "pane
|
|
242
|
+
assertKnownFlags(args, VERSION_FLAGS, NO_BOOLS, "pane template version");
|
|
243
243
|
const idOrSlug = args.positionals[1];
|
|
244
244
|
if (!idOrSlug) {
|
|
245
|
-
fail("missing
|
|
245
|
+
fail("missing template <id|slug> — usage: pane template version <id|slug>", "invalid_args");
|
|
246
246
|
}
|
|
247
247
|
const type = resolveArtifactType(args);
|
|
248
248
|
const source = resolveSource(args, type);
|
|
@@ -268,17 +268,17 @@ async function runArtifactVersion(args) {
|
|
|
268
268
|
const client = makeClient(args);
|
|
269
269
|
try {
|
|
270
270
|
const res = await client.createArtifactVersion(idOrSlug, req);
|
|
271
|
-
printJson({
|
|
271
|
+
printJson({ template_id: res.template_id, version: res.version });
|
|
272
272
|
}
|
|
273
273
|
catch (e) {
|
|
274
274
|
failFromError(e);
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
async function runArtifactUpdate(args) {
|
|
278
|
-
assertKnownFlags(args, UPDATE_FLAGS, NO_BOOLS, "pane
|
|
278
|
+
assertKnownFlags(args, UPDATE_FLAGS, NO_BOOLS, "pane template update");
|
|
279
279
|
const idOrSlug = args.positionals[1];
|
|
280
280
|
if (!idOrSlug) {
|
|
281
|
-
fail("missing
|
|
281
|
+
fail("missing template <id|slug> — usage: pane template update <id|slug>", "invalid_args");
|
|
282
282
|
}
|
|
283
283
|
const candidate = {};
|
|
284
284
|
const name = args.flags.get("name");
|
|
@@ -313,7 +313,7 @@ async function runArtifactUpdate(args) {
|
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
async function runArtifactSearch(args, query) {
|
|
316
|
-
assertKnownFlags(args, NO_FLAGS, NO_BOOLS, query === undefined ? "pane
|
|
316
|
+
assertKnownFlags(args, NO_FLAGS, NO_BOOLS, query === undefined ? "pane template list" : "pane template search");
|
|
317
317
|
const client = makeClient(args);
|
|
318
318
|
try {
|
|
319
319
|
const res = await client.searchArtifacts(query);
|
|
@@ -324,10 +324,10 @@ async function runArtifactSearch(args, query) {
|
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
async function runArtifactShow(args) {
|
|
327
|
-
assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane
|
|
327
|
+
assertKnownFlags(args, NO_FLAGS, NO_BOOLS, "pane template show");
|
|
328
328
|
const idOrSlug = args.positionals[1];
|
|
329
329
|
if (!idOrSlug) {
|
|
330
|
-
fail("missing
|
|
330
|
+
fail("missing template <id|slug> — usage: pane template show <id|slug>", "invalid_args");
|
|
331
331
|
}
|
|
332
332
|
const client = makeClient(args);
|
|
333
333
|
try {
|
|
@@ -338,24 +338,24 @@ async function runArtifactShow(args) {
|
|
|
338
338
|
failFromError(e);
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
-
// `pane
|
|
341
|
+
// `pane template delete <id|slug> --yes` — remove an template (and, server-
|
|
342
342
|
// side, all its versions). The relay refuses with 409 conflict if any
|
|
343
|
-
//
|
|
343
|
+
// surface still references it; the CLI surfaces that as the relay-supplied
|
|
344
344
|
// envelope. `--yes` is required because there's no Undo button on a delete
|
|
345
|
-
// and the same `pane
|
|
345
|
+
// and the same `pane template create` slug isn't reservable once gone.
|
|
346
346
|
async function runArtifactDelete(args) {
|
|
347
|
-
assertKnownFlags(args, NO_FLAGS, DELETE_BOOLS, "pane
|
|
347
|
+
assertKnownFlags(args, NO_FLAGS, DELETE_BOOLS, "pane template delete");
|
|
348
348
|
const idOrSlug = args.positionals[1];
|
|
349
349
|
if (!idOrSlug) {
|
|
350
|
-
fail("missing
|
|
350
|
+
fail("missing template <id|slug> — usage: pane template delete <id|slug> --yes", "invalid_args");
|
|
351
351
|
}
|
|
352
352
|
if (!args.bools.has("yes")) {
|
|
353
|
-
fail("'pane
|
|
353
|
+
fail("'pane template delete' permanently removes the template and all its versions — it is destructive. Pass --yes to confirm.", "invalid_args");
|
|
354
354
|
}
|
|
355
355
|
const client = makeClient(args);
|
|
356
356
|
try {
|
|
357
357
|
await client.deleteArtifact(idOrSlug);
|
|
358
|
-
printJson({
|
|
358
|
+
printJson({ template: idOrSlug, deleted: true });
|
|
359
359
|
}
|
|
360
360
|
catch (e) {
|
|
361
361
|
failFromError(e);
|
|
@@ -386,9 +386,9 @@ export async function runArtifact(args) {
|
|
|
386
386
|
await runArtifactDelete(args);
|
|
387
387
|
break;
|
|
388
388
|
case undefined:
|
|
389
|
-
fail("missing subcommand — usage: pane
|
|
389
|
+
fail("missing subcommand — usage: pane template <create|version|update|search|list|show|delete> (run 'pane template --help')", "invalid_args");
|
|
390
390
|
break;
|
|
391
391
|
default:
|
|
392
|
-
fail(`unknown
|
|
392
|
+
fail(`unknown template subcommand '${sub}' — expected create|version|update|search|list|show|delete (run 'pane template --help')`, "invalid_args");
|
|
393
393
|
}
|
|
394
394
|
}
|
package/dist/commands/watch.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `pane
|
|
1
|
+
// `pane surface watch <id>` — long-lived: hold a WebSocket and stream events as
|
|
2
2
|
// JSON-lines on stdout. This harness-agnostic stdout is the core contract:
|
|
3
3
|
// one compact JSON object per line, flushed after every event, so any
|
|
4
4
|
// pipe-reader (Claude Code's Monitor tool, `while read line`, jq -c, ...)
|
|
@@ -11,14 +11,14 @@ import { printJsonLine, fail } from "../output.js";
|
|
|
11
11
|
import { VERSION } from "../version.js";
|
|
12
12
|
const KNOWN_FLAGS = ["since", "type", "filter-type", "timeout"];
|
|
13
13
|
const KNOWN_BOOLS = ["once"];
|
|
14
|
-
export const watchHelp = `pane
|
|
14
|
+
export const watchHelp = `pane surface watch — stream a surface's events as JSON-lines
|
|
15
15
|
|
|
16
16
|
Usage:
|
|
17
|
-
pane
|
|
17
|
+
pane surface watch <surface-id> [options]
|
|
18
18
|
|
|
19
|
-
Holds a WebSocket to WS /v1/
|
|
19
|
+
Holds a WebSocket to WS /v1/surfaces/:id/stream. Prints ONE compact JSON
|
|
20
20
|
object per line to stdout, flushing after each — designed to be piped into a
|
|
21
|
-
line-reader. On
|
|
21
|
+
line-reader. On surface close, prints a final {"type":"_closed"} line and
|
|
22
22
|
exits 0.
|
|
23
23
|
|
|
24
24
|
Modes:
|
|
@@ -34,7 +34,7 @@ Options:
|
|
|
34
34
|
--filter-type <t[,t2,…]>
|
|
35
35
|
Print only events whose type is in this set.
|
|
36
36
|
system.* events (lifecycle: participant.joined,
|
|
37
|
-
|
|
37
|
+
surface.expired, …) and the terminal {"type":
|
|
38
38
|
"_closed"} line always pass through, so the
|
|
39
39
|
harness still sees them. Combine with --type X
|
|
40
40
|
--filter-type X for "stream only X events and
|
|
@@ -42,7 +42,7 @@ Options:
|
|
|
42
42
|
--type alone that agents often expect.
|
|
43
43
|
--since <cursor> Replay only events after this opaque cursor.
|
|
44
44
|
--timeout <secs> Wall-clock max wait. Fail with code ws_timeout if
|
|
45
|
-
the natural exit condition (--once, --type,
|
|
45
|
+
the natural exit condition (--once, --type, surface
|
|
46
46
|
close) doesn't happen within this many seconds.
|
|
47
47
|
Frames arriving DO NOT reset the timer — this is
|
|
48
48
|
the budget for "give up on the human", not an idle
|
|
@@ -52,17 +52,17 @@ Options:
|
|
|
52
52
|
--api-key <key> Agent API key (overrides PANE_API_KEY).
|
|
53
53
|
-h, --help Show this help.
|
|
54
54
|
|
|
55
|
-
Each line is one event envelope: { id,
|
|
55
|
+
Each line is one event envelope: { id, surface_id, author, ts, type, data,
|
|
56
56
|
causation_id, idempotency_key }. The terminal line is {"type":"_closed"}.
|
|
57
57
|
|
|
58
|
-
Pattern — Claude Code Monitor tool: run \`pane
|
|
58
|
+
Pattern — Claude Code Monitor tool: run \`pane surface watch <id> --type form.submitted\`
|
|
59
59
|
as a monitored process; the harness re-invokes the model when the line lands.
|
|
60
60
|
|
|
61
61
|
Wait for any of several events:
|
|
62
|
-
pane
|
|
62
|
+
pane surface watch <id> --type form.submitted,form.cancelled --timeout 60
|
|
63
63
|
|
|
64
64
|
Stream only matching events to stdout, exit on the first:
|
|
65
|
-
pane
|
|
65
|
+
pane surface watch <id> --type form.submitted --filter-type form.submitted`;
|
|
66
66
|
// Parse a comma-separated event-type list (e.g. "form.submitted,form.cancelled")
|
|
67
67
|
// into a Set. Empty/whitespace entries are dropped. Returns null when the flag
|
|
68
68
|
// wasn't given (so callers can distinguish "no filter" from "empty filter").
|
|
@@ -91,10 +91,10 @@ export function shouldPrintEvent(eventType, filterTypes) {
|
|
|
91
91
|
return filterTypes.has(eventType);
|
|
92
92
|
}
|
|
93
93
|
export async function runWatch(args) {
|
|
94
|
-
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane
|
|
95
|
-
const
|
|
96
|
-
if (!
|
|
97
|
-
fail("missing <
|
|
94
|
+
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane surface watch");
|
|
95
|
+
const surfaceId = args.positionals[0];
|
|
96
|
+
if (!surfaceId)
|
|
97
|
+
fail("missing <surface-id>", "invalid_args");
|
|
98
98
|
const cfg = resolveConfig(args);
|
|
99
99
|
const since = args.flags.get("since") ?? null;
|
|
100
100
|
// --type controls the EXIT condition (set of types that trigger exit 0
|
|
@@ -135,7 +135,7 @@ export async function runWatch(args) {
|
|
|
135
135
|
}
|
|
136
136
|
finish(0);
|
|
137
137
|
};
|
|
138
|
-
// Track whether the relay told us the
|
|
138
|
+
// Track whether the relay told us the surface expired before the socket
|
|
139
139
|
// closed — a 1006/1008/1011 close after that is still a clean shutdown.
|
|
140
140
|
let sawSessionExpired = false;
|
|
141
141
|
// Wall-clock timeout. The reporter's mental model (#137) and the skill
|
|
@@ -145,7 +145,7 @@ export async function runWatch(args) {
|
|
|
145
145
|
// useless once any frame arrived, even a system.participant.joined
|
|
146
146
|
// emitted the moment a human connected. Frames now DO NOT reset the
|
|
147
147
|
// timer; the only ways `--timeout` doesn't fire are the natural exit
|
|
148
|
-
// conditions (--once, --type match,
|
|
148
|
+
// conditions (--once, --type match, surface close) finishing first.
|
|
149
149
|
let timer;
|
|
150
150
|
if (timeoutSec !== null) {
|
|
151
151
|
timer = setTimeout(() => {
|
|
@@ -154,7 +154,7 @@ export async function runWatch(args) {
|
|
|
154
154
|
}
|
|
155
155
|
const handle = openStream({
|
|
156
156
|
wsBaseUrl: client.wsBaseUrl,
|
|
157
|
-
|
|
157
|
+
surfaceId: surfaceId,
|
|
158
158
|
token: cfg.apiKey,
|
|
159
159
|
since,
|
|
160
160
|
}, {
|
|
@@ -167,8 +167,8 @@ export async function runWatch(args) {
|
|
|
167
167
|
if (shouldPrintEvent(event.type, filterTypes)) {
|
|
168
168
|
printJsonLine(event);
|
|
169
169
|
}
|
|
170
|
-
// A system.
|
|
171
|
-
if (event.type === "system.
|
|
170
|
+
// A system.surface.expired event means the surface is closing.
|
|
171
|
+
if (event.type === "system.surface.expired") {
|
|
172
172
|
sawSessionExpired = true;
|
|
173
173
|
emitClosed();
|
|
174
174
|
return;
|
|
@@ -184,8 +184,8 @@ export async function runWatch(args) {
|
|
|
184
184
|
onClose: ({ code, reason }) => {
|
|
185
185
|
// A clean close is 1000 (normal) or 1001 (going away). Any other code
|
|
186
186
|
// — 1006 abnormal, 1008 policy/auth, 1011 server error — is a failure
|
|
187
|
-
// UNLESS we already saw system.
|
|
188
|
-
// closed us on purpose after a clean
|
|
187
|
+
// UNLESS we already saw system.surface.expired, which means the relay
|
|
188
|
+
// closed us on purpose after a clean surface end.
|
|
189
189
|
if (code === 1000 || code === 1001 || sawSessionExpired) {
|
|
190
190
|
emitClosed();
|
|
191
191
|
return;
|
package/dist/index.js
CHANGED
|
@@ -23,14 +23,14 @@ function failArgvError(e) {
|
|
|
23
23
|
process.stderr.write(JSON.stringify({ error }) + "\n");
|
|
24
24
|
process.exit(1);
|
|
25
25
|
}
|
|
26
|
-
import { runSession, sessionHelp } from "./commands/
|
|
27
|
-
import { runArtifact, artifactHelp } from "./commands/
|
|
26
|
+
import { runSession, sessionHelp } from "./commands/surface.js";
|
|
27
|
+
import { runArtifact, artifactHelp } from "./commands/template.js";
|
|
28
28
|
import { runAgent, agentHelp } from "./commands/agent.js";
|
|
29
29
|
import { runKey, keyHelp } from "./commands/key.js";
|
|
30
30
|
import { runTaste, tasteHelp } from "./commands/taste.js";
|
|
31
31
|
import { runFeedback, feedbackHelp } from "./commands/feedback.js";
|
|
32
32
|
import { runConfig, configHelp } from "./commands/config.js";
|
|
33
|
-
import { runBlob, blobHelp } from "./commands/
|
|
33
|
+
import { runBlob, blobHelp } from "./commands/attachment.js";
|
|
34
34
|
import { runSkill, skillHelp } from "./commands/skill.js";
|
|
35
35
|
import { VERSION } from "./version.js";
|
|
36
36
|
import { PaneApiError } from "@paneui/core";
|
|
@@ -41,23 +41,23 @@ Usage:
|
|
|
41
41
|
pane <noun> <verb> [options]
|
|
42
42
|
|
|
43
43
|
Nouns:
|
|
44
|
-
|
|
44
|
+
surface Open / observe / send to / close surfaces
|
|
45
45
|
(create | list | show | send | watch | delete |
|
|
46
46
|
participant <list|new|revoke>).
|
|
47
|
-
|
|
47
|
+
template Reusable, versioned UI templates
|
|
48
48
|
(create | version | update | search | list | show | delete).
|
|
49
49
|
key YOUR agent's API key (list | revoke).
|
|
50
50
|
taste YOUR agent's freeform UI taste notes
|
|
51
51
|
(get | set | clear) — presentation preferences the agent
|
|
52
52
|
has learned from human feedback and reads before
|
|
53
|
-
generating a pane
|
|
53
|
+
generating a pane template.
|
|
54
54
|
feedback One-shot feedback to the relay operator
|
|
55
55
|
(create | list) — bug reports, feature requests, notes.
|
|
56
|
-
|
|
56
|
+
attachment Binary attachments (upload | download | show | list |
|
|
57
57
|
delete | token <mint|revoke|list>). Blobs are scoped to
|
|
58
|
-
an agent, a
|
|
58
|
+
an agent, a surface, or an template, and can be referenced
|
|
59
59
|
from event payloads + input_data via
|
|
60
|
-
\`format: pane-
|
|
60
|
+
\`format: pane-attachment-id\`.
|
|
61
61
|
agent Agent identity on this machine (register | logout).
|
|
62
62
|
config CLI config inspection (show).
|
|
63
63
|
skill The relay's SKILL.md (show | version) — auto-updating;
|
|
@@ -85,8 +85,8 @@ Output: stdout is machine-readable JSON; errors go to stderr as
|
|
|
85
85
|
//
|
|
86
86
|
// `version` is deliberately NOT here: the top-level `-v` / `--version` is
|
|
87
87
|
// handled from rawArgv[0] before parseArgs runs, so it never needs to be a
|
|
88
|
-
// boolean flag — and keeping it out lets `pane
|
|
89
|
-
// `pane
|
|
88
|
+
// boolean flag — and keeping it out lets `pane surface create --version <n>` /
|
|
89
|
+
// `pane template version` consume a value as a normal value-flag.
|
|
90
90
|
const BOOLEAN_FLAGS = new Set([
|
|
91
91
|
"json",
|
|
92
92
|
"once",
|
|
@@ -122,12 +122,12 @@ async function main() {
|
|
|
122
122
|
throw e;
|
|
123
123
|
}
|
|
124
124
|
const helps = {
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
surface: sessionHelp,
|
|
126
|
+
template: artifactHelp,
|
|
127
127
|
key: keyHelp,
|
|
128
128
|
taste: tasteHelp,
|
|
129
129
|
feedback: feedbackHelp,
|
|
130
|
-
|
|
130
|
+
attachment: blobHelp,
|
|
131
131
|
agent: agentHelp,
|
|
132
132
|
config: configHelp,
|
|
133
133
|
skill: skillHelp,
|
|
@@ -150,10 +150,10 @@ async function main() {
|
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
152
|
switch (noun) {
|
|
153
|
-
case "
|
|
153
|
+
case "surface":
|
|
154
154
|
await runSession(args);
|
|
155
155
|
break;
|
|
156
|
-
case "
|
|
156
|
+
case "template":
|
|
157
157
|
await runArtifact(args);
|
|
158
158
|
break;
|
|
159
159
|
case "key":
|
|
@@ -165,7 +165,7 @@ async function main() {
|
|
|
165
165
|
case "feedback":
|
|
166
166
|
await runFeedback(args);
|
|
167
167
|
break;
|
|
168
|
-
case "
|
|
168
|
+
case "attachment":
|
|
169
169
|
await runBlob(args);
|
|
170
170
|
break;
|
|
171
171
|
case "agent":
|
package/dist/input.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Helpers for reading CLI inputs that may be either a file path or an inline
|
|
2
|
-
// literal (JSON, or raw text for an HTML
|
|
2
|
+
// literal (JSON, or raw text for an HTML template body).
|
|
3
3
|
import { readFileSync, statSync } from "node:fs";
|
|
4
4
|
/**
|
|
5
5
|
* True if `value` names an existing file. Only a missing path (ENOENT) is
|
|
@@ -35,7 +35,7 @@ export function resolveJson(value, label) {
|
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Resolve raw text that is either a file path or an inline literal — no JSON
|
|
38
|
-
* parsing. Used for an inline HTML
|
|
38
|
+
* parsing. Used for an inline HTML template body.
|
|
39
39
|
*/
|
|
40
40
|
export function resolveText(value) {
|
|
41
41
|
return isFilePath(value) ? readFileSync(value, "utf8") : value;
|
package/dist/output.js
CHANGED
|
@@ -8,7 +8,7 @@ export function printJson(value) {
|
|
|
8
8
|
process.stdout.write(JSON.stringify(value, null, 2) + "\n");
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* Print a single compact JSON line to stdout and flush. Used by `pane
|
|
11
|
+
* Print a single compact JSON line to stdout and flush. Used by `pane surface watch`
|
|
12
12
|
* so a pipe-reader (e.g. Claude Code's Monitor tool) sees each event
|
|
13
13
|
* immediately, one event per line.
|
|
14
14
|
*/
|
package/dist/version.js
CHANGED
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
// Keep this in lockstep with packages/cli/package.json's `version` field;
|
|
9
9
|
// they're consulted in different places (here for the runtime header,
|
|
10
10
|
// package.json for npm publish + dependency resolution).
|
|
11
|
-
export const VERSION = "0.0.
|
|
11
|
+
export const VERSION = "0.0.8";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paneui/cli",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Command-line client for the Pane relay: create
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"description": "Command-line client for the Pane relay: create surfaces, inspect state, send and watch events.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"test:unit": "vitest run"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@paneui/core": "^0.0.
|
|
44
|
+
"@paneui/core": "^0.0.8"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^25.9.1",
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// `pane blob delete <blob-id>` — soft-delete a blob.
|
|
2
|
-
import { assertKnownFlags } from "../argv.js";
|
|
3
|
-
import { makeClient } from "../config.js";
|
|
4
|
-
import { fail, failFromError, printJson } from "../output.js";
|
|
5
|
-
const KNOWN_FLAGS = [];
|
|
6
|
-
const KNOWN_BOOLS = [];
|
|
7
|
-
export const blobDeleteHelp = `pane blob delete — soft-delete a blob
|
|
8
|
-
|
|
9
|
-
Usage:
|
|
10
|
-
pane blob delete <blob-id> [options]
|
|
11
|
-
|
|
12
|
-
Marks the blob as deleted (DELETE /v1/blobs/:id). Idempotent: deleting an
|
|
13
|
-
already-deleted blob still returns success. Tokens minted against this blob
|
|
14
|
-
become unusable.
|
|
15
|
-
|
|
16
|
-
Options:
|
|
17
|
-
--url <url> Relay base URL (overrides PANE_URL).
|
|
18
|
-
--api-key <key> Agent API key (overrides PANE_API_KEY).
|
|
19
|
-
-h, --help Show this help.
|
|
20
|
-
|
|
21
|
-
Output (stdout, JSON):
|
|
22
|
-
{ blob_id, deleted: true }`;
|
|
23
|
-
export async function runBlobDelete(args) {
|
|
24
|
-
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane blob delete");
|
|
25
|
-
const blobId = args.positionals[0];
|
|
26
|
-
if (!blobId) {
|
|
27
|
-
fail("missing <blob-id> — 'pane blob delete <blob-id>'", "invalid_args");
|
|
28
|
-
}
|
|
29
|
-
const client = makeClient(args);
|
|
30
|
-
try {
|
|
31
|
-
const r = await client.deleteBlob(blobId);
|
|
32
|
-
printJson({ blob_id: blobId, ...r });
|
|
33
|
-
}
|
|
34
|
-
catch (e) {
|
|
35
|
-
failFromError(e);
|
|
36
|
-
}
|
|
37
|
-
}
|