@paneui/cli 0.0.9 → 0.0.11
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 +8 -8
- package/dist/argv.js +3 -3
- package/dist/commands/agent.js +10 -2
- package/dist/commands/attachment-token.js +2 -2
- package/dist/commands/attachment-upload.js +8 -10
- package/dist/commands/attachment.js +7 -7
- package/dist/commands/claim.js +1 -1
- package/dist/commands/config.js +232 -20
- package/dist/commands/create.js +132 -21
- package/dist/commands/delete.js +12 -12
- package/dist/commands/feedback.js +5 -5
- package/dist/commands/list.js +17 -17
- package/dist/commands/logout.js +43 -13
- package/dist/commands/participant.js +38 -38
- package/dist/commands/query.js +204 -0
- package/dist/commands/records.js +285 -0
- package/dist/commands/register.js +53 -15
- package/dist/commands/send.js +17 -17
- package/dist/commands/set-key.js +92 -0
- package/dist/commands/skill.js +1 -1
- package/dist/commands/state.js +12 -12
- package/dist/commands/taste.js +3 -3
- package/dist/commands/template-records.js +195 -0
- package/dist/commands/template.js +243 -35
- package/dist/commands/trash.js +102 -0
- package/dist/commands/watch.js +22 -22
- package/dist/config.js +87 -20
- package/dist/format.js +133 -0
- package/dist/index.js +97 -20
- package/dist/output.js +1 -1
- package/dist/store.js +167 -26
- package/dist/upgrade.js +1 -1
- package/dist/version.js +2 -2
- package/package.json +5 -3
- package/dist/commands/surface.js +0 -118
package/dist/commands/create.js
CHANGED
|
@@ -1,27 +1,37 @@
|
|
|
1
|
-
// `pane
|
|
2
|
-
import {
|
|
1
|
+
// `pane create` — create a pane via POST /v1/panes.
|
|
2
|
+
import { createPaneSchema } from "@paneui/core";
|
|
3
3
|
import { assertKnownFlags } from "../argv.js";
|
|
4
4
|
import { makeClient } from "../config.js";
|
|
5
5
|
import { resolveJson, resolveText } from "../input.js";
|
|
6
6
|
import { printJson, fail, failFromError } from "../output.js";
|
|
7
|
+
import { formatPaneCreated } from "../format.js";
|
|
7
8
|
const KNOWN_FLAGS = [
|
|
8
9
|
"template",
|
|
9
10
|
"template-id",
|
|
10
11
|
"template-type",
|
|
12
|
+
"name",
|
|
13
|
+
"slug",
|
|
11
14
|
"version",
|
|
12
15
|
"event-schema",
|
|
13
16
|
"input-schema",
|
|
14
17
|
"title",
|
|
18
|
+
"preamble",
|
|
15
19
|
"input-data",
|
|
16
20
|
"ttl",
|
|
17
21
|
"participants",
|
|
18
22
|
"metadata",
|
|
19
23
|
"callback",
|
|
24
|
+
"context-key",
|
|
25
|
+
"icon-emoji",
|
|
26
|
+
"icon-attachment-id",
|
|
20
27
|
];
|
|
21
|
-
|
|
28
|
+
// `--json` forces machine-readable output even on a TTY. Without it, an
|
|
29
|
+
// interactive terminal gets the human-readable form (title + URLs + QR +
|
|
30
|
+
// countdown); pipes and `--json` callers still get the legacy JSON shape.
|
|
31
|
+
const KNOWN_BOOLS = ["json"];
|
|
22
32
|
// Translate a Zod schema path (e.g. ["participants","humans"]) back to the
|
|
23
33
|
// public CLI flag the user actually typed. Without this, a `--participants 0`
|
|
24
|
-
// rejection
|
|
34
|
+
// rejection panes as `participants.humans: ...` — which leaks the wire
|
|
25
35
|
// shape and refers to no flag the user could fix.
|
|
26
36
|
//
|
|
27
37
|
// Match strategy: longest prefix wins. Schema paths whose top segment isn't
|
|
@@ -37,9 +47,15 @@ const SCHEMA_PATH_TO_FLAG = {
|
|
|
37
47
|
callback: "--callback",
|
|
38
48
|
input_data: "--input-data",
|
|
39
49
|
title: "--title",
|
|
50
|
+
preamble: "--preamble",
|
|
51
|
+
context_key: "--context-key",
|
|
52
|
+
icon_emoji: "--icon-emoji",
|
|
53
|
+
icon_attachment_id: "--icon-attachment-id",
|
|
40
54
|
"template.id": "--template-id",
|
|
41
55
|
"template.version": "--version",
|
|
42
56
|
"template.type": "--template-type",
|
|
57
|
+
"template.name": "--name",
|
|
58
|
+
"template.slug": "--slug",
|
|
43
59
|
"template.source": "--template",
|
|
44
60
|
"template.event_schema": "--event-schema",
|
|
45
61
|
"template.input_schema": "--input-schema",
|
|
@@ -57,16 +73,16 @@ function schemaPathToFlag(path) {
|
|
|
57
73
|
}
|
|
58
74
|
return dotted;
|
|
59
75
|
}
|
|
60
|
-
export const createHelp = `pane
|
|
76
|
+
export const createHelp = `pane create — create a Pane pane
|
|
61
77
|
|
|
62
|
-
A
|
|
78
|
+
A pane is one use of an template. Supply the template in ONE of two ways:
|
|
63
79
|
|
|
64
80
|
Reference form — instance an existing reusable template (the cheap path,
|
|
65
81
|
no HTML re-sent):
|
|
66
|
-
pane
|
|
82
|
+
pane create --template-id <id|slug> [--version <n>] [--input-data <v>]
|
|
67
83
|
|
|
68
84
|
Inline form — a one-off template, defined on this call:
|
|
69
|
-
pane
|
|
85
|
+
pane create --template <path|inline> [--event-schema <path|json>] [options]
|
|
70
86
|
|
|
71
87
|
Exactly one of --template-id / --template must be given.
|
|
72
88
|
|
|
@@ -79,6 +95,14 @@ Template (choose one):
|
|
|
79
95
|
the template's latest version.
|
|
80
96
|
--template <v> Inline HTML template. Either a file path / URL, or inline
|
|
81
97
|
HTML. Combine with --template-type to control reading.
|
|
98
|
+
--name <text> Inline-form template name. REQUIRED with --template so
|
|
99
|
+
the auto-created template carries a readable label in the
|
|
100
|
+
owner-shell UI (and so --title can fall back to it).
|
|
101
|
+
Rejected with --template-id (the reference form inherits
|
|
102
|
+
the existing template's name).
|
|
103
|
+
--slug <text> Inline-form template slug (optional). Must be unique among
|
|
104
|
+
your templates; a collision is rejected. Rejected with
|
|
105
|
+
--template-id.
|
|
82
106
|
--event-schema <v> Inline-form event schema. A .json file, or inline JSON.
|
|
83
107
|
Optional with --template. Omit for a view-only template
|
|
84
108
|
(a report/dashboard the human only views — no page/agent
|
|
@@ -105,7 +129,7 @@ Template (choose one):
|
|
|
105
129
|
--input-schema <v> Inline-form input schema. A .json file, or inline JSON.
|
|
106
130
|
Optional with --template, rejected with --template-id
|
|
107
131
|
(the schema comes from the pinned template version
|
|
108
|
-
there). When present, the
|
|
132
|
+
there). When present, the pane's --input-data is
|
|
109
133
|
validated against it AND any attachment ids declared at a
|
|
110
134
|
"format": "pane-attachment-id" site become reachable from the
|
|
111
135
|
page via window.pane.downloadBlob. Without it, attachment
|
|
@@ -114,10 +138,16 @@ Template (choose one):
|
|
|
114
138
|
|
|
115
139
|
Options:
|
|
116
140
|
--title <text> Tab title shown to the human (max 80 chars, single
|
|
117
|
-
line).
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
141
|
+
line). Optional: when omitted, the relay falls back to
|
|
142
|
+
the template's name — the existing Template.name for the
|
|
143
|
+
reference form, or the --name you pass for the inline
|
|
144
|
+
form.
|
|
145
|
+
--preamble <text> Optional one- or two-line context message rendered in
|
|
146
|
+
the shell band above the iframe — "who is asking, why".
|
|
147
|
+
Max 280 chars after trim; a single \\n is allowed for a
|
|
148
|
+
two-line message; other control chars are rejected. Pass
|
|
149
|
+
this whenever the artifact itself doesn't make the
|
|
150
|
+
request self-explanatory.
|
|
121
151
|
--input-data <v> This instance's seed data — a JSON object (file path or
|
|
122
152
|
inline JSON), validated by the relay against the template
|
|
123
153
|
version's input_schema. The page reads it as
|
|
@@ -125,24 +155,43 @@ Options:
|
|
|
125
155
|
--template-type <t> "html-inline" (default) or "html-ref". With "html-ref"
|
|
126
156
|
the --template value is treated as a URL. Note: the relay
|
|
127
157
|
does not serve "html-ref" templates in this release and
|
|
128
|
-
will reject the
|
|
129
|
-
--ttl <seconds>
|
|
158
|
+
will reject the pane — use "html-inline".
|
|
159
|
+
--ttl <seconds> Pane time-to-live in seconds. The relay clamps this
|
|
130
160
|
to its configured MAX_TTL_SECONDS (defaults: 1 h
|
|
131
161
|
requested, 24 h max for self-host; hosted may differ).
|
|
132
162
|
The returned \`expires_at\` is the authoritative value.
|
|
133
163
|
--participants <n> Number of human participants (default 1).
|
|
134
164
|
--metadata <path|json> Arbitrary metadata object (file path or inline JSON).
|
|
135
165
|
--callback <path|json> Webhook callback config: { url, events[], secret }.
|
|
166
|
+
--context-key <key> Natural key for "the same logical thing" — the relay
|
|
167
|
+
dedups repeated creates with the same
|
|
168
|
+
(template, owner, context_key) into one pane row,
|
|
169
|
+
returning {created:false, pane_id:<existing>} on
|
|
170
|
+
subsequent calls. Use this to make scripted creates
|
|
171
|
+
idempotent (e.g. "pr-42", "deal-1138", "home"). Only
|
|
172
|
+
meaningful when the calling agent is claimed by a
|
|
173
|
+
human; omit otherwise. Allowed chars: A-Za-z0-9_:.-,
|
|
174
|
+
max 256.
|
|
175
|
+
--icon-emoji <e> Per-pane icon override — a single emoji grapheme. NULL/
|
|
176
|
+
omitted = inherit the template's icon.
|
|
177
|
+
--icon-attachment-id <id>
|
|
178
|
+
Per-pane icon override — a ready raster-image attachment
|
|
179
|
+
(png/jpeg/webp/gif) accessible to this agent. No SVG, no
|
|
180
|
+
URLs. Omitted = inherit the template's icon.
|
|
136
181
|
--url <url> Relay base URL (overrides PANE_URL).
|
|
137
182
|
--api-key <key> Agent API key (overrides PANE_API_KEY).
|
|
183
|
+
--json Force JSON output even on a TTY. Default: JSON when
|
|
184
|
+
stdout is piped; a human-readable summary (title, URL,
|
|
185
|
+
QR code, expiry countdown) when stdout is a terminal.
|
|
138
186
|
-h, --help Show this help.
|
|
139
187
|
|
|
140
|
-
Output
|
|
141
|
-
{
|
|
188
|
+
Output:
|
|
189
|
+
- Piped (or --json): { pane_id, urls, tokens, expires_at } as JSON
|
|
190
|
+
- TTY: title + each human URL + a scannable QR code + expiry countdown
|
|
142
191
|
|
|
143
192
|
Deliver urls.humans to the human(s); keep tokens.agent for the WS stream.`;
|
|
144
193
|
export async function runCreate(args) {
|
|
145
|
-
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane
|
|
194
|
+
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane create");
|
|
146
195
|
const artifactIdVal = args.flags.get("template-id");
|
|
147
196
|
const artifactVal = args.flags.get("template");
|
|
148
197
|
// Exactly one of the two template forms must be present.
|
|
@@ -164,6 +213,15 @@ export async function runCreate(args) {
|
|
|
164
213
|
if (args.flags.get("input-schema") !== undefined) {
|
|
165
214
|
fail("--input-schema is incompatible with --template-id — the input schema comes from the pinned template version. Author the schema on the template (`pane template create --input-schema …`) instead.", "invalid_args");
|
|
166
215
|
}
|
|
216
|
+
// --name / --slug name the inline form's auto-created template. The
|
|
217
|
+
// reference form inherits the existing Template.name/slug, so they have
|
|
218
|
+
// no meaning here — reject rather than silently ignore.
|
|
219
|
+
if (args.flags.get("name") !== undefined) {
|
|
220
|
+
fail("--name is incompatible with --template-id — the reference form inherits the existing template's name. Use --name only with --template (inline form).", "invalid_args");
|
|
221
|
+
}
|
|
222
|
+
if (args.flags.get("slug") !== undefined) {
|
|
223
|
+
fail("--slug is incompatible with --template-id — the reference form inherits the existing template's slug. Use --slug only with --template (inline form).", "invalid_args");
|
|
224
|
+
}
|
|
167
225
|
const ref = { id: artifactIdVal };
|
|
168
226
|
const versionRaw = args.flags.get("version");
|
|
169
227
|
if (versionRaw !== undefined) {
|
|
@@ -201,14 +259,28 @@ export async function runCreate(args) {
|
|
|
201
259
|
catch (e) {
|
|
202
260
|
fail(e instanceof Error ? e.message : String(e), "invalid_args");
|
|
203
261
|
}
|
|
262
|
+
// --name is REQUIRED for the inline form: the relay names the
|
|
263
|
+
// auto-created template with it so the owner-shell UI has a readable
|
|
264
|
+
// label (the reference form inherits the existing Template.name instead).
|
|
265
|
+
// --slug is optional. Both are inline-only — they are rejected with
|
|
266
|
+
// --template-id below.
|
|
267
|
+
const nameVal = args.flags.get("name");
|
|
268
|
+
if (nameVal === undefined || nameVal === "") {
|
|
269
|
+
fail("--name is required with --template (inline form); it names the auto-created template so the UI shows a readable label", "invalid_args");
|
|
270
|
+
}
|
|
271
|
+
const slugVal = args.flags.get("slug");
|
|
204
272
|
// Build the inline template object. event_schema / input_schema are
|
|
205
273
|
// OMITTED entirely (not set to undefined) when their flags are absent —
|
|
206
274
|
// omission is meaningful at the relay (view-only template / no input
|
|
207
275
|
// contract).
|
|
208
276
|
const inlineArtifact = {
|
|
277
|
+
name: nameVal,
|
|
209
278
|
type: templateType,
|
|
210
279
|
source,
|
|
211
280
|
};
|
|
281
|
+
if (slugVal !== undefined) {
|
|
282
|
+
inlineArtifact["slug"] = slugVal;
|
|
283
|
+
}
|
|
212
284
|
if (schemaVal !== undefined) {
|
|
213
285
|
try {
|
|
214
286
|
inlineArtifact["event_schema"] = resolveJson(schemaVal, "--event-schema");
|
|
@@ -240,6 +312,13 @@ export async function runCreate(args) {
|
|
|
240
312
|
if (titleRaw !== undefined) {
|
|
241
313
|
candidate["title"] = titleRaw;
|
|
242
314
|
}
|
|
315
|
+
// --preamble — passthrough. The relay trims, normalises CRLF, enforces
|
|
316
|
+
// ≤280 chars and rejects non-newline control chars; mirroring those
|
|
317
|
+
// checks here would just create drift on edge cases.
|
|
318
|
+
const preambleRaw = args.flags.get("preamble");
|
|
319
|
+
if (preambleRaw !== undefined) {
|
|
320
|
+
candidate["preamble"] = preambleRaw;
|
|
321
|
+
}
|
|
243
322
|
// --input-data — per-instance seed data, applies to either form (the relay
|
|
244
323
|
// validates it against the pinned version's input_schema).
|
|
245
324
|
const inputDataRaw = args.flags.get("input-data");
|
|
@@ -283,7 +362,26 @@ export async function runCreate(args) {
|
|
|
283
362
|
fail(e instanceof Error ? e.message : String(e), "invalid_args");
|
|
284
363
|
}
|
|
285
364
|
}
|
|
286
|
-
|
|
365
|
+
// --context-key — natural-key dedup. Passthrough; the relay enforces
|
|
366
|
+
// length + charset (createPaneSchema in @paneui/core), so an invalid
|
|
367
|
+
// value panes as a schema rejection on the call below rather than
|
|
368
|
+
// a duplicated client-side guard that could drift.
|
|
369
|
+
const contextKey = args.flags.get("context-key");
|
|
370
|
+
if (contextKey !== undefined) {
|
|
371
|
+
candidate["context_key"] = contextKey;
|
|
372
|
+
}
|
|
373
|
+
// Per-pane icon override. Passthrough — the relay validates the emoji
|
|
374
|
+
// (single grapheme) and the attachment (ready raster image, accessible to
|
|
375
|
+
// the agent), so a bad value panes as a schema/route rejection rather than
|
|
376
|
+
// a duplicated client guard.
|
|
377
|
+
const iconEmoji = args.flags.get("icon-emoji");
|
|
378
|
+
if (iconEmoji !== undefined)
|
|
379
|
+
candidate["icon_emoji"] = iconEmoji;
|
|
380
|
+
const iconAttachmentId = args.flags.get("icon-attachment-id");
|
|
381
|
+
if (iconAttachmentId !== undefined) {
|
|
382
|
+
candidate["icon_attachment_id"] = iconAttachmentId;
|
|
383
|
+
}
|
|
384
|
+
const parsed = createPaneSchema.safeParse(candidate);
|
|
287
385
|
if (!parsed.success) {
|
|
288
386
|
const issue = parsed.error.issues[0];
|
|
289
387
|
const where = issue && issue.path.length > 0 ? schemaPathToFlag(issue.path) : "request";
|
|
@@ -292,8 +390,21 @@ export async function runCreate(args) {
|
|
|
292
390
|
const req = parsed.data;
|
|
293
391
|
const client = makeClient(args);
|
|
294
392
|
try {
|
|
295
|
-
const res = await client.
|
|
296
|
-
|
|
393
|
+
const res = await client.createPane(req);
|
|
394
|
+
// Output mode:
|
|
395
|
+
// --json explicit → JSON
|
|
396
|
+
// stdout NOT a TTY (pipe) → JSON (so scripts / agents stay parseable)
|
|
397
|
+
// stdout IS a TTY → human-readable (URL + QR + countdown)
|
|
398
|
+
// The TTY check matches the existing `pane taste` / `pane feedback`
|
|
399
|
+
// pattern: agents are non-interactive, humans are.
|
|
400
|
+
const forceJson = args.bools.has("json");
|
|
401
|
+
const isTty = Boolean(process.stdout.isTTY);
|
|
402
|
+
if (forceJson || !isTty) {
|
|
403
|
+
printJson(res);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
process.stdout.write(formatPaneCreated(res, { color: isTty }));
|
|
407
|
+
}
|
|
297
408
|
}
|
|
298
409
|
catch (e) {
|
|
299
410
|
failFromError(e);
|
package/dist/commands/delete.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
// `pane
|
|
1
|
+
// `pane delete <id>` — close/delete a pane.
|
|
2
2
|
import { assertKnownFlags } from "../argv.js";
|
|
3
3
|
import { makeClient } from "../config.js";
|
|
4
4
|
import { printJson, fail, failFromError } from "../output.js";
|
|
5
5
|
const KNOWN_FLAGS = [];
|
|
6
6
|
const KNOWN_BOOLS = [];
|
|
7
|
-
export const deleteHelp = `pane
|
|
7
|
+
export const deleteHelp = `pane delete — close/delete a pane
|
|
8
8
|
|
|
9
9
|
Usage:
|
|
10
|
-
pane
|
|
10
|
+
pane delete <pane-id> [options]
|
|
11
11
|
|
|
12
|
-
Closes and deletes the
|
|
13
|
-
relay side — deleting an already-closed
|
|
12
|
+
Closes and deletes the pane (DELETE /v1/panes/:id). Idempotent on the
|
|
13
|
+
relay side — deleting an already-closed pane still succeeds.
|
|
14
14
|
|
|
15
15
|
Options:
|
|
16
16
|
--url <url> Relay base URL (overrides PANE_URL).
|
|
@@ -18,16 +18,16 @@ Options:
|
|
|
18
18
|
-h, --help Show this help.
|
|
19
19
|
|
|
20
20
|
Output (stdout, JSON):
|
|
21
|
-
{
|
|
21
|
+
{ pane_id, deleted: true }`;
|
|
22
22
|
export async function runDelete(args) {
|
|
23
|
-
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane
|
|
24
|
-
const
|
|
25
|
-
if (!
|
|
26
|
-
fail("missing <
|
|
23
|
+
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane delete");
|
|
24
|
+
const paneId = args.positionals[0];
|
|
25
|
+
if (!paneId)
|
|
26
|
+
fail("missing <pane-id>", "invalid_args");
|
|
27
27
|
const client = makeClient(args);
|
|
28
28
|
try {
|
|
29
|
-
await client.
|
|
30
|
-
printJson({
|
|
29
|
+
await client.deletePane(paneId);
|
|
30
|
+
printJson({ pane_id: paneId, deleted: true });
|
|
31
31
|
}
|
|
32
32
|
catch (e) {
|
|
33
33
|
failFromError(e);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assertKnownFlags } from "../argv.js";
|
|
2
2
|
import { makeClient } from "../config.js";
|
|
3
3
|
import { printJson, fail, failFromError } from "../output.js";
|
|
4
|
-
const CREATE_FLAGS = ["type", "message", "
|
|
4
|
+
const CREATE_FLAGS = ["type", "message", "pane-id"];
|
|
5
5
|
const LIST_FLAGS = ["limit", "before"];
|
|
6
6
|
const NO_BOOLS = [];
|
|
7
7
|
export const feedbackHelp = `pane feedback — submit / list feedback to the relay operator
|
|
@@ -25,7 +25,7 @@ Options for 'create':
|
|
|
25
25
|
--type <bug|feature|note> Feedback category. Required.
|
|
26
26
|
--message <text|-> Message body. Pass '-' to read from stdin.
|
|
27
27
|
1..4000 chars after trim.
|
|
28
|
-
--
|
|
28
|
+
--pane-id <id> Optional pane this feedback relates to;
|
|
29
29
|
must belong to YOUR agent.
|
|
30
30
|
|
|
31
31
|
Options for 'list':
|
|
@@ -38,7 +38,7 @@ Global:
|
|
|
38
38
|
-h, --help Show this help.
|
|
39
39
|
|
|
40
40
|
Examples:
|
|
41
|
-
pane feedback create --type bug --message "watch hangs on empty
|
|
41
|
+
pane feedback create --type bug --message "watch hangs on empty pane"
|
|
42
42
|
echo "long-form note..." | pane feedback create --type note --message -
|
|
43
43
|
pane feedback list --limit 20
|
|
44
44
|
|
|
@@ -55,7 +55,7 @@ async function runFeedbackCreate(args) {
|
|
|
55
55
|
assertKnownFlags(args, CREATE_FLAGS, NO_BOOLS, "pane feedback create");
|
|
56
56
|
const type = args.flags.get("type");
|
|
57
57
|
const rawMessage = args.flags.get("message");
|
|
58
|
-
const
|
|
58
|
+
const paneId = args.flags.get("pane-id");
|
|
59
59
|
if (type === undefined) {
|
|
60
60
|
fail("'pane feedback create' requires --type <bug|feature|note>", "invalid_args");
|
|
61
61
|
}
|
|
@@ -83,7 +83,7 @@ async function runFeedbackCreate(args) {
|
|
|
83
83
|
const res = await client.submitFeedback({
|
|
84
84
|
type: type,
|
|
85
85
|
message,
|
|
86
|
-
...(
|
|
86
|
+
...(paneId !== undefined ? { paneId } : {}),
|
|
87
87
|
});
|
|
88
88
|
printJson(res);
|
|
89
89
|
}
|
package/dist/commands/list.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
// `pane
|
|
1
|
+
// `pane list` — enumerate YOUR agent's panes.
|
|
2
2
|
//
|
|
3
3
|
// The recovery primitive when the create-response was dropped: the URL itself
|
|
4
4
|
// is unrecoverable (the relay stores only the token hash), but every other
|
|
5
|
-
// field of the
|
|
6
|
-
// `pane
|
|
5
|
+
// field of the pane is intact and listable here. Pair with
|
|
6
|
+
// `pane participant new` to mint a fresh URL on a pane whose
|
|
7
7
|
// original was lost.
|
|
8
8
|
import { assertKnownFlags } from "../argv.js";
|
|
9
9
|
import { makeClient } from "../config.js";
|
|
10
10
|
import { printJson, fail, failFromError } from "../output.js";
|
|
11
11
|
const KNOWN_FLAGS = ["status", "limit", "cursor", "template-id"];
|
|
12
12
|
const KNOWN_BOOLS = [];
|
|
13
|
-
export const listHelp = `pane
|
|
13
|
+
export const listHelp = `pane list — list YOUR agent's panes
|
|
14
14
|
|
|
15
|
-
Prints
|
|
16
|
-
tokens are stored hashed and CANNOT be recovered — if you lost a
|
|
17
|
-
mint a fresh one with 'pane
|
|
15
|
+
Prints panes (newest first) with no secrets in the response. Participant
|
|
16
|
+
tokens are stored hashed and CANNOT be recovered — if you lost a pane URL,
|
|
17
|
+
mint a fresh one with 'pane participant new <pane-id>'.
|
|
18
18
|
|
|
19
19
|
Usage:
|
|
20
|
-
pane
|
|
20
|
+
pane list [options]
|
|
21
21
|
|
|
22
22
|
Options:
|
|
23
23
|
--status <s> open | closed | all. Default: open. The status reported
|
|
@@ -25,7 +25,7 @@ Options:
|
|
|
25
25
|
is reported as 'closed' even if not yet swept.
|
|
26
26
|
--limit <N> Page size (default 50, max 200).
|
|
27
27
|
--cursor <c> Opaque cursor from a previous page's next_cursor.
|
|
28
|
-
--template-id <i> Filter to
|
|
28
|
+
--template-id <i> Filter to panes instantiated from a specific named
|
|
29
29
|
template (head id; not version id). Inline (anonymous)
|
|
30
30
|
templates cannot be filtered this way — they have no
|
|
31
31
|
stable handle.
|
|
@@ -33,20 +33,20 @@ Options:
|
|
|
33
33
|
--api-key <key> Agent API key (overrides PANE_API_KEY).
|
|
34
34
|
-h, --help Show this help.
|
|
35
35
|
|
|
36
|
-
Recovery recipe (lost the URL but the
|
|
37
|
-
pane
|
|
38
|
-
#
|
|
36
|
+
Recovery recipe (lost the URL but the pane is still alive):
|
|
37
|
+
pane list # find the
|
|
38
|
+
# pane_id +
|
|
39
39
|
# participant_id
|
|
40
40
|
# you lost
|
|
41
|
-
pane
|
|
42
|
-
pane
|
|
41
|
+
pane participant new <pane-id> # mint a fresh URL
|
|
42
|
+
pane participant revoke <pane-id> <p-id> # invalidate the
|
|
43
43
|
# old URL
|
|
44
44
|
|
|
45
45
|
Output (stdout, JSON):
|
|
46
46
|
{
|
|
47
47
|
items: [
|
|
48
48
|
{
|
|
49
|
-
|
|
49
|
+
pane_id, title, status, template_id, template_version_id,
|
|
50
50
|
template_version, participants: [...], created_at, expires_at,
|
|
51
51
|
has_callback
|
|
52
52
|
},
|
|
@@ -56,7 +56,7 @@ Output (stdout, JSON):
|
|
|
56
56
|
}`;
|
|
57
57
|
const STATUSES = ["open", "closed", "all"];
|
|
58
58
|
export async function runList(args) {
|
|
59
|
-
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane
|
|
59
|
+
assertKnownFlags(args, KNOWN_FLAGS, KNOWN_BOOLS, "pane list");
|
|
60
60
|
const opts = {};
|
|
61
61
|
const status = args.flags.get("status");
|
|
62
62
|
if (status !== undefined) {
|
|
@@ -82,7 +82,7 @@ export async function runList(args) {
|
|
|
82
82
|
}
|
|
83
83
|
const client = makeClient(args);
|
|
84
84
|
try {
|
|
85
|
-
const page = await client.
|
|
85
|
+
const page = await client.listPanes(opts);
|
|
86
86
|
printJson(page);
|
|
87
87
|
}
|
|
88
88
|
catch (e) {
|
package/dist/commands/logout.js
CHANGED
|
@@ -1,29 +1,59 @@
|
|
|
1
|
-
// `pane agent logout` — clear
|
|
1
|
+
// `pane agent logout` — clear one (or all) saved profile(s).
|
|
2
2
|
import { assertKnownFlags } from "../argv.js";
|
|
3
|
-
import { clearStore } from "../store.js";
|
|
4
|
-
import { printJson } from "../output.js";
|
|
3
|
+
import { clearStore, readStore, removeProfile, resolveProfile, } from "../store.js";
|
|
4
|
+
import { printJson, fail } from "../output.js";
|
|
5
5
|
const NO_FLAGS = [];
|
|
6
|
-
const
|
|
7
|
-
export const logoutHelp = `pane agent logout — clear
|
|
6
|
+
const KNOWN_BOOLS = ["all"];
|
|
7
|
+
export const logoutHelp = `pane agent logout — clear a saved profile (or all of them)
|
|
8
8
|
|
|
9
9
|
Usage:
|
|
10
10
|
pane agent logout [options]
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
By default this clears the ACTIVE profile only (the one selected by --profile
|
|
13
|
+
/ PANE_PROFILE / the store's current_profile). The on-disk file keeps the
|
|
14
|
+
other profiles, and 'current_profile' is unset so the next command falls back
|
|
15
|
+
to env / default URL until another profile is selected.
|
|
16
|
+
|
|
17
|
+
Pass --all to delete the whole config file (the pre-profile behaviour) — this
|
|
18
|
+
wipes every profile, not just the active one. Idempotent — no error if there
|
|
19
|
+
is nothing to clear.
|
|
15
20
|
|
|
16
21
|
This only clears the LOCAL config. It does NOT revoke the key on the relay —
|
|
17
|
-
|
|
22
|
+
keys keep working until revoked. To revoke a key server-side, use
|
|
18
23
|
'pane key revoke'.
|
|
19
24
|
|
|
20
25
|
Options:
|
|
26
|
+
--profile <name> Target this profile instead of the active one.
|
|
27
|
+
--all Delete every profile (the whole config file).
|
|
21
28
|
-h, --help Show this help.
|
|
22
29
|
|
|
23
30
|
Output (stdout, JSON):
|
|
24
|
-
{ cleared: true, path }`;
|
|
31
|
+
{ cleared: true, profile, path } (profile=null when --all)`;
|
|
25
32
|
export async function runLogout(args) {
|
|
26
|
-
assertKnownFlags(args, NO_FLAGS,
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
assertKnownFlags(args, NO_FLAGS, KNOWN_BOOLS, "pane agent logout");
|
|
34
|
+
if (args.bools.has("all")) {
|
|
35
|
+
// Nuke everything — file gone, both legacy and new shape covered.
|
|
36
|
+
const path = clearStore();
|
|
37
|
+
printJson({ cleared: true, profile: null, path });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const store = readStore();
|
|
41
|
+
const selector = args.flags.get("profile") ?? process.env.PANE_PROFILE;
|
|
42
|
+
let target;
|
|
43
|
+
try {
|
|
44
|
+
target = resolveProfile(store, selector);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
fail(e instanceof Error ? e.message : String(e), "config_error");
|
|
48
|
+
}
|
|
49
|
+
// Nothing to clear: empty store or legacy file with no migrate yet.
|
|
50
|
+
if (!target) {
|
|
51
|
+
// If there's literally nothing saved, mirror the legacy idempotent
|
|
52
|
+
// behaviour — delete the file (no-op if absent) and report cleared.
|
|
53
|
+
const path = clearStore();
|
|
54
|
+
printJson({ cleared: true, profile: null, path });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const { path } = removeProfile(target.name);
|
|
58
|
+
printJson({ cleared: true, profile: target.name, path });
|
|
29
59
|
}
|