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.
@@ -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: boundaryDecoder_1.boundary.enumeration('uncommitted-changes', 'unpushed-commits', 'uncommitted-and-unpushed', 'status-unknown'),
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: boundaryDecoder_1.boundary.enumeration('uncommitted-changes', 'unpushed-commits', 'uncommitted-and-unpushed', 'status-unknown'),
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: boundaryDecoder_1.boundary.enumeration('completed', 'failed', 'timeout', 'not-applicable'),
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 && format === 'lines' ? true : undefined;
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 ? process.env.PANE_PANEL_ID || (cadenceValueFlagPresent ? `follow-${process.pid}` : undefined) : undefined);
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
- emitWatchLine((0, watchLines_1.formatNonEntry)('_reconnected', { generation: result.generation }, format));
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
- emitWatchLine((0, watchLines_1.formatNonEntry)('_ok', { generation: result.generation, epoch: result.epoch }, format));
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
- emitWatchLine((0, watchLines_1.formatNonEntry)('_heartbeat', {
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) ?? true,
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
- await confirmPaneArchive(parsed, request);
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
- node_process_1.stdout.write(result.text);
1222
- if (result.text && !result.text.endsWith('\n')) {
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 Enter.');
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
- if (pinnedOverride !== undefined) {
1402
- request.panes = request.panes.map(item => ({ ...item, pinned: pinnedOverride }));
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) ?? true,
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, request) {
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 suffix = request.force ? ' (including any uncommitted or unpushed work)' : '';
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
- console.log(`Archived pane ${result.paneId}${result.forced ? ' (forced)' : ''}. Worktree cleanup: ${result.worktreeCleanup}.`);
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
- console.log(`${marker} ${panel.id}\t${panel.type}\t${panel.title}${initialized}${agent}`);
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.`);