poly-weaver 0.15.3 → 1.0.0
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/dist/agents/implementors/handler.d.ts.map +1 -1
- package/dist/agents/implementors/handler.js +7 -2
- package/dist/agents/implementors/handler.js.map +1 -1
- package/dist/agents/interviewers/handler.d.ts.map +1 -1
- package/dist/agents/interviewers/handler.js +3 -1
- package/dist/agents/interviewers/handler.js.map +1 -1
- package/dist/agents/planners/adapter.d.ts.map +1 -1
- package/dist/agents/planners/adapter.js +30 -11
- package/dist/agents/planners/adapter.js.map +1 -1
- package/dist/agents/planners/handler.d.ts.map +1 -1
- package/dist/agents/planners/handler.js +7 -2
- package/dist/agents/planners/handler.js.map +1 -1
- package/dist/agents/reviewers/adapter.d.ts.map +1 -1
- package/dist/agents/reviewers/adapter.js +1 -0
- package/dist/agents/reviewers/adapter.js.map +1 -1
- package/dist/agents/reviewers/handler.d.ts.map +1 -1
- package/dist/agents/reviewers/handler.js +23 -4
- package/dist/agents/reviewers/handler.js.map +1 -1
- package/dist/agents/reviewers/types.d.ts +2 -0
- package/dist/agents/reviewers/types.d.ts.map +1 -1
- package/dist/agents/runner.d.ts +18 -1
- package/dist/agents/runner.d.ts.map +1 -1
- package/dist/agents/runner.js +136 -20
- package/dist/agents/runner.js.map +1 -1
- package/dist/agents/simplifiers/handler.d.ts.map +1 -1
- package/dist/agents/simplifiers/handler.js +7 -2
- package/dist/agents/simplifiers/handler.js.map +1 -1
- package/dist/auto-update/detect-agents.d.ts +1 -0
- package/dist/auto-update/detect-agents.d.ts.map +1 -1
- package/dist/auto-update/detect-agents.js +8 -7
- package/dist/auto-update/detect-agents.js.map +1 -1
- package/dist/cli.js +16 -4
- package/dist/cli.js.map +1 -1
- package/dist/crosscheck/coordinator.d.ts +5 -0
- package/dist/crosscheck/coordinator.d.ts.map +1 -1
- package/dist/crosscheck/coordinator.js +177 -91
- package/dist/crosscheck/coordinator.js.map +1 -1
- package/dist/crosscheck/live-agent-session.d.ts +7 -1
- package/dist/crosscheck/live-agent-session.d.ts.map +1 -1
- package/dist/crosscheck/live-agent-session.js +61 -7
- package/dist/crosscheck/live-agent-session.js.map +1 -1
- package/dist/crosscheck/state.d.ts +3 -0
- package/dist/crosscheck/state.d.ts.map +1 -1
- package/dist/crosscheck/state.js +17 -2
- package/dist/crosscheck/state.js.map +1 -1
- package/dist/dump/collector.d.ts.map +1 -1
- package/dist/dump/collector.js +3 -0
- package/dist/dump/collector.js.map +1 -1
- package/dist/dump/service.d.ts.map +1 -1
- package/dist/dump/service.js +3 -0
- package/dist/dump/service.js.map +1 -1
- package/dist/dump/types.d.ts +3 -0
- package/dist/dump/types.d.ts.map +1 -1
- package/dist/dump/types.js.map +1 -1
- package/dist/flow/executor.d.ts.map +1 -1
- package/dist/flow/executor.js +5 -0
- package/dist/flow/executor.js.map +1 -1
- package/dist/flow/types.d.ts +5 -0
- package/dist/flow/types.d.ts.map +1 -1
- package/dist/flow/types.js.map +1 -1
- package/dist/offscreen/controller.d.ts +13 -2
- package/dist/offscreen/controller.d.ts.map +1 -1
- package/dist/offscreen/controller.js +212 -91
- package/dist/offscreen/controller.js.map +1 -1
- package/dist/offscreen/fork-launch.d.ts +2 -2
- package/dist/offscreen/fork-launch.d.ts.map +1 -1
- package/dist/offscreen/fork-launch.js +2 -2
- package/dist/offscreen/fork-launch.js.map +1 -1
- package/dist/offscreen/fork.d.ts +16 -2
- package/dist/offscreen/fork.d.ts.map +1 -1
- package/dist/offscreen/fork.js +79 -40
- package/dist/offscreen/fork.js.map +1 -1
- package/dist/offscreen/inquiry-pane.d.ts +2 -1
- package/dist/offscreen/inquiry-pane.d.ts.map +1 -1
- package/dist/offscreen/inquiry-pane.js +8 -2
- package/dist/offscreen/inquiry-pane.js.map +1 -1
- package/dist/offscreen/panes.d.ts +1 -0
- package/dist/offscreen/panes.d.ts.map +1 -1
- package/dist/offscreen/registry.d.ts +2 -2
- package/dist/offscreen/registry.d.ts.map +1 -1
- package/dist/offscreen/registry.js +5 -1
- package/dist/offscreen/registry.js.map +1 -1
- package/dist/offscreen/resolve.d.ts +2 -0
- package/dist/offscreen/resolve.d.ts.map +1 -1
- package/dist/offscreen/resolve.js +5 -1
- package/dist/offscreen/resolve.js.map +1 -1
- package/dist/offscreen/session-turn-monitor.d.ts +3 -1
- package/dist/offscreen/session-turn-monitor.d.ts.map +1 -1
- package/dist/offscreen/session-turn-monitor.js +10 -2
- package/dist/offscreen/session-turn-monitor.js.map +1 -1
- package/dist/offscreen/split-inquiry.d.ts.map +1 -1
- package/dist/offscreen/split-inquiry.js +5 -0
- package/dist/offscreen/split-inquiry.js.map +1 -1
- package/dist/offscreen/starting-pane.d.ts +13 -0
- package/dist/offscreen/starting-pane.d.ts.map +1 -0
- package/dist/offscreen/starting-pane.js +24 -0
- package/dist/offscreen/starting-pane.js.map +1 -0
- package/dist/offscreen/surface.d.ts +1 -0
- package/dist/offscreen/surface.d.ts.map +1 -1
- package/dist/offscreen/surface.js +5 -3
- package/dist/offscreen/surface.js.map +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +7 -1
- package/dist/orchestrator.js.map +1 -1
- package/dist/providers/copilot/completion.d.ts +32 -21
- package/dist/providers/copilot/completion.d.ts.map +1 -1
- package/dist/providers/copilot/completion.js +100 -165
- package/dist/providers/copilot/completion.js.map +1 -1
- package/dist/providers/copilot/environment.d.ts +2 -0
- package/dist/providers/copilot/environment.d.ts.map +1 -0
- package/dist/providers/copilot/environment.js +8 -0
- package/dist/providers/copilot/environment.js.map +1 -0
- package/dist/providers/copilot/fork-state.d.ts +7 -0
- package/dist/providers/copilot/fork-state.d.ts.map +1 -0
- package/dist/providers/copilot/fork-state.js +150 -0
- package/dist/providers/copilot/fork-state.js.map +1 -0
- package/dist/providers/copilot/observation.d.ts +275 -0
- package/dist/providers/copilot/observation.d.ts.map +1 -0
- package/dist/providers/copilot/observation.js +2072 -0
- package/dist/providers/copilot/observation.js.map +1 -0
- package/dist/providers/copilot/observer-extension/com.github.copilot/extensions/poly-weaver-observer/extension.d.mts +2 -0
- package/dist/providers/copilot/observer-extension/com.github.copilot/extensions/poly-weaver-observer/extension.d.mts.map +1 -0
- package/dist/providers/copilot/observer-extension/com.github.copilot/extensions/poly-weaver-observer/extension.mjs +426 -0
- package/dist/providers/copilot/observer-extension/com.github.copilot/extensions/poly-weaver-observer/extension.mjs.map +1 -0
- package/dist/providers/copilot/observer-extension/plugin.json +6 -0
- package/dist/providers/copilot/record-properties.d.ts +4 -0
- package/dist/providers/copilot/record-properties.d.ts.map +1 -0
- package/dist/providers/copilot/record-properties.js +14 -0
- package/dist/providers/copilot/record-properties.js.map +1 -0
- package/dist/providers/copilot/session.d.ts +8 -33
- package/dist/providers/copilot/session.d.ts.map +1 -1
- package/dist/providers/copilot/session.js +10 -176
- package/dist/providers/copilot/session.js.map +1 -1
- package/dist/providers/copilot/strategy.d.ts +3 -5
- package/dist/providers/copilot/strategy.d.ts.map +1 -1
- package/dist/providers/copilot/strategy.js +59 -66
- package/dist/providers/copilot/strategy.js.map +1 -1
- package/dist/providers/fork-cleanup.d.ts +4 -0
- package/dist/providers/fork-cleanup.d.ts.map +1 -0
- package/dist/providers/fork-cleanup.js +21 -0
- package/dist/providers/fork-cleanup.js.map +1 -0
- package/dist/providers/fork.d.ts +8 -3
- package/dist/providers/fork.d.ts.map +1 -1
- package/dist/providers/fork.js.map +1 -1
- package/dist/providers/invoke.d.ts.map +1 -1
- package/dist/providers/invoke.js +85 -34
- package/dist/providers/invoke.js.map +1 -1
- package/dist/providers/live.d.ts.map +1 -1
- package/dist/providers/live.js +43 -17
- package/dist/providers/live.js.map +1 -1
- package/dist/providers/observer-run.d.ts +4 -0
- package/dist/providers/observer-run.d.ts.map +1 -0
- package/dist/providers/observer-run.js +23 -0
- package/dist/providers/observer-run.js.map +1 -0
- package/dist/providers/session-launch.d.ts +3 -1
- package/dist/providers/session-launch.d.ts.map +1 -1
- package/dist/providers/session-launch.js +38 -19
- package/dist/providers/session-launch.js.map +1 -1
- package/dist/providers/types.d.ts +156 -4
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/session/resume.d.ts.map +1 -1
- package/dist/session/resume.js +16 -2
- package/dist/session/resume.js.map +1 -1
- package/dist/terminal/paste-submit.d.ts.map +1 -1
- package/dist/terminal/paste-submit.js +43 -37
- package/dist/terminal/paste-submit.js.map +1 -1
- package/dist/user/host-curate-prompt.d.ts.map +1 -1
- package/dist/user/host-curate-prompt.js +9 -6
- package/dist/user/host-curate-prompt.js.map +1 -1
- package/dist/user/host-prompt.d.ts.map +1 -1
- package/dist/user/host-prompt.js +9 -6
- package/dist/user/host-prompt.js.map +1 -1
- package/package.json +4 -2
|
@@ -3,6 +3,7 @@ import { builtinStrategies, resolveProvider } from "../providers/registry.js";
|
|
|
3
3
|
import { Fork } from "./fork.js";
|
|
4
4
|
import { foldAltMetaKeys, isPrimaryIssueKey, isPrimaryShowKey, isSecondaryIssueKey, isSecondaryShowKey, isSummarizeKey, } from "./keys.js";
|
|
5
5
|
import { InquiryPaneController } from "./inquiry-pane.js";
|
|
6
|
+
import { StartingInquiryPane } from "./starting-pane.js";
|
|
6
7
|
import { ArtifactPaneController } from "./artifact-pane.js";
|
|
7
8
|
import { registerOffscreenDisposer } from "./registry.js";
|
|
8
9
|
import { SplitInquiryCoordinator } from "./split-inquiry.js";
|
|
@@ -19,6 +20,7 @@ export class OffscreenController {
|
|
|
19
20
|
host;
|
|
20
21
|
workdir;
|
|
21
22
|
inquiry;
|
|
23
|
+
observerRuns;
|
|
22
24
|
slots = new Map();
|
|
23
25
|
artifactConfigs;
|
|
24
26
|
turnPollMs;
|
|
@@ -26,6 +28,9 @@ export class OffscreenController {
|
|
|
26
28
|
tracksTurns;
|
|
27
29
|
forks = new Map();
|
|
28
30
|
pending = new Map();
|
|
31
|
+
pendingForks = new Map();
|
|
32
|
+
pendingQuestions = new Map();
|
|
33
|
+
launchAbort = new AbortController();
|
|
29
34
|
sendPending = new Set();
|
|
30
35
|
turnInProgress = new Set();
|
|
31
36
|
turnMonitors = new Map();
|
|
@@ -41,14 +46,17 @@ export class OffscreenController {
|
|
|
41
46
|
forkSubmitFloorReads = new Map();
|
|
42
47
|
forkLocateWarned = new Set();
|
|
43
48
|
activeArtifactIndexes = new Map();
|
|
49
|
+
artifactPanes = new Map();
|
|
44
50
|
unregister;
|
|
45
51
|
split;
|
|
46
52
|
shown;
|
|
47
53
|
disposed = false;
|
|
48
|
-
|
|
54
|
+
disposal;
|
|
55
|
+
constructor(host, workdir, slots, artifactConfigs = {}, inquiry, observerRuns) {
|
|
49
56
|
this.host = host;
|
|
50
57
|
this.workdir = workdir;
|
|
51
58
|
this.inquiry = inquiry;
|
|
59
|
+
this.observerRuns = observerRuns;
|
|
52
60
|
for (const slot of slots) {
|
|
53
61
|
this.slots.set(slot.binding, slot);
|
|
54
62
|
}
|
|
@@ -66,7 +74,7 @@ export class OffscreenController {
|
|
|
66
74
|
}
|
|
67
75
|
selectionDelegate() {
|
|
68
76
|
return {
|
|
69
|
-
fork: this.shown ? this.
|
|
77
|
+
fork: this.shown ? this.presentedFork(this.shown) : undefined,
|
|
70
78
|
layout: this.host.getLayout(),
|
|
71
79
|
coordinator: this.activeCoordinator(),
|
|
72
80
|
};
|
|
@@ -74,15 +82,16 @@ export class OffscreenController {
|
|
|
74
82
|
wrap(base) {
|
|
75
83
|
return {
|
|
76
84
|
getSurface: () => {
|
|
77
|
-
const fork = this.shown ? this.
|
|
78
|
-
if (!
|
|
85
|
+
const fork = this.shown ? this.presentedFork(this.shown) : undefined;
|
|
86
|
+
if (!this.shown)
|
|
79
87
|
return base.getSurface();
|
|
80
88
|
const layout = this.host.getLayout();
|
|
81
89
|
const coordinator = this.activeCoordinator();
|
|
82
90
|
if (coordinator) {
|
|
83
91
|
return coordinator.getSurface(layout.columns, layout.childRows);
|
|
84
92
|
}
|
|
85
|
-
return new InquiryPaneController(fork
|
|
93
|
+
return (fork ? new InquiryPaneController(fork, this.forks.has(this.shown)) : this.startingPane(this.shown))
|
|
94
|
+
.render(layout.columns, layout.childRows);
|
|
86
95
|
},
|
|
87
96
|
selectionRegionAt: (column, row) => {
|
|
88
97
|
const { fork, layout, coordinator } = this.selectionDelegate();
|
|
@@ -90,7 +99,7 @@ export class OffscreenController {
|
|
|
90
99
|
return coordinator.selectionRegionAt(column, row, layout.columns, layout.childRows);
|
|
91
100
|
}
|
|
92
101
|
if (!fork)
|
|
93
|
-
return base.selectionRegionAt?.(column, row);
|
|
102
|
+
return this.shown ? null : base.selectionRegionAt?.(column, row);
|
|
94
103
|
if (row < 2 || row > layout.childRows)
|
|
95
104
|
return null;
|
|
96
105
|
return fork.vt.isAlternate === true
|
|
@@ -103,7 +112,7 @@ export class OffscreenController {
|
|
|
103
112
|
return coordinator.selectionTargetAt(column, row, layout.columns, layout.childRows);
|
|
104
113
|
}
|
|
105
114
|
if (!fork)
|
|
106
|
-
return base.selectionTargetAt?.(column, row) ?? null;
|
|
115
|
+
return this.shown ? null : base.selectionTargetAt?.(column, row) ?? null;
|
|
107
116
|
if (fork.vt.isAlternate === true)
|
|
108
117
|
return null;
|
|
109
118
|
if (column < 1 || column > layout.columns || row < 2 || row > layout.childRows)
|
|
@@ -116,7 +125,7 @@ export class OffscreenController {
|
|
|
116
125
|
return coordinator.scrollSelectableSurfaceAt(column, row, direction, layout.columns, layout.childRows);
|
|
117
126
|
}
|
|
118
127
|
if (!fork || fork.vt.isAlternate === true) {
|
|
119
|
-
return base.scrollSelectableSurfaceAt?.(column, row, direction) ?? 0;
|
|
128
|
+
return this.shown ? 0 : base.scrollSelectableSurfaceAt?.(column, row, direction) ?? 0;
|
|
120
129
|
}
|
|
121
130
|
if (column < 1 || column > layout.columns)
|
|
122
131
|
return 0;
|
|
@@ -134,7 +143,7 @@ export class OffscreenController {
|
|
|
134
143
|
return placement ? { region: placement.region, vt: fork.vt } : undefined;
|
|
135
144
|
}
|
|
136
145
|
if (!fork || fork.vt.isAlternate === true || layout.childRows < 2) {
|
|
137
|
-
return base.forkSelectionPlacement?.();
|
|
146
|
+
return this.shown ? undefined : base.forkSelectionPlacement?.();
|
|
138
147
|
}
|
|
139
148
|
return {
|
|
140
149
|
region: { rowStart: 2, rowEnd: layout.childRows, colStart: 1, colEnd: layout.columns },
|
|
@@ -146,7 +155,7 @@ export class OffscreenController {
|
|
|
146
155
|
if (coordinator) {
|
|
147
156
|
return coordinator.artifactPlacementAt(column, row, layout.columns, layout.childRows);
|
|
148
157
|
}
|
|
149
|
-
if (
|
|
158
|
+
if (this.shown)
|
|
150
159
|
return undefined;
|
|
151
160
|
return base.docSurfaceSelectionPlacementAt?.(column, row);
|
|
152
161
|
},
|
|
@@ -156,7 +165,7 @@ export class OffscreenController {
|
|
|
156
165
|
const placement = coordinator.artifactPlacement(layout.columns, layout.childRows);
|
|
157
166
|
return placement ? [placement] : [];
|
|
158
167
|
}
|
|
159
|
-
if (
|
|
168
|
+
if (this.shown)
|
|
160
169
|
return [];
|
|
161
170
|
return base.docSurfaceSelectionPlacements?.() ?? [];
|
|
162
171
|
},
|
|
@@ -165,11 +174,13 @@ export class OffscreenController {
|
|
|
165
174
|
if (coordinator) {
|
|
166
175
|
return coordinator.artifactPlacement(layout.columns, layout.childRows);
|
|
167
176
|
}
|
|
168
|
-
if (
|
|
177
|
+
if (this.shown)
|
|
169
178
|
return undefined;
|
|
170
179
|
return base.artifactSelectionPlacement?.();
|
|
171
180
|
},
|
|
172
181
|
onEvents: (keys) => {
|
|
182
|
+
if (this.disposed)
|
|
183
|
+
return true;
|
|
173
184
|
const events = this.inquiry ? foldAltMetaKeys(keys) : keys;
|
|
174
185
|
if (keys.some(isSummarizeKey) && this.canSummarize("primary")) {
|
|
175
186
|
return this.summarize("primary");
|
|
@@ -201,41 +212,60 @@ export class OffscreenController {
|
|
|
201
212
|
onResize: (cols, rows) => {
|
|
202
213
|
if (this.disposed)
|
|
203
214
|
return;
|
|
204
|
-
const fork = this.shown ? this.
|
|
205
|
-
if (
|
|
215
|
+
const fork = this.shown ? this.presentedFork(this.shown) : undefined;
|
|
216
|
+
if (this.shown)
|
|
206
217
|
this.configurePresentation(this.shown, fork, cols, rows);
|
|
207
218
|
this.updateForkState();
|
|
208
219
|
},
|
|
209
220
|
};
|
|
210
221
|
}
|
|
211
222
|
dispose() {
|
|
212
|
-
if (this.
|
|
213
|
-
return;
|
|
223
|
+
if (this.disposal)
|
|
224
|
+
return this.disposal;
|
|
214
225
|
this.disposed = true;
|
|
226
|
+
this.launchAbort.abort();
|
|
215
227
|
this.unregister();
|
|
216
228
|
for (const binding of Array.from(this.sendControllers.keys())) {
|
|
217
229
|
this.abortIssueSend(binding);
|
|
218
230
|
}
|
|
219
231
|
this.clearForkSessionWatchers();
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
232
|
+
const releases = [...this.forks.values(), ...this.pendingForks.values()].map((fork) => fork.kill());
|
|
233
|
+
const pending = Array.from(this.pending.values());
|
|
223
234
|
this.forks.clear();
|
|
224
235
|
this.pending.clear();
|
|
236
|
+
this.pendingForks.clear();
|
|
237
|
+
this.pendingQuestions.clear();
|
|
238
|
+
this.artifactPanes.clear();
|
|
225
239
|
this.sendPending.clear();
|
|
226
240
|
this.sendLocks.clear();
|
|
227
241
|
this.shown = undefined;
|
|
228
242
|
this.clearSplitCoordinator();
|
|
229
243
|
this.host.clearMouseModeSource(OFFSCREEN_MOUSE_SOURCE);
|
|
230
244
|
this.updateForkState();
|
|
245
|
+
return this.disposal = Promise.all([...releases, ...pending]).then(() => { });
|
|
231
246
|
}
|
|
232
247
|
handleForkEvents(keys) {
|
|
233
248
|
const binding = this.shown;
|
|
234
249
|
const fork = binding ? this.forks.get(binding) : undefined;
|
|
235
250
|
if (!fork) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
251
|
+
if (!binding)
|
|
252
|
+
return true;
|
|
253
|
+
if (keys.some((key) => key.kind === "control" && key.byte === 0x03)) {
|
|
254
|
+
this.hideFork(this.pendingForks.get(binding));
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
for (const key of keys) {
|
|
258
|
+
if (isArtifactViewerKey(key) && this.cycleCompanionArtifact(binding))
|
|
259
|
+
continue;
|
|
260
|
+
const shortcut = this.inquiry ? inquiryShortcutForKey(key) : undefined;
|
|
261
|
+
if (shortcut?.kind === "issue" && shortcut.binding === binding) {
|
|
262
|
+
this.openInquiry(shortcut);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const layout = this.host.getLayout();
|
|
266
|
+
const result = this.activeCoordinator()?.handleArtifactScroll(keys, layout.columns, layout.childRows);
|
|
267
|
+
if (result)
|
|
268
|
+
this.applyPaneResult(undefined, result);
|
|
239
269
|
return true;
|
|
240
270
|
}
|
|
241
271
|
if (binding && this.sendLocks.has(binding)) {
|
|
@@ -335,14 +365,17 @@ export class OffscreenController {
|
|
|
335
365
|
this.hideFork(fork);
|
|
336
366
|
}
|
|
337
367
|
}
|
|
368
|
+
presentedFork(binding) {
|
|
369
|
+
return this.forks.get(binding) ?? this.pendingForks.get(binding);
|
|
370
|
+
}
|
|
338
371
|
hideFork(fork) {
|
|
339
372
|
if (this.shown)
|
|
340
373
|
this.abortIssueSend(this.shown);
|
|
341
374
|
if (this.activeCoordinator()) {
|
|
342
375
|
const layout = this.host.getLayout();
|
|
343
|
-
fork
|
|
376
|
+
fork?.resize(layout.columns, layout.childRows);
|
|
344
377
|
}
|
|
345
|
-
fork
|
|
378
|
+
fork?.setVisible(false);
|
|
346
379
|
this.shown = undefined;
|
|
347
380
|
this.clearSplitCoordinator();
|
|
348
381
|
this.host.clearMouseModeSource(OFFSCREEN_MOUSE_SOURCE);
|
|
@@ -375,7 +408,7 @@ export class OffscreenController {
|
|
|
375
408
|
];
|
|
376
409
|
}
|
|
377
410
|
nextCompanionArtifactHint(binding) {
|
|
378
|
-
if (this.shown !== binding
|
|
411
|
+
if (this.shown !== binding)
|
|
379
412
|
return undefined;
|
|
380
413
|
const config = this.artifactConfigs[binding];
|
|
381
414
|
if (!config)
|
|
@@ -388,8 +421,8 @@ export class OffscreenController {
|
|
|
388
421
|
}
|
|
389
422
|
cycleCompanionArtifact(binding) {
|
|
390
423
|
const primary = this.artifactConfigs[binding];
|
|
391
|
-
const fork = this.
|
|
392
|
-
if (!primary
|
|
424
|
+
const fork = this.presentedFork(binding);
|
|
425
|
+
if (!primary)
|
|
393
426
|
return false;
|
|
394
427
|
const count = this.companionArtifacts(primary).length;
|
|
395
428
|
if (count <= 1)
|
|
@@ -405,21 +438,33 @@ export class OffscreenController {
|
|
|
405
438
|
configurePresentation(binding, fork, cols, rows) {
|
|
406
439
|
const artifact = this.activeArtifactConfig(binding);
|
|
407
440
|
if (artifact && (cols >= SPLIT_COLLAPSE_AT_COLS || artifact.collapseWhenNarrow)) {
|
|
441
|
+
const index = this.activeArtifactIndexes.get(binding) ?? 0;
|
|
442
|
+
let panes = this.artifactPanes.get(binding);
|
|
443
|
+
if (!panes)
|
|
444
|
+
this.artifactPanes.set(binding, panes = new Map());
|
|
445
|
+
let artifactPane = panes.get(index);
|
|
446
|
+
if (!artifactPane) {
|
|
447
|
+
artifactPane = new ArtifactPaneController(artifact.renderArtifact, artifact.styleVersion);
|
|
448
|
+
panes.set(index, artifactPane);
|
|
449
|
+
}
|
|
408
450
|
this.split = {
|
|
409
451
|
binding,
|
|
410
452
|
coordinator: new SplitInquiryCoordinator({
|
|
411
453
|
inquirySide: artifact.inquirySide,
|
|
412
|
-
inquiryPane: new InquiryPaneController(fork),
|
|
413
|
-
artifactPane
|
|
454
|
+
inquiryPane: fork ? new InquiryPaneController(fork, this.forks.has(binding)) : this.startingPane(binding),
|
|
455
|
+
artifactPane,
|
|
414
456
|
collapseAt: SPLIT_COLLAPSE_AT_COLS,
|
|
415
457
|
collapseArtifact: artifact.collapseWhenNarrow,
|
|
416
458
|
}),
|
|
417
459
|
};
|
|
418
|
-
fork
|
|
460
|
+
fork?.resize(this.split.coordinator.inquiryWidth(cols), this.split.coordinator.inquiryHeight(cols, rows));
|
|
419
461
|
return;
|
|
420
462
|
}
|
|
421
463
|
this.clearSplitCoordinator();
|
|
422
|
-
fork
|
|
464
|
+
fork?.resize(cols, rows);
|
|
465
|
+
}
|
|
466
|
+
startingPane(binding) {
|
|
467
|
+
return new StartingInquiryPane(this.slots.get(binding).roleLabel);
|
|
423
468
|
}
|
|
424
469
|
focusArtifactForCurrentIssue(binding) {
|
|
425
470
|
if (this.shown !== binding)
|
|
@@ -445,60 +490,98 @@ export class OffscreenController {
|
|
|
445
490
|
this.host.scheduleParentUiRender();
|
|
446
491
|
return;
|
|
447
492
|
}
|
|
448
|
-
|
|
449
|
-
.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
this.
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
this.host.scheduleRender();
|
|
493
|
+
if (this.shown && this.shown !== binding)
|
|
494
|
+
this.abortIssueSend(this.shown);
|
|
495
|
+
for (const [key, other] of [...this.forks, ...this.pendingForks]) {
|
|
496
|
+
if (key !== binding)
|
|
497
|
+
other.setVisible(false);
|
|
498
|
+
}
|
|
499
|
+
const fork = this.forks.get(binding);
|
|
500
|
+
const presented = this.presentedFork(binding);
|
|
501
|
+
const layout = this.host.getLayout();
|
|
502
|
+
this.shown = binding;
|
|
503
|
+
this.configurePresentation(binding, presented, layout.columns, layout.childRows);
|
|
504
|
+
if (focusIssueArtifact)
|
|
505
|
+
this.focusArtifactForCurrentIssue(binding);
|
|
506
|
+
presented?.setVisible(true);
|
|
507
|
+
this.updateForkState();
|
|
508
|
+
this.host.scheduleRender();
|
|
509
|
+
if (fork) {
|
|
466
510
|
if (question)
|
|
467
511
|
this.startInquirySend(binding, fork, question);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
this.
|
|
473
|
-
|
|
474
|
-
this.host.scheduleParentUiRender();
|
|
475
|
-
});
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
if (question)
|
|
515
|
+
this.pendingQuestions.set(binding, question);
|
|
516
|
+
this.ensureFork(binding, slot);
|
|
517
|
+
}
|
|
476
518
|
}
|
|
477
519
|
ensureFork(binding, slot) {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
520
|
+
if (this.pending.has(binding))
|
|
521
|
+
return;
|
|
522
|
+
let constructed;
|
|
523
|
+
// The host's coalesced first frame must run before any provider preparation.
|
|
524
|
+
const created = new Promise((resolve) => setImmediate(resolve)).then(async () => {
|
|
525
|
+
this.launchAbort.signal.throwIfAborted();
|
|
526
|
+
const layout = this.host.getLayout();
|
|
527
|
+
return Fork.spawn(slot, this.workdir, this.host, layout.columns, layout.childRows, () => {
|
|
528
|
+
if (!this.disposed && constructed && this.presentedFork(binding) === constructed) {
|
|
529
|
+
this.updateForkState();
|
|
530
|
+
}
|
|
531
|
+
}, this.observerRuns, this.launchAbort.signal, (fork) => {
|
|
532
|
+
constructed = fork;
|
|
533
|
+
if (this.disposed || this.pending.get(binding) !== created) {
|
|
534
|
+
void fork.kill();
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
this.pendingForks.set(binding, fork);
|
|
538
|
+
if (this.shown !== binding)
|
|
539
|
+
return;
|
|
540
|
+
const layout = this.host.getLayout();
|
|
541
|
+
this.configurePresentation(binding, fork, layout.columns, layout.childRows);
|
|
542
|
+
fork.setVisible(true);
|
|
543
|
+
this.updateForkState();
|
|
544
|
+
this.host.scheduleParentUiRender();
|
|
545
|
+
});
|
|
546
|
+
}).then(async (fork) => {
|
|
547
|
+
if (this.disposed || this.pending.get(binding) !== created) {
|
|
548
|
+
await fork.kill();
|
|
549
|
+
return;
|
|
490
550
|
}
|
|
551
|
+
constructed = fork;
|
|
552
|
+
this.pendingForks.delete(binding);
|
|
491
553
|
this.forks.set(binding, fork);
|
|
492
554
|
if (this.tracksTurns) {
|
|
493
555
|
void this.ensureForkSession(binding, fork);
|
|
494
556
|
}
|
|
495
|
-
|
|
557
|
+
if (this.shown === binding) {
|
|
558
|
+
const layout = this.host.getLayout();
|
|
559
|
+
this.configurePresentation(binding, fork, layout.columns, layout.childRows);
|
|
560
|
+
fork.setVisible(true);
|
|
561
|
+
this.updateForkState();
|
|
562
|
+
this.host.scheduleRender();
|
|
563
|
+
}
|
|
564
|
+
const question = this.pendingQuestions.get(binding);
|
|
565
|
+
this.pendingQuestions.delete(binding);
|
|
566
|
+
if (question)
|
|
567
|
+
this.startInquirySend(binding, fork, question);
|
|
496
568
|
}).catch((err) => {
|
|
497
|
-
this.
|
|
498
|
-
|
|
569
|
+
if (this.disposed && err === this.launchAbort.signal.reason)
|
|
570
|
+
return;
|
|
571
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
572
|
+
this.host.output.warn(`offscreen ${slot.roleLabel} fork failed: ${reason}`);
|
|
573
|
+
if (this.disposed || this.pending.get(binding) !== created)
|
|
574
|
+
return;
|
|
575
|
+
this.pendingQuestions.delete(binding);
|
|
576
|
+
this.clearSendPending(binding);
|
|
577
|
+
this.pendingForks.delete(binding);
|
|
578
|
+
if (this.shown === binding)
|
|
579
|
+
this.hideFork();
|
|
580
|
+
}).finally(() => {
|
|
581
|
+
if (this.pending.get(binding) === created)
|
|
582
|
+
this.pending.delete(binding);
|
|
499
583
|
});
|
|
500
584
|
this.pending.set(binding, created);
|
|
501
|
-
return created;
|
|
502
585
|
}
|
|
503
586
|
startInquirySend(binding, fork, question) {
|
|
504
587
|
if (this.disposed || this.sendControllers.has(binding))
|
|
@@ -515,13 +598,16 @@ export class OffscreenController {
|
|
|
515
598
|
composer,
|
|
516
599
|
beforeSubmit: async () => {
|
|
517
600
|
await this.turnMonitors.get(binding)?.refreshExpiredAttempts();
|
|
601
|
+
controller.signal.throwIfAborted();
|
|
602
|
+
this.launchAbort.signal.throwIfAborted();
|
|
518
603
|
receipt = this.reserveTurn(binding);
|
|
519
604
|
},
|
|
520
605
|
onSubmitWritten: () => receipt?.markWritten(),
|
|
521
606
|
onSubmitted: () => {
|
|
522
607
|
submitted = true;
|
|
523
608
|
receipt?.confirm();
|
|
524
|
-
this.
|
|
609
|
+
if (!this.disposed && this.sendControllers.get(binding) === controller)
|
|
610
|
+
this.clearSendPending(binding);
|
|
525
611
|
},
|
|
526
612
|
}).catch((err) => {
|
|
527
613
|
if (!controller.signal.aborted) {
|
|
@@ -530,6 +616,8 @@ export class OffscreenController {
|
|
|
530
616
|
}
|
|
531
617
|
}).finally(() => {
|
|
532
618
|
receipt?.release();
|
|
619
|
+
if (this.disposed)
|
|
620
|
+
return;
|
|
533
621
|
if (receipt?.settlement === "released") {
|
|
534
622
|
const remaining = (this.pendingTurns.get(binding) ?? []).filter((pending) => pending !== receipt);
|
|
535
623
|
if (remaining.length > 0)
|
|
@@ -538,9 +626,9 @@ export class OffscreenController {
|
|
|
538
626
|
this.pendingTurns.delete(binding);
|
|
539
627
|
this.refreshStagedActivity(binding);
|
|
540
628
|
}
|
|
541
|
-
if (this.sendControllers.get(binding)
|
|
542
|
-
|
|
543
|
-
|
|
629
|
+
if (this.sendControllers.get(binding) !== controller)
|
|
630
|
+
return;
|
|
631
|
+
this.sendControllers.delete(binding);
|
|
544
632
|
this.sendLocks.delete(binding);
|
|
545
633
|
if (!submitted)
|
|
546
634
|
this.clearSendPending(binding);
|
|
@@ -556,7 +644,8 @@ export class OffscreenController {
|
|
|
556
644
|
clearSendPending(binding) {
|
|
557
645
|
if (!this.sendPending.delete(binding))
|
|
558
646
|
return;
|
|
559
|
-
this.
|
|
647
|
+
if (!this.disposed)
|
|
648
|
+
this.host.scheduleParentUiRender();
|
|
560
649
|
}
|
|
561
650
|
reserveTurn(binding, rawAttempt = false) {
|
|
562
651
|
const pendingChanged = this.sendPending.delete(binding);
|
|
@@ -619,8 +708,9 @@ export class OffscreenController {
|
|
|
619
708
|
const turnChanged = !this.turnInProgress.has(binding);
|
|
620
709
|
this.turnInProgress.add(binding);
|
|
621
710
|
const fork = this.forks.get(binding);
|
|
622
|
-
if (!this.
|
|
623
|
-
|
|
711
|
+
if (!this.turnMonitors.has(binding)
|
|
712
|
+
&& (!this.forkSessionFiles.has(binding)
|
|
713
|
+
|| (fork && this.needsSubmitFloor(binding, fork)))) {
|
|
624
714
|
if (fork) {
|
|
625
715
|
this.forkLocateAborts.get(binding)?.abort();
|
|
626
716
|
this.forkSession.delete(binding);
|
|
@@ -649,6 +739,17 @@ export class OffscreenController {
|
|
|
649
739
|
const abort = new AbortController();
|
|
650
740
|
this.forkLocateAborts.set(binding, abort);
|
|
651
741
|
const promise = (async () => {
|
|
742
|
+
const liveMonitor = fork.createTurnMonitor?.(this.forkMonitorOptions(binding));
|
|
743
|
+
if (liveMonitor) {
|
|
744
|
+
this.installForkTurnMonitor(binding, liveMonitor);
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
const policy = resolveProvider(fork.driver).forkSubmitFloor;
|
|
748
|
+
if (!policy) {
|
|
749
|
+
if (this.turnInProgress.has(binding))
|
|
750
|
+
this.warnForkSessionUnavailable(binding);
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
652
753
|
await this.captureForkSubmitFloor(binding, fork, abort.signal);
|
|
653
754
|
if (this.disposed || abort.signal.aborted)
|
|
654
755
|
return;
|
|
@@ -673,7 +774,6 @@ export class OffscreenController {
|
|
|
673
774
|
}
|
|
674
775
|
}
|
|
675
776
|
else {
|
|
676
|
-
const policy = resolveProvider(fork.driver).forkSubmitFloor;
|
|
677
777
|
while (!this.disposed && !abort.signal.aborted && this.needsTurnObservation(binding)) {
|
|
678
778
|
let lines;
|
|
679
779
|
try {
|
|
@@ -711,7 +811,8 @@ export class OffscreenController {
|
|
|
711
811
|
return promise;
|
|
712
812
|
}
|
|
713
813
|
async captureForkSubmitFloor(binding, fork, signal) {
|
|
714
|
-
|
|
814
|
+
const policy = resolveProvider(fork.driver).forkSubmitFloor;
|
|
815
|
+
if (!policy || policy.from !== "source")
|
|
715
816
|
return;
|
|
716
817
|
if (this.forkSubmitFloors.has(binding))
|
|
717
818
|
return;
|
|
@@ -775,6 +876,8 @@ export class OffscreenController {
|
|
|
775
876
|
void this.ensureForkSession(binding, fork);
|
|
776
877
|
return;
|
|
777
878
|
}
|
|
879
|
+
if (!resolveProvider(fork.driver).forkSubmitFloor)
|
|
880
|
+
return;
|
|
778
881
|
const providerFork = resolveProvider(fork.driver).fork;
|
|
779
882
|
const effectiveSubmitCount = providerFork.forkFileSubmitFloor
|
|
780
883
|
? (lines) => Math.max(0, submitCount(fork.driver, lines) -
|
|
@@ -786,6 +889,14 @@ export class OffscreenController {
|
|
|
786
889
|
submitFloor: this.forkSubmitFloors.get(binding),
|
|
787
890
|
submitCount: effectiveSubmitCount,
|
|
788
891
|
readResult: readSessionFileWithStatus,
|
|
892
|
+
...this.forkMonitorOptions(binding),
|
|
893
|
+
});
|
|
894
|
+
this.installForkTurnMonitor(binding, monitor);
|
|
895
|
+
}
|
|
896
|
+
forkMonitorOptions(binding) {
|
|
897
|
+
return {
|
|
898
|
+
pollMs: this.turnPollMs,
|
|
899
|
+
attemptTimeoutMs: this.turnAttemptTimeoutMs,
|
|
789
900
|
onReadFailure: () => this.warnForkSessionUnavailable(binding),
|
|
790
901
|
onHistorySnapshot: (snapshot) => {
|
|
791
902
|
this.forkBaselines.set(binding, snapshot.lineCount);
|
|
@@ -802,27 +913,36 @@ export class OffscreenController {
|
|
|
802
913
|
}
|
|
803
914
|
return;
|
|
804
915
|
}
|
|
805
|
-
this.
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
916
|
+
const monitor = this.turnMonitors.get(binding);
|
|
917
|
+
if (monitor) {
|
|
918
|
+
this.forkBaselines.set(binding, monitor.lineBaseline);
|
|
919
|
+
const submitFloor = monitor.currentSubmitFloor;
|
|
920
|
+
if (submitFloor !== undefined) {
|
|
921
|
+
this.forkSubmitFloors.set(binding, submitFloor);
|
|
922
|
+
}
|
|
809
923
|
}
|
|
810
924
|
this.releaseTurn(binding);
|
|
811
925
|
},
|
|
812
|
-
}
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
installForkTurnMonitor(binding, monitor, initialLines) {
|
|
813
929
|
this.turnMonitors.set(binding, monitor);
|
|
814
930
|
const pending = this.pendingTurns.get(binding) ?? [];
|
|
815
931
|
this.clearStagedAttemptTimers(binding);
|
|
816
932
|
this.pendingTurns.delete(binding);
|
|
817
933
|
monitor.attachTurns(pending, initialLines);
|
|
818
934
|
}
|
|
819
|
-
needsSubmitFloor(binding,
|
|
935
|
+
needsSubmitFloor(binding, fork) {
|
|
936
|
+
if (!resolveProvider(fork.driver).forkSubmitFloor)
|
|
937
|
+
return false;
|
|
820
938
|
return !this.forkSubmitFloors.has(binding);
|
|
821
939
|
}
|
|
822
940
|
clearTurnPoll(binding) {
|
|
823
941
|
const monitor = this.turnMonitors.get(binding);
|
|
824
942
|
if (monitor) {
|
|
825
|
-
if (monitor.supportsHistoryRegression
|
|
943
|
+
if (monitor.supportsHistoryRegression
|
|
944
|
+
|| monitor.hasUnobservedExpiredAttempts
|
|
945
|
+
|| monitor.classifyDeliverySince)
|
|
826
946
|
return;
|
|
827
947
|
monitor.dispose();
|
|
828
948
|
this.turnMonitors.delete(binding);
|
|
@@ -855,6 +975,7 @@ export class OffscreenController {
|
|
|
855
975
|
this.host.output.warn(`offscreen inquiry fork session unavailable for ${binding}; inquiry remains busy`);
|
|
856
976
|
}
|
|
857
977
|
abortIssueSend(binding) {
|
|
978
|
+
this.pendingQuestions.delete(binding);
|
|
858
979
|
const controller = this.sendControllers.get(binding);
|
|
859
980
|
if (controller) {
|
|
860
981
|
controller.abort(new Error("Inquiry send aborted"));
|
|
@@ -889,7 +1010,7 @@ export class OffscreenController {
|
|
|
889
1010
|
}
|
|
890
1011
|
updateVisibleMouseModes() {
|
|
891
1012
|
const fork = this.shown ? this.forks.get(this.shown) : undefined;
|
|
892
|
-
if (!
|
|
1013
|
+
if (!this.shown) {
|
|
893
1014
|
this.host.clearMouseModeSource(OFFSCREEN_MOUSE_SOURCE);
|
|
894
1015
|
return;
|
|
895
1016
|
}
|
|
@@ -901,7 +1022,7 @@ export class OffscreenController {
|
|
|
901
1022
|
this.updateVisibleMouseModes();
|
|
902
1023
|
}
|
|
903
1024
|
visibleMouseModes(fork) {
|
|
904
|
-
const modes = fork
|
|
1025
|
+
const modes = fork?.mouseModes() ?? [];
|
|
905
1026
|
const coordinator = this.activeCoordinator();
|
|
906
1027
|
if (!coordinator)
|
|
907
1028
|
return modes;
|