runpane 2.4.180 → 2.4.181
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 +28 -1
- package/dist/agentTasks.d.ts.map +1 -1
- package/dist/agentTasks.js +8 -3
- package/dist/agentTasks.js.map +1 -1
- package/dist/boundaryDecoder.d.ts +32 -0
- package/dist/boundaryDecoder.d.ts.map +1 -1
- package/dist/boundaryDecoder.js +90 -6
- package/dist/boundaryDecoder.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +3 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +21 -0
- package/dist/commands.js.map +1 -1
- package/dist/docs-index.json +1 -1
- package/dist/generated/contract.d.ts +572 -57
- package/dist/generated/contract.d.ts.map +1 -1
- package/dist/generated/contract.js +953 -116
- package/dist/generated/contract.js.map +1 -1
- package/dist/handoff.d.ts.map +1 -1
- package/dist/handoff.js +96 -1
- package/dist/handoff.js.map +1 -1
- package/dist/localControl.d.ts +93 -1
- package/dist/localControl.d.ts.map +1 -1
- package/dist/localControl.js +275 -79
- package/dist/localControl.js.map +1 -1
- package/dist/mcpTools.d.ts.map +1 -1
- package/dist/mcpTools.js +3 -2
- package/dist/mcpTools.js.map +1 -1
- package/dist/sessionPayload.d.ts +77 -0
- package/dist/sessionPayload.d.ts.map +1 -0
- package/dist/sessionPayload.js +99 -0
- package/dist/sessionPayload.js.map +1 -0
- package/dist/watchLines.d.ts +1 -1
- package/dist/watchLines.d.ts.map +1 -1
- package/dist/watchLines.js +4 -1
- package/dist/watchLines.js.map +1 -1
- package/package.json +1 -1
package/dist/localControl.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.workspaceStateResultSchema = exports.panelSubmitResultSchema = exports.panelScreenResultSchema = exports.panelCreateResultSchema = exports.panelListResultSchema = exports.paneCreateResultSchema = exports.paneListResultSchema = exports.repoListResultSchema = void 0;
|
|
6
|
+
exports.workspaceStateResultSchema = exports.panelSubmitResultSchema = exports.panelScreenResultSchema = exports.panelCreateResultSchema = exports.panelListResultSchema = exports.paneCreateResultSchema = exports.runpaneSessionResultSchema = exports.runpaneSessionListResultSchema = exports.paneListResultSchema = exports.repoListResultSchema = void 0;
|
|
7
7
|
exports.runReposList = runReposList;
|
|
8
8
|
exports.runReposAdd = runReposAdd;
|
|
9
9
|
exports.runPanesList = runPanesList;
|
|
@@ -41,6 +41,7 @@ exports.markSuggestionLine = markSuggestionLine;
|
|
|
41
41
|
exports.printPromptNotes = printPromptNotes;
|
|
42
42
|
exports.runPanelsSubmitComposer = runPanelsSubmitComposer;
|
|
43
43
|
exports.runPanelsWait = runPanelsWait;
|
|
44
|
+
exports.runPanelsResume = runPanelsResume;
|
|
44
45
|
exports.runAgentsDoctor = runAgentsDoctor;
|
|
45
46
|
exports.buildPanelInputRequest = buildPanelInputRequest;
|
|
46
47
|
exports.buildPanelCreateRequest = buildPanelCreateRequest;
|
|
@@ -54,6 +55,7 @@ const boundaryDecoder_1 = require("./boundaryDecoder");
|
|
|
54
55
|
const daemonClient_1 = require("./daemonClient");
|
|
55
56
|
const contract_1 = require("./generated/contract");
|
|
56
57
|
const commands_1 = require("./commands");
|
|
58
|
+
const sessionPayload_1 = require("./sessionPayload");
|
|
57
59
|
const watchLines_1 = require("./watchLines");
|
|
58
60
|
const agentSchema = boundaryDecoder_1.boundary.enumeration(...contract_1.RUNPANE_CONTRACT.enums.agents);
|
|
59
61
|
const orchestrationAgentSchema = boundaryDecoder_1.boundary.enumeration('claude', 'codex', 'cursor');
|
|
@@ -96,6 +98,7 @@ const panelBlockedSchema = boundaryDecoder_1.boundary.object({
|
|
|
96
98
|
});
|
|
97
99
|
const panelStateSchema = boundaryDecoder_1.boundary.object({
|
|
98
100
|
initialized: boundaryDecoder_1.boundary.boolean,
|
|
101
|
+
running: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
99
102
|
isAlternateScreen: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
100
103
|
activityStatus: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('active', 'idle')),
|
|
101
104
|
isCliReady: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
@@ -103,6 +106,10 @@ const panelStateSchema = boundaryDecoder_1.boundary.object({
|
|
|
103
106
|
agentType: boundaryDecoder_1.boundary.optional(agentSchema),
|
|
104
107
|
lastActivity: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
105
108
|
});
|
|
109
|
+
const panelReadinessReasonSchema = boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({
|
|
110
|
+
code: boundaryDecoder_1.boundary.enumeration('no-agent-detected', 'agent-not-ready', 'command-exited'),
|
|
111
|
+
message: boundaryDecoder_1.boundary.string,
|
|
112
|
+
}));
|
|
106
113
|
const panelReadinessSchema = boundaryDecoder_1.boundary.object({
|
|
107
114
|
ok: boundaryDecoder_1.boundary.boolean,
|
|
108
115
|
condition: boundaryDecoder_1.boundary.string,
|
|
@@ -111,6 +118,7 @@ const panelReadinessSchema = boundaryDecoder_1.boundary.object({
|
|
|
111
118
|
elapsedMs: boundaryDecoder_1.boundary.number,
|
|
112
119
|
state: panelStateSchema,
|
|
113
120
|
blocked: boundaryDecoder_1.boundary.optional(panelBlockedSchema),
|
|
121
|
+
reason: panelReadinessReasonSchema,
|
|
114
122
|
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
115
123
|
});
|
|
116
124
|
const verificationSchema = boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('observed', 'unverifiable'));
|
|
@@ -180,6 +188,7 @@ const reportResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
180
188
|
panelId: boundaryDecoder_1.boundary.string,
|
|
181
189
|
report: agentReportSchema,
|
|
182
190
|
sessionIds: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string),
|
|
191
|
+
liveWatchers: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
183
192
|
});
|
|
184
193
|
const panelLastMessageResultSchema = boundaryDecoder_1.boundary.union(boundaryDecoder_1.boundary.object({
|
|
185
194
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
@@ -208,14 +217,18 @@ const panelSummarySchema = boundaryDecoder_1.boundary.object({
|
|
|
208
217
|
title: boundaryDecoder_1.boundary.string,
|
|
209
218
|
active: boundaryDecoder_1.boundary.boolean,
|
|
210
219
|
initialized: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
220
|
+
running: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
211
221
|
agentType: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
212
222
|
agentDetection: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('declared', 'command', 'process', 'screen')),
|
|
213
223
|
launchCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
214
224
|
isCliPanel: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
225
|
+
dock: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
215
226
|
position: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
216
227
|
createdAt: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
217
228
|
lastActiveAt: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
218
229
|
report: boundaryDecoder_1.boundary.optional(agentReportSchema),
|
|
230
|
+
resumeId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
231
|
+
resumeSource: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('agent-farm', 'configured', 'agent')),
|
|
219
232
|
});
|
|
220
233
|
exports.repoListResultSchema = boundaryDecoder_1.boundary.object({
|
|
221
234
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
@@ -293,12 +306,12 @@ const orchestrationSessionRecordSchema = boundaryDecoder_1.boundary.object({
|
|
|
293
306
|
createdAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
294
307
|
updatedAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
295
308
|
});
|
|
296
|
-
|
|
309
|
+
exports.runpaneSessionListResultSchema = boundaryDecoder_1.boundary.object({
|
|
297
310
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
298
311
|
sessions: boundaryDecoder_1.boundary.array(orchestrationSessionRecordSchema),
|
|
299
312
|
selectedSessionId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nonEmptyString),
|
|
300
313
|
});
|
|
301
|
-
|
|
314
|
+
exports.runpaneSessionResultSchema = boundaryDecoder_1.boundary.object({
|
|
302
315
|
ok: boundaryDecoder_1.boundary.literal(true),
|
|
303
316
|
session: orchestrationSessionRecordSchema,
|
|
304
317
|
panelId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nonEmptyString),
|
|
@@ -507,6 +520,12 @@ exports.paneCreateResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
507
520
|
position: boundaryDecoder_1.boundary.number,
|
|
508
521
|
message: boundaryDecoder_1.boundary.string,
|
|
509
522
|
})),
|
|
523
|
+
base: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.object({
|
|
524
|
+
ref: boundaryDecoder_1.boundary.string,
|
|
525
|
+
commit: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
526
|
+
refresh: boundaryDecoder_1.boundary.enumeration('fetched', 'recent', 'skipped', 'failed'),
|
|
527
|
+
notice: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
528
|
+
})),
|
|
510
529
|
}), boundaryDecoder_1.boundary.object({
|
|
511
530
|
ok: boundaryDecoder_1.boundary.literal(false),
|
|
512
531
|
index: boundaryDecoder_1.boundary.number,
|
|
@@ -620,6 +639,45 @@ exports.panelListResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
620
639
|
paneId: boundaryDecoder_1.boundary.string,
|
|
621
640
|
panels: boundaryDecoder_1.boundary.array(panelSummarySchema),
|
|
622
641
|
});
|
|
642
|
+
const panelResumeManyResultSchema = boundaryDecoder_1.boundary.object({
|
|
643
|
+
ok: boundaryDecoder_1.boundary.boolean,
|
|
644
|
+
scope: boundaryDecoder_1.boundary.object({
|
|
645
|
+
kind: boundaryDecoder_1.boundary.enumeration('session', 'all-stopped'),
|
|
646
|
+
sessionId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
647
|
+
sessionName: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
648
|
+
}),
|
|
649
|
+
resumed: boundaryDecoder_1.boundary.number,
|
|
650
|
+
alreadyRunning: boundaryDecoder_1.boundary.number,
|
|
651
|
+
failed: boundaryDecoder_1.boundary.number,
|
|
652
|
+
notReady: boundaryDecoder_1.boundary.number,
|
|
653
|
+
concurrency: boundaryDecoder_1.boundary.number,
|
|
654
|
+
items: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.object({
|
|
655
|
+
ok: boundaryDecoder_1.boundary.boolean,
|
|
656
|
+
panelId: boundaryDecoder_1.boundary.string,
|
|
657
|
+
paneId: boundaryDecoder_1.boundary.string,
|
|
658
|
+
paneName: boundaryDecoder_1.boundary.string,
|
|
659
|
+
panelTitle: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
660
|
+
agentType: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
661
|
+
action: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('resumed', 'already-running')),
|
|
662
|
+
message: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
663
|
+
agentSessionId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
664
|
+
readiness: boundaryDecoder_1.boundary.optional(panelReadinessSchema),
|
|
665
|
+
error: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
666
|
+
})),
|
|
667
|
+
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
668
|
+
});
|
|
669
|
+
const panelResumeResultSchema = boundaryDecoder_1.boundary.object({
|
|
670
|
+
ok: boundaryDecoder_1.boundary.boolean,
|
|
671
|
+
panelId: boundaryDecoder_1.boundary.string,
|
|
672
|
+
paneId: boundaryDecoder_1.boundary.string,
|
|
673
|
+
action: boundaryDecoder_1.boundary.enumeration('resumed', 'already-running'),
|
|
674
|
+
message: boundaryDecoder_1.boundary.string,
|
|
675
|
+
agentType: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
676
|
+
agentSessionId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
677
|
+
panel: panelSummarySchema,
|
|
678
|
+
readiness: boundaryDecoder_1.boundary.optional(panelReadinessSchema),
|
|
679
|
+
nextCommand: boundaryDecoder_1.boundary.string,
|
|
680
|
+
});
|
|
623
681
|
exports.panelCreateResultSchema = boundaryDecoder_1.boundary.object({
|
|
624
682
|
ok: boundaryDecoder_1.boundary.boolean,
|
|
625
683
|
generation: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
@@ -719,6 +777,8 @@ const panelWaitResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
719
777
|
elapsedMs: boundaryDecoder_1.boundary.number,
|
|
720
778
|
state: panelStateSchema,
|
|
721
779
|
blocked: boundaryDecoder_1.boundary.optional(panelBlockedSchema),
|
|
780
|
+
reason: panelReadinessReasonSchema,
|
|
781
|
+
stopped: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
722
782
|
nextCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
723
783
|
panelId: boundaryDecoder_1.boundary.string,
|
|
724
784
|
paneId: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
@@ -744,13 +804,14 @@ const agentDoctorResultSchema = boundaryDecoder_1.boundary.object({
|
|
|
744
804
|
})),
|
|
745
805
|
warnings: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
746
806
|
});
|
|
747
|
-
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');
|
|
807
|
+
const workspaceEntryKindSchema = boundaryDecoder_1.boundary.enumeration('agent.ready', 'agent.busy', 'agent.blocked', 'agent.unknown', 'agent.idle', 'pane.created', 'pane.gone', 'panel.exited', 'panel.stopped', 'pane.associated', 'pane.detached', 'pr.conflicted', 'pr.checks', 'pr.merged', 'agent.report');
|
|
748
808
|
const agentStateSchema = boundaryDecoder_1.boundary.enumeration('blocked', 'working', 'idle', 'unknown');
|
|
749
809
|
const workspacePanelSummarySchema = boundaryDecoder_1.boundary.object({
|
|
750
810
|
panelId: boundaryDecoder_1.boundary.string,
|
|
751
811
|
title: boundaryDecoder_1.boundary.string,
|
|
752
812
|
agentType: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
753
813
|
agentState: boundaryDecoder_1.boundary.optional(agentStateSchema),
|
|
814
|
+
running: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
754
815
|
});
|
|
755
816
|
const workspaceEntrySchema = boundaryDecoder_1.boundary.object({
|
|
756
817
|
gen: boundaryDecoder_1.boundary.number,
|
|
@@ -774,6 +835,7 @@ const workspaceEntrySchema = boundaryDecoder_1.boundary.object({
|
|
|
774
835
|
heldInput: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
775
836
|
heldInputPresent: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
776
837
|
exitCode: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
838
|
+
running: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
777
839
|
baseline: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
778
840
|
replay: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.literal(true)),
|
|
779
841
|
changedWhileAway: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
@@ -901,7 +963,7 @@ async function runPanesList(parsed) {
|
|
|
901
963
|
return 0;
|
|
902
964
|
}
|
|
903
965
|
async function runSessionsList(parsed) {
|
|
904
|
-
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:list', [], runpaneSessionListResultSchema, {
|
|
966
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:list', [], exports.runpaneSessionListResultSchema, {
|
|
905
967
|
paneDir: parsed.paneDir,
|
|
906
968
|
});
|
|
907
969
|
if (parsed.json) {
|
|
@@ -918,15 +980,15 @@ async function runSessionsList(parsed) {
|
|
|
918
980
|
async function runSessionsCreate(parsed) {
|
|
919
981
|
if (!parsed.fromJson)
|
|
920
982
|
throw new Error('runpane sessions create requires --from-json <path|->.');
|
|
921
|
-
const input = parseSessionCreatePayload(JSON.parse(stripUtf8Bom(readInputSource(parsed.fromJson))));
|
|
922
|
-
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:create', [input], runpaneSessionResultSchema, {
|
|
983
|
+
const input = (0, sessionPayload_1.parseSessionCreatePayload)(JSON.parse(stripUtf8Bom(readInputSource(parsed.fromJson))));
|
|
984
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:create', [input], exports.runpaneSessionResultSchema, {
|
|
923
985
|
paneDir: parsed.paneDir,
|
|
924
986
|
});
|
|
925
987
|
return printSessionResult(result, parsed.json, 'Created');
|
|
926
988
|
}
|
|
927
989
|
async function runSessionsGet(parsed) {
|
|
928
990
|
const selector = sessionSelectorFromParsed(parsed);
|
|
929
|
-
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:get', [selector], runpaneSessionResultSchema, {
|
|
991
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:get', [selector], exports.runpaneSessionResultSchema, {
|
|
930
992
|
paneDir: parsed.paneDir,
|
|
931
993
|
});
|
|
932
994
|
return printSessionResult(result, parsed.json, '');
|
|
@@ -934,8 +996,8 @@ async function runSessionsGet(parsed) {
|
|
|
934
996
|
async function runSessionsUpdate(parsed) {
|
|
935
997
|
if (!parsed.fromJson)
|
|
936
998
|
throw new Error('runpane sessions update requires --from-json <path|->.');
|
|
937
|
-
const input = parseSessionUpdatePayload(JSON.parse(stripUtf8Bom(readInputSource(parsed.fromJson))));
|
|
938
|
-
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:update', [{ selector: sessionSelectorFromParsed(parsed), input }], runpaneSessionResultSchema, {
|
|
999
|
+
const input = (0, sessionPayload_1.parseSessionUpdatePayload)(JSON.parse(stripUtf8Bom(readInputSource(parsed.fromJson))));
|
|
1000
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:update', [{ selector: sessionSelectorFromParsed(parsed), input }], exports.runpaneSessionResultSchema, {
|
|
939
1001
|
paneDir: parsed.paneDir,
|
|
940
1002
|
});
|
|
941
1003
|
return printSessionResult(result, parsed.json, 'Updated');
|
|
@@ -943,14 +1005,14 @@ async function runSessionsUpdate(parsed) {
|
|
|
943
1005
|
async function runSessionsPin(parsed, pinned) {
|
|
944
1006
|
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:update', [{
|
|
945
1007
|
selector: sessionSelectorFromParsed(parsed), input: { isPinned: pinned },
|
|
946
|
-
}], runpaneSessionResultSchema, { paneDir: parsed.paneDir });
|
|
1008
|
+
}], exports.runpaneSessionResultSchema, { paneDir: parsed.paneDir });
|
|
947
1009
|
return printSessionResult(result, parsed.json, pinned ? 'Pinned' : 'Unpinned');
|
|
948
1010
|
}
|
|
949
1011
|
async function runSessionsSetAgent(parsed) {
|
|
950
1012
|
const selector = sessionSelectorFromParsed(parsed);
|
|
951
1013
|
if (!parsed.agent)
|
|
952
1014
|
throw new Error('runpane sessions set-agent requires --agent.');
|
|
953
|
-
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:set-agent', [{ selector, agent: parsed.agent }], runpaneSessionResultSchema, {
|
|
1015
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:set-agent', [{ selector, agent: parsed.agent }], exports.runpaneSessionResultSchema, {
|
|
954
1016
|
paneDir: parsed.paneDir,
|
|
955
1017
|
});
|
|
956
1018
|
return printSessionResult(result, parsed.json, 'Updated agent for');
|
|
@@ -962,12 +1024,12 @@ async function runSessionsAssociate(parsed) {
|
|
|
962
1024
|
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:associate', [{ selector, association: {
|
|
963
1025
|
paneId: parsed.paneId,
|
|
964
1026
|
panelIds: parsed.panelId ? [parsed.panelId] : undefined,
|
|
965
|
-
} }], runpaneSessionResultSchema, { paneDir: parsed.paneDir });
|
|
1027
|
+
} }], exports.runpaneSessionResultSchema, { paneDir: parsed.paneDir });
|
|
966
1028
|
return printSessionResult(result, parsed.json, 'Associated');
|
|
967
1029
|
}
|
|
968
1030
|
async function runSessionsDetach(parsed) {
|
|
969
1031
|
const selector = sessionSelectorFromParsed(parsed);
|
|
970
|
-
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:detach', [{ selector, paneId: parsed.paneId }], runpaneSessionResultSchema, {
|
|
1032
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:sessions:detach', [{ selector, paneId: parsed.paneId }], exports.runpaneSessionResultSchema, {
|
|
971
1033
|
paneDir: parsed.paneDir,
|
|
972
1034
|
});
|
|
973
1035
|
return printSessionResult(result, parsed.json, 'Detached');
|
|
@@ -1107,44 +1169,6 @@ function sessionSelectorFromParsed(parsed) {
|
|
|
1107
1169
|
throw new Error('Named Session id or name is required via --session.');
|
|
1108
1170
|
return { sessionId };
|
|
1109
1171
|
}
|
|
1110
|
-
function parseSessionCreatePayload(value) {
|
|
1111
|
-
return (0, boundaryDecoder_1.decodeBoundary)(value, boundaryDecoder_1.boundary.object({
|
|
1112
|
-
runtime: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('windows', 'wsl')),
|
|
1113
|
-
wslDistribution: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nonEmptyString),
|
|
1114
|
-
name: boundaryDecoder_1.boundary.nonEmptyString,
|
|
1115
|
-
isPinned: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
1116
|
-
agent: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('codex', 'claude', 'cursor')),
|
|
1117
|
-
launchCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1118
|
-
profile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1119
|
-
goal: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1120
|
-
context: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1121
|
-
decisions: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
1122
|
-
blockers: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
1123
|
-
nextAction: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1124
|
-
evidence: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(orchestrationLinkSchema)),
|
|
1125
|
-
outputs: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(orchestrationLinkSchema)),
|
|
1126
|
-
}));
|
|
1127
|
-
}
|
|
1128
|
-
function parseSessionUpdatePayload(value) {
|
|
1129
|
-
return (0, boundaryDecoder_1.decodeBoundary)(value, boundaryDecoder_1.boundary.object({
|
|
1130
|
-
name: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1131
|
-
archived: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
1132
|
-
isPinned: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.boolean),
|
|
1133
|
-
agent: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('codex', 'claude', 'cursor')),
|
|
1134
|
-
launchCommand: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1135
|
-
profile: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1136
|
-
goal: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1137
|
-
context: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1138
|
-
decisions: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
1139
|
-
blockers: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.string)),
|
|
1140
|
-
nextAction: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
1141
|
-
evidence: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(orchestrationLinkSchema)),
|
|
1142
|
-
outputs: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.array(orchestrationLinkSchema)),
|
|
1143
|
-
report: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.nullable(orchestrationReportSchema)),
|
|
1144
|
-
expectedRevision: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
1145
|
-
source: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.enumeration('user', 'agent')),
|
|
1146
|
-
}));
|
|
1147
|
-
}
|
|
1148
1172
|
function printSessionResult(result, json, action) {
|
|
1149
1173
|
if (json) {
|
|
1150
1174
|
printJson(result);
|
|
@@ -1191,22 +1215,34 @@ async function runWatch(parsed) {
|
|
|
1191
1215
|
}
|
|
1192
1216
|
const defaults = contract_1.RUNPANE_CONTRACT.defaults.watch;
|
|
1193
1217
|
const format = parsed.watchFormat ?? (parsed.json ? 'json' : 'lines');
|
|
1218
|
+
// --until-event takes --follow's scope defaults; it only stops after the first event.
|
|
1219
|
+
const keepsWaiting = parsed.follow || parsed.untilEvent;
|
|
1194
1220
|
const heartbeatMs = (0, watchLines_1.effectiveWatchHeartbeatMs)(parsed.heartbeatSeconds ?? (parsed.follow ? defaults.heartbeatSeconds : 0));
|
|
1195
|
-
const idleAfterMs = parsed.idleAfterMs ?? (
|
|
1221
|
+
const idleAfterMs = parsed.idleAfterMs ?? (keepsWaiting ? defaults.idleAfterMs : 0);
|
|
1196
1222
|
const effectiveAgentsOnly = parsed.includeShells
|
|
1197
1223
|
? undefined
|
|
1198
|
-
: parsed.agentsOnly ||
|
|
1224
|
+
: parsed.agentsOnly || keepsWaiting ? true : undefined;
|
|
1199
1225
|
const includeHeldInput = parsed.includeHeldInput && !parsed.noHeldInput ? true : undefined;
|
|
1200
1226
|
// Lines mode turns presence into STUCK; JSON mode passes heldInputPresent through as the equivalent.
|
|
1201
1227
|
const includeHeldInputPresence = defaults.includeHeldInputPresence
|
|
1202
|
-
&& !parsed.noHeldInput &&
|
|
1228
|
+
&& !parsed.noHeldInput && keepsWaiting ? true : undefined;
|
|
1203
1229
|
const cadenceValueFlagPresent = (0, commands_1.hasCadenceValueFlag)(parsed);
|
|
1230
|
+
const ownPanelId = process.env.PANE_PANEL_ID?.trim() || undefined;
|
|
1204
1231
|
// Cadence state lives in the daemon per named consumer, so an anonymous follower names itself.
|
|
1205
1232
|
// A Session watch is named after the Session, so it survives an orchestrator agent switch.
|
|
1206
1233
|
const sessionCursor = parsed.sessionId ? sessionWatchCursorName(parsed.sessionId) : undefined;
|
|
1207
|
-
const panelCursor =
|
|
1234
|
+
const panelCursor = ownPanelId ? derivedWatchCursorName('panel', ownPanelId) : undefined;
|
|
1235
|
+
// An --until-event re-arm resumes where the last one stopped, under a name apart from the
|
|
1236
|
+
// panel's --follow cursor so it never takes over a running monitor.
|
|
1237
|
+
const untilEventCursor = ownPanelId && parsed.watchSince === undefined
|
|
1238
|
+
? derivedWatchCursorName('until', `until-${ownPanelId}`)
|
|
1239
|
+
: undefined;
|
|
1208
1240
|
const watchAs = parsed.watchAs
|
|
1241
|
+
?? (parsed.untilEvent ? untilEventCursor : undefined)
|
|
1209
1242
|
?? (parsed.follow ? sessionCursor || panelCursor || (cadenceValueFlagPresent ? `follow-${process.pid}` : undefined) : undefined);
|
|
1243
|
+
// Under --until-event, --timeout-ms is the deadline for the whole wait, not for one daemon call.
|
|
1244
|
+
const deadlineAt = parsed.untilEvent && parsed.timeoutMs !== undefined ? Date.now() + parsed.timeoutMs : undefined;
|
|
1245
|
+
exitWhenReaderCloses();
|
|
1210
1246
|
// --quiet drops lines that only prove liveness; --self-test still prints its WATCH OK result.
|
|
1211
1247
|
const emitControlLine = (line) => {
|
|
1212
1248
|
if (!parsed.quiet)
|
|
@@ -1239,9 +1275,15 @@ async function runWatch(parsed) {
|
|
|
1239
1275
|
let failingCode;
|
|
1240
1276
|
let lastFailureAt = 0;
|
|
1241
1277
|
let lastHeartbeatAt = Date.now();
|
|
1242
|
-
let anonymousIdleWindowStartMs = !watchAs &&
|
|
1278
|
+
let anonymousIdleWindowStartMs = !watchAs && keepsWaiting ? 0 : undefined;
|
|
1243
1279
|
do {
|
|
1244
|
-
|
|
1280
|
+
if (deadlineAt !== undefined && Date.now() >= deadlineAt) {
|
|
1281
|
+
emitControlLine((0, watchLines_1.formatNonEntry)('_timeout', { timeoutMs: parsed.timeoutMs }, format));
|
|
1282
|
+
return 124;
|
|
1283
|
+
}
|
|
1284
|
+
const requestedWaitMs = deadlineAt !== undefined
|
|
1285
|
+
? deadlineAt - Date.now()
|
|
1286
|
+
: parsed.timeoutMs ?? (heartbeatMs > 0 ? heartbeatMs : parsed.untilEvent ? 120_000 : 60_000);
|
|
1245
1287
|
const heartbeatWaitMs = heartbeatMs > 0
|
|
1246
1288
|
? Math.max(0, heartbeatMs - (Date.now() - lastHeartbeatAt))
|
|
1247
1289
|
: requestedWaitMs;
|
|
@@ -1263,7 +1305,7 @@ async function runWatch(parsed) {
|
|
|
1263
1305
|
emitControlLine((0, watchLines_1.formatNonEntry)('_reconnected', { generation: result.generation }, format));
|
|
1264
1306
|
failingCode = undefined;
|
|
1265
1307
|
}
|
|
1266
|
-
if (!armed && (
|
|
1308
|
+
if (!armed && (keepsWaiting || parsed.selfTest)) {
|
|
1267
1309
|
const okLine = (0, watchLines_1.formatNonEntry)('_ok', { generation: result.generation, epoch: result.epoch }, format);
|
|
1268
1310
|
if (parsed.selfTest)
|
|
1269
1311
|
emitWatchLine(okLine);
|
|
@@ -1273,8 +1315,25 @@ async function runWatch(parsed) {
|
|
|
1273
1315
|
if (parsed.selfTest)
|
|
1274
1316
|
return 0;
|
|
1275
1317
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1318
|
+
if (parsed.untilEvent) {
|
|
1319
|
+
// A reset restates current state; it never ends the wait. Nor does the caller's own panel.
|
|
1320
|
+
if (result.reset || result.dropped !== undefined) {
|
|
1321
|
+
for (const line of (0, watchLines_1.formatWaitResult)(result, format))
|
|
1322
|
+
emitControlLine(line);
|
|
1323
|
+
}
|
|
1324
|
+
else {
|
|
1325
|
+
const entries = ownPanelId ? result.entries.filter(entry => entry.panelId !== ownPanelId) : result.entries;
|
|
1326
|
+
if (entries.length > 0) {
|
|
1327
|
+
for (const line of (0, watchLines_1.formatWaitResult)({ ...result, entries }, format))
|
|
1328
|
+
emitWatchLine(line);
|
|
1329
|
+
return 0;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
else {
|
|
1334
|
+
for (const line of (0, watchLines_1.formatWaitResult)(result, format))
|
|
1335
|
+
emitWatchLine(line);
|
|
1336
|
+
}
|
|
1278
1337
|
if (heartbeatMs > 0 && Date.now() - lastHeartbeatAt >= heartbeatMs) {
|
|
1279
1338
|
emitControlLine((0, watchLines_1.formatNonEntry)('_heartbeat', {
|
|
1280
1339
|
generation: result.generation,
|
|
@@ -1284,13 +1343,13 @@ async function runWatch(parsed) {
|
|
|
1284
1343
|
}
|
|
1285
1344
|
if (!watchAs) {
|
|
1286
1345
|
request.since = result.generation;
|
|
1287
|
-
if (
|
|
1346
|
+
if (keepsWaiting)
|
|
1288
1347
|
anonymousIdleWindowStartMs = Date.now();
|
|
1289
1348
|
}
|
|
1290
1349
|
}
|
|
1291
1350
|
catch (error) {
|
|
1292
1351
|
const watchError = error instanceof Error ? error : new Error(String(error));
|
|
1293
|
-
if (!
|
|
1352
|
+
if (!keepsWaiting || !isRetryableWatchError(watchError)) {
|
|
1294
1353
|
return emitWatchFailure(watchError, format);
|
|
1295
1354
|
}
|
|
1296
1355
|
const code = watchErrorCode(watchError);
|
|
@@ -1301,12 +1360,22 @@ async function runWatch(parsed) {
|
|
|
1301
1360
|
failingCode = code;
|
|
1302
1361
|
await new Promise(resolve => setTimeout(resolve, 1_000));
|
|
1303
1362
|
}
|
|
1304
|
-
} while (
|
|
1363
|
+
} while (keepsWaiting);
|
|
1305
1364
|
return 0;
|
|
1306
1365
|
}
|
|
1307
1366
|
function emitWatchLine(line) {
|
|
1308
1367
|
node_process_1.stdout.write(`${line}\n`);
|
|
1309
1368
|
}
|
|
1369
|
+
/** Codes a stdout write fails with once its reader is gone: a pipe, a socket pair (macOS), or Windows. */
|
|
1370
|
+
const CLOSED_READER_CODES = new Set(['EPIPE', 'ENOTCONN', 'ECONNRESET', 'EOF']);
|
|
1371
|
+
/** A reader that exits early (`| head -1`) closes stdout; the next write then ends the watch cleanly. */
|
|
1372
|
+
function exitWhenReaderCloses() {
|
|
1373
|
+
node_process_1.stdout.on('error', (error) => {
|
|
1374
|
+
if (!CLOSED_READER_CODES.has(error.code ?? ''))
|
|
1375
|
+
throw error;
|
|
1376
|
+
process.exit(0);
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1310
1379
|
/** Names older daemons accept; the daemon itself allows up to 128 characters. */
|
|
1311
1380
|
const PORTABLE_WATCH_CURSOR_PATTERN = /^[A-Za-z0-9._-]{1,64}$/u;
|
|
1312
1381
|
/**
|
|
@@ -1731,11 +1800,29 @@ async function runReport(parsed, env = process.env) {
|
|
|
1731
1800
|
printJson(result);
|
|
1732
1801
|
}
|
|
1733
1802
|
else {
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1803
|
+
for (const line of describeReportDelivery(result))
|
|
1804
|
+
console.log(line);
|
|
1736
1805
|
}
|
|
1737
1806
|
return 0;
|
|
1738
1807
|
}
|
|
1808
|
+
/**
|
|
1809
|
+
* What `runpane report` prints: the report, who recorded it, and how many watches were waiting.
|
|
1810
|
+
* Zero waiting watchers means nobody is waiting right now, not that the report is lost.
|
|
1811
|
+
*/
|
|
1812
|
+
function describeReportDelivery(result) {
|
|
1813
|
+
const sessions = result.sessionIds.length > 0 ? ` Recorded on Session ${result.sessionIds.join(', ')}.` : '';
|
|
1814
|
+
const watchers = result.liveWatchers ?? 0;
|
|
1815
|
+
const delivered = watchers > 0 ? ` Delivered to ${watchers} waiting watcher${watchers === 1 ? '' : 's'}.` : '';
|
|
1816
|
+
const lines = [`Reported ${(0, watchLines_1.describeReport)(result.report)} for panel ${result.panelId}.${sessions}${delivered}`];
|
|
1817
|
+
if (result.sessionIds.length > 0 || watchers > 0)
|
|
1818
|
+
return lines;
|
|
1819
|
+
const stored = `It is stored on the panel (runpane agents status --panel ${result.panelId})`;
|
|
1820
|
+
lines.push(result.liveWatchers === undefined
|
|
1821
|
+
? `No Session recorded this report. ${stored}, and only watchers that list agent.report receive it.`
|
|
1822
|
+
: `No Session recorded this report and no watcher was waiting for it. ${stored}, `
|
|
1823
|
+
+ 'and a watch with a named cursor (runpane watch --as <name> --kinds agent.report) still receives it when it next waits.');
|
|
1824
|
+
return lines;
|
|
1825
|
+
}
|
|
1739
1826
|
async function runPanelsSubmit(parsed) {
|
|
1740
1827
|
const request = buildPanelInputRequest(parsed, 'submit');
|
|
1741
1828
|
await confirmPanelInput(parsed, request, 'submit');
|
|
@@ -1843,6 +1930,34 @@ async function runPanelsWait(parsed) {
|
|
|
1843
1930
|
printPanelWaitResult(result);
|
|
1844
1931
|
return result.ok ? 0 : 1;
|
|
1845
1932
|
}
|
|
1933
|
+
async function runPanelsResume(parsed) {
|
|
1934
|
+
const scopes = [parsed.panelId, parsed.sessionId, parsed.allStopped].filter(Boolean).length;
|
|
1935
|
+
if (scopes !== 1) {
|
|
1936
|
+
throw new Error('runpane panels resume requires exactly one of --panel, --session, or --all-stopped.');
|
|
1937
|
+
}
|
|
1938
|
+
if (parsed.panelId && parsed.concurrency !== undefined) {
|
|
1939
|
+
throw new Error('runpane panels resume --concurrency applies only to --session or --all-stopped.');
|
|
1940
|
+
}
|
|
1941
|
+
await confirmPanelResume(parsed);
|
|
1942
|
+
if (!parsed.panelId) {
|
|
1943
|
+
return runPanelsResumeMany(parsed);
|
|
1944
|
+
}
|
|
1945
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:panels:resume', [{
|
|
1946
|
+
panelId: parsed.panelId,
|
|
1947
|
+
waitReady: parsed.waitReady,
|
|
1948
|
+
readyTimeoutMs: parsed.readyTimeoutMs,
|
|
1949
|
+
}], panelResumeResultSchema, {
|
|
1950
|
+
paneDir: parsed.paneDir,
|
|
1951
|
+
timeoutMs: (parsed.readyTimeoutMs ?? 30_000) + 10_000,
|
|
1952
|
+
});
|
|
1953
|
+
if (parsed.json) {
|
|
1954
|
+
printJson(result);
|
|
1955
|
+
}
|
|
1956
|
+
else {
|
|
1957
|
+
printPanelResumeResult(result);
|
|
1958
|
+
}
|
|
1959
|
+
return result.ok ? 0 : 1;
|
|
1960
|
+
}
|
|
1846
1961
|
async function runAgentsDoctor(parsed) {
|
|
1847
1962
|
if (!parsed.agent) {
|
|
1848
1963
|
throw new Error(`runpane agents doctor requires --agent ${contract_1.RUNPANE_CONTRACT.enums.agents.join('|')}.`);
|
|
@@ -2255,6 +2370,27 @@ async function confirmPanelInput(parsed, request, command = 'input') {
|
|
|
2255
2370
|
rl.close();
|
|
2256
2371
|
}
|
|
2257
2372
|
}
|
|
2373
|
+
async function confirmPanelResume(parsed) {
|
|
2374
|
+
if (parsed.yes) {
|
|
2375
|
+
return;
|
|
2376
|
+
}
|
|
2377
|
+
if (!isInteractiveShell()) {
|
|
2378
|
+
throw new Error('runpane panels resume restarts a Pane terminal. Rerun with --yes in non-interactive shells.');
|
|
2379
|
+
}
|
|
2380
|
+
const rl = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
2381
|
+
try {
|
|
2382
|
+
const target = parsed.panelId
|
|
2383
|
+
? `panel ${parsed.panelId}`
|
|
2384
|
+
: parsed.sessionId ? `every stopped agent panel in Session ${parsed.sessionId}` : 'every stopped agent panel';
|
|
2385
|
+
const answer = (await rl.question(`Resume ${target}? [y/N] `)).trim().toLowerCase();
|
|
2386
|
+
if (answer !== 'y' && answer !== 'yes') {
|
|
2387
|
+
throw new Error('Cancelled.');
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
finally {
|
|
2391
|
+
rl.close();
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2258
2394
|
async function confirmPanelSubmitComposer(parsed) {
|
|
2259
2395
|
if (parsed.yes) {
|
|
2260
2396
|
return;
|
|
@@ -2326,6 +2462,7 @@ function workspaceLabel(kind) {
|
|
|
2326
2462
|
'pane.created': 'NEW',
|
|
2327
2463
|
'pane.gone': 'GONE',
|
|
2328
2464
|
'panel.exited': 'EXIT',
|
|
2465
|
+
'panel.stopped': 'STOPPED',
|
|
2329
2466
|
'pane.associated': 'JOINED',
|
|
2330
2467
|
'pane.detached': 'LEFT',
|
|
2331
2468
|
'pr.conflicted': 'PR CONFLICTED',
|
|
@@ -2393,12 +2530,8 @@ function printPaneCreateResult(result, dryRun = false, action = 'create') {
|
|
|
2393
2530
|
continue;
|
|
2394
2531
|
}
|
|
2395
2532
|
console.log(`Created ${item.name ?? `pane ${item.index}`}: session ${item.sessionId ?? 'unknown'} panel ${item.panelId ?? 'unknown'}${worktree}`);
|
|
2396
|
-
if (item.readiness)
|
|
2397
|
-
|
|
2398
|
-
if (item.readiness.blocked) {
|
|
2399
|
-
console.log(` Blocked: ${item.readiness.blocked.message}`);
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2533
|
+
if (item.readiness)
|
|
2534
|
+
printReadiness(item.readiness, ' ');
|
|
2402
2535
|
printInitialInputDelivery(item.initialInput, ' ');
|
|
2403
2536
|
if (item.association) {
|
|
2404
2537
|
console.log(item.association.ok
|
|
@@ -2406,6 +2539,9 @@ function printPaneCreateResult(result, dryRun = false, action = 'create') {
|
|
|
2406
2539
|
: ` Not associated with Session ${item.association.sessionId}: ${item.association.error ?? 'unknown error'}`);
|
|
2407
2540
|
}
|
|
2408
2541
|
printPromptNotes(item, ' ');
|
|
2542
|
+
if (item.base?.notice) {
|
|
2543
|
+
console.log(` ! ${item.base.notice}`);
|
|
2544
|
+
}
|
|
2409
2545
|
if (item.setupQueue) {
|
|
2410
2546
|
console.log(` ${item.setupQueue.message}`);
|
|
2411
2547
|
}
|
|
@@ -2478,18 +2614,32 @@ function printArchiveCommitEvidence(safetyCheck, print = console.log) {
|
|
|
2478
2614
|
}
|
|
2479
2615
|
function printPanelCreateResult(result) {
|
|
2480
2616
|
console.log(`Created panel ${result.panelId} in pane ${result.paneId}: ${result.title}${result.active ? ' active' : ' background'}`);
|
|
2481
|
-
if (result.readiness)
|
|
2482
|
-
|
|
2483
|
-
if (result.readiness.blocked) {
|
|
2484
|
-
console.log(`Blocked: ${result.readiness.blocked.message}`);
|
|
2485
|
-
}
|
|
2486
|
-
}
|
|
2617
|
+
if (result.readiness)
|
|
2618
|
+
printReadiness(result.readiness);
|
|
2487
2619
|
printInitialInputDelivery(result.initialInput);
|
|
2488
2620
|
printPromptNotes(result);
|
|
2489
2621
|
if (result.nextCommand) {
|
|
2490
2622
|
console.log(`Next: ${result.nextCommand}`);
|
|
2491
2623
|
}
|
|
2492
2624
|
}
|
|
2625
|
+
/** One-line status for a bulk resume item that resumed but did not become ready. */
|
|
2626
|
+
function notReadySummary(readiness) {
|
|
2627
|
+
if (readiness.blocked)
|
|
2628
|
+
return `blocked: ${readiness.blocked.message}`;
|
|
2629
|
+
const state = readiness.reason?.code === 'command-exited' ? 'command exited' : 'not ready';
|
|
2630
|
+
return readiness.reason ? `${state}: ${readiness.reason.message}` : state;
|
|
2631
|
+
}
|
|
2632
|
+
function printReadiness(readiness, prefix = '') {
|
|
2633
|
+
const state = readiness.ok ? 'yes'
|
|
2634
|
+
: readiness.blocked ? 'blocked'
|
|
2635
|
+
: readiness.reason?.code === 'command-exited' ? 'command exited'
|
|
2636
|
+
: readiness.timedOut ? 'timed out' : 'no';
|
|
2637
|
+
console.log(`${prefix}Ready: ${state} after ${readiness.elapsedMs}ms`);
|
|
2638
|
+
if (readiness.blocked)
|
|
2639
|
+
console.log(`${prefix}Blocked: ${readiness.blocked.message}`);
|
|
2640
|
+
if (readiness.reason)
|
|
2641
|
+
console.log(`${prefix}Why: ${readiness.reason.message}`);
|
|
2642
|
+
}
|
|
2493
2643
|
function printInitialInputDelivery(initialInput, prefix = '') {
|
|
2494
2644
|
if (!initialInput) {
|
|
2495
2645
|
return;
|
|
@@ -2511,10 +2661,51 @@ function printInitialInputDelivery(initialInput, prefix = '') {
|
|
|
2511
2661
|
console.log(`${prefix}Initial input error: ${initialInput.error.message}`);
|
|
2512
2662
|
}
|
|
2513
2663
|
}
|
|
2664
|
+
/** Time the daemon gets to restart every panel in scope, before any readiness wait. */
|
|
2665
|
+
const RESUME_MANY_RESTART_BUDGET_MS = 5 * 60_000;
|
|
2666
|
+
async function runPanelsResumeMany(parsed) {
|
|
2667
|
+
const result = await (0, daemonClient_1.invokeDaemon)('runpane:panels:resume-many', [{
|
|
2668
|
+
sessionId: parsed.sessionId,
|
|
2669
|
+
allStopped: parsed.allStopped || undefined,
|
|
2670
|
+
waitReady: parsed.waitReady,
|
|
2671
|
+
readyTimeoutMs: parsed.readyTimeoutMs,
|
|
2672
|
+
concurrency: parsed.concurrency,
|
|
2673
|
+
}], panelResumeManyResultSchema, {
|
|
2674
|
+
paneDir: parsed.paneDir,
|
|
2675
|
+
// The resumed panels wait together, so the wait adds one --ready-timeout-ms however many there are.
|
|
2676
|
+
timeoutMs: RESUME_MANY_RESTART_BUDGET_MS + (parsed.waitReady ? parsed.readyTimeoutMs ?? 30_000 : 0),
|
|
2677
|
+
});
|
|
2678
|
+
if (parsed.json) {
|
|
2679
|
+
printJson(result);
|
|
2680
|
+
}
|
|
2681
|
+
else {
|
|
2682
|
+
const scope = result.scope.kind === 'session' ? `Session ${result.scope.sessionName}` : 'every Pane';
|
|
2683
|
+
const notReady = result.notReady > 0 ? `, ${result.notReady} not ready` : '';
|
|
2684
|
+
console.log(`Resumed ${result.resumed} stopped agent panel${result.resumed === 1 ? '' : 's'} in ${scope}, ${result.concurrency} at a time; ${result.alreadyRunning} already running, ${result.failed} failed${notReady}.`);
|
|
2685
|
+
for (const item of result.items) {
|
|
2686
|
+
const status = item.error
|
|
2687
|
+
? `failed: ${item.error}`
|
|
2688
|
+
: item.readiness && !item.readiness.ok
|
|
2689
|
+
? notReadySummary(item.readiness)
|
|
2690
|
+
: item.action ?? 'resumed';
|
|
2691
|
+
console.log(`${item.ok ? 'OK' : 'FAIL'} ${item.paneName} panel ${item.panelId}: ${status}`);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
return result.ok ? 0 : 1;
|
|
2695
|
+
}
|
|
2696
|
+
function printPanelResumeResult(result) {
|
|
2697
|
+
console.log(`${result.action === 'resumed' ? 'Resumed' : 'Already running:'} panel ${result.panelId} in pane ${result.paneId}. ${result.message}`);
|
|
2698
|
+
if (result.readiness)
|
|
2699
|
+
printReadiness(result.readiness);
|
|
2700
|
+
console.log(`Next: ${result.nextCommand}`);
|
|
2701
|
+
}
|
|
2514
2702
|
function printPanelWaitResult(result) {
|
|
2515
2703
|
if (result.ok) {
|
|
2516
2704
|
console.log(`Matched ${result.condition} for panel ${result.panelId} after ${result.elapsedMs}ms.`);
|
|
2517
2705
|
}
|
|
2706
|
+
else if (result.stopped && !result.timedOut) {
|
|
2707
|
+
console.log(`Panel ${result.panelId} is not running, so it cannot become ${result.condition}.`);
|
|
2708
|
+
}
|
|
2518
2709
|
else if (result.blocked) {
|
|
2519
2710
|
console.log(`Blocked waiting for ${result.condition} on panel ${result.panelId}: ${result.blocked.message}`);
|
|
2520
2711
|
}
|
|
@@ -2524,7 +2715,10 @@ function printPanelWaitResult(result) {
|
|
|
2524
2715
|
else {
|
|
2525
2716
|
console.log(`Did not match ${result.condition} for panel ${result.panelId}.`);
|
|
2526
2717
|
}
|
|
2718
|
+
if (result.reason)
|
|
2719
|
+
console.log(`Why: ${result.reason.message}`);
|
|
2527
2720
|
const statusParts = [
|
|
2721
|
+
result.state.running === false ? 'stopped' : undefined,
|
|
2528
2722
|
result.state.initialized ? 'initialized' : 'not-initialized',
|
|
2529
2723
|
result.state.activityStatus,
|
|
2530
2724
|
result.state.isCliReady === undefined ? undefined : result.state.isCliReady ? 'cli-ready' : 'cli-not-ready',
|
|
@@ -2562,9 +2756,11 @@ function printPanelListResult(result) {
|
|
|
2562
2756
|
for (const panel of result.panels) {
|
|
2563
2757
|
const marker = panel.active ? '*' : ' ';
|
|
2564
2758
|
const initialized = panel.initialized === undefined ? '' : panel.initialized ? ' initialized' : ' not-initialized';
|
|
2759
|
+
const stopped = panel.running === false ? ' stopped' : '';
|
|
2565
2760
|
const agent = panel.agentType ? ` ${panel.agentType}` : '';
|
|
2566
2761
|
const detection = panel.agentDetection && panel.agentDetection !== 'command' ? ` (${panel.agentDetection})` : '';
|
|
2567
|
-
|
|
2762
|
+
const resume = panel.resumeId ? ` resume ${panel.resumeId}` : '';
|
|
2763
|
+
console.log(`${marker} ${panel.id}\t${panel.type}\t${panel.title}${initialized}${stopped}${agent}${detection}${resume}`);
|
|
2568
2764
|
}
|
|
2569
2765
|
}
|
|
2570
2766
|
function isInteractiveShell() {
|