@adhdev/daemon-core 0.9.82-rc.354 → 0.9.82-rc.355
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/index.js +571 -202
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +571 -202
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-event-trace.d.ts +21 -0
- package/dist/mesh/mesh-runtime-store.d.ts +1 -1
- package/dist/mesh/mesh-work-queue.d.ts +1 -1
- package/dist/providers/cli-provider-instance.d.ts +2 -0
- package/dist/providers/spec/adapter.d.ts +22 -0
- package/dist/providers/spec/fsm-driver.d.ts +49 -7
- package/dist/providers/spec/fsm-evaluator.d.ts +4 -0
- package/dist/providers/spec/types.d.ts +9 -5
- package/package.json +2 -2
- package/src/commands/router.ts +19 -6
- package/src/mesh/mesh-event-trace.ts +67 -0
- package/src/mesh/mesh-events-coordinator.ts +117 -12
- package/src/mesh/mesh-events-pending.ts +33 -0
- package/src/mesh/mesh-events-stale.ts +3 -1
- package/src/mesh/mesh-reconcile-loop.ts +47 -0
- package/src/mesh/mesh-runtime-store.ts +18 -2
- package/src/mesh/mesh-work-queue.ts +8 -1
- package/src/providers/cli-provider-instance.ts +69 -4
- package/src/providers/spec/adapter.ts +67 -0
- package/src/providers/spec/cli-adapter.ts +6 -0
- package/src/providers/spec/evaluator.ts +24 -9
- package/src/providers/spec/fsm-driver.ts +135 -13
- package/src/providers/spec/fsm-evaluator.ts +19 -2
- package/src/providers/spec/types.ts +9 -5
package/dist/index.js
CHANGED
|
@@ -316,10 +316,10 @@ function readInjected(value) {
|
|
|
316
316
|
}
|
|
317
317
|
function getDaemonBuildInfo() {
|
|
318
318
|
if (cached) return cached;
|
|
319
|
-
const commit = readInjected(true ? "
|
|
320
|
-
const commitShort = readInjected(true ? "
|
|
321
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
322
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
319
|
+
const commit = readInjected(true ? "a45106605e2ae1c10c0bc6cbe48c2cac4e862ded" : void 0) ?? "unknown";
|
|
320
|
+
const commitShort = readInjected(true ? "a4510660" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
321
|
+
const version = readInjected(true ? "0.9.82-rc.355" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
322
|
+
const builtAt = readInjected(true ? "2026-06-22T15:21:19.981Z" : void 0);
|
|
323
323
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
324
324
|
return cached;
|
|
325
325
|
}
|
|
@@ -4827,9 +4827,12 @@ function getActiveDirectDispatches(meshId) {
|
|
|
4827
4827
|
return [];
|
|
4828
4828
|
}
|
|
4829
4829
|
}
|
|
4830
|
-
function updateDirectDispatchStatus(meshId, sessionId, status) {
|
|
4830
|
+
function updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
|
|
4831
4831
|
try {
|
|
4832
|
-
|
|
4832
|
+
if (!taskId) {
|
|
4833
|
+
LOG.warn("MeshQueue", `updateDirectDispatchStatus(${status}) for mesh ${meshId} session ${sessionId} has no taskId \u2014 falling back to session_id match (may flip a sibling dispatch row)`);
|
|
4834
|
+
}
|
|
4835
|
+
MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status, taskId);
|
|
4833
4836
|
} catch {
|
|
4834
4837
|
}
|
|
4835
4838
|
}
|
|
@@ -5662,9 +5665,25 @@ var init_mesh_runtime_store = __esm({
|
|
|
5662
5665
|
updatedAt: r.updated_at
|
|
5663
5666
|
}));
|
|
5664
5667
|
}
|
|
5665
|
-
|
|
5666
|
-
|
|
5668
|
+
// CANON-B (dispatch identity): mesh_direct_dispatches is keyed by task_id (PK), but a
|
|
5669
|
+
// single session can host several sequential direct dispatches (re-dispatch / nudge), so
|
|
5670
|
+
// matching a status flip by session_id alone hits EVERY non-terminal row for that session
|
|
5671
|
+
// — flipping a sibling task's row and stranding the one whose event actually fired (the
|
|
5672
|
+
// assigned-stranded watchdog then requeues a task that is really still generating). When
|
|
5673
|
+
// the firing event carries a taskId, target the single PK row; the session_id match is the
|
|
5674
|
+
// legacy fallback only for events that arrive without a taskId.
|
|
5675
|
+
updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
|
|
5667
5676
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5677
|
+
if (taskId) {
|
|
5678
|
+
this.db.prepare(`
|
|
5679
|
+
UPDATE mesh_direct_dispatches
|
|
5680
|
+
SET status = @status, updated_at = @updatedAt
|
|
5681
|
+
WHERE mesh_id = @meshId AND task_id = @taskId
|
|
5682
|
+
AND status NOT IN ('completed', 'failed')
|
|
5683
|
+
`).run({ status, meshId, taskId, updatedAt: now });
|
|
5684
|
+
return;
|
|
5685
|
+
}
|
|
5686
|
+
if (!sessionId) return;
|
|
5668
5687
|
this.db.prepare(`
|
|
5669
5688
|
UPDATE mesh_direct_dispatches
|
|
5670
5689
|
SET status = @status, updated_at = @updatedAt
|
|
@@ -7390,7 +7409,7 @@ function resolveWin32Executable(command) {
|
|
|
7390
7409
|
windowsHide: true
|
|
7391
7410
|
}).trim();
|
|
7392
7411
|
if (out) {
|
|
7393
|
-
const matches = out.split(/\r?\n/).map((
|
|
7412
|
+
const matches = out.split(/\r?\n/).map((s2) => s2.trim()).filter(Boolean);
|
|
7394
7413
|
const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
|
|
7395
7414
|
return direct || matches[0] || command;
|
|
7396
7415
|
}
|
|
@@ -8742,11 +8761,29 @@ function hasPendingRefineTerminalEventDuplicate(event) {
|
|
|
8742
8761
|
(pending) => pending.event === event.event && readRefineJobId2(pending) === jobId
|
|
8743
8762
|
);
|
|
8744
8763
|
}
|
|
8764
|
+
function isWeakCompletionMetadata(metadata) {
|
|
8765
|
+
const evidenceLevel = readNonEmptyString2(metadata.evidenceLevel);
|
|
8766
|
+
if (evidenceLevel === "insufficient" || evidenceLevel === "weak") return true;
|
|
8767
|
+
if (metadata.reviewRecommended === true) return true;
|
|
8768
|
+
const diag = readRecord4(metadata.completionDiagnostic);
|
|
8769
|
+
return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
|
|
8770
|
+
}
|
|
8745
8771
|
function buildPendingEventFingerprint(event) {
|
|
8746
8772
|
const metadata = readRecord4(event.metadataEvent) || {};
|
|
8747
8773
|
if (event.event === "worktree_bootstrap_complete" || event.event === "worktree_bootstrap_failed") {
|
|
8748
8774
|
return [event.meshId, event.event, event.nodeId || ""].join("::");
|
|
8749
8775
|
}
|
|
8776
|
+
if (TERMINAL_COMPLETION_EVENTS.has(event.event)) {
|
|
8777
|
+
const terminalTaskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
|
|
8778
|
+
if (terminalTaskId) {
|
|
8779
|
+
return [
|
|
8780
|
+
event.meshId,
|
|
8781
|
+
event.event,
|
|
8782
|
+
terminalTaskId,
|
|
8783
|
+
isWeakCompletionMetadata(metadata) ? "weak" : "genuine"
|
|
8784
|
+
].join("::");
|
|
8785
|
+
}
|
|
8786
|
+
}
|
|
8750
8787
|
const sessionId = resolveEventSessionId(metadata);
|
|
8751
8788
|
const providerSessionId = readNonEmptyString2(metadata.providerSessionId);
|
|
8752
8789
|
const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
|
|
@@ -9105,7 +9142,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
9105
9142
|
}
|
|
9106
9143
|
}
|
|
9107
9144
|
}
|
|
9108
|
-
var import_fs10, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
|
|
9145
|
+
var import_fs10, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
|
|
9109
9146
|
var init_mesh_events_pending = __esm({
|
|
9110
9147
|
"src/mesh/mesh-events-pending.ts"() {
|
|
9111
9148
|
"use strict";
|
|
@@ -9118,6 +9155,7 @@ var init_mesh_events_pending = __esm({
|
|
|
9118
9155
|
init_mesh_events_utils();
|
|
9119
9156
|
init_dist();
|
|
9120
9157
|
REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
|
|
9158
|
+
TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
|
|
9121
9159
|
MAX_PENDING_EVENTS_BYTES = 100 * 1024;
|
|
9122
9160
|
MAX_PENDING_EVENTS_KEEP = 50;
|
|
9123
9161
|
}
|
|
@@ -9447,7 +9485,7 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
|
|
|
9447
9485
|
evidence
|
|
9448
9486
|
}
|
|
9449
9487
|
});
|
|
9450
|
-
updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
|
|
9488
|
+
updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed", args.taskId);
|
|
9451
9489
|
markSessionDeliveriesTerminal(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
|
|
9452
9490
|
setImmediate(() => cleanupTerminalDirectDispatches());
|
|
9453
9491
|
queuePendingMeshCoordinatorEvent({
|
|
@@ -9737,8 +9775,8 @@ function parsePatternEntry(x) {
|
|
|
9737
9775
|
if (x instanceof RegExp) return x;
|
|
9738
9776
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
9739
9777
|
try {
|
|
9740
|
-
const
|
|
9741
|
-
return new RegExp(
|
|
9778
|
+
const s2 = x;
|
|
9779
|
+
return new RegExp(s2.source, s2.flags || "");
|
|
9742
9780
|
} catch {
|
|
9743
9781
|
return null;
|
|
9744
9782
|
}
|
|
@@ -10309,6 +10347,38 @@ var init_mesh_unresolved_forward_outbox = __esm({
|
|
|
10309
10347
|
}
|
|
10310
10348
|
});
|
|
10311
10349
|
|
|
10350
|
+
// src/mesh/mesh-event-trace.ts
|
|
10351
|
+
function s(v) {
|
|
10352
|
+
return typeof v === "string" && v.trim() ? v.trim() : "";
|
|
10353
|
+
}
|
|
10354
|
+
function meshEventTraceKey(ctx) {
|
|
10355
|
+
const segs = [`task=${s(ctx.taskId) || "-"}`];
|
|
10356
|
+
const eventId = s(ctx.eventId);
|
|
10357
|
+
if (eventId) segs.push(`evt=${eventId}`);
|
|
10358
|
+
segs.push(`sess=${s(ctx.sessionId) || "-"}`);
|
|
10359
|
+
const nodeId = s(ctx.nodeId);
|
|
10360
|
+
if (nodeId) segs.push(`node=${nodeId}`);
|
|
10361
|
+
const meshId = s(ctx.meshId);
|
|
10362
|
+
if (meshId) segs.push(`mesh=${meshId}`);
|
|
10363
|
+
const event = s(ctx.event);
|
|
10364
|
+
if (event) segs.push(`event=${event}`);
|
|
10365
|
+
return segs.join(" ");
|
|
10366
|
+
}
|
|
10367
|
+
function traceMeshEventStage(stage, ctx, detail) {
|
|
10368
|
+
LOG.info(CAT, `[stage:${stage}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
10369
|
+
}
|
|
10370
|
+
function traceMeshEventDrop(reason, ctx, detail) {
|
|
10371
|
+
LOG.warn(CAT, `[drop:${reason}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
10372
|
+
}
|
|
10373
|
+
var CAT;
|
|
10374
|
+
var init_mesh_event_trace = __esm({
|
|
10375
|
+
"src/mesh/mesh-event-trace.ts"() {
|
|
10376
|
+
"use strict";
|
|
10377
|
+
init_logger();
|
|
10378
|
+
CAT = "EvtTrace";
|
|
10379
|
+
}
|
|
10380
|
+
});
|
|
10381
|
+
|
|
10312
10382
|
// src/config/state-store.ts
|
|
10313
10383
|
function isPlainObject2(value) {
|
|
10314
10384
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -12094,9 +12164,9 @@ function buildAcpSession(state, options) {
|
|
|
12094
12164
|
}
|
|
12095
12165
|
function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
12096
12166
|
const sessions = [];
|
|
12097
|
-
const ideStates = allStates.filter((
|
|
12098
|
-
const cliStates = allStates.filter((
|
|
12099
|
-
const acpStates = allStates.filter((
|
|
12167
|
+
const ideStates = allStates.filter((s2) => s2.category === "ide");
|
|
12168
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli");
|
|
12169
|
+
const acpStates = allStates.filter((s2) => s2.category === "acp");
|
|
12100
12170
|
for (const state of ideStates) {
|
|
12101
12171
|
sessions.push(buildWorkspaceSession(state, cdpManagers, options));
|
|
12102
12172
|
for (const ext of state.extensions) {
|
|
@@ -12580,6 +12650,15 @@ function getCachedMeshByWorkspace(workspace) {
|
|
|
12580
12650
|
meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
|
|
12581
12651
|
return mesh;
|
|
12582
12652
|
}
|
|
12653
|
+
function recoverMeshIdByNodeId(nodeId) {
|
|
12654
|
+
if (!nodeId) return "";
|
|
12655
|
+
for (const mesh of listMeshes()) {
|
|
12656
|
+
if (Array.isArray(mesh.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, nodeId))) {
|
|
12657
|
+
return readNonEmptyString2(mesh.id);
|
|
12658
|
+
}
|
|
12659
|
+
}
|
|
12660
|
+
return "";
|
|
12661
|
+
}
|
|
12583
12662
|
function __resetIdleAutoFastForwardForTests() {
|
|
12584
12663
|
idleAutoFastForwardLastAttempt.clear();
|
|
12585
12664
|
}
|
|
@@ -13482,6 +13561,13 @@ function shouldForceInjectMeshEvent(eventName) {
|
|
|
13482
13561
|
function injectMeshSystemMessage(components, args) {
|
|
13483
13562
|
const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
13484
13563
|
const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
13564
|
+
const traceCtx = {
|
|
13565
|
+
taskId: args.metadataEvent.taskId,
|
|
13566
|
+
sessionId: eventSessionId,
|
|
13567
|
+
nodeId: eventNodeId,
|
|
13568
|
+
meshId: args.meshId,
|
|
13569
|
+
event: args.event
|
|
13570
|
+
};
|
|
13485
13571
|
const sourceSession = args.sourceInstanceId ? components.instanceManager.getInstance(args.sourceInstanceId) : void 0;
|
|
13486
13572
|
const workerCoordinatorDaemonId = readNonEmptyString2(
|
|
13487
13573
|
sourceSession?.getState()?.settings?.meshCoordinatorDaemonId
|
|
@@ -13535,6 +13621,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13535
13621
|
}
|
|
13536
13622
|
}
|
|
13537
13623
|
LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
|
|
13624
|
+
traceMeshEventDrop("intentional_cleanup_stop", traceCtx);
|
|
13538
13625
|
return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
|
|
13539
13626
|
}
|
|
13540
13627
|
if (args.event === "monitor:no_progress") {
|
|
@@ -13555,6 +13642,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13555
13642
|
}
|
|
13556
13643
|
if (reconciledCompletion?.source === "no_progress_terminal_ledger_suppression") {
|
|
13557
13644
|
LOG.info("MeshEvents", `Suppressed no-progress monitor because terminal ledger evidence already exists for session ${eventSessionId || "(unknown session)"}`);
|
|
13645
|
+
traceMeshEventDrop("no_progress_terminal_ledger_suppression", traceCtx, `terminalKind=${reconciledCompletion.terminalLedgerKind}`);
|
|
13558
13646
|
return {
|
|
13559
13647
|
success: true,
|
|
13560
13648
|
forwarded: 0,
|
|
@@ -13566,6 +13654,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13566
13654
|
}
|
|
13567
13655
|
if (isDuplicateRefineTerminalEvent(args.meshId, args.event, args.metadataEvent)) {
|
|
13568
13656
|
LOG.info("MeshEvents", `Suppressed duplicate ${args.event} for refine job ${readRefineJobId({ metadataEvent: args.metadataEvent })}`);
|
|
13657
|
+
traceMeshEventDrop("duplicate_refine_terminal", traceCtx);
|
|
13569
13658
|
return { success: true, forwarded: 0, suppressed: true, duplicateRefineTerminalEvent: true };
|
|
13570
13659
|
}
|
|
13571
13660
|
const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
|
|
@@ -13580,6 +13669,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13580
13669
|
});
|
|
13581
13670
|
if (duplicateApproval) {
|
|
13582
13671
|
LOG.info("MeshEvents", `Suppressed duplicate approval event for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13672
|
+
traceMeshEventDrop("duplicate_approval", traceCtx);
|
|
13583
13673
|
return { success: true, forwarded: 0, suppressed: true, duplicateApproval: true };
|
|
13584
13674
|
}
|
|
13585
13675
|
}
|
|
@@ -13599,6 +13689,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13599
13689
|
const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
|
|
13600
13690
|
if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "no_progress_reconciliation") {
|
|
13601
13691
|
LOG.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13692
|
+
traceMeshEventDrop("duplicate_completion_terminal_ledger", traceCtx);
|
|
13602
13693
|
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
|
|
13603
13694
|
}
|
|
13604
13695
|
}
|
|
@@ -13617,6 +13708,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13617
13708
|
});
|
|
13618
13709
|
if (duplicateCompletion) {
|
|
13619
13710
|
LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13711
|
+
traceMeshEventDrop("duplicate_completion", traceCtx);
|
|
13620
13712
|
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
|
|
13621
13713
|
}
|
|
13622
13714
|
}
|
|
@@ -13635,6 +13727,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13635
13727
|
});
|
|
13636
13728
|
if (duplicateStopped) {
|
|
13637
13729
|
LOG.info("MeshEvents", `Suppressed duplicate stopped event for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13730
|
+
traceMeshEventDrop("duplicate_stopped", traceCtx);
|
|
13638
13731
|
return { success: true, forwarded: 0, suppressed: true, duplicateStopped: true };
|
|
13639
13732
|
}
|
|
13640
13733
|
}
|
|
@@ -13646,7 +13739,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13646
13739
|
});
|
|
13647
13740
|
const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true;
|
|
13648
13741
|
if (!leaveDirectDispatchActive) {
|
|
13649
|
-
updateDirectDispatchStatus(args.meshId, sessionId, outcome);
|
|
13742
|
+
updateDirectDispatchStatus(args.meshId, sessionId, outcome, eventTaskId);
|
|
13650
13743
|
}
|
|
13651
13744
|
markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
|
|
13652
13745
|
setImmediate(() => cleanupTerminalDirectDispatches());
|
|
@@ -13659,7 +13752,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13659
13752
|
const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
13660
13753
|
const providerType = readNonEmptyString2(args.metadataEvent.providerType);
|
|
13661
13754
|
if (sessionId) {
|
|
13662
|
-
directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13755
|
+
directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13663
13756
|
const isFalseIdle = isFalseIdleCompletion(args.metadataEvent);
|
|
13664
13757
|
completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
|
|
13665
13758
|
if (nodeId && providerType) {
|
|
@@ -13742,7 +13835,8 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13742
13835
|
}
|
|
13743
13836
|
}
|
|
13744
13837
|
if (sessionId) {
|
|
13745
|
-
|
|
13838
|
+
const startedTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
|
|
13839
|
+
updateDirectDispatchStatus(args.meshId, sessionId, "acked", startedTaskId);
|
|
13746
13840
|
const activeDeliveries = (() => {
|
|
13747
13841
|
try {
|
|
13748
13842
|
return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(args.meshId, sessionId);
|
|
@@ -13750,7 +13844,8 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13750
13844
|
return [];
|
|
13751
13845
|
}
|
|
13752
13846
|
})();
|
|
13753
|
-
|
|
13847
|
+
const deliveriesToAck = startedTaskId ? activeDeliveries.filter((d) => d.taskId === startedTaskId) : activeDeliveries;
|
|
13848
|
+
for (const d of deliveriesToAck) {
|
|
13754
13849
|
updateSessionDeliveryStatus(d.id, "acked");
|
|
13755
13850
|
}
|
|
13756
13851
|
}
|
|
@@ -13764,7 +13859,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13764
13859
|
}
|
|
13765
13860
|
}
|
|
13766
13861
|
if (sessionId) {
|
|
13767
|
-
directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13862
|
+
directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13768
13863
|
completedTaskForLedger = markSessionTerminal(sessionId, "failed");
|
|
13769
13864
|
}
|
|
13770
13865
|
}
|
|
@@ -13910,6 +14005,9 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13910
14005
|
};
|
|
13911
14006
|
if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
|
|
13912
14007
|
LOG.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ""})`);
|
|
14008
|
+
traceMeshEventStage("queued", traceCtx, workerCoordinatorDaemonId ? `coordinatorDaemon=${workerCoordinatorDaemonId}` : "broadcast");
|
|
14009
|
+
} else {
|
|
14010
|
+
traceMeshEventDrop("queue_dedup", traceCtx);
|
|
13913
14011
|
}
|
|
13914
14012
|
return { success: true, forwarded: 0 };
|
|
13915
14013
|
}
|
|
@@ -13920,8 +14018,23 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
13920
14018
|
}
|
|
13921
14019
|
const nodeId = readNonEmptyString2(payload.nodeId);
|
|
13922
14020
|
const workspace = readNonEmptyString2(payload.workspace);
|
|
13923
|
-
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "");
|
|
13924
|
-
if (!meshId)
|
|
14021
|
+
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId);
|
|
14022
|
+
if (!meshId) {
|
|
14023
|
+
traceMeshEventDrop("meshId_required", {
|
|
14024
|
+
taskId: payload.taskId,
|
|
14025
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
14026
|
+
nodeId,
|
|
14027
|
+
event: eventName
|
|
14028
|
+
}, workspace ? `workspace=${workspace} unresolved` : "no workspace/nodeId");
|
|
14029
|
+
return { success: false, error: "meshId required" };
|
|
14030
|
+
}
|
|
14031
|
+
traceMeshEventStage("received", {
|
|
14032
|
+
taskId: payload.taskId,
|
|
14033
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
14034
|
+
nodeId,
|
|
14035
|
+
meshId,
|
|
14036
|
+
event: eventName
|
|
14037
|
+
});
|
|
13925
14038
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
13926
14039
|
const relayModalMessage = readNonEmptyString2(payload.modalMessage);
|
|
13927
14040
|
const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
|
|
@@ -14002,9 +14115,18 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
14002
14115
|
workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
|
|
14003
14116
|
};
|
|
14004
14117
|
const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
|
|
14118
|
+
const fwdTraceCtx = {
|
|
14119
|
+
taskId: payload.taskId,
|
|
14120
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
14121
|
+
nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId),
|
|
14122
|
+
event: eventName
|
|
14123
|
+
};
|
|
14124
|
+
traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=absent`);
|
|
14125
|
+
traceMeshEventStage("forward_send", fwdTraceCtx, "immediate push");
|
|
14005
14126
|
Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
|
|
14006
14127
|
if (result && result.success === false) {
|
|
14007
14128
|
LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
|
|
14129
|
+
traceMeshEventDrop("immediate_forward_rejected", fwdTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
14008
14130
|
return;
|
|
14009
14131
|
}
|
|
14010
14132
|
if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
|
|
@@ -14072,6 +14194,14 @@ function setupMeshEventForwarding(components) {
|
|
|
14072
14194
|
if (isUnroutableDelegateRejection(routing) && forwardUnresolvedDelegateEvent(components, routing, event)) {
|
|
14073
14195
|
return;
|
|
14074
14196
|
}
|
|
14197
|
+
if (isUnroutableDelegateRejection(routing)) {
|
|
14198
|
+
traceMeshEventDrop("unroutable", {
|
|
14199
|
+
taskId: event.meshActiveTaskId ?? event.taskId,
|
|
14200
|
+
sessionId: routing.sessionId,
|
|
14201
|
+
nodeId: routing.nodeId,
|
|
14202
|
+
event: event.event
|
|
14203
|
+
}, "no coordinator anchor / mesh_unresolved");
|
|
14204
|
+
}
|
|
14075
14205
|
recordUnroutableDelegateEvent(routing, event.event);
|
|
14076
14206
|
return;
|
|
14077
14207
|
}
|
|
@@ -14102,6 +14232,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14102
14232
|
init_mesh_events_pending();
|
|
14103
14233
|
init_mesh_routing();
|
|
14104
14234
|
init_mesh_unresolved_forward_outbox();
|
|
14235
|
+
init_mesh_event_trace();
|
|
14105
14236
|
init_snapshot();
|
|
14106
14237
|
init_repo_mesh_types();
|
|
14107
14238
|
init_dist();
|
|
@@ -14213,6 +14344,13 @@ function findLiveCoordinators(components) {
|
|
|
14213
14344
|
function injectPendingIntoCoordinator(coordinator, pending) {
|
|
14214
14345
|
if (!coordinator || !pending.coordinatorMessage) return;
|
|
14215
14346
|
const force = shouldForceInjectMeshEvent(pending.event);
|
|
14347
|
+
traceMeshEventStage("surfaced", {
|
|
14348
|
+
taskId: pending.metadataEvent?.taskId,
|
|
14349
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? pending.targetCoordinatorSessionId,
|
|
14350
|
+
nodeId: pending.nodeId,
|
|
14351
|
+
meshId: pending.meshId,
|
|
14352
|
+
event: pending.event
|
|
14353
|
+
}, force ? "force-inject" : "inject");
|
|
14216
14354
|
coordinator.onEvent("send_message", {
|
|
14217
14355
|
input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
|
|
14218
14356
|
...force ? { force: true } : {}
|
|
@@ -14271,6 +14409,13 @@ function recoverStrandedAssignedDispatches(meshId, store) {
|
|
|
14271
14409
|
});
|
|
14272
14410
|
if (reclaimed) {
|
|
14273
14411
|
LOG.warn("MeshReconcile", `Reclaimed stranded assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, dispatched ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s ago, never confirmed delivered \u2192 ${reclaimed.status})`);
|
|
14412
|
+
traceMeshEventDrop("assigned_stranded_reclaim", {
|
|
14413
|
+
taskId: row.id,
|
|
14414
|
+
sessionId: row.assignedSessionId,
|
|
14415
|
+
nodeId: row.assignedNodeId,
|
|
14416
|
+
meshId,
|
|
14417
|
+
event: "agent:generating_completed"
|
|
14418
|
+
}, `unconfirmed ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s \u2192 ${reclaimed.status}`);
|
|
14274
14419
|
}
|
|
14275
14420
|
}
|
|
14276
14421
|
}
|
|
@@ -14430,6 +14575,13 @@ function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
|
|
|
14430
14575
|
try {
|
|
14431
14576
|
queuePendingMeshCoordinatorEvent(pending);
|
|
14432
14577
|
LOG.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})`);
|
|
14578
|
+
traceMeshEventDrop("strict_route_hold", {
|
|
14579
|
+
taskId: pending.metadataEvent?.taskId,
|
|
14580
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
|
|
14581
|
+
nodeId: pending.nodeId,
|
|
14582
|
+
meshId,
|
|
14583
|
+
event: pending.event
|
|
14584
|
+
}, `coordinatorSession=${wantSession} not live`);
|
|
14433
14585
|
} catch (e) {
|
|
14434
14586
|
LOG.warn("MeshReconcile", `Strict route re-queue failed for ${pending.event} on mesh ${meshId}: ${e?.message || e}`);
|
|
14435
14587
|
}
|
|
@@ -14453,6 +14605,13 @@ function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
|
|
|
14453
14605
|
}
|
|
14454
14606
|
});
|
|
14455
14607
|
LOG.warn("MeshReconcile", `Strict route expire: coordinator session ${wantSession} never returned for mesh ${meshId} \u2014 recorded to ledger (recoverable), dropped (${pending.event})`);
|
|
14608
|
+
traceMeshEventDrop("strict_route_expired", {
|
|
14609
|
+
taskId: pending.metadataEvent?.taskId,
|
|
14610
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
|
|
14611
|
+
nodeId: pending.nodeId,
|
|
14612
|
+
meshId,
|
|
14613
|
+
event: pending.event
|
|
14614
|
+
}, `coordinatorSession=${wantSession} never returned`);
|
|
14456
14615
|
} catch (e) {
|
|
14457
14616
|
LOG.warn("MeshReconcile", `Failed to ledger-expire strict-unmatched ${pending.event} for mesh ${meshId}: ${e?.message || e}`);
|
|
14458
14617
|
}
|
|
@@ -14464,15 +14623,24 @@ async function retryUnresolvedDelegateForwards(components) {
|
|
|
14464
14623
|
const entries = peekUnresolvedDelegateForwards();
|
|
14465
14624
|
if (entries.length === 0) return;
|
|
14466
14625
|
for (const entry of entries) {
|
|
14626
|
+
const entryTraceCtx = {
|
|
14627
|
+
taskId: entry.payload.taskId,
|
|
14628
|
+
sessionId: readNonEmptyString2(entry.payload.targetSessionId) || readNonEmptyString2(entry.payload.sessionId),
|
|
14629
|
+
nodeId: readNonEmptyString2(entry.payload.nodeId),
|
|
14630
|
+
event: readNonEmptyString2(entry.payload.event)
|
|
14631
|
+
};
|
|
14467
14632
|
let result;
|
|
14468
14633
|
try {
|
|
14634
|
+
traceMeshEventStage("forward_send", entryTraceCtx, `retry \u2192 ${entry.coordinatorDaemonId}`);
|
|
14469
14635
|
result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
|
|
14470
14636
|
} catch (e) {
|
|
14471
14637
|
LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
|
|
14638
|
+
traceMeshEventDrop("retry_forward_failed", entryTraceCtx, e?.message || String(e));
|
|
14472
14639
|
continue;
|
|
14473
14640
|
}
|
|
14474
14641
|
if (result && result.success === false) {
|
|
14475
14642
|
LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
|
|
14643
|
+
traceMeshEventDrop("retry_forward_rejected", entryTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
14476
14644
|
continue;
|
|
14477
14645
|
}
|
|
14478
14646
|
ackUnresolvedDelegateForward(entry.id);
|
|
@@ -14714,6 +14882,7 @@ var init_mesh_reconcile_loop = __esm({
|
|
|
14714
14882
|
init_mesh_events_coordinator();
|
|
14715
14883
|
init_mesh_unresolved_forward_outbox();
|
|
14716
14884
|
init_mesh_events_utils();
|
|
14885
|
+
init_mesh_event_trace();
|
|
14717
14886
|
init_dist();
|
|
14718
14887
|
init_mesh_work_queue();
|
|
14719
14888
|
init_mesh_ledger();
|
|
@@ -15549,8 +15718,8 @@ function saveProvidersActive(file) {
|
|
|
15549
15718
|
}
|
|
15550
15719
|
function isValidSource(x) {
|
|
15551
15720
|
if (!x || typeof x !== "object") return false;
|
|
15552
|
-
const
|
|
15553
|
-
return typeof
|
|
15721
|
+
const s2 = x;
|
|
15722
|
+
return typeof s2.name === "string" && s2.name.length > 0 && typeof s2.url === "string" && s2.url.length > 0 && typeof s2.ref === "string" && s2.ref.length > 0 && typeof s2.addedAt === "string";
|
|
15554
15723
|
}
|
|
15555
15724
|
function deriveSourceName(url) {
|
|
15556
15725
|
const m = url.match(/[/:]([^/:]+)\/([^/]+?)(?:\.git)?$/);
|
|
@@ -15606,7 +15775,7 @@ function inventoryExternalSources() {
|
|
|
15606
15775
|
}
|
|
15607
15776
|
function sourcesProviding(category, type) {
|
|
15608
15777
|
const inventory = inventoryExternalSources();
|
|
15609
|
-
return inventory.filter((
|
|
15778
|
+
return inventory.filter((s2) => (s2.providers[category] || []).includes(type)).map((s2) => s2.sourceName);
|
|
15610
15779
|
}
|
|
15611
15780
|
function resolveActiveSource(category, type, activeFile) {
|
|
15612
15781
|
const candidates = sourcesProviding(category, type);
|
|
@@ -15813,10 +15982,10 @@ function compileSettledPromptMatchers(spec) {
|
|
|
15813
15982
|
const footers = (spec.withFooter ?? []).map((f) => {
|
|
15814
15983
|
if (f.kind === "regex") {
|
|
15815
15984
|
const re = compile2(f.pattern, f.flags ?? "i");
|
|
15816
|
-
return { test: (
|
|
15985
|
+
return { test: (s2) => re.test(s2) };
|
|
15817
15986
|
}
|
|
15818
15987
|
const needle = f.pattern.toLowerCase();
|
|
15819
|
-
return { test: (
|
|
15988
|
+
return { test: (s2) => s2.toLowerCase().includes(needle) };
|
|
15820
15989
|
});
|
|
15821
15990
|
return { prompt, footers };
|
|
15822
15991
|
}
|
|
@@ -16690,7 +16859,7 @@ var init_cli_state_engine = __esm({
|
|
|
16690
16859
|
}
|
|
16691
16860
|
resolveModal(buttonIndex) {
|
|
16692
16861
|
const snap = this.transport.getSnapshot();
|
|
16693
|
-
const parseApproval = typeof this.transport.runParseApproval === "function" ? (
|
|
16862
|
+
const parseApproval = typeof this.transport.runParseApproval === "function" ? (s2) => this.transport.runParseApproval(s2.recentOutputBuffer.slice(-500)) : (s2) => this.runParseApproval(s2);
|
|
16694
16863
|
let modal = this.activeModal ?? parseApproval(snap);
|
|
16695
16864
|
if (!modal && this.runner.hasParseSession()) {
|
|
16696
16865
|
try {
|
|
@@ -19379,22 +19548,23 @@ function resolveSections(sectionsObj, lines) {
|
|
|
19379
19548
|
const matchesCandidate = (c, i) => c.re.test(lines[i]) && (c.prevRe === null || i > 0 && c.prevRe.test(lines[i - 1])) && (c.nextRe === null || i < total - 1 && c.nextRe.test(lines[i + 1]));
|
|
19380
19549
|
let idx = -1;
|
|
19381
19550
|
for (const c of candidates) {
|
|
19551
|
+
let candIdx = -1;
|
|
19382
19552
|
if (sec.anchor_last) {
|
|
19383
19553
|
for (let i = total - 1; i >= 0; i--) {
|
|
19384
19554
|
if (matchesCandidate(c, i)) {
|
|
19385
|
-
|
|
19555
|
+
candIdx = i;
|
|
19386
19556
|
break;
|
|
19387
19557
|
}
|
|
19388
19558
|
}
|
|
19389
19559
|
} else {
|
|
19390
19560
|
for (let i = 0; i < total; i++) {
|
|
19391
19561
|
if (matchesCandidate(c, i)) {
|
|
19392
|
-
|
|
19562
|
+
candIdx = i;
|
|
19393
19563
|
break;
|
|
19394
19564
|
}
|
|
19395
19565
|
}
|
|
19396
19566
|
}
|
|
19397
|
-
if (
|
|
19567
|
+
if (candIdx !== -1 && (idx === -1 || candIdx < idx)) idx = candIdx;
|
|
19398
19568
|
}
|
|
19399
19569
|
if (idx !== -1) {
|
|
19400
19570
|
from = idx;
|
|
@@ -19446,7 +19616,7 @@ function resolveSections(sectionsObj, lines) {
|
|
|
19446
19616
|
}
|
|
19447
19617
|
function sectionText(sections, sectionId, fullScreen) {
|
|
19448
19618
|
if (!sectionId) return fullScreen;
|
|
19449
|
-
const found = sections.find((
|
|
19619
|
+
const found = sections.find((s2) => s2.id === sectionId);
|
|
19450
19620
|
return found ? found.text : "";
|
|
19451
19621
|
}
|
|
19452
19622
|
function isRegexCondition(c) {
|
|
@@ -19614,10 +19784,10 @@ function isV4Spec(raw) {
|
|
|
19614
19784
|
return !!raw && typeof raw === "object" && raw.$schema === "adhdev:cli/spec@4";
|
|
19615
19785
|
}
|
|
19616
19786
|
function initialState(spec) {
|
|
19617
|
-
return spec.states.find((
|
|
19787
|
+
return spec.states.find((s2) => s2.initial) ?? spec.states[0];
|
|
19618
19788
|
}
|
|
19619
19789
|
function stateById(spec, id) {
|
|
19620
|
-
return spec.states.find((
|
|
19790
|
+
return spec.states.find((s2) => s2.id === id);
|
|
19621
19791
|
}
|
|
19622
19792
|
function outgoingTransitions(spec, stateId) {
|
|
19623
19793
|
const matches = spec.transitions.filter((t) => {
|
|
@@ -19706,7 +19876,17 @@ function evalCond(cond, sections, fullScreen, cursor, prevLines, clock, legacyTr
|
|
|
19706
19876
|
const result = evaluateCondition(cond, sections, fullScreen, cursor, prevLines, legacyTrace, stateId);
|
|
19707
19877
|
const kind = isRegex(cond) ? "regex" : "changed";
|
|
19708
19878
|
const detail = isRegex(cond) ? `${cond.section ?? "*"}~/${cond.matches}/` : `cursor_above=${cond.cursor_above} changed=${cond.changed}`;
|
|
19709
|
-
|
|
19879
|
+
let matchedText;
|
|
19880
|
+
if (result && isRegex(cond)) {
|
|
19881
|
+
try {
|
|
19882
|
+
const hay = sectionText(sections, cond.section, fullScreen);
|
|
19883
|
+
const re = new RegExp(cond.matches, cond.flags ?? "i");
|
|
19884
|
+
const m = re.exec(hay);
|
|
19885
|
+
if (m && m[0]) matchedText = m[0].replace(/\s+/g, " ").trim().slice(0, 160);
|
|
19886
|
+
} catch {
|
|
19887
|
+
}
|
|
19888
|
+
}
|
|
19889
|
+
return matchedText ? { kind, result, detail, matchedText } : { kind, result, detail };
|
|
19710
19890
|
}
|
|
19711
19891
|
return { kind: "all", result: false, detail: "unknown condition" };
|
|
19712
19892
|
}
|
|
@@ -19821,17 +20001,17 @@ function validateFsmSpec(raw) {
|
|
|
19821
20001
|
}
|
|
19822
20002
|
const ids = /* @__PURE__ */ new Set();
|
|
19823
20003
|
let initialCount = 0;
|
|
19824
|
-
for (const [i,
|
|
19825
|
-
if (!
|
|
20004
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
20005
|
+
if (!s2.id) {
|
|
19826
20006
|
errs.push(`states[${i}].id is required`);
|
|
19827
20007
|
continue;
|
|
19828
20008
|
}
|
|
19829
|
-
if (ids.has(
|
|
19830
|
-
ids.add(
|
|
19831
|
-
if (!
|
|
19832
|
-
if (
|
|
19833
|
-
if (
|
|
19834
|
-
errs.push(`states[${i}].status "${
|
|
20009
|
+
if (ids.has(s2.id)) errs.push(`states[${i}].id "${s2.id}" is duplicated`);
|
|
20010
|
+
ids.add(s2.id);
|
|
20011
|
+
if (!s2.label) errs.push(`states[${i}].label is required`);
|
|
20012
|
+
if (s2.initial) initialCount += 1;
|
|
20013
|
+
if (s2.status && !["idle", "generating", "approval"].includes(s2.status)) {
|
|
20014
|
+
errs.push(`states[${i}].status "${s2.status}" must be idle|generating|approval`);
|
|
19835
20015
|
}
|
|
19836
20016
|
}
|
|
19837
20017
|
if (initialCount === 0) errs.push("exactly one state must have initial:true (none found)");
|
|
@@ -19847,10 +20027,10 @@ function validateFsmSpec(raw) {
|
|
|
19847
20027
|
else if (!ids.has(t.to)) errs.push(`transitions[${i}].to references unknown state "${t.to}"`);
|
|
19848
20028
|
if (t.when) errs.push(...validateCondition(t.when, sectionIds, `transitions[${i}].when`));
|
|
19849
20029
|
}
|
|
19850
|
-
for (const [i,
|
|
19851
|
-
const sec =
|
|
20030
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
20031
|
+
const sec = s2.extract?.title?.section;
|
|
19852
20032
|
if (sec && !sectionIds.has(sec)) errs.push(`states[${i}].extract.title.section "${sec}" unknown`);
|
|
19853
|
-
const bsec =
|
|
20033
|
+
const bsec = s2.extract?.buttons?.section;
|
|
19854
20034
|
if (bsec && !sectionIds.has(bsec)) errs.push(`states[${i}].extract.buttons.section "${bsec}" unknown`);
|
|
19855
20035
|
}
|
|
19856
20036
|
return errs;
|
|
@@ -32586,10 +32766,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32586
32766
|
const path42 = require("path");
|
|
32587
32767
|
const { spawnSync: spawnSync2 } = require("child_process");
|
|
32588
32768
|
const file = ext.loadExternalSources();
|
|
32589
|
-
if (file.sources.some((
|
|
32769
|
+
if (file.sources.some((s2) => s2.name === requestedName)) {
|
|
32590
32770
|
return { success: false, error: `source name "${requestedName}" is already registered` };
|
|
32591
32771
|
}
|
|
32592
|
-
if (file.sources.some((
|
|
32772
|
+
if (file.sources.some((s2) => s2.url === url && s2.ref === ref)) {
|
|
32593
32773
|
return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
|
|
32594
32774
|
}
|
|
32595
32775
|
const sourceDir = path42.join(ext.externalRoot(), requestedName);
|
|
@@ -32651,7 +32831,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32651
32831
|
const fs32 = require("fs");
|
|
32652
32832
|
const path42 = require("path");
|
|
32653
32833
|
const file = ext.loadExternalSources();
|
|
32654
|
-
const match = file.sources.find((
|
|
32834
|
+
const match = file.sources.find((s2) => s2.name === name);
|
|
32655
32835
|
if (!match) return { success: false, error: `source "${name}" not registered` };
|
|
32656
32836
|
const sourceDir = path42.join(ext.externalRoot(), name);
|
|
32657
32837
|
if (fs32.existsSync(sourceDir)) {
|
|
@@ -32663,7 +32843,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32663
32843
|
}
|
|
32664
32844
|
ext.saveExternalSources({
|
|
32665
32845
|
schema: 1,
|
|
32666
|
-
sources: file.sources.filter((
|
|
32846
|
+
sources: file.sources.filter((s2) => s2.name !== name)
|
|
32667
32847
|
});
|
|
32668
32848
|
const active = ext.loadProvidersActive();
|
|
32669
32849
|
const filteredActive = {};
|
|
@@ -32687,10 +32867,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32687
32867
|
const file = ext.loadExternalSources();
|
|
32688
32868
|
const inventory = ext.inventoryExternalSources();
|
|
32689
32869
|
const active = ext.loadProvidersActive();
|
|
32690
|
-
const sources = file.sources.map((
|
|
32691
|
-
const inv = inventory.find((e) => e.sourceName ===
|
|
32870
|
+
const sources = file.sources.map((s2) => {
|
|
32871
|
+
const inv = inventory.find((e) => e.sourceName === s2.name);
|
|
32692
32872
|
return {
|
|
32693
|
-
...
|
|
32873
|
+
...s2,
|
|
32694
32874
|
providers: inv?.providers ?? {}
|
|
32695
32875
|
};
|
|
32696
32876
|
});
|
|
@@ -32867,6 +33047,21 @@ var path21 = __toESM(require("path"));
|
|
|
32867
33047
|
// src/providers/spec/adapter.ts
|
|
32868
33048
|
init_terminal_screen();
|
|
32869
33049
|
var import_session_host_core6 = require("@adhdev/session-host-core");
|
|
33050
|
+
var MAX_PTY_EVENTS = 300;
|
|
33051
|
+
var EVENT_CONTENT_CAP = 240;
|
|
33052
|
+
function escapeControl(text) {
|
|
33053
|
+
return String(text).replace(/[\x00-\x1f\x7f]/g, (ch) => {
|
|
33054
|
+
const code = ch.charCodeAt(0);
|
|
33055
|
+
if (ch === "\r") return "\\r";
|
|
33056
|
+
if (ch === "\n") return "\\n";
|
|
33057
|
+
if (ch === " ") return "\\t";
|
|
33058
|
+
if (code === 27) return "\\x1b";
|
|
33059
|
+
return "\\x" + code.toString(16).padStart(2, "0");
|
|
33060
|
+
});
|
|
33061
|
+
}
|
|
33062
|
+
function capPreview(text) {
|
|
33063
|
+
return text.length > EVENT_CONTENT_CAP ? text.slice(0, EVENT_CONTENT_CAP) + `\u2026(+${text.length - EVENT_CONTENT_CAP})` : text;
|
|
33064
|
+
}
|
|
32870
33065
|
var TerminalAdapter = class {
|
|
32871
33066
|
constructor(opts, handlers) {
|
|
32872
33067
|
this.opts = opts;
|
|
@@ -32893,6 +33088,9 @@ var TerminalAdapter = class {
|
|
|
32893
33088
|
screenTimer = null;
|
|
32894
33089
|
tickTimer = null;
|
|
32895
33090
|
lastScreen = "";
|
|
33091
|
+
/** Debug-only ring buffer of PTY input/output/resize/cursor events. */
|
|
33092
|
+
events = [];
|
|
33093
|
+
lastCursorKey = "";
|
|
32896
33094
|
start() {
|
|
32897
33095
|
const env = this.opts.envIsComplete ? this.opts.env ?? {} : { ...process.env, ...this.opts.env ?? {} };
|
|
32898
33096
|
this.pty = this.factory.spawn(this.opts.binary, this.opts.args ?? [], {
|
|
@@ -32901,10 +33099,12 @@ var TerminalAdapter = class {
|
|
|
32901
33099
|
cols: this.cols,
|
|
32902
33100
|
rows: this.rows
|
|
32903
33101
|
});
|
|
33102
|
+
this.recordEvent("spawn", `${this.opts.binary} (${this.cols}x${this.rows})`);
|
|
32904
33103
|
this.handlers.init?.({ pid: this.pty.pid });
|
|
32905
33104
|
this.pty.onData((chunk) => this.onChunk(chunk));
|
|
32906
33105
|
this.pty.onExit((info) => {
|
|
32907
33106
|
this.stopTimers();
|
|
33107
|
+
this.recordEvent("exit", `exitCode=${typeof info.exitCode === "number" ? info.exitCode : 0}`);
|
|
32908
33108
|
this.handlers.on_exit?.({ exitCode: typeof info.exitCode === "number" ? info.exitCode : 0 });
|
|
32909
33109
|
this.pty = null;
|
|
32910
33110
|
});
|
|
@@ -32915,6 +33115,7 @@ var TerminalAdapter = class {
|
|
|
32915
33115
|
resize(cols, rows) {
|
|
32916
33116
|
this.cols = cols;
|
|
32917
33117
|
this.rows = rows;
|
|
33118
|
+
this.recordEvent("resize", `${cols}x${rows}`);
|
|
32918
33119
|
this.pty?.resize(cols, rows);
|
|
32919
33120
|
this.screen.resize(rows, cols);
|
|
32920
33121
|
}
|
|
@@ -32935,8 +33136,21 @@ var TerminalAdapter = class {
|
|
|
32935
33136
|
return { row: pos.row, col: pos.col };
|
|
32936
33137
|
}
|
|
32937
33138
|
send_keys(text) {
|
|
33139
|
+
this.recordEvent("input", capPreview(escapeControl(text)), text.length);
|
|
32938
33140
|
this.pty?.write(text);
|
|
32939
33141
|
}
|
|
33142
|
+
/** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
|
|
33143
|
+
* first. Pure observation — never consulted by the FSM. */
|
|
33144
|
+
getEventTimeline(limit = MAX_PTY_EVENTS) {
|
|
33145
|
+
const n = Math.max(0, Math.min(limit, this.events.length));
|
|
33146
|
+
return this.events.slice(this.events.length - n);
|
|
33147
|
+
}
|
|
33148
|
+
recordEvent(kind, content, bytes) {
|
|
33149
|
+
const ev = { ts: Date.now(), kind, content };
|
|
33150
|
+
if (typeof bytes === "number") ev.bytes = bytes;
|
|
33151
|
+
this.events.push(ev);
|
|
33152
|
+
if (this.events.length > MAX_PTY_EVENTS) this.events.splice(0, this.events.length - MAX_PTY_EVENTS);
|
|
33153
|
+
}
|
|
32940
33154
|
kill() {
|
|
32941
33155
|
this.stopTimers();
|
|
32942
33156
|
try {
|
|
@@ -32947,6 +33161,7 @@ var TerminalAdapter = class {
|
|
|
32947
33161
|
this.screen.dispose();
|
|
32948
33162
|
}
|
|
32949
33163
|
onChunk(chunk) {
|
|
33164
|
+
this.recordEvent("output", capPreview(escapeControl(chunk)), chunk.length);
|
|
32950
33165
|
try {
|
|
32951
33166
|
this.handlers.on_pty_data?.(chunk);
|
|
32952
33167
|
} catch {
|
|
@@ -32956,6 +33171,12 @@ var TerminalAdapter = class {
|
|
|
32956
33171
|
this.screenTimer = setTimeout(() => {
|
|
32957
33172
|
this.screenTimer = null;
|
|
32958
33173
|
const snap = this.computeScreen();
|
|
33174
|
+
const cur = this.screen.getCursorPosition();
|
|
33175
|
+
const curKey = `${cur.row},${cur.col}`;
|
|
33176
|
+
if (curKey !== this.lastCursorKey) {
|
|
33177
|
+
this.lastCursorKey = curKey;
|
|
33178
|
+
this.recordEvent("cursor", `(${cur.row},${cur.col})`);
|
|
33179
|
+
}
|
|
32959
33180
|
if (snap === this.lastScreen) return;
|
|
32960
33181
|
this.lastScreen = snap;
|
|
32961
33182
|
try {
|
|
@@ -33040,20 +33261,40 @@ function applyPreLaunchTrust(trust, workingDir) {
|
|
|
33040
33261
|
|
|
33041
33262
|
// src/providers/spec/fsm-driver.ts
|
|
33042
33263
|
init_logger();
|
|
33043
|
-
function countNewlines(
|
|
33264
|
+
function countNewlines(s2) {
|
|
33044
33265
|
let n = 0;
|
|
33045
|
-
for (let i = 0; i <
|
|
33266
|
+
for (let i = 0; i < s2.length; i += 1) if (s2.charCodeAt(i) === 10) n += 1;
|
|
33046
33267
|
return n;
|
|
33047
33268
|
}
|
|
33048
33269
|
var SUBMIT_DELAY_FLOOR_MS = 200;
|
|
33049
33270
|
var WIN32_SUBMIT_RESEND_GAP_MS = 350;
|
|
33050
33271
|
var WIN32_SUBMIT_MAX_RESENDS = 14;
|
|
33272
|
+
var WIN32_SUBMIT_SETTLE_MS = 500;
|
|
33273
|
+
var WIN32_SUBMIT_MAX_SETTLE_WAIT_MS = 1e4;
|
|
33274
|
+
var WIN32_SUBMIT_SETTLE_POLL_MS = 120;
|
|
33275
|
+
var WIN32_PTY_WRITE_CHUNK_CHARS = 1024;
|
|
33276
|
+
var WIN32_PTY_WRITE_CHUNK_GAP_MS = 8;
|
|
33051
33277
|
function resolveSubmitDelayMs(specBeforeSubmit, text) {
|
|
33052
33278
|
const lines = countNewlines(text);
|
|
33053
33279
|
const linesBonus = Math.min(800, lines * 80);
|
|
33054
33280
|
const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
|
|
33055
33281
|
return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
|
|
33056
33282
|
}
|
|
33283
|
+
function chunkPreservingSurrogates(text, size) {
|
|
33284
|
+
const chunks = [];
|
|
33285
|
+
let offset = 0;
|
|
33286
|
+
while (offset < text.length) {
|
|
33287
|
+
let end = Math.min(text.length, offset + size);
|
|
33288
|
+
if (end < text.length) {
|
|
33289
|
+
const code = text.charCodeAt(end - 1);
|
|
33290
|
+
if (code >= 55296 && code <= 56319) end -= 1;
|
|
33291
|
+
}
|
|
33292
|
+
if (end <= offset) end = Math.min(text.length, offset + size);
|
|
33293
|
+
chunks.push(text.slice(offset, end));
|
|
33294
|
+
offset = end;
|
|
33295
|
+
}
|
|
33296
|
+
return chunks;
|
|
33297
|
+
}
|
|
33057
33298
|
function guessExt(mime) {
|
|
33058
33299
|
if (/png/i.test(mime)) return ".png";
|
|
33059
33300
|
if (/jpe?g/i.test(mime)) return ".jpg";
|
|
@@ -33069,7 +33310,10 @@ var FsmDriver = class {
|
|
|
33069
33310
|
this.buildAdapterOpts(),
|
|
33070
33311
|
{
|
|
33071
33312
|
init: () => this.emitInitialState(),
|
|
33072
|
-
on_pty_data: (chunk) =>
|
|
33313
|
+
on_pty_data: (chunk) => {
|
|
33314
|
+
this.lastPtyDataAt = Date.now();
|
|
33315
|
+
this.emit({ kind: "pty_data", chunk });
|
|
33316
|
+
},
|
|
33073
33317
|
on_screen_changed: () => this.reevaluate(),
|
|
33074
33318
|
on_exit: ({ exitCode }) => this.handleExit(exitCode)
|
|
33075
33319
|
}
|
|
@@ -33103,6 +33347,16 @@ var FsmDriver = class {
|
|
|
33103
33347
|
* WIN32_SUBMIT_* and scheduleWin32Submit). Re-arms itself until the FSM
|
|
33104
33348
|
* leaves idle (submitted) or the resend budget is spent. */
|
|
33105
33349
|
win32SubmitTimer = null;
|
|
33350
|
+
/** Wall-clock (ms) of the most recent raw PTY output chunk. Advances on every
|
|
33351
|
+
* on_pty_data — including the echo of text written into the composer — so the
|
|
33352
|
+
* win32 submit settle-gate can tell when input has finished landing. */
|
|
33353
|
+
lastPtyDataAt = 0;
|
|
33354
|
+
/** Wall-clock (ms) of the most recent win32 message-body input write. Bridges
|
|
33355
|
+
* the gap between writing a chunk and its echo so the settle-gate does not
|
|
33356
|
+
* declare "quiet" mid-write. */
|
|
33357
|
+
lastWin32WriteAt = 0;
|
|
33358
|
+
/** Pending paced chunk-write timer for a large win32 body (see writeWin32Body). */
|
|
33359
|
+
win32WriteTimer = null;
|
|
33106
33360
|
currentEval = null;
|
|
33107
33361
|
stateHistory = [];
|
|
33108
33362
|
prevStateAt = 0;
|
|
@@ -33223,6 +33477,10 @@ var FsmDriver = class {
|
|
|
33223
33477
|
clearTimeout(this.win32SubmitTimer);
|
|
33224
33478
|
this.win32SubmitTimer = null;
|
|
33225
33479
|
}
|
|
33480
|
+
if (this.win32WriteTimer) {
|
|
33481
|
+
clearTimeout(this.win32WriteTimer);
|
|
33482
|
+
this.win32WriteTimer = null;
|
|
33483
|
+
}
|
|
33226
33484
|
this.specWatcher?.close();
|
|
33227
33485
|
this.adapter.kill();
|
|
33228
33486
|
}
|
|
@@ -33253,11 +33511,15 @@ var FsmDriver = class {
|
|
|
33253
33511
|
getFsmSnapshotHistory() {
|
|
33254
33512
|
return this.fsmSnapshotHistory;
|
|
33255
33513
|
}
|
|
33514
|
+
/** Debug-only PTY input/output/resize/cursor timeline from the adapter. */
|
|
33515
|
+
getEventTimeline(limit) {
|
|
33516
|
+
return this.adapter.getEventTimeline(limit);
|
|
33517
|
+
}
|
|
33256
33518
|
getSections() {
|
|
33257
33519
|
try {
|
|
33258
33520
|
const screen = this.adapter.snapshot();
|
|
33259
33521
|
const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
33260
|
-
return resolveSections(this.spec.sections ?? {}, lines).map((
|
|
33522
|
+
return resolveSections(this.spec.sections ?? {}, lines).map((s2) => ({ id: s2.id, text: s2.text }));
|
|
33261
33523
|
} catch {
|
|
33262
33524
|
return null;
|
|
33263
33525
|
}
|
|
@@ -33635,7 +33897,7 @@ var FsmDriver = class {
|
|
|
33635
33897
|
const perChar = sm.delay_ms_per_char ?? 0;
|
|
33636
33898
|
const beforeSubmit = resolveSubmitDelayMs(sm.delay_ms_before_submit, text);
|
|
33637
33899
|
if (process.platform === "win32") {
|
|
33638
|
-
this.
|
|
33900
|
+
this.writeWin32Body(text);
|
|
33639
33901
|
this.scheduleWin32Submit(sm.submit_key, beforeSubmit);
|
|
33640
33902
|
return;
|
|
33641
33903
|
}
|
|
@@ -33661,20 +33923,72 @@ var FsmDriver = class {
|
|
|
33661
33923
|
const st = stateById(this.spec, this.currentStateId);
|
|
33662
33924
|
return st ? statusForState(st) : "idle";
|
|
33663
33925
|
}
|
|
33926
|
+
/** Record a win32 body write so the settle-gate counts it as input activity
|
|
33927
|
+
* even before the echo arrives. */
|
|
33928
|
+
markWin32Write() {
|
|
33929
|
+
this.lastWin32WriteAt = Date.now();
|
|
33930
|
+
}
|
|
33931
|
+
/** Most recent win32 input activity — a write we issued OR a PTY output chunk
|
|
33932
|
+
* (echo). The submit settle-gate waits for this to go quiet. */
|
|
33933
|
+
lastWin32InputActivityAt() {
|
|
33934
|
+
return Math.max(this.lastPtyDataAt, this.lastWin32WriteAt);
|
|
33935
|
+
}
|
|
33664
33936
|
/**
|
|
33665
|
-
*
|
|
33666
|
-
*
|
|
33667
|
-
* a
|
|
33668
|
-
*
|
|
33669
|
-
*
|
|
33670
|
-
*
|
|
33671
|
-
|
|
33937
|
+
* Write the message body to the PTY for win32, paced into bounded chunks. A
|
|
33938
|
+
* single unbounded ConPTY write can overflow the input pipe and drop leading
|
|
33939
|
+
* bytes; splitting it with a short inter-chunk gap keeps the console input
|
|
33940
|
+
* buffer from overflowing. Small bodies still go out in a single write. Each
|
|
33941
|
+
* chunk advances lastWin32WriteAt so the submit settle-gate keeps waiting until
|
|
33942
|
+
* the final chunk is out and echoed.
|
|
33943
|
+
*/
|
|
33944
|
+
writeWin32Body(text) {
|
|
33945
|
+
if (this.win32WriteTimer) {
|
|
33946
|
+
clearTimeout(this.win32WriteTimer);
|
|
33947
|
+
this.win32WriteTimer = null;
|
|
33948
|
+
}
|
|
33949
|
+
if (text.length <= WIN32_PTY_WRITE_CHUNK_CHARS) {
|
|
33950
|
+
this.markWin32Write();
|
|
33951
|
+
this.adapter.send_keys(text);
|
|
33952
|
+
return;
|
|
33953
|
+
}
|
|
33954
|
+
const chunks = chunkPreservingSurrogates(text, WIN32_PTY_WRITE_CHUNK_CHARS);
|
|
33955
|
+
let idx = 0;
|
|
33956
|
+
const writeNext = () => {
|
|
33957
|
+
this.win32WriteTimer = null;
|
|
33958
|
+
if (idx >= chunks.length) return;
|
|
33959
|
+
this.markWin32Write();
|
|
33960
|
+
this.adapter.send_keys(chunks[idx]);
|
|
33961
|
+
idx += 1;
|
|
33962
|
+
if (idx < chunks.length) {
|
|
33963
|
+
this.win32WriteTimer = setTimeout(writeNext, WIN32_PTY_WRITE_CHUNK_GAP_MS);
|
|
33964
|
+
}
|
|
33965
|
+
};
|
|
33966
|
+
writeNext();
|
|
33967
|
+
}
|
|
33968
|
+
/**
|
|
33969
|
+
* win32 submit. Two phases:
|
|
33970
|
+
*
|
|
33971
|
+
* Phase 1 (settle-gate): hold the first CR until the PTY output has been quiet
|
|
33972
|
+
* for WIN32_SUBMIT_SETTLE_MS after the last input write — i.e. the full
|
|
33973
|
+
* (possibly multi-KB / multiline) body has finished arriving in the composer
|
|
33974
|
+
* and echoing. Honors an initial minimum delay and is bounded by
|
|
33975
|
+
* WIN32_SUBMIT_MAX_SETTLE_WAIT_MS so a noisy screen can never hang the submit.
|
|
33976
|
+
* This is what stops a long message from being submitted half-arrived (its
|
|
33977
|
+
* leading lines lost). A short message settles almost immediately.
|
|
33978
|
+
*
|
|
33979
|
+
* Phase 2 (verified resend — unchanged): send the submit key, wait a gap, and
|
|
33980
|
+
* if the FSM is still 'idle' (the CR was absorbed as a multiline-paste
|
|
33981
|
+
* newline) resend, up to WIN32_SUBMIT_MAX_RESENDS. The first CR always fires
|
|
33982
|
+
* (a stale/edge status never suppresses it); resends are gated on still being
|
|
33983
|
+
* idle and stop the instant the agent leaves idle (submitted → generating /
|
|
33984
|
+
* approval). This preserves the win32 lone-CR-swallow handling.
|
|
33672
33985
|
*/
|
|
33673
33986
|
scheduleWin32Submit(submitKey, initialDelayMs) {
|
|
33674
33987
|
if (this.win32SubmitTimer) {
|
|
33675
33988
|
clearTimeout(this.win32SubmitTimer);
|
|
33676
33989
|
this.win32SubmitTimer = null;
|
|
33677
33990
|
}
|
|
33991
|
+
const startedAt = Date.now();
|
|
33678
33992
|
const fire = (attempt) => {
|
|
33679
33993
|
this.win32SubmitTimer = null;
|
|
33680
33994
|
this.adapter.send_keys(submitKey);
|
|
@@ -33687,8 +34001,20 @@ var FsmDriver = class {
|
|
|
33687
34001
|
fire(attempt + 1);
|
|
33688
34002
|
}, WIN32_SUBMIT_RESEND_GAP_MS);
|
|
33689
34003
|
};
|
|
33690
|
-
|
|
33691
|
-
|
|
34004
|
+
const waitForSettle = () => {
|
|
34005
|
+
this.win32SubmitTimer = null;
|
|
34006
|
+
const now = Date.now();
|
|
34007
|
+
const quietFor = now - this.lastWin32InputActivityAt();
|
|
34008
|
+
const waited = now - startedAt;
|
|
34009
|
+
if (quietFor >= WIN32_SUBMIT_SETTLE_MS || waited >= WIN32_SUBMIT_MAX_SETTLE_WAIT_MS) {
|
|
34010
|
+
fire(0);
|
|
34011
|
+
return;
|
|
34012
|
+
}
|
|
34013
|
+
const recheckIn = Math.min(WIN32_SUBMIT_SETTLE_MS - quietFor, WIN32_SUBMIT_SETTLE_POLL_MS);
|
|
34014
|
+
this.win32SubmitTimer = setTimeout(waitForSettle, Math.max(recheckIn, 30));
|
|
34015
|
+
};
|
|
34016
|
+
if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(waitForSettle, initialDelayMs);
|
|
34017
|
+
else waitForSettle();
|
|
33692
34018
|
}
|
|
33693
34019
|
handleClickControl(controlId, payload) {
|
|
33694
34020
|
const ctl = (this.spec.control_bar ?? []).find((c) => c.id === controlId);
|
|
@@ -33801,7 +34127,8 @@ function summarizeTransition(t) {
|
|
|
33801
34127
|
return out;
|
|
33802
34128
|
}
|
|
33803
34129
|
function flattenCond(c, out, depth) {
|
|
33804
|
-
|
|
34130
|
+
const matched = c.matchedText ? ` matched=${JSON.stringify(c.matchedText)}` : "";
|
|
34131
|
+
out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}${matched}`);
|
|
33805
34132
|
for (const child of c.children ?? []) flattenCond(child, out, depth + 1);
|
|
33806
34133
|
}
|
|
33807
34134
|
function findStable(c) {
|
|
@@ -34519,8 +34846,8 @@ function projectToolBlock(block2, role, tmap) {
|
|
|
34519
34846
|
}
|
|
34520
34847
|
return null;
|
|
34521
34848
|
}
|
|
34522
|
-
function oneLine(
|
|
34523
|
-
const flat =
|
|
34849
|
+
function oneLine(s2, max) {
|
|
34850
|
+
const flat = s2.replace(/\s+/g, " ").trim();
|
|
34524
34851
|
return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
|
|
34525
34852
|
}
|
|
34526
34853
|
function parseTimestamp(v) {
|
|
@@ -34540,10 +34867,10 @@ function parseTimestamp(v) {
|
|
|
34540
34867
|
return null;
|
|
34541
34868
|
}
|
|
34542
34869
|
function normalizeRole(r) {
|
|
34543
|
-
const
|
|
34544
|
-
if (
|
|
34545
|
-
if (
|
|
34546
|
-
if (
|
|
34870
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
34871
|
+
if (s2 === "user" || s2 === "human" || s2 === "user_explicit") return "user";
|
|
34872
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
34873
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
34547
34874
|
return "system";
|
|
34548
34875
|
}
|
|
34549
34876
|
function stringifyContent(v) {
|
|
@@ -34591,18 +34918,18 @@ function compileWhere(src) {
|
|
|
34591
34918
|
return (record) => ors.some((ands) => ands.every((t) => evalTerm(t, record)));
|
|
34592
34919
|
}
|
|
34593
34920
|
function parseTerm(src) {
|
|
34594
|
-
let
|
|
34921
|
+
let s2 = src.trim();
|
|
34595
34922
|
let negate = false;
|
|
34596
|
-
if (
|
|
34923
|
+
if (s2.startsWith("!")) {
|
|
34597
34924
|
negate = true;
|
|
34598
|
-
|
|
34925
|
+
s2 = s2.slice(1).trim();
|
|
34599
34926
|
}
|
|
34600
|
-
const fnMatch =
|
|
34927
|
+
const fnMatch = s2.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
|
|
34601
34928
|
if (fnMatch) {
|
|
34602
34929
|
const [, op2, pathExpr, litExpr] = fnMatch;
|
|
34603
34930
|
return { path: pathExpr, op: op2, lit: parseLiteral(litExpr), negate };
|
|
34604
34931
|
}
|
|
34605
|
-
const opMatch =
|
|
34932
|
+
const opMatch = s2.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
|
|
34606
34933
|
if (!opMatch) return null;
|
|
34607
34934
|
const [, lhs, op, rhsRaw] = opMatch;
|
|
34608
34935
|
return { path: lhs.trim(), op, lit: parseLiteral(rhsRaw.trim()), negate };
|
|
@@ -35034,7 +35361,7 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
35034
35361
|
try {
|
|
35035
35362
|
const sections = this.driver.getSections();
|
|
35036
35363
|
if (sectionId && sections) {
|
|
35037
|
-
const hit = sections.find((
|
|
35364
|
+
const hit = sections.find((s2) => s2.id === sectionId);
|
|
35038
35365
|
if (hit) return hit.text;
|
|
35039
35366
|
}
|
|
35040
35367
|
return this.driver.getScreen();
|
|
@@ -35049,7 +35376,7 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
35049
35376
|
screen = this.driver.snapshot();
|
|
35050
35377
|
const driverSections = this.driver.getSections?.();
|
|
35051
35378
|
if (driverSections) {
|
|
35052
|
-
sections = Object.fromEntries(driverSections.map((
|
|
35379
|
+
sections = Object.fromEntries(driverSections.map((s2) => [s2.id, s2.text]));
|
|
35053
35380
|
} else {
|
|
35054
35381
|
sections = this.readCurrentScreenSections(screen);
|
|
35055
35382
|
}
|
|
@@ -35095,6 +35422,10 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
35095
35422
|
// answers "why did this rule fire" after the fact, unlike the live
|
|
35096
35423
|
// `fsm` field which only reflects the current instant.
|
|
35097
35424
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
35425
|
+
// PTY input/output/resize/cursor event timeline (debug-only) so the
|
|
35426
|
+
// snapshot shows what we typed / what the PTY printed around each
|
|
35427
|
+
// status transition. Null for drivers without the timeline.
|
|
35428
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
35098
35429
|
// Extended fields
|
|
35099
35430
|
name: this.cliName,
|
|
35100
35431
|
status: this.getStatus().status,
|
|
@@ -35459,6 +35790,8 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
35459
35790
|
// v4 FSM transition snapshot history — the captured pre-transition
|
|
35460
35791
|
// evaluation table at each transition (null for v3 specs).
|
|
35461
35792
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
35793
|
+
// PTY input/output/resize/cursor event timeline (debug-only).
|
|
35794
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
35462
35795
|
messages,
|
|
35463
35796
|
committedMessages: messages
|
|
35464
35797
|
};
|
|
@@ -35503,6 +35836,7 @@ function createCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFact
|
|
|
35503
35836
|
|
|
35504
35837
|
// src/providers/cli-provider-instance.ts
|
|
35505
35838
|
init_logger();
|
|
35839
|
+
init_mesh_event_trace();
|
|
35506
35840
|
init_control_effects();
|
|
35507
35841
|
init_approval_utils();
|
|
35508
35842
|
init_provider_patch_state();
|
|
@@ -36554,6 +36888,23 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36554
36888
|
if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
|
|
36555
36889
|
this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
|
|
36556
36890
|
}
|
|
36891
|
+
// EVTTRACE (observation-only): is this a mesh worker session whose completion
|
|
36892
|
+
// events must route to a coordinator? Used purely to gate trace logging so a
|
|
36893
|
+
// non-mesh CLI session's completions don't add EvtTrace noise. No decision logic.
|
|
36894
|
+
isMeshWorkerSession() {
|
|
36895
|
+
return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
|
|
36896
|
+
}
|
|
36897
|
+
// EVTTRACE correlation context for this session's completion lifecycle. taskId is
|
|
36898
|
+
// the primary grep anchor; instanceId is the session fallback.
|
|
36899
|
+
meshTraceCtx(event = "agent:generating_completed") {
|
|
36900
|
+
return {
|
|
36901
|
+
taskId: this.settings.meshActiveTaskId,
|
|
36902
|
+
sessionId: this.instanceId,
|
|
36903
|
+
nodeId: this.settings.meshNodeId,
|
|
36904
|
+
meshId: this.settings.meshNodeFor,
|
|
36905
|
+
event
|
|
36906
|
+
};
|
|
36907
|
+
}
|
|
36557
36908
|
flushCompletedDebounceIfFinalized() {
|
|
36558
36909
|
const pending = this.completedDebouncePending;
|
|
36559
36910
|
if (!pending) {
|
|
@@ -36574,24 +36925,33 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36574
36925
|
if (block2) {
|
|
36575
36926
|
const blockReason = block2.reason;
|
|
36576
36927
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
36577
|
-
|
|
36578
|
-
|
|
36928
|
+
const isTranscriptEvidenceGate = block2.allowTimeout === true;
|
|
36929
|
+
LOG.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} allowTimeout=${isTranscriptEvidenceGate} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
|
|
36930
|
+
if (!isTranscriptEvidenceGate && (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS)) {
|
|
36579
36931
|
if (pending.loggedBlockReason !== blockReason) {
|
|
36580
36932
|
LOG.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
|
|
36933
|
+
if (this.isMeshWorkerSession()) {
|
|
36934
|
+
traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `${blockReason} waited=${waitedMs}ms`);
|
|
36935
|
+
}
|
|
36581
36936
|
pending.loggedBlockReason = blockReason;
|
|
36582
36937
|
}
|
|
36583
36938
|
this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
|
|
36584
36939
|
return;
|
|
36585
36940
|
}
|
|
36941
|
+
const emittedAfterFinalizationTimeout = waitedMs >= COMPLETED_FINALIZATION_MAX_WAIT_MS;
|
|
36586
36942
|
const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
|
|
36587
36943
|
blockReason,
|
|
36588
36944
|
latestStatus,
|
|
36589
36945
|
latestVisibleStatus,
|
|
36590
36946
|
waitedMs,
|
|
36591
36947
|
pending,
|
|
36592
|
-
emittedAfterFinalizationTimeout
|
|
36948
|
+
emittedAfterFinalizationTimeout
|
|
36593
36949
|
});
|
|
36594
|
-
|
|
36950
|
+
completionDiagnostic.decoupledImmediateEmit = isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout;
|
|
36951
|
+
LOG.warn("CLI", `[${this.type}] emitting completed event (${isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`}) without finalized assistant turn (${blockReason})`);
|
|
36952
|
+
if (this.isMeshWorkerSession()) {
|
|
36953
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `forced after ${waitedMs}ms (${blockReason})`);
|
|
36954
|
+
}
|
|
36595
36955
|
this.pushEvent({
|
|
36596
36956
|
event: "agent:generating_completed",
|
|
36597
36957
|
chatTitle: pending.chatTitle,
|
|
@@ -36614,6 +36974,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36614
36974
|
return;
|
|
36615
36975
|
}
|
|
36616
36976
|
LOG.info("CLI", `[${this.type}] completed in ${pending.duration}s`);
|
|
36977
|
+
if (this.isMeshWorkerSession()) {
|
|
36978
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `duration=${pending.duration}s`);
|
|
36979
|
+
}
|
|
36617
36980
|
this.pushEvent({
|
|
36618
36981
|
event: "agent:generating_completed",
|
|
36619
36982
|
chatTitle: pending.chatTitle,
|
|
@@ -36852,6 +37215,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36852
37215
|
if (missingEvidence && !hasMeshContext) {
|
|
36853
37216
|
LOG.info("CLI", `[${this.type}] short completion suppressed: missing final assistant evidence, no mesh context (source=${shortEvidenceSource})`);
|
|
36854
37217
|
} else {
|
|
37218
|
+
if (this.isMeshWorkerSession()) {
|
|
37219
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `short-generating idle (source=${shortEvidenceSource})`);
|
|
37220
|
+
}
|
|
36855
37221
|
this.pushEvent({
|
|
36856
37222
|
event: "agent:generating_completed",
|
|
36857
37223
|
chatTitle,
|
|
@@ -36928,6 +37294,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36928
37294
|
const monitorParsedStatus = parsedStatus;
|
|
36929
37295
|
for (const me of monitorEvents) {
|
|
36930
37296
|
if (me.type === "monitor:no_progress" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
|
|
37297
|
+
if (this.isMeshWorkerSession()) {
|
|
37298
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), "no_progress_monitor_final_summary");
|
|
37299
|
+
}
|
|
36931
37300
|
this.pushEvent({
|
|
36932
37301
|
event: "agent:generating_completed",
|
|
36933
37302
|
chatTitle,
|
|
@@ -40791,7 +41160,7 @@ function parsePbFile(filePath, sessionId) {
|
|
|
40791
41160
|
}
|
|
40792
41161
|
if (buf.length === 0) return null;
|
|
40793
41162
|
const strings = extractStringsFromBuffer(buf);
|
|
40794
|
-
const meaningful = strings.filter((
|
|
41163
|
+
const meaningful = strings.filter((s2) => s2.length >= MIN_PRINTABLE_RUN && /\w/.test(s2));
|
|
40795
41164
|
if (meaningful.length === 0) return null;
|
|
40796
41165
|
const content = meaningful.join("\n");
|
|
40797
41166
|
const sourceMtimeMs = statMtimeMs3(filePath);
|
|
@@ -40999,10 +41368,10 @@ function readSession4(sessionPath) {
|
|
|
40999
41368
|
};
|
|
41000
41369
|
}
|
|
41001
41370
|
function normalizeHermesRole(r) {
|
|
41002
|
-
const
|
|
41003
|
-
if (
|
|
41004
|
-
if (
|
|
41005
|
-
if (
|
|
41371
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
41372
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
41373
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
41374
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
41006
41375
|
return "system";
|
|
41007
41376
|
}
|
|
41008
41377
|
|
|
@@ -41228,10 +41597,10 @@ function safeMtime(p) {
|
|
|
41228
41597
|
}
|
|
41229
41598
|
}
|
|
41230
41599
|
function normalizeRole2(r) {
|
|
41231
|
-
const
|
|
41232
|
-
if (
|
|
41233
|
-
if (
|
|
41234
|
-
if (
|
|
41600
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
41601
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
41602
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
41603
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
41235
41604
|
return "system";
|
|
41236
41605
|
}
|
|
41237
41606
|
|
|
@@ -41251,7 +41620,7 @@ function synthesizeControlsFromControlBar(specControls) {
|
|
|
41251
41620
|
const actionType = ctl?.action?.type;
|
|
41252
41621
|
if (!id || !actionType) return;
|
|
41253
41622
|
const label = typeof ctl?.label === "string" && ctl.label.trim() ? ctl.label : id;
|
|
41254
|
-
const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((
|
|
41623
|
+
const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s2) => typeof s2 === "string") : void 0;
|
|
41255
41624
|
if (actionType === "open_picker") {
|
|
41256
41625
|
out.push({
|
|
41257
41626
|
id,
|
|
@@ -48167,7 +48536,7 @@ var DaemonCommandRouter = class {
|
|
|
48167
48536
|
const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : validationSummary.failureCode === "spawn_resolution_failed" ? validationSummary.spawnResolutionError || "Refinery validation command could not be spawned (executable not found); merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
|
|
48168
48537
|
if (!firstFailedCmd) return base;
|
|
48169
48538
|
const cmdName = typeof firstFailedCmd.displayCommand === "string" ? firstFailedCmd.displayCommand : typeof firstFailedCmd.command === "string" ? [firstFailedCmd.command, ...Array.isArray(firstFailedCmd.args) ? firstFailedCmd.args : []].join(" ").trim() : typeof firstFailedCmd.cmd === "string" ? firstFailedCmd.cmd : "";
|
|
48170
|
-
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((
|
|
48539
|
+
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s2) => typeof s2 === "string" && s2.length > 0).join("\n");
|
|
48171
48540
|
const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
|
|
48172
48541
|
return [
|
|
48173
48542
|
base,
|
|
@@ -48918,7 +49287,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
48918
49287
|
convergence = "blocked_review";
|
|
48919
49288
|
}
|
|
48920
49289
|
const fbcs = result.finalBranchConvergenceState && typeof result.finalBranchConvergenceState === "object" ? result.finalBranchConvergenceState : void 0;
|
|
48921
|
-
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((
|
|
49290
|
+
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s2) => s2.status === "failed").map((s2) => s2.stage).filter(Boolean).pop() : void 0;
|
|
48922
49291
|
results.push({
|
|
48923
49292
|
nodeId: node.id,
|
|
48924
49293
|
workspace: node.workspace,
|
|
@@ -49915,7 +50284,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
49915
50284
|
return {
|
|
49916
50285
|
success: true,
|
|
49917
50286
|
screenLineCount: lines.length,
|
|
49918
|
-
sections: resolved.map((
|
|
50287
|
+
sections: resolved.map((s2) => ({ id: s2.id, fromLine: s2.fromLine, toLine: s2.toLine, text: s2.text }))
|
|
49919
50288
|
};
|
|
49920
50289
|
} catch (e) {
|
|
49921
50290
|
return { success: false, error: `resolve failed: ${e.message}` };
|
|
@@ -50484,7 +50853,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50484
50853
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
50485
50854
|
try {
|
|
50486
50855
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2, describeTaskDependencyState: describeTaskDependencyState2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
50487
|
-
const status = Array.isArray(args?.status) ? args.status.map((
|
|
50856
|
+
const status = Array.isArray(args?.status) ? args.status.map((s2) => typeof s2 === "string" ? s2.trim() : "").filter(Boolean) : void 0;
|
|
50488
50857
|
const rawQueue = getQueue2(meshId, { status });
|
|
50489
50858
|
const statusById = new Map(getQueue2(meshId).map((task) => [task.id, task.status]));
|
|
50490
50859
|
const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById) } : task);
|
|
@@ -50765,7 +51134,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50765
51134
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
50766
51135
|
}
|
|
50767
51136
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
50768
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
51137
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
50769
51138
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50770
51139
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
|
|
50771
51140
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -50799,7 +51168,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50799
51168
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
50800
51169
|
}
|
|
50801
51170
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
50802
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
51171
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
50803
51172
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50804
51173
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
|
|
50805
51174
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -50847,7 +51216,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50847
51216
|
const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
50848
51217
|
const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
|
|
50849
51218
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
50850
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
51219
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
50851
51220
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50852
51221
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
50853
51222
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
|
|
@@ -50934,7 +51303,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50934
51303
|
let worktreeCleanup;
|
|
50935
51304
|
if (node?.isLocalWorktree) {
|
|
50936
51305
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
50937
|
-
const isRemoteWorktree = nodeDaemonId && nodeDaemonId
|
|
51306
|
+
const isRemoteWorktree = nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
|
|
50938
51307
|
if (isRemoteWorktree) {
|
|
50939
51308
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "remove_mesh_node", {
|
|
50940
51309
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -51016,7 +51385,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
51016
51385
|
const sourceNode = mesh.nodes?.find((n) => meshNodeIdMatches(n, sourceNodeId));
|
|
51017
51386
|
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
51018
51387
|
const sourceDaemonId = typeof sourceNode.daemonId === "string" ? sourceNode.daemonId.trim() : void 0;
|
|
51019
|
-
if (sourceDaemonId && sourceDaemonId
|
|
51388
|
+
if (sourceDaemonId && !daemonIdsEquivalent(sourceDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
51020
51389
|
const forwarded = await this.deps.dispatchMeshCommand(sourceDaemonId, "clone_mesh_node", {
|
|
51021
51390
|
...typeof args === "object" && args !== null ? args : {},
|
|
51022
51391
|
_meshDirectDispatch: true
|
|
@@ -51258,7 +51627,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
51258
51627
|
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
51259
51628
|
if (!node.isLocalWorktree) return { success: false, error: "Node is not a local worktree node" };
|
|
51260
51629
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
51261
|
-
if (nodeDaemonId && nodeDaemonId
|
|
51630
|
+
if (nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
51262
51631
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "retry_mesh_node_bootstrap", {
|
|
51263
51632
|
...typeof args === "object" && args !== null ? args : {},
|
|
51264
51633
|
_meshDirectDispatch: true
|
|
@@ -52468,16 +52837,16 @@ var DaemonStatusReporter = class {
|
|
|
52468
52837
|
const now = this.lastStatusSentAt;
|
|
52469
52838
|
const target = opts?.p2pOnly ? "P2P" : serverConnected ? "P2P+Server" : "P2P";
|
|
52470
52839
|
const allStates = this.deps.instanceManager.collectAllStates();
|
|
52471
|
-
const ideStates = allStates.filter((
|
|
52472
|
-
const cliStates = allStates.filter((
|
|
52473
|
-
const acpStates = allStates.filter((
|
|
52474
|
-
const ideSummary = ideStates.map((
|
|
52475
|
-
const msgs =
|
|
52476
|
-
const exts =
|
|
52477
|
-
return `${
|
|
52840
|
+
const ideStates = allStates.filter((s2) => s2.category === "ide");
|
|
52841
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli");
|
|
52842
|
+
const acpStates = allStates.filter((s2) => s2.category === "acp");
|
|
52843
|
+
const ideSummary = ideStates.map((s2) => {
|
|
52844
|
+
const msgs = s2.activeChat?.messages?.length || 0;
|
|
52845
|
+
const exts = s2.extensions.length;
|
|
52846
|
+
return `${s2.type}(${s2.status},${msgs}msg,${exts}ext)`;
|
|
52478
52847
|
}).join(", ");
|
|
52479
|
-
const cliSummary = cliStates.map((
|
|
52480
|
-
const acpSummary = acpStates.map((
|
|
52848
|
+
const cliSummary = cliStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
52849
|
+
const acpSummary = acpStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
52481
52850
|
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
52482
52851
|
const baseSummary = `IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
|
|
52483
52852
|
const summaryChanged = baseSummary !== this.lastStatusSummary;
|
|
@@ -52588,10 +52957,10 @@ var DaemonStatusReporter = class {
|
|
|
52588
52957
|
}
|
|
52589
52958
|
return false;
|
|
52590
52959
|
}
|
|
52591
|
-
simpleHash(
|
|
52960
|
+
simpleHash(s2) {
|
|
52592
52961
|
let h = 2166136261;
|
|
52593
|
-
for (let i = 0; i <
|
|
52594
|
-
h ^=
|
|
52962
|
+
for (let i = 0; i < s2.length; i++) {
|
|
52963
|
+
h ^= s2.charCodeAt(i);
|
|
52595
52964
|
h = h * 16777619 >>> 0;
|
|
52596
52965
|
}
|
|
52597
52966
|
return h.toString(36);
|
|
@@ -53817,7 +54186,7 @@ var ProviderInstanceManager = class {
|
|
|
53817
54186
|
* Per-category status collect
|
|
53818
54187
|
*/
|
|
53819
54188
|
collectStatesByCategory(category) {
|
|
53820
|
-
return this.collectAllStates().filter((
|
|
54189
|
+
return this.collectAllStates().filter((s2) => s2.category === category);
|
|
53821
54190
|
}
|
|
53822
54191
|
// ─── Tick engine ─────────────────────────────────
|
|
53823
54192
|
/**
|
|
@@ -55717,9 +56086,9 @@ function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
|
55717
56086
|
function findCliTarget(ctx, type, instanceId) {
|
|
55718
56087
|
if (!ctx.instanceManager) return null;
|
|
55719
56088
|
const cliStates = ctx.instanceManager.collectAllStates().filter(isCliTargetState);
|
|
55720
|
-
if (instanceId) return cliStates.find((
|
|
56089
|
+
if (instanceId) return cliStates.find((s2) => s2.instanceId === instanceId) || null;
|
|
55721
56090
|
if (!type) return cliStates[cliStates.length - 1] || null;
|
|
55722
|
-
const matches = cliStates.filter((
|
|
56091
|
+
const matches = cliStates.filter((s2) => s2.type === type);
|
|
55723
56092
|
return matches[matches.length - 1] || null;
|
|
55724
56093
|
}
|
|
55725
56094
|
function getCliTargetBundle(ctx, type, instanceId) {
|
|
@@ -56082,20 +56451,20 @@ async function handleCliStatus(ctx, _req, res) {
|
|
|
56082
56451
|
return;
|
|
56083
56452
|
}
|
|
56084
56453
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
56085
|
-
const cliStates = allStates.filter((
|
|
56086
|
-
const result = cliStates.map((
|
|
56087
|
-
instanceId:
|
|
56088
|
-
type:
|
|
56089
|
-
name:
|
|
56090
|
-
category:
|
|
56091
|
-
status:
|
|
56092
|
-
mode:
|
|
56093
|
-
workspace:
|
|
56094
|
-
messageCount:
|
|
56095
|
-
lastMessage:
|
|
56096
|
-
activeModal:
|
|
56097
|
-
pendingEvents:
|
|
56098
|
-
settings:
|
|
56454
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
56455
|
+
const result = cliStates.map((s2) => ({
|
|
56456
|
+
instanceId: s2.instanceId,
|
|
56457
|
+
type: s2.type,
|
|
56458
|
+
name: s2.name,
|
|
56459
|
+
category: s2.category,
|
|
56460
|
+
status: s2.status,
|
|
56461
|
+
mode: s2.mode,
|
|
56462
|
+
workspace: s2.workspace,
|
|
56463
|
+
messageCount: s2.activeChat?.messages?.length || 0,
|
|
56464
|
+
lastMessage: s2.activeChat?.messages?.slice(-1)[0] || null,
|
|
56465
|
+
activeModal: s2.activeChat?.activeModal || null,
|
|
56466
|
+
pendingEvents: s2.pendingEvents || [],
|
|
56467
|
+
settings: s2.settings
|
|
56099
56468
|
}));
|
|
56100
56469
|
ctx.json(res, 200, { instances: result, count: result.length });
|
|
56101
56470
|
}
|
|
@@ -56184,9 +56553,9 @@ function handleCliSSE(ctx, cliSSEClients, _req, res) {
|
|
|
56184
56553
|
}
|
|
56185
56554
|
if (ctx.instanceManager) {
|
|
56186
56555
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
56187
|
-
const cliStates = allStates.filter((
|
|
56188
|
-
for (const
|
|
56189
|
-
ctx.sendCliSSE({ event: "snapshot", providerType:
|
|
56556
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
56557
|
+
for (const s2 of cliStates) {
|
|
56558
|
+
ctx.sendCliSSE({ event: "snapshot", providerType: s2.type, status: s2.status, instanceId: s2.instanceId });
|
|
56190
56559
|
}
|
|
56191
56560
|
}
|
|
56192
56561
|
_req.on("close", () => {
|
|
@@ -56202,7 +56571,7 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
56202
56571
|
const target = findCliTarget(ctx, type);
|
|
56203
56572
|
if (!target) {
|
|
56204
56573
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
56205
|
-
ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((
|
|
56574
|
+
ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type) });
|
|
56206
56575
|
return;
|
|
56207
56576
|
}
|
|
56208
56577
|
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
@@ -56248,7 +56617,7 @@ async function handleCliTrace(ctx, type, req, res) {
|
|
|
56248
56617
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
56249
56618
|
ctx.json(res, 404, {
|
|
56250
56619
|
error: `No running instance for: ${type}`,
|
|
56251
|
-
available: allStates.filter((
|
|
56620
|
+
available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type)
|
|
56252
56621
|
});
|
|
56253
56622
|
return;
|
|
56254
56623
|
}
|
|
@@ -57053,7 +57422,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
57053
57422
|
child.write("\x1B[12;1R");
|
|
57054
57423
|
ctx.log("Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]");
|
|
57055
57424
|
}
|
|
57056
|
-
checkAutoApproval(data, (
|
|
57425
|
+
checkAutoApproval(data, (s2) => child.write(s2));
|
|
57057
57426
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
57058
57427
|
scheduleAutoStopForVerification();
|
|
57059
57428
|
});
|
|
@@ -57066,7 +57435,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
57066
57435
|
stdout += chunk;
|
|
57067
57436
|
clearAutoStopTimer();
|
|
57068
57437
|
if (chunk.includes("\x1B[6n")) child.stdin?.write("\x1B[1;1R");
|
|
57069
|
-
checkAutoApproval(chunk, (
|
|
57438
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
57070
57439
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stdout" } });
|
|
57071
57440
|
scheduleAutoStopForVerification();
|
|
57072
57441
|
});
|
|
@@ -57074,7 +57443,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
57074
57443
|
const chunk = d.toString();
|
|
57075
57444
|
stderr += chunk;
|
|
57076
57445
|
clearAutoStopTimer();
|
|
57077
|
-
checkAutoApproval(chunk, (
|
|
57446
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
57078
57447
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
57079
57448
|
scheduleAutoStopForVerification();
|
|
57080
57449
|
});
|
|
@@ -57889,59 +58258,59 @@ var DevServer = class _DevServer {
|
|
|
57889
58258
|
// ─── Route Table ─────────────────────────────────────
|
|
57890
58259
|
routes = [
|
|
57891
58260
|
// Static routes
|
|
57892
|
-
{ method: "GET", pattern: "/api/providers", handler: (q,
|
|
57893
|
-
{ method: "GET", pattern: "/api/providers/source-config", handler: (q,
|
|
57894
|
-
{ method: "POST", pattern: "/api/providers/source-config", handler: (q,
|
|
57895
|
-
{ method: "GET", pattern: "/api/providers/versions", handler: (q,
|
|
57896
|
-
{ method: "POST", pattern: "/api/providers/reload", handler: (q,
|
|
57897
|
-
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q,
|
|
57898
|
-
{ method: "POST", pattern: "/api/cdp/click", handler: (q,
|
|
57899
|
-
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q,
|
|
57900
|
-
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q,
|
|
57901
|
-
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q,
|
|
57902
|
-
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q,
|
|
57903
|
-
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q,
|
|
57904
|
-
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q,
|
|
57905
|
-
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q,
|
|
57906
|
-
{ method: "GET", pattern: "/api/cdp/targets", handler: (q,
|
|
57907
|
-
{ method: "POST", pattern: "/api/scripts/run", handler: (q,
|
|
57908
|
-
{ method: "GET", pattern: "/api/status", handler: (q,
|
|
57909
|
-
{ method: "POST", pattern: "/api/watch/start", handler: (q,
|
|
57910
|
-
{ method: "POST", pattern: "/api/watch/stop", handler: (q,
|
|
57911
|
-
{ method: "GET", pattern: "/api/watch/events", handler: (q,
|
|
57912
|
-
{ method: "POST", pattern: "/api/scaffold", handler: (q,
|
|
58261
|
+
{ method: "GET", pattern: "/api/providers", handler: (q, s2) => this.handleListProviders(q, s2) },
|
|
58262
|
+
{ method: "GET", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleGetProviderSourceConfig(q, s2) },
|
|
58263
|
+
{ method: "POST", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleSetProviderSourceConfig(q, s2) },
|
|
58264
|
+
{ method: "GET", pattern: "/api/providers/versions", handler: (q, s2) => this.handleDetectVersions(q, s2) },
|
|
58265
|
+
{ method: "POST", pattern: "/api/providers/reload", handler: (q, s2) => this.handleReload(q, s2) },
|
|
58266
|
+
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s2) => this.handleCdpEvaluate(q, s2) },
|
|
58267
|
+
{ method: "POST", pattern: "/api/cdp/click", handler: (q, s2) => this.handleCdpClick(q, s2) },
|
|
58268
|
+
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s2) => this.handleCdpDomQuery(q, s2) },
|
|
58269
|
+
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s2) => this.handleDomInspect(q, s2) },
|
|
58270
|
+
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s2) => this.handleDomChildren(q, s2) },
|
|
58271
|
+
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s2) => this.handleDomAnalyze(q, s2) },
|
|
58272
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s2) => this.handleFindByText(q, s2) },
|
|
58273
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s2) => this.handleFindCommon(q, s2) },
|
|
58274
|
+
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s2) => this.handleScreenshot(q, s2) },
|
|
58275
|
+
{ method: "GET", pattern: "/api/cdp/targets", handler: (q, s2) => this.handleCdpTargets(q, s2) },
|
|
58276
|
+
{ method: "POST", pattern: "/api/scripts/run", handler: (q, s2) => this.handleScriptsRun(q, s2) },
|
|
58277
|
+
{ method: "GET", pattern: "/api/status", handler: (q, s2) => this.handleStatus(q, s2) },
|
|
58278
|
+
{ method: "POST", pattern: "/api/watch/start", handler: (q, s2) => this.handleWatchStart(q, s2) },
|
|
58279
|
+
{ method: "POST", pattern: "/api/watch/stop", handler: (q, s2) => this.handleWatchStop(q, s2) },
|
|
58280
|
+
{ method: "GET", pattern: "/api/watch/events", handler: (q, s2) => this.handleSSE(q, s2) },
|
|
58281
|
+
{ method: "POST", pattern: "/api/scaffold", handler: (q, s2) => this.handleScaffold(q, s2) },
|
|
57913
58282
|
// CLI Debug routes
|
|
57914
|
-
{ method: "GET", pattern: "/api/cli/status", handler: (q,
|
|
57915
|
-
{ method: "POST", pattern: "/api/cli/launch", handler: (q,
|
|
57916
|
-
{ method: "POST", pattern: "/api/cli/send", handler: (q,
|
|
57917
|
-
{ method: "POST", pattern: "/api/cli/exercise", handler: (q,
|
|
57918
|
-
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q,
|
|
57919
|
-
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q,
|
|
57920
|
-
{ method: "POST", pattern: "/api/cli/resolve", handler: (q,
|
|
57921
|
-
{ method: "POST", pattern: "/api/cli/raw", handler: (q,
|
|
57922
|
-
{ method: "POST", pattern: "/api/cli/stop", handler: (q,
|
|
57923
|
-
{ method: "GET", pattern: "/api/cli/events", handler: (q,
|
|
57924
|
-
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q,
|
|
57925
|
-
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q,
|
|
57926
|
-
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q,
|
|
58283
|
+
{ method: "GET", pattern: "/api/cli/status", handler: (q, s2) => this.handleCliStatus(q, s2) },
|
|
58284
|
+
{ method: "POST", pattern: "/api/cli/launch", handler: (q, s2) => this.handleCliLaunch(q, s2) },
|
|
58285
|
+
{ method: "POST", pattern: "/api/cli/send", handler: (q, s2) => this.handleCliSend(q, s2) },
|
|
58286
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q, s2) => this.handleCliExercise(q, s2) },
|
|
58287
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s2) => this.handleCliFixtureCapture(q, s2) },
|
|
58288
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s2) => this.handleCliFixtureReplay(q, s2) },
|
|
58289
|
+
{ method: "POST", pattern: "/api/cli/resolve", handler: (q, s2) => this.handleCliResolve(q, s2) },
|
|
58290
|
+
{ method: "POST", pattern: "/api/cli/raw", handler: (q, s2) => this.handleCliRaw(q, s2) },
|
|
58291
|
+
{ method: "POST", pattern: "/api/cli/stop", handler: (q, s2) => this.handleCliStop(q, s2) },
|
|
58292
|
+
{ method: "GET", pattern: "/api/cli/events", handler: (q, s2) => this.handleCliSSE(q, s2) },
|
|
58293
|
+
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s2, p) => this.handleCliDebug(p[0], q, s2) },
|
|
58294
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s2, p) => this.handleCliTrace(p[0], q, s2) },
|
|
58295
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s2, p) => this.handleCliFixtureList(p[0], q, s2) },
|
|
57927
58296
|
// Dynamic routes (provider :type param)
|
|
57928
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q,
|
|
57929
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q,
|
|
57930
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q,
|
|
57931
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q,
|
|
57932
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q,
|
|
57933
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q,
|
|
57934
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q,
|
|
57935
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q,
|
|
57936
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q,
|
|
57937
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q,
|
|
57938
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q,
|
|
57939
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q,
|
|
57940
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q,
|
|
57941
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q,
|
|
57942
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q,
|
|
57943
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q,
|
|
57944
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q,
|
|
58297
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s2, p) => this.handleRunScript(p[0], q, s2) },
|
|
58298
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s2, p) => this.handleListFiles(p[0], q, s2) },
|
|
58299
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleReadFile(p[0], q, s2) },
|
|
58300
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleWriteFile(p[0], q, s2) },
|
|
58301
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s2, p) => this.handleSource(p[0], q, s2) },
|
|
58302
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s2, p) => this.handleSave(p[0], q, s2) },
|
|
58303
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s2, p) => this.handleTypeAndSend(p[0], q, s2) },
|
|
58304
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s2, p) => this.handleTypeAndSendAt(p[0], q, s2) },
|
|
58305
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s2, p) => this.handleProviderConfig(p[0], q, s2) },
|
|
58306
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s2, p) => this.handleDomContext(p[0], q, s2) },
|
|
58307
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s2, p) => this.handleAutoImplement(p[0], q, s2) },
|
|
58308
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s2, p) => this.handleAutoImplCancel(p[0], q, s2) },
|
|
58309
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s2, p) => this.handleAutoImplSSE(p[0], q, s2) },
|
|
58310
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s2, p) => this.handleSpawnTest(p[0], q, s2) },
|
|
58311
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s2, p) => this.handleValidate(p[0], q, s2) },
|
|
58312
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s2, p) => this.handleAcpChat(p[0], q, s2) },
|
|
58313
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s2, p) => this.handleScriptHints(p[0], q, s2) }
|
|
57945
58314
|
];
|
|
57946
58315
|
matchRoute(method, pathname) {
|
|
57947
58316
|
for (const route of this.routes) {
|
|
@@ -58536,14 +58905,14 @@ var DevServer = class _DevServer {
|
|
|
58536
58905
|
warnings.push(...validation.warnings);
|
|
58537
58906
|
if (config.settings) {
|
|
58538
58907
|
for (const [key, val] of Object.entries(config.settings)) {
|
|
58539
|
-
const
|
|
58540
|
-
if (!
|
|
58541
|
-
else if (!["boolean", "number", "string", "select"].includes(
|
|
58542
|
-
errors.push(`settings.${key}: invalid type '${
|
|
58543
|
-
if (
|
|
58544
|
-
if (
|
|
58545
|
-
errors.push(`settings.${key}: min (${
|
|
58546
|
-
if (
|
|
58908
|
+
const s2 = val;
|
|
58909
|
+
if (!s2.type) errors.push(`settings.${key}: missing type`);
|
|
58910
|
+
else if (!["boolean", "number", "string", "select"].includes(s2.type))
|
|
58911
|
+
errors.push(`settings.${key}: invalid type '${s2.type}'`);
|
|
58912
|
+
if (s2.default === void 0) warnings.push(`settings.${key}: no default value`);
|
|
58913
|
+
if (s2.type === "number" && s2.min !== void 0 && s2.max !== void 0 && s2.min > s2.max)
|
|
58914
|
+
errors.push(`settings.${key}: min (${s2.min}) > max (${s2.max})`);
|
|
58915
|
+
if (s2.type === "select" && (!s2.options || !Array.isArray(s2.options) || s2.options.length === 0))
|
|
58547
58916
|
errors.push(`settings.${key}: select type requires options[]`);
|
|
58548
58917
|
}
|
|
58549
58918
|
}
|