runpane 2.4.136 → 2.4.138
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 +34 -3
- package/dist/agentContext.d.ts.map +1 -1
- package/dist/agentContext.js +72 -2
- package/dist/agentContext.js.map +1 -1
- package/dist/agentTasks.d.ts +1 -1
- package/dist/agentTasks.d.ts.map +1 -1
- package/dist/agentTasks.js +22 -4
- package/dist/agentTasks.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +20 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +152 -3
- package/dist/commands.js.map +1 -1
- package/dist/docs-index.json +1 -1
- package/dist/generated/contract.d.ts +1437 -150
- package/dist/generated/contract.d.ts.map +1 -1
- package/dist/generated/contract.js +2632 -216
- package/dist/generated/contract.js.map +1 -1
- package/dist/localControl.d.ts +66 -3
- package/dist/localControl.d.ts.map +1 -1
- package/dist/localControl.js +637 -32
- package/dist/localControl.js.map +1 -1
- package/dist/watchLines.d.ts +19 -0
- package/dist/watchLines.d.ts.map +1 -1
- package/dist/watchLines.js +31 -0
- package/dist/watchLines.js.map +1 -1
- package/package.json +1 -1
package/dist/localControl.js
CHANGED
|
@@ -15,6 +15,9 @@ exports.runSessionsSetAgent = runSessionsSetAgent;
|
|
|
15
15
|
exports.runSessionsAssociate = runSessionsAssociate;
|
|
16
16
|
exports.runSessionsDetach = runSessionsDetach;
|
|
17
17
|
exports.runSessionsOverview = runSessionsOverview;
|
|
18
|
+
exports.runLockAcquire = runLockAcquire;
|
|
19
|
+
exports.runLockRelease = runLockRelease;
|
|
20
|
+
exports.runLockList = runLockList;
|
|
18
21
|
exports.runPanesCost = runPanesCost;
|
|
19
22
|
exports.runWorkspaceState = runWorkspaceState;
|
|
20
23
|
exports.runWatch = runWatch;
|
|
@@ -26,16 +29,23 @@ exports.runPanesRename = runPanesRename;
|
|
|
26
29
|
exports.runPanesFocus = runPanesFocus;
|
|
27
30
|
exports.runPanelsList = runPanelsList;
|
|
28
31
|
exports.runPanelsCreate = runPanelsCreate;
|
|
32
|
+
exports.runPanelsOpen = runPanelsOpen;
|
|
29
33
|
exports.runPanelsOutput = runPanelsOutput;
|
|
30
34
|
exports.runPanelsInput = runPanelsInput;
|
|
31
35
|
exports.runPanelsScreen = runPanelsScreen;
|
|
36
|
+
exports.runPanelsLastMessage = runPanelsLastMessage;
|
|
37
|
+
exports.runReport = runReport;
|
|
32
38
|
exports.runPanelsSubmit = runPanelsSubmit;
|
|
39
|
+
exports.markSuggestionLine = markSuggestionLine;
|
|
40
|
+
exports.printPromptNotes = printPromptNotes;
|
|
33
41
|
exports.runPanelsSubmitComposer = runPanelsSubmitComposer;
|
|
34
42
|
exports.runPanelsWait = runPanelsWait;
|
|
35
43
|
exports.runAgentsDoctor = runAgentsDoctor;
|
|
36
44
|
exports.buildPanelInputRequest = buildPanelInputRequest;
|
|
37
45
|
exports.buildPaneCreateRequest = buildPaneCreateRequest;
|
|
46
|
+
const node_crypto_1 = require("node:crypto");
|
|
38
47
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
48
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
39
49
|
const node_process_1 = require("node:process");
|
|
40
50
|
const promises_1 = require("node:readline/promises");
|
|
41
51
|
const boundaryDecoder_1 = require("./boundaryDecoder");
|
|
@@ -65,6 +75,7 @@ const paneSummarySchema = boundaryDecoder_1.boundary.object({
|
|
|
65
75
|
name: boundaryDecoder_1.boundary.string,
|
|
66
76
|
status: boundaryDecoder_1.boundary.string,
|
|
67
77
|
agentStatus: boundaryDecoder_1.boundary.enumeration('active', 'idle'),
|
|
78
|
+
agentState: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('ready', 'working', 'blocked', 'none')),
|
|
68
79
|
worktreePath: boundaryDecoder_1.boundary.string,
|
|
69
80
|
repoId: boundaryDecoder_1.boundary.number,
|
|
70
81
|
repoName: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
@@ -76,7 +87,7 @@ const paneSummarySchema = boundaryDecoder_1.boundary.object({
|
|
|
76
87
|
ownership: boundaryDecoder_1.boundary.enumeration('pane', 'external'),
|
|
77
88
|
});
|
|
78
89
|
const panelBlockedSchema = boundaryDecoder_1.boundary.object({
|
|
79
|
-
kind: boundaryDecoder_1.boundary.enumeration('codex-update', 'agent-prompt', 'submission_unverified', 'unknown'),
|
|
90
|
+
kind: boundaryDecoder_1.boundary.enumeration('codex-update', 'agent-prompt', 'submission_unverified', 'composer-unknown', 'unknown'),
|
|
80
91
|
message: boundaryDecoder_1.boundary.string,
|
|
81
92
|
suggestedCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
82
93
|
});
|
|
@@ -100,6 +111,14 @@ const panelReadinessSchema = boundaryDecoder_1.boundary.object({
|
|
|
100
111
|
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
101
112
|
});
|
|
102
113
|
const verificationSchema = boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('observed', 'unverifiable'));
|
|
114
|
+
const deliverySchema = boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({
|
|
115
|
+
state: boundaryDecoder_1.boundary.enumeration('taken', 'queued', 'in-composer', 'unknown'),
|
|
116
|
+
evidence: boundaryDecoder_1.boundary.enumeration('transcript', 'screen', 'argv'),
|
|
117
|
+
}));
|
|
118
|
+
const promptWarningsSchema = boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.object({
|
|
119
|
+
code: boundaryDecoder_1.boundary.enumeration('leading-bang-runs-shell', 'leading-hash-memory', 'leading-slash-command', 'leading-at-mention'),
|
|
120
|
+
message: boundaryDecoder_1.boundary.string,
|
|
121
|
+
})));
|
|
103
122
|
const initialInputSchema = boundaryDecoder_1.boundary.object({
|
|
104
123
|
delivered: boundaryDecoder_1.boundary.boolean,
|
|
105
124
|
submitted: boundaryDecoder_1.boundary.boolean,
|
|
@@ -108,6 +127,7 @@ const initialInputSchema = boundaryDecoder_1.boundary.object({
|
|
|
108
127
|
sequenceName: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('codex-ctrl-enter-cr', 'enter-cr', 'argument')),
|
|
109
128
|
verifiedSubmitted: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
110
129
|
verification: verificationSchema,
|
|
130
|
+
delivery: deliverySchema,
|
|
111
131
|
staged: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
112
132
|
attempts: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
113
133
|
sentAt: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
@@ -130,7 +150,52 @@ const archiveSafetySchema = boundaryDecoder_1.boundary.object({
|
|
|
130
150
|
sha: boundaryDecoder_1.boundary.string,
|
|
131
151
|
subject: boundaryDecoder_1.boundary.string,
|
|
132
152
|
}))),
|
|
153
|
+
reason: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('external-worktree', 'main-repo', 'missing-project-context', 'git-error')),
|
|
154
|
+
worktreeWillRemain: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
155
|
+
upstreamGone: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
156
|
+
mergedViaPr: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({
|
|
157
|
+
number: boundaryDecoder_1.boundary.number,
|
|
158
|
+
headOid: boundaryDecoder_1.boundary.string,
|
|
159
|
+
})),
|
|
133
160
|
});
|
|
161
|
+
const agentReportFields = {
|
|
162
|
+
state: boundaryDecoder_1.boundary.enumeration('ready', 'blocked', 'failed', 'done'),
|
|
163
|
+
pr: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
164
|
+
head: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
165
|
+
summary: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
166
|
+
summaryTruncated: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
167
|
+
summaryPath: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
168
|
+
question: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
169
|
+
reportedAt: boundaryDecoder_1.boundary.string,
|
|
170
|
+
};
|
|
171
|
+
const agentReportSchema = boundaryDecoder_1.boundary.object(agentReportFields);
|
|
172
|
+
const reportResultSchema = boundaryDecoder_1.boundary.object({
|
|
173
|
+
ok: boundaryDecoder_1.boundary.literal(true),
|
|
174
|
+
generation: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
175
|
+
paneId: boundaryDecoder_1.boundary.string,
|
|
176
|
+
panelId: boundaryDecoder_1.boundary.string,
|
|
177
|
+
report: agentReportSchema,
|
|
178
|
+
sessionIds: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string),
|
|
179
|
+
});
|
|
180
|
+
const panelLastMessageResultSchema = boundaryDecoder_1.boundary.union(boundaryDecoder_1.boundary.object({
|
|
181
|
+
ok: boundaryDecoder_1.boundary.literal(true),
|
|
182
|
+
panelId: boundaryDecoder_1.boundary.string,
|
|
183
|
+
paneId: boundaryDecoder_1.boundary.string,
|
|
184
|
+
agentType: boundaryDecoder_1.boundary.enumeration('claude', 'codex'),
|
|
185
|
+
text: boundaryDecoder_1.boundary.string,
|
|
186
|
+
length: boundaryDecoder_1.boundary.number,
|
|
187
|
+
limit: boundaryDecoder_1.boundary.number,
|
|
188
|
+
truncated: boundaryDecoder_1.boundary.boolean,
|
|
189
|
+
}), boundaryDecoder_1.boundary.object({
|
|
190
|
+
ok: boundaryDecoder_1.boundary.literal(false),
|
|
191
|
+
panelId: boundaryDecoder_1.boundary.string,
|
|
192
|
+
paneId: boundaryDecoder_1.boundary.string,
|
|
193
|
+
reason: boundaryDecoder_1.boundary.literal('transcript-unavailable'),
|
|
194
|
+
message: boundaryDecoder_1.boundary.string,
|
|
195
|
+
}));
|
|
196
|
+
const archiveBlockCodeSchema = boundaryDecoder_1.boundary.enumeration('uncommitted-changes', 'unpushed-commits', 'uncommitted-and-unpushed', 'status-unknown');
|
|
197
|
+
const worktreeCleanupSchema = boundaryDecoder_1.boundary.enumeration('completed', 'failed', 'timeout', 'not-applicable');
|
|
198
|
+
const trashDeletionSchema = boundaryDecoder_1.boundary.enumeration('pending', 'done');
|
|
134
199
|
const panelSummarySchema = boundaryDecoder_1.boundary.object({
|
|
135
200
|
id: boundaryDecoder_1.boundary.string,
|
|
136
201
|
panelId: boundaryDecoder_1.boundary.string,
|
|
@@ -140,10 +205,13 @@ const panelSummarySchema = boundaryDecoder_1.boundary.object({
|
|
|
140
205
|
active: boundaryDecoder_1.boundary.boolean,
|
|
141
206
|
initialized: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
142
207
|
agentType: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
208
|
+
agentDetection: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('declared', 'command', 'process', 'screen')),
|
|
209
|
+
launchCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
143
210
|
isCliPanel: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
144
211
|
position: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
145
212
|
createdAt: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
146
213
|
lastActiveAt: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
214
|
+
report: boundaryDecoder_1.boundary.optional(agentReportSchema),
|
|
147
215
|
});
|
|
148
216
|
const repoListResultSchema = boundaryDecoder_1.boundary.object({
|
|
149
217
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
@@ -201,6 +269,8 @@ const orchestrationSessionRecordSchema = boundaryDecoder_1.boundary.object({
|
|
|
201
269
|
codex: boundaryDecoder_1.boundary.nonEmptyString,
|
|
202
270
|
cursor: boundaryDecoder_1.boundary.nonEmptyString,
|
|
203
271
|
}),
|
|
272
|
+
launchCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
273
|
+
profile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
204
274
|
goal: boundaryDecoder_1.boundary.string,
|
|
205
275
|
context: boundaryDecoder_1.boundary.string,
|
|
206
276
|
decisions: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string),
|
|
@@ -256,6 +326,55 @@ const orchestrationPaneOverviewSchema = boundaryDecoder_1.boundary.object({
|
|
|
256
326
|
prTitle: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
257
327
|
prState: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
258
328
|
})),
|
|
329
|
+
report: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({ ...agentReportFields, panelId: boundaryDecoder_1.boundary.nonEmptyString })),
|
|
330
|
+
});
|
|
331
|
+
const lockOwnerSchema = boundaryDecoder_1.boundary.object({
|
|
332
|
+
kind: boundaryDecoder_1.boundary.enumeration('pane', 'external'),
|
|
333
|
+
paneId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nonEmptyString),
|
|
334
|
+
panelId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nonEmptyString),
|
|
335
|
+
label: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
336
|
+
});
|
|
337
|
+
const lockRecordSchema = boundaryDecoder_1.boundary.object({
|
|
338
|
+
name: boundaryDecoder_1.boundary.nonEmptyString,
|
|
339
|
+
scope: boundaryDecoder_1.boundary.enumeration('session', 'global'),
|
|
340
|
+
sessionId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nonEmptyString),
|
|
341
|
+
owner: lockOwnerSchema,
|
|
342
|
+
note: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
343
|
+
acquiredAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
344
|
+
expiresAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
345
|
+
ttlMs: boundaryDecoder_1.boundary.number,
|
|
346
|
+
});
|
|
347
|
+
const lockAcquireResultSchema = boundaryDecoder_1.boundary.union(boundaryDecoder_1.boundary.object({
|
|
348
|
+
ok: boundaryDecoder_1.boundary.literal(true),
|
|
349
|
+
acquired: boundaryDecoder_1.boundary.literal(true),
|
|
350
|
+
renewed: boundaryDecoder_1.boundary.boolean,
|
|
351
|
+
waitedMs: boundaryDecoder_1.boundary.number,
|
|
352
|
+
lock: lockRecordSchema,
|
|
353
|
+
}), boundaryDecoder_1.boundary.object({
|
|
354
|
+
ok: boundaryDecoder_1.boundary.literal(false),
|
|
355
|
+
acquired: boundaryDecoder_1.boundary.literal(false),
|
|
356
|
+
timedOut: boundaryDecoder_1.boundary.boolean,
|
|
357
|
+
waitedMs: boundaryDecoder_1.boundary.number,
|
|
358
|
+
heldBy: lockOwnerSchema,
|
|
359
|
+
expiresAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
360
|
+
lock: lockRecordSchema,
|
|
361
|
+
}));
|
|
362
|
+
const lockReleaseResultSchema = boundaryDecoder_1.boundary.union(boundaryDecoder_1.boundary.object({
|
|
363
|
+
ok: boundaryDecoder_1.boundary.literal(true),
|
|
364
|
+
released: boundaryDecoder_1.boundary.boolean,
|
|
365
|
+
forced: boundaryDecoder_1.boundary.boolean,
|
|
366
|
+
lock: boundaryDecoder_1.boundary.optional(lockRecordSchema),
|
|
367
|
+
}), boundaryDecoder_1.boundary.object({
|
|
368
|
+
ok: boundaryDecoder_1.boundary.literal(false),
|
|
369
|
+
released: boundaryDecoder_1.boundary.literal(false),
|
|
370
|
+
reason: boundaryDecoder_1.boundary.literal('not-owner'),
|
|
371
|
+
heldBy: lockOwnerSchema,
|
|
372
|
+
expiresAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
373
|
+
lock: lockRecordSchema,
|
|
374
|
+
}));
|
|
375
|
+
const lockListResultSchema = boundaryDecoder_1.boundary.object({
|
|
376
|
+
ok: boundaryDecoder_1.boundary.literal(true),
|
|
377
|
+
locks: boundaryDecoder_1.boundary.array(lockRecordSchema),
|
|
259
378
|
});
|
|
260
379
|
const runpaneSessionOverviewResultSchema = boundaryDecoder_1.boundary.object({
|
|
261
380
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
@@ -268,6 +387,7 @@ const runpaneSessionOverviewResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
268
387
|
freshness: boundaryDecoder_1.boundary.enumeration('current', 'stale'),
|
|
269
388
|
})),
|
|
270
389
|
refreshedAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
390
|
+
locks: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(lockRecordSchema)),
|
|
271
391
|
});
|
|
272
392
|
function orchestrationReportSchemaFields() {
|
|
273
393
|
return {
|
|
@@ -367,6 +487,8 @@ exports.paneCreateResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
367
487
|
ok: boundaryDecoder_1.boundary.boolean,
|
|
368
488
|
error: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
369
489
|
})),
|
|
490
|
+
promptFile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
491
|
+
warnings: promptWarningsSchema,
|
|
370
492
|
}), boundaryDecoder_1.boundary.object({
|
|
371
493
|
ok: boundaryDecoder_1.boundary.literal(false),
|
|
372
494
|
index: boundaryDecoder_1.boundary.number,
|
|
@@ -385,7 +507,7 @@ const paneArchiveResultSchema = boundaryDecoder_1.boundary.union(boundaryDecoder
|
|
|
385
507
|
generation: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
386
508
|
paneId: boundaryDecoder_1.boundary.string,
|
|
387
509
|
blocked: boundaryDecoder_1.boundary.object({
|
|
388
|
-
code:
|
|
510
|
+
code: archiveBlockCodeSchema,
|
|
389
511
|
message: boundaryDecoder_1.boundary.string,
|
|
390
512
|
safetyCheck: archiveSafetySchema,
|
|
391
513
|
}),
|
|
@@ -398,7 +520,7 @@ const paneArchiveResultSchema = boundaryDecoder_1.boundary.union(boundaryDecoder
|
|
|
398
520
|
forced: boundaryDecoder_1.boundary.boolean,
|
|
399
521
|
safetyCheck: archiveSafetySchema,
|
|
400
522
|
blocked: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({
|
|
401
|
-
code:
|
|
523
|
+
code: archiveBlockCodeSchema,
|
|
402
524
|
message: boundaryDecoder_1.boundary.string,
|
|
403
525
|
safetyCheck: archiveSafetySchema,
|
|
404
526
|
})),
|
|
@@ -408,10 +530,35 @@ const paneArchiveResultSchema = boundaryDecoder_1.boundary.union(boundaryDecoder
|
|
|
408
530
|
paneId: boundaryDecoder_1.boundary.string,
|
|
409
531
|
archived: boundaryDecoder_1.boundary.literal(true),
|
|
410
532
|
forced: boundaryDecoder_1.boundary.boolean,
|
|
411
|
-
worktreeCleanup:
|
|
533
|
+
worktreeCleanup: worktreeCleanupSchema,
|
|
534
|
+
trashDeletion: boundaryDecoder_1.boundary.optional(trashDeletionSchema),
|
|
412
535
|
worktreePath: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
413
536
|
safetyCheck: archiveSafetySchema,
|
|
414
537
|
}));
|
|
538
|
+
const paneArchiveBulkResultSchema = boundaryDecoder_1.boundary.object({
|
|
539
|
+
ok: boundaryDecoder_1.boundary.boolean,
|
|
540
|
+
sessionId: boundaryDecoder_1.boundary.string,
|
|
541
|
+
merged: boundaryDecoder_1.boundary.literal(true),
|
|
542
|
+
dryRun: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
543
|
+
removeWorktree: boundaryDecoder_1.boundary.boolean,
|
|
544
|
+
archived: boundaryDecoder_1.boundary.number,
|
|
545
|
+
skipped: boundaryDecoder_1.boundary.number,
|
|
546
|
+
failed: boundaryDecoder_1.boundary.number,
|
|
547
|
+
items: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.object({
|
|
548
|
+
paneId: boundaryDecoder_1.boundary.string,
|
|
549
|
+
name: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
550
|
+
outcome: boundaryDecoder_1.boundary.enumeration('archived', 'would-archive', 'skipped', 'failed'),
|
|
551
|
+
skipped: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({
|
|
552
|
+
code: boundaryDecoder_1.boundary.enumeration('uncommitted-changes', 'unpushed-commits', 'uncommitted-and-unpushed', 'status-unknown', 'missing-pane', 'already-archived', 'main-repo'),
|
|
553
|
+
message: boundaryDecoder_1.boundary.string,
|
|
554
|
+
})),
|
|
555
|
+
error: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
556
|
+
safetyCheck: boundaryDecoder_1.boundary.optional(archiveSafetySchema),
|
|
557
|
+
worktreeCleanup: boundaryDecoder_1.boundary.optional(worktreeCleanupSchema),
|
|
558
|
+
trashDeletion: boundaryDecoder_1.boundary.optional(trashDeletionSchema),
|
|
559
|
+
worktreePath: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
560
|
+
})),
|
|
561
|
+
});
|
|
415
562
|
const panePinResultSchema = boundaryDecoder_1.boundary.object({
|
|
416
563
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
417
564
|
generation: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
@@ -432,6 +579,18 @@ const paneFocusResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
432
579
|
panelId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
433
580
|
focused: boundaryDecoder_1.boundary.literal(true),
|
|
434
581
|
});
|
|
582
|
+
const panelOpenResultSchema = boundaryDecoder_1.boundary.object({
|
|
583
|
+
ok: boundaryDecoder_1.boundary.literal(true),
|
|
584
|
+
paneId: boundaryDecoder_1.boundary.string,
|
|
585
|
+
panelId: boundaryDecoder_1.boundary.string,
|
|
586
|
+
type: boundaryDecoder_1.boundary.enumeration('browser', 'editor'),
|
|
587
|
+
title: boundaryDecoder_1.boundary.string,
|
|
588
|
+
url: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
589
|
+
filePath: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
590
|
+
placement: boundaryDecoder_1.boundary.enumeration('split', 'tab'),
|
|
591
|
+
active: boundaryDecoder_1.boundary.boolean,
|
|
592
|
+
reused: boundaryDecoder_1.boundary.boolean,
|
|
593
|
+
});
|
|
435
594
|
exports.panelListResultSchema = boundaryDecoder_1.boundary.object({
|
|
436
595
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
437
596
|
paneId: boundaryDecoder_1.boundary.string,
|
|
@@ -452,6 +611,8 @@ const panelCreateResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
452
611
|
}),
|
|
453
612
|
readiness: boundaryDecoder_1.boundary.optional(panelReadinessSchema),
|
|
454
613
|
initialInput: boundaryDecoder_1.boundary.optional(initialInputSchema),
|
|
614
|
+
promptFile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
615
|
+
warnings: promptWarningsSchema,
|
|
455
616
|
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
456
617
|
});
|
|
457
618
|
const panelOutputResultSchema = boundaryDecoder_1.boundary.object({
|
|
@@ -490,6 +651,7 @@ exports.panelScreenResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
490
651
|
composer: boundaryDecoder_1.boundary.object({
|
|
491
652
|
isPresent: boundaryDecoder_1.boundary.boolean,
|
|
492
653
|
hasUndeliveredText: boundaryDecoder_1.boundary.boolean,
|
|
654
|
+
ghostText: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
493
655
|
}),
|
|
494
656
|
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
495
657
|
});
|
|
@@ -503,8 +665,11 @@ exports.panelSubmitResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
503
665
|
sequenceName: boundaryDecoder_1.boundary.enumeration('codex-ctrl-enter-cr', 'enter-cr', 'tab'),
|
|
504
666
|
verifiedSubmitted: boundaryDecoder_1.boundary.boolean,
|
|
505
667
|
verification: verificationSchema,
|
|
668
|
+
delivery: deliverySchema,
|
|
506
669
|
sentAt: boundaryDecoder_1.boundary.string,
|
|
507
670
|
blocked: boundaryDecoder_1.boundary.optional(panelBlockedSchema),
|
|
671
|
+
promptFile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
672
|
+
warnings: promptWarningsSchema,
|
|
508
673
|
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
509
674
|
});
|
|
510
675
|
const panelSubmitComposerResultSchema = boundaryDecoder_1.boundary.object({
|
|
@@ -517,6 +682,7 @@ const panelSubmitComposerResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
517
682
|
sequenceName: boundaryDecoder_1.boundary.enumeration('codex-ctrl-enter-cr', 'enter-cr', 'tab'),
|
|
518
683
|
verifiedSubmitted: boundaryDecoder_1.boundary.boolean,
|
|
519
684
|
verification: verificationSchema,
|
|
685
|
+
delivery: deliverySchema,
|
|
520
686
|
sentAt: boundaryDecoder_1.boundary.string,
|
|
521
687
|
blocked: boundaryDecoder_1.boundary.optional(panelBlockedSchema),
|
|
522
688
|
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
@@ -554,7 +720,7 @@ const agentDoctorResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
554
720
|
})),
|
|
555
721
|
warnings: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
556
722
|
});
|
|
557
|
-
const workspaceEntryKindSchema = boundaryDecoder_1.boundary.enumeration('agent.ready', 'agent.busy', 'agent.blocked', 'agent.unknown', 'agent.idle', 'pane.created', 'pane.gone', 'panel.exited');
|
|
723
|
+
const workspaceEntryKindSchema = boundaryDecoder_1.boundary.enumeration('agent.ready', 'agent.busy', 'agent.blocked', 'agent.unknown', 'agent.idle', 'pane.created', 'pane.gone', 'panel.exited', 'pane.associated', 'pane.detached', 'pr.conflicted', 'pr.checks', 'pr.merged', 'agent.report');
|
|
558
724
|
const agentStateSchema = boundaryDecoder_1.boundary.enumeration('blocked', 'working', 'idle', 'unknown');
|
|
559
725
|
const workspacePanelSummarySchema = boundaryDecoder_1.boundary.object({
|
|
560
726
|
panelId: boundaryDecoder_1.boundary.string,
|
|
@@ -576,7 +742,7 @@ const workspaceEntrySchema = boundaryDecoder_1.boundary.object({
|
|
|
576
742
|
agentType: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
577
743
|
from: boundaryDecoder_1.boundary.optional(agentStateSchema),
|
|
578
744
|
to: boundaryDecoder_1.boundary.optional(agentStateSchema),
|
|
579
|
-
source: boundaryDecoder_1.boundary.enumeration('agent', 'exit', 'session'),
|
|
745
|
+
source: boundaryDecoder_1.boundary.enumeration('agent', 'exit', 'session', 'github'),
|
|
580
746
|
reason: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nullable(boundaryDecoder_1.boundary.string)),
|
|
581
747
|
settledMs: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
582
748
|
idleMs: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
@@ -585,7 +751,14 @@ const workspaceEntrySchema = boundaryDecoder_1.boundary.object({
|
|
|
585
751
|
heldInputPresent: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
586
752
|
exitCode: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
587
753
|
baseline: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
754
|
+
replay: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
588
755
|
changedWhileAway: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
756
|
+
sessionId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
757
|
+
sessionName: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
758
|
+
pr: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({ number: boundaryDecoder_1.boundary.number, url: boundaryDecoder_1.boundary.string, headOid: boundaryDecoder_1.boundary.string })),
|
|
759
|
+
checks: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('passed', 'failed')),
|
|
760
|
+
failingChecks: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
761
|
+
report: boundaryDecoder_1.boundary.optional(agentReportSchema),
|
|
589
762
|
panels: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(workspacePanelSummarySchema)),
|
|
590
763
|
});
|
|
591
764
|
exports.workspaceStateResultSchema = boundaryDecoder_1.boundary.object({
|
|
@@ -604,20 +777,24 @@ const workspaceWaitResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
604
777
|
reset: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({
|
|
605
778
|
reason: boundaryDecoder_1.boundary.enumeration('first-use', 'epoch-changed', 'cursor-truncated', 'unknown-consumer'),
|
|
606
779
|
})),
|
|
780
|
+
session: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.string, name: boundaryDecoder_1.boundary.string })),
|
|
607
781
|
nextCommand: boundaryDecoder_1.boundary.string,
|
|
608
782
|
});
|
|
609
783
|
const repoSelectorSchema = boundaryDecoder_1.boundary.union(boundaryDecoder_1.boundary.nonEmptyString, boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.number }), boundaryDecoder_1.boundary.object({ path: boundaryDecoder_1.boundary.string }), boundaryDecoder_1.boundary.object({ name: boundaryDecoder_1.boundary.string }), boundaryDecoder_1.boundary.object({ active: boundaryDecoder_1.boundary.literal(true) }));
|
|
610
784
|
const paneToolInputSchema = boundaryDecoder_1.boundary.object({
|
|
611
785
|
agent: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
612
786
|
command: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
787
|
+
agentType: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
613
788
|
title: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
614
789
|
initialInput: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
790
|
+
initialInputAsFilePointer: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
615
791
|
});
|
|
616
792
|
const paneCreateRequestInputSchema = boundaryDecoder_1.boundary.object({
|
|
617
793
|
repo: repoSelectorSchema,
|
|
618
794
|
panes: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.object({
|
|
619
795
|
name: boundaryDecoder_1.boundary.string,
|
|
620
796
|
worktreeName: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
797
|
+
branch: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
621
798
|
baseBranch: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
622
799
|
sessionPrompt: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
623
800
|
pinned: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
@@ -646,6 +823,8 @@ const paneAdoptRequestInputSchema = boundaryDecoder_1.boundary.object({
|
|
|
646
823
|
launch: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
647
824
|
})),
|
|
648
825
|
dryRun: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
826
|
+
waitReady: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
827
|
+
readyTimeoutMs: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
649
828
|
noFocus: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
650
829
|
focus: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
651
830
|
source: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('user', 'agent')),
|
|
@@ -775,9 +954,123 @@ async function runSessionsOverview(parsed) {
|
|
|
775
954
|
for (const pane of result.panes) {
|
|
776
955
|
const details = pane.missing ? 'missing' : pane.archived ? 'archived' : pane.panels.map(panel => `${panel.title}=${panel.state}`).join(', ') || 'no terminal panels';
|
|
777
956
|
console.log(` ${pane.name}: ${details}`);
|
|
957
|
+
if (pane.report) {
|
|
958
|
+
console.log(` report ${(0, watchLines_1.describeReport)(pane.report)} (panel ${pane.report.panelId}, ${pane.report.reportedAt})`);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
for (const lock of result.locks ?? []) {
|
|
962
|
+
console.log(` lock ${formatLockLine(lock)}`);
|
|
963
|
+
}
|
|
964
|
+
return 0;
|
|
965
|
+
}
|
|
966
|
+
/** One daemon call waits at most this long; longer waits chain calls, each blocking in the daemon. */
|
|
967
|
+
const LOCK_WAIT_PER_CALL_MS = 120_000;
|
|
968
|
+
async function runLockAcquire(parsed) {
|
|
969
|
+
const name = requireLockName(parsed, 'acquire');
|
|
970
|
+
if (parsed.lockTtlMs === undefined)
|
|
971
|
+
throw new Error('runpane lock acquire requires --ttl <duration>, such as --ttl 30m.');
|
|
972
|
+
const request = { name, ttlMs: parsed.lockTtlMs, note: parsed.note, owner: lockOwnerFromParsed(parsed, false) };
|
|
973
|
+
const waitMs = parsed.lockWaitMs ?? 0;
|
|
974
|
+
const startedAt = Date.now();
|
|
975
|
+
let result;
|
|
976
|
+
for (;;) {
|
|
977
|
+
const callWaitMs = Math.min(Math.max(0, waitMs - (Date.now() - startedAt)), LOCK_WAIT_PER_CALL_MS);
|
|
978
|
+
result = await (0, daemonClient_1.invokeDaemon)('runpane:locks:acquire', [{ ...request, waitMs: callWaitMs }], lockAcquireResultSchema, {
|
|
979
|
+
paneDir: parsed.paneDir,
|
|
980
|
+
timeoutMs: callWaitMs + 15_000,
|
|
981
|
+
});
|
|
982
|
+
// Only a call that waited out its whole window without the lock coming free chains another.
|
|
983
|
+
if (result.ok || !result.timedOut || Date.now() - startedAt >= waitMs)
|
|
984
|
+
break;
|
|
985
|
+
}
|
|
986
|
+
const final = { ...result, waitedMs: Date.now() - startedAt };
|
|
987
|
+
if (parsed.json) {
|
|
988
|
+
printJson(final);
|
|
989
|
+
}
|
|
990
|
+
else if (final.ok) {
|
|
991
|
+
console.log(`${final.renewed ? 'Renewed' : 'Acquired'} lock ${formatLockLine(final.lock)}`);
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
console.log(`Lock ${final.lock.name} is held by ${formatLockOwner(final.heldBy)} until ${final.expiresAt}${final.lock.note ? ` (${final.lock.note})` : ''}.`);
|
|
995
|
+
}
|
|
996
|
+
return final.ok ? 0 : 1;
|
|
997
|
+
}
|
|
998
|
+
async function runLockRelease(parsed) {
|
|
999
|
+
const name = requireLockName(parsed, 'release');
|
|
1000
|
+
const request = {
|
|
1001
|
+
name,
|
|
1002
|
+
force: parsed.force || undefined,
|
|
1003
|
+
sessionId: parsed.sessionId?.trim() || undefined,
|
|
1004
|
+
owner: lockOwnerFromParsed(parsed, parsed.force === true),
|
|
1005
|
+
};
|
|
1006
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:locks:release', [request], lockReleaseResultSchema, { paneDir: parsed.paneDir });
|
|
1007
|
+
if (parsed.json) {
|
|
1008
|
+
printJson(result);
|
|
1009
|
+
}
|
|
1010
|
+
else if (!result.ok) {
|
|
1011
|
+
console.log(`Lock ${name} is held by ${formatLockOwner(result.heldBy)} until ${result.expiresAt}; only its owner can release it. Rerun with --force to release it anyway.`);
|
|
778
1012
|
}
|
|
1013
|
+
else if (result.released) {
|
|
1014
|
+
console.log(`${result.forced ? 'Force-released' : 'Released'} lock ${name}.`);
|
|
1015
|
+
}
|
|
1016
|
+
else {
|
|
1017
|
+
console.log(`Lock ${name} was not held.`);
|
|
1018
|
+
}
|
|
1019
|
+
return result.ok ? 0 : 1;
|
|
1020
|
+
}
|
|
1021
|
+
async function runLockList(parsed) {
|
|
1022
|
+
const sessionId = parsed.sessionId?.trim() || undefined;
|
|
1023
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:locks:list', [{ sessionId }], lockListResultSchema, { paneDir: parsed.paneDir });
|
|
1024
|
+
if (parsed.json) {
|
|
1025
|
+
printJson(result);
|
|
1026
|
+
return 0;
|
|
1027
|
+
}
|
|
1028
|
+
for (const lock of result.locks)
|
|
1029
|
+
console.log(formatLockLine(lock));
|
|
1030
|
+
if (result.locks.length === 0)
|
|
1031
|
+
console.log('No locks held.');
|
|
779
1032
|
return 0;
|
|
780
1033
|
}
|
|
1034
|
+
function requireLockName(parsed, action) {
|
|
1035
|
+
const name = parsed.name?.trim();
|
|
1036
|
+
if (!name)
|
|
1037
|
+
throw new Error(`runpane lock ${action} requires --name <name>.`);
|
|
1038
|
+
return name;
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* The caller owns the lock: --pane/--panel when given, else the Pane terminal
|
|
1042
|
+
* it runs in ($PANE_SESSION_ID/$PANE_PANEL_ID). Outside Pane, --note names the owner.
|
|
1043
|
+
*/
|
|
1044
|
+
function lockOwnerFromParsed(parsed, forced) {
|
|
1045
|
+
const explicit = Boolean(parsed.paneId || parsed.panelId);
|
|
1046
|
+
const paneId = explicit ? parsed.paneId : process.env.PANE_SESSION_ID?.trim() || undefined;
|
|
1047
|
+
const panelId = explicit ? parsed.panelId : process.env.PANE_PANEL_ID?.trim() || undefined;
|
|
1048
|
+
const owner = {};
|
|
1049
|
+
if (paneId || panelId) {
|
|
1050
|
+
if (paneId)
|
|
1051
|
+
owner.paneId = paneId;
|
|
1052
|
+
if (panelId)
|
|
1053
|
+
owner.panelId = panelId;
|
|
1054
|
+
return owner;
|
|
1055
|
+
}
|
|
1056
|
+
const label = parsed.note?.trim();
|
|
1057
|
+
if (!label && !forced) {
|
|
1058
|
+
throw new Error('Outside a Pane terminal, pass --note <text> to say who holds the lock (or --pane/--panel to act for a Pane).');
|
|
1059
|
+
}
|
|
1060
|
+
if (label)
|
|
1061
|
+
owner.label = label;
|
|
1062
|
+
return owner;
|
|
1063
|
+
}
|
|
1064
|
+
function formatLockOwner(owner) {
|
|
1065
|
+
if (owner.kind === 'external')
|
|
1066
|
+
return `external "${owner.label ?? ''}"`;
|
|
1067
|
+
return owner.panelId ? `pane ${owner.paneId} panel ${owner.panelId}` : `pane ${owner.paneId}`;
|
|
1068
|
+
}
|
|
1069
|
+
function formatLockLine(lock) {
|
|
1070
|
+
const scope = lock.scope === 'session' ? `session ${lock.sessionId}` : 'global';
|
|
1071
|
+
const note = lock.note ? ` (${lock.note})` : '';
|
|
1072
|
+
return `${lock.name} [${scope}] held by ${formatLockOwner(lock.owner)} until ${lock.expiresAt}${note}`;
|
|
1073
|
+
}
|
|
781
1074
|
function sessionSelectorFromParsed(parsed) {
|
|
782
1075
|
const sessionId = parsed.sessionId?.trim();
|
|
783
1076
|
if (!sessionId)
|
|
@@ -788,6 +1081,8 @@ function parseSessionCreatePayload(value) {
|
|
|
788
1081
|
return (0, boundaryDecoder_1.decodeBoundary)(value, boundaryDecoder_1.boundary.object({
|
|
789
1082
|
name: boundaryDecoder_1.boundary.nonEmptyString,
|
|
790
1083
|
agent: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('codex', 'claude', 'cursor')),
|
|
1084
|
+
launchCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1085
|
+
profile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
791
1086
|
goal: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
792
1087
|
context: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
793
1088
|
decisions: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
@@ -803,6 +1098,8 @@ function parseSessionUpdatePayload(value) {
|
|
|
803
1098
|
archived: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
804
1099
|
isPinned: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
805
1100
|
agent: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('codex', 'claude', 'cursor')),
|
|
1101
|
+
launchCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1102
|
+
profile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
806
1103
|
goal: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
807
1104
|
context: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
808
1105
|
decisions: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
@@ -867,12 +1164,21 @@ async function runWatch(parsed) {
|
|
|
867
1164
|
? undefined
|
|
868
1165
|
: parsed.agentsOnly || parsed.follow ? true : undefined;
|
|
869
1166
|
const includeHeldInput = parsed.includeHeldInput && !parsed.noHeldInput ? true : undefined;
|
|
1167
|
+
// Lines mode turns presence into STUCK; JSON mode passes heldInputPresent through as the equivalent.
|
|
870
1168
|
const includeHeldInputPresence = defaults.includeHeldInputPresence
|
|
871
|
-
&& !parsed.noHeldInput && parsed.follow
|
|
1169
|
+
&& !parsed.noHeldInput && parsed.follow ? true : undefined;
|
|
872
1170
|
const cadenceValueFlagPresent = (0, commands_1.hasCadenceValueFlag)(parsed);
|
|
873
1171
|
// Cadence state lives in the daemon per named consumer, so an anonymous follower names itself.
|
|
1172
|
+
// A Session watch is named after the Session, so it survives an orchestrator agent switch.
|
|
1173
|
+
const sessionCursor = parsed.sessionId ? sessionWatchCursorName(parsed.sessionId) : undefined;
|
|
1174
|
+
const panelCursor = process.env.PANE_PANEL_ID ? derivedWatchCursorName('panel', process.env.PANE_PANEL_ID) : undefined;
|
|
874
1175
|
const watchAs = parsed.watchAs
|
|
875
|
-
?? (parsed.follow ?
|
|
1176
|
+
?? (parsed.follow ? sessionCursor || panelCursor || (cadenceValueFlagPresent ? `follow-${process.pid}` : undefined) : undefined);
|
|
1177
|
+
// --quiet drops lines that only prove liveness; --self-test still prints its WATCH OK result.
|
|
1178
|
+
const emitControlLine = (line) => {
|
|
1179
|
+
if (!parsed.quiet)
|
|
1180
|
+
emitWatchLine(line);
|
|
1181
|
+
};
|
|
876
1182
|
const request = {
|
|
877
1183
|
as: watchAs,
|
|
878
1184
|
since: parsed.watchSince,
|
|
@@ -881,6 +1187,8 @@ async function runWatch(parsed) {
|
|
|
881
1187
|
limit: parsed.limit,
|
|
882
1188
|
kinds: parsed.watchKinds,
|
|
883
1189
|
paneIds: parsed.watchPaneIds,
|
|
1190
|
+
// The daemon resolves the Session (id or exact name) and re-reads its Panes on every read.
|
|
1191
|
+
session: parsed.sessionId,
|
|
884
1192
|
excludePaneIds: parsed.watchExcludePaneIds,
|
|
885
1193
|
repo: parsed.repo,
|
|
886
1194
|
nameContains: parsed.nameContains,
|
|
@@ -914,12 +1222,20 @@ async function runWatch(parsed) {
|
|
|
914
1222
|
timeoutMs: timeoutMs + 5_000,
|
|
915
1223
|
eventInclude: [],
|
|
916
1224
|
});
|
|
1225
|
+
if (request.session && !result.session) {
|
|
1226
|
+
// An older daemon ignores the unknown field and would watch every Pane instead.
|
|
1227
|
+
throw new Error('This Pane daemon does not support runpane watch --session; update Pane, or pass one --pane per Session Pane.');
|
|
1228
|
+
}
|
|
917
1229
|
if (failingCode) {
|
|
918
|
-
|
|
1230
|
+
emitControlLine((0, watchLines_1.formatNonEntry)('_reconnected', { generation: result.generation }, format));
|
|
919
1231
|
failingCode = undefined;
|
|
920
1232
|
}
|
|
921
1233
|
if (!armed && (parsed.follow || parsed.selfTest)) {
|
|
922
|
-
|
|
1234
|
+
const okLine = (0, watchLines_1.formatNonEntry)('_ok', { generation: result.generation, epoch: result.epoch }, format);
|
|
1235
|
+
if (parsed.selfTest)
|
|
1236
|
+
emitWatchLine(okLine);
|
|
1237
|
+
else
|
|
1238
|
+
emitControlLine(okLine);
|
|
923
1239
|
armed = true;
|
|
924
1240
|
if (parsed.selfTest)
|
|
925
1241
|
return 0;
|
|
@@ -927,7 +1243,7 @@ async function runWatch(parsed) {
|
|
|
927
1243
|
for (const line of (0, watchLines_1.formatWaitResult)(result, format))
|
|
928
1244
|
emitWatchLine(line);
|
|
929
1245
|
if (heartbeatMs > 0 && Date.now() - lastHeartbeatAt >= heartbeatMs) {
|
|
930
|
-
|
|
1246
|
+
emitControlLine((0, watchLines_1.formatNonEntry)('_heartbeat', {
|
|
931
1247
|
generation: result.generation,
|
|
932
1248
|
at: new Date().toISOString(),
|
|
933
1249
|
}, format));
|
|
@@ -958,6 +1274,27 @@ async function runWatch(parsed) {
|
|
|
958
1274
|
function emitWatchLine(line) {
|
|
959
1275
|
node_process_1.stdout.write(`${line}\n`);
|
|
960
1276
|
}
|
|
1277
|
+
/** Names older daemons accept; the daemon itself allows up to 128 characters. */
|
|
1278
|
+
const PORTABLE_WATCH_CURSOR_PATTERN = /^[A-Za-z0-9._-]{1,64}$/u;
|
|
1279
|
+
/**
|
|
1280
|
+
* Returns a derived watch cursor name (one runpane builds from an ID, not one the user typed)
|
|
1281
|
+
* that every daemon accepts. A name that is too long or has other characters becomes
|
|
1282
|
+
* `<prefix>-<first 12 hex chars of its sha256>`, which is stable across runs.
|
|
1283
|
+
*/
|
|
1284
|
+
function derivedWatchCursorName(prefix, name) {
|
|
1285
|
+
if (PORTABLE_WATCH_CURSOR_PATTERN.test(name))
|
|
1286
|
+
return name;
|
|
1287
|
+
return `${prefix}-${(0, node_crypto_1.createHash)('sha256').update(name).digest('hex').slice(0, 12)}`;
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Default cursor for `watch --session`: `session-<uuid>` for a Session id
|
|
1291
|
+
* (`__orchestration_session_<uuid>__`), `session-<name>` for a name, shortened like any
|
|
1292
|
+
* derived name when it is longer than 64 characters or has other characters.
|
|
1293
|
+
*/
|
|
1294
|
+
function sessionWatchCursorName(session) {
|
|
1295
|
+
const uuid = /^__orchestration_session_(.+)__$/u.exec(session)?.[1];
|
|
1296
|
+
return derivedWatchCursorName('session', `session-${uuid ?? session}`);
|
|
1297
|
+
}
|
|
961
1298
|
function watchErrorCode(error) {
|
|
962
1299
|
return error instanceof daemonClient_1.PaneDaemonClientError ? error.code ?? 'PaneDaemonClientError' : error.name || 'Error';
|
|
963
1300
|
}
|
|
@@ -1003,6 +1340,7 @@ async function runPanesAdopt(parsed) {
|
|
|
1003
1340
|
...decoded,
|
|
1004
1341
|
panes: decoded.panes.map((pane, index) => ({
|
|
1005
1342
|
...pane,
|
|
1343
|
+
pinned: resolvePinnedOverride(parsed) ?? pane.pinned ?? !process.env.PANE_ORCHESTRATION_SESSION_ID,
|
|
1006
1344
|
tool: parsePaneToolSpecPayload(pane.tool, index),
|
|
1007
1345
|
})),
|
|
1008
1346
|
associateSession: parsed.noAssociate ? undefined : resolveAssociateSession(parsed) ?? decoded.associateSession,
|
|
@@ -1012,6 +1350,9 @@ async function runPanesAdopt(parsed) {
|
|
|
1012
1350
|
if (!parsed.repo || !parsed.repoPath || !parsed.name) {
|
|
1013
1351
|
throw new Error('runpane panes adopt requires --repo, --path, and --name.');
|
|
1014
1352
|
}
|
|
1353
|
+
if (!parsed.launch && (parsed.initialInput !== undefined || parsed.initialInputFile !== undefined || parsed.waitReady)) {
|
|
1354
|
+
throw new Error('runpane panes adopt only sends a prompt or waits for readiness with --launch. Add --launch to start the agent now.');
|
|
1355
|
+
}
|
|
1015
1356
|
const tool = await buildToolSpec(parsed, 'panes adopt');
|
|
1016
1357
|
request = {
|
|
1017
1358
|
repo: parsed.repo,
|
|
@@ -1020,12 +1361,14 @@ async function runPanesAdopt(parsed) {
|
|
|
1020
1361
|
name: parsed.name,
|
|
1021
1362
|
baseBranch: parsed.baseBranch,
|
|
1022
1363
|
folder: parsed.folder,
|
|
1023
|
-
pinned: resolvePinnedOverride(parsed) ??
|
|
1364
|
+
pinned: resolvePinnedOverride(parsed) ?? !process.env.PANE_ORCHESTRATION_SESSION_ID,
|
|
1024
1365
|
tool,
|
|
1025
1366
|
resume: parsed.resume,
|
|
1026
1367
|
launch: parsed.launch || undefined,
|
|
1027
1368
|
}],
|
|
1028
1369
|
dryRun: parsed.dryRun || undefined,
|
|
1370
|
+
waitReady: parsed.waitReady || undefined,
|
|
1371
|
+
readyTimeoutMs: parsed.readyTimeoutMs,
|
|
1029
1372
|
noFocus: parsed.noFocus || undefined,
|
|
1030
1373
|
focus: parsed.focus || undefined,
|
|
1031
1374
|
source: parsed.source === 'user' || parsed.source === 'agent' ? parsed.source : undefined,
|
|
@@ -1035,7 +1378,7 @@ async function runPanesAdopt(parsed) {
|
|
|
1035
1378
|
await confirmPaneAdopt(parsed, request);
|
|
1036
1379
|
const result = await (0, daemonClient_1.invokeDaemon)('runpane:panes:adopt', [request], exports.paneCreateResultSchema, {
|
|
1037
1380
|
paneDir: parsed.paneDir,
|
|
1038
|
-
timeoutMs: 120_000,
|
|
1381
|
+
timeoutMs: 120_000 + (request.waitReady ? (request.readyTimeoutMs ?? 30_000) : 0),
|
|
1039
1382
|
});
|
|
1040
1383
|
if (parsed.json)
|
|
1041
1384
|
printJson(result);
|
|
@@ -1044,8 +1387,11 @@ async function runPanesAdopt(parsed) {
|
|
|
1044
1387
|
return result.ok ? 0 : 1;
|
|
1045
1388
|
}
|
|
1046
1389
|
async function runPanesArchive(parsed) {
|
|
1390
|
+
if (parsed.sessionId) {
|
|
1391
|
+
return runPanesArchiveSession(parsed, parsed.sessionId);
|
|
1392
|
+
}
|
|
1047
1393
|
if (!parsed.paneId) {
|
|
1048
|
-
throw new Error('runpane panes archive requires --pane.');
|
|
1394
|
+
throw new Error('runpane panes archive requires --pane (or --session with --merged).');
|
|
1049
1395
|
}
|
|
1050
1396
|
const request = {
|
|
1051
1397
|
paneId: parsed.paneId,
|
|
@@ -1056,7 +1402,9 @@ async function runPanesArchive(parsed) {
|
|
|
1056
1402
|
request.source = parsed.source;
|
|
1057
1403
|
if (parsed.dryRun)
|
|
1058
1404
|
request.dryRun = true;
|
|
1059
|
-
|
|
1405
|
+
if (parsed.removeWorktree)
|
|
1406
|
+
request.removeWorktree = true;
|
|
1407
|
+
await confirmPaneArchive(parsed, `Archive pane ${request.paneId}${request.force ? ' (including any uncommitted or unpushed work)' : ''}`);
|
|
1060
1408
|
const result = await (0, daemonClient_1.invokeDaemon)('runpane:panes:archive', [request], paneArchiveResultSchema, {
|
|
1061
1409
|
paneDir: parsed.paneDir,
|
|
1062
1410
|
timeoutMs: 40_000,
|
|
@@ -1069,6 +1417,31 @@ async function runPanesArchive(parsed) {
|
|
|
1069
1417
|
}
|
|
1070
1418
|
return result.ok ? 0 : 1;
|
|
1071
1419
|
}
|
|
1420
|
+
async function runPanesArchiveSession(parsed, sessionId) {
|
|
1421
|
+
if (!parsed.merged) {
|
|
1422
|
+
throw new Error('runpane panes archive --session requires --merged.');
|
|
1423
|
+
}
|
|
1424
|
+
const request = { sessionId, merged: true };
|
|
1425
|
+
if (parsed.source === 'user' || parsed.source === 'agent')
|
|
1426
|
+
request.source = parsed.source;
|
|
1427
|
+
if (parsed.dryRun)
|
|
1428
|
+
request.dryRun = true;
|
|
1429
|
+
if (parsed.removeWorktree)
|
|
1430
|
+
request.removeWorktree = true;
|
|
1431
|
+
await confirmPaneArchive(parsed, `Archive every merged or pushed Pane in Session ${sessionId}`);
|
|
1432
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:panes:archive', [request], paneArchiveBulkResultSchema, {
|
|
1433
|
+
paneDir: parsed.paneDir,
|
|
1434
|
+
// Each Pane refreshes its upstream and may wait for its worktree removal.
|
|
1435
|
+
timeoutMs: 600_000,
|
|
1436
|
+
});
|
|
1437
|
+
if (parsed.json) {
|
|
1438
|
+
printJson(result);
|
|
1439
|
+
}
|
|
1440
|
+
else {
|
|
1441
|
+
printPaneArchiveBulkResult(result);
|
|
1442
|
+
}
|
|
1443
|
+
return result.ok ? 0 : 1;
|
|
1444
|
+
}
|
|
1072
1445
|
async function runPanesPin(parsed, pinned) {
|
|
1073
1446
|
if (!parsed.paneId) {
|
|
1074
1447
|
throw new Error(`runpane panes ${pinned ? 'pin' : 'unpin'} requires --pane.`);
|
|
@@ -1170,6 +1543,40 @@ async function runPanelsCreate(parsed) {
|
|
|
1170
1543
|
}
|
|
1171
1544
|
return result.ok ? 0 : 1;
|
|
1172
1545
|
}
|
|
1546
|
+
async function runPanelsOpen(parsed) {
|
|
1547
|
+
const paneId = parsed.paneId || process.env.PANE_SESSION_ID;
|
|
1548
|
+
if (!paneId) {
|
|
1549
|
+
throw new Error('runpane panels open requires --pane (or PANE_SESSION_ID from a Pane terminal).');
|
|
1550
|
+
}
|
|
1551
|
+
if (Boolean(parsed.url) === Boolean(parsed.file)) {
|
|
1552
|
+
throw new Error('runpane panels open requires exactly one of --url or --file.');
|
|
1553
|
+
}
|
|
1554
|
+
if (parsed.noFocus && parsed.focus) {
|
|
1555
|
+
throw new Error('Use either --focus or --no-focus, not both.');
|
|
1556
|
+
}
|
|
1557
|
+
const request = {
|
|
1558
|
+
paneId,
|
|
1559
|
+
url: parsed.url || undefined,
|
|
1560
|
+
filePath: parsed.file || undefined,
|
|
1561
|
+
title: parsed.title || undefined,
|
|
1562
|
+
placement: parsed.placement ?? 'split',
|
|
1563
|
+
noFocus: parsed.noFocus || undefined,
|
|
1564
|
+
focus: parsed.focus || undefined,
|
|
1565
|
+
source: parsed.source === 'user' || parsed.source === 'agent' ? parsed.source : undefined,
|
|
1566
|
+
};
|
|
1567
|
+
await confirmPanelOpen(parsed, request);
|
|
1568
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:panels:open', [request], panelOpenResultSchema, {
|
|
1569
|
+
paneDir: parsed.paneDir,
|
|
1570
|
+
});
|
|
1571
|
+
if (parsed.json) {
|
|
1572
|
+
printJson(result);
|
|
1573
|
+
}
|
|
1574
|
+
else {
|
|
1575
|
+
const target = result.url ?? result.filePath ?? result.title;
|
|
1576
|
+
console.log(`${result.reused ? 'Reused' : 'Opened'} ${result.type} panel ${result.panelId} in pane ${result.paneId} (${result.placement}): ${target}`);
|
|
1577
|
+
}
|
|
1578
|
+
return 0;
|
|
1579
|
+
}
|
|
1173
1580
|
async function runPanelsOutput(parsed) {
|
|
1174
1581
|
if (!parsed.panelId) {
|
|
1175
1582
|
throw new Error('runpane panels output requires --panel.');
|
|
@@ -1218,12 +1625,84 @@ async function runPanelsScreen(parsed) {
|
|
|
1218
1625
|
printJson(result);
|
|
1219
1626
|
return 0;
|
|
1220
1627
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1628
|
+
const text = markSuggestionLine(result.text, result.composer.ghostText);
|
|
1629
|
+
node_process_1.stdout.write(text);
|
|
1630
|
+
if (text && !text.endsWith('\n')) {
|
|
1223
1631
|
node_process_1.stdout.write('\n');
|
|
1224
1632
|
}
|
|
1225
1633
|
return 0;
|
|
1226
1634
|
}
|
|
1635
|
+
async function runPanelsLastMessage(parsed) {
|
|
1636
|
+
if (!parsed.panelId) {
|
|
1637
|
+
throw new Error('runpane panels last-message requires --panel.');
|
|
1638
|
+
}
|
|
1639
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:panels:last-message', [{
|
|
1640
|
+
panelId: parsed.panelId,
|
|
1641
|
+
limit: parsed.limit,
|
|
1642
|
+
}], panelLastMessageResultSchema, {
|
|
1643
|
+
paneDir: parsed.paneDir,
|
|
1644
|
+
});
|
|
1645
|
+
if (parsed.json) {
|
|
1646
|
+
printJson(result);
|
|
1647
|
+
}
|
|
1648
|
+
else if (result.ok) {
|
|
1649
|
+
node_process_1.stdout.write(result.text);
|
|
1650
|
+
if (result.text && !result.text.endsWith('\n'))
|
|
1651
|
+
node_process_1.stdout.write('\n');
|
|
1652
|
+
if (result.truncated)
|
|
1653
|
+
console.error(`(showing the last ${result.limit} of ${result.length} characters)`);
|
|
1654
|
+
}
|
|
1655
|
+
else {
|
|
1656
|
+
console.error(`${result.reason}: ${result.message}`);
|
|
1657
|
+
}
|
|
1658
|
+
return result.ok ? 0 : 1;
|
|
1659
|
+
}
|
|
1660
|
+
/** Where a report is for: explicit --panel (with an optional --pane), else the Pane terminal's own panel. */
|
|
1661
|
+
function resolveReportIdentity(parsed, env = process.env) {
|
|
1662
|
+
if (parsed.paneId || parsed.panelId) {
|
|
1663
|
+
if (!parsed.panelId) {
|
|
1664
|
+
throw new Error('runpane report --pane also needs --panel <panel-id>. Find it with `runpane panels list --pane <pane-id>`.');
|
|
1665
|
+
}
|
|
1666
|
+
return parsed.paneId ? { paneId: parsed.paneId, panelId: parsed.panelId } : { panelId: parsed.panelId };
|
|
1667
|
+
}
|
|
1668
|
+
const panelId = env.PANE_PANEL_ID?.trim();
|
|
1669
|
+
if (!panelId) {
|
|
1670
|
+
throw new Error('runpane report cannot tell which panel is reporting. Run it inside a Pane terminal '
|
|
1671
|
+
+ '(which sets PANE_SESSION_ID and PANE_PANEL_ID), or pass --pane <pane-id> --panel <panel-id>.');
|
|
1672
|
+
}
|
|
1673
|
+
const paneId = env.PANE_SESSION_ID?.trim();
|
|
1674
|
+
return paneId ? { paneId, panelId } : { panelId };
|
|
1675
|
+
}
|
|
1676
|
+
/** The CLIs send one character past the daemon's 16,000 so it still marks an overlong summary truncated. */
|
|
1677
|
+
const MAX_SENT_SUMMARY_LENGTH = 16_001;
|
|
1678
|
+
async function runReport(parsed, env = process.env) {
|
|
1679
|
+
const identity = resolveReportIdentity(parsed, env);
|
|
1680
|
+
const summaryText = parsed.summaryFile !== undefined
|
|
1681
|
+
? stripUtf8Bom(readInputSource(parsed.summaryFile))
|
|
1682
|
+
: parsed.summary;
|
|
1683
|
+
const summaryPath = parsed.summaryFile !== undefined && parsed.summaryFile !== '-'
|
|
1684
|
+
? node_path_1.default.resolve(parsed.summaryFile)
|
|
1685
|
+
: undefined;
|
|
1686
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:report', [{
|
|
1687
|
+
...identity,
|
|
1688
|
+
state: parsed.reportState,
|
|
1689
|
+
pr: parsed.reportPr,
|
|
1690
|
+
head: parsed.reportHead,
|
|
1691
|
+
summary: summaryText?.slice(0, MAX_SENT_SUMMARY_LENGTH),
|
|
1692
|
+
summaryPath,
|
|
1693
|
+
question: parsed.question,
|
|
1694
|
+
}], reportResultSchema, {
|
|
1695
|
+
paneDir: parsed.paneDir,
|
|
1696
|
+
});
|
|
1697
|
+
if (parsed.json) {
|
|
1698
|
+
printJson(result);
|
|
1699
|
+
}
|
|
1700
|
+
else {
|
|
1701
|
+
const sessions = result.sessionIds.length > 0 ? ` Recorded on Session ${result.sessionIds.join(', ')}.` : '';
|
|
1702
|
+
console.log(`Reported ${(0, watchLines_1.describeReport)(result.report)} for panel ${result.panelId}.${sessions}`);
|
|
1703
|
+
}
|
|
1704
|
+
return 0;
|
|
1705
|
+
}
|
|
1227
1706
|
async function runPanelsSubmit(parsed) {
|
|
1228
1707
|
const request = buildPanelInputRequest(parsed, 'submit');
|
|
1229
1708
|
await confirmPanelInput(parsed, request, 'submit');
|
|
@@ -1237,15 +1716,50 @@ async function runPanelsSubmit(parsed) {
|
|
|
1237
1716
|
const verb = result.ok ? 'Submitted' : 'Could not verify';
|
|
1238
1717
|
const verified = result.verifiedSubmitted ? ' verified' : ' unverified';
|
|
1239
1718
|
console.log(`${verb} ${result.inputBytes} byte${result.inputBytes === 1 ? '' : 's'} via ${result.sequenceName} to panel ${result.panelId}.${verified}`);
|
|
1719
|
+
printDelivery(result.delivery);
|
|
1240
1720
|
if (result.blocked) {
|
|
1241
1721
|
console.log(`Blocked: ${result.blocked.message}`);
|
|
1242
1722
|
}
|
|
1723
|
+
printPromptNotes(result);
|
|
1243
1724
|
if (result.nextCommand) {
|
|
1244
1725
|
console.log(`Next: ${result.nextCommand}`);
|
|
1245
1726
|
}
|
|
1246
1727
|
}
|
|
1247
1728
|
return result.ok ? 0 : 1;
|
|
1248
1729
|
}
|
|
1730
|
+
/** Where the prompt went, for human output: `Delivery: queued (transcript)`. */
|
|
1731
|
+
function printDelivery(delivery, prefix = '') {
|
|
1732
|
+
if (delivery) {
|
|
1733
|
+
console.log(`${prefix}Delivery: ${delivery.state} (${delivery.evidence})`);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Mark the composer line that shows ghost text (a placeholder or the agent's
|
|
1738
|
+
* suggested next prompt), so it does not read as typed input.
|
|
1739
|
+
*/
|
|
1740
|
+
function markSuggestionLine(text, ghostText) {
|
|
1741
|
+
const ghost = ghostText?.split('\n')[0]?.trim();
|
|
1742
|
+
if (!ghost)
|
|
1743
|
+
return text;
|
|
1744
|
+
const lines = text.split('\n');
|
|
1745
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
1746
|
+
const line = lines[index].trim();
|
|
1747
|
+
if (/^[❯›>]/u.test(line) && line.includes(ghost)) {
|
|
1748
|
+
lines[index] = `${lines[index].trimEnd()} ⟨suggestion⟩`;
|
|
1749
|
+
break;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
return lines.join('\n');
|
|
1753
|
+
}
|
|
1754
|
+
/** The prompt file Pane wrote and any leading-character warnings, for human output. */
|
|
1755
|
+
function printPromptNotes(result, prefix = '') {
|
|
1756
|
+
if (result.promptFile) {
|
|
1757
|
+
console.log(`${prefix}Prompt file: ${result.promptFile}`);
|
|
1758
|
+
}
|
|
1759
|
+
for (const warning of result.warnings ?? []) {
|
|
1760
|
+
console.log(`${prefix}Warning (${warning.code}): ${warning.message}`);
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1249
1763
|
async function runPanelsSubmitComposer(parsed) {
|
|
1250
1764
|
if (!parsed.panelId) {
|
|
1251
1765
|
throw new Error('runpane panels submit-composer requires --panel.');
|
|
@@ -1263,6 +1777,7 @@ async function runPanelsSubmitComposer(parsed) {
|
|
|
1263
1777
|
else {
|
|
1264
1778
|
const verified = result.verifiedSubmitted ? ' verified' : ' unverified';
|
|
1265
1779
|
console.log(`${result.ok ? 'Submitted' : 'Could not verify'} composer with ${result.sequenceName} to panel ${result.panelId}.${verified}`);
|
|
1780
|
+
printDelivery(result.delivery);
|
|
1266
1781
|
if (result.blocked) {
|
|
1267
1782
|
console.log(`Blocked: ${result.blocked.message}`);
|
|
1268
1783
|
}
|
|
@@ -1332,11 +1847,15 @@ function buildPanelInputRequest(parsed, command = 'input') {
|
|
|
1332
1847
|
throw new Error(`runpane panels ${command} requires --text, --keys, or --input-file.`);
|
|
1333
1848
|
}
|
|
1334
1849
|
if (parsed.keys !== undefined && command !== 'input') {
|
|
1335
|
-
throw new Error('--keys is for panels input; panels submit sends text followed by
|
|
1850
|
+
throw new Error('--keys is for panels input; panels submit sends text followed by the agent submit key.');
|
|
1851
|
+
}
|
|
1852
|
+
if (parsed.asFilePointer && command !== 'submit') {
|
|
1853
|
+
throw new Error('--as-file-pointer is for panels submit; panels input sends exact bytes.');
|
|
1336
1854
|
}
|
|
1337
1855
|
return {
|
|
1338
1856
|
panelId: parsed.panelId,
|
|
1339
1857
|
input: parsed.keys ? keysToBytes(parsed.keys) : parsed.panelInputFile ? readInputSource(parsed.panelInputFile) : parsed.panelInput ?? '',
|
|
1858
|
+
asFilePointer: parsed.asFilePointer || undefined,
|
|
1340
1859
|
};
|
|
1341
1860
|
}
|
|
1342
1861
|
/** `--keys down,enter`: named keys from the contract, or a single literal character each. */
|
|
@@ -1398,9 +1917,9 @@ async function buildPaneCreateRequest(parsed) {
|
|
|
1398
1917
|
request.concurrency = parsed.concurrency;
|
|
1399
1918
|
}
|
|
1400
1919
|
const pinnedOverride = resolvePinnedOverride(parsed);
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
}
|
|
1920
|
+
request.panes = request.panes.map(item => ({
|
|
1921
|
+
...item, pinned: pinnedOverride ?? item.pinned ?? !process.env.PANE_ORCHESTRATION_SESSION_ID,
|
|
1922
|
+
}));
|
|
1404
1923
|
applyPaneFocusOptions(parsed, request);
|
|
1405
1924
|
request.associateSession = parsed.noAssociate ? undefined : resolveAssociateSession(parsed) ?? request.associateSession;
|
|
1406
1925
|
return request;
|
|
@@ -1421,8 +1940,9 @@ async function buildPaneCreateRequest(parsed) {
|
|
|
1421
1940
|
panes: [{
|
|
1422
1941
|
name: parsed.name,
|
|
1423
1942
|
worktreeName: parsed.worktreeName,
|
|
1943
|
+
branch: parsed.branch,
|
|
1424
1944
|
baseBranch: parsed.baseBranch,
|
|
1425
|
-
pinned: resolvePinnedOverride(parsed) ??
|
|
1945
|
+
pinned: resolvePinnedOverride(parsed) ?? !process.env.PANE_ORCHESTRATION_SESSION_ID,
|
|
1426
1946
|
tool,
|
|
1427
1947
|
}],
|
|
1428
1948
|
dryRun: parsed.dryRun || undefined,
|
|
@@ -1478,10 +1998,22 @@ async function confirmRepoAdd(parsed, request) {
|
|
|
1478
1998
|
}
|
|
1479
1999
|
}
|
|
1480
2000
|
async function buildToolSpec(parsed, command = 'panes create') {
|
|
1481
|
-
if (parsed.agent && parsed.toolCommand) {
|
|
1482
|
-
throw new Error('Use either --agent or --tool-command, not both.');
|
|
1483
|
-
}
|
|
1484
2001
|
const initialInput = resolveInitialInput(parsed);
|
|
2002
|
+
if (parsed.asFilePointer && initialInput === undefined) {
|
|
2003
|
+
throw new Error(`--as-file-pointer needs a prompt: pass --prompt or --initial-input-file to runpane ${command}.`);
|
|
2004
|
+
}
|
|
2005
|
+
const initialInputAsFilePointer = parsed.asFilePointer || undefined;
|
|
2006
|
+
// With --tool-command, --agent names the agent the command runs (a wrapper
|
|
2007
|
+
// such as `agent-farm run`); Pane launches the command unchanged.
|
|
2008
|
+
if (parsed.toolCommand && parsed.agent) {
|
|
2009
|
+
return {
|
|
2010
|
+
command: parsed.toolCommand,
|
|
2011
|
+
agentType: parsed.agent,
|
|
2012
|
+
title: parsed.title,
|
|
2013
|
+
initialInput,
|
|
2014
|
+
initialInputAsFilePointer,
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
1485
2017
|
let agent = parsed.agent;
|
|
1486
2018
|
if (!agent && !parsed.toolCommand) {
|
|
1487
2019
|
if (!isInteractiveShell()) {
|
|
@@ -1494,6 +2026,7 @@ async function buildToolSpec(parsed, command = 'panes create') {
|
|
|
1494
2026
|
agent,
|
|
1495
2027
|
title: parsed.title,
|
|
1496
2028
|
initialInput,
|
|
2029
|
+
initialInputAsFilePointer,
|
|
1497
2030
|
};
|
|
1498
2031
|
}
|
|
1499
2032
|
if (!parsed.toolCommand) {
|
|
@@ -1503,11 +2036,12 @@ async function buildToolSpec(parsed, command = 'panes create') {
|
|
|
1503
2036
|
command: parsed.toolCommand,
|
|
1504
2037
|
title: parsed.title,
|
|
1505
2038
|
initialInput,
|
|
2039
|
+
initialInputAsFilePointer,
|
|
1506
2040
|
};
|
|
1507
2041
|
}
|
|
1508
2042
|
function resolveInitialInput(parsed) {
|
|
1509
2043
|
if (parsed.initialInput && parsed.initialInputFile) {
|
|
1510
|
-
throw new Error('Use either --initial-input/--prompt or --initial-input-file, not both.');
|
|
2044
|
+
throw new Error('Use either --initial-input/--prompt or --initial-input-file/--prompt-file, not both.');
|
|
1511
2045
|
}
|
|
1512
2046
|
if (parsed.initialInputFile) {
|
|
1513
2047
|
return readInputSource(parsed.initialInputFile);
|
|
@@ -1549,7 +2083,7 @@ async function confirmPaneAdopt(parsed, request) {
|
|
|
1549
2083
|
rl.close();
|
|
1550
2084
|
}
|
|
1551
2085
|
}
|
|
1552
|
-
async function confirmPaneArchive(parsed,
|
|
2086
|
+
async function confirmPaneArchive(parsed, question) {
|
|
1553
2087
|
if (parsed.dryRun || parsed.yes) {
|
|
1554
2088
|
return;
|
|
1555
2089
|
}
|
|
@@ -1558,8 +2092,7 @@ async function confirmPaneArchive(parsed, request) {
|
|
|
1558
2092
|
}
|
|
1559
2093
|
const rl = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
1560
2094
|
try {
|
|
1561
|
-
const
|
|
1562
|
-
const answer = (await rl.question(`Archive pane ${request.paneId}${suffix}? [y/N] `)).trim().toLowerCase();
|
|
2095
|
+
const answer = (await rl.question(`${question}? [y/N] `)).trim().toLowerCase();
|
|
1563
2096
|
if (answer !== 'y' && answer !== 'yes') {
|
|
1564
2097
|
throw new Error('Cancelled.');
|
|
1565
2098
|
}
|
|
@@ -1624,6 +2157,24 @@ async function confirmPaneFocus(parsed, request) {
|
|
|
1624
2157
|
rl.close();
|
|
1625
2158
|
}
|
|
1626
2159
|
}
|
|
2160
|
+
async function confirmPanelOpen(parsed, request) {
|
|
2161
|
+
if (parsed.yes) {
|
|
2162
|
+
return;
|
|
2163
|
+
}
|
|
2164
|
+
if (!isInteractiveShell()) {
|
|
2165
|
+
throw new Error('runpane panels open mutates Pane state. Rerun with --yes in non-interactive shells.');
|
|
2166
|
+
}
|
|
2167
|
+
const rl = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
2168
|
+
try {
|
|
2169
|
+
const answer = (await rl.question(`Open ${request.url ?? request.filePath} in pane ${request.paneId}? [y/N] `)).trim().toLowerCase();
|
|
2170
|
+
if (answer !== 'y' && answer !== 'yes') {
|
|
2171
|
+
throw new Error('Cancelled.');
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
finally {
|
|
2175
|
+
rl.close();
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
1627
2178
|
async function confirmPanelCreate(parsed, request) {
|
|
1628
2179
|
if (parsed.yes) {
|
|
1629
2180
|
return;
|
|
@@ -1735,6 +2286,12 @@ function workspaceLabel(kind) {
|
|
|
1735
2286
|
'pane.created': 'NEW',
|
|
1736
2287
|
'pane.gone': 'GONE',
|
|
1737
2288
|
'panel.exited': 'EXIT',
|
|
2289
|
+
'pane.associated': 'JOINED',
|
|
2290
|
+
'pane.detached': 'LEFT',
|
|
2291
|
+
'pr.conflicted': 'PR CONFLICTED',
|
|
2292
|
+
'pr.checks': 'PR CHECKS',
|
|
2293
|
+
'pr.merged': 'PR MERGED',
|
|
2294
|
+
'agent.report': 'REPORT',
|
|
1738
2295
|
};
|
|
1739
2296
|
return labels[kind];
|
|
1740
2297
|
}
|
|
@@ -1804,6 +2361,7 @@ function printPaneCreateResult(result) {
|
|
|
1804
2361
|
? ` Associated with Session ${item.association.sessionId}`
|
|
1805
2362
|
: ` Not associated with Session ${item.association.sessionId}: ${item.association.error ?? 'unknown error'}`);
|
|
1806
2363
|
}
|
|
2364
|
+
printPromptNotes(item, ' ');
|
|
1807
2365
|
if (item.nextCommand) {
|
|
1808
2366
|
console.log(` Next: ${item.nextCommand}`);
|
|
1809
2367
|
}
|
|
@@ -1828,11 +2386,44 @@ function printPaneArchiveResult(result) {
|
|
|
1828
2386
|
console.error(`Next: ${result.nextCommand}`);
|
|
1829
2387
|
return;
|
|
1830
2388
|
}
|
|
1831
|
-
|
|
2389
|
+
const trash = result.trashDeletion === 'pending' ? ' (files are still being deleted in the background)' : '';
|
|
2390
|
+
console.log(`Archived pane ${result.paneId}${result.forced ? ' (forced)' : ''}. Worktree cleanup: ${result.worktreeCleanup}${trash}.`);
|
|
2391
|
+
printArchiveSkipReason(result.safetyCheck);
|
|
2392
|
+
if (result.safetyCheck.mergedViaPr) {
|
|
2393
|
+
console.log(`Merged via PR #${result.safetyCheck.mergedViaPr.number} (head ${result.safetyCheck.mergedViaPr.headOid}).`);
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
function printPaneArchiveBulkResult(result) {
|
|
2397
|
+
const verb = result.dryRun ? 'Would archive' : 'Archived';
|
|
2398
|
+
console.log(`${verb} ${result.archived} Pane(s) in Session ${result.sessionId}; skipped ${result.skipped}; failed ${result.failed}.`);
|
|
2399
|
+
for (const item of result.items) {
|
|
2400
|
+
const label = item.name ? `${item.name} (${item.paneId})` : item.paneId;
|
|
2401
|
+
if (item.outcome === 'skipped') {
|
|
2402
|
+
console.log(` skipped ${label}: ${item.skipped?.code ?? 'unknown'} - ${item.skipped?.message ?? ''}`);
|
|
2403
|
+
}
|
|
2404
|
+
else if (item.outcome === 'failed') {
|
|
2405
|
+
console.error(` failed ${label}: ${item.error ?? 'unknown error'}`);
|
|
2406
|
+
}
|
|
2407
|
+
else {
|
|
2408
|
+
const merged = item.safetyCheck?.mergedViaPr ? ` merged via PR #${item.safetyCheck.mergedViaPr.number}` : '';
|
|
2409
|
+
const trash = item.trashDeletion === 'pending' ? ', files deleting in background' : '';
|
|
2410
|
+
const cleanup = item.worktreeCleanup ? ` worktree ${item.worktreeCleanup}${trash}` : '';
|
|
2411
|
+
console.log(` ${item.outcome} ${label}${merged}${cleanup}`);
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
function printArchiveSkipReason(safetyCheck, print = console.log) {
|
|
2416
|
+
if (!safetyCheck.reason)
|
|
2417
|
+
return;
|
|
2418
|
+
print(`Safety check skipped: ${safetyCheck.reason}${safetyCheck.worktreeWillRemain ? '; the worktree stays on disk' : ''}.`);
|
|
1832
2419
|
}
|
|
1833
2420
|
function printArchiveCommitEvidence(safetyCheck, print = console.log) {
|
|
2421
|
+
printArchiveSkipReason(safetyCheck, print);
|
|
1834
2422
|
if (safetyCheck.upstream) {
|
|
1835
|
-
print(`Upstream: ${safetyCheck.upstream}${safetyCheck.upstreamRefreshed ? ' (refreshed)' : ''}`);
|
|
2423
|
+
print(`Upstream: ${safetyCheck.upstream}${safetyCheck.upstreamRefreshed ? ' (refreshed)' : ''}${safetyCheck.upstreamGone ? ' (gone from the remote)' : ''}`);
|
|
2424
|
+
}
|
|
2425
|
+
if (safetyCheck.mergedViaPr) {
|
|
2426
|
+
print(`Merged via PR #${safetyCheck.mergedViaPr.number} (head ${safetyCheck.mergedViaPr.headOid})`);
|
|
1836
2427
|
}
|
|
1837
2428
|
for (const commit of safetyCheck.unpushedCommitDetails ?? []) {
|
|
1838
2429
|
print(`Unpushed: ${commit.sha} ${commit.subject}`);
|
|
@@ -1847,6 +2438,7 @@ function printPanelCreateResult(result) {
|
|
|
1847
2438
|
}
|
|
1848
2439
|
}
|
|
1849
2440
|
printInitialInputDelivery(result.initialInput);
|
|
2441
|
+
printPromptNotes(result);
|
|
1850
2442
|
if (result.nextCommand) {
|
|
1851
2443
|
console.log(`Next: ${result.nextCommand}`);
|
|
1852
2444
|
}
|
|
@@ -1864,6 +2456,7 @@ function printInitialInputDelivery(initialInput, prefix = '') {
|
|
|
1864
2456
|
const attempts = initialInput.attempts === undefined ? '' : ` after ${initialInput.attempts} attempt${initialInput.attempts === 1 ? '' : 's'}`;
|
|
1865
2457
|
const staged = initialInput.staged === undefined ? '' : `; staged: ${initialInput.staged ? 'yes' : 'no'}`;
|
|
1866
2458
|
console.log(`${prefix}Initial input: ${status}${strategy}${attempts}${staged}`);
|
|
2459
|
+
printDelivery(initialInput.delivery, prefix);
|
|
1867
2460
|
if (initialInput.blocked) {
|
|
1868
2461
|
console.log(`${prefix}Initial input blocked: ${initialInput.blocked.message}`);
|
|
1869
2462
|
}
|
|
@@ -1923,7 +2516,8 @@ function printPanelListResult(result) {
|
|
|
1923
2516
|
const marker = panel.active ? '*' : ' ';
|
|
1924
2517
|
const initialized = panel.initialized === undefined ? '' : panel.initialized ? ' initialized' : ' not-initialized';
|
|
1925
2518
|
const agent = panel.agentType ? ` ${panel.agentType}` : '';
|
|
1926
|
-
|
|
2519
|
+
const detection = panel.agentDetection && panel.agentDetection !== 'command' ? ` (${panel.agentDetection})` : '';
|
|
2520
|
+
console.log(`${marker} ${panel.id}\t${panel.type}\t${panel.title}${initialized}${agent}${detection}`);
|
|
1927
2521
|
}
|
|
1928
2522
|
}
|
|
1929
2523
|
function isInteractiveShell() {
|
|
@@ -1949,6 +2543,7 @@ function parsePaneCreateItemPayload(value, index) {
|
|
|
1949
2543
|
return {
|
|
1950
2544
|
name: value.name,
|
|
1951
2545
|
worktreeName: value.worktreeName,
|
|
2546
|
+
branch: value.branch,
|
|
1952
2547
|
baseBranch: value.baseBranch,
|
|
1953
2548
|
sessionPrompt: value.sessionPrompt,
|
|
1954
2549
|
pinned: value.pinned,
|
|
@@ -1968,13 +2563,23 @@ function parsePaneToolSpecPayload(value, index) {
|
|
|
1968
2563
|
agent,
|
|
1969
2564
|
title: value.title,
|
|
1970
2565
|
initialInput: value.initialInput,
|
|
2566
|
+
initialInputAsFilePointer: value.initialInputAsFilePointer,
|
|
1971
2567
|
};
|
|
1972
2568
|
}
|
|
1973
2569
|
if (value.command !== undefined && value.command.trim().length > 0) {
|
|
2570
|
+
let agentType;
|
|
2571
|
+
try {
|
|
2572
|
+
agentType = value.agentType === undefined ? undefined : (0, boundaryDecoder_1.decodeBoundary)(value.agentType, agentSchema);
|
|
2573
|
+
}
|
|
2574
|
+
catch {
|
|
2575
|
+
throw new Error(`--from-json pane ${index} includes an unsupported agentType.`);
|
|
2576
|
+
}
|
|
1974
2577
|
return {
|
|
1975
2578
|
command: value.command,
|
|
2579
|
+
agentType,
|
|
1976
2580
|
title: value.title,
|
|
1977
2581
|
initialInput: value.initialInput,
|
|
2582
|
+
initialInputAsFilePointer: value.initialInputAsFilePointer,
|
|
1978
2583
|
};
|
|
1979
2584
|
}
|
|
1980
2585
|
throw new Error(`--from-json pane ${index} tool must include agent or command.`);
|