@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.mjs
CHANGED
|
@@ -311,10 +311,10 @@ function readInjected(value) {
|
|
|
311
311
|
}
|
|
312
312
|
function getDaemonBuildInfo() {
|
|
313
313
|
if (cached) return cached;
|
|
314
|
-
const commit = readInjected(true ? "
|
|
315
|
-
const commitShort = readInjected(true ? "
|
|
316
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
317
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
314
|
+
const commit = readInjected(true ? "a45106605e2ae1c10c0bc6cbe48c2cac4e862ded" : void 0) ?? "unknown";
|
|
315
|
+
const commitShort = readInjected(true ? "a4510660" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
316
|
+
const version = readInjected(true ? "0.9.82-rc.355" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
317
|
+
const builtAt = readInjected(true ? "2026-06-22T15:21:19.981Z" : void 0);
|
|
318
318
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
319
319
|
return cached;
|
|
320
320
|
}
|
|
@@ -4822,9 +4822,12 @@ function getActiveDirectDispatches(meshId) {
|
|
|
4822
4822
|
return [];
|
|
4823
4823
|
}
|
|
4824
4824
|
}
|
|
4825
|
-
function updateDirectDispatchStatus(meshId, sessionId, status) {
|
|
4825
|
+
function updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
|
|
4826
4826
|
try {
|
|
4827
|
-
|
|
4827
|
+
if (!taskId) {
|
|
4828
|
+
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)`);
|
|
4829
|
+
}
|
|
4830
|
+
MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status, taskId);
|
|
4828
4831
|
} catch {
|
|
4829
4832
|
}
|
|
4830
4833
|
}
|
|
@@ -5656,9 +5659,25 @@ var init_mesh_runtime_store = __esm({
|
|
|
5656
5659
|
updatedAt: r.updated_at
|
|
5657
5660
|
}));
|
|
5658
5661
|
}
|
|
5659
|
-
|
|
5660
|
-
|
|
5662
|
+
// CANON-B (dispatch identity): mesh_direct_dispatches is keyed by task_id (PK), but a
|
|
5663
|
+
// single session can host several sequential direct dispatches (re-dispatch / nudge), so
|
|
5664
|
+
// matching a status flip by session_id alone hits EVERY non-terminal row for that session
|
|
5665
|
+
// — flipping a sibling task's row and stranding the one whose event actually fired (the
|
|
5666
|
+
// assigned-stranded watchdog then requeues a task that is really still generating). When
|
|
5667
|
+
// the firing event carries a taskId, target the single PK row; the session_id match is the
|
|
5668
|
+
// legacy fallback only for events that arrive without a taskId.
|
|
5669
|
+
updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
|
|
5661
5670
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5671
|
+
if (taskId) {
|
|
5672
|
+
this.db.prepare(`
|
|
5673
|
+
UPDATE mesh_direct_dispatches
|
|
5674
|
+
SET status = @status, updated_at = @updatedAt
|
|
5675
|
+
WHERE mesh_id = @meshId AND task_id = @taskId
|
|
5676
|
+
AND status NOT IN ('completed', 'failed')
|
|
5677
|
+
`).run({ status, meshId, taskId, updatedAt: now });
|
|
5678
|
+
return;
|
|
5679
|
+
}
|
|
5680
|
+
if (!sessionId) return;
|
|
5662
5681
|
this.db.prepare(`
|
|
5663
5682
|
UPDATE mesh_direct_dispatches
|
|
5664
5683
|
SET status = @status, updated_at = @updatedAt
|
|
@@ -7387,7 +7406,7 @@ function resolveWin32Executable(command) {
|
|
|
7387
7406
|
windowsHide: true
|
|
7388
7407
|
}).trim();
|
|
7389
7408
|
if (out) {
|
|
7390
|
-
const matches = out.split(/\r?\n/).map((
|
|
7409
|
+
const matches = out.split(/\r?\n/).map((s2) => s2.trim()).filter(Boolean);
|
|
7391
7410
|
const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
|
|
7392
7411
|
return direct || matches[0] || command;
|
|
7393
7412
|
}
|
|
@@ -8739,11 +8758,29 @@ function hasPendingRefineTerminalEventDuplicate(event) {
|
|
|
8739
8758
|
(pending) => pending.event === event.event && readRefineJobId2(pending) === jobId
|
|
8740
8759
|
);
|
|
8741
8760
|
}
|
|
8761
|
+
function isWeakCompletionMetadata(metadata) {
|
|
8762
|
+
const evidenceLevel = readNonEmptyString2(metadata.evidenceLevel);
|
|
8763
|
+
if (evidenceLevel === "insufficient" || evidenceLevel === "weak") return true;
|
|
8764
|
+
if (metadata.reviewRecommended === true) return true;
|
|
8765
|
+
const diag = readRecord4(metadata.completionDiagnostic);
|
|
8766
|
+
return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
|
|
8767
|
+
}
|
|
8742
8768
|
function buildPendingEventFingerprint(event) {
|
|
8743
8769
|
const metadata = readRecord4(event.metadataEvent) || {};
|
|
8744
8770
|
if (event.event === "worktree_bootstrap_complete" || event.event === "worktree_bootstrap_failed") {
|
|
8745
8771
|
return [event.meshId, event.event, event.nodeId || ""].join("::");
|
|
8746
8772
|
}
|
|
8773
|
+
if (TERMINAL_COMPLETION_EVENTS.has(event.event)) {
|
|
8774
|
+
const terminalTaskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
|
|
8775
|
+
if (terminalTaskId) {
|
|
8776
|
+
return [
|
|
8777
|
+
event.meshId,
|
|
8778
|
+
event.event,
|
|
8779
|
+
terminalTaskId,
|
|
8780
|
+
isWeakCompletionMetadata(metadata) ? "weak" : "genuine"
|
|
8781
|
+
].join("::");
|
|
8782
|
+
}
|
|
8783
|
+
}
|
|
8747
8784
|
const sessionId = resolveEventSessionId(metadata);
|
|
8748
8785
|
const providerSessionId = readNonEmptyString2(metadata.providerSessionId);
|
|
8749
8786
|
const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
|
|
@@ -9102,7 +9139,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
9102
9139
|
}
|
|
9103
9140
|
}
|
|
9104
9141
|
}
|
|
9105
|
-
var REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
|
|
9142
|
+
var REFINE_TERMINAL_EVENTS, TERMINAL_COMPLETION_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
|
|
9106
9143
|
var init_mesh_events_pending = __esm({
|
|
9107
9144
|
"src/mesh/mesh-events-pending.ts"() {
|
|
9108
9145
|
"use strict";
|
|
@@ -9112,6 +9149,7 @@ var init_mesh_events_pending = __esm({
|
|
|
9112
9149
|
init_mesh_events_utils();
|
|
9113
9150
|
init_dist();
|
|
9114
9151
|
REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
|
|
9152
|
+
TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
|
|
9115
9153
|
MAX_PENDING_EVENTS_BYTES = 100 * 1024;
|
|
9116
9154
|
MAX_PENDING_EVENTS_KEEP = 50;
|
|
9117
9155
|
}
|
|
@@ -9441,7 +9479,7 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
|
|
|
9441
9479
|
evidence
|
|
9442
9480
|
}
|
|
9443
9481
|
});
|
|
9444
|
-
updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
|
|
9482
|
+
updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed", args.taskId);
|
|
9445
9483
|
markSessionDeliveriesTerminal(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
|
|
9446
9484
|
setImmediate(() => cleanupTerminalDirectDispatches());
|
|
9447
9485
|
queuePendingMeshCoordinatorEvent({
|
|
@@ -9736,8 +9774,8 @@ function parsePatternEntry(x) {
|
|
|
9736
9774
|
if (x instanceof RegExp) return x;
|
|
9737
9775
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
9738
9776
|
try {
|
|
9739
|
-
const
|
|
9740
|
-
return new RegExp(
|
|
9777
|
+
const s2 = x;
|
|
9778
|
+
return new RegExp(s2.source, s2.flags || "");
|
|
9741
9779
|
} catch {
|
|
9742
9780
|
return null;
|
|
9743
9781
|
}
|
|
@@ -10305,6 +10343,38 @@ var init_mesh_unresolved_forward_outbox = __esm({
|
|
|
10305
10343
|
}
|
|
10306
10344
|
});
|
|
10307
10345
|
|
|
10346
|
+
// src/mesh/mesh-event-trace.ts
|
|
10347
|
+
function s(v) {
|
|
10348
|
+
return typeof v === "string" && v.trim() ? v.trim() : "";
|
|
10349
|
+
}
|
|
10350
|
+
function meshEventTraceKey(ctx) {
|
|
10351
|
+
const segs = [`task=${s(ctx.taskId) || "-"}`];
|
|
10352
|
+
const eventId = s(ctx.eventId);
|
|
10353
|
+
if (eventId) segs.push(`evt=${eventId}`);
|
|
10354
|
+
segs.push(`sess=${s(ctx.sessionId) || "-"}`);
|
|
10355
|
+
const nodeId = s(ctx.nodeId);
|
|
10356
|
+
if (nodeId) segs.push(`node=${nodeId}`);
|
|
10357
|
+
const meshId = s(ctx.meshId);
|
|
10358
|
+
if (meshId) segs.push(`mesh=${meshId}`);
|
|
10359
|
+
const event = s(ctx.event);
|
|
10360
|
+
if (event) segs.push(`event=${event}`);
|
|
10361
|
+
return segs.join(" ");
|
|
10362
|
+
}
|
|
10363
|
+
function traceMeshEventStage(stage, ctx, detail) {
|
|
10364
|
+
LOG.info(CAT, `[stage:${stage}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
10365
|
+
}
|
|
10366
|
+
function traceMeshEventDrop(reason, ctx, detail) {
|
|
10367
|
+
LOG.warn(CAT, `[drop:${reason}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
10368
|
+
}
|
|
10369
|
+
var CAT;
|
|
10370
|
+
var init_mesh_event_trace = __esm({
|
|
10371
|
+
"src/mesh/mesh-event-trace.ts"() {
|
|
10372
|
+
"use strict";
|
|
10373
|
+
init_logger();
|
|
10374
|
+
CAT = "EvtTrace";
|
|
10375
|
+
}
|
|
10376
|
+
});
|
|
10377
|
+
|
|
10308
10378
|
// src/config/state-store.ts
|
|
10309
10379
|
import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
10310
10380
|
import { join as join18 } from "path";
|
|
@@ -12090,9 +12160,9 @@ function buildAcpSession(state, options) {
|
|
|
12090
12160
|
}
|
|
12091
12161
|
function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
12092
12162
|
const sessions = [];
|
|
12093
|
-
const ideStates = allStates.filter((
|
|
12094
|
-
const cliStates = allStates.filter((
|
|
12095
|
-
const acpStates = allStates.filter((
|
|
12163
|
+
const ideStates = allStates.filter((s2) => s2.category === "ide");
|
|
12164
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli");
|
|
12165
|
+
const acpStates = allStates.filter((s2) => s2.category === "acp");
|
|
12096
12166
|
for (const state of ideStates) {
|
|
12097
12167
|
sessions.push(buildWorkspaceSession(state, cdpManagers, options));
|
|
12098
12168
|
for (const ext of state.extensions) {
|
|
@@ -12577,6 +12647,15 @@ function getCachedMeshByWorkspace(workspace) {
|
|
|
12577
12647
|
meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
|
|
12578
12648
|
return mesh;
|
|
12579
12649
|
}
|
|
12650
|
+
function recoverMeshIdByNodeId(nodeId) {
|
|
12651
|
+
if (!nodeId) return "";
|
|
12652
|
+
for (const mesh of listMeshes()) {
|
|
12653
|
+
if (Array.isArray(mesh.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, nodeId))) {
|
|
12654
|
+
return readNonEmptyString2(mesh.id);
|
|
12655
|
+
}
|
|
12656
|
+
}
|
|
12657
|
+
return "";
|
|
12658
|
+
}
|
|
12580
12659
|
function __resetIdleAutoFastForwardForTests() {
|
|
12581
12660
|
idleAutoFastForwardLastAttempt.clear();
|
|
12582
12661
|
}
|
|
@@ -13479,6 +13558,13 @@ function shouldForceInjectMeshEvent(eventName) {
|
|
|
13479
13558
|
function injectMeshSystemMessage(components, args) {
|
|
13480
13559
|
const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
13481
13560
|
const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
13561
|
+
const traceCtx = {
|
|
13562
|
+
taskId: args.metadataEvent.taskId,
|
|
13563
|
+
sessionId: eventSessionId,
|
|
13564
|
+
nodeId: eventNodeId,
|
|
13565
|
+
meshId: args.meshId,
|
|
13566
|
+
event: args.event
|
|
13567
|
+
};
|
|
13482
13568
|
const sourceSession = args.sourceInstanceId ? components.instanceManager.getInstance(args.sourceInstanceId) : void 0;
|
|
13483
13569
|
const workerCoordinatorDaemonId = readNonEmptyString2(
|
|
13484
13570
|
sourceSession?.getState()?.settings?.meshCoordinatorDaemonId
|
|
@@ -13532,6 +13618,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13532
13618
|
}
|
|
13533
13619
|
}
|
|
13534
13620
|
LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
|
|
13621
|
+
traceMeshEventDrop("intentional_cleanup_stop", traceCtx);
|
|
13535
13622
|
return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
|
|
13536
13623
|
}
|
|
13537
13624
|
if (args.event === "monitor:no_progress") {
|
|
@@ -13552,6 +13639,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13552
13639
|
}
|
|
13553
13640
|
if (reconciledCompletion?.source === "no_progress_terminal_ledger_suppression") {
|
|
13554
13641
|
LOG.info("MeshEvents", `Suppressed no-progress monitor because terminal ledger evidence already exists for session ${eventSessionId || "(unknown session)"}`);
|
|
13642
|
+
traceMeshEventDrop("no_progress_terminal_ledger_suppression", traceCtx, `terminalKind=${reconciledCompletion.terminalLedgerKind}`);
|
|
13555
13643
|
return {
|
|
13556
13644
|
success: true,
|
|
13557
13645
|
forwarded: 0,
|
|
@@ -13563,6 +13651,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13563
13651
|
}
|
|
13564
13652
|
if (isDuplicateRefineTerminalEvent(args.meshId, args.event, args.metadataEvent)) {
|
|
13565
13653
|
LOG.info("MeshEvents", `Suppressed duplicate ${args.event} for refine job ${readRefineJobId({ metadataEvent: args.metadataEvent })}`);
|
|
13654
|
+
traceMeshEventDrop("duplicate_refine_terminal", traceCtx);
|
|
13566
13655
|
return { success: true, forwarded: 0, suppressed: true, duplicateRefineTerminalEvent: true };
|
|
13567
13656
|
}
|
|
13568
13657
|
const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
|
|
@@ -13577,6 +13666,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13577
13666
|
});
|
|
13578
13667
|
if (duplicateApproval) {
|
|
13579
13668
|
LOG.info("MeshEvents", `Suppressed duplicate approval event for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13669
|
+
traceMeshEventDrop("duplicate_approval", traceCtx);
|
|
13580
13670
|
return { success: true, forwarded: 0, suppressed: true, duplicateApproval: true };
|
|
13581
13671
|
}
|
|
13582
13672
|
}
|
|
@@ -13596,6 +13686,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13596
13686
|
const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
|
|
13597
13687
|
if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "no_progress_reconciliation") {
|
|
13598
13688
|
LOG.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13689
|
+
traceMeshEventDrop("duplicate_completion_terminal_ledger", traceCtx);
|
|
13599
13690
|
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
|
|
13600
13691
|
}
|
|
13601
13692
|
}
|
|
@@ -13614,6 +13705,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13614
13705
|
});
|
|
13615
13706
|
if (duplicateCompletion) {
|
|
13616
13707
|
LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13708
|
+
traceMeshEventDrop("duplicate_completion", traceCtx);
|
|
13617
13709
|
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
|
|
13618
13710
|
}
|
|
13619
13711
|
}
|
|
@@ -13632,6 +13724,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13632
13724
|
});
|
|
13633
13725
|
if (duplicateStopped) {
|
|
13634
13726
|
LOG.info("MeshEvents", `Suppressed duplicate stopped event for mesh ${args.meshId} session ${eventSessionId}`);
|
|
13727
|
+
traceMeshEventDrop("duplicate_stopped", traceCtx);
|
|
13635
13728
|
return { success: true, forwarded: 0, suppressed: true, duplicateStopped: true };
|
|
13636
13729
|
}
|
|
13637
13730
|
}
|
|
@@ -13643,7 +13736,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13643
13736
|
});
|
|
13644
13737
|
const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true;
|
|
13645
13738
|
if (!leaveDirectDispatchActive) {
|
|
13646
|
-
updateDirectDispatchStatus(args.meshId, sessionId, outcome);
|
|
13739
|
+
updateDirectDispatchStatus(args.meshId, sessionId, outcome, eventTaskId);
|
|
13647
13740
|
}
|
|
13648
13741
|
markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
|
|
13649
13742
|
setImmediate(() => cleanupTerminalDirectDispatches());
|
|
@@ -13656,7 +13749,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13656
13749
|
const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
13657
13750
|
const providerType = readNonEmptyString2(args.metadataEvent.providerType);
|
|
13658
13751
|
if (sessionId) {
|
|
13659
|
-
directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13752
|
+
directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13660
13753
|
const isFalseIdle = isFalseIdleCompletion(args.metadataEvent);
|
|
13661
13754
|
completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
|
|
13662
13755
|
if (nodeId && providerType) {
|
|
@@ -13739,7 +13832,8 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13739
13832
|
}
|
|
13740
13833
|
}
|
|
13741
13834
|
if (sessionId) {
|
|
13742
|
-
|
|
13835
|
+
const startedTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
|
|
13836
|
+
updateDirectDispatchStatus(args.meshId, sessionId, "acked", startedTaskId);
|
|
13743
13837
|
const activeDeliveries = (() => {
|
|
13744
13838
|
try {
|
|
13745
13839
|
return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(args.meshId, sessionId);
|
|
@@ -13747,7 +13841,8 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13747
13841
|
return [];
|
|
13748
13842
|
}
|
|
13749
13843
|
})();
|
|
13750
|
-
|
|
13844
|
+
const deliveriesToAck = startedTaskId ? activeDeliveries.filter((d) => d.taskId === startedTaskId) : activeDeliveries;
|
|
13845
|
+
for (const d of deliveriesToAck) {
|
|
13751
13846
|
updateSessionDeliveryStatus(d.id, "acked");
|
|
13752
13847
|
}
|
|
13753
13848
|
}
|
|
@@ -13761,7 +13856,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13761
13856
|
}
|
|
13762
13857
|
}
|
|
13763
13858
|
if (sessionId) {
|
|
13764
|
-
directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13859
|
+
directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
13765
13860
|
completedTaskForLedger = markSessionTerminal(sessionId, "failed");
|
|
13766
13861
|
}
|
|
13767
13862
|
}
|
|
@@ -13907,6 +14002,9 @@ function injectMeshSystemMessage(components, args) {
|
|
|
13907
14002
|
};
|
|
13908
14003
|
if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
|
|
13909
14004
|
LOG.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ""})`);
|
|
14005
|
+
traceMeshEventStage("queued", traceCtx, workerCoordinatorDaemonId ? `coordinatorDaemon=${workerCoordinatorDaemonId}` : "broadcast");
|
|
14006
|
+
} else {
|
|
14007
|
+
traceMeshEventDrop("queue_dedup", traceCtx);
|
|
13910
14008
|
}
|
|
13911
14009
|
return { success: true, forwarded: 0 };
|
|
13912
14010
|
}
|
|
@@ -13917,8 +14015,23 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
13917
14015
|
}
|
|
13918
14016
|
const nodeId = readNonEmptyString2(payload.nodeId);
|
|
13919
14017
|
const workspace = readNonEmptyString2(payload.workspace);
|
|
13920
|
-
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "");
|
|
13921
|
-
if (!meshId)
|
|
14018
|
+
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId);
|
|
14019
|
+
if (!meshId) {
|
|
14020
|
+
traceMeshEventDrop("meshId_required", {
|
|
14021
|
+
taskId: payload.taskId,
|
|
14022
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
14023
|
+
nodeId,
|
|
14024
|
+
event: eventName
|
|
14025
|
+
}, workspace ? `workspace=${workspace} unresolved` : "no workspace/nodeId");
|
|
14026
|
+
return { success: false, error: "meshId required" };
|
|
14027
|
+
}
|
|
14028
|
+
traceMeshEventStage("received", {
|
|
14029
|
+
taskId: payload.taskId,
|
|
14030
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
14031
|
+
nodeId,
|
|
14032
|
+
meshId,
|
|
14033
|
+
event: eventName
|
|
14034
|
+
});
|
|
13922
14035
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
13923
14036
|
const relayModalMessage = readNonEmptyString2(payload.modalMessage);
|
|
13924
14037
|
const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
|
|
@@ -13999,9 +14112,18 @@ function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
|
13999
14112
|
workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
|
|
14000
14113
|
};
|
|
14001
14114
|
const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
|
|
14115
|
+
const fwdTraceCtx = {
|
|
14116
|
+
taskId: payload.taskId,
|
|
14117
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
14118
|
+
nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId),
|
|
14119
|
+
event: eventName
|
|
14120
|
+
};
|
|
14121
|
+
traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=absent`);
|
|
14122
|
+
traceMeshEventStage("forward_send", fwdTraceCtx, "immediate push");
|
|
14002
14123
|
Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
|
|
14003
14124
|
if (result && result.success === false) {
|
|
14004
14125
|
LOG.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
|
|
14126
|
+
traceMeshEventDrop("immediate_forward_rejected", fwdTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
14005
14127
|
return;
|
|
14006
14128
|
}
|
|
14007
14129
|
if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
|
|
@@ -14069,6 +14191,14 @@ function setupMeshEventForwarding(components) {
|
|
|
14069
14191
|
if (isUnroutableDelegateRejection(routing) && forwardUnresolvedDelegateEvent(components, routing, event)) {
|
|
14070
14192
|
return;
|
|
14071
14193
|
}
|
|
14194
|
+
if (isUnroutableDelegateRejection(routing)) {
|
|
14195
|
+
traceMeshEventDrop("unroutable", {
|
|
14196
|
+
taskId: event.meshActiveTaskId ?? event.taskId,
|
|
14197
|
+
sessionId: routing.sessionId,
|
|
14198
|
+
nodeId: routing.nodeId,
|
|
14199
|
+
event: event.event
|
|
14200
|
+
}, "no coordinator anchor / mesh_unresolved");
|
|
14201
|
+
}
|
|
14072
14202
|
recordUnroutableDelegateEvent(routing, event.event);
|
|
14073
14203
|
return;
|
|
14074
14204
|
}
|
|
@@ -14098,6 +14228,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
14098
14228
|
init_mesh_events_pending();
|
|
14099
14229
|
init_mesh_routing();
|
|
14100
14230
|
init_mesh_unresolved_forward_outbox();
|
|
14231
|
+
init_mesh_event_trace();
|
|
14101
14232
|
init_snapshot();
|
|
14102
14233
|
init_repo_mesh_types();
|
|
14103
14234
|
init_dist();
|
|
@@ -14209,6 +14340,13 @@ function findLiveCoordinators(components) {
|
|
|
14209
14340
|
function injectPendingIntoCoordinator(coordinator, pending) {
|
|
14210
14341
|
if (!coordinator || !pending.coordinatorMessage) return;
|
|
14211
14342
|
const force = shouldForceInjectMeshEvent(pending.event);
|
|
14343
|
+
traceMeshEventStage("surfaced", {
|
|
14344
|
+
taskId: pending.metadataEvent?.taskId,
|
|
14345
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? pending.targetCoordinatorSessionId,
|
|
14346
|
+
nodeId: pending.nodeId,
|
|
14347
|
+
meshId: pending.meshId,
|
|
14348
|
+
event: pending.event
|
|
14349
|
+
}, force ? "force-inject" : "inject");
|
|
14212
14350
|
coordinator.onEvent("send_message", {
|
|
14213
14351
|
input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
|
|
14214
14352
|
...force ? { force: true } : {}
|
|
@@ -14267,6 +14405,13 @@ function recoverStrandedAssignedDispatches(meshId, store) {
|
|
|
14267
14405
|
});
|
|
14268
14406
|
if (reclaimed) {
|
|
14269
14407
|
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})`);
|
|
14408
|
+
traceMeshEventDrop("assigned_stranded_reclaim", {
|
|
14409
|
+
taskId: row.id,
|
|
14410
|
+
sessionId: row.assignedSessionId,
|
|
14411
|
+
nodeId: row.assignedNodeId,
|
|
14412
|
+
meshId,
|
|
14413
|
+
event: "agent:generating_completed"
|
|
14414
|
+
}, `unconfirmed ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s \u2192 ${reclaimed.status}`);
|
|
14270
14415
|
}
|
|
14271
14416
|
}
|
|
14272
14417
|
}
|
|
@@ -14426,6 +14571,13 @@ function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
|
|
|
14426
14571
|
try {
|
|
14427
14572
|
queuePendingMeshCoordinatorEvent(pending);
|
|
14428
14573
|
LOG.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})`);
|
|
14574
|
+
traceMeshEventDrop("strict_route_hold", {
|
|
14575
|
+
taskId: pending.metadataEvent?.taskId,
|
|
14576
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
|
|
14577
|
+
nodeId: pending.nodeId,
|
|
14578
|
+
meshId,
|
|
14579
|
+
event: pending.event
|
|
14580
|
+
}, `coordinatorSession=${wantSession} not live`);
|
|
14429
14581
|
} catch (e) {
|
|
14430
14582
|
LOG.warn("MeshReconcile", `Strict route re-queue failed for ${pending.event} on mesh ${meshId}: ${e?.message || e}`);
|
|
14431
14583
|
}
|
|
@@ -14449,6 +14601,13 @@ function holdOrExpireStrictUnmatchedEvent(pending, wantSession, meshId) {
|
|
|
14449
14601
|
}
|
|
14450
14602
|
});
|
|
14451
14603
|
LOG.warn("MeshReconcile", `Strict route expire: coordinator session ${wantSession} never returned for mesh ${meshId} \u2014 recorded to ledger (recoverable), dropped (${pending.event})`);
|
|
14604
|
+
traceMeshEventDrop("strict_route_expired", {
|
|
14605
|
+
taskId: pending.metadataEvent?.taskId,
|
|
14606
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
|
|
14607
|
+
nodeId: pending.nodeId,
|
|
14608
|
+
meshId,
|
|
14609
|
+
event: pending.event
|
|
14610
|
+
}, `coordinatorSession=${wantSession} never returned`);
|
|
14452
14611
|
} catch (e) {
|
|
14453
14612
|
LOG.warn("MeshReconcile", `Failed to ledger-expire strict-unmatched ${pending.event} for mesh ${meshId}: ${e?.message || e}`);
|
|
14454
14613
|
}
|
|
@@ -14460,15 +14619,24 @@ async function retryUnresolvedDelegateForwards(components) {
|
|
|
14460
14619
|
const entries = peekUnresolvedDelegateForwards();
|
|
14461
14620
|
if (entries.length === 0) return;
|
|
14462
14621
|
for (const entry of entries) {
|
|
14622
|
+
const entryTraceCtx = {
|
|
14623
|
+
taskId: entry.payload.taskId,
|
|
14624
|
+
sessionId: readNonEmptyString2(entry.payload.targetSessionId) || readNonEmptyString2(entry.payload.sessionId),
|
|
14625
|
+
nodeId: readNonEmptyString2(entry.payload.nodeId),
|
|
14626
|
+
event: readNonEmptyString2(entry.payload.event)
|
|
14627
|
+
};
|
|
14463
14628
|
let result;
|
|
14464
14629
|
try {
|
|
14630
|
+
traceMeshEventStage("forward_send", entryTraceCtx, `retry \u2192 ${entry.coordinatorDaemonId}`);
|
|
14465
14631
|
result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
|
|
14466
14632
|
} catch (e) {
|
|
14467
14633
|
LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
|
|
14634
|
+
traceMeshEventDrop("retry_forward_failed", entryTraceCtx, e?.message || String(e));
|
|
14468
14635
|
continue;
|
|
14469
14636
|
}
|
|
14470
14637
|
if (result && result.success === false) {
|
|
14471
14638
|
LOG.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
|
|
14639
|
+
traceMeshEventDrop("retry_forward_rejected", entryTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
14472
14640
|
continue;
|
|
14473
14641
|
}
|
|
14474
14642
|
ackUnresolvedDelegateForward(entry.id);
|
|
@@ -14710,6 +14878,7 @@ var init_mesh_reconcile_loop = __esm({
|
|
|
14710
14878
|
init_mesh_events_coordinator();
|
|
14711
14879
|
init_mesh_unresolved_forward_outbox();
|
|
14712
14880
|
init_mesh_events_utils();
|
|
14881
|
+
init_mesh_event_trace();
|
|
14713
14882
|
init_dist();
|
|
14714
14883
|
init_mesh_work_queue();
|
|
14715
14884
|
init_mesh_ledger();
|
|
@@ -15548,8 +15717,8 @@ function saveProvidersActive(file) {
|
|
|
15548
15717
|
}
|
|
15549
15718
|
function isValidSource(x) {
|
|
15550
15719
|
if (!x || typeof x !== "object") return false;
|
|
15551
|
-
const
|
|
15552
|
-
return typeof
|
|
15720
|
+
const s2 = x;
|
|
15721
|
+
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";
|
|
15553
15722
|
}
|
|
15554
15723
|
function deriveSourceName(url) {
|
|
15555
15724
|
const m = url.match(/[/:]([^/:]+)\/([^/]+?)(?:\.git)?$/);
|
|
@@ -15605,7 +15774,7 @@ function inventoryExternalSources() {
|
|
|
15605
15774
|
}
|
|
15606
15775
|
function sourcesProviding(category, type) {
|
|
15607
15776
|
const inventory = inventoryExternalSources();
|
|
15608
|
-
return inventory.filter((
|
|
15777
|
+
return inventory.filter((s2) => (s2.providers[category] || []).includes(type)).map((s2) => s2.sourceName);
|
|
15609
15778
|
}
|
|
15610
15779
|
function resolveActiveSource(category, type, activeFile) {
|
|
15611
15780
|
const candidates = sourcesProviding(category, type);
|
|
@@ -15809,10 +15978,10 @@ function compileSettledPromptMatchers(spec) {
|
|
|
15809
15978
|
const footers = (spec.withFooter ?? []).map((f) => {
|
|
15810
15979
|
if (f.kind === "regex") {
|
|
15811
15980
|
const re = compile2(f.pattern, f.flags ?? "i");
|
|
15812
|
-
return { test: (
|
|
15981
|
+
return { test: (s2) => re.test(s2) };
|
|
15813
15982
|
}
|
|
15814
15983
|
const needle = f.pattern.toLowerCase();
|
|
15815
|
-
return { test: (
|
|
15984
|
+
return { test: (s2) => s2.toLowerCase().includes(needle) };
|
|
15816
15985
|
});
|
|
15817
15986
|
return { prompt, footers };
|
|
15818
15987
|
}
|
|
@@ -16686,7 +16855,7 @@ var init_cli_state_engine = __esm({
|
|
|
16686
16855
|
}
|
|
16687
16856
|
resolveModal(buttonIndex) {
|
|
16688
16857
|
const snap = this.transport.getSnapshot();
|
|
16689
|
-
const parseApproval = typeof this.transport.runParseApproval === "function" ? (
|
|
16858
|
+
const parseApproval = typeof this.transport.runParseApproval === "function" ? (s2) => this.transport.runParseApproval(s2.recentOutputBuffer.slice(-500)) : (s2) => this.runParseApproval(s2);
|
|
16690
16859
|
let modal = this.activeModal ?? parseApproval(snap);
|
|
16691
16860
|
if (!modal && this.runner.hasParseSession()) {
|
|
16692
16861
|
try {
|
|
@@ -19374,22 +19543,23 @@ function resolveSections(sectionsObj, lines) {
|
|
|
19374
19543
|
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]));
|
|
19375
19544
|
let idx = -1;
|
|
19376
19545
|
for (const c of candidates) {
|
|
19546
|
+
let candIdx = -1;
|
|
19377
19547
|
if (sec.anchor_last) {
|
|
19378
19548
|
for (let i = total - 1; i >= 0; i--) {
|
|
19379
19549
|
if (matchesCandidate(c, i)) {
|
|
19380
|
-
|
|
19550
|
+
candIdx = i;
|
|
19381
19551
|
break;
|
|
19382
19552
|
}
|
|
19383
19553
|
}
|
|
19384
19554
|
} else {
|
|
19385
19555
|
for (let i = 0; i < total; i++) {
|
|
19386
19556
|
if (matchesCandidate(c, i)) {
|
|
19387
|
-
|
|
19557
|
+
candIdx = i;
|
|
19388
19558
|
break;
|
|
19389
19559
|
}
|
|
19390
19560
|
}
|
|
19391
19561
|
}
|
|
19392
|
-
if (
|
|
19562
|
+
if (candIdx !== -1 && (idx === -1 || candIdx < idx)) idx = candIdx;
|
|
19393
19563
|
}
|
|
19394
19564
|
if (idx !== -1) {
|
|
19395
19565
|
from = idx;
|
|
@@ -19441,7 +19611,7 @@ function resolveSections(sectionsObj, lines) {
|
|
|
19441
19611
|
}
|
|
19442
19612
|
function sectionText(sections, sectionId, fullScreen) {
|
|
19443
19613
|
if (!sectionId) return fullScreen;
|
|
19444
|
-
const found = sections.find((
|
|
19614
|
+
const found = sections.find((s2) => s2.id === sectionId);
|
|
19445
19615
|
return found ? found.text : "";
|
|
19446
19616
|
}
|
|
19447
19617
|
function isRegexCondition(c) {
|
|
@@ -19609,10 +19779,10 @@ function isV4Spec(raw) {
|
|
|
19609
19779
|
return !!raw && typeof raw === "object" && raw.$schema === "adhdev:cli/spec@4";
|
|
19610
19780
|
}
|
|
19611
19781
|
function initialState(spec) {
|
|
19612
|
-
return spec.states.find((
|
|
19782
|
+
return spec.states.find((s2) => s2.initial) ?? spec.states[0];
|
|
19613
19783
|
}
|
|
19614
19784
|
function stateById(spec, id) {
|
|
19615
|
-
return spec.states.find((
|
|
19785
|
+
return spec.states.find((s2) => s2.id === id);
|
|
19616
19786
|
}
|
|
19617
19787
|
function outgoingTransitions(spec, stateId) {
|
|
19618
19788
|
const matches = spec.transitions.filter((t) => {
|
|
@@ -19701,7 +19871,17 @@ function evalCond(cond, sections, fullScreen, cursor, prevLines, clock, legacyTr
|
|
|
19701
19871
|
const result = evaluateCondition(cond, sections, fullScreen, cursor, prevLines, legacyTrace, stateId);
|
|
19702
19872
|
const kind = isRegex(cond) ? "regex" : "changed";
|
|
19703
19873
|
const detail = isRegex(cond) ? `${cond.section ?? "*"}~/${cond.matches}/` : `cursor_above=${cond.cursor_above} changed=${cond.changed}`;
|
|
19704
|
-
|
|
19874
|
+
let matchedText;
|
|
19875
|
+
if (result && isRegex(cond)) {
|
|
19876
|
+
try {
|
|
19877
|
+
const hay = sectionText(sections, cond.section, fullScreen);
|
|
19878
|
+
const re = new RegExp(cond.matches, cond.flags ?? "i");
|
|
19879
|
+
const m = re.exec(hay);
|
|
19880
|
+
if (m && m[0]) matchedText = m[0].replace(/\s+/g, " ").trim().slice(0, 160);
|
|
19881
|
+
} catch {
|
|
19882
|
+
}
|
|
19883
|
+
}
|
|
19884
|
+
return matchedText ? { kind, result, detail, matchedText } : { kind, result, detail };
|
|
19705
19885
|
}
|
|
19706
19886
|
return { kind: "all", result: false, detail: "unknown condition" };
|
|
19707
19887
|
}
|
|
@@ -19817,17 +19997,17 @@ function validateFsmSpec(raw) {
|
|
|
19817
19997
|
}
|
|
19818
19998
|
const ids = /* @__PURE__ */ new Set();
|
|
19819
19999
|
let initialCount = 0;
|
|
19820
|
-
for (const [i,
|
|
19821
|
-
if (!
|
|
20000
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
20001
|
+
if (!s2.id) {
|
|
19822
20002
|
errs.push(`states[${i}].id is required`);
|
|
19823
20003
|
continue;
|
|
19824
20004
|
}
|
|
19825
|
-
if (ids.has(
|
|
19826
|
-
ids.add(
|
|
19827
|
-
if (!
|
|
19828
|
-
if (
|
|
19829
|
-
if (
|
|
19830
|
-
errs.push(`states[${i}].status "${
|
|
20005
|
+
if (ids.has(s2.id)) errs.push(`states[${i}].id "${s2.id}" is duplicated`);
|
|
20006
|
+
ids.add(s2.id);
|
|
20007
|
+
if (!s2.label) errs.push(`states[${i}].label is required`);
|
|
20008
|
+
if (s2.initial) initialCount += 1;
|
|
20009
|
+
if (s2.status && !["idle", "generating", "approval"].includes(s2.status)) {
|
|
20010
|
+
errs.push(`states[${i}].status "${s2.status}" must be idle|generating|approval`);
|
|
19831
20011
|
}
|
|
19832
20012
|
}
|
|
19833
20013
|
if (initialCount === 0) errs.push("exactly one state must have initial:true (none found)");
|
|
@@ -19843,10 +20023,10 @@ function validateFsmSpec(raw) {
|
|
|
19843
20023
|
else if (!ids.has(t.to)) errs.push(`transitions[${i}].to references unknown state "${t.to}"`);
|
|
19844
20024
|
if (t.when) errs.push(...validateCondition(t.when, sectionIds, `transitions[${i}].when`));
|
|
19845
20025
|
}
|
|
19846
|
-
for (const [i,
|
|
19847
|
-
const sec =
|
|
20026
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
20027
|
+
const sec = s2.extract?.title?.section;
|
|
19848
20028
|
if (sec && !sectionIds.has(sec)) errs.push(`states[${i}].extract.title.section "${sec}" unknown`);
|
|
19849
|
-
const bsec =
|
|
20029
|
+
const bsec = s2.extract?.buttons?.section;
|
|
19850
20030
|
if (bsec && !sectionIds.has(bsec)) errs.push(`states[${i}].extract.buttons.section "${bsec}" unknown`);
|
|
19851
20031
|
}
|
|
19852
20032
|
return errs;
|
|
@@ -32218,10 +32398,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32218
32398
|
const path42 = __require("path");
|
|
32219
32399
|
const { spawnSync: spawnSync2 } = __require("child_process");
|
|
32220
32400
|
const file = ext.loadExternalSources();
|
|
32221
|
-
if (file.sources.some((
|
|
32401
|
+
if (file.sources.some((s2) => s2.name === requestedName)) {
|
|
32222
32402
|
return { success: false, error: `source name "${requestedName}" is already registered` };
|
|
32223
32403
|
}
|
|
32224
|
-
if (file.sources.some((
|
|
32404
|
+
if (file.sources.some((s2) => s2.url === url && s2.ref === ref)) {
|
|
32225
32405
|
return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
|
|
32226
32406
|
}
|
|
32227
32407
|
const sourceDir = path42.join(ext.externalRoot(), requestedName);
|
|
@@ -32283,7 +32463,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32283
32463
|
const fs32 = __require("fs");
|
|
32284
32464
|
const path42 = __require("path");
|
|
32285
32465
|
const file = ext.loadExternalSources();
|
|
32286
|
-
const match = file.sources.find((
|
|
32466
|
+
const match = file.sources.find((s2) => s2.name === name);
|
|
32287
32467
|
if (!match) return { success: false, error: `source "${name}" not registered` };
|
|
32288
32468
|
const sourceDir = path42.join(ext.externalRoot(), name);
|
|
32289
32469
|
if (fs32.existsSync(sourceDir)) {
|
|
@@ -32295,7 +32475,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32295
32475
|
}
|
|
32296
32476
|
ext.saveExternalSources({
|
|
32297
32477
|
schema: 1,
|
|
32298
|
-
sources: file.sources.filter((
|
|
32478
|
+
sources: file.sources.filter((s2) => s2.name !== name)
|
|
32299
32479
|
});
|
|
32300
32480
|
const active = ext.loadProvidersActive();
|
|
32301
32481
|
const filteredActive = {};
|
|
@@ -32319,10 +32499,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
32319
32499
|
const file = ext.loadExternalSources();
|
|
32320
32500
|
const inventory = ext.inventoryExternalSources();
|
|
32321
32501
|
const active = ext.loadProvidersActive();
|
|
32322
|
-
const sources = file.sources.map((
|
|
32323
|
-
const inv = inventory.find((e) => e.sourceName ===
|
|
32502
|
+
const sources = file.sources.map((s2) => {
|
|
32503
|
+
const inv = inventory.find((e) => e.sourceName === s2.name);
|
|
32324
32504
|
return {
|
|
32325
|
-
...
|
|
32505
|
+
...s2,
|
|
32326
32506
|
providers: inv?.providers ?? {}
|
|
32327
32507
|
};
|
|
32328
32508
|
});
|
|
@@ -32499,6 +32679,21 @@ import * as path21 from "path";
|
|
|
32499
32679
|
// src/providers/spec/adapter.ts
|
|
32500
32680
|
init_terminal_screen();
|
|
32501
32681
|
import { DEFAULT_SESSION_HOST_COLS as DEFAULT_SESSION_HOST_COLS5, DEFAULT_SESSION_HOST_ROWS as DEFAULT_SESSION_HOST_ROWS5 } from "@adhdev/session-host-core";
|
|
32682
|
+
var MAX_PTY_EVENTS = 300;
|
|
32683
|
+
var EVENT_CONTENT_CAP = 240;
|
|
32684
|
+
function escapeControl(text) {
|
|
32685
|
+
return String(text).replace(/[\x00-\x1f\x7f]/g, (ch) => {
|
|
32686
|
+
const code = ch.charCodeAt(0);
|
|
32687
|
+
if (ch === "\r") return "\\r";
|
|
32688
|
+
if (ch === "\n") return "\\n";
|
|
32689
|
+
if (ch === " ") return "\\t";
|
|
32690
|
+
if (code === 27) return "\\x1b";
|
|
32691
|
+
return "\\x" + code.toString(16).padStart(2, "0");
|
|
32692
|
+
});
|
|
32693
|
+
}
|
|
32694
|
+
function capPreview(text) {
|
|
32695
|
+
return text.length > EVENT_CONTENT_CAP ? text.slice(0, EVENT_CONTENT_CAP) + `\u2026(+${text.length - EVENT_CONTENT_CAP})` : text;
|
|
32696
|
+
}
|
|
32502
32697
|
var TerminalAdapter = class {
|
|
32503
32698
|
constructor(opts, handlers) {
|
|
32504
32699
|
this.opts = opts;
|
|
@@ -32525,6 +32720,9 @@ var TerminalAdapter = class {
|
|
|
32525
32720
|
screenTimer = null;
|
|
32526
32721
|
tickTimer = null;
|
|
32527
32722
|
lastScreen = "";
|
|
32723
|
+
/** Debug-only ring buffer of PTY input/output/resize/cursor events. */
|
|
32724
|
+
events = [];
|
|
32725
|
+
lastCursorKey = "";
|
|
32528
32726
|
start() {
|
|
32529
32727
|
const env = this.opts.envIsComplete ? this.opts.env ?? {} : { ...process.env, ...this.opts.env ?? {} };
|
|
32530
32728
|
this.pty = this.factory.spawn(this.opts.binary, this.opts.args ?? [], {
|
|
@@ -32533,10 +32731,12 @@ var TerminalAdapter = class {
|
|
|
32533
32731
|
cols: this.cols,
|
|
32534
32732
|
rows: this.rows
|
|
32535
32733
|
});
|
|
32734
|
+
this.recordEvent("spawn", `${this.opts.binary} (${this.cols}x${this.rows})`);
|
|
32536
32735
|
this.handlers.init?.({ pid: this.pty.pid });
|
|
32537
32736
|
this.pty.onData((chunk) => this.onChunk(chunk));
|
|
32538
32737
|
this.pty.onExit((info) => {
|
|
32539
32738
|
this.stopTimers();
|
|
32739
|
+
this.recordEvent("exit", `exitCode=${typeof info.exitCode === "number" ? info.exitCode : 0}`);
|
|
32540
32740
|
this.handlers.on_exit?.({ exitCode: typeof info.exitCode === "number" ? info.exitCode : 0 });
|
|
32541
32741
|
this.pty = null;
|
|
32542
32742
|
});
|
|
@@ -32547,6 +32747,7 @@ var TerminalAdapter = class {
|
|
|
32547
32747
|
resize(cols, rows) {
|
|
32548
32748
|
this.cols = cols;
|
|
32549
32749
|
this.rows = rows;
|
|
32750
|
+
this.recordEvent("resize", `${cols}x${rows}`);
|
|
32550
32751
|
this.pty?.resize(cols, rows);
|
|
32551
32752
|
this.screen.resize(rows, cols);
|
|
32552
32753
|
}
|
|
@@ -32567,8 +32768,21 @@ var TerminalAdapter = class {
|
|
|
32567
32768
|
return { row: pos.row, col: pos.col };
|
|
32568
32769
|
}
|
|
32569
32770
|
send_keys(text) {
|
|
32771
|
+
this.recordEvent("input", capPreview(escapeControl(text)), text.length);
|
|
32570
32772
|
this.pty?.write(text);
|
|
32571
32773
|
}
|
|
32774
|
+
/** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
|
|
32775
|
+
* first. Pure observation — never consulted by the FSM. */
|
|
32776
|
+
getEventTimeline(limit = MAX_PTY_EVENTS) {
|
|
32777
|
+
const n = Math.max(0, Math.min(limit, this.events.length));
|
|
32778
|
+
return this.events.slice(this.events.length - n);
|
|
32779
|
+
}
|
|
32780
|
+
recordEvent(kind, content, bytes) {
|
|
32781
|
+
const ev = { ts: Date.now(), kind, content };
|
|
32782
|
+
if (typeof bytes === "number") ev.bytes = bytes;
|
|
32783
|
+
this.events.push(ev);
|
|
32784
|
+
if (this.events.length > MAX_PTY_EVENTS) this.events.splice(0, this.events.length - MAX_PTY_EVENTS);
|
|
32785
|
+
}
|
|
32572
32786
|
kill() {
|
|
32573
32787
|
this.stopTimers();
|
|
32574
32788
|
try {
|
|
@@ -32579,6 +32793,7 @@ var TerminalAdapter = class {
|
|
|
32579
32793
|
this.screen.dispose();
|
|
32580
32794
|
}
|
|
32581
32795
|
onChunk(chunk) {
|
|
32796
|
+
this.recordEvent("output", capPreview(escapeControl(chunk)), chunk.length);
|
|
32582
32797
|
try {
|
|
32583
32798
|
this.handlers.on_pty_data?.(chunk);
|
|
32584
32799
|
} catch {
|
|
@@ -32588,6 +32803,12 @@ var TerminalAdapter = class {
|
|
|
32588
32803
|
this.screenTimer = setTimeout(() => {
|
|
32589
32804
|
this.screenTimer = null;
|
|
32590
32805
|
const snap = this.computeScreen();
|
|
32806
|
+
const cur = this.screen.getCursorPosition();
|
|
32807
|
+
const curKey = `${cur.row},${cur.col}`;
|
|
32808
|
+
if (curKey !== this.lastCursorKey) {
|
|
32809
|
+
this.lastCursorKey = curKey;
|
|
32810
|
+
this.recordEvent("cursor", `(${cur.row},${cur.col})`);
|
|
32811
|
+
}
|
|
32591
32812
|
if (snap === this.lastScreen) return;
|
|
32592
32813
|
this.lastScreen = snap;
|
|
32593
32814
|
try {
|
|
@@ -32672,20 +32893,40 @@ function applyPreLaunchTrust(trust, workingDir) {
|
|
|
32672
32893
|
|
|
32673
32894
|
// src/providers/spec/fsm-driver.ts
|
|
32674
32895
|
init_logger();
|
|
32675
|
-
function countNewlines(
|
|
32896
|
+
function countNewlines(s2) {
|
|
32676
32897
|
let n = 0;
|
|
32677
|
-
for (let i = 0; i <
|
|
32898
|
+
for (let i = 0; i < s2.length; i += 1) if (s2.charCodeAt(i) === 10) n += 1;
|
|
32678
32899
|
return n;
|
|
32679
32900
|
}
|
|
32680
32901
|
var SUBMIT_DELAY_FLOOR_MS = 200;
|
|
32681
32902
|
var WIN32_SUBMIT_RESEND_GAP_MS = 350;
|
|
32682
32903
|
var WIN32_SUBMIT_MAX_RESENDS = 14;
|
|
32904
|
+
var WIN32_SUBMIT_SETTLE_MS = 500;
|
|
32905
|
+
var WIN32_SUBMIT_MAX_SETTLE_WAIT_MS = 1e4;
|
|
32906
|
+
var WIN32_SUBMIT_SETTLE_POLL_MS = 120;
|
|
32907
|
+
var WIN32_PTY_WRITE_CHUNK_CHARS = 1024;
|
|
32908
|
+
var WIN32_PTY_WRITE_CHUNK_GAP_MS = 8;
|
|
32683
32909
|
function resolveSubmitDelayMs(specBeforeSubmit, text) {
|
|
32684
32910
|
const lines = countNewlines(text);
|
|
32685
32911
|
const linesBonus = Math.min(800, lines * 80);
|
|
32686
32912
|
const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
|
|
32687
32913
|
return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
|
|
32688
32914
|
}
|
|
32915
|
+
function chunkPreservingSurrogates(text, size) {
|
|
32916
|
+
const chunks = [];
|
|
32917
|
+
let offset = 0;
|
|
32918
|
+
while (offset < text.length) {
|
|
32919
|
+
let end = Math.min(text.length, offset + size);
|
|
32920
|
+
if (end < text.length) {
|
|
32921
|
+
const code = text.charCodeAt(end - 1);
|
|
32922
|
+
if (code >= 55296 && code <= 56319) end -= 1;
|
|
32923
|
+
}
|
|
32924
|
+
if (end <= offset) end = Math.min(text.length, offset + size);
|
|
32925
|
+
chunks.push(text.slice(offset, end));
|
|
32926
|
+
offset = end;
|
|
32927
|
+
}
|
|
32928
|
+
return chunks;
|
|
32929
|
+
}
|
|
32689
32930
|
function guessExt(mime) {
|
|
32690
32931
|
if (/png/i.test(mime)) return ".png";
|
|
32691
32932
|
if (/jpe?g/i.test(mime)) return ".jpg";
|
|
@@ -32701,7 +32942,10 @@ var FsmDriver = class {
|
|
|
32701
32942
|
this.buildAdapterOpts(),
|
|
32702
32943
|
{
|
|
32703
32944
|
init: () => this.emitInitialState(),
|
|
32704
|
-
on_pty_data: (chunk) =>
|
|
32945
|
+
on_pty_data: (chunk) => {
|
|
32946
|
+
this.lastPtyDataAt = Date.now();
|
|
32947
|
+
this.emit({ kind: "pty_data", chunk });
|
|
32948
|
+
},
|
|
32705
32949
|
on_screen_changed: () => this.reevaluate(),
|
|
32706
32950
|
on_exit: ({ exitCode }) => this.handleExit(exitCode)
|
|
32707
32951
|
}
|
|
@@ -32735,6 +32979,16 @@ var FsmDriver = class {
|
|
|
32735
32979
|
* WIN32_SUBMIT_* and scheduleWin32Submit). Re-arms itself until the FSM
|
|
32736
32980
|
* leaves idle (submitted) or the resend budget is spent. */
|
|
32737
32981
|
win32SubmitTimer = null;
|
|
32982
|
+
/** Wall-clock (ms) of the most recent raw PTY output chunk. Advances on every
|
|
32983
|
+
* on_pty_data — including the echo of text written into the composer — so the
|
|
32984
|
+
* win32 submit settle-gate can tell when input has finished landing. */
|
|
32985
|
+
lastPtyDataAt = 0;
|
|
32986
|
+
/** Wall-clock (ms) of the most recent win32 message-body input write. Bridges
|
|
32987
|
+
* the gap between writing a chunk and its echo so the settle-gate does not
|
|
32988
|
+
* declare "quiet" mid-write. */
|
|
32989
|
+
lastWin32WriteAt = 0;
|
|
32990
|
+
/** Pending paced chunk-write timer for a large win32 body (see writeWin32Body). */
|
|
32991
|
+
win32WriteTimer = null;
|
|
32738
32992
|
currentEval = null;
|
|
32739
32993
|
stateHistory = [];
|
|
32740
32994
|
prevStateAt = 0;
|
|
@@ -32855,6 +33109,10 @@ var FsmDriver = class {
|
|
|
32855
33109
|
clearTimeout(this.win32SubmitTimer);
|
|
32856
33110
|
this.win32SubmitTimer = null;
|
|
32857
33111
|
}
|
|
33112
|
+
if (this.win32WriteTimer) {
|
|
33113
|
+
clearTimeout(this.win32WriteTimer);
|
|
33114
|
+
this.win32WriteTimer = null;
|
|
33115
|
+
}
|
|
32858
33116
|
this.specWatcher?.close();
|
|
32859
33117
|
this.adapter.kill();
|
|
32860
33118
|
}
|
|
@@ -32885,11 +33143,15 @@ var FsmDriver = class {
|
|
|
32885
33143
|
getFsmSnapshotHistory() {
|
|
32886
33144
|
return this.fsmSnapshotHistory;
|
|
32887
33145
|
}
|
|
33146
|
+
/** Debug-only PTY input/output/resize/cursor timeline from the adapter. */
|
|
33147
|
+
getEventTimeline(limit) {
|
|
33148
|
+
return this.adapter.getEventTimeline(limit);
|
|
33149
|
+
}
|
|
32888
33150
|
getSections() {
|
|
32889
33151
|
try {
|
|
32890
33152
|
const screen = this.adapter.snapshot();
|
|
32891
33153
|
const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
32892
|
-
return resolveSections(this.spec.sections ?? {}, lines).map((
|
|
33154
|
+
return resolveSections(this.spec.sections ?? {}, lines).map((s2) => ({ id: s2.id, text: s2.text }));
|
|
32893
33155
|
} catch {
|
|
32894
33156
|
return null;
|
|
32895
33157
|
}
|
|
@@ -33267,7 +33529,7 @@ var FsmDriver = class {
|
|
|
33267
33529
|
const perChar = sm.delay_ms_per_char ?? 0;
|
|
33268
33530
|
const beforeSubmit = resolveSubmitDelayMs(sm.delay_ms_before_submit, text);
|
|
33269
33531
|
if (process.platform === "win32") {
|
|
33270
|
-
this.
|
|
33532
|
+
this.writeWin32Body(text);
|
|
33271
33533
|
this.scheduleWin32Submit(sm.submit_key, beforeSubmit);
|
|
33272
33534
|
return;
|
|
33273
33535
|
}
|
|
@@ -33293,20 +33555,72 @@ var FsmDriver = class {
|
|
|
33293
33555
|
const st = stateById(this.spec, this.currentStateId);
|
|
33294
33556
|
return st ? statusForState(st) : "idle";
|
|
33295
33557
|
}
|
|
33558
|
+
/** Record a win32 body write so the settle-gate counts it as input activity
|
|
33559
|
+
* even before the echo arrives. */
|
|
33560
|
+
markWin32Write() {
|
|
33561
|
+
this.lastWin32WriteAt = Date.now();
|
|
33562
|
+
}
|
|
33563
|
+
/** Most recent win32 input activity — a write we issued OR a PTY output chunk
|
|
33564
|
+
* (echo). The submit settle-gate waits for this to go quiet. */
|
|
33565
|
+
lastWin32InputActivityAt() {
|
|
33566
|
+
return Math.max(this.lastPtyDataAt, this.lastWin32WriteAt);
|
|
33567
|
+
}
|
|
33296
33568
|
/**
|
|
33297
|
-
*
|
|
33298
|
-
*
|
|
33299
|
-
* a
|
|
33300
|
-
*
|
|
33301
|
-
*
|
|
33302
|
-
*
|
|
33303
|
-
|
|
33569
|
+
* Write the message body to the PTY for win32, paced into bounded chunks. A
|
|
33570
|
+
* single unbounded ConPTY write can overflow the input pipe and drop leading
|
|
33571
|
+
* bytes; splitting it with a short inter-chunk gap keeps the console input
|
|
33572
|
+
* buffer from overflowing. Small bodies still go out in a single write. Each
|
|
33573
|
+
* chunk advances lastWin32WriteAt so the submit settle-gate keeps waiting until
|
|
33574
|
+
* the final chunk is out and echoed.
|
|
33575
|
+
*/
|
|
33576
|
+
writeWin32Body(text) {
|
|
33577
|
+
if (this.win32WriteTimer) {
|
|
33578
|
+
clearTimeout(this.win32WriteTimer);
|
|
33579
|
+
this.win32WriteTimer = null;
|
|
33580
|
+
}
|
|
33581
|
+
if (text.length <= WIN32_PTY_WRITE_CHUNK_CHARS) {
|
|
33582
|
+
this.markWin32Write();
|
|
33583
|
+
this.adapter.send_keys(text);
|
|
33584
|
+
return;
|
|
33585
|
+
}
|
|
33586
|
+
const chunks = chunkPreservingSurrogates(text, WIN32_PTY_WRITE_CHUNK_CHARS);
|
|
33587
|
+
let idx = 0;
|
|
33588
|
+
const writeNext = () => {
|
|
33589
|
+
this.win32WriteTimer = null;
|
|
33590
|
+
if (idx >= chunks.length) return;
|
|
33591
|
+
this.markWin32Write();
|
|
33592
|
+
this.adapter.send_keys(chunks[idx]);
|
|
33593
|
+
idx += 1;
|
|
33594
|
+
if (idx < chunks.length) {
|
|
33595
|
+
this.win32WriteTimer = setTimeout(writeNext, WIN32_PTY_WRITE_CHUNK_GAP_MS);
|
|
33596
|
+
}
|
|
33597
|
+
};
|
|
33598
|
+
writeNext();
|
|
33599
|
+
}
|
|
33600
|
+
/**
|
|
33601
|
+
* win32 submit. Two phases:
|
|
33602
|
+
*
|
|
33603
|
+
* Phase 1 (settle-gate): hold the first CR until the PTY output has been quiet
|
|
33604
|
+
* for WIN32_SUBMIT_SETTLE_MS after the last input write — i.e. the full
|
|
33605
|
+
* (possibly multi-KB / multiline) body has finished arriving in the composer
|
|
33606
|
+
* and echoing. Honors an initial minimum delay and is bounded by
|
|
33607
|
+
* WIN32_SUBMIT_MAX_SETTLE_WAIT_MS so a noisy screen can never hang the submit.
|
|
33608
|
+
* This is what stops a long message from being submitted half-arrived (its
|
|
33609
|
+
* leading lines lost). A short message settles almost immediately.
|
|
33610
|
+
*
|
|
33611
|
+
* Phase 2 (verified resend — unchanged): send the submit key, wait a gap, and
|
|
33612
|
+
* if the FSM is still 'idle' (the CR was absorbed as a multiline-paste
|
|
33613
|
+
* newline) resend, up to WIN32_SUBMIT_MAX_RESENDS. The first CR always fires
|
|
33614
|
+
* (a stale/edge status never suppresses it); resends are gated on still being
|
|
33615
|
+
* idle and stop the instant the agent leaves idle (submitted → generating /
|
|
33616
|
+
* approval). This preserves the win32 lone-CR-swallow handling.
|
|
33304
33617
|
*/
|
|
33305
33618
|
scheduleWin32Submit(submitKey, initialDelayMs) {
|
|
33306
33619
|
if (this.win32SubmitTimer) {
|
|
33307
33620
|
clearTimeout(this.win32SubmitTimer);
|
|
33308
33621
|
this.win32SubmitTimer = null;
|
|
33309
33622
|
}
|
|
33623
|
+
const startedAt = Date.now();
|
|
33310
33624
|
const fire = (attempt) => {
|
|
33311
33625
|
this.win32SubmitTimer = null;
|
|
33312
33626
|
this.adapter.send_keys(submitKey);
|
|
@@ -33319,8 +33633,20 @@ var FsmDriver = class {
|
|
|
33319
33633
|
fire(attempt + 1);
|
|
33320
33634
|
}, WIN32_SUBMIT_RESEND_GAP_MS);
|
|
33321
33635
|
};
|
|
33322
|
-
|
|
33323
|
-
|
|
33636
|
+
const waitForSettle = () => {
|
|
33637
|
+
this.win32SubmitTimer = null;
|
|
33638
|
+
const now = Date.now();
|
|
33639
|
+
const quietFor = now - this.lastWin32InputActivityAt();
|
|
33640
|
+
const waited = now - startedAt;
|
|
33641
|
+
if (quietFor >= WIN32_SUBMIT_SETTLE_MS || waited >= WIN32_SUBMIT_MAX_SETTLE_WAIT_MS) {
|
|
33642
|
+
fire(0);
|
|
33643
|
+
return;
|
|
33644
|
+
}
|
|
33645
|
+
const recheckIn = Math.min(WIN32_SUBMIT_SETTLE_MS - quietFor, WIN32_SUBMIT_SETTLE_POLL_MS);
|
|
33646
|
+
this.win32SubmitTimer = setTimeout(waitForSettle, Math.max(recheckIn, 30));
|
|
33647
|
+
};
|
|
33648
|
+
if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(waitForSettle, initialDelayMs);
|
|
33649
|
+
else waitForSettle();
|
|
33324
33650
|
}
|
|
33325
33651
|
handleClickControl(controlId, payload) {
|
|
33326
33652
|
const ctl = (this.spec.control_bar ?? []).find((c) => c.id === controlId);
|
|
@@ -33433,7 +33759,8 @@ function summarizeTransition(t) {
|
|
|
33433
33759
|
return out;
|
|
33434
33760
|
}
|
|
33435
33761
|
function flattenCond(c, out, depth) {
|
|
33436
|
-
|
|
33762
|
+
const matched = c.matchedText ? ` matched=${JSON.stringify(c.matchedText)}` : "";
|
|
33763
|
+
out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}${matched}`);
|
|
33437
33764
|
for (const child of c.children ?? []) flattenCond(child, out, depth + 1);
|
|
33438
33765
|
}
|
|
33439
33766
|
function findStable(c) {
|
|
@@ -34151,8 +34478,8 @@ function projectToolBlock(block2, role, tmap) {
|
|
|
34151
34478
|
}
|
|
34152
34479
|
return null;
|
|
34153
34480
|
}
|
|
34154
|
-
function oneLine(
|
|
34155
|
-
const flat =
|
|
34481
|
+
function oneLine(s2, max) {
|
|
34482
|
+
const flat = s2.replace(/\s+/g, " ").trim();
|
|
34156
34483
|
return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
|
|
34157
34484
|
}
|
|
34158
34485
|
function parseTimestamp(v) {
|
|
@@ -34172,10 +34499,10 @@ function parseTimestamp(v) {
|
|
|
34172
34499
|
return null;
|
|
34173
34500
|
}
|
|
34174
34501
|
function normalizeRole(r) {
|
|
34175
|
-
const
|
|
34176
|
-
if (
|
|
34177
|
-
if (
|
|
34178
|
-
if (
|
|
34502
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
34503
|
+
if (s2 === "user" || s2 === "human" || s2 === "user_explicit") return "user";
|
|
34504
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
34505
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
34179
34506
|
return "system";
|
|
34180
34507
|
}
|
|
34181
34508
|
function stringifyContent(v) {
|
|
@@ -34223,18 +34550,18 @@ function compileWhere(src) {
|
|
|
34223
34550
|
return (record) => ors.some((ands) => ands.every((t) => evalTerm(t, record)));
|
|
34224
34551
|
}
|
|
34225
34552
|
function parseTerm(src) {
|
|
34226
|
-
let
|
|
34553
|
+
let s2 = src.trim();
|
|
34227
34554
|
let negate = false;
|
|
34228
|
-
if (
|
|
34555
|
+
if (s2.startsWith("!")) {
|
|
34229
34556
|
negate = true;
|
|
34230
|
-
|
|
34557
|
+
s2 = s2.slice(1).trim();
|
|
34231
34558
|
}
|
|
34232
|
-
const fnMatch =
|
|
34559
|
+
const fnMatch = s2.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
|
|
34233
34560
|
if (fnMatch) {
|
|
34234
34561
|
const [, op2, pathExpr, litExpr] = fnMatch;
|
|
34235
34562
|
return { path: pathExpr, op: op2, lit: parseLiteral(litExpr), negate };
|
|
34236
34563
|
}
|
|
34237
|
-
const opMatch =
|
|
34564
|
+
const opMatch = s2.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
|
|
34238
34565
|
if (!opMatch) return null;
|
|
34239
34566
|
const [, lhs, op, rhsRaw] = opMatch;
|
|
34240
34567
|
return { path: lhs.trim(), op, lit: parseLiteral(rhsRaw.trim()), negate };
|
|
@@ -34666,7 +34993,7 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
34666
34993
|
try {
|
|
34667
34994
|
const sections = this.driver.getSections();
|
|
34668
34995
|
if (sectionId && sections) {
|
|
34669
|
-
const hit = sections.find((
|
|
34996
|
+
const hit = sections.find((s2) => s2.id === sectionId);
|
|
34670
34997
|
if (hit) return hit.text;
|
|
34671
34998
|
}
|
|
34672
34999
|
return this.driver.getScreen();
|
|
@@ -34681,7 +35008,7 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
34681
35008
|
screen = this.driver.snapshot();
|
|
34682
35009
|
const driverSections = this.driver.getSections?.();
|
|
34683
35010
|
if (driverSections) {
|
|
34684
|
-
sections = Object.fromEntries(driverSections.map((
|
|
35011
|
+
sections = Object.fromEntries(driverSections.map((s2) => [s2.id, s2.text]));
|
|
34685
35012
|
} else {
|
|
34686
35013
|
sections = this.readCurrentScreenSections(screen);
|
|
34687
35014
|
}
|
|
@@ -34727,6 +35054,10 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
34727
35054
|
// answers "why did this rule fire" after the fact, unlike the live
|
|
34728
35055
|
// `fsm` field which only reflects the current instant.
|
|
34729
35056
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
35057
|
+
// PTY input/output/resize/cursor event timeline (debug-only) so the
|
|
35058
|
+
// snapshot shows what we typed / what the PTY printed around each
|
|
35059
|
+
// status transition. Null for drivers without the timeline.
|
|
35060
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
34730
35061
|
// Extended fields
|
|
34731
35062
|
name: this.cliName,
|
|
34732
35063
|
status: this.getStatus().status,
|
|
@@ -35091,6 +35422,8 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
35091
35422
|
// v4 FSM transition snapshot history — the captured pre-transition
|
|
35092
35423
|
// evaluation table at each transition (null for v3 specs).
|
|
35093
35424
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
35425
|
+
// PTY input/output/resize/cursor event timeline (debug-only).
|
|
35426
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
35094
35427
|
messages,
|
|
35095
35428
|
committedMessages: messages
|
|
35096
35429
|
};
|
|
@@ -35135,6 +35468,7 @@ function createCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFact
|
|
|
35135
35468
|
|
|
35136
35469
|
// src/providers/cli-provider-instance.ts
|
|
35137
35470
|
init_logger();
|
|
35471
|
+
init_mesh_event_trace();
|
|
35138
35472
|
init_control_effects();
|
|
35139
35473
|
init_approval_utils();
|
|
35140
35474
|
init_provider_patch_state();
|
|
@@ -36186,6 +36520,23 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36186
36520
|
if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
|
|
36187
36521
|
this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
|
|
36188
36522
|
}
|
|
36523
|
+
// EVTTRACE (observation-only): is this a mesh worker session whose completion
|
|
36524
|
+
// events must route to a coordinator? Used purely to gate trace logging so a
|
|
36525
|
+
// non-mesh CLI session's completions don't add EvtTrace noise. No decision logic.
|
|
36526
|
+
isMeshWorkerSession() {
|
|
36527
|
+
return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
|
|
36528
|
+
}
|
|
36529
|
+
// EVTTRACE correlation context for this session's completion lifecycle. taskId is
|
|
36530
|
+
// the primary grep anchor; instanceId is the session fallback.
|
|
36531
|
+
meshTraceCtx(event = "agent:generating_completed") {
|
|
36532
|
+
return {
|
|
36533
|
+
taskId: this.settings.meshActiveTaskId,
|
|
36534
|
+
sessionId: this.instanceId,
|
|
36535
|
+
nodeId: this.settings.meshNodeId,
|
|
36536
|
+
meshId: this.settings.meshNodeFor,
|
|
36537
|
+
event
|
|
36538
|
+
};
|
|
36539
|
+
}
|
|
36189
36540
|
flushCompletedDebounceIfFinalized() {
|
|
36190
36541
|
const pending = this.completedDebouncePending;
|
|
36191
36542
|
if (!pending) {
|
|
@@ -36206,24 +36557,33 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36206
36557
|
if (block2) {
|
|
36207
36558
|
const blockReason = block2.reason;
|
|
36208
36559
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
36209
|
-
|
|
36210
|
-
|
|
36560
|
+
const isTranscriptEvidenceGate = block2.allowTimeout === true;
|
|
36561
|
+
LOG.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} allowTimeout=${isTranscriptEvidenceGate} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
|
|
36562
|
+
if (!isTranscriptEvidenceGate && (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS)) {
|
|
36211
36563
|
if (pending.loggedBlockReason !== blockReason) {
|
|
36212
36564
|
LOG.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
|
|
36565
|
+
if (this.isMeshWorkerSession()) {
|
|
36566
|
+
traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `${blockReason} waited=${waitedMs}ms`);
|
|
36567
|
+
}
|
|
36213
36568
|
pending.loggedBlockReason = blockReason;
|
|
36214
36569
|
}
|
|
36215
36570
|
this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
|
|
36216
36571
|
return;
|
|
36217
36572
|
}
|
|
36573
|
+
const emittedAfterFinalizationTimeout = waitedMs >= COMPLETED_FINALIZATION_MAX_WAIT_MS;
|
|
36218
36574
|
const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
|
|
36219
36575
|
blockReason,
|
|
36220
36576
|
latestStatus,
|
|
36221
36577
|
latestVisibleStatus,
|
|
36222
36578
|
waitedMs,
|
|
36223
36579
|
pending,
|
|
36224
|
-
emittedAfterFinalizationTimeout
|
|
36580
|
+
emittedAfterFinalizationTimeout
|
|
36225
36581
|
});
|
|
36226
|
-
|
|
36582
|
+
completionDiagnostic.decoupledImmediateEmit = isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout;
|
|
36583
|
+
LOG.warn("CLI", `[${this.type}] emitting completed event (${isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`}) without finalized assistant turn (${blockReason})`);
|
|
36584
|
+
if (this.isMeshWorkerSession()) {
|
|
36585
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `forced after ${waitedMs}ms (${blockReason})`);
|
|
36586
|
+
}
|
|
36227
36587
|
this.pushEvent({
|
|
36228
36588
|
event: "agent:generating_completed",
|
|
36229
36589
|
chatTitle: pending.chatTitle,
|
|
@@ -36246,6 +36606,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36246
36606
|
return;
|
|
36247
36607
|
}
|
|
36248
36608
|
LOG.info("CLI", `[${this.type}] completed in ${pending.duration}s`);
|
|
36609
|
+
if (this.isMeshWorkerSession()) {
|
|
36610
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `duration=${pending.duration}s`);
|
|
36611
|
+
}
|
|
36249
36612
|
this.pushEvent({
|
|
36250
36613
|
event: "agent:generating_completed",
|
|
36251
36614
|
chatTitle: pending.chatTitle,
|
|
@@ -36484,6 +36847,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36484
36847
|
if (missingEvidence && !hasMeshContext) {
|
|
36485
36848
|
LOG.info("CLI", `[${this.type}] short completion suppressed: missing final assistant evidence, no mesh context (source=${shortEvidenceSource})`);
|
|
36486
36849
|
} else {
|
|
36850
|
+
if (this.isMeshWorkerSession()) {
|
|
36851
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `short-generating idle (source=${shortEvidenceSource})`);
|
|
36852
|
+
}
|
|
36487
36853
|
this.pushEvent({
|
|
36488
36854
|
event: "agent:generating_completed",
|
|
36489
36855
|
chatTitle,
|
|
@@ -36560,6 +36926,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36560
36926
|
const monitorParsedStatus = parsedStatus;
|
|
36561
36927
|
for (const me of monitorEvents) {
|
|
36562
36928
|
if (me.type === "monitor:no_progress" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
|
|
36929
|
+
if (this.isMeshWorkerSession()) {
|
|
36930
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), "no_progress_monitor_final_summary");
|
|
36931
|
+
}
|
|
36563
36932
|
this.pushEvent({
|
|
36564
36933
|
event: "agent:generating_completed",
|
|
36565
36934
|
chatTitle,
|
|
@@ -40428,7 +40797,7 @@ function parsePbFile(filePath, sessionId) {
|
|
|
40428
40797
|
}
|
|
40429
40798
|
if (buf.length === 0) return null;
|
|
40430
40799
|
const strings = extractStringsFromBuffer(buf);
|
|
40431
|
-
const meaningful = strings.filter((
|
|
40800
|
+
const meaningful = strings.filter((s2) => s2.length >= MIN_PRINTABLE_RUN && /\w/.test(s2));
|
|
40432
40801
|
if (meaningful.length === 0) return null;
|
|
40433
40802
|
const content = meaningful.join("\n");
|
|
40434
40803
|
const sourceMtimeMs = statMtimeMs3(filePath);
|
|
@@ -40636,10 +41005,10 @@ function readSession4(sessionPath) {
|
|
|
40636
41005
|
};
|
|
40637
41006
|
}
|
|
40638
41007
|
function normalizeHermesRole(r) {
|
|
40639
|
-
const
|
|
40640
|
-
if (
|
|
40641
|
-
if (
|
|
40642
|
-
if (
|
|
41008
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
41009
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
41010
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
41011
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
40643
41012
|
return "system";
|
|
40644
41013
|
}
|
|
40645
41014
|
|
|
@@ -40865,10 +41234,10 @@ function safeMtime(p) {
|
|
|
40865
41234
|
}
|
|
40866
41235
|
}
|
|
40867
41236
|
function normalizeRole2(r) {
|
|
40868
|
-
const
|
|
40869
|
-
if (
|
|
40870
|
-
if (
|
|
40871
|
-
if (
|
|
41237
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
41238
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
41239
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
41240
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
40872
41241
|
return "system";
|
|
40873
41242
|
}
|
|
40874
41243
|
|
|
@@ -40888,7 +41257,7 @@ function synthesizeControlsFromControlBar(specControls) {
|
|
|
40888
41257
|
const actionType = ctl?.action?.type;
|
|
40889
41258
|
if (!id || !actionType) return;
|
|
40890
41259
|
const label = typeof ctl?.label === "string" && ctl.label.trim() ? ctl.label : id;
|
|
40891
|
-
const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((
|
|
41260
|
+
const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s2) => typeof s2 === "string") : void 0;
|
|
40892
41261
|
if (actionType === "open_picker") {
|
|
40893
41262
|
out.push({
|
|
40894
41263
|
id,
|
|
@@ -47804,7 +48173,7 @@ var DaemonCommandRouter = class {
|
|
|
47804
48173
|
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.";
|
|
47805
48174
|
if (!firstFailedCmd) return base;
|
|
47806
48175
|
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 : "";
|
|
47807
|
-
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((
|
|
48176
|
+
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s2) => typeof s2 === "string" && s2.length > 0).join("\n");
|
|
47808
48177
|
const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
|
|
47809
48178
|
return [
|
|
47810
48179
|
base,
|
|
@@ -48555,7 +48924,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
48555
48924
|
convergence = "blocked_review";
|
|
48556
48925
|
}
|
|
48557
48926
|
const fbcs = result.finalBranchConvergenceState && typeof result.finalBranchConvergenceState === "object" ? result.finalBranchConvergenceState : void 0;
|
|
48558
|
-
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((
|
|
48927
|
+
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s2) => s2.status === "failed").map((s2) => s2.stage).filter(Boolean).pop() : void 0;
|
|
48559
48928
|
results.push({
|
|
48560
48929
|
nodeId: node.id,
|
|
48561
48930
|
workspace: node.workspace,
|
|
@@ -49552,7 +49921,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
49552
49921
|
return {
|
|
49553
49922
|
success: true,
|
|
49554
49923
|
screenLineCount: lines.length,
|
|
49555
|
-
sections: resolved.map((
|
|
49924
|
+
sections: resolved.map((s2) => ({ id: s2.id, fromLine: s2.fromLine, toLine: s2.toLine, text: s2.text }))
|
|
49556
49925
|
};
|
|
49557
49926
|
} catch (e) {
|
|
49558
49927
|
return { success: false, error: `resolve failed: ${e.message}` };
|
|
@@ -50121,7 +50490,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50121
50490
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
50122
50491
|
try {
|
|
50123
50492
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2, describeTaskDependencyState: describeTaskDependencyState2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
50124
|
-
const status = Array.isArray(args?.status) ? args.status.map((
|
|
50493
|
+
const status = Array.isArray(args?.status) ? args.status.map((s2) => typeof s2 === "string" ? s2.trim() : "").filter(Boolean) : void 0;
|
|
50125
50494
|
const rawQueue = getQueue2(meshId, { status });
|
|
50126
50495
|
const statusById = new Map(getQueue2(meshId).map((task) => [task.id, task.status]));
|
|
50127
50496
|
const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById) } : task);
|
|
@@ -50402,7 +50771,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50402
50771
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
50403
50772
|
}
|
|
50404
50773
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
50405
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
50774
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
50406
50775
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50407
50776
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
|
|
50408
50777
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -50436,7 +50805,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50436
50805
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
50437
50806
|
}
|
|
50438
50807
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
50439
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
50808
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
50440
50809
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50441
50810
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
|
|
50442
50811
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -50484,7 +50853,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50484
50853
|
const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
50485
50854
|
const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
|
|
50486
50855
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
50487
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
50856
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
50488
50857
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50489
50858
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
50490
50859
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
|
|
@@ -50571,7 +50940,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50571
50940
|
let worktreeCleanup;
|
|
50572
50941
|
if (node?.isLocalWorktree) {
|
|
50573
50942
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
50574
|
-
const isRemoteWorktree = nodeDaemonId && nodeDaemonId
|
|
50943
|
+
const isRemoteWorktree = nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
|
|
50575
50944
|
if (isRemoteWorktree) {
|
|
50576
50945
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "remove_mesh_node", {
|
|
50577
50946
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -50653,7 +51022,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50653
51022
|
const sourceNode = mesh.nodes?.find((n) => meshNodeIdMatches(n, sourceNodeId));
|
|
50654
51023
|
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
50655
51024
|
const sourceDaemonId = typeof sourceNode.daemonId === "string" ? sourceNode.daemonId.trim() : void 0;
|
|
50656
|
-
if (sourceDaemonId && sourceDaemonId
|
|
51025
|
+
if (sourceDaemonId && !daemonIdsEquivalent(sourceDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50657
51026
|
const forwarded = await this.deps.dispatchMeshCommand(sourceDaemonId, "clone_mesh_node", {
|
|
50658
51027
|
...typeof args === "object" && args !== null ? args : {},
|
|
50659
51028
|
_meshDirectDispatch: true
|
|
@@ -50895,7 +51264,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
50895
51264
|
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
50896
51265
|
if (!node.isLocalWorktree) return { success: false, error: "Node is not a local worktree node" };
|
|
50897
51266
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
50898
|
-
if (nodeDaemonId && nodeDaemonId
|
|
51267
|
+
if (nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
50899
51268
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "retry_mesh_node_bootstrap", {
|
|
50900
51269
|
...typeof args === "object" && args !== null ? args : {},
|
|
50901
51270
|
_meshDirectDispatch: true
|
|
@@ -52105,16 +52474,16 @@ var DaemonStatusReporter = class {
|
|
|
52105
52474
|
const now = this.lastStatusSentAt;
|
|
52106
52475
|
const target = opts?.p2pOnly ? "P2P" : serverConnected ? "P2P+Server" : "P2P";
|
|
52107
52476
|
const allStates = this.deps.instanceManager.collectAllStates();
|
|
52108
|
-
const ideStates = allStates.filter((
|
|
52109
|
-
const cliStates = allStates.filter((
|
|
52110
|
-
const acpStates = allStates.filter((
|
|
52111
|
-
const ideSummary = ideStates.map((
|
|
52112
|
-
const msgs =
|
|
52113
|
-
const exts =
|
|
52114
|
-
return `${
|
|
52477
|
+
const ideStates = allStates.filter((s2) => s2.category === "ide");
|
|
52478
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli");
|
|
52479
|
+
const acpStates = allStates.filter((s2) => s2.category === "acp");
|
|
52480
|
+
const ideSummary = ideStates.map((s2) => {
|
|
52481
|
+
const msgs = s2.activeChat?.messages?.length || 0;
|
|
52482
|
+
const exts = s2.extensions.length;
|
|
52483
|
+
return `${s2.type}(${s2.status},${msgs}msg,${exts}ext)`;
|
|
52115
52484
|
}).join(", ");
|
|
52116
|
-
const cliSummary = cliStates.map((
|
|
52117
|
-
const acpSummary = acpStates.map((
|
|
52485
|
+
const cliSummary = cliStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
52486
|
+
const acpSummary = acpStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
52118
52487
|
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
52119
52488
|
const baseSummary = `IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
|
|
52120
52489
|
const summaryChanged = baseSummary !== this.lastStatusSummary;
|
|
@@ -52225,10 +52594,10 @@ var DaemonStatusReporter = class {
|
|
|
52225
52594
|
}
|
|
52226
52595
|
return false;
|
|
52227
52596
|
}
|
|
52228
|
-
simpleHash(
|
|
52597
|
+
simpleHash(s2) {
|
|
52229
52598
|
let h = 2166136261;
|
|
52230
|
-
for (let i = 0; i <
|
|
52231
|
-
h ^=
|
|
52599
|
+
for (let i = 0; i < s2.length; i++) {
|
|
52600
|
+
h ^= s2.charCodeAt(i);
|
|
52232
52601
|
h = h * 16777619 >>> 0;
|
|
52233
52602
|
}
|
|
52234
52603
|
return h.toString(36);
|
|
@@ -53454,7 +53823,7 @@ var ProviderInstanceManager = class {
|
|
|
53454
53823
|
* Per-category status collect
|
|
53455
53824
|
*/
|
|
53456
53825
|
collectStatesByCategory(category) {
|
|
53457
|
-
return this.collectAllStates().filter((
|
|
53826
|
+
return this.collectAllStates().filter((s2) => s2.category === category);
|
|
53458
53827
|
}
|
|
53459
53828
|
// ─── Tick engine ─────────────────────────────────
|
|
53460
53829
|
/**
|
|
@@ -55354,9 +55723,9 @@ function getCliProviderResolutionMeta(ctx, type, adapter) {
|
|
|
55354
55723
|
function findCliTarget(ctx, type, instanceId) {
|
|
55355
55724
|
if (!ctx.instanceManager) return null;
|
|
55356
55725
|
const cliStates = ctx.instanceManager.collectAllStates().filter(isCliTargetState);
|
|
55357
|
-
if (instanceId) return cliStates.find((
|
|
55726
|
+
if (instanceId) return cliStates.find((s2) => s2.instanceId === instanceId) || null;
|
|
55358
55727
|
if (!type) return cliStates[cliStates.length - 1] || null;
|
|
55359
|
-
const matches = cliStates.filter((
|
|
55728
|
+
const matches = cliStates.filter((s2) => s2.type === type);
|
|
55360
55729
|
return matches[matches.length - 1] || null;
|
|
55361
55730
|
}
|
|
55362
55731
|
function getCliTargetBundle(ctx, type, instanceId) {
|
|
@@ -55719,20 +56088,20 @@ async function handleCliStatus(ctx, _req, res) {
|
|
|
55719
56088
|
return;
|
|
55720
56089
|
}
|
|
55721
56090
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
55722
|
-
const cliStates = allStates.filter((
|
|
55723
|
-
const result = cliStates.map((
|
|
55724
|
-
instanceId:
|
|
55725
|
-
type:
|
|
55726
|
-
name:
|
|
55727
|
-
category:
|
|
55728
|
-
status:
|
|
55729
|
-
mode:
|
|
55730
|
-
workspace:
|
|
55731
|
-
messageCount:
|
|
55732
|
-
lastMessage:
|
|
55733
|
-
activeModal:
|
|
55734
|
-
pendingEvents:
|
|
55735
|
-
settings:
|
|
56091
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
56092
|
+
const result = cliStates.map((s2) => ({
|
|
56093
|
+
instanceId: s2.instanceId,
|
|
56094
|
+
type: s2.type,
|
|
56095
|
+
name: s2.name,
|
|
56096
|
+
category: s2.category,
|
|
56097
|
+
status: s2.status,
|
|
56098
|
+
mode: s2.mode,
|
|
56099
|
+
workspace: s2.workspace,
|
|
56100
|
+
messageCount: s2.activeChat?.messages?.length || 0,
|
|
56101
|
+
lastMessage: s2.activeChat?.messages?.slice(-1)[0] || null,
|
|
56102
|
+
activeModal: s2.activeChat?.activeModal || null,
|
|
56103
|
+
pendingEvents: s2.pendingEvents || [],
|
|
56104
|
+
settings: s2.settings
|
|
55736
56105
|
}));
|
|
55737
56106
|
ctx.json(res, 200, { instances: result, count: result.length });
|
|
55738
56107
|
}
|
|
@@ -55821,9 +56190,9 @@ function handleCliSSE(ctx, cliSSEClients, _req, res) {
|
|
|
55821
56190
|
}
|
|
55822
56191
|
if (ctx.instanceManager) {
|
|
55823
56192
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
55824
|
-
const cliStates = allStates.filter((
|
|
55825
|
-
for (const
|
|
55826
|
-
ctx.sendCliSSE({ event: "snapshot", providerType:
|
|
56193
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
56194
|
+
for (const s2 of cliStates) {
|
|
56195
|
+
ctx.sendCliSSE({ event: "snapshot", providerType: s2.type, status: s2.status, instanceId: s2.instanceId });
|
|
55827
56196
|
}
|
|
55828
56197
|
}
|
|
55829
56198
|
_req.on("close", () => {
|
|
@@ -55839,7 +56208,7 @@ async function handleCliDebug(ctx, type, _req, res) {
|
|
|
55839
56208
|
const target = findCliTarget(ctx, type);
|
|
55840
56209
|
if (!target) {
|
|
55841
56210
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
55842
|
-
ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((
|
|
56211
|
+
ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type) });
|
|
55843
56212
|
return;
|
|
55844
56213
|
}
|
|
55845
56214
|
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
@@ -55885,7 +56254,7 @@ async function handleCliTrace(ctx, type, req, res) {
|
|
|
55885
56254
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
55886
56255
|
ctx.json(res, 404, {
|
|
55887
56256
|
error: `No running instance for: ${type}`,
|
|
55888
|
-
available: allStates.filter((
|
|
56257
|
+
available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type)
|
|
55889
56258
|
});
|
|
55890
56259
|
return;
|
|
55891
56260
|
}
|
|
@@ -56690,7 +57059,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
56690
57059
|
child.write("\x1B[12;1R");
|
|
56691
57060
|
ctx.log("Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]");
|
|
56692
57061
|
}
|
|
56693
|
-
checkAutoApproval(data, (
|
|
57062
|
+
checkAutoApproval(data, (s2) => child.write(s2));
|
|
56694
57063
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
56695
57064
|
scheduleAutoStopForVerification();
|
|
56696
57065
|
});
|
|
@@ -56703,7 +57072,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
56703
57072
|
stdout += chunk;
|
|
56704
57073
|
clearAutoStopTimer();
|
|
56705
57074
|
if (chunk.includes("\x1B[6n")) child.stdin?.write("\x1B[1;1R");
|
|
56706
|
-
checkAutoApproval(chunk, (
|
|
57075
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
56707
57076
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stdout" } });
|
|
56708
57077
|
scheduleAutoStopForVerification();
|
|
56709
57078
|
});
|
|
@@ -56711,7 +57080,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
56711
57080
|
const chunk = d.toString();
|
|
56712
57081
|
stderr += chunk;
|
|
56713
57082
|
clearAutoStopTimer();
|
|
56714
|
-
checkAutoApproval(chunk, (
|
|
57083
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
56715
57084
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
56716
57085
|
scheduleAutoStopForVerification();
|
|
56717
57086
|
});
|
|
@@ -57526,59 +57895,59 @@ var DevServer = class _DevServer {
|
|
|
57526
57895
|
// ─── Route Table ─────────────────────────────────────
|
|
57527
57896
|
routes = [
|
|
57528
57897
|
// Static routes
|
|
57529
|
-
{ method: "GET", pattern: "/api/providers", handler: (q,
|
|
57530
|
-
{ method: "GET", pattern: "/api/providers/source-config", handler: (q,
|
|
57531
|
-
{ method: "POST", pattern: "/api/providers/source-config", handler: (q,
|
|
57532
|
-
{ method: "GET", pattern: "/api/providers/versions", handler: (q,
|
|
57533
|
-
{ method: "POST", pattern: "/api/providers/reload", handler: (q,
|
|
57534
|
-
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q,
|
|
57535
|
-
{ method: "POST", pattern: "/api/cdp/click", handler: (q,
|
|
57536
|
-
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q,
|
|
57537
|
-
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q,
|
|
57538
|
-
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q,
|
|
57539
|
-
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q,
|
|
57540
|
-
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q,
|
|
57541
|
-
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q,
|
|
57542
|
-
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q,
|
|
57543
|
-
{ method: "GET", pattern: "/api/cdp/targets", handler: (q,
|
|
57544
|
-
{ method: "POST", pattern: "/api/scripts/run", handler: (q,
|
|
57545
|
-
{ method: "GET", pattern: "/api/status", handler: (q,
|
|
57546
|
-
{ method: "POST", pattern: "/api/watch/start", handler: (q,
|
|
57547
|
-
{ method: "POST", pattern: "/api/watch/stop", handler: (q,
|
|
57548
|
-
{ method: "GET", pattern: "/api/watch/events", handler: (q,
|
|
57549
|
-
{ method: "POST", pattern: "/api/scaffold", handler: (q,
|
|
57898
|
+
{ method: "GET", pattern: "/api/providers", handler: (q, s2) => this.handleListProviders(q, s2) },
|
|
57899
|
+
{ method: "GET", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleGetProviderSourceConfig(q, s2) },
|
|
57900
|
+
{ method: "POST", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleSetProviderSourceConfig(q, s2) },
|
|
57901
|
+
{ method: "GET", pattern: "/api/providers/versions", handler: (q, s2) => this.handleDetectVersions(q, s2) },
|
|
57902
|
+
{ method: "POST", pattern: "/api/providers/reload", handler: (q, s2) => this.handleReload(q, s2) },
|
|
57903
|
+
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s2) => this.handleCdpEvaluate(q, s2) },
|
|
57904
|
+
{ method: "POST", pattern: "/api/cdp/click", handler: (q, s2) => this.handleCdpClick(q, s2) },
|
|
57905
|
+
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s2) => this.handleCdpDomQuery(q, s2) },
|
|
57906
|
+
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s2) => this.handleDomInspect(q, s2) },
|
|
57907
|
+
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s2) => this.handleDomChildren(q, s2) },
|
|
57908
|
+
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s2) => this.handleDomAnalyze(q, s2) },
|
|
57909
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s2) => this.handleFindByText(q, s2) },
|
|
57910
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s2) => this.handleFindCommon(q, s2) },
|
|
57911
|
+
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s2) => this.handleScreenshot(q, s2) },
|
|
57912
|
+
{ method: "GET", pattern: "/api/cdp/targets", handler: (q, s2) => this.handleCdpTargets(q, s2) },
|
|
57913
|
+
{ method: "POST", pattern: "/api/scripts/run", handler: (q, s2) => this.handleScriptsRun(q, s2) },
|
|
57914
|
+
{ method: "GET", pattern: "/api/status", handler: (q, s2) => this.handleStatus(q, s2) },
|
|
57915
|
+
{ method: "POST", pattern: "/api/watch/start", handler: (q, s2) => this.handleWatchStart(q, s2) },
|
|
57916
|
+
{ method: "POST", pattern: "/api/watch/stop", handler: (q, s2) => this.handleWatchStop(q, s2) },
|
|
57917
|
+
{ method: "GET", pattern: "/api/watch/events", handler: (q, s2) => this.handleSSE(q, s2) },
|
|
57918
|
+
{ method: "POST", pattern: "/api/scaffold", handler: (q, s2) => this.handleScaffold(q, s2) },
|
|
57550
57919
|
// CLI Debug routes
|
|
57551
|
-
{ method: "GET", pattern: "/api/cli/status", handler: (q,
|
|
57552
|
-
{ method: "POST", pattern: "/api/cli/launch", handler: (q,
|
|
57553
|
-
{ method: "POST", pattern: "/api/cli/send", handler: (q,
|
|
57554
|
-
{ method: "POST", pattern: "/api/cli/exercise", handler: (q,
|
|
57555
|
-
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q,
|
|
57556
|
-
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q,
|
|
57557
|
-
{ method: "POST", pattern: "/api/cli/resolve", handler: (q,
|
|
57558
|
-
{ method: "POST", pattern: "/api/cli/raw", handler: (q,
|
|
57559
|
-
{ method: "POST", pattern: "/api/cli/stop", handler: (q,
|
|
57560
|
-
{ method: "GET", pattern: "/api/cli/events", handler: (q,
|
|
57561
|
-
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q,
|
|
57562
|
-
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q,
|
|
57563
|
-
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q,
|
|
57920
|
+
{ method: "GET", pattern: "/api/cli/status", handler: (q, s2) => this.handleCliStatus(q, s2) },
|
|
57921
|
+
{ method: "POST", pattern: "/api/cli/launch", handler: (q, s2) => this.handleCliLaunch(q, s2) },
|
|
57922
|
+
{ method: "POST", pattern: "/api/cli/send", handler: (q, s2) => this.handleCliSend(q, s2) },
|
|
57923
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q, s2) => this.handleCliExercise(q, s2) },
|
|
57924
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s2) => this.handleCliFixtureCapture(q, s2) },
|
|
57925
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s2) => this.handleCliFixtureReplay(q, s2) },
|
|
57926
|
+
{ method: "POST", pattern: "/api/cli/resolve", handler: (q, s2) => this.handleCliResolve(q, s2) },
|
|
57927
|
+
{ method: "POST", pattern: "/api/cli/raw", handler: (q, s2) => this.handleCliRaw(q, s2) },
|
|
57928
|
+
{ method: "POST", pattern: "/api/cli/stop", handler: (q, s2) => this.handleCliStop(q, s2) },
|
|
57929
|
+
{ method: "GET", pattern: "/api/cli/events", handler: (q, s2) => this.handleCliSSE(q, s2) },
|
|
57930
|
+
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s2, p) => this.handleCliDebug(p[0], q, s2) },
|
|
57931
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s2, p) => this.handleCliTrace(p[0], q, s2) },
|
|
57932
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s2, p) => this.handleCliFixtureList(p[0], q, s2) },
|
|
57564
57933
|
// Dynamic routes (provider :type param)
|
|
57565
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q,
|
|
57566
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q,
|
|
57567
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q,
|
|
57568
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q,
|
|
57569
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q,
|
|
57570
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q,
|
|
57571
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q,
|
|
57572
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q,
|
|
57573
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q,
|
|
57574
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q,
|
|
57575
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q,
|
|
57576
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q,
|
|
57577
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q,
|
|
57578
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q,
|
|
57579
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q,
|
|
57580
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q,
|
|
57581
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q,
|
|
57934
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s2, p) => this.handleRunScript(p[0], q, s2) },
|
|
57935
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s2, p) => this.handleListFiles(p[0], q, s2) },
|
|
57936
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleReadFile(p[0], q, s2) },
|
|
57937
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleWriteFile(p[0], q, s2) },
|
|
57938
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s2, p) => this.handleSource(p[0], q, s2) },
|
|
57939
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s2, p) => this.handleSave(p[0], q, s2) },
|
|
57940
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s2, p) => this.handleTypeAndSend(p[0], q, s2) },
|
|
57941
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s2, p) => this.handleTypeAndSendAt(p[0], q, s2) },
|
|
57942
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s2, p) => this.handleProviderConfig(p[0], q, s2) },
|
|
57943
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s2, p) => this.handleDomContext(p[0], q, s2) },
|
|
57944
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s2, p) => this.handleAutoImplement(p[0], q, s2) },
|
|
57945
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s2, p) => this.handleAutoImplCancel(p[0], q, s2) },
|
|
57946
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s2, p) => this.handleAutoImplSSE(p[0], q, s2) },
|
|
57947
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s2, p) => this.handleSpawnTest(p[0], q, s2) },
|
|
57948
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s2, p) => this.handleValidate(p[0], q, s2) },
|
|
57949
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s2, p) => this.handleAcpChat(p[0], q, s2) },
|
|
57950
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s2, p) => this.handleScriptHints(p[0], q, s2) }
|
|
57582
57951
|
];
|
|
57583
57952
|
matchRoute(method, pathname) {
|
|
57584
57953
|
for (const route of this.routes) {
|
|
@@ -58173,14 +58542,14 @@ var DevServer = class _DevServer {
|
|
|
58173
58542
|
warnings.push(...validation.warnings);
|
|
58174
58543
|
if (config.settings) {
|
|
58175
58544
|
for (const [key, val] of Object.entries(config.settings)) {
|
|
58176
|
-
const
|
|
58177
|
-
if (!
|
|
58178
|
-
else if (!["boolean", "number", "string", "select"].includes(
|
|
58179
|
-
errors.push(`settings.${key}: invalid type '${
|
|
58180
|
-
if (
|
|
58181
|
-
if (
|
|
58182
|
-
errors.push(`settings.${key}: min (${
|
|
58183
|
-
if (
|
|
58545
|
+
const s2 = val;
|
|
58546
|
+
if (!s2.type) errors.push(`settings.${key}: missing type`);
|
|
58547
|
+
else if (!["boolean", "number", "string", "select"].includes(s2.type))
|
|
58548
|
+
errors.push(`settings.${key}: invalid type '${s2.type}'`);
|
|
58549
|
+
if (s2.default === void 0) warnings.push(`settings.${key}: no default value`);
|
|
58550
|
+
if (s2.type === "number" && s2.min !== void 0 && s2.max !== void 0 && s2.min > s2.max)
|
|
58551
|
+
errors.push(`settings.${key}: min (${s2.min}) > max (${s2.max})`);
|
|
58552
|
+
if (s2.type === "select" && (!s2.options || !Array.isArray(s2.options) || s2.options.length === 0))
|
|
58184
58553
|
errors.push(`settings.${key}: select type requires options[]`);
|
|
58185
58554
|
}
|
|
58186
58555
|
}
|