@adhdev/daemon-standalone 0.9.82-rc.354 → 0.9.82-rc.355
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +569 -201
- 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 ? "a45106605e2ae1c10c0bc6cbe48c2cac4e862ded" : void 0) ?? "unknown";
|
|
30040
|
+
const commitShort = readInjected(true ? "a4510660" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30041
|
+
const version2 = readInjected(true ? "0.9.82-rc.355" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30042
|
+
const builtAt = readInjected(true ? "2026-06-22T15:22:12.689Z" : 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) {
|
|
@@ -49414,10 +49583,10 @@ ${lastSnapshot}`;
|
|
|
49414
49583
|
return !!raw && typeof raw === "object" && raw.$schema === "adhdev:cli/spec@4";
|
|
49415
49584
|
}
|
|
49416
49585
|
function initialState(spec) {
|
|
49417
|
-
return spec.states.find((
|
|
49586
|
+
return spec.states.find((s2) => s2.initial) ?? spec.states[0];
|
|
49418
49587
|
}
|
|
49419
49588
|
function stateById(spec, id) {
|
|
49420
|
-
return spec.states.find((
|
|
49589
|
+
return spec.states.find((s2) => s2.id === id);
|
|
49421
49590
|
}
|
|
49422
49591
|
function outgoingTransitions(spec, stateId) {
|
|
49423
49592
|
const matches = spec.transitions.filter((t) => {
|
|
@@ -49504,7 +49673,17 @@ ${lastSnapshot}`;
|
|
|
49504
49673
|
const result = evaluateCondition(cond, sections, fullScreen, cursor, prevLines, legacyTrace, stateId);
|
|
49505
49674
|
const kind = isRegex(cond) ? "regex" : "changed";
|
|
49506
49675
|
const detail = isRegex(cond) ? `${cond.section ?? "*"}~/${cond.matches}/` : `cursor_above=${cond.cursor_above} changed=${cond.changed}`;
|
|
49507
|
-
|
|
49676
|
+
let matchedText;
|
|
49677
|
+
if (result && isRegex(cond)) {
|
|
49678
|
+
try {
|
|
49679
|
+
const hay = sectionText(sections, cond.section, fullScreen);
|
|
49680
|
+
const re = new RegExp(cond.matches, cond.flags ?? "i");
|
|
49681
|
+
const m = re.exec(hay);
|
|
49682
|
+
if (m && m[0]) matchedText = m[0].replace(/\s+/g, " ").trim().slice(0, 160);
|
|
49683
|
+
} catch {
|
|
49684
|
+
}
|
|
49685
|
+
}
|
|
49686
|
+
return matchedText ? { kind, result, detail, matchedText } : { kind, result, detail };
|
|
49508
49687
|
}
|
|
49509
49688
|
return { kind: "all", result: false, detail: "unknown condition" };
|
|
49510
49689
|
}
|
|
@@ -49617,17 +49796,17 @@ ${lastSnapshot}`;
|
|
|
49617
49796
|
}
|
|
49618
49797
|
const ids = /* @__PURE__ */ new Set();
|
|
49619
49798
|
let initialCount = 0;
|
|
49620
|
-
for (const [i,
|
|
49621
|
-
if (!
|
|
49799
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
49800
|
+
if (!s2.id) {
|
|
49622
49801
|
errs.push(`states[${i}].id is required`);
|
|
49623
49802
|
continue;
|
|
49624
49803
|
}
|
|
49625
|
-
if (ids.has(
|
|
49626
|
-
ids.add(
|
|
49627
|
-
if (!
|
|
49628
|
-
if (
|
|
49629
|
-
if (
|
|
49630
|
-
errs.push(`states[${i}].status "${
|
|
49804
|
+
if (ids.has(s2.id)) errs.push(`states[${i}].id "${s2.id}" is duplicated`);
|
|
49805
|
+
ids.add(s2.id);
|
|
49806
|
+
if (!s2.label) errs.push(`states[${i}].label is required`);
|
|
49807
|
+
if (s2.initial) initialCount += 1;
|
|
49808
|
+
if (s2.status && !["idle", "generating", "approval"].includes(s2.status)) {
|
|
49809
|
+
errs.push(`states[${i}].status "${s2.status}" must be idle|generating|approval`);
|
|
49631
49810
|
}
|
|
49632
49811
|
}
|
|
49633
49812
|
if (initialCount === 0) errs.push("exactly one state must have initial:true (none found)");
|
|
@@ -49643,10 +49822,10 @@ ${lastSnapshot}`;
|
|
|
49643
49822
|
else if (!ids.has(t.to)) errs.push(`transitions[${i}].to references unknown state "${t.to}"`);
|
|
49644
49823
|
if (t.when) errs.push(...validateCondition(t.when, sectionIds, `transitions[${i}].when`));
|
|
49645
49824
|
}
|
|
49646
|
-
for (const [i,
|
|
49647
|
-
const sec =
|
|
49825
|
+
for (const [i, s2] of spec.states.entries()) {
|
|
49826
|
+
const sec = s2.extract?.title?.section;
|
|
49648
49827
|
if (sec && !sectionIds.has(sec)) errs.push(`states[${i}].extract.title.section "${sec}" unknown`);
|
|
49649
|
-
const bsec =
|
|
49828
|
+
const bsec = s2.extract?.buttons?.section;
|
|
49650
49829
|
if (bsec && !sectionIds.has(bsec)) errs.push(`states[${i}].extract.buttons.section "${bsec}" unknown`);
|
|
49651
49830
|
}
|
|
49652
49831
|
return errs;
|
|
@@ -62273,10 +62452,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62273
62452
|
const path422 = require("path");
|
|
62274
62453
|
const { spawnSync: spawnSync2 } = require("child_process");
|
|
62275
62454
|
const file2 = ext.loadExternalSources();
|
|
62276
|
-
if (file2.sources.some((
|
|
62455
|
+
if (file2.sources.some((s2) => s2.name === requestedName)) {
|
|
62277
62456
|
return { success: false, error: `source name "${requestedName}" is already registered` };
|
|
62278
62457
|
}
|
|
62279
|
-
if (file2.sources.some((
|
|
62458
|
+
if (file2.sources.some((s2) => s2.url === url2 && s2.ref === ref)) {
|
|
62280
62459
|
return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
|
|
62281
62460
|
}
|
|
62282
62461
|
const sourceDir = path422.join(ext.externalRoot(), requestedName);
|
|
@@ -62338,7 +62517,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62338
62517
|
const fs322 = require("fs");
|
|
62339
62518
|
const path422 = require("path");
|
|
62340
62519
|
const file2 = ext.loadExternalSources();
|
|
62341
|
-
const match = file2.sources.find((
|
|
62520
|
+
const match = file2.sources.find((s2) => s2.name === name);
|
|
62342
62521
|
if (!match) return { success: false, error: `source "${name}" not registered` };
|
|
62343
62522
|
const sourceDir = path422.join(ext.externalRoot(), name);
|
|
62344
62523
|
if (fs322.existsSync(sourceDir)) {
|
|
@@ -62350,7 +62529,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62350
62529
|
}
|
|
62351
62530
|
ext.saveExternalSources({
|
|
62352
62531
|
schema: 1,
|
|
62353
|
-
sources: file2.sources.filter((
|
|
62532
|
+
sources: file2.sources.filter((s2) => s2.name !== name)
|
|
62354
62533
|
});
|
|
62355
62534
|
const active = ext.loadProvidersActive();
|
|
62356
62535
|
const filteredActive = {};
|
|
@@ -62374,10 +62553,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62374
62553
|
const file2 = ext.loadExternalSources();
|
|
62375
62554
|
const inventory = ext.inventoryExternalSources();
|
|
62376
62555
|
const active = ext.loadProvidersActive();
|
|
62377
|
-
const sources = file2.sources.map((
|
|
62378
|
-
const inv = inventory.find((e) => e.sourceName ===
|
|
62556
|
+
const sources = file2.sources.map((s2) => {
|
|
62557
|
+
const inv = inventory.find((e) => e.sourceName === s2.name);
|
|
62379
62558
|
return {
|
|
62380
|
-
...
|
|
62559
|
+
...s2,
|
|
62381
62560
|
providers: inv?.providers ?? {}
|
|
62382
62561
|
};
|
|
62383
62562
|
});
|
|
@@ -62544,6 +62723,21 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62544
62723
|
var path21 = __toESM2(require("path"));
|
|
62545
62724
|
init_terminal_screen();
|
|
62546
62725
|
var import_session_host_core6 = require_dist();
|
|
62726
|
+
var MAX_PTY_EVENTS = 300;
|
|
62727
|
+
var EVENT_CONTENT_CAP = 240;
|
|
62728
|
+
function escapeControl(text) {
|
|
62729
|
+
return String(text).replace(/[\x00-\x1f\x7f]/g, (ch) => {
|
|
62730
|
+
const code = ch.charCodeAt(0);
|
|
62731
|
+
if (ch === "\r") return "\\r";
|
|
62732
|
+
if (ch === "\n") return "\\n";
|
|
62733
|
+
if (ch === " ") return "\\t";
|
|
62734
|
+
if (code === 27) return "\\x1b";
|
|
62735
|
+
return "\\x" + code.toString(16).padStart(2, "0");
|
|
62736
|
+
});
|
|
62737
|
+
}
|
|
62738
|
+
function capPreview(text) {
|
|
62739
|
+
return text.length > EVENT_CONTENT_CAP ? text.slice(0, EVENT_CONTENT_CAP) + `\u2026(+${text.length - EVENT_CONTENT_CAP})` : text;
|
|
62740
|
+
}
|
|
62547
62741
|
var TerminalAdapter = class {
|
|
62548
62742
|
constructor(opts, handlers) {
|
|
62549
62743
|
this.opts = opts;
|
|
@@ -62570,6 +62764,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62570
62764
|
screenTimer = null;
|
|
62571
62765
|
tickTimer = null;
|
|
62572
62766
|
lastScreen = "";
|
|
62767
|
+
/** Debug-only ring buffer of PTY input/output/resize/cursor events. */
|
|
62768
|
+
events = [];
|
|
62769
|
+
lastCursorKey = "";
|
|
62573
62770
|
start() {
|
|
62574
62771
|
const env2 = this.opts.envIsComplete ? this.opts.env ?? {} : { ...process.env, ...this.opts.env ?? {} };
|
|
62575
62772
|
this.pty = this.factory.spawn(this.opts.binary, this.opts.args ?? [], {
|
|
@@ -62578,10 +62775,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62578
62775
|
cols: this.cols,
|
|
62579
62776
|
rows: this.rows
|
|
62580
62777
|
});
|
|
62778
|
+
this.recordEvent("spawn", `${this.opts.binary} (${this.cols}x${this.rows})`);
|
|
62581
62779
|
this.handlers.init?.({ pid: this.pty.pid });
|
|
62582
62780
|
this.pty.onData((chunk) => this.onChunk(chunk));
|
|
62583
62781
|
this.pty.onExit((info) => {
|
|
62584
62782
|
this.stopTimers();
|
|
62783
|
+
this.recordEvent("exit", `exitCode=${typeof info.exitCode === "number" ? info.exitCode : 0}`);
|
|
62585
62784
|
this.handlers.on_exit?.({ exitCode: typeof info.exitCode === "number" ? info.exitCode : 0 });
|
|
62586
62785
|
this.pty = null;
|
|
62587
62786
|
});
|
|
@@ -62592,6 +62791,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62592
62791
|
resize(cols, rows) {
|
|
62593
62792
|
this.cols = cols;
|
|
62594
62793
|
this.rows = rows;
|
|
62794
|
+
this.recordEvent("resize", `${cols}x${rows}`);
|
|
62595
62795
|
this.pty?.resize(cols, rows);
|
|
62596
62796
|
this.screen.resize(rows, cols);
|
|
62597
62797
|
}
|
|
@@ -62612,8 +62812,21 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62612
62812
|
return { row: pos.row, col: pos.col };
|
|
62613
62813
|
}
|
|
62614
62814
|
send_keys(text) {
|
|
62815
|
+
this.recordEvent("input", capPreview(escapeControl(text)), text.length);
|
|
62615
62816
|
this.pty?.write(text);
|
|
62616
62817
|
}
|
|
62818
|
+
/** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
|
|
62819
|
+
* first. Pure observation — never consulted by the FSM. */
|
|
62820
|
+
getEventTimeline(limit = MAX_PTY_EVENTS) {
|
|
62821
|
+
const n = Math.max(0, Math.min(limit, this.events.length));
|
|
62822
|
+
return this.events.slice(this.events.length - n);
|
|
62823
|
+
}
|
|
62824
|
+
recordEvent(kind, content, bytes) {
|
|
62825
|
+
const ev = { ts: Date.now(), kind, content };
|
|
62826
|
+
if (typeof bytes === "number") ev.bytes = bytes;
|
|
62827
|
+
this.events.push(ev);
|
|
62828
|
+
if (this.events.length > MAX_PTY_EVENTS) this.events.splice(0, this.events.length - MAX_PTY_EVENTS);
|
|
62829
|
+
}
|
|
62617
62830
|
kill() {
|
|
62618
62831
|
this.stopTimers();
|
|
62619
62832
|
try {
|
|
@@ -62624,6 +62837,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62624
62837
|
this.screen.dispose();
|
|
62625
62838
|
}
|
|
62626
62839
|
onChunk(chunk) {
|
|
62840
|
+
this.recordEvent("output", capPreview(escapeControl(chunk)), chunk.length);
|
|
62627
62841
|
try {
|
|
62628
62842
|
this.handlers.on_pty_data?.(chunk);
|
|
62629
62843
|
} catch {
|
|
@@ -62633,6 +62847,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62633
62847
|
this.screenTimer = setTimeout(() => {
|
|
62634
62848
|
this.screenTimer = null;
|
|
62635
62849
|
const snap = this.computeScreen();
|
|
62850
|
+
const cur = this.screen.getCursorPosition();
|
|
62851
|
+
const curKey = `${cur.row},${cur.col}`;
|
|
62852
|
+
if (curKey !== this.lastCursorKey) {
|
|
62853
|
+
this.lastCursorKey = curKey;
|
|
62854
|
+
this.recordEvent("cursor", `(${cur.row},${cur.col})`);
|
|
62855
|
+
}
|
|
62636
62856
|
if (snap === this.lastScreen) return;
|
|
62637
62857
|
this.lastScreen = snap;
|
|
62638
62858
|
try {
|
|
@@ -62711,20 +62931,40 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62711
62931
|
}
|
|
62712
62932
|
}
|
|
62713
62933
|
init_logger();
|
|
62714
|
-
function countNewlines(
|
|
62934
|
+
function countNewlines(s2) {
|
|
62715
62935
|
let n = 0;
|
|
62716
|
-
for (let i = 0; i <
|
|
62936
|
+
for (let i = 0; i < s2.length; i += 1) if (s2.charCodeAt(i) === 10) n += 1;
|
|
62717
62937
|
return n;
|
|
62718
62938
|
}
|
|
62719
62939
|
var SUBMIT_DELAY_FLOOR_MS = 200;
|
|
62720
62940
|
var WIN32_SUBMIT_RESEND_GAP_MS = 350;
|
|
62721
62941
|
var WIN32_SUBMIT_MAX_RESENDS = 14;
|
|
62942
|
+
var WIN32_SUBMIT_SETTLE_MS = 500;
|
|
62943
|
+
var WIN32_SUBMIT_MAX_SETTLE_WAIT_MS = 1e4;
|
|
62944
|
+
var WIN32_SUBMIT_SETTLE_POLL_MS = 120;
|
|
62945
|
+
var WIN32_PTY_WRITE_CHUNK_CHARS = 1024;
|
|
62946
|
+
var WIN32_PTY_WRITE_CHUNK_GAP_MS = 8;
|
|
62722
62947
|
function resolveSubmitDelayMs(specBeforeSubmit, text) {
|
|
62723
62948
|
const lines = countNewlines(text);
|
|
62724
62949
|
const linesBonus = Math.min(800, lines * 80);
|
|
62725
62950
|
const spec = typeof specBeforeSubmit === "number" && specBeforeSubmit > 0 ? specBeforeSubmit : 0;
|
|
62726
62951
|
return Math.max(spec, SUBMIT_DELAY_FLOOR_MS + linesBonus);
|
|
62727
62952
|
}
|
|
62953
|
+
function chunkPreservingSurrogates(text, size) {
|
|
62954
|
+
const chunks = [];
|
|
62955
|
+
let offset = 0;
|
|
62956
|
+
while (offset < text.length) {
|
|
62957
|
+
let end = Math.min(text.length, offset + size);
|
|
62958
|
+
if (end < text.length) {
|
|
62959
|
+
const code = text.charCodeAt(end - 1);
|
|
62960
|
+
if (code >= 55296 && code <= 56319) end -= 1;
|
|
62961
|
+
}
|
|
62962
|
+
if (end <= offset) end = Math.min(text.length, offset + size);
|
|
62963
|
+
chunks.push(text.slice(offset, end));
|
|
62964
|
+
offset = end;
|
|
62965
|
+
}
|
|
62966
|
+
return chunks;
|
|
62967
|
+
}
|
|
62728
62968
|
function guessExt(mime) {
|
|
62729
62969
|
if (/png/i.test(mime)) return ".png";
|
|
62730
62970
|
if (/jpe?g/i.test(mime)) return ".jpg";
|
|
@@ -62740,7 +62980,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62740
62980
|
this.buildAdapterOpts(),
|
|
62741
62981
|
{
|
|
62742
62982
|
init: () => this.emitInitialState(),
|
|
62743
|
-
on_pty_data: (chunk) =>
|
|
62983
|
+
on_pty_data: (chunk) => {
|
|
62984
|
+
this.lastPtyDataAt = Date.now();
|
|
62985
|
+
this.emit({ kind: "pty_data", chunk });
|
|
62986
|
+
},
|
|
62744
62987
|
on_screen_changed: () => this.reevaluate(),
|
|
62745
62988
|
on_exit: ({ exitCode }) => this.handleExit(exitCode)
|
|
62746
62989
|
}
|
|
@@ -62774,6 +63017,16 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62774
63017
|
* WIN32_SUBMIT_* and scheduleWin32Submit). Re-arms itself until the FSM
|
|
62775
63018
|
* leaves idle (submitted) or the resend budget is spent. */
|
|
62776
63019
|
win32SubmitTimer = null;
|
|
63020
|
+
/** Wall-clock (ms) of the most recent raw PTY output chunk. Advances on every
|
|
63021
|
+
* on_pty_data — including the echo of text written into the composer — so the
|
|
63022
|
+
* win32 submit settle-gate can tell when input has finished landing. */
|
|
63023
|
+
lastPtyDataAt = 0;
|
|
63024
|
+
/** Wall-clock (ms) of the most recent win32 message-body input write. Bridges
|
|
63025
|
+
* the gap between writing a chunk and its echo so the settle-gate does not
|
|
63026
|
+
* declare "quiet" mid-write. */
|
|
63027
|
+
lastWin32WriteAt = 0;
|
|
63028
|
+
/** Pending paced chunk-write timer for a large win32 body (see writeWin32Body). */
|
|
63029
|
+
win32WriteTimer = null;
|
|
62777
63030
|
currentEval = null;
|
|
62778
63031
|
stateHistory = [];
|
|
62779
63032
|
prevStateAt = 0;
|
|
@@ -62894,6 +63147,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62894
63147
|
clearTimeout(this.win32SubmitTimer);
|
|
62895
63148
|
this.win32SubmitTimer = null;
|
|
62896
63149
|
}
|
|
63150
|
+
if (this.win32WriteTimer) {
|
|
63151
|
+
clearTimeout(this.win32WriteTimer);
|
|
63152
|
+
this.win32WriteTimer = null;
|
|
63153
|
+
}
|
|
62897
63154
|
this.specWatcher?.close();
|
|
62898
63155
|
this.adapter.kill();
|
|
62899
63156
|
}
|
|
@@ -62924,11 +63181,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
62924
63181
|
getFsmSnapshotHistory() {
|
|
62925
63182
|
return this.fsmSnapshotHistory;
|
|
62926
63183
|
}
|
|
63184
|
+
/** Debug-only PTY input/output/resize/cursor timeline from the adapter. */
|
|
63185
|
+
getEventTimeline(limit) {
|
|
63186
|
+
return this.adapter.getEventTimeline(limit);
|
|
63187
|
+
}
|
|
62927
63188
|
getSections() {
|
|
62928
63189
|
try {
|
|
62929
63190
|
const screen = this.adapter.snapshot();
|
|
62930
63191
|
const lines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
|
|
62931
|
-
return resolveSections(this.spec.sections ?? {}, lines).map((
|
|
63192
|
+
return resolveSections(this.spec.sections ?? {}, lines).map((s2) => ({ id: s2.id, text: s2.text }));
|
|
62932
63193
|
} catch {
|
|
62933
63194
|
return null;
|
|
62934
63195
|
}
|
|
@@ -63306,7 +63567,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63306
63567
|
const perChar = sm.delay_ms_per_char ?? 0;
|
|
63307
63568
|
const beforeSubmit = resolveSubmitDelayMs(sm.delay_ms_before_submit, text);
|
|
63308
63569
|
if (process.platform === "win32") {
|
|
63309
|
-
this.
|
|
63570
|
+
this.writeWin32Body(text);
|
|
63310
63571
|
this.scheduleWin32Submit(sm.submit_key, beforeSubmit);
|
|
63311
63572
|
return;
|
|
63312
63573
|
}
|
|
@@ -63332,20 +63593,72 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63332
63593
|
const st = stateById(this.spec, this.currentStateId);
|
|
63333
63594
|
return st ? statusForState(st) : "idle";
|
|
63334
63595
|
}
|
|
63596
|
+
/** Record a win32 body write so the settle-gate counts it as input activity
|
|
63597
|
+
* even before the echo arrives. */
|
|
63598
|
+
markWin32Write() {
|
|
63599
|
+
this.lastWin32WriteAt = Date.now();
|
|
63600
|
+
}
|
|
63601
|
+
/** Most recent win32 input activity — a write we issued OR a PTY output chunk
|
|
63602
|
+
* (echo). The submit settle-gate waits for this to go quiet. */
|
|
63603
|
+
lastWin32InputActivityAt() {
|
|
63604
|
+
return Math.max(this.lastPtyDataAt, this.lastWin32WriteAt);
|
|
63605
|
+
}
|
|
63606
|
+
/**
|
|
63607
|
+
* Write the message body to the PTY for win32, paced into bounded chunks. A
|
|
63608
|
+
* single unbounded ConPTY write can overflow the input pipe and drop leading
|
|
63609
|
+
* bytes; splitting it with a short inter-chunk gap keeps the console input
|
|
63610
|
+
* buffer from overflowing. Small bodies still go out in a single write. Each
|
|
63611
|
+
* chunk advances lastWin32WriteAt so the submit settle-gate keeps waiting until
|
|
63612
|
+
* the final chunk is out and echoed.
|
|
63613
|
+
*/
|
|
63614
|
+
writeWin32Body(text) {
|
|
63615
|
+
if (this.win32WriteTimer) {
|
|
63616
|
+
clearTimeout(this.win32WriteTimer);
|
|
63617
|
+
this.win32WriteTimer = null;
|
|
63618
|
+
}
|
|
63619
|
+
if (text.length <= WIN32_PTY_WRITE_CHUNK_CHARS) {
|
|
63620
|
+
this.markWin32Write();
|
|
63621
|
+
this.adapter.send_keys(text);
|
|
63622
|
+
return;
|
|
63623
|
+
}
|
|
63624
|
+
const chunks = chunkPreservingSurrogates(text, WIN32_PTY_WRITE_CHUNK_CHARS);
|
|
63625
|
+
let idx = 0;
|
|
63626
|
+
const writeNext = () => {
|
|
63627
|
+
this.win32WriteTimer = null;
|
|
63628
|
+
if (idx >= chunks.length) return;
|
|
63629
|
+
this.markWin32Write();
|
|
63630
|
+
this.adapter.send_keys(chunks[idx]);
|
|
63631
|
+
idx += 1;
|
|
63632
|
+
if (idx < chunks.length) {
|
|
63633
|
+
this.win32WriteTimer = setTimeout(writeNext, WIN32_PTY_WRITE_CHUNK_GAP_MS);
|
|
63634
|
+
}
|
|
63635
|
+
};
|
|
63636
|
+
writeNext();
|
|
63637
|
+
}
|
|
63335
63638
|
/**
|
|
63336
|
-
* win32
|
|
63337
|
-
*
|
|
63338
|
-
*
|
|
63339
|
-
*
|
|
63340
|
-
*
|
|
63341
|
-
*
|
|
63342
|
-
*
|
|
63639
|
+
* win32 submit. Two phases:
|
|
63640
|
+
*
|
|
63641
|
+
* Phase 1 (settle-gate): hold the first CR until the PTY output has been quiet
|
|
63642
|
+
* for WIN32_SUBMIT_SETTLE_MS after the last input write — i.e. the full
|
|
63643
|
+
* (possibly multi-KB / multiline) body has finished arriving in the composer
|
|
63644
|
+
* and echoing. Honors an initial minimum delay and is bounded by
|
|
63645
|
+
* WIN32_SUBMIT_MAX_SETTLE_WAIT_MS so a noisy screen can never hang the submit.
|
|
63646
|
+
* This is what stops a long message from being submitted half-arrived (its
|
|
63647
|
+
* leading lines lost). A short message settles almost immediately.
|
|
63648
|
+
*
|
|
63649
|
+
* Phase 2 (verified resend — unchanged): send the submit key, wait a gap, and
|
|
63650
|
+
* if the FSM is still 'idle' (the CR was absorbed as a multiline-paste
|
|
63651
|
+
* newline) resend, up to WIN32_SUBMIT_MAX_RESENDS. The first CR always fires
|
|
63652
|
+
* (a stale/edge status never suppresses it); resends are gated on still being
|
|
63653
|
+
* idle and stop the instant the agent leaves idle (submitted → generating /
|
|
63654
|
+
* approval). This preserves the win32 lone-CR-swallow handling.
|
|
63343
63655
|
*/
|
|
63344
63656
|
scheduleWin32Submit(submitKey, initialDelayMs) {
|
|
63345
63657
|
if (this.win32SubmitTimer) {
|
|
63346
63658
|
clearTimeout(this.win32SubmitTimer);
|
|
63347
63659
|
this.win32SubmitTimer = null;
|
|
63348
63660
|
}
|
|
63661
|
+
const startedAt = Date.now();
|
|
63349
63662
|
const fire = (attempt) => {
|
|
63350
63663
|
this.win32SubmitTimer = null;
|
|
63351
63664
|
this.adapter.send_keys(submitKey);
|
|
@@ -63358,8 +63671,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63358
63671
|
fire(attempt + 1);
|
|
63359
63672
|
}, WIN32_SUBMIT_RESEND_GAP_MS);
|
|
63360
63673
|
};
|
|
63361
|
-
|
|
63362
|
-
|
|
63674
|
+
const waitForSettle = () => {
|
|
63675
|
+
this.win32SubmitTimer = null;
|
|
63676
|
+
const now = Date.now();
|
|
63677
|
+
const quietFor = now - this.lastWin32InputActivityAt();
|
|
63678
|
+
const waited = now - startedAt;
|
|
63679
|
+
if (quietFor >= WIN32_SUBMIT_SETTLE_MS || waited >= WIN32_SUBMIT_MAX_SETTLE_WAIT_MS) {
|
|
63680
|
+
fire(0);
|
|
63681
|
+
return;
|
|
63682
|
+
}
|
|
63683
|
+
const recheckIn = Math.min(WIN32_SUBMIT_SETTLE_MS - quietFor, WIN32_SUBMIT_SETTLE_POLL_MS);
|
|
63684
|
+
this.win32SubmitTimer = setTimeout(waitForSettle, Math.max(recheckIn, 30));
|
|
63685
|
+
};
|
|
63686
|
+
if (initialDelayMs > 0) this.win32SubmitTimer = setTimeout(waitForSettle, initialDelayMs);
|
|
63687
|
+
else waitForSettle();
|
|
63363
63688
|
}
|
|
63364
63689
|
handleClickControl(controlId, payload) {
|
|
63365
63690
|
const ctl = (this.spec.control_bar ?? []).find((c) => c.id === controlId);
|
|
@@ -63472,7 +63797,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63472
63797
|
return out;
|
|
63473
63798
|
}
|
|
63474
63799
|
function flattenCond(c, out, depth) {
|
|
63475
|
-
|
|
63800
|
+
const matched = c.matchedText ? ` matched=${JSON.stringify(c.matchedText)}` : "";
|
|
63801
|
+
out.push(`${" ".repeat(depth)}${c.kind} ${c.detail} = ${c.result}${c.remainingMs ? ` (${c.remainingMs}ms left)` : ""}${matched}`);
|
|
63476
63802
|
for (const child of c.children ?? []) flattenCond(child, out, depth + 1);
|
|
63477
63803
|
}
|
|
63478
63804
|
function findStable(c) {
|
|
@@ -64188,8 +64514,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64188
64514
|
}
|
|
64189
64515
|
return null;
|
|
64190
64516
|
}
|
|
64191
|
-
function oneLine(
|
|
64192
|
-
const flat =
|
|
64517
|
+
function oneLine(s2, max) {
|
|
64518
|
+
const flat = s2.replace(/\s+/g, " ").trim();
|
|
64193
64519
|
return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
|
|
64194
64520
|
}
|
|
64195
64521
|
function parseTimestamp(v) {
|
|
@@ -64209,10 +64535,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64209
64535
|
return null;
|
|
64210
64536
|
}
|
|
64211
64537
|
function normalizeRole(r) {
|
|
64212
|
-
const
|
|
64213
|
-
if (
|
|
64214
|
-
if (
|
|
64215
|
-
if (
|
|
64538
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
64539
|
+
if (s2 === "user" || s2 === "human" || s2 === "user_explicit") return "user";
|
|
64540
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
64541
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
64216
64542
|
return "system";
|
|
64217
64543
|
}
|
|
64218
64544
|
function stringifyContent(v) {
|
|
@@ -64260,18 +64586,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64260
64586
|
return (record2) => ors.some((ands) => ands.every((t) => evalTerm(t, record2)));
|
|
64261
64587
|
}
|
|
64262
64588
|
function parseTerm(src) {
|
|
64263
|
-
let
|
|
64589
|
+
let s2 = src.trim();
|
|
64264
64590
|
let negate = false;
|
|
64265
|
-
if (
|
|
64591
|
+
if (s2.startsWith("!")) {
|
|
64266
64592
|
negate = true;
|
|
64267
|
-
|
|
64593
|
+
s2 = s2.slice(1).trim();
|
|
64268
64594
|
}
|
|
64269
|
-
const fnMatch =
|
|
64595
|
+
const fnMatch = s2.match(/^(startsWith|endsWith|contains)\s*\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);
|
|
64270
64596
|
if (fnMatch) {
|
|
64271
64597
|
const [, op2, pathExpr, litExpr] = fnMatch;
|
|
64272
64598
|
return { path: pathExpr, op: op2, lit: parseLiteral(litExpr), negate };
|
|
64273
64599
|
}
|
|
64274
|
-
const opMatch =
|
|
64600
|
+
const opMatch = s2.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
|
|
64275
64601
|
if (!opMatch) return null;
|
|
64276
64602
|
const [, lhs, op, rhsRaw] = opMatch;
|
|
64277
64603
|
return { path: lhs.trim(), op, lit: parseLiteral(rhsRaw.trim()), negate };
|
|
@@ -64701,7 +65027,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64701
65027
|
try {
|
|
64702
65028
|
const sections = this.driver.getSections();
|
|
64703
65029
|
if (sectionId && sections) {
|
|
64704
|
-
const hit = sections.find((
|
|
65030
|
+
const hit = sections.find((s2) => s2.id === sectionId);
|
|
64705
65031
|
if (hit) return hit.text;
|
|
64706
65032
|
}
|
|
64707
65033
|
return this.driver.getScreen();
|
|
@@ -64716,7 +65042,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64716
65042
|
screen = this.driver.snapshot();
|
|
64717
65043
|
const driverSections = this.driver.getSections?.();
|
|
64718
65044
|
if (driverSections) {
|
|
64719
|
-
sections = Object.fromEntries(driverSections.map((
|
|
65045
|
+
sections = Object.fromEntries(driverSections.map((s2) => [s2.id, s2.text]));
|
|
64720
65046
|
} else {
|
|
64721
65047
|
sections = this.readCurrentScreenSections(screen);
|
|
64722
65048
|
}
|
|
@@ -64762,6 +65088,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64762
65088
|
// answers "why did this rule fire" after the fact, unlike the live
|
|
64763
65089
|
// `fsm` field which only reflects the current instant.
|
|
64764
65090
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
65091
|
+
// PTY input/output/resize/cursor event timeline (debug-only) so the
|
|
65092
|
+
// snapshot shows what we typed / what the PTY printed around each
|
|
65093
|
+
// status transition. Null for drivers without the timeline.
|
|
65094
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
64765
65095
|
// Extended fields
|
|
64766
65096
|
name: this.cliName,
|
|
64767
65097
|
status: this.getStatus().status,
|
|
@@ -65126,6 +65456,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
65126
65456
|
// v4 FSM transition snapshot history — the captured pre-transition
|
|
65127
65457
|
// evaluation table at each transition (null for v3 specs).
|
|
65128
65458
|
fsmHistory: this.driver.getFsmSnapshotHistory?.() ?? null,
|
|
65459
|
+
// PTY input/output/resize/cursor event timeline (debug-only).
|
|
65460
|
+
eventTimeline: this.driver.getEventTimeline?.() ?? null,
|
|
65129
65461
|
messages,
|
|
65130
65462
|
committedMessages: messages
|
|
65131
65463
|
};
|
|
@@ -65166,6 +65498,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
65166
65498
|
return new ProviderCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFactory);
|
|
65167
65499
|
}
|
|
65168
65500
|
init_logger();
|
|
65501
|
+
init_mesh_event_trace();
|
|
65169
65502
|
init_control_effects();
|
|
65170
65503
|
init_approval_utils();
|
|
65171
65504
|
init_provider_patch_state();
|
|
@@ -66209,6 +66542,23 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66209
66542
|
if (this.completedDebounceTimer) clearTimeout(this.completedDebounceTimer);
|
|
66210
66543
|
this.completedDebounceTimer = setTimeout(() => this.flushCompletedDebounceIfFinalized(), delayMs);
|
|
66211
66544
|
}
|
|
66545
|
+
// EVTTRACE (observation-only): is this a mesh worker session whose completion
|
|
66546
|
+
// events must route to a coordinator? Used purely to gate trace logging so a
|
|
66547
|
+
// non-mesh CLI session's completions don't add EvtTrace noise. No decision logic.
|
|
66548
|
+
isMeshWorkerSession() {
|
|
66549
|
+
return !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.meshNodeId || this.settings.launchedByCoordinator);
|
|
66550
|
+
}
|
|
66551
|
+
// EVTTRACE correlation context for this session's completion lifecycle. taskId is
|
|
66552
|
+
// the primary grep anchor; instanceId is the session fallback.
|
|
66553
|
+
meshTraceCtx(event = "agent:generating_completed") {
|
|
66554
|
+
return {
|
|
66555
|
+
taskId: this.settings.meshActiveTaskId,
|
|
66556
|
+
sessionId: this.instanceId,
|
|
66557
|
+
nodeId: this.settings.meshNodeId,
|
|
66558
|
+
meshId: this.settings.meshNodeFor,
|
|
66559
|
+
event
|
|
66560
|
+
};
|
|
66561
|
+
}
|
|
66212
66562
|
flushCompletedDebounceIfFinalized() {
|
|
66213
66563
|
const pending = this.completedDebouncePending;
|
|
66214
66564
|
if (!pending) {
|
|
@@ -66229,24 +66579,33 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66229
66579
|
if (block2) {
|
|
66230
66580
|
const blockReason = block2.reason;
|
|
66231
66581
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
66232
|
-
|
|
66233
|
-
|
|
66582
|
+
const isTranscriptEvidenceGate = block2.allowTimeout === true;
|
|
66583
|
+
LOG2.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} allowTimeout=${isTranscriptEvidenceGate} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
|
|
66584
|
+
if (!isTranscriptEvidenceGate && (block2.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS)) {
|
|
66234
66585
|
if (pending.loggedBlockReason !== blockReason) {
|
|
66235
66586
|
LOG2.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
|
|
66587
|
+
if (this.isMeshWorkerSession()) {
|
|
66588
|
+
traceMeshEventDrop("completion_gate_hold", this.meshTraceCtx(), `${blockReason} waited=${waitedMs}ms`);
|
|
66589
|
+
}
|
|
66236
66590
|
pending.loggedBlockReason = blockReason;
|
|
66237
66591
|
}
|
|
66238
66592
|
this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
|
|
66239
66593
|
return;
|
|
66240
66594
|
}
|
|
66595
|
+
const emittedAfterFinalizationTimeout = waitedMs >= COMPLETED_FINALIZATION_MAX_WAIT_MS;
|
|
66241
66596
|
const completionDiagnostic = this.buildCompletedFinalizationDiagnostic({
|
|
66242
66597
|
blockReason,
|
|
66243
66598
|
latestStatus,
|
|
66244
66599
|
latestVisibleStatus,
|
|
66245
66600
|
waitedMs,
|
|
66246
66601
|
pending,
|
|
66247
|
-
emittedAfterFinalizationTimeout
|
|
66602
|
+
emittedAfterFinalizationTimeout
|
|
66248
66603
|
});
|
|
66249
|
-
|
|
66604
|
+
completionDiagnostic.decoupledImmediateEmit = isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout;
|
|
66605
|
+
LOG2.warn("CLI", `[${this.type}] emitting completed event (${isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`}) without finalized assistant turn (${blockReason})`);
|
|
66606
|
+
if (this.isMeshWorkerSession()) {
|
|
66607
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `forced after ${waitedMs}ms (${blockReason})`);
|
|
66608
|
+
}
|
|
66250
66609
|
this.pushEvent({
|
|
66251
66610
|
event: "agent:generating_completed",
|
|
66252
66611
|
chatTitle: pending.chatTitle,
|
|
@@ -66269,6 +66628,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66269
66628
|
return;
|
|
66270
66629
|
}
|
|
66271
66630
|
LOG2.info("CLI", `[${this.type}] completed in ${pending.duration}s`);
|
|
66631
|
+
if (this.isMeshWorkerSession()) {
|
|
66632
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `duration=${pending.duration}s`);
|
|
66633
|
+
}
|
|
66272
66634
|
this.pushEvent({
|
|
66273
66635
|
event: "agent:generating_completed",
|
|
66274
66636
|
chatTitle: pending.chatTitle,
|
|
@@ -66507,6 +66869,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66507
66869
|
if (missingEvidence && !hasMeshContext) {
|
|
66508
66870
|
LOG2.info("CLI", `[${this.type}] short completion suppressed: missing final assistant evidence, no mesh context (source=${shortEvidenceSource})`);
|
|
66509
66871
|
} else {
|
|
66872
|
+
if (this.isMeshWorkerSession()) {
|
|
66873
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), `short-generating idle (source=${shortEvidenceSource})`);
|
|
66874
|
+
}
|
|
66510
66875
|
this.pushEvent({
|
|
66511
66876
|
event: "agent:generating_completed",
|
|
66512
66877
|
chatTitle,
|
|
@@ -66583,6 +66948,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66583
66948
|
const monitorParsedStatus = parsedStatus;
|
|
66584
66949
|
for (const me of monitorEvents) {
|
|
66585
66950
|
if (me.type === "monitor:no_progress" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
|
|
66951
|
+
if (this.isMeshWorkerSession()) {
|
|
66952
|
+
traceMeshEventStage("fired", this.meshTraceCtx(), "no_progress_monitor_final_summary");
|
|
66953
|
+
}
|
|
66586
66954
|
this.pushEvent({
|
|
66587
66955
|
event: "agent:generating_completed",
|
|
66588
66956
|
chatTitle,
|
|
@@ -70422,7 +70790,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70422
70790
|
}
|
|
70423
70791
|
if (buf.length === 0) return null;
|
|
70424
70792
|
const strings = extractStringsFromBuffer(buf);
|
|
70425
|
-
const meaningful = strings.filter((
|
|
70793
|
+
const meaningful = strings.filter((s2) => s2.length >= MIN_PRINTABLE_RUN && /\w/.test(s2));
|
|
70426
70794
|
if (meaningful.length === 0) return null;
|
|
70427
70795
|
const content = meaningful.join("\n");
|
|
70428
70796
|
const sourceMtimeMs = statMtimeMs3(filePath);
|
|
@@ -70628,10 +70996,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70628
70996
|
};
|
|
70629
70997
|
}
|
|
70630
70998
|
function normalizeHermesRole(r) {
|
|
70631
|
-
const
|
|
70632
|
-
if (
|
|
70633
|
-
if (
|
|
70634
|
-
if (
|
|
70999
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
71000
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
71001
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
71002
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
70635
71003
|
return "system";
|
|
70636
71004
|
}
|
|
70637
71005
|
function createNativeHistoryDispatcher(reader) {
|
|
@@ -70855,10 +71223,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70855
71223
|
}
|
|
70856
71224
|
}
|
|
70857
71225
|
function normalizeRole2(r) {
|
|
70858
|
-
const
|
|
70859
|
-
if (
|
|
70860
|
-
if (
|
|
70861
|
-
if (
|
|
71226
|
+
const s2 = String(r ?? "").toLowerCase();
|
|
71227
|
+
if (s2 === "user" || s2 === "human") return "user";
|
|
71228
|
+
if (s2 === "assistant" || s2 === "ai" || s2 === "model") return "assistant";
|
|
71229
|
+
if (s2 === "tool" || s2 === "tool_result" || s2 === "function") return "assistant";
|
|
70862
71230
|
return "system";
|
|
70863
71231
|
}
|
|
70864
71232
|
function registerProviderScriptRootSafely(root) {
|
|
@@ -70876,7 +71244,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
70876
71244
|
const actionType = ctl?.action?.type;
|
|
70877
71245
|
if (!id || !actionType) return;
|
|
70878
71246
|
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((
|
|
71247
|
+
const visibleWhenState = Array.isArray(ctl?.visible_when_state) ? ctl.visible_when_state.filter((s2) => typeof s2 === "string") : void 0;
|
|
70880
71248
|
if (actionType === "open_picker") {
|
|
70881
71249
|
out.push({
|
|
70882
71250
|
id,
|
|
@@ -77762,7 +78130,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
77762
78130
|
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
78131
|
if (!firstFailedCmd) return base;
|
|
77764
78132
|
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((
|
|
78133
|
+
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s2) => typeof s2 === "string" && s2.length > 0).join("\n");
|
|
77766
78134
|
const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
|
|
77767
78135
|
return [
|
|
77768
78136
|
base,
|
|
@@ -78513,7 +78881,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
78513
78881
|
convergence = "blocked_review";
|
|
78514
78882
|
}
|
|
78515
78883
|
const fbcs = result.finalBranchConvergenceState && typeof result.finalBranchConvergenceState === "object" ? result.finalBranchConvergenceState : void 0;
|
|
78516
|
-
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((
|
|
78884
|
+
const stage = Array.isArray(result.refineStages) ? result.refineStages.filter((s2) => s2.status === "failed").map((s2) => s2.stage).filter(Boolean).pop() : void 0;
|
|
78517
78885
|
results.push({
|
|
78518
78886
|
nodeId: node.id,
|
|
78519
78887
|
workspace: node.workspace,
|
|
@@ -79510,7 +79878,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
79510
79878
|
return {
|
|
79511
79879
|
success: true,
|
|
79512
79880
|
screenLineCount: lines.length,
|
|
79513
|
-
sections: resolved.map((
|
|
79881
|
+
sections: resolved.map((s2) => ({ id: s2.id, fromLine: s2.fromLine, toLine: s2.toLine, text: s2.text }))
|
|
79514
79882
|
};
|
|
79515
79883
|
} catch (e) {
|
|
79516
79884
|
return { success: false, error: `resolve failed: ${e.message}` };
|
|
@@ -80079,7 +80447,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80079
80447
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
80080
80448
|
try {
|
|
80081
80449
|
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((
|
|
80450
|
+
const status = Array.isArray(args?.status) ? args.status.map((s2) => typeof s2 === "string" ? s2.trim() : "").filter(Boolean) : void 0;
|
|
80083
80451
|
const rawQueue = getQueue2(meshId, { status });
|
|
80084
80452
|
const statusById = new Map(getQueue2(meshId).map((task) => [task.id, task.status]));
|
|
80085
80453
|
const queue = rawQueue.map((task) => Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? { ...task, ...describeTaskDependencyState2(task, statusById) } : task);
|
|
@@ -80360,7 +80728,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80360
80728
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80361
80729
|
}
|
|
80362
80730
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
80363
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
80731
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
80364
80732
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80365
80733
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "fast_forward_mesh_node", {
|
|
80366
80734
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -80394,7 +80762,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80394
80762
|
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80395
80763
|
}
|
|
80396
80764
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
80397
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
80765
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
80398
80766
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80399
80767
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
|
|
80400
80768
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -80442,7 +80810,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80442
80810
|
const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
80443
80811
|
const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
|
|
80444
80812
|
const selfDaemonId = this.deps.statusInstanceId;
|
|
80445
|
-
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId
|
|
80813
|
+
const isRemote = nodeDaemonId && selfDaemonId && !daemonIdsEquivalent(nodeDaemonId, selfDaemonId);
|
|
80446
80814
|
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80447
80815
|
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
80448
80816
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
|
|
@@ -80529,7 +80897,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80529
80897
|
let worktreeCleanup;
|
|
80530
80898
|
if (node?.isLocalWorktree) {
|
|
80531
80899
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80532
|
-
const isRemoteWorktree = nodeDaemonId && nodeDaemonId
|
|
80900
|
+
const isRemoteWorktree = nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
|
|
80533
80901
|
if (isRemoteWorktree) {
|
|
80534
80902
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "remove_mesh_node", {
|
|
80535
80903
|
...typeof args === "object" && args !== null ? args : {},
|
|
@@ -80611,7 +80979,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80611
80979
|
const sourceNode = mesh.nodes?.find((n) => meshNodeIdMatches(n, sourceNodeId));
|
|
80612
80980
|
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
80613
80981
|
const sourceDaemonId = typeof sourceNode.daemonId === "string" ? sourceNode.daemonId.trim() : void 0;
|
|
80614
|
-
if (sourceDaemonId && sourceDaemonId
|
|
80982
|
+
if (sourceDaemonId && !daemonIdsEquivalent(sourceDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80615
80983
|
const forwarded = await this.deps.dispatchMeshCommand(sourceDaemonId, "clone_mesh_node", {
|
|
80616
80984
|
...typeof args === "object" && args !== null ? args : {},
|
|
80617
80985
|
_meshDirectDispatch: true
|
|
@@ -80853,7 +81221,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
80853
81221
|
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
80854
81222
|
if (!node.isLocalWorktree) return { success: false, error: "Node is not a local worktree node" };
|
|
80855
81223
|
const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
80856
|
-
if (nodeDaemonId && nodeDaemonId
|
|
81224
|
+
if (nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, this.deps.statusInstanceId) && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
80857
81225
|
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "retry_mesh_node_bootstrap", {
|
|
80858
81226
|
...typeof args === "object" && args !== null ? args : {},
|
|
80859
81227
|
_meshDirectDispatch: true
|
|
@@ -82061,16 +82429,16 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
82061
82429
|
const now = this.lastStatusSentAt;
|
|
82062
82430
|
const target = opts?.p2pOnly ? "P2P" : serverConnected ? "P2P+Server" : "P2P";
|
|
82063
82431
|
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 `${
|
|
82432
|
+
const ideStates = allStates.filter((s2) => s2.category === "ide");
|
|
82433
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli");
|
|
82434
|
+
const acpStates = allStates.filter((s2) => s2.category === "acp");
|
|
82435
|
+
const ideSummary = ideStates.map((s2) => {
|
|
82436
|
+
const msgs = s2.activeChat?.messages?.length || 0;
|
|
82437
|
+
const exts = s2.extensions.length;
|
|
82438
|
+
return `${s2.type}(${s2.status},${msgs}msg,${exts}ext)`;
|
|
82071
82439
|
}).join(", ");
|
|
82072
|
-
const cliSummary = cliStates.map((
|
|
82073
|
-
const acpSummary = acpStates.map((
|
|
82440
|
+
const cliSummary = cliStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
82441
|
+
const acpSummary = acpStates.map((s2) => `${s2.type}(${s2.status})`).join(", ");
|
|
82074
82442
|
const logLevel = opts?.p2pOnly ? "debug" : "info";
|
|
82075
82443
|
const baseSummary = `IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
|
|
82076
82444
|
const summaryChanged = baseSummary !== this.lastStatusSummary;
|
|
@@ -82181,10 +82549,10 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
82181
82549
|
}
|
|
82182
82550
|
return false;
|
|
82183
82551
|
}
|
|
82184
|
-
simpleHash(
|
|
82552
|
+
simpleHash(s2) {
|
|
82185
82553
|
let h = 2166136261;
|
|
82186
|
-
for (let i = 0; i <
|
|
82187
|
-
h ^=
|
|
82554
|
+
for (let i = 0; i < s2.length; i++) {
|
|
82555
|
+
h ^= s2.charCodeAt(i);
|
|
82188
82556
|
h = h * 16777619 >>> 0;
|
|
82189
82557
|
}
|
|
82190
82558
|
return h.toString(36);
|
|
@@ -83392,7 +83760,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
83392
83760
|
* Per-category status collect
|
|
83393
83761
|
*/
|
|
83394
83762
|
collectStatesByCategory(category) {
|
|
83395
|
-
return this.collectAllStates().filter((
|
|
83763
|
+
return this.collectAllStates().filter((s2) => s2.category === category);
|
|
83396
83764
|
}
|
|
83397
83765
|
// ─── Tick engine ─────────────────────────────────
|
|
83398
83766
|
/**
|
|
@@ -85278,9 +85646,9 @@ async (params) => {
|
|
|
85278
85646
|
function findCliTarget(ctx, type, instanceId) {
|
|
85279
85647
|
if (!ctx.instanceManager) return null;
|
|
85280
85648
|
const cliStates = ctx.instanceManager.collectAllStates().filter(isCliTargetState);
|
|
85281
|
-
if (instanceId) return cliStates.find((
|
|
85649
|
+
if (instanceId) return cliStates.find((s2) => s2.instanceId === instanceId) || null;
|
|
85282
85650
|
if (!type) return cliStates[cliStates.length - 1] || null;
|
|
85283
|
-
const matches = cliStates.filter((
|
|
85651
|
+
const matches = cliStates.filter((s2) => s2.type === type);
|
|
85284
85652
|
return matches[matches.length - 1] || null;
|
|
85285
85653
|
}
|
|
85286
85654
|
function getCliTargetBundle(ctx, type, instanceId) {
|
|
@@ -85643,20 +86011,20 @@ async (params) => {
|
|
|
85643
86011
|
return;
|
|
85644
86012
|
}
|
|
85645
86013
|
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:
|
|
86014
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
86015
|
+
const result = cliStates.map((s2) => ({
|
|
86016
|
+
instanceId: s2.instanceId,
|
|
86017
|
+
type: s2.type,
|
|
86018
|
+
name: s2.name,
|
|
86019
|
+
category: s2.category,
|
|
86020
|
+
status: s2.status,
|
|
86021
|
+
mode: s2.mode,
|
|
86022
|
+
workspace: s2.workspace,
|
|
86023
|
+
messageCount: s2.activeChat?.messages?.length || 0,
|
|
86024
|
+
lastMessage: s2.activeChat?.messages?.slice(-1)[0] || null,
|
|
86025
|
+
activeModal: s2.activeChat?.activeModal || null,
|
|
86026
|
+
pendingEvents: s2.pendingEvents || [],
|
|
86027
|
+
settings: s2.settings
|
|
85660
86028
|
}));
|
|
85661
86029
|
ctx.json(res, 200, { instances: result, count: result.length });
|
|
85662
86030
|
}
|
|
@@ -85745,9 +86113,9 @@ async (params) => {
|
|
|
85745
86113
|
}
|
|
85746
86114
|
if (ctx.instanceManager) {
|
|
85747
86115
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
85748
|
-
const cliStates = allStates.filter((
|
|
85749
|
-
for (const
|
|
85750
|
-
ctx.sendCliSSE({ event: "snapshot", providerType:
|
|
86116
|
+
const cliStates = allStates.filter((s2) => s2.category === "cli" || s2.category === "acp");
|
|
86117
|
+
for (const s2 of cliStates) {
|
|
86118
|
+
ctx.sendCliSSE({ event: "snapshot", providerType: s2.type, status: s2.status, instanceId: s2.instanceId });
|
|
85751
86119
|
}
|
|
85752
86120
|
}
|
|
85753
86121
|
_req.on("close", () => {
|
|
@@ -85763,7 +86131,7 @@ async (params) => {
|
|
|
85763
86131
|
const target = findCliTarget(ctx, type);
|
|
85764
86132
|
if (!target) {
|
|
85765
86133
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
85766
|
-
ctx.json(res, 404, { error: `No running instance for: ${type}`, available: allStates.filter((
|
|
86134
|
+
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
86135
|
return;
|
|
85768
86136
|
}
|
|
85769
86137
|
const instance = ctx.instanceManager.getInstance(target.instanceId);
|
|
@@ -85809,7 +86177,7 @@ async (params) => {
|
|
|
85809
86177
|
const allStates = ctx.instanceManager.collectAllStates();
|
|
85810
86178
|
ctx.json(res, 404, {
|
|
85811
86179
|
error: `No running instance for: ${type}`,
|
|
85812
|
-
available: allStates.filter((
|
|
86180
|
+
available: allStates.filter((s2) => s2.category === "cli" || s2.category === "acp").map((s2) => s2.type)
|
|
85813
86181
|
});
|
|
85814
86182
|
return;
|
|
85815
86183
|
}
|
|
@@ -86612,7 +86980,7 @@ async (params) => {
|
|
|
86612
86980
|
child.write("\x1B[12;1R");
|
|
86613
86981
|
ctx.log("Terminal CPR request (\\x1b[6n) intercepted in PTY, responding with dummy coordinates [12;1R]");
|
|
86614
86982
|
}
|
|
86615
|
-
checkAutoApproval(data, (
|
|
86983
|
+
checkAutoApproval(data, (s2) => child.write(s2));
|
|
86616
86984
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk: data, stream: "stdout" } });
|
|
86617
86985
|
scheduleAutoStopForVerification();
|
|
86618
86986
|
});
|
|
@@ -86625,7 +86993,7 @@ async (params) => {
|
|
|
86625
86993
|
stdout += chunk;
|
|
86626
86994
|
clearAutoStopTimer();
|
|
86627
86995
|
if (chunk.includes("\x1B[6n")) child.stdin?.write("\x1B[1;1R");
|
|
86628
|
-
checkAutoApproval(chunk, (
|
|
86996
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
86629
86997
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stdout" } });
|
|
86630
86998
|
scheduleAutoStopForVerification();
|
|
86631
86999
|
});
|
|
@@ -86633,7 +87001,7 @@ async (params) => {
|
|
|
86633
87001
|
const chunk = d.toString();
|
|
86634
87002
|
stderr += chunk;
|
|
86635
87003
|
clearAutoStopTimer();
|
|
86636
|
-
checkAutoApproval(chunk, (
|
|
87004
|
+
checkAutoApproval(chunk, (s2) => child.stdin?.write(s2));
|
|
86637
87005
|
sendAutoImplSSE(ctx, { event: "output", data: { chunk, stream: "stderr" } });
|
|
86638
87006
|
scheduleAutoStopForVerification();
|
|
86639
87007
|
});
|
|
@@ -87446,59 +87814,59 @@ data: ${JSON.stringify(msg.data)}
|
|
|
87446
87814
|
// ─── Route Table ─────────────────────────────────────
|
|
87447
87815
|
routes = [
|
|
87448
87816
|
// 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,
|
|
87817
|
+
{ method: "GET", pattern: "/api/providers", handler: (q, s2) => this.handleListProviders(q, s2) },
|
|
87818
|
+
{ method: "GET", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleGetProviderSourceConfig(q, s2) },
|
|
87819
|
+
{ method: "POST", pattern: "/api/providers/source-config", handler: (q, s2) => this.handleSetProviderSourceConfig(q, s2) },
|
|
87820
|
+
{ method: "GET", pattern: "/api/providers/versions", handler: (q, s2) => this.handleDetectVersions(q, s2) },
|
|
87821
|
+
{ method: "POST", pattern: "/api/providers/reload", handler: (q, s2) => this.handleReload(q, s2) },
|
|
87822
|
+
{ method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s2) => this.handleCdpEvaluate(q, s2) },
|
|
87823
|
+
{ method: "POST", pattern: "/api/cdp/click", handler: (q, s2) => this.handleCdpClick(q, s2) },
|
|
87824
|
+
{ method: "POST", pattern: "/api/cdp/dom/query", handler: (q, s2) => this.handleCdpDomQuery(q, s2) },
|
|
87825
|
+
{ method: "POST", pattern: "/api/cdp/dom/inspect", handler: (q, s2) => this.handleDomInspect(q, s2) },
|
|
87826
|
+
{ method: "POST", pattern: "/api/cdp/dom/children", handler: (q, s2) => this.handleDomChildren(q, s2) },
|
|
87827
|
+
{ method: "POST", pattern: "/api/cdp/dom/analyze", handler: (q, s2) => this.handleDomAnalyze(q, s2) },
|
|
87828
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-text", handler: (q, s2) => this.handleFindByText(q, s2) },
|
|
87829
|
+
{ method: "POST", pattern: "/api/cdp/dom/find-common", handler: (q, s2) => this.handleFindCommon(q, s2) },
|
|
87830
|
+
{ method: "GET", pattern: "/api/cdp/screenshot", handler: (q, s2) => this.handleScreenshot(q, s2) },
|
|
87831
|
+
{ method: "GET", pattern: "/api/cdp/targets", handler: (q, s2) => this.handleCdpTargets(q, s2) },
|
|
87832
|
+
{ method: "POST", pattern: "/api/scripts/run", handler: (q, s2) => this.handleScriptsRun(q, s2) },
|
|
87833
|
+
{ method: "GET", pattern: "/api/status", handler: (q, s2) => this.handleStatus(q, s2) },
|
|
87834
|
+
{ method: "POST", pattern: "/api/watch/start", handler: (q, s2) => this.handleWatchStart(q, s2) },
|
|
87835
|
+
{ method: "POST", pattern: "/api/watch/stop", handler: (q, s2) => this.handleWatchStop(q, s2) },
|
|
87836
|
+
{ method: "GET", pattern: "/api/watch/events", handler: (q, s2) => this.handleSSE(q, s2) },
|
|
87837
|
+
{ method: "POST", pattern: "/api/scaffold", handler: (q, s2) => this.handleScaffold(q, s2) },
|
|
87470
87838
|
// 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,
|
|
87839
|
+
{ method: "GET", pattern: "/api/cli/status", handler: (q, s2) => this.handleCliStatus(q, s2) },
|
|
87840
|
+
{ method: "POST", pattern: "/api/cli/launch", handler: (q, s2) => this.handleCliLaunch(q, s2) },
|
|
87841
|
+
{ method: "POST", pattern: "/api/cli/send", handler: (q, s2) => this.handleCliSend(q, s2) },
|
|
87842
|
+
{ method: "POST", pattern: "/api/cli/exercise", handler: (q, s2) => this.handleCliExercise(q, s2) },
|
|
87843
|
+
{ method: "POST", pattern: "/api/cli/fixture/capture", handler: (q, s2) => this.handleCliFixtureCapture(q, s2) },
|
|
87844
|
+
{ method: "POST", pattern: "/api/cli/fixture/replay", handler: (q, s2) => this.handleCliFixtureReplay(q, s2) },
|
|
87845
|
+
{ method: "POST", pattern: "/api/cli/resolve", handler: (q, s2) => this.handleCliResolve(q, s2) },
|
|
87846
|
+
{ method: "POST", pattern: "/api/cli/raw", handler: (q, s2) => this.handleCliRaw(q, s2) },
|
|
87847
|
+
{ method: "POST", pattern: "/api/cli/stop", handler: (q, s2) => this.handleCliStop(q, s2) },
|
|
87848
|
+
{ method: "GET", pattern: "/api/cli/events", handler: (q, s2) => this.handleCliSSE(q, s2) },
|
|
87849
|
+
{ method: "GET", pattern: /^\/api\/cli\/debug\/([^/]+)$/, handler: (q, s2, p) => this.handleCliDebug(p[0], q, s2) },
|
|
87850
|
+
{ method: "GET", pattern: /^\/api\/cli\/trace\/([^/]+)$/, handler: (q, s2, p) => this.handleCliTrace(p[0], q, s2) },
|
|
87851
|
+
{ method: "GET", pattern: /^\/api\/cli\/fixtures\/([^/]+)$/, handler: (q, s2, p) => this.handleCliFixtureList(p[0], q, s2) },
|
|
87484
87852
|
// 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,
|
|
87853
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/script$/, handler: (q, s2, p) => this.handleRunScript(p[0], q, s2) },
|
|
87854
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/files$/, handler: (q, s2, p) => this.handleListFiles(p[0], q, s2) },
|
|
87855
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleReadFile(p[0], q, s2) },
|
|
87856
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/file$/, handler: (q, s2, p) => this.handleWriteFile(p[0], q, s2) },
|
|
87857
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s2, p) => this.handleSource(p[0], q, s2) },
|
|
87858
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s2, p) => this.handleSave(p[0], q, s2) },
|
|
87859
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s2, p) => this.handleTypeAndSend(p[0], q, s2) },
|
|
87860
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s2, p) => this.handleTypeAndSendAt(p[0], q, s2) },
|
|
87861
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s2, p) => this.handleProviderConfig(p[0], q, s2) },
|
|
87862
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s2, p) => this.handleDomContext(p[0], q, s2) },
|
|
87863
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s2, p) => this.handleAutoImplement(p[0], q, s2) },
|
|
87864
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/cancel$/, handler: (q, s2, p) => this.handleAutoImplCancel(p[0], q, s2) },
|
|
87865
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/auto-implement\/status$/, handler: (q, s2, p) => this.handleAutoImplSSE(p[0], q, s2) },
|
|
87866
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/spawn-test$/, handler: (q, s2, p) => this.handleSpawnTest(p[0], q, s2) },
|
|
87867
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/validate$/, handler: (q, s2, p) => this.handleValidate(p[0], q, s2) },
|
|
87868
|
+
{ method: "POST", pattern: /^\/api\/providers\/([^/]+)\/acp-chat$/, handler: (q, s2, p) => this.handleAcpChat(p[0], q, s2) },
|
|
87869
|
+
{ method: "GET", pattern: /^\/api\/providers\/([^/]+)\/script-hints$/, handler: (q, s2, p) => this.handleScriptHints(p[0], q, s2) }
|
|
87502
87870
|
];
|
|
87503
87871
|
matchRoute(method, pathname) {
|
|
87504
87872
|
for (const route of this.routes) {
|
|
@@ -88093,14 +88461,14 @@ data: ${JSON.stringify(msg.data)}
|
|
|
88093
88461
|
warnings.push(...validation.warnings);
|
|
88094
88462
|
if (config2.settings) {
|
|
88095
88463
|
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 (
|
|
88464
|
+
const s2 = val;
|
|
88465
|
+
if (!s2.type) errors.push(`settings.${key}: missing type`);
|
|
88466
|
+
else if (!["boolean", "number", "string", "select"].includes(s2.type))
|
|
88467
|
+
errors.push(`settings.${key}: invalid type '${s2.type}'`);
|
|
88468
|
+
if (s2.default === void 0) warnings.push(`settings.${key}: no default value`);
|
|
88469
|
+
if (s2.type === "number" && s2.min !== void 0 && s2.max !== void 0 && s2.min > s2.max)
|
|
88470
|
+
errors.push(`settings.${key}: min (${s2.min}) > max (${s2.max})`);
|
|
88471
|
+
if (s2.type === "select" && (!s2.options || !Array.isArray(s2.options) || s2.options.length === 0))
|
|
88104
88472
|
errors.push(`settings.${key}: select type requires options[]`);
|
|
88105
88473
|
}
|
|
88106
88474
|
}
|