@adhdev/daemon-standalone 0.9.82-rc.354 → 0.9.82-rc.356
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 +635 -208
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +36 -5
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/index.js
CHANGED
|
@@ -30036,10 +30036,10 @@ var require_dist3 = __commonJS({
|
|
|
30036
30036
|
}
|
|
30037
30037
|
function getDaemonBuildInfo() {
|
|
30038
30038
|
if (cached2) return cached2;
|
|
30039
|
-
const commit = readInjected(true ? "
|
|
30040
|
-
const commitShort = readInjected(true ? "
|
|
30041
|
-
const version2 = readInjected(true ? "0.9.82-rc.
|
|
30042
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
30039
|
+
const commit = readInjected(true ? "91500e054cf2b6258f6041f90c18be03ad05a8ad" : void 0) ?? "unknown";
|
|
30040
|
+
const commitShort = readInjected(true ? "91500e05" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30041
|
+
const version2 = readInjected(true ? "0.9.82-rc.356" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30042
|
+
const builtAt = readInjected(true ? "2026-06-22T22:47:57.762Z" : void 0);
|
|
30043
30043
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30044
30044
|
return cached2;
|
|
30045
30045
|
}
|
|
@@ -34593,9 +34593,12 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
34593
34593
|
return [];
|
|
34594
34594
|
}
|
|
34595
34595
|
}
|
|
34596
|
-
function updateDirectDispatchStatus(meshId, sessionId, status) {
|
|
34596
|
+
function updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
|
|
34597
34597
|
try {
|
|
34598
|
-
|
|
34598
|
+
if (!taskId) {
|
|
34599
|
+
LOG2.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)`);
|
|
34600
|
+
}
|
|
34601
|
+
MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status, taskId);
|
|
34599
34602
|
} catch {
|
|
34600
34603
|
}
|
|
34601
34604
|
}
|
|
@@ -35440,9 +35443,25 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
35440
35443
|
updatedAt: r.updated_at
|
|
35441
35444
|
}));
|
|
35442
35445
|
}
|
|
35443
|
-
|
|
35444
|
-
|
|
35446
|
+
// CANON-B (dispatch identity): mesh_direct_dispatches is keyed by task_id (PK), but a
|
|
35447
|
+
// single session can host several sequential direct dispatches (re-dispatch / nudge), so
|
|
35448
|
+
// matching a status flip by session_id alone hits EVERY non-terminal row for that session
|
|
35449
|
+
// — flipping a sibling task's row and stranding the one whose event actually fired (the
|
|
35450
|
+
// assigned-stranded watchdog then requeues a task that is really still generating). When
|
|
35451
|
+
// the firing event carries a taskId, target the single PK row; the session_id match is the
|
|
35452
|
+
// legacy fallback only for events that arrive without a taskId.
|
|
35453
|
+
updateDirectDispatchStatus(meshId, sessionId, status, taskId) {
|
|
35445
35454
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
35455
|
+
if (taskId) {
|
|
35456
|
+
this.db.prepare(`
|
|
35457
|
+
UPDATE mesh_direct_dispatches
|
|
35458
|
+
SET status = @status, updated_at = @updatedAt
|
|
35459
|
+
WHERE mesh_id = @meshId AND task_id = @taskId
|
|
35460
|
+
AND status NOT IN ('completed', 'failed')
|
|
35461
|
+
`).run({ status, meshId, taskId, updatedAt: now });
|
|
35462
|
+
return;
|
|
35463
|
+
}
|
|
35464
|
+
if (!sessionId) return;
|
|
35446
35465
|
this.db.prepare(`
|
|
35447
35466
|
UPDATE mesh_direct_dispatches
|
|
35448
35467
|
SET status = @status, updated_at = @updatedAt
|
|
@@ -37169,7 +37188,7 @@ ${rendered}`, "utf-8");
|
|
|
37169
37188
|
windowsHide: true
|
|
37170
37189
|
}).trim();
|
|
37171
37190
|
if (out) {
|
|
37172
|
-
const matches = out.split(/\r?\n/).map((
|
|
37191
|
+
const matches = out.split(/\r?\n/).map((s2) => s2.trim()).filter(Boolean);
|
|
37173
37192
|
const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
|
|
37174
37193
|
return direct || matches[0] || command;
|
|
37175
37194
|
}
|
|
@@ -38521,11 +38540,29 @@ Next step: ${nextStep}`;
|
|
|
38521
38540
|
(pending) => pending.event === event.event && readRefineJobId2(pending) === jobId
|
|
38522
38541
|
);
|
|
38523
38542
|
}
|
|
38543
|
+
function isWeakCompletionMetadata(metadata) {
|
|
38544
|
+
const evidenceLevel = readNonEmptyString2(metadata.evidenceLevel);
|
|
38545
|
+
if (evidenceLevel === "insufficient" || evidenceLevel === "weak") return true;
|
|
38546
|
+
if (metadata.reviewRecommended === true) return true;
|
|
38547
|
+
const diag = readRecord4(metadata.completionDiagnostic);
|
|
38548
|
+
return diag?.finalAssistantPresent === false || diag?.blockReason === "missing_final_assistant";
|
|
38549
|
+
}
|
|
38524
38550
|
function buildPendingEventFingerprint(event) {
|
|
38525
38551
|
const metadata = readRecord4(event.metadataEvent) || {};
|
|
38526
38552
|
if (event.event === "worktree_bootstrap_complete" || event.event === "worktree_bootstrap_failed") {
|
|
38527
38553
|
return [event.meshId, event.event, event.nodeId || ""].join("::");
|
|
38528
38554
|
}
|
|
38555
|
+
if (TERMINAL_COMPLETION_EVENTS.has(event.event)) {
|
|
38556
|
+
const terminalTaskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
|
|
38557
|
+
if (terminalTaskId) {
|
|
38558
|
+
return [
|
|
38559
|
+
event.meshId,
|
|
38560
|
+
event.event,
|
|
38561
|
+
terminalTaskId,
|
|
38562
|
+
isWeakCompletionMetadata(metadata) ? "weak" : "genuine"
|
|
38563
|
+
].join("::");
|
|
38564
|
+
}
|
|
38565
|
+
}
|
|
38529
38566
|
const sessionId = resolveEventSessionId(metadata);
|
|
38530
38567
|
const providerSessionId = readNonEmptyString2(metadata.providerSessionId);
|
|
38531
38568
|
const taskId = readNonEmptyString2(metadata.taskId) || readNonEmptyString2(readRecord4(metadata.payload)?.taskId);
|
|
@@ -38888,6 +38925,7 @@ Next step: ${nextStep}`;
|
|
|
38888
38925
|
var import_path9;
|
|
38889
38926
|
var import_crypto7;
|
|
38890
38927
|
var REFINE_TERMINAL_EVENTS;
|
|
38928
|
+
var TERMINAL_COMPLETION_EVENTS;
|
|
38891
38929
|
var MAX_PENDING_EVENTS_BYTES;
|
|
38892
38930
|
var MAX_PENDING_EVENTS_KEEP;
|
|
38893
38931
|
var init_mesh_events_pending = __esm2({
|
|
@@ -38902,6 +38940,7 @@ Next step: ${nextStep}`;
|
|
|
38902
38940
|
init_mesh_events_utils();
|
|
38903
38941
|
init_dist();
|
|
38904
38942
|
REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
|
|
38943
|
+
TERMINAL_COMPLETION_EVENTS = /* @__PURE__ */ new Set(["agent:generating_completed", "agent:stopped"]);
|
|
38905
38944
|
MAX_PENDING_EVENTS_BYTES = 100 * 1024;
|
|
38906
38945
|
MAX_PENDING_EVENTS_KEEP = 50;
|
|
38907
38946
|
}
|
|
@@ -39230,7 +39269,7 @@ Next step: ${nextStep}`;
|
|
|
39230
39269
|
evidence
|
|
39231
39270
|
}
|
|
39232
39271
|
});
|
|
39233
|
-
updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
|
|
39272
|
+
updateDirectDispatchStatus(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed", args.taskId);
|
|
39234
39273
|
markSessionDeliveriesTerminal(args.meshId, args.sessionId, kind === "task_completed" ? "completed" : "failed");
|
|
39235
39274
|
setImmediate(() => cleanupTerminalDirectDispatches());
|
|
39236
39275
|
queuePendingMeshCoordinatorEvent({
|
|
@@ -39516,8 +39555,8 @@ Next step: ${nextStep}`;
|
|
|
39516
39555
|
if (x instanceof RegExp) return x;
|
|
39517
39556
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
39518
39557
|
try {
|
|
39519
|
-
const
|
|
39520
|
-
return new RegExp(
|
|
39558
|
+
const s2 = x;
|
|
39559
|
+
return new RegExp(s2.source, s2.flags || "");
|
|
39521
39560
|
} catch {
|
|
39522
39561
|
return null;
|
|
39523
39562
|
}
|
|
@@ -40091,6 +40130,36 @@ Next step: ${nextStep}`;
|
|
|
40091
40130
|
UNRESOLVED_FORWARD_MAX_AGE_MS = 30 * 60 * 1e3;
|
|
40092
40131
|
}
|
|
40093
40132
|
});
|
|
40133
|
+
function s(v) {
|
|
40134
|
+
return typeof v === "string" && v.trim() ? v.trim() : "";
|
|
40135
|
+
}
|
|
40136
|
+
function meshEventTraceKey(ctx) {
|
|
40137
|
+
const segs = [`task=${s(ctx.taskId) || "-"}`];
|
|
40138
|
+
const eventId = s(ctx.eventId);
|
|
40139
|
+
if (eventId) segs.push(`evt=${eventId}`);
|
|
40140
|
+
segs.push(`sess=${s(ctx.sessionId) || "-"}`);
|
|
40141
|
+
const nodeId = s(ctx.nodeId);
|
|
40142
|
+
if (nodeId) segs.push(`node=${nodeId}`);
|
|
40143
|
+
const meshId = s(ctx.meshId);
|
|
40144
|
+
if (meshId) segs.push(`mesh=${meshId}`);
|
|
40145
|
+
const event = s(ctx.event);
|
|
40146
|
+
if (event) segs.push(`event=${event}`);
|
|
40147
|
+
return segs.join(" ");
|
|
40148
|
+
}
|
|
40149
|
+
function traceMeshEventStage(stage, ctx, detail) {
|
|
40150
|
+
LOG2.info(CAT, `[stage:${stage}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
40151
|
+
}
|
|
40152
|
+
function traceMeshEventDrop(reason, ctx, detail) {
|
|
40153
|
+
LOG2.warn(CAT, `[drop:${reason}] ${meshEventTraceKey(ctx)}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
40154
|
+
}
|
|
40155
|
+
var CAT;
|
|
40156
|
+
var init_mesh_event_trace = __esm2({
|
|
40157
|
+
"src/mesh/mesh-event-trace.ts"() {
|
|
40158
|
+
"use strict";
|
|
40159
|
+
init_logger();
|
|
40160
|
+
CAT = "EvtTrace";
|
|
40161
|
+
}
|
|
40162
|
+
});
|
|
40094
40163
|
function isPlainObject22(value) {
|
|
40095
40164
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
40096
40165
|
}
|
|
@@ -41884,9 +41953,9 @@ ${cleanBody}`;
|
|
|
41884
41953
|
}
|
|
41885
41954
|
function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
41886
41955
|
const sessions = [];
|
|
41887
|
-
const ideStates = allStates.filter((
|
|
41888
|
-
const cliStates = allStates.filter((
|
|
41889
|
-
const acpStates = allStates.filter((
|
|
41956
|
+
const ideStates = allStates.filter((s2) => s2.category === "ide");
|
|
41957
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli");
|
|
41958
|
+
const acpStates = allStates.filter((s2) => s2.category === "acp");
|
|
41890
41959
|
for (const state of ideStates) {
|
|
41891
41960
|
sessions.push(buildWorkspaceSession(state, cdpManagers, options));
|
|
41892
41961
|
for (const ext of state.extensions) {
|
|
@@ -42370,6 +42439,15 @@ ${cleanBody}`;
|
|
|
42370
42439
|
meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
|
|
42371
42440
|
return mesh;
|
|
42372
42441
|
}
|
|
42442
|
+
function recoverMeshIdByNodeId(nodeId) {
|
|
42443
|
+
if (!nodeId) return "";
|
|
42444
|
+
for (const mesh of listMeshes()) {
|
|
42445
|
+
if (Array.isArray(mesh.nodes) && mesh.nodes.some((n) => meshNodeIdMatches(n, nodeId))) {
|
|
42446
|
+
return readNonEmptyString2(mesh.id);
|
|
42447
|
+
}
|
|
42448
|
+
}
|
|
42449
|
+
return "";
|
|
42450
|
+
}
|
|
42373
42451
|
function __resetIdleAutoFastForwardForTests() {
|
|
42374
42452
|
idleAutoFastForwardLastAttempt.clear();
|
|
42375
42453
|
}
|
|
@@ -43272,6 +43350,13 @@ ${cleanBody}`;
|
|
|
43272
43350
|
function injectMeshSystemMessage(components, args) {
|
|
43273
43351
|
const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
43274
43352
|
const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
43353
|
+
const traceCtx = {
|
|
43354
|
+
taskId: args.metadataEvent.taskId,
|
|
43355
|
+
sessionId: eventSessionId,
|
|
43356
|
+
nodeId: eventNodeId,
|
|
43357
|
+
meshId: args.meshId,
|
|
43358
|
+
event: args.event
|
|
43359
|
+
};
|
|
43275
43360
|
const sourceSession = args.sourceInstanceId ? components.instanceManager.getInstance(args.sourceInstanceId) : void 0;
|
|
43276
43361
|
const workerCoordinatorDaemonId = readNonEmptyString2(
|
|
43277
43362
|
sourceSession?.getState()?.settings?.meshCoordinatorDaemonId
|
|
@@ -43325,6 +43410,7 @@ ${cleanBody}`;
|
|
|
43325
43410
|
}
|
|
43326
43411
|
}
|
|
43327
43412
|
LOG2.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
|
|
43413
|
+
traceMeshEventDrop("intentional_cleanup_stop", traceCtx);
|
|
43328
43414
|
return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
|
|
43329
43415
|
}
|
|
43330
43416
|
if (args.event === "monitor:no_progress") {
|
|
@@ -43345,6 +43431,7 @@ ${cleanBody}`;
|
|
|
43345
43431
|
}
|
|
43346
43432
|
if (reconciledCompletion?.source === "no_progress_terminal_ledger_suppression") {
|
|
43347
43433
|
LOG2.info("MeshEvents", `Suppressed no-progress monitor because terminal ledger evidence already exists for session ${eventSessionId || "(unknown session)"}`);
|
|
43434
|
+
traceMeshEventDrop("no_progress_terminal_ledger_suppression", traceCtx, `terminalKind=${reconciledCompletion.terminalLedgerKind}`);
|
|
43348
43435
|
return {
|
|
43349
43436
|
success: true,
|
|
43350
43437
|
forwarded: 0,
|
|
@@ -43356,6 +43443,7 @@ ${cleanBody}`;
|
|
|
43356
43443
|
}
|
|
43357
43444
|
if (isDuplicateRefineTerminalEvent(args.meshId, args.event, args.metadataEvent)) {
|
|
43358
43445
|
LOG2.info("MeshEvents", `Suppressed duplicate ${args.event} for refine job ${readRefineJobId({ metadataEvent: args.metadataEvent })}`);
|
|
43446
|
+
traceMeshEventDrop("duplicate_refine_terminal", traceCtx);
|
|
43359
43447
|
return { success: true, forwarded: 0, suppressed: true, duplicateRefineTerminalEvent: true };
|
|
43360
43448
|
}
|
|
43361
43449
|
const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
|
|
@@ -43370,6 +43458,7 @@ ${cleanBody}`;
|
|
|
43370
43458
|
});
|
|
43371
43459
|
if (duplicateApproval) {
|
|
43372
43460
|
LOG2.info("MeshEvents", `Suppressed duplicate approval event for mesh ${args.meshId} session ${eventSessionId}`);
|
|
43461
|
+
traceMeshEventDrop("duplicate_approval", traceCtx);
|
|
43373
43462
|
return { success: true, forwarded: 0, suppressed: true, duplicateApproval: true };
|
|
43374
43463
|
}
|
|
43375
43464
|
}
|
|
@@ -43389,6 +43478,7 @@ ${cleanBody}`;
|
|
|
43389
43478
|
const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
|
|
43390
43479
|
if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "no_progress_reconciliation") {
|
|
43391
43480
|
LOG2.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
|
|
43481
|
+
traceMeshEventDrop("duplicate_completion_terminal_ledger", traceCtx);
|
|
43392
43482
|
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
|
|
43393
43483
|
}
|
|
43394
43484
|
}
|
|
@@ -43407,6 +43497,7 @@ ${cleanBody}`;
|
|
|
43407
43497
|
});
|
|
43408
43498
|
if (duplicateCompletion) {
|
|
43409
43499
|
LOG2.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
|
|
43500
|
+
traceMeshEventDrop("duplicate_completion", traceCtx);
|
|
43410
43501
|
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
|
|
43411
43502
|
}
|
|
43412
43503
|
}
|
|
@@ -43425,6 +43516,7 @@ ${cleanBody}`;
|
|
|
43425
43516
|
});
|
|
43426
43517
|
if (duplicateStopped) {
|
|
43427
43518
|
LOG2.info("MeshEvents", `Suppressed duplicate stopped event for mesh ${args.meshId} session ${eventSessionId}`);
|
|
43519
|
+
traceMeshEventDrop("duplicate_stopped", traceCtx);
|
|
43428
43520
|
return { success: true, forwarded: 0, suppressed: true, duplicateStopped: true };
|
|
43429
43521
|
}
|
|
43430
43522
|
}
|
|
@@ -43436,7 +43528,7 @@ ${cleanBody}`;
|
|
|
43436
43528
|
});
|
|
43437
43529
|
const leaveDirectDispatchActive = !task && opts?.tentativeIfDirect === true;
|
|
43438
43530
|
if (!leaveDirectDispatchActive) {
|
|
43439
|
-
updateDirectDispatchStatus(args.meshId, sessionId, outcome);
|
|
43531
|
+
updateDirectDispatchStatus(args.meshId, sessionId, outcome, eventTaskId);
|
|
43440
43532
|
}
|
|
43441
43533
|
markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
|
|
43442
43534
|
setImmediate(() => cleanupTerminalDirectDispatches());
|
|
@@ -43449,7 +43541,7 @@ ${cleanBody}`;
|
|
|
43449
43541
|
const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
43450
43542
|
const providerType = readNonEmptyString2(args.metadataEvent.providerType);
|
|
43451
43543
|
if (sessionId) {
|
|
43452
|
-
directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
43544
|
+
directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
43453
43545
|
const isFalseIdle = isFalseIdleCompletion(args.metadataEvent);
|
|
43454
43546
|
completedTaskForLedger = markSessionTerminal(sessionId, "completed", eventTimestamp, { tentativeIfDirect: isFalseIdle });
|
|
43455
43547
|
if (nodeId && providerType) {
|
|
@@ -43532,7 +43624,8 @@ ${cleanBody}`;
|
|
|
43532
43624
|
}
|
|
43533
43625
|
}
|
|
43534
43626
|
if (sessionId) {
|
|
43535
|
-
|
|
43627
|
+
const startedTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
|
|
43628
|
+
updateDirectDispatchStatus(args.meshId, sessionId, "acked", startedTaskId);
|
|
43536
43629
|
const activeDeliveries = (() => {
|
|
43537
43630
|
try {
|
|
43538
43631
|
return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(args.meshId, sessionId);
|
|
@@ -43540,7 +43633,8 @@ ${cleanBody}`;
|
|
|
43540
43633
|
return [];
|
|
43541
43634
|
}
|
|
43542
43635
|
})();
|
|
43543
|
-
|
|
43636
|
+
const deliveriesToAck = startedTaskId ? activeDeliveries.filter((d) => d.taskId === startedTaskId) : activeDeliveries;
|
|
43637
|
+
for (const d of deliveriesToAck) {
|
|
43544
43638
|
updateSessionDeliveryStatus(d.id, "acked");
|
|
43545
43639
|
}
|
|
43546
43640
|
}
|
|
@@ -43554,7 +43648,7 @@ ${cleanBody}`;
|
|
|
43554
43648
|
}
|
|
43555
43649
|
}
|
|
43556
43650
|
if (sessionId) {
|
|
43557
|
-
directDispatchTaskIdForLedger = resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
43651
|
+
directDispatchTaskIdForLedger = readNonEmptyString2(args.metadataEvent.taskId) || resolveActiveDirectDispatchTaskId(args.meshId, sessionId);
|
|
43558
43652
|
completedTaskForLedger = markSessionTerminal(sessionId, "failed");
|
|
43559
43653
|
}
|
|
43560
43654
|
}
|
|
@@ -43700,6 +43794,9 @@ ${cleanBody}`;
|
|
|
43700
43794
|
};
|
|
43701
43795
|
if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
|
|
43702
43796
|
LOG2.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ""})`);
|
|
43797
|
+
traceMeshEventStage("queued", traceCtx, workerCoordinatorDaemonId ? `coordinatorDaemon=${workerCoordinatorDaemonId}` : "broadcast");
|
|
43798
|
+
} else {
|
|
43799
|
+
traceMeshEventDrop("queue_dedup", traceCtx);
|
|
43703
43800
|
}
|
|
43704
43801
|
return { success: true, forwarded: 0 };
|
|
43705
43802
|
}
|
|
@@ -43710,8 +43807,23 @@ ${cleanBody}`;
|
|
|
43710
43807
|
}
|
|
43711
43808
|
const nodeId = readNonEmptyString2(payload.nodeId);
|
|
43712
43809
|
const workspace = readNonEmptyString2(payload.workspace);
|
|
43713
|
-
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "");
|
|
43714
|
-
if (!meshId)
|
|
43810
|
+
const meshId = readNonEmptyString2(payload.meshId) || (workspace ? readNonEmptyString2(getCachedMeshByWorkspace(workspace)?.id) : "") || recoverMeshIdByNodeId(nodeId);
|
|
43811
|
+
if (!meshId) {
|
|
43812
|
+
traceMeshEventDrop("meshId_required", {
|
|
43813
|
+
taskId: payload.taskId,
|
|
43814
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
43815
|
+
nodeId,
|
|
43816
|
+
event: eventName
|
|
43817
|
+
}, workspace ? `workspace=${workspace} unresolved` : "no workspace/nodeId");
|
|
43818
|
+
return { success: false, error: "meshId required" };
|
|
43819
|
+
}
|
|
43820
|
+
traceMeshEventStage("received", {
|
|
43821
|
+
taskId: payload.taskId,
|
|
43822
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
43823
|
+
nodeId,
|
|
43824
|
+
meshId,
|
|
43825
|
+
event: eventName
|
|
43826
|
+
});
|
|
43715
43827
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
43716
43828
|
const relayModalMessage = readNonEmptyString2(payload.modalMessage);
|
|
43717
43829
|
const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
|
|
@@ -43792,9 +43904,18 @@ ${cleanBody}`;
|
|
|
43792
43904
|
workspace: readNonEmptyString2(routing.workspace) || readNonEmptyString2(event.workspace) || void 0
|
|
43793
43905
|
};
|
|
43794
43906
|
const persisted = enqueueUnresolvedDelegateForward(coordinatorDaemonId, eventName, payload);
|
|
43907
|
+
const fwdTraceCtx = {
|
|
43908
|
+
taskId: payload.taskId,
|
|
43909
|
+
sessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId),
|
|
43910
|
+
nodeId: readNonEmptyString2(routing.nodeId) || readNonEmptyString2(event.meshNodeId),
|
|
43911
|
+
event: eventName
|
|
43912
|
+
};
|
|
43913
|
+
traceMeshEventStage("outbox_enqueue", fwdTraceCtx, `coordinatorDaemon=${coordinatorDaemonId} meshId=absent`);
|
|
43914
|
+
traceMeshEventStage("forward_send", fwdTraceCtx, "immediate push");
|
|
43795
43915
|
Promise.resolve(components.dispatchMeshCommand(coordinatorDaemonId, "mesh_forward_event", payload)).then((result) => {
|
|
43796
43916
|
if (result && result.success === false) {
|
|
43797
43917
|
LOG2.warn("MeshEvents", `Immediate forward of ${eventName} to coordinator ${coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued for retry`);
|
|
43918
|
+
traceMeshEventDrop("immediate_forward_rejected", fwdTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
43798
43919
|
return;
|
|
43799
43920
|
}
|
|
43800
43921
|
if (persisted) ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventName, payload);
|
|
@@ -43862,6 +43983,14 @@ ${cleanBody}`;
|
|
|
43862
43983
|
if (isUnroutableDelegateRejection(routing) && forwardUnresolvedDelegateEvent(components, routing, event)) {
|
|
43863
43984
|
return;
|
|
43864
43985
|
}
|
|
43986
|
+
if (isUnroutableDelegateRejection(routing)) {
|
|
43987
|
+
traceMeshEventDrop("unroutable", {
|
|
43988
|
+
taskId: event.meshActiveTaskId ?? event.taskId,
|
|
43989
|
+
sessionId: routing.sessionId,
|
|
43990
|
+
nodeId: routing.nodeId,
|
|
43991
|
+
event: event.event
|
|
43992
|
+
}, "no coordinator anchor / mesh_unresolved");
|
|
43993
|
+
}
|
|
43865
43994
|
recordUnroutableDelegateEvent(routing, event.event);
|
|
43866
43995
|
return;
|
|
43867
43996
|
}
|
|
@@ -43909,6 +44038,7 @@ ${cleanBody}`;
|
|
|
43909
44038
|
init_mesh_events_pending();
|
|
43910
44039
|
init_mesh_routing();
|
|
43911
44040
|
init_mesh_unresolved_forward_outbox();
|
|
44041
|
+
init_mesh_event_trace();
|
|
43912
44042
|
init_snapshot();
|
|
43913
44043
|
init_repo_mesh_types();
|
|
43914
44044
|
init_dist();
|
|
@@ -44018,6 +44148,13 @@ ${cleanBody}`;
|
|
|
44018
44148
|
function injectPendingIntoCoordinator(coordinator, pending) {
|
|
44019
44149
|
if (!coordinator || !pending.coordinatorMessage) return;
|
|
44020
44150
|
const force = shouldForceInjectMeshEvent(pending.event);
|
|
44151
|
+
traceMeshEventStage("surfaced", {
|
|
44152
|
+
taskId: pending.metadataEvent?.taskId,
|
|
44153
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? pending.targetCoordinatorSessionId,
|
|
44154
|
+
nodeId: pending.nodeId,
|
|
44155
|
+
meshId: pending.meshId,
|
|
44156
|
+
event: pending.event
|
|
44157
|
+
}, force ? "force-inject" : "inject");
|
|
44021
44158
|
coordinator.onEvent("send_message", {
|
|
44022
44159
|
input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
|
|
44023
44160
|
...force ? { force: true } : {}
|
|
@@ -44076,6 +44213,13 @@ ${cleanBody}`;
|
|
|
44076
44213
|
});
|
|
44077
44214
|
if (reclaimed) {
|
|
44078
44215
|
LOG2.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})`);
|
|
44216
|
+
traceMeshEventDrop("assigned_stranded_reclaim", {
|
|
44217
|
+
taskId: row.id,
|
|
44218
|
+
sessionId: row.assignedSessionId,
|
|
44219
|
+
nodeId: row.assignedNodeId,
|
|
44220
|
+
meshId,
|
|
44221
|
+
event: "agent:generating_completed"
|
|
44222
|
+
}, `unconfirmed ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s \u2192 ${reclaimed.status}`);
|
|
44079
44223
|
}
|
|
44080
44224
|
}
|
|
44081
44225
|
}
|
|
@@ -44235,6 +44379,13 @@ ${cleanBody}`;
|
|
|
44235
44379
|
try {
|
|
44236
44380
|
queuePendingMeshCoordinatorEvent(pending);
|
|
44237
44381
|
LOG2.info("MeshReconcile", `Strict route hold: coordinator session ${wantSession} not live on mesh ${meshId} \u2014 re-queued (${pending.event})`);
|
|
44382
|
+
traceMeshEventDrop("strict_route_hold", {
|
|
44383
|
+
taskId: pending.metadataEvent?.taskId,
|
|
44384
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
|
|
44385
|
+
nodeId: pending.nodeId,
|
|
44386
|
+
meshId,
|
|
44387
|
+
event: pending.event
|
|
44388
|
+
}, `coordinatorSession=${wantSession} not live`);
|
|
44238
44389
|
} catch (e) {
|
|
44239
44390
|
LOG2.warn("MeshReconcile", `Strict route re-queue failed for ${pending.event} on mesh ${meshId}: ${e?.message || e}`);
|
|
44240
44391
|
}
|
|
@@ -44258,6 +44409,13 @@ ${cleanBody}`;
|
|
|
44258
44409
|
}
|
|
44259
44410
|
});
|
|
44260
44411
|
LOG2.warn("MeshReconcile", `Strict route expire: coordinator session ${wantSession} never returned for mesh ${meshId} \u2014 recorded to ledger (recoverable), dropped (${pending.event})`);
|
|
44412
|
+
traceMeshEventDrop("strict_route_expired", {
|
|
44413
|
+
taskId: pending.metadataEvent?.taskId,
|
|
44414
|
+
sessionId: pending.metadataEvent?.targetSessionId ?? wantSession,
|
|
44415
|
+
nodeId: pending.nodeId,
|
|
44416
|
+
meshId,
|
|
44417
|
+
event: pending.event
|
|
44418
|
+
}, `coordinatorSession=${wantSession} never returned`);
|
|
44261
44419
|
} catch (e) {
|
|
44262
44420
|
LOG2.warn("MeshReconcile", `Failed to ledger-expire strict-unmatched ${pending.event} for mesh ${meshId}: ${e?.message || e}`);
|
|
44263
44421
|
}
|
|
@@ -44269,15 +44427,24 @@ ${cleanBody}`;
|
|
|
44269
44427
|
const entries = peekUnresolvedDelegateForwards();
|
|
44270
44428
|
if (entries.length === 0) return;
|
|
44271
44429
|
for (const entry of entries) {
|
|
44430
|
+
const entryTraceCtx = {
|
|
44431
|
+
taskId: entry.payload.taskId,
|
|
44432
|
+
sessionId: readNonEmptyString2(entry.payload.targetSessionId) || readNonEmptyString2(entry.payload.sessionId),
|
|
44433
|
+
nodeId: readNonEmptyString2(entry.payload.nodeId),
|
|
44434
|
+
event: readNonEmptyString2(entry.payload.event)
|
|
44435
|
+
};
|
|
44272
44436
|
let result;
|
|
44273
44437
|
try {
|
|
44438
|
+
traceMeshEventStage("forward_send", entryTraceCtx, `retry \u2192 ${entry.coordinatorDaemonId}`);
|
|
44274
44439
|
result = await dispatchMeshCommand(entry.coordinatorDaemonId, "mesh_forward_event", entry.payload);
|
|
44275
44440
|
} catch (e) {
|
|
44276
44441
|
LOG2.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} failed: ${e?.message || e} \u2014 left queued`);
|
|
44442
|
+
traceMeshEventDrop("retry_forward_failed", entryTraceCtx, e?.message || String(e));
|
|
44277
44443
|
continue;
|
|
44278
44444
|
}
|
|
44279
44445
|
if (result && result.success === false) {
|
|
44280
44446
|
LOG2.warn("MeshReconcile", `Retry forward to coordinator ${entry.coordinatorDaemonId} rejected (${readNonEmptyString2(result.error) || "no reason"}) \u2014 left queued`);
|
|
44447
|
+
traceMeshEventDrop("retry_forward_rejected", entryTraceCtx, readNonEmptyString2(result.error) || "no reason");
|
|
44281
44448
|
continue;
|
|
44282
44449
|
}
|
|
44283
44450
|
ackUnresolvedDelegateForward(entry.id);
|
|
@@ -44523,6 +44690,7 @@ ${cleanBody}`;
|
|
|
44523
44690
|
init_mesh_events_coordinator();
|
|
44524
44691
|
init_mesh_unresolved_forward_outbox();
|
|
44525
44692
|
init_mesh_events_utils();
|
|
44693
|
+
init_mesh_event_trace();
|
|
44526
44694
|
init_dist();
|
|
44527
44695
|
init_mesh_work_queue();
|
|
44528
44696
|
init_mesh_ledger();
|
|
@@ -45352,8 +45520,8 @@ ${cleanBody}`;
|
|
|
45352
45520
|
}
|
|
45353
45521
|
function isValidSource(x) {
|
|
45354
45522
|
if (!x || typeof x !== "object") return false;
|
|
45355
|
-
const
|
|
45356
|
-
return typeof
|
|
45523
|
+
const s2 = x;
|
|
45524
|
+
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";
|
|
45357
45525
|
}
|
|
45358
45526
|
function deriveSourceName(url2) {
|
|
45359
45527
|
const m = url2.match(/[/:]([^/:]+)\/([^/]+?)(?:\.git)?$/);
|
|
@@ -45409,7 +45577,7 @@ ${cleanBody}`;
|
|
|
45409
45577
|
}
|
|
45410
45578
|
function sourcesProviding(category, type) {
|
|
45411
45579
|
const inventory = inventoryExternalSources();
|
|
45412
|
-
return inventory.filter((
|
|
45580
|
+
return inventory.filter((s2) => (s2.providers[category] || []).includes(type)).map((s2) => s2.sourceName);
|
|
45413
45581
|
}
|
|
45414
45582
|
function resolveActiveSource(category, type, activeFile) {
|
|
45415
45583
|
const candidates = sourcesProviding(category, type);
|
|
@@ -45617,10 +45785,10 @@ ${cleanBody}`;
|
|
|
45617
45785
|
const footers = (spec.withFooter ?? []).map((f) => {
|
|
45618
45786
|
if (f.kind === "regex") {
|
|
45619
45787
|
const re = compile2(f.pattern, f.flags ?? "i");
|
|
45620
|
-
return { test: (
|
|
45788
|
+
return { test: (s2) => re.test(s2) };
|
|
45621
45789
|
}
|
|
45622
45790
|
const needle = f.pattern.toLowerCase();
|
|
45623
|
-
return { test: (
|
|
45791
|
+
return { test: (s2) => s2.toLowerCase().includes(needle) };
|
|
45624
45792
|
});
|
|
45625
45793
|
return { prompt, footers };
|
|
45626
45794
|
}
|
|
@@ -46495,7 +46663,7 @@ ${cont}` : cont;
|
|
|
46495
46663
|
}
|
|
46496
46664
|
resolveModal(buttonIndex) {
|
|
46497
46665
|
const snap = this.transport.getSnapshot();
|
|
46498
|
-
const parseApproval = typeof this.transport.runParseApproval === "function" ? (
|
|
46666
|
+
const parseApproval = typeof this.transport.runParseApproval === "function" ? (s2) => this.transport.runParseApproval(s2.recentOutputBuffer.slice(-500)) : (s2) => this.runParseApproval(s2);
|
|
46499
46667
|
let modal = this.activeModal ?? parseApproval(snap);
|
|
46500
46668
|
if (!modal && this.runner.hasParseSession()) {
|
|
46501
46669
|
try {
|
|
@@ -49181,22 +49349,23 @@ ${lastSnapshot}`;
|
|
|
49181
49349
|
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]));
|
|
49182
49350
|
let idx = -1;
|
|
49183
49351
|
for (const c of candidates) {
|
|
49352
|
+
let candIdx = -1;
|
|
49184
49353
|
if (sec.anchor_last) {
|
|
49185
49354
|
for (let i = total - 1; i >= 0; i--) {
|
|
49186
49355
|
if (matchesCandidate(c, i)) {
|
|
49187
|
-
|
|
49356
|
+
candIdx = i;
|
|
49188
49357
|
break;
|
|
49189
49358
|
}
|
|
49190
49359
|
}
|
|
49191
49360
|
} else {
|
|
49192
49361
|
for (let i = 0; i < total; i++) {
|
|
49193
49362
|
if (matchesCandidate(c, i)) {
|
|
49194
|
-
|
|
49363
|
+
candIdx = i;
|
|
49195
49364
|
break;
|
|
49196
49365
|
}
|
|
49197
49366
|
}
|
|
49198
49367
|
}
|
|
49199
|
-
if (
|
|
49368
|
+
if (candIdx !== -1 && (idx === -1 || candIdx < idx)) idx = candIdx;
|
|
49200
49369
|
}
|
|
49201
49370
|
if (idx !== -1) {
|
|
49202
49371
|
from = idx;
|
|
@@ -49248,7 +49417,7 @@ ${lastSnapshot}`;
|
|
|
49248
49417
|
}
|
|
49249
49418
|
function sectionText(sections, sectionId, fullScreen) {
|
|
49250
49419
|
if (!sectionId) return fullScreen;
|
|
49251
|
-
const found = sections.find((
|
|
49420
|
+
const found = sections.find((s2) => s2.id === sectionId);
|
|
49252
49421
|
return found ? found.text : "";
|
|
49253
49422
|
}
|
|
49254
49423
|
function isRegexCondition(c) {
|
|
@@ -49376,6 +49545,7 @@ ${lastSnapshot}`;
|
|
|
49376
49545
|
const idx = Number(m[1]);
|
|
49377
49546
|
let label = String(m[2] ?? "").trim();
|
|
49378
49547
|
if (!Number.isFinite(idx) || idx <= 0 || !label) continue;
|
|
49548
|
+
const current = hasCursorMarker(lines[i]);
|
|
49379
49549
|
let j = i + 1;
|
|
49380
49550
|
while (j < lines.length) {
|
|
49381
49551
|
const next = lines[j];
|
|
@@ -49387,7 +49557,7 @@ ${lastSnapshot}`;
|
|
|
49387
49557
|
}
|
|
49388
49558
|
if (buttons.some((b) => b.index === idx)) continue;
|
|
49389
49559
|
const key = keyTemplate.replace(/\{index\}/g, String(idx));
|
|
49390
|
-
buttons.push({ index: idx, label, key });
|
|
49560
|
+
buttons.push({ index: idx, label, key, current });
|
|
49391
49561
|
i = j - 1;
|
|
49392
49562
|
}
|
|
49393
49563
|
} else {
|
|
@@ -49399,12 +49569,15 @@ ${lastSnapshot}`;
|
|
|
49399
49569
|
if (!Number.isFinite(idx) || idx <= 0 || !label) continue;
|
|
49400
49570
|
if (buttons.some((b) => b.index === idx)) continue;
|
|
49401
49571
|
const key = keyTemplate.replace(/\{index\}/g, String(idx));
|
|
49402
|
-
buttons.push({ index: idx, label, key });
|
|
49572
|
+
buttons.push({ index: idx, label, key, current: hasCursorMarker(m[0]) });
|
|
49403
49573
|
}
|
|
49404
49574
|
}
|
|
49405
49575
|
buttons.sort((a, b) => a.index - b.index);
|
|
49406
49576
|
return buttons;
|
|
49407
49577
|
}
|
|
49578
|
+
function hasCursorMarker(text) {
|
|
49579
|
+
return /^\s*[❯›>]/.test(text);
|
|
49580
|
+
}
|
|
49408
49581
|
var init_evaluator = __esm2({
|
|
49409
49582
|
"src/providers/spec/evaluator.ts"() {
|
|
49410
49583
|
"use strict";
|
|
@@ -49414,10 +49587,10 @@ ${lastSnapshot}`;
|
|
|
49414
49587
|
return !!raw && typeof raw === "object" && raw.$schema === "adhdev:cli/spec@4";
|
|
49415
49588
|
}
|
|
49416
49589
|
function initialState(spec) {
|
|
49417
|
-
return spec.states.find((
|
|
49590
|
+
return spec.states.find((s2) => s2.initial) ?? spec.states[0];
|
|
49418
49591
|
}
|
|
49419
49592
|
function stateById(spec, id) {
|
|
49420
|
-
return spec.states.find((
|
|
49593
|
+
return spec.states.find((s2) => s2.id === id);
|
|
49421
49594
|
}
|
|
49422
49595
|
function outgoingTransitions(spec, stateId) {
|
|
49423
49596
|
const matches = spec.transitions.filter((t) => {
|
|
@@ -49504,7 +49677,17 @@ ${lastSnapshot}`;
|
|
|
49504
49677
|
const result = evaluateCondition(cond, sections, fullScreen, cursor, prevLines, legacyTrace, stateId);
|
|
49505
49678
|
const kind = isRegex(cond) ? "regex" : "changed";
|
|
49506
49679
|
const detail = isRegex(cond) ? `${cond.section ?? "*"}~/${cond.matches}/` : `cursor_above=${cond.cursor_above} changed=${cond.changed}`;
|
|
49507
|
-
|
|
49680
|
+
let matchedText;
|
|
49681
|
+
if (result && isRegex(cond)) {
|
|
49682
|
+
try {
|
|
49683
|
+
const hay = sectionText(sections, cond.section, fullScreen);
|
|
49684
|
+
const re = new RegExp(cond.matches, cond.flags ?? "i");
|
|
49685
|
+
const m = re.exec(hay);
|
|
49686
|
+
if (m && m[0]) matchedText = m[0].replace(/\s+/g, " ").trim().slice(0, 160);
|
|
49687
|
+
} catch {
|
|
49688
|
+
}
|
|
49689
|
+
}
|
|
49690
|
+
return matchedText ? { kind, result, detail, matchedText } : { kind, result, detail };
|
|
49508
49691
|
}
|
|
49509
49692
|
return { kind: "all", result: false, detail: "unknown condition" };
|
|
49510
49693
|
}
|
|
@@ -49617,17 +49800,17 @@ ${lastSnapshot}`;
|
|
|
49617
49800
|
}
|
|
49618
49801
|
const ids = /* @__PURE__ */ new Set();
|
|
49619
49802
|
let initialCount = 0;
|
|
49620
|
-
for (const [i,
|
|
49621
|
-
if (!
|
|
49803
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
49804
|
+
if (!s2.id) {
|
|
49622
49805
|
errs.push(`states[${i}].id is required`);
|
|
49623
49806
|
continue;
|
|
49624
49807
|
}
|
|
49625
|
-
if (ids.has(
|
|
49626
|
-
ids.add(
|
|
49627
|
-
if (!
|
|
49628
|
-
if (
|
|
49629
|
-
if (
|
|
49630
|
-
errs.push(`states[${i}].status "${
|
|
49808
|
+
if (ids.has(s2.id)) errs.push(`states[${i}].id "${s2.id}" is duplicated`);
|
|
49809
|
+
ids.add(s2.id);
|
|
49810
|
+
if (!s2.label) errs.push(`states[${i}].label is required`);
|
|
49811
|
+
if (s2.initial) initialCount += 1;
|
|
49812
|
+
if (s2.status && !["idle", "generating", "approval"].includes(s2.status)) {
|
|
49813
|
+
errs.push(`states[${i}].status "${s2.status}" must be idle|generating|approval`);
|
|
49631
49814
|
}
|
|
49632
49815
|
}
|
|
49633
49816
|
if (initialCount === 0) errs.push("exactly one state must have initial:true (none found)");
|
|
@@ -49643,10 +49826,10 @@ ${lastSnapshot}`;
|
|
|
49643
49826
|
else if (!ids.has(t.to)) errs.push(`transitions[${i}].to references unknown state "${t.to}"`);
|
|
49644
49827
|
if (t.when) errs.push(...validateCondition(t.when, sectionIds, `transitions[${i}].when`));
|
|
49645
49828
|
}
|
|
49646
|
-
for (const [i,
|
|
49647
|
-
const sec =
|
|
49829
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
49830
|
+
const sec = s2.extract?.title?.section;
|
|
49648
49831
|
if (sec && !sectionIds.has(sec)) errs.push(`states[${i}].extract.title.section "${sec}" unknown`);
|
|
49649
|
-
const bsec =
|
|
49832
|
+
const bsec = s2.extract?.buttons?.section;
|
|
49650
49833
|
if (bsec && !sectionIds.has(bsec)) errs.push(`states[${i}].extract.buttons.section "${bsec}" unknown`);
|
|
49651
49834
|
}
|
|
49652
49835
|
return errs;
|
|
@@ -62273,10 +62456,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62273
62456
|
const path422 = require("path");
|
|
62274
62457
|
const { spawnSync: spawnSync2 } = require("child_process");
|
|
62275
62458
|
const file2 = ext.loadExternalSources();
|
|
62276
|
-
if (file2.sources.some((
|
|
62459
|
+
if (file2.sources.some((s2) => s2.name === requestedName)) {
|
|
62277
62460
|
return { success: false, error: `source name "${requestedName}" is already registered` };
|
|
62278
62461
|
}
|
|
62279
|
-
if (file2.sources.some((
|
|
62462
|
+
if (file2.sources.some((s2) => s2.url === url2 && s2.ref === ref)) {
|
|
62280
62463
|
return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
|
|
62281
62464
|
}
|
|
62282
62465
|
const sourceDir = path422.join(ext.externalRoot(), requestedName);
|
|
@@ -62338,7 +62521,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62338
62521
|
const fs322 = require("fs");
|
|
62339
62522
|
const path422 = require("path");
|
|
62340
62523
|
const file2 = ext.loadExternalSources();
|
|
62341
|
-
const match = file2.sources.find((
|
|
62524
|
+
const match = file2.sources.find((s2) => s2.name === name);
|
|
62342
62525
|
if (!match) return { success: false, error: `source "${name}" not registered` };
|
|
62343
62526
|
const sourceDir = path422.join(ext.externalRoot(), name);
|
|
62344
62527
|
if (fs322.existsSync(sourceDir)) {
|
|
@@ -62350,7 +62533,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62350
62533
|
}
|
|
62351
62534
|
ext.saveExternalSources({
|
|
62352
62535
|
schema: 1,
|
|
62353
|
-
sources: file2.sources.filter((
|
|
62536
|
+
sources: file2.sources.filter((s2) => s2.name !== name)
|
|
62354
62537
|
});
|
|
62355
62538
|
const active = ext.loadProvidersActive();
|
|
62356
62539
|
const filteredActive = {};
|
|
@@ -62374,10 +62557,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62374
62557
|
const file2 = ext.loadExternalSources();
|
|
62375
62558
|
const inventory = ext.inventoryExternalSources();
|
|
62376
62559
|
const active = ext.loadProvidersActive();
|
|
62377
|
-
const sources = file2.sources.map((
|
|
62378
|
-
const inv = inventory.find((e) => e.sourceName ===
|
|
62560
|
+
const sources = file2.sources.map((s2) => {
|
|
62561
|
+
const inv = inventory.find((e) => e.sourceName === s2.name);
|
|
62379
62562
|
return {
|
|
62380
|
-
...
|
|
62563
|
+
...s2,
|
|
62381
62564
|
providers: inv?.providers ?? {}
|
|
62382
62565
|
};
|
|
62383
62566
|
});
|
|
@@ -62544,6 +62727,21 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62544
62727
|
var path21 = __toESM2(require("path"));
|
|
62545
62728
|
init_terminal_screen();
|
|
62546
62729
|
var import_session_host_core6 = require_dist();
|
|
62730
|
+
var MAX_PTY_EVENTS = 300;
|
|
62731
|
+
var EVENT_CONTENT_CAP = 240;
|
|
62732
|
+
function escapeControl(text) {
|
|
62733
|
+
return String(text).replace(/[\x00-\x1f\x7f]/g, (ch) => {
|
|
62734
|
+
const code = ch.charCodeAt(0);
|
|
62735
|
+
if (ch === "\r") return "\\r";
|
|
62736
|
+
if (ch === "\n") return "\\n";
|
|
62737
|
+
if (ch === " ") return "\\t";
|
|
62738
|
+
if (code === 27) return "\\x1b";
|
|
62739
|
+
return "\\x" + code.toString(16).padStart(2, "0");
|
|
62740
|
+
});
|
|
62741
|
+
}
|
|
62742
|
+
function capPreview(text) {
|
|
62743
|
+
return text.length > EVENT_CONTENT_CAP ? text.slice(0, EVENT_CONTENT_CAP) + `\u2026(+${text.length - EVENT_CONTENT_CAP})` : text;
|
|
62744
|
+
}
|
|
62547
62745
|
var TerminalAdapter = class {
|
|
62548
62746
|
constructor(opts, handlers) {
|
|
62549
62747
|
this.opts = opts;
|
|
@@ -62570,6 +62768,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62570
62768
|
screenTimer = null;
|
|
62571
62769
|
tickTimer = null;
|
|
62572
62770
|
lastScreen = "";
|
|
62771
|
+
/** Debug-only ring buffer of PTY input/output/resize/cursor events. */
|
|
62772
|
+
events = [];
|
|
62773
|
+
lastCursorKey = "";
|
|
62573
62774
|
start() {
|
|
62574
62775
|
const env2 = this.opts.envIsComplete ? this.opts.env ?? {} : { ...process.env, ...this.opts.env ?? {} };
|
|
62575
62776
|
this.pty = this.factory.spawn(this.opts.binary, this.opts.args ?? [], {
|
|
@@ -62578,10 +62779,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62578
62779
|
cols: this.cols,
|
|
62579
62780
|
rows: this.rows
|
|
62580
62781
|
});
|
|
62782
|
+
this.recordEvent("spawn", `${this.opts.binary} (${this.cols}x${this.rows})`);
|
|
62581
62783
|
this.handlers.init?.({ pid: this.pty.pid });
|
|
62582
62784
|
this.pty.onData((chunk) => this.onChunk(chunk));
|
|
62583
62785
|
this.pty.onExit((info) => {
|
|
62584
62786
|
this.stopTimers();
|
|
62787
|
+
this.recordEvent("exit", `exitCode=${typeof info.exitCode === "number" ? info.exitCode : 0}`);
|
|
62585
62788
|
this.handlers.on_exit?.({ exitCode: typeof info.exitCode === "number" ? info.exitCode : 0 });
|
|
62586
62789
|
this.pty = null;
|
|
62587
62790
|
});
|
|
@@ -62592,6 +62795,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62592
62795
|
resize(cols, rows) {
|
|
62593
62796
|
this.cols = cols;
|
|
62594
62797
|
this.rows = rows;
|
|
62798
|
+
this.recordEvent("resize", `${cols}x${rows}`);
|
|
62595
62799
|
this.pty?.resize(cols, rows);
|
|
62596
62800
|
this.screen.resize(rows, cols);
|
|
62597
62801
|
}
|
|
@@ -62612,8 +62816,21 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62612
62816
|
return { row: pos.row, col: pos.col };
|
|
62613
62817
|
}
|
|
62614
62818
|
send_keys(text) {
|
|
62819
|
+
this.recordEvent("input", capPreview(escapeControl(text)), text.length);
|
|
62615
62820
|
this.pty?.write(text);
|
|
62616
62821
|
}
|
|
62822
|
+
/** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
|
|
62823
|
+
* first. Pure observation — never consulted by the FSM. */
|
|
62824
|
+
getEventTimeline(limit = MAX_PTY_EVENTS) {
|
|
62825
|
+
const n = Math.max(0, Math.min(limit, this.events.length));
|
|
62826
|
+
return this.events.slice(this.events.length - n);
|
|
62827
|
+
}
|
|
62828
|
+
recordEvent(kind, content, bytes) {
|
|
62829
|
+
const ev = { ts: Date.now(), kind, content };
|
|
62830
|
+
if (typeof bytes === "number") ev.bytes = bytes;
|
|
62831
|
+
this.events.push(ev);
|
|
62832
|
+
if (this.events.length > MAX_PTY_EVENTS) this.events.splice(0, this.events.length - MAX_PTY_EVENTS);
|
|
62833
|
+
}
|
|
62617
62834
|
kill() {
|
|
62618
62835
|
this.stopTimers();
|
|
62619
62836
|
try {
|
|
@@ -62624,6 +62841,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62624
62841
|
this.screen.dispose();
|
|
62625
62842
|
}
|
|
62626
62843
|
onChunk(chunk) {
|
|
62844
|
+
this.recordEvent("output", capPreview(escapeControl(chunk)), chunk.length);
|
|
62627
62845
|
try {
|
|
62628
62846
|
this.handlers.on_pty_data?.(chunk);
|
|
62629
62847
|
} catch {
|
|
@@ -62633,6 +62851,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62633
62851
|
this.screenTimer = setTimeout(() => {
|
|
62634
62852
|
this.screenTimer = null;
|
|
62635
62853
|
const snap = this.computeScreen();
|
|
62854
|
+
const cur = this.screen.getCursorPosition();
|
|
62855
|
+
const curKey = `${cur.row},${cur.col}`;
|
|
62856
|
+
if (curKey !== this.lastCursorKey) {
|
|
62857
|
+
this.lastCursorKey = curKey;
|
|
62858
|
+
this.recordEvent("cursor", `(${cur.row},${cur.col})`);
|
|
62859
|
+
}
|
|
62636
62860
|
if (snap === this.lastScreen) return;
|
|
62637
62861
|
this.lastScreen = snap;
|
|
62638
62862
|
try {
|
|
@@ -62711,20 +62935,40 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62711
62935
|
}
|
|
62712
62936
|
}
|
|
62713
62937
|
init_logger();
|
|
62714
|
-
function countNewlines(
|
|
62938
|
+
function countNewlines(s2) {
|
|
62715
62939
|
let n = 0;
|
|
62716
|
-
for (let i = 0; i <
|
|
62940
|
+
for (let i = 0; i < s2.length; i += 1) if (s2.charCodeAt(i) === 10) n += 1;
|
|
62717
62941
|
return n;
|
|
62718
62942
|
}
|
|
62719
62943
|
var SUBMIT_DELAY_FLOOR_MS = 200;
|
|
62720
62944
|
var WIN32_SUBMIT_RESEND_GAP_MS = 350;
|
|
62721
62945
|
var WIN32_SUBMIT_MAX_RESENDS = 14;
|
|
62946
|
+
var WIN32_SUBMIT_SETTLE_MS = 500;
|
|
62947
|
+
var WIN32_SUBMIT_MAX_SETTLE_WAIT_MS = 1e4;
|
|
62948
|
+
var WIN32_SUBMIT_SETTLE_POLL_MS = 120;
|
|
62949
|
+
var WIN32_PTY_WRITE_CHUNK_CHARS = 1024;
|
|
62950
|
+
var WIN32_PTY_WRITE_CHUNK_GAP_MS = 8;
|
|
62722
62951
|
function resolveSubmitDelayMs(specBeforeSubmit, text) {
|
|
62723
62952
|
const lines = countNewlines(text);
|
|
62724
62953
|
const linesBonus = Math.min(800, lines * 80);
|
|
62725
62954
|
const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
|
|
62726
62955
|
return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
|
|
62727
62956
|
}
|
|
62957
|
+
function chunkPreservingSurrogates(text, size) {
|
|
62958
|
+
const chunks = [];
|
|
62959
|
+
let offset = 0;
|
|
62960
|
+
while (offset < text.length) {
|
|
62961
|
+
let end = Math.min(text.length, offset + size);
|
|
62962
|
+
if (end < text.length) {
|
|
62963
|
+
const code = text.charCodeAt(end - 1);
|
|
62964
|
+
if (code >= 55296 && code <= 56319) end -= 1;
|
|
62965
|
+
}
|
|
62966
|
+
if (end <= offset) end = Math.min(text.length, offset + size);
|
|
62967
|
+
chunks.push(text.slice(offset, end));
|
|
62968
|
+
offset = end;
|
|
62969
|
+
}
|
|
62970
|
+
return chunks;
|
|
62971
|
+
}
|
|
62728
62972
|
function guessExt(mime) {
|
|
62729
62973
|
if (/png/i.test(mime)) return ".png";
|
|
62730
62974
|
if (/jpe?g/i.test(mime)) return ".jpg";
|
|
@@ -62740,7 +62984,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62740
62984
|
this.buildAdapterOpts(),
|
|
62741
62985
|
{
|
|
62742
62986
|
init: () => this.emitInitialState(),
|
|
62743
|
-
on_pty_data: (chunk) =>
|
|
62987
|
+
on_pty_data: (chunk) => {
|
|
62988
|
+
this.lastPtyDataAt = Date.now();
|
|
62989
|
+
this.emit({ kind: "pty_data", chunk });
|
|
62990
|
+
},
|
|
62744
62991
|
on_screen_changed: () => this.reevaluate(),
|
|
62745
62992
|
on_exit: ({ exitCode }) => this.handleExit(exitCode)
|
|
62746
62993
|
}
|
|
@@ -62774,6 +63021,16 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62774
63021
|
* WIN32_SUBMIT_* and scheduleWin32Submit). Re-arms itself until the FSM
|
|
62775
63022
|
* leaves idle (submitted) or the resend budget is spent. */
|
|
62776
63023
|
win32SubmitTimer = null;
|
|
63024
|
+
/** Wall-clock (ms) of the most recent raw PTY output chunk. Advances on every
|
|
63025
|
+
* on_pty_data — including the echo of text written into the composer — so the
|
|
63026
|
+
* win32 submit settle-gate can tell when input has finished landing. */
|
|
63027
|
+
lastPtyDataAt = 0;
|
|
63028
|
+
/** Wall-clock (ms) of the most recent win32 message-body input write. Bridges
|
|
63029
|
+
* the gap between writing a chunk and its echo so the settle-gate does not
|
|
63030
|
+
* declare "quiet" mid-write. */
|
|
63031
|
+
lastWin32WriteAt = 0;
|
|
63032
|
+
/** Pending paced chunk-write timer for a large win32 body (see writeWin32Body). */
|
|
63033
|
+
win32WriteTimer = null;
|
|
62777
63034
|
currentEval = null;
|
|
62778
63035
|
stateHistory = [];
|
|
62779
63036
|
prevStateAt = 0;
|
|
@@ -62894,6 +63151,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62894
63151
|
clearTimeout(this.win32SubmitTimer);
|
|
62895
63152
|
this.win32SubmitTimer = null;
|
|
62896
63153
|
}
|
|
63154
|
+
if (this.win32WriteTimer) {
|
|
63155
|
+
clearTimeout(this.win32WriteTimer);
|
|
63156
|
+
this.win32WriteTimer = null;
|
|
63157
|
+
}
|
|
62897
63158
|
this.specWatcher?.close();
|
|
62898
63159
|
this.adapter.kill();
|
|
62899
63160
|
}
|
|
@@ -62924,11 +63185,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62924
63185
|
getFsmSnapshotHistory() {
|
|
62925
63186
|
return this.fsmSnapshotHistory;
|
|
62926
63187
|
}
|
|
63188
|
+
/** Debug-only PTY input/output/resize/cursor timeline from the adapter. */
|
|
63189
|
+
getEventTimeline(limit) {
|
|
63190
|
+
return this.adapter.getEventTimeline(limit);
|
|
63191
|
+
}
|
|
62927
63192
|
getSections() {
|
|
62928
63193
|
try {
|
|
62929
63194
|
const screen = this.adapter.snapshot();
|
|
62930
63195
|
const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
62931
|
-
return resolveSections(this.spec.sections ?? {}, lines).map((
|
|
63196
|
+
return resolveSections(this.spec.sections ?? {}, lines).map((s2) => ({ id: s2.id, text: s2.text }));
|
|
62932
63197
|
} catch {
|
|
62933
63198
|
return null;
|
|
62934
63199
|
}
|
|
@@ -63306,7 +63571,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63306
63571
|
const perChar = sm.delay_ms_per_char ?? 0;
|
|
63307
63572
|
const beforeSubmit = resolveSubmitDelayMs(sm.delay_ms_before_submit, text);
|
|
63308
63573
|
if (process.platform === "win32") {
|
|
63309
|
-
this.
|
|
63574
|
+
this.writeWin32Body(text);
|
|
63310
63575
|
this.scheduleWin32Submit(sm.submit_key, beforeSubmit);
|
|
63311
63576
|
return;
|
|
63312
63577
|
}
|
|
@@ -63332,20 +63597,72 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63332
63597
|
const st = stateById(this.spec, this.currentStateId);
|
|
63333
63598
|
return st ? statusForState(st) : "idle";
|
|
63334
63599
|
}
|
|
63600
|
+
/** Record a win32 body write so the settle-gate counts it as input activity
|
|
63601
|
+
* even before the echo arrives. */
|
|
63602
|
+
markWin32Write() {
|
|
63603
|
+
this.lastWin32WriteAt = Date.now();
|
|
63604
|
+
}
|
|
63605
|
+
/** Most recent win32 input activity — a write we issued OR a PTY output chunk
|
|
63606
|
+
* (echo). The submit settle-gate waits for this to go quiet. */
|
|
63607
|
+
lastWin32InputActivityAt() {
|
|
63608
|
+
return Math.max(this.lastPtyDataAt, this.lastWin32WriteAt);
|
|
63609
|
+
}
|
|
63335
63610
|
/**
|
|
63336
|
-
*
|
|
63337
|
-
*
|
|
63338
|
-
* a
|
|
63339
|
-
*
|
|
63340
|
-
*
|
|
63341
|
-
*
|
|
63342
|
-
|
|
63611
|
+
* Write the message body to the PTY for win32, paced into bounded chunks. A
|
|
63612
|
+
* single unbounded ConPTY write can overflow the input pipe and drop leading
|
|
63613
|
+
* bytes; splitting it with a short inter-chunk gap keeps the console input
|
|
63614
|
+
* buffer from overflowing. Small bodies still go out in a single write. Each
|
|
63615
|
+
* chunk advances lastWin32WriteAt so the submit settle-gate keeps waiting until
|
|
63616
|
+
* the final chunk is out and echoed.
|
|
63617
|
+
*/
|
|
63618
|
+
writeWin32Body(text) {
|
|
63619
|
+
if (this.win32WriteTimer) {
|
|
63620
|
+
clearTimeout(this.win32WriteTimer);
|
|
63621
|
+
this.win32WriteTimer = null;
|
|
63622
|
+
}
|
|
63623
|
+
if (text.length <= WIN32_PTY_WRITE_CHUNK_CHARS) {
|
|
63624
|
+
this.markWin32Write();
|
|
63625
|
+
this.adapter.send_keys(text);
|
|
63626
|
+
return;
|
|
63627
|
+
}
|
|
63628
|
+
const chunks = chunkPreservingSurrogates(text, WIN32_PTY_WRITE_CHUNK_CHARS);
|
|
63629
|
+
let idx = 0;
|
|
63630
|
+
const writeNext = () => {
|
|
63631
|
+
this.win32WriteTimer = null;
|
|
63632
|
+
if (idx >= chunks.length) return;
|
|
63633
|
+
this.markWin32Write();
|
|
63634
|
+
this.adapter.send_keys(chunks[idx]);
|
|
63635
|
+
idx += 1;
|
|
63636
|
+
if (idx < chunks.length) {
|
|
63637
|
+
this.win32WriteTimer = setTimeout(writeNext, WIN32_PTY_WRITE_CHUNK_GAP_MS);
|
|
63638
|
+
}
|
|
63639
|
+
};
|
|
63640
|
+
writeNext();
|
|
63641
|
+
}
|
|
63642
|
+
/**
|
|
63643
|
+
* win32 submit. Two phases:
|
|
63644
|
+
*
|
|
63645
|
+
* Phase 1 (settle-gate): hold the first CR until the PTY output has been quiet
|
|
63646
|
+
* for WIN32_SUBMIT_SETTLE_MS after the last input write — i.e. the full
|
|
63647
|
+
* (possibly multi-KB / multiline) body has finished arriving in the composer
|
|
63648
|
+
* and echoing. Honors an initial minimum delay and is bounded by
|
|
63649
|
+
* WIN32_SUBMIT_MAX_SETTLE_WAIT_MS so a noisy screen can never hang the submit.
|
|
63650
|
+
* This is what stops a long message from being submitted half-arrived (its
|
|
63651
|
+
* leading lines lost). A short message settles almost immediately.
|
|
63652
|
+
*
|
|
63653
|
+
* Phase 2 (verified resend — unchanged): send the submit key, wait a gap, and
|
|
63654
|
+
* if the FSM is still 'idle' (the CR was absorbed as a multiline-paste
|
|
63655
|
+
* newline) resend, up to WIN32_SUBMIT_MAX_RESENDS. The first CR always fires
|
|
63656
|
+
* (a stale/edge status never suppresses it); resends are gated on still being
|
|
63657
|
+
* idle and stop the instant the agent leaves idle (submitted → generating /
|
|
63658
|
+
* approval). This preserves the win32 lone-CR-swallow handling.
|
|
63343
63659
|
*/
|
|
63344
63660
|
scheduleWin32Submit(submitKey, initialDelayMs) {
|
|
63345
63661
|
if (this.win32SubmitTimer) {
|
|
63346
63662
|
clearTimeout(this.win32SubmitTimer);
|
|
63347
63663
|
this.win32SubmitTimer = null;
|
|
63348
63664
|
}
|
|
63665
|
+
const startedAt = Date.now();
|
|
63349
63666
|
const fire = (attempt) => {
|
|
63350
63667
|
this.win32SubmitTimer = null;
|
|
63351
63668
|
this.adapter.send_keys(submitKey);
|
|
@@ -63358,8 +63675,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63358
63675
|
fire(attempt + 1);
|
|
63359
63676
|
}, WIN32_SUBMIT_RESEND_GAP_MS);
|
|
63360
63677
|
};
|
|
63361
|
-
|
|
63362
|
-
|
|
63678
|
+
const waitForSettle = () => {
|
|
63679
|
+
this.win32SubmitTimer = null;
|
|
63680
|
+
const now = Date.now();
|
|
63681
|
+
const quietFor = now - this.lastWin32InputActivityAt();
|
|
63682
|
+
const waited = now - startedAt;
|
|
63683
|
+
if (quietFor >= WIN32_SUBMIT_SETTLE_MS || waited >= WIN32_SUBMIT_MAX_SETTLE_WAIT_MS) {
|
|
63684
|
+
fire(0);
|
|
63685
|
+
return;
|
|
63686
|
+
}
|
|
63687
|
+
const recheckIn = Math.min(WIN32_SUBMIT_SETTLE_MS - quietFor, WIN32_SUBMIT_SETTLE_POLL_MS);
|
|
63688
|
+
this.win32SubmitTimer = setTimeout(waitForSettle, Math.max(recheckIn, 30));
|
|
63689
|
+
};
|
|
63690
|
+
if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(waitForSettle, initialDelayMs);
|
|
63691
|
+
else waitForSettle();
|
|
63363
63692
|
}
|
|
63364
63693
|
handleClickControl(controlId, payload) {
|
|
63365
63694
|
const ctl = (this.spec.control_bar ?? []).find((c) => c.id === controlId);
|
|
@@ -63394,6 +63723,19 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63394
63723
|
if (!m) return;
|
|
63395
63724
|
const btn = m.buttons.find((b) => b.index === index);
|
|
63396
63725
|
if (!btn) return;
|
|
63726
|
+
const rule = stateById(this.spec, this.currentStateId)?.extract?.buttons;
|
|
63727
|
+
if (rule?.select_mode === "arrow_keys") {
|
|
63728
|
+
const from = m.buttons.find((b) => b.current)?.index ?? 1;
|
|
63729
|
+
const up = rule.cursor_keys?.up ?? "\x1B[A";
|
|
63730
|
+
const down = rule.cursor_keys?.down ?? "\x1B[B";
|
|
63731
|
+
const delta = btn.index - from;
|
|
63732
|
+
const step = delta >= 0 ? down : up;
|
|
63733
|
+
const nav = step.repeat(Math.abs(delta));
|
|
63734
|
+
const confirm = (rule.key_for_index || "\r").replace(/\{index\}/g, "") || "\r";
|
|
63735
|
+
if (nav) this.adapter.send_keys(nav);
|
|
63736
|
+
this.adapter.send_keys(confirm);
|
|
63737
|
+
return;
|
|
63738
|
+
}
|
|
63397
63739
|
this.adapter.send_keys(btn.key);
|
|
63398
63740
|
}
|
|
63399
63741
|
handleAttachImage(blob, mime) {
|
|
@@ -63472,7 +63814,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63472
63814
|
return out;
|
|
63473
63815
|
}
|
|
63474
63816
|
function flattenCond(c, out, depth) {
|
|
63475
|
-
|
|
63817
|
+
const matched = c.matchedText ? ` matched=${JSON.stringify(c.matchedText)}` : "";
|
|
63818
|
+
out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}${matched}`);
|
|
63476
63819
|
for (const child of c.children ?? []) flattenCond(child, out, depth + 1);
|
|
63477
63820
|
}
|
|
63478
63821
|
function findStable(c) {
|
|
@@ -64188,8 +64531,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64188
64531
|
}
|
|
64189
64532
|
return null;
|
|
64190
64533
|
}
|
|
64191
|
-
function oneLine(
|
|
64192
|
-
const flat =
|
|
64534
|
+
function oneLine(s2, max) {
|
|
64535
|
+
const flat = s2.replace(/\s+/g, " ").trim();
|
|
64193
64536
|
return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
|
|
64194
64537
|
}
|
|
64195
64538
|
function parseTimestamp(v) {
|
|
@@ -64209,10 +64552,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64209
64552
|
return null;
|
|
64210
64553
|
}
|
|
64211
64554
|
function normalizeRole(r) {
|
|
64212
|
-
const
|
|
64213
|
-
if (
|
|
64214
|
-
if (
|
|
64215
|
-
if (
|
|
64555
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
64556
|
+
if (s2 === "user" || s2 === "human" || s2 === "user_explicit") return "user";
|
|
64557
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
64558
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
64216
64559
|
return "system";
|
|
64217
64560
|
}
|
|
64218
64561
|
function stringifyContent(v) {
|
|
@@ -64260,18 +64603,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64260
64603
|
return (record2) => ors.some((ands) => ands.every((t) => evalTerm(t, record2)));
|
|
64261
64604
|
}
|
|
64262
64605
|
function parseTerm(src) {
|
|
64263
|
-
let
|
|
64606
|
+
let s2 = src.trim();
|
|
64264
64607
|
let negate = false;
|
|
64265
|
-
if (
|
|
64608
|
+
if (s2.startsWith("!")) {
|
|
64266
64609
|
negate = true;
|
|
64267
|
-
|
|
64610
|
+
s2 = s2.slice(1).trim();
|
|
64268
64611
|
}
|
|
64269
|
-
const fnMatch =
|
|
64612
|
+
const fnMatch = s2.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
|
|
64270
64613
|
if (fnMatch) {
|
|
64271
64614
|
const [, op2, pathExpr, litExpr] = fnMatch;
|
|
64272
64615
|
return { path: pathExpr, op: op2, lit: parseLiteral(litExpr), negate };
|
|
64273
64616
|
}
|
|
64274
|
-
const opMatch =
|
|
64617
|
+
const opMatch = s2.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
|
|
64275
64618
|
if (!opMatch) return null;
|
|
64276
64619
|
const [, lhs, op, rhsRaw] = opMatch;
|
|
64277
64620
|
return { path: lhs.trim(), op, lit: parseLiteral(rhsRaw.trim()), negate };
|
|
@@ -64626,9 +64969,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64626
64969
|
* — not this code — decides how a selection is keyed for each CLI.
|
|
64627
64970
|
*/
|
|
64628
64971
|
async selectPickerChoice(ctl, action, choiceIndex, choiceLabel) {
|
|
64629
|
-
|
|
64630
|
-
|
|
64631
|
-
|
|
64972
|
+
let options = this.extractPickerChoicesIfRendered(action);
|
|
64973
|
+
if (!options) {
|
|
64974
|
+
this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
|
|
64975
|
+
await this.waitForPickerRendered(action);
|
|
64976
|
+
options = this.extractPickerChoices(action);
|
|
64977
|
+
}
|
|
64632
64978
|
let index = choiceIndex;
|
|
64633
64979
|
if ((index == null || !Number.isFinite(index)) && choiceLabel) {
|
|
64634
64980
|
const needle = choiceLabel.trim().toLowerCase();
|
|
@@ -64641,8 +64987,27 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64641
64987
|
if (index == null || !Number.isFinite(index)) {
|
|
64642
64988
|
return { ok: false, error: "choiceIndex or choiceLabel required to select" };
|
|
64643
64989
|
}
|
|
64644
|
-
|
|
64645
|
-
|
|
64990
|
+
if (action.select_mode === "arrow_keys") {
|
|
64991
|
+
const current = options.find((o) => o.current);
|
|
64992
|
+
if (current == null) {
|
|
64993
|
+
return {
|
|
64994
|
+
ok: false,
|
|
64995
|
+
error: "arrow-nav picker: current cursor row not detected on screen",
|
|
64996
|
+
controlResult: { options: options.map((o) => ({ value: o.label, label: o.label, current: o.current })) }
|
|
64997
|
+
};
|
|
64998
|
+
}
|
|
64999
|
+
const up = action.cursor_keys?.up ?? "\x1B[A";
|
|
65000
|
+
const down = action.cursor_keys?.down ?? "\x1B[B";
|
|
65001
|
+
const delta = index - current.index;
|
|
65002
|
+
const step = delta >= 0 ? down : up;
|
|
65003
|
+
const nav = step.repeat(Math.abs(delta));
|
|
65004
|
+
const confirm = (action.submit_key || "\r").replace(/\{index\}/g, "") || "\r";
|
|
65005
|
+
if (nav) this.driver.dispatch({ kind: "pty_write", data: nav });
|
|
65006
|
+
this.driver.dispatch({ kind: "pty_write", data: confirm });
|
|
65007
|
+
} else {
|
|
65008
|
+
const keys = (action.submit_key || "{index}\r").replace(/\{index\}/g, String(index));
|
|
65009
|
+
this.driver.dispatch({ kind: "pty_write", data: keys });
|
|
65010
|
+
}
|
|
64646
65011
|
const selected = options.find((o) => o.index === index);
|
|
64647
65012
|
return {
|
|
64648
65013
|
ok: true,
|
|
@@ -64654,6 +65019,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64654
65019
|
}
|
|
64655
65020
|
};
|
|
64656
65021
|
}
|
|
65022
|
+
/** Parse the picker choices only if the picker already appears rendered on
|
|
65023
|
+
* the live screen (its `wait_for` condition currently matches and at least
|
|
65024
|
+
* one choice parses). Returns the parsed choices when open, else null so
|
|
65025
|
+
* the caller knows it must send the trigger to open it. Used to de-dup the
|
|
65026
|
+
* picker open in {@link selectPickerChoice}. */
|
|
65027
|
+
extractPickerChoicesIfRendered(action) {
|
|
65028
|
+
const wf = action.wait_for;
|
|
65029
|
+
if (wf?.regex) {
|
|
65030
|
+
const re = new RegExp(wf.regex, wf.flags ?? "i");
|
|
65031
|
+
if (!re.test(this.readScreenSectionText(wf.section))) return null;
|
|
65032
|
+
}
|
|
65033
|
+
const options = this.extractPickerChoices(action);
|
|
65034
|
+
return options.length > 0 ? options : null;
|
|
65035
|
+
}
|
|
64657
65036
|
/** Poll the live screen until the picker's `wait_for` condition matches,
|
|
64658
65037
|
* up to a short budget. Returns true if it rendered, false on timeout. */
|
|
64659
65038
|
async waitForPickerRendered(action) {
|
|
@@ -64701,7 +65080,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64701
65080
|
try {
|
|
64702
65081
|
const sections = this.driver.getSections();
|
|
64703
65082
|
if (sectionId && sections) {
|
|
64704
|
-
const hit = sections.find((
|
|
65083
|
+
const hit = sections.find((s2) => s2.id === sectionId);
|
|
64705
65084
|
if (hit) return hit.text;
|
|
64706
65085
|
}
|
|
64707
65086
|
return this.driver.getScreen();
|
|
@@ -64716,7 +65095,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64716
65095
|
screen = this.driver.snapshot();
|
|
64717
65096
|
const driverSections = this.driver.getSections?.();
|
|
64718
65097
|
if (driverSections) {
|
|
64719
|
-
sections = Object.fromEntries(driverSections.map((
|
|
65098
|
+
sections = Object.fromEntries(driverSections.map((s2) => [s2.id, s2.text]));
|
|
64720
65099
|
} else {
|
|
64721
65100
|
sections = this.readCurrentScreenSections(screen);
|
|
64722
65101
|
}
|
|
@@ -64762,6 +65141,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64762
65141
|
// answers "why did this rule fire" after the fact, unlike the live
|
|
64763
65142
|
// `fsm` field which only reflects the current instant.
|
|
64764
65143
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
65144
|
+
// PTY input/output/resize/cursor event timeline (debug-only) so the
|
|
65145
|
+
// snapshot shows what we typed / what the PTY printed around each
|
|
65146
|
+
// status transition. Null for drivers without the timeline.
|
|
65147
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
64765
65148
|
// Extended fields
|
|
64766
65149
|
name: this.cliName,
|
|
64767
65150
|
status: this.getStatus().status,
|
|
@@ -65126,6 +65509,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
65126
65509
|
// v4 FSM transition snapshot history — the captured pre-transition
|
|
65127
65510
|
// evaluation table at each transition (null for v3 specs).
|
|
65128
65511
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
65512
|
+
// PTY input/output/resize/cursor event timeline (debug-only).
|
|
65513
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
65129
65514
|
messages,
|
|
65130
65515
|
committedMessages: messages
|
|
65131
65516
|
};
|
|
@@ -65166,6 +65551,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
65166
65551
|
return new ProviderCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFactory);
|
|
65167
65552
|
}
|
|
65168
65553
|
init_logger();
|
|
65554
|
+
init_mesh_event_trace();
|
|
65169
65555
|
init_control_effects();
|
|
65170
65556
|
init_approval_utils();
|
|
65171
65557
|
init_provider_patch_state();
|
|
@@ -66209,6 +66595,23 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66209
66595
|
if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
|
|
66210
66596
|
this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
|
|
66211
66597
|
}
|
|
66598
|
+
// EVTTRACE (observation-only): is this a mesh worker session whose completion
|
|
66599
|
+
// events must route to a coordinator? Used purely to gate trace logging so a
|
|
66600
|
+
// non-mesh CLI session's completions don't add EvtTrace noise. No decision logic.
|
|
66601
|
+
isMeshWorkerSession() {
|
|
66602
|
+
return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
|
|
66603
|
+
}
|
|
66604
|
+
// EVTTRACE correlation context for this session's completion lifecycle. taskId is
|
|
66605
|
+
// the primary grep anchor; instanceId is the session fallback.
|
|
66606
|
+
meshTraceCtx(event = "agent:generating_completed") {
|
|
66607
|
+
return {
|
|
66608
|
+
taskId: this.settings.meshActiveTaskId,
|
|
66609
|
+
sessionId: this.instanceId,
|
|
66610
|
+
nodeId: this.settings.meshNodeId,
|
|
66611
|
+
meshId: this.settings.meshNodeFor,
|
|
66612
|
+
event
|
|
66613
|
+
};
|
|
66614
|
+
}
|
|
66212
66615
|
flushCompletedDebounceIfFinalized() {
|
|
66213
66616
|
const pending = this.completedDebouncePending;
|
|
66214
66617
|
if (!pending) {
|
|
@@ -66229,24 +66632,33 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66229
66632
|
if (block2) {
|
|
66230
66633
|
const blockReason = block2.reason;
|
|
66231
66634
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
66232
|
-
|
|
66233
|
-
|
|
66635
|
+
const isTranscriptEvidenceGate = block2.allowTimeout === true;
|
|
66636
|
+
LOG2.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} allowTimeout=${isTranscriptEvidenceGate} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
|
|
66637
|
+
if (!isTranscriptEvidenceGate && (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS)) {
|
|
66234
66638
|
if (pending.loggedBlockReason !== blockReason) {
|
|
66235
66639
|
LOG2.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
|
|
66640
|
+
if (this.isMeshWorkerSession()) {
|
|
66641
|
+
traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `${blockReason} waited=${waitedMs}ms`);
|
|
66642
|
+
}
|
|
66236
66643
|
pending.loggedBlockReason = blockReason;
|
|
66237
66644
|
}
|
|
66238
66645
|
this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
|
|
66239
66646
|
return;
|
|
66240
66647
|
}
|
|
66648
|
+
const emittedAfterFinalizationTimeout = waitedMs >= COMPLETED_FINALIZATION_MAX_WAIT_MS;
|
|
66241
66649
|
const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
|
|
66242
66650
|
blockReason,
|
|
66243
66651
|
latestStatus,
|
|
66244
66652
|
latestVisibleStatus,
|
|
66245
66653
|
waitedMs,
|
|
66246
66654
|
pending,
|
|
66247
|
-
emittedAfterFinalizationTimeout
|
|
66655
|
+
emittedAfterFinalizationTimeout
|
|
66248
66656
|
});
|
|
66249
|
-
|
|
66657
|
+
completionDiagnostic.decoupledImmediateEmit = isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout;
|
|
66658
|
+
LOG2.warn("CLI", `[${this.type}] emitting completed event (${isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`}) without finalized assistant turn (${blockReason})`);
|
|
66659
|
+
if (this.isMeshWorkerSession()) {
|
|
66660
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `forced after ${waitedMs}ms (${blockReason})`);
|
|
66661
|
+
}
|
|
66250
66662
|
this.pushEvent({
|
|
66251
66663
|
event: "agent:generating_completed",
|
|
66252
66664
|
chatTitle: pending.chatTitle,
|
|
@@ -66269,6 +66681,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66269
66681
|
return;
|
|
66270
66682
|
}
|
|
66271
66683
|
LOG2.info("CLI", `[${this.type}] completed in ${pending.duration}s`);
|
|
66684
|
+
if (this.isMeshWorkerSession()) {
|
|
66685
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `duration=${pending.duration}s`);
|
|
66686
|
+
}
|
|
66272
66687
|
this.pushEvent({
|
|
66273
66688
|
event: "agent:generating_completed",
|
|
66274
66689
|
chatTitle: pending.chatTitle,
|
|
@@ -66507,6 +66922,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66507
66922
|
if (missingEvidence && !hasMeshContext) {
|
|
66508
66923
|
LOG2.info("CLI", `[${this.type}] short completion suppressed: missing final assistant evidence, no mesh context (source=${shortEvidenceSource})`);
|
|
66509
66924
|
} else {
|
|
66925
|
+
if (this.isMeshWorkerSession()) {
|
|
66926
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `short-generating idle (source=${shortEvidenceSource})`);
|
|
66927
|
+
}
|
|
66510
66928
|
this.pushEvent({
|
|
66511
66929
|
event: "agent:generating_completed",
|
|
66512
66930
|
chatTitle,
|
|
@@ -66583,6 +67001,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66583
67001
|
const monitorParsedStatus = parsedStatus;
|
|
66584
67002
|
for (const me of monitorEvents) {
|
|
66585
67003
|
if (me.type === "monitor:no_progress" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
|
|
67004
|
+
if (this.isMeshWorkerSession()) {
|
|
67005
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), "no_progress_monitor_final_summary");
|
|
67006
|
+
}
|
|
66586
67007
|
this.pushEvent({
|
|
66587
67008
|
event: "agent:generating_completed",
|
|
66588
67009
|
chatTitle,
|
|
@@ -66623,6 +67044,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66623
67044
|
workspace: typeof event.workspace === "string" && event.workspace.trim() ? event.workspace : this.workingDir,
|
|
66624
67045
|
providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
|
|
66625
67046
|
};
|
|
67047
|
+
if (this.isMeshWorkerSession() && this.settings.meshActiveTaskId) {
|
|
67048
|
+
const existingTaskId = typeof enrichedEvent.taskId === "string" && enrichedEvent.taskId.trim() ? enrichedEvent.taskId : void 0;
|
|
67049
|
+
if (!existingTaskId) {
|
|
67050
|
+
enrichedEvent.taskId = this.settings.meshActiveTaskId;
|
|
67051
|
+
}
|
|
67052
|
+
}
|
|
66626
67053
|
if (this.context?.emitProviderEvent) {
|
|
66627
67054
|
this.context.emitProviderEvent(enrichedEvent);
|
|
66628
67055
|
} else {
|
|
@@ -70422,7 +70849,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70422
70849
|
}
|
|
70423
70850
|
if (buf.length === 0) return null;
|
|
70424
70851
|
const strings = extractStringsFromBuffer(buf);
|
|
70425
|
-
const meaningful = strings.filter((
|
|
70852
|
+
const meaningful = strings.filter((s2) => s2.length >= MIN_PRINTABLE_RUN && /\w/.test(s2));
|
|
70426
70853
|
if (meaningful.length === 0) return null;
|
|
70427
70854
|
const content = meaningful.join("\n");
|
|
70428
70855
|
const sourceMtimeMs = statMtimeMs3(filePath);
|
|
@@ -70628,10 +71055,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70628
71055
|
};
|
|
70629
71056
|
}
|
|
70630
71057
|
function normalizeHermesRole(r) {
|
|
70631
|
-
const
|
|
70632
|
-
if (
|
|
70633
|
-
if (
|
|
70634
|
-
if (
|
|
71058
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
71059
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
71060
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
71061
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
70635
71062
|
return "system";
|
|
70636
71063
|
}
|
|
70637
71064
|
function createNativeHistoryDispatcher(reader) {
|
|
@@ -70855,10 +71282,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70855
71282
|
}
|
|
70856
71283
|
}
|
|
70857
71284
|
function normalizeRole2(r) {
|
|
70858
|
-
const
|
|
70859
|
-
if (
|
|
70860
|
-
if (
|
|
70861
|
-
if (
|
|
71285
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
71286
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
71287
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
71288
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
70862
71289
|
return "system";
|
|
70863
71290
|
}
|
|
70864
71291
|
function registerProviderScriptRootSafely(root) {
|
|
@@ -70876,7 +71303,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70876
71303
|
const actionType = ctl?.action?.type;
|
|
70877
71304
|
if (!id || !actionType) return;
|
|
70878
71305
|
const label = typeof ctl?.label === "string" && ctl.label.trim() ? ctl.label : id;
|
|
70879
|
-
const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((
|
|
71306
|
+
const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s2) => typeof s2 === "string") : void 0;
|
|
70880
71307
|
if (actionType === "open_picker") {
|
|
70881
71308
|
out.push({
|
|
70882
71309
|
id,
|
|
@@ -77762,7 +78189,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
77762
78189
|
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.";
|
|
77763
78190
|
if (!firstFailedCmd) return base;
|
|
77764
78191
|
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 : "";
|
|
77765
|
-
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((
|
|
78192
|
+
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s2) => typeof s2 === "string" && s2.length > 0).join("\n");
|
|
77766
78193
|
const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
|
|
77767
78194
|
return [
|
|
77768
78195
|
base,
|
|
@@ -78513,7 +78940,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
78513
78940
|
convergence = "blocked_review";
|
|
78514
78941
|
}
|
|
78515
78942
|
const fbcs = result.finalBranchConvergenceState && typeof result.finalBranchConvergenceState === "object" ? result.finalBranchConvergenceState : void 0;
|
|
78516
|
-
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((
|
|
78943
|
+
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s2) => s2.status === "failed").map((s2) => s2.stage).filter(Boolean).pop() : void 0;
|
|
78517
78944
|
results.push({
|
|
78518
78945
|
nodeId: node.id,
|
|
78519
78946
|
workspace: node.workspace,
|
|
@@ -79510,7 +79937,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
79510
79937
|
return {
|
|
79511
79938
|
success: true,
|
|
79512
79939
|
screenLineCount: lines.length,
|
|
79513
|
-
sections: resolved.map((
|
|
79940
|
+
sections: resolved.map((s2) => ({ id: s2.id, fromLine: s2.fromLine, toLine: s2.toLine, text: s2.text }))
|
|
79514
79941
|
};
|
|
79515
79942
|
} catch (e) {
|
|
79516
79943
|
return { success: false, error: `resolve failed: ${e.message}` };
|
|
@@ -80079,7 +80506,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80079
80506
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
80080
80507
|
try {
|
|
80081
80508
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2, describeTaskDependencyState: describeTaskDependencyState2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
80082
|
-
const status = Array.isArray(args?.status) ? args.status.map((
|
|
80509
|
+
const status = Array.isArray(args?.status) ? args.status.map((s2) => typeof s2 === "string" ? s2.trim() : "").filter(Boolean) : void 0;
|
|
80083
80510
|
const rawQueue = getQueue2(meshId, { status });
|
|
80084
80511
|
const statusById = new Map(getQueue2(meshId).map((task) => [task.id, task.status]));
|
|
80085
80512
|
const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById) } : task);
|
|
@@ -80360,7 +80787,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80360
80787
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80361
80788
|
}
|
|
80362
80789
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
80363
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
80790
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
80364
80791
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80365
80792
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
|
|
80366
80793
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -80394,7 +80821,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80394
80821
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80395
80822
|
}
|
|
80396
80823
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
80397
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
80824
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
80398
80825
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80399
80826
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
|
|
80400
80827
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -80442,7 +80869,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80442
80869
|
const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
80443
80870
|
const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
|
|
80444
80871
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
80445
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
80872
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
80446
80873
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80447
80874
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
80448
80875
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
|
|
@@ -80529,7 +80956,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80529
80956
|
let worktreeCleanup;
|
|
80530
80957
|
if (node?.isLocalWorktree) {
|
|
80531
80958
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80532
|
-
const isRemoteWorktree = nodeDaemonId && nodeDaemonId
|
|
80959
|
+
const isRemoteWorktree = nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
|
|
80533
80960
|
if (isRemoteWorktree) {
|
|
80534
80961
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "remove_mesh_node", {
|
|
80535
80962
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -80611,7 +81038,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80611
81038
|
const sourceNode = mesh.nodes?.find((n) => meshNodeIdMatches(n, sourceNodeId));
|
|
80612
81039
|
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
80613
81040
|
const sourceDaemonId = typeof sourceNode.daemonId === "string" ? sourceNode.daemonId.trim() : void 0;
|
|
80614
|
-
if (sourceDaemonId && sourceDaemonId
|
|
81041
|
+
if (sourceDaemonId && !daemonIdsEquivalent(sourceDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80615
81042
|
const forwarded = await this.deps.dispatchMeshCommand(sourceDaemonId, "clone_mesh_node", {
|
|
80616
81043
|
...typeof args === "object" && args !== null ? args : {},
|
|
80617
81044
|
_meshDirectDispatch: true
|
|
@@ -80853,7 +81280,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80853
81280
|
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
80854
81281
|
if (!node.isLocalWorktree) return { success: false, error: "Node is not a local worktree node" };
|
|
80855
81282
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80856
|
-
if (nodeDaemonId && nodeDaemonId
|
|
81283
|
+
if (nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80857
81284
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "retry_mesh_node_bootstrap", {
|
|
80858
81285
|
...typeof args === "object" && args !== null ? args : {},
|
|
80859
81286
|
_meshDirectDispatch: true
|
|
@@ -82061,16 +82488,16 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
82061
82488
|
const now = this.lastStatusSentAt;
|
|
82062
82489
|
const target = opts?.p2pOnly ? "P2P" : serverConnected ? "P2P+Server" : "P2P";
|
|
82063
82490
|
const allStates = this.deps.instanceManager.collectAllStates();
|
|
82064
|
-
const ideStates = allStates.filter((
|
|
82065
|
-
const cliStates = allStates.filter((
|
|
82066
|
-
const acpStates = allStates.filter((
|
|
82067
|
-
const ideSummary = ideStates.map((
|
|
82068
|
-
const msgs =
|
|
82069
|
-
const exts =
|
|
82070
|
-
return `${
|
|
82491
|
+
const ideStates = allStates.filter((s2) => s2.category === "ide");
|
|
82492
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli");
|
|
82493
|
+
const acpStates = allStates.filter((s2) => s2.category === "acp");
|
|
82494
|
+
const ideSummary = ideStates.map((s2) => {
|
|
82495
|
+
const msgs = s2.activeChat?.messages?.length || 0;
|
|
82496
|
+
const exts = s2.extensions.length;
|
|
82497
|
+
return `${s2.type}(${s2.status},${msgs}msg,${exts}ext)`;
|
|
82071
82498
|
}).join(", ");
|
|
82072
|
-
const cliSummary = cliStates.map((
|
|
82073
|
-
const acpSummary = acpStates.map((
|
|
82499
|
+
const cliSummary = cliStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
82500
|
+
const acpSummary = acpStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
82074
82501
|
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
82075
82502
|
const baseSummary = `IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
|
|
82076
82503
|
const summaryChanged = baseSummary !== this.lastStatusSummary;
|
|
@@ -82181,10 +82608,10 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
82181
82608
|
}
|
|
82182
82609
|
return false;
|
|
82183
82610
|
}
|
|
82184
|
-
simpleHash(
|
|
82611
|
+
simpleHash(s2) {
|
|
82185
82612
|
let h = 2166136261;
|
|
82186
|
-
for (let i = 0; i <
|
|
82187
|
-
h ^=
|
|
82613
|
+
for (let i = 0; i < s2.length; i++) {
|
|
82614
|
+
h ^= s2.charCodeAt(i);
|
|
82188
82615
|
h = h * 16777619 >>> 0;
|
|
82189
82616
|
}
|
|
82190
82617
|
return h.toString(36);
|
|
@@ -83392,7 +83819,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
83392
83819
|
* Per-category status collect
|
|
83393
83820
|
*/
|
|
83394
83821
|
collectStatesByCategory(category) {
|
|
83395
|
-
return this.collectAllStates().filter((
|
|
83822
|
+
return this.collectAllStates().filter((s2) => s2.category === category);
|
|
83396
83823
|
}
|
|
83397
83824
|
// ─── Tick engine ─────────────────────────────────
|
|
83398
83825
|
/**
|
|
@@ -85278,9 +85705,9 @@ async (params) => {
|
|
|
85278
85705
|
function findCliTarget(ctx, type, instanceId) {
|
|
85279
85706
|
if (!ctx.instanceManager) return null;
|
|
85280
85707
|
const cliStates = ctx.instanceManager.collectAllStates().filter(isCliTargetState);
|
|
85281
|
-
if (instanceId) return cliStates.find((
|
|
85708
|
+
if (instanceId) return cliStates.find((s2) => s2.instanceId === instanceId) || null;
|
|
85282
85709
|
if (!type) return cliStates[cliStates.length - 1] || null;
|
|
85283
|
-
const matches = cliStates.filter((
|
|
85710
|
+
const matches = cliStates.filter((s2) => s2.type === type);
|
|
85284
85711
|
return matches[matches.length - 1] || null;
|
|
85285
85712
|
}
|
|
85286
85713
|
function getCliTargetBundle(ctx, type, instanceId) {
|
|
@@ -85643,20 +86070,20 @@ async (params) => {
|
|
|
85643
86070
|
return;
|
|
85644
86071
|
}
|
|
85645
86072
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
85646
|
-
const cliStates = allStates.filter((
|
|
85647
|
-
const result = cliStates.map((
|
|
85648
|
-
instanceId:
|
|
85649
|
-
type:
|
|
85650
|
-
name:
|
|
85651
|
-
category:
|
|
85652
|
-
status:
|
|
85653
|
-
mode:
|
|
85654
|
-
workspace:
|
|
85655
|
-
messageCount:
|
|
85656
|
-
lastMessage:
|
|
85657
|
-
activeModal:
|
|
85658
|
-
pendingEvents:
|
|
85659
|
-
settings:
|
|
86073
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
86074
|
+
const result = cliStates.map((s2) => ({
|
|
86075
|
+
instanceId: s2.instanceId,
|
|
86076
|
+
type: s2.type,
|
|
86077
|
+
name: s2.name,
|
|
86078
|
+
category: s2.category,
|
|
86079
|
+
status: s2.status,
|
|
86080
|
+
mode: s2.mode,
|
|
86081
|
+
workspace: s2.workspace,
|
|
86082
|
+
messageCount: s2.activeChat?.messages?.length || 0,
|
|
86083
|
+
lastMessage: s2.activeChat?.messages?.slice(-1)[0] || null,
|
|
86084
|
+
activeModal: s2.activeChat?.activeModal || null,
|
|
86085
|
+
pendingEvents: s2.pendingEvents || [],
|
|
86086
|
+
settings: s2.settings
|
|
85660
86087
|
}));
|
|
85661
86088
|
ctx.json(res, 200, { instances: result, count: result.length });
|
|
85662
86089
|
}
|
|
@@ -85745,9 +86172,9 @@ async (params) => {
|
|
|
85745
86172
|
}
|
|
85746
86173
|
if (ctx.instanceManager) {
|
|
85747
86174
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
85748
|
-
const cliStates = allStates.filter((
|
|
85749
|
-
for (const
|
|
85750
|
-
ctx.sendCliSSE({ event: "snapshot", providerType:
|
|
86175
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
86176
|
+
for (const s2 of cliStates) {
|
|
86177
|
+
ctx.sendCliSSE({ event: "snapshot", providerType: s2.type, status: s2.status, instanceId: s2.instanceId });
|
|
85751
86178
|
}
|
|
85752
86179
|
}
|
|
85753
86180
|
_req.on("close", () => {
|
|
@@ -85763,7 +86190,7 @@ async (params) => {
|
|
|
85763
86190
|
const target = findCliTarget(ctx, type);
|
|
85764
86191
|
if (!target) {
|
|
85765
86192
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
85766
|
-
ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((
|
|
86193
|
+
ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type) });
|
|
85767
86194
|
return;
|
|
85768
86195
|
}
|
|
85769
86196
|
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
@@ -85809,7 +86236,7 @@ async (params) => {
|
|
|
85809
86236
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
85810
86237
|
ctx.json(res, 404, {
|
|
85811
86238
|
error: `No running instance for: ${type}`,
|
|
85812
|
-
available: allStates.filter((
|
|
86239
|
+
available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type)
|
|
85813
86240
|
});
|
|
85814
86241
|
return;
|
|
85815
86242
|
}
|
|
@@ -86612,7 +87039,7 @@ async (params) => {
|
|
|
86612
87039
|
child.write("\x1B[12;1R");
|
|
86613
87040
|
ctx.log("Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]");
|
|
86614
87041
|
}
|
|
86615
|
-
checkAutoApproval(data, (
|
|
87042
|
+
checkAutoApproval(data, (s2) => child.write(s2));
|
|
86616
87043
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
86617
87044
|
scheduleAutoStopForVerification();
|
|
86618
87045
|
});
|
|
@@ -86625,7 +87052,7 @@ async (params) => {
|
|
|
86625
87052
|
stdout += chunk;
|
|
86626
87053
|
clearAutoStopTimer();
|
|
86627
87054
|
if (chunk.includes("\x1B[6n")) child.stdin?.write("\x1B[1;1R");
|
|
86628
|
-
checkAutoApproval(chunk, (
|
|
87055
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
86629
87056
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stdout" } });
|
|
86630
87057
|
scheduleAutoStopForVerification();
|
|
86631
87058
|
});
|
|
@@ -86633,7 +87060,7 @@ async (params) => {
|
|
|
86633
87060
|
const chunk = d.toString();
|
|
86634
87061
|
stderr += chunk;
|
|
86635
87062
|
clearAutoStopTimer();
|
|
86636
|
-
checkAutoApproval(chunk, (
|
|
87063
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
86637
87064
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
86638
87065
|
scheduleAutoStopForVerification();
|
|
86639
87066
|
});
|
|
@@ -87446,59 +87873,59 @@ data: ${JSON.stringify(msg.data)}
|
|
|
87446
87873
|
// ─── Route Table ─────────────────────────────────────
|
|
87447
87874
|
routes = [
|
|
87448
87875
|
// Static routes
|
|
87449
|
-
{ method: "GET", pattern: "/api/providers", handler: (q,
|
|
87450
|
-
{ method: "GET", pattern: "/api/providers/source-config", handler: (q,
|
|
87451
|
-
{ method: "POST", pattern: "/api/providers/source-config", handler: (q,
|
|
87452
|
-
{ method: "GET", pattern: "/api/providers/versions", handler: (q,
|
|
87453
|
-
{ method: "POST", pattern: "/api/providers/reload", handler: (q,
|
|
87454
|
-
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q,
|
|
87455
|
-
{ method: "POST", pattern: "/api/cdp/click", handler: (q,
|
|
87456
|
-
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q,
|
|
87457
|
-
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q,
|
|
87458
|
-
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q,
|
|
87459
|
-
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q,
|
|
87460
|
-
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q,
|
|
87461
|
-
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q,
|
|
87462
|
-
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q,
|
|
87463
|
-
{ method: "GET", pattern: "/api/cdp/targets", handler: (q,
|
|
87464
|
-
{ method: "POST", pattern: "/api/scripts/run", handler: (q,
|
|
87465
|
-
{ method: "GET", pattern: "/api/status", handler: (q,
|
|
87466
|
-
{ method: "POST", pattern: "/api/watch/start", handler: (q,
|
|
87467
|
-
{ method: "POST", pattern: "/api/watch/stop", handler: (q,
|
|
87468
|
-
{ method: "GET", pattern: "/api/watch/events", handler: (q,
|
|
87469
|
-
{ method: "POST", pattern: "/api/scaffold", handler: (q,
|
|
87876
|
+
{ method: "GET", pattern: "/api/providers", handler: (q, s2) => this.handleListProviders(q, s2) },
|
|
87877
|
+
{ method: "GET", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleGetProviderSourceConfig(q, s2) },
|
|
87878
|
+
{ method: "POST", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleSetProviderSourceConfig(q, s2) },
|
|
87879
|
+
{ method: "GET", pattern: "/api/providers/versions", handler: (q, s2) => this.handleDetectVersions(q, s2) },
|
|
87880
|
+
{ method: "POST", pattern: "/api/providers/reload", handler: (q, s2) => this.handleReload(q, s2) },
|
|
87881
|
+
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s2) => this.handleCdpEvaluate(q, s2) },
|
|
87882
|
+
{ method: "POST", pattern: "/api/cdp/click", handler: (q, s2) => this.handleCdpClick(q, s2) },
|
|
87883
|
+
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s2) => this.handleCdpDomQuery(q, s2) },
|
|
87884
|
+
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s2) => this.handleDomInspect(q, s2) },
|
|
87885
|
+
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s2) => this.handleDomChildren(q, s2) },
|
|
87886
|
+
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s2) => this.handleDomAnalyze(q, s2) },
|
|
87887
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s2) => this.handleFindByText(q, s2) },
|
|
87888
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s2) => this.handleFindCommon(q, s2) },
|
|
87889
|
+
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s2) => this.handleScreenshot(q, s2) },
|
|
87890
|
+
{ method: "GET", pattern: "/api/cdp/targets", handler: (q, s2) => this.handleCdpTargets(q, s2) },
|
|
87891
|
+
{ method: "POST", pattern: "/api/scripts/run", handler: (q, s2) => this.handleScriptsRun(q, s2) },
|
|
87892
|
+
{ method: "GET", pattern: "/api/status", handler: (q, s2) => this.handleStatus(q, s2) },
|
|
87893
|
+
{ method: "POST", pattern: "/api/watch/start", handler: (q, s2) => this.handleWatchStart(q, s2) },
|
|
87894
|
+
{ method: "POST", pattern: "/api/watch/stop", handler: (q, s2) => this.handleWatchStop(q, s2) },
|
|
87895
|
+
{ method: "GET", pattern: "/api/watch/events", handler: (q, s2) => this.handleSSE(q, s2) },
|
|
87896
|
+
{ method: "POST", pattern: "/api/scaffold", handler: (q, s2) => this.handleScaffold(q, s2) },
|
|
87470
87897
|
// CLI Debug routes
|
|
87471
|
-
{ method: "GET", pattern: "/api/cli/status", handler: (q,
|
|
87472
|
-
{ method: "POST", pattern: "/api/cli/launch", handler: (q,
|
|
87473
|
-
{ method: "POST", pattern: "/api/cli/send", handler: (q,
|
|
87474
|
-
{ method: "POST", pattern: "/api/cli/exercise", handler: (q,
|
|
87475
|
-
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q,
|
|
87476
|
-
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q,
|
|
87477
|
-
{ method: "POST", pattern: "/api/cli/resolve", handler: (q,
|
|
87478
|
-
{ method: "POST", pattern: "/api/cli/raw", handler: (q,
|
|
87479
|
-
{ method: "POST", pattern: "/api/cli/stop", handler: (q,
|
|
87480
|
-
{ method: "GET", pattern: "/api/cli/events", handler: (q,
|
|
87481
|
-
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q,
|
|
87482
|
-
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q,
|
|
87483
|
-
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q,
|
|
87898
|
+
{ method: "GET", pattern: "/api/cli/status", handler: (q, s2) => this.handleCliStatus(q, s2) },
|
|
87899
|
+
{ method: "POST", pattern: "/api/cli/launch", handler: (q, s2) => this.handleCliLaunch(q, s2) },
|
|
87900
|
+
{ method: "POST", pattern: "/api/cli/send", handler: (q, s2) => this.handleCliSend(q, s2) },
|
|
87901
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q, s2) => this.handleCliExercise(q, s2) },
|
|
87902
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s2) => this.handleCliFixtureCapture(q, s2) },
|
|
87903
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s2) => this.handleCliFixtureReplay(q, s2) },
|
|
87904
|
+
{ method: "POST", pattern: "/api/cli/resolve", handler: (q, s2) => this.handleCliResolve(q, s2) },
|
|
87905
|
+
{ method: "POST", pattern: "/api/cli/raw", handler: (q, s2) => this.handleCliRaw(q, s2) },
|
|
87906
|
+
{ method: "POST", pattern: "/api/cli/stop", handler: (q, s2) => this.handleCliStop(q, s2) },
|
|
87907
|
+
{ method: "GET", pattern: "/api/cli/events", handler: (q, s2) => this.handleCliSSE(q, s2) },
|
|
87908
|
+
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s2, p) => this.handleCliDebug(p[0], q, s2) },
|
|
87909
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s2, p) => this.handleCliTrace(p[0], q, s2) },
|
|
87910
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s2, p) => this.handleCliFixtureList(p[0], q, s2) },
|
|
87484
87911
|
// Dynamic routes (provider :type param)
|
|
87485
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q,
|
|
87486
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q,
|
|
87487
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q,
|
|
87488
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q,
|
|
87489
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q,
|
|
87490
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q,
|
|
87491
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q,
|
|
87492
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q,
|
|
87493
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q,
|
|
87494
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q,
|
|
87495
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q,
|
|
87496
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q,
|
|
87497
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q,
|
|
87498
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q,
|
|
87499
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q,
|
|
87500
|
-
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q,
|
|
87501
|
-
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q,
|
|
87912
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s2, p) => this.handleRunScript(p[0], q, s2) },
|
|
87913
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s2, p) => this.handleListFiles(p[0], q, s2) },
|
|
87914
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleReadFile(p[0], q, s2) },
|
|
87915
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleWriteFile(p[0], q, s2) },
|
|
87916
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s2, p) => this.handleSource(p[0], q, s2) },
|
|
87917
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s2, p) => this.handleSave(p[0], q, s2) },
|
|
87918
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s2, p) => this.handleTypeAndSend(p[0], q, s2) },
|
|
87919
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s2, p) => this.handleTypeAndSendAt(p[0], q, s2) },
|
|
87920
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s2, p) => this.handleProviderConfig(p[0], q, s2) },
|
|
87921
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s2, p) => this.handleDomContext(p[0], q, s2) },
|
|
87922
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s2, p) => this.handleAutoImplement(p[0], q, s2) },
|
|
87923
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s2, p) => this.handleAutoImplCancel(p[0], q, s2) },
|
|
87924
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s2, p) => this.handleAutoImplSSE(p[0], q, s2) },
|
|
87925
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s2, p) => this.handleSpawnTest(p[0], q, s2) },
|
|
87926
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s2, p) => this.handleValidate(p[0], q, s2) },
|
|
87927
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s2, p) => this.handleAcpChat(p[0], q, s2) },
|
|
87928
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s2, p) => this.handleScriptHints(p[0], q, s2) }
|
|
87502
87929
|
];
|
|
87503
87930
|
matchRoute(method, pathname) {
|
|
87504
87931
|
for (const route of this.routes) {
|
|
@@ -88093,14 +88520,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
88093
88520
|
warnings.push(...validation.warnings);
|
|
88094
88521
|
if (config2.settings) {
|
|
88095
88522
|
for (const [key, val] of Object.entries(config2.settings)) {
|
|
88096
|
-
const
|
|
88097
|
-
if (!
|
|
88098
|
-
else if (!["boolean", "number", "string", "select"].includes(
|
|
88099
|
-
errors.push(`settings.${key}: invalid type '${
|
|
88100
|
-
if (
|
|
88101
|
-
if (
|
|
88102
|
-
errors.push(`settings.${key}: min (${
|
|
88103
|
-
if (
|
|
88523
|
+
const s2 = val;
|
|
88524
|
+
if (!s2.type) errors.push(`settings.${key}: missing type`);
|
|
88525
|
+
else if (!["boolean", "number", "string", "select"].includes(s2.type))
|
|
88526
|
+
errors.push(`settings.${key}: invalid type '${s2.type}'`);
|
|
88527
|
+
if (s2.default === void 0) warnings.push(`settings.${key}: no default value`);
|
|
88528
|
+
if (s2.type === "number" && s2.min !== void 0 && s2.max !== void 0 && s2.min > s2.max)
|
|
88529
|
+
errors.push(`settings.${key}: min (${s2.min}) > max (${s2.max})`);
|
|
88530
|
+
if (s2.type === "select" && (!s2.options || !Array.isArray(s2.options) || s2.options.length === 0))
|
|
88104
88531
|
errors.push(`settings.${key}: select type requires options[]`);
|
|
88105
88532
|
}
|
|
88106
88533
|
}
|