@adhdev/daemon-standalone 0.9.82-rc.355 → 0.9.82-rc.357
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 +177 -76
- package/dist/index.js.map +1 -1
- package/package.json +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 ? "37b9d1d9e10336707dbc0861a96d5bcc55cc015e" : void 0) ?? "unknown";
|
|
30040
|
+
const commitShort = readInjected(true ? "37b9d1d9" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30041
|
+
const version2 = readInjected(true ? "0.9.82-rc.357" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30042
|
+
const builtAt = readInjected(true ? "2026-06-23T00:25:47.104Z" : void 0);
|
|
30043
30043
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30044
30044
|
return cached2;
|
|
30045
30045
|
}
|
|
@@ -42462,8 +42462,22 @@ ${cleanBody}`;
|
|
|
42462
42462
|
}
|
|
42463
42463
|
function getMeshWithCache(components, meshId) {
|
|
42464
42464
|
const localMesh = getMesh(meshId);
|
|
42465
|
-
|
|
42466
|
-
|
|
42465
|
+
const cachedMesh = components.router?.getCachedInlineMesh(meshId);
|
|
42466
|
+
if (!localMesh) return cachedMesh;
|
|
42467
|
+
if (!cachedMesh) return localMesh;
|
|
42468
|
+
return mergeInlineCacheOnlyNodes(localMesh, cachedMesh);
|
|
42469
|
+
}
|
|
42470
|
+
function mergeInlineCacheOnlyNodes(localMesh, cachedMesh) {
|
|
42471
|
+
const localNodes = Array.isArray(localMesh?.nodes) ? localMesh.nodes : [];
|
|
42472
|
+
const cachedNodes = Array.isArray(cachedMesh?.nodes) ? cachedMesh.nodes : [];
|
|
42473
|
+
if (!cachedNodes.length) return localMesh;
|
|
42474
|
+
const cacheOnly = cachedNodes.filter((cachedNode) => {
|
|
42475
|
+
const cachedId = readMeshNodeId(cachedNode);
|
|
42476
|
+
if (!cachedId) return false;
|
|
42477
|
+
return !localNodes.some((localNode) => meshNodeIdMatches(localNode, cachedId));
|
|
42478
|
+
});
|
|
42479
|
+
if (!cacheOnly.length) return localMesh;
|
|
42480
|
+
return { ...localMesh, nodes: [...localNodes, ...cacheOnly] };
|
|
42467
42481
|
}
|
|
42468
42482
|
function isIntentionalCleanupStopMetadata(event) {
|
|
42469
42483
|
return event.intentional === true || event.intentionalStop === true || event.operatorCleanup === true || event.reason === "operator_cleanup" || event.stopReason === "operator_cleanup" || event.cleanupReason === "operator_cleanup" || event.source === "mesh_cleanup_sessions" || event.source === "mesh_remove_node";
|
|
@@ -43800,6 +43814,76 @@ ${cleanBody}`;
|
|
|
43800
43814
|
}
|
|
43801
43815
|
return { success: true, forwarded: 0 };
|
|
43802
43816
|
}
|
|
43817
|
+
function buildRelayMetadataEvent(payload) {
|
|
43818
|
+
const relayModalMessage = readNonEmptyString2(payload.modalMessage);
|
|
43819
|
+
const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
|
|
43820
|
+
return {
|
|
43821
|
+
// Preserve the dispatch task id across the machine boundary. The `received` trace
|
|
43822
|
+
// stage reads payload.taskId; without mirroring it here the rebuilt metadataEvent
|
|
43823
|
+
// loses it, so injectMeshSystemMessage's traceCtx.taskId and the
|
|
43824
|
+
// updateDirectDispatchStatus(eventTaskId) call go undefined — the EvtTrace
|
|
43825
|
+
// queued/surfaced stages show task=- and the direct-dispatch ledger falls back to a
|
|
43826
|
+
// session_id match (which can flip a sibling row). The local in-process forward path
|
|
43827
|
+
// keeps event.taskId/meshActiveTaskId for free; this mirrors it for the remote relay.
|
|
43828
|
+
// Same taskId/meshActiveTaskId ordering the local unroutable trace uses.
|
|
43829
|
+
taskId: readNonEmptyString2(payload.taskId) || readNonEmptyString2(payload.meshActiveTaskId),
|
|
43830
|
+
targetSessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId) || readNonEmptyString2(payload.instanceId),
|
|
43831
|
+
providerType: readNonEmptyString2(payload.providerType),
|
|
43832
|
+
providerSessionId: readNonEmptyString2(payload.providerSessionId),
|
|
43833
|
+
// Preserve the originating coordinator SESSION id across the machine boundary so
|
|
43834
|
+
// the completion routes back to the exact coordinator session (multi-coordinator).
|
|
43835
|
+
// buildForwardPayloadFromPending spreads the worker event's metadata, so the id
|
|
43836
|
+
// arrives as payload.meshCoordinatorSessionId; the top-level targetCoordinatorSessionId
|
|
43837
|
+
// is also accepted as a fallback. injectMeshSystemMessage re-derives the routing
|
|
43838
|
+
// anchors from this. Absent → daemon-level fallback (version-skew safe).
|
|
43839
|
+
meshCoordinatorSessionId: readNonEmptyString2(payload.meshCoordinatorSessionId) || readNonEmptyString2(payload.targetCoordinatorSessionId),
|
|
43840
|
+
// Carry the session identity fields the worker provider event emits so the
|
|
43841
|
+
// coordinator's mirror (updateMeshOwnedSession) gets a real workspace/title/
|
|
43842
|
+
// settings. Without these the remote-relay hop reconstructs metadataEvent with
|
|
43843
|
+
// an empty workspace, and the dashboard flaps to the generic
|
|
43844
|
+
// "Terminal (Mesh Node)" title (and degrades the provider label) between live
|
|
43845
|
+
// events and the periodic get_status_metadata snapshot. The local in-process
|
|
43846
|
+
// forward path (onMeshCoordinatorEventForwarded) already preserves these; this
|
|
43847
|
+
// mirrors them for the remote-only relay path.
|
|
43848
|
+
workspace: readNonEmptyString2(payload.workspace) || readNonEmptyString2(payload.workspaceName),
|
|
43849
|
+
workspaceName: readNonEmptyString2(payload.workspaceName) || readNonEmptyString2(payload.workspace),
|
|
43850
|
+
sessionTitle: readNonEmptyString2(payload.sessionTitle),
|
|
43851
|
+
sessionStatus: readNonEmptyString2(payload.sessionStatus),
|
|
43852
|
+
sessionChatStatus: readNonEmptyString2(payload.sessionChatStatus),
|
|
43853
|
+
providerName: readNonEmptyString2(payload.providerName),
|
|
43854
|
+
...payload.sessionSettings && typeof payload.sessionSettings === "object" && !Array.isArray(payload.sessionSettings) ? { sessionSettings: payload.sessionSettings } : {},
|
|
43855
|
+
finalSummary: readNonEmptyString2(payload.finalSummary) || readNonEmptyString2(payload.summary),
|
|
43856
|
+
// T2: carry the worker's status-snapshot last-message preview across the machine
|
|
43857
|
+
// boundary so a summary-less completion still surfaces the assistant reply in the
|
|
43858
|
+
// coordinator's inbox mirror. resolveMeshSurfacedSessionPreview reads these
|
|
43859
|
+
// (assistant-role only) when finalSummary is absent.
|
|
43860
|
+
lastMessagePreview: readNonEmptyString2(payload.lastMessagePreview),
|
|
43861
|
+
lastMessageRole: readNonEmptyString2(payload.lastMessageRole),
|
|
43862
|
+
...payload.lastMessageAt !== void 0 ? { lastMessageAt: payload.lastMessageAt } : {},
|
|
43863
|
+
jobId: readNonEmptyString2(payload.jobId),
|
|
43864
|
+
interactionId: readNonEmptyString2(payload.interactionId),
|
|
43865
|
+
status: readNonEmptyString2(payload.status),
|
|
43866
|
+
targetDaemonId: readNonEmptyString2(payload.targetDaemonId),
|
|
43867
|
+
startedAt: readNonEmptyString2(payload.startedAt),
|
|
43868
|
+
completedAt: readNonEmptyString2(payload.completedAt),
|
|
43869
|
+
retryOfJobId: readNonEmptyString2(payload.retryOfJobId),
|
|
43870
|
+
...relayModalMessage ? { modalMessage: relayModalMessage } : {},
|
|
43871
|
+
...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
|
|
43872
|
+
...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
|
|
43873
|
+
...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
|
|
43874
|
+
...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
|
|
43875
|
+
...payload.meshWorkerResult && typeof payload.meshWorkerResult === "object" && !Array.isArray(payload.meshWorkerResult) ? { meshWorkerResult: payload.meshWorkerResult } : {},
|
|
43876
|
+
...payload.structuredResult && typeof payload.structuredResult === "object" && !Array.isArray(payload.structuredResult) ? { structuredResult: payload.structuredResult } : {},
|
|
43877
|
+
...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
|
|
43878
|
+
intentional: payload.intentional === true,
|
|
43879
|
+
intentionalStop: payload.intentionalStop === true,
|
|
43880
|
+
operatorCleanup: payload.operatorCleanup === true,
|
|
43881
|
+
reason: readNonEmptyString2(payload.reason),
|
|
43882
|
+
stopReason: readNonEmptyString2(payload.stopReason),
|
|
43883
|
+
cleanupReason: readNonEmptyString2(payload.cleanupReason),
|
|
43884
|
+
source: readNonEmptyString2(payload.source)
|
|
43885
|
+
};
|
|
43886
|
+
}
|
|
43803
43887
|
function handleMeshForwardEvent(components, payload) {
|
|
43804
43888
|
const eventName = readNonEmptyString2(payload.event);
|
|
43805
43889
|
if (!isMeshCoordinatorEvent(eventName)) {
|
|
@@ -43825,70 +43909,12 @@ ${cleanBody}`;
|
|
|
43825
43909
|
event: eventName
|
|
43826
43910
|
});
|
|
43827
43911
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
43828
|
-
const relayModalMessage = readNonEmptyString2(payload.modalMessage);
|
|
43829
|
-
const relayModalButtons = Array.isArray(payload.modalButtons) ? payload.modalButtons.filter((b) => typeof b === "string" && b.trim().length > 0) : null;
|
|
43830
43912
|
return injectMeshSystemMessage(components, {
|
|
43831
43913
|
meshId,
|
|
43832
43914
|
nodeId,
|
|
43833
43915
|
nodeLabel,
|
|
43834
43916
|
event: eventName,
|
|
43835
|
-
metadataEvent:
|
|
43836
|
-
targetSessionId: readNonEmptyString2(payload.targetSessionId) || readNonEmptyString2(payload.sessionId) || readNonEmptyString2(payload.instanceId),
|
|
43837
|
-
providerType: readNonEmptyString2(payload.providerType),
|
|
43838
|
-
providerSessionId: readNonEmptyString2(payload.providerSessionId),
|
|
43839
|
-
// Preserve the originating coordinator SESSION id across the machine boundary so
|
|
43840
|
-
// the completion routes back to the exact coordinator session (multi-coordinator).
|
|
43841
|
-
// buildForwardPayloadFromPending spreads the worker event's metadata, so the id
|
|
43842
|
-
// arrives as payload.meshCoordinatorSessionId; the top-level targetCoordinatorSessionId
|
|
43843
|
-
// is also accepted as a fallback. injectMeshSystemMessage re-derives the routing
|
|
43844
|
-
// anchors from this. Absent → daemon-level fallback (version-skew safe).
|
|
43845
|
-
meshCoordinatorSessionId: readNonEmptyString2(payload.meshCoordinatorSessionId) || readNonEmptyString2(payload.targetCoordinatorSessionId),
|
|
43846
|
-
// Carry the session identity fields the worker provider event emits so the
|
|
43847
|
-
// coordinator's mirror (updateMeshOwnedSession) gets a real workspace/title/
|
|
43848
|
-
// settings. Without these the remote-relay hop reconstructs metadataEvent with
|
|
43849
|
-
// an empty workspace, and the dashboard flaps to the generic
|
|
43850
|
-
// "Terminal (Mesh Node)" title (and degrades the provider label) between live
|
|
43851
|
-
// events and the periodic get_status_metadata snapshot. The local in-process
|
|
43852
|
-
// forward path (onMeshCoordinatorEventForwarded) already preserves these; this
|
|
43853
|
-
// mirrors them for the remote-only relay path.
|
|
43854
|
-
workspace: readNonEmptyString2(payload.workspace) || readNonEmptyString2(payload.workspaceName),
|
|
43855
|
-
workspaceName: readNonEmptyString2(payload.workspaceName) || readNonEmptyString2(payload.workspace),
|
|
43856
|
-
sessionTitle: readNonEmptyString2(payload.sessionTitle),
|
|
43857
|
-
sessionStatus: readNonEmptyString2(payload.sessionStatus),
|
|
43858
|
-
sessionChatStatus: readNonEmptyString2(payload.sessionChatStatus),
|
|
43859
|
-
providerName: readNonEmptyString2(payload.providerName),
|
|
43860
|
-
...payload.sessionSettings && typeof payload.sessionSettings === "object" && !Array.isArray(payload.sessionSettings) ? { sessionSettings: payload.sessionSettings } : {},
|
|
43861
|
-
finalSummary: readNonEmptyString2(payload.finalSummary) || readNonEmptyString2(payload.summary),
|
|
43862
|
-
// T2: carry the worker's status-snapshot last-message preview across the machine
|
|
43863
|
-
// boundary so a summary-less completion still surfaces the assistant reply in the
|
|
43864
|
-
// coordinator's inbox mirror. resolveMeshSurfacedSessionPreview reads these
|
|
43865
|
-
// (assistant-role only) when finalSummary is absent.
|
|
43866
|
-
lastMessagePreview: readNonEmptyString2(payload.lastMessagePreview),
|
|
43867
|
-
lastMessageRole: readNonEmptyString2(payload.lastMessageRole),
|
|
43868
|
-
...payload.lastMessageAt !== void 0 ? { lastMessageAt: payload.lastMessageAt } : {},
|
|
43869
|
-
jobId: readNonEmptyString2(payload.jobId),
|
|
43870
|
-
interactionId: readNonEmptyString2(payload.interactionId),
|
|
43871
|
-
status: readNonEmptyString2(payload.status),
|
|
43872
|
-
targetDaemonId: readNonEmptyString2(payload.targetDaemonId),
|
|
43873
|
-
startedAt: readNonEmptyString2(payload.startedAt),
|
|
43874
|
-
completedAt: readNonEmptyString2(payload.completedAt),
|
|
43875
|
-
retryOfJobId: readNonEmptyString2(payload.retryOfJobId),
|
|
43876
|
-
...relayModalMessage ? { modalMessage: relayModalMessage } : {},
|
|
43877
|
-
...relayModalButtons && relayModalButtons.length > 0 ? { modalButtons: relayModalButtons } : {},
|
|
43878
|
-
...payload.result && typeof payload.result === "object" && !Array.isArray(payload.result) ? { result: payload.result } : {},
|
|
43879
|
-
...payload.completionDiagnostic && typeof payload.completionDiagnostic === "object" && !Array.isArray(payload.completionDiagnostic) ? { completionDiagnostic: payload.completionDiagnostic } : {},
|
|
43880
|
-
...payload.workerResult && typeof payload.workerResult === "object" && !Array.isArray(payload.workerResult) ? { workerResult: payload.workerResult } : {},
|
|
43881
|
-
...payload.meshWorkerResult && typeof payload.meshWorkerResult === "object" && !Array.isArray(payload.meshWorkerResult) ? { meshWorkerResult: payload.meshWorkerResult } : {},
|
|
43882
|
-
...payload.structuredResult && typeof payload.structuredResult === "object" && !Array.isArray(payload.structuredResult) ? { structuredResult: payload.structuredResult } : {},
|
|
43883
|
-
...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
|
|
43884
|
-
intentional: payload.intentional === true,
|
|
43885
|
-
intentionalStop: payload.intentionalStop === true,
|
|
43886
|
-
operatorCleanup: payload.operatorCleanup === true,
|
|
43887
|
-
reason: readNonEmptyString2(payload.reason),
|
|
43888
|
-
stopReason: readNonEmptyString2(payload.stopReason),
|
|
43889
|
-
cleanupReason: readNonEmptyString2(payload.cleanupReason),
|
|
43890
|
-
source: readNonEmptyString2(payload.source)
|
|
43891
|
-
}
|
|
43917
|
+
metadataEvent: buildRelayMetadataEvent(payload)
|
|
43892
43918
|
});
|
|
43893
43919
|
}
|
|
43894
43920
|
function forwardUnresolvedDelegateEvent(components, routing, event) {
|
|
@@ -49545,6 +49571,7 @@ ${lastSnapshot}`;
|
|
|
49545
49571
|
const idx = Number(m[1]);
|
|
49546
49572
|
let label = String(m[2] ?? "").trim();
|
|
49547
49573
|
if (!Number.isFinite(idx) || idx <= 0 || !label) continue;
|
|
49574
|
+
const current = hasCursorMarker(lines[i]);
|
|
49548
49575
|
let j = i + 1;
|
|
49549
49576
|
while (j < lines.length) {
|
|
49550
49577
|
const next = lines[j];
|
|
@@ -49556,7 +49583,7 @@ ${lastSnapshot}`;
|
|
|
49556
49583
|
}
|
|
49557
49584
|
if (buttons.some((b) => b.index === idx)) continue;
|
|
49558
49585
|
const key = keyTemplate.replace(/\{index\}/g, String(idx));
|
|
49559
|
-
buttons.push({ index: idx, label, key });
|
|
49586
|
+
buttons.push({ index: idx, label, key, current });
|
|
49560
49587
|
i = j - 1;
|
|
49561
49588
|
}
|
|
49562
49589
|
} else {
|
|
@@ -49568,12 +49595,15 @@ ${lastSnapshot}`;
|
|
|
49568
49595
|
if (!Number.isFinite(idx) || idx <= 0 || !label) continue;
|
|
49569
49596
|
if (buttons.some((b) => b.index === idx)) continue;
|
|
49570
49597
|
const key = keyTemplate.replace(/\{index\}/g, String(idx));
|
|
49571
|
-
buttons.push({ index: idx, label, key });
|
|
49598
|
+
buttons.push({ index: idx, label, key, current: hasCursorMarker(m[0]) });
|
|
49572
49599
|
}
|
|
49573
49600
|
}
|
|
49574
49601
|
buttons.sort((a, b) => a.index - b.index);
|
|
49575
49602
|
return buttons;
|
|
49576
49603
|
}
|
|
49604
|
+
function hasCursorMarker(text) {
|
|
49605
|
+
return /^\s*[❯›>]/.test(text);
|
|
49606
|
+
}
|
|
49577
49607
|
var init_evaluator = __esm2({
|
|
49578
49608
|
"src/providers/spec/evaluator.ts"() {
|
|
49579
49609
|
"use strict";
|
|
@@ -49602,6 +49632,11 @@ ${lastSnapshot}`;
|
|
|
49602
49632
|
if (state.id === "busy" || state.id === "generating") return "generating";
|
|
49603
49633
|
return "idle";
|
|
49604
49634
|
}
|
|
49635
|
+
function modalKindForState(state) {
|
|
49636
|
+
if (state.modal_kind) return state.modal_kind;
|
|
49637
|
+
if (state.modal) return "approval";
|
|
49638
|
+
return null;
|
|
49639
|
+
}
|
|
49605
49640
|
var init_fsm_types = __esm2({
|
|
49606
49641
|
"src/providers/spec/fsm-types.ts"() {
|
|
49607
49642
|
"use strict";
|
|
@@ -63364,7 +63399,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63364
63399
|
this.emit({
|
|
63365
63400
|
kind: "state_changed",
|
|
63366
63401
|
state: next.state,
|
|
63367
|
-
|
|
63402
|
+
// kind is the SEMANTIC modal class (approval vs picker/confirm)
|
|
63403
|
+
// derived from the FSM state, NOT from the parsed buttons — the
|
|
63404
|
+
// status field already collapsed it to 'approval' so the modal is
|
|
63405
|
+
// surfaced. The auto-approve worker needs the distinction back to
|
|
63406
|
+
// avoid answering a /model picker on the user's behalf.
|
|
63407
|
+
modal: next.modal ? { title: next.modal.title, buttons: next.modal.buttons.map((b) => ({ index: b.index, label: b.label })), kind: modalKindForState(state) } : null,
|
|
63368
63408
|
controls: next.controls.map((c) => ({ id: c.id, label: c.label, action_type: c.actionType }))
|
|
63369
63409
|
});
|
|
63370
63410
|
this.fireNotifications(state.id, title);
|
|
@@ -63719,6 +63759,19 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
63719
63759
|
if (!m) return;
|
|
63720
63760
|
const btn = m.buttons.find((b) => b.index === index);
|
|
63721
63761
|
if (!btn) return;
|
|
63762
|
+
const rule = stateById(this.spec, this.currentStateId)?.extract?.buttons;
|
|
63763
|
+
if (rule?.select_mode === "arrow_keys") {
|
|
63764
|
+
const from = m.buttons.find((b) => b.current)?.index ?? 1;
|
|
63765
|
+
const up = rule.cursor_keys?.up ?? "\x1B[A";
|
|
63766
|
+
const down = rule.cursor_keys?.down ?? "\x1B[B";
|
|
63767
|
+
const delta = btn.index - from;
|
|
63768
|
+
const step = delta >= 0 ? down : up;
|
|
63769
|
+
const nav = step.repeat(Math.abs(delta));
|
|
63770
|
+
const confirm = (rule.key_for_index || "\r").replace(/\{index\}/g, "") || "\r";
|
|
63771
|
+
if (nav) this.adapter.send_keys(nav);
|
|
63772
|
+
this.adapter.send_keys(confirm);
|
|
63773
|
+
return;
|
|
63774
|
+
}
|
|
63722
63775
|
this.adapter.send_keys(btn.key);
|
|
63723
63776
|
}
|
|
63724
63777
|
handleAttachImage(blob, mime) {
|
|
@@ -64767,7 +64820,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64767
64820
|
messages: [],
|
|
64768
64821
|
// Surface buttons when we have them; an approval state with no parsed
|
|
64769
64822
|
// modal this frame still stays waiting_approval (no activeModal yet).
|
|
64770
|
-
|
|
64823
|
+
// `kind` carries the semantic modal class through to the auto-approve
|
|
64824
|
+
// gate so a /model picker (kind='picker') is never auto-answered.
|
|
64825
|
+
activeModal: modal ? { message: modal.title ?? state.label, buttons: modal.buttons.map((b) => b.label), kind: modal.kind ?? null } : null,
|
|
64771
64826
|
activeInteractivePrompt: this.activeInteractivePrompt,
|
|
64772
64827
|
...sessionFields
|
|
64773
64828
|
};
|
|
@@ -64952,9 +65007,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64952
65007
|
* — not this code — decides how a selection is keyed for each CLI.
|
|
64953
65008
|
*/
|
|
64954
65009
|
async selectPickerChoice(ctl, action, choiceIndex, choiceLabel) {
|
|
64955
|
-
|
|
64956
|
-
|
|
64957
|
-
|
|
65010
|
+
let options = this.extractPickerChoicesIfRendered(action);
|
|
65011
|
+
if (!options) {
|
|
65012
|
+
this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
|
|
65013
|
+
await this.waitForPickerRendered(action);
|
|
65014
|
+
options = this.extractPickerChoices(action);
|
|
65015
|
+
}
|
|
64958
65016
|
let index = choiceIndex;
|
|
64959
65017
|
if ((index == null || !Number.isFinite(index)) && choiceLabel) {
|
|
64960
65018
|
const needle = choiceLabel.trim().toLowerCase();
|
|
@@ -64967,8 +65025,27 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64967
65025
|
if (index == null || !Number.isFinite(index)) {
|
|
64968
65026
|
return { ok: false, error: "choiceIndex or choiceLabel required to select" };
|
|
64969
65027
|
}
|
|
64970
|
-
|
|
64971
|
-
|
|
65028
|
+
if (action.select_mode === "arrow_keys") {
|
|
65029
|
+
const current = options.find((o) => o.current);
|
|
65030
|
+
if (current == null) {
|
|
65031
|
+
return {
|
|
65032
|
+
ok: false,
|
|
65033
|
+
error: "arrow-nav picker: current cursor row not detected on screen",
|
|
65034
|
+
controlResult: { options: options.map((o) => ({ value: o.label, label: o.label, current: o.current })) }
|
|
65035
|
+
};
|
|
65036
|
+
}
|
|
65037
|
+
const up = action.cursor_keys?.up ?? "\x1B[A";
|
|
65038
|
+
const down = action.cursor_keys?.down ?? "\x1B[B";
|
|
65039
|
+
const delta = index - current.index;
|
|
65040
|
+
const step = delta >= 0 ? down : up;
|
|
65041
|
+
const nav = step.repeat(Math.abs(delta));
|
|
65042
|
+
const confirm = (action.submit_key || "\r").replace(/\{index\}/g, "") || "\r";
|
|
65043
|
+
if (nav) this.driver.dispatch({ kind: "pty_write", data: nav });
|
|
65044
|
+
this.driver.dispatch({ kind: "pty_write", data: confirm });
|
|
65045
|
+
} else {
|
|
65046
|
+
const keys = (action.submit_key || "{index}\r").replace(/\{index\}/g, String(index));
|
|
65047
|
+
this.driver.dispatch({ kind: "pty_write", data: keys });
|
|
65048
|
+
}
|
|
64972
65049
|
const selected = options.find((o) => o.index === index);
|
|
64973
65050
|
return {
|
|
64974
65051
|
ok: true,
|
|
@@ -64980,6 +65057,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
64980
65057
|
}
|
|
64981
65058
|
};
|
|
64982
65059
|
}
|
|
65060
|
+
/** Parse the picker choices only if the picker already appears rendered on
|
|
65061
|
+
* the live screen (its `wait_for` condition currently matches and at least
|
|
65062
|
+
* one choice parses). Returns the parsed choices when open, else null so
|
|
65063
|
+
* the caller knows it must send the trigger to open it. Used to de-dup the
|
|
65064
|
+
* picker open in {@link selectPickerChoice}. */
|
|
65065
|
+
extractPickerChoicesIfRendered(action) {
|
|
65066
|
+
const wf = action.wait_for;
|
|
65067
|
+
if (wf?.regex) {
|
|
65068
|
+
const re = new RegExp(wf.regex, wf.flags ?? "i");
|
|
65069
|
+
if (!re.test(this.readScreenSectionText(wf.section))) return null;
|
|
65070
|
+
}
|
|
65071
|
+
const options = this.extractPickerChoices(action);
|
|
65072
|
+
return options.length > 0 ? options : null;
|
|
65073
|
+
}
|
|
64983
65074
|
/** Poll the live screen until the picker's `wait_for` condition matches,
|
|
64984
65075
|
* up to a short budget. Returns true if it rendered, false on timeout. */
|
|
64985
65076
|
async waitForPickerRendered(action) {
|
|
@@ -66686,8 +66777,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66686
66777
|
if (!modal || buttons.length === 0) {
|
|
66687
66778
|
return autoApproveActive;
|
|
66688
66779
|
}
|
|
66689
|
-
const
|
|
66690
|
-
if (
|
|
66780
|
+
const modalKind = typeof modal?.kind === "string" ? modal.kind : "approval";
|
|
66781
|
+
if (modalKind !== "approval") {
|
|
66782
|
+
return autoApproveActive;
|
|
66783
|
+
}
|
|
66784
|
+
const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(buttons, this.provider);
|
|
66785
|
+
if (buttonIndex < 0 || !hasNegativeApprovalOption(buttons)) {
|
|
66691
66786
|
return autoApproveActive;
|
|
66692
66787
|
}
|
|
66693
66788
|
const modalSignature = [
|
|
@@ -66991,6 +67086,12 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
66991
67086
|
workspace: typeof event.workspace === "string" && event.workspace.trim() ? event.workspace : this.workingDir,
|
|
66992
67087
|
providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
|
|
66993
67088
|
};
|
|
67089
|
+
if (this.isMeshWorkerSession() && this.settings.meshActiveTaskId) {
|
|
67090
|
+
const existingTaskId = typeof enrichedEvent.taskId === "string" && enrichedEvent.taskId.trim() ? enrichedEvent.taskId : void 0;
|
|
67091
|
+
if (!existingTaskId) {
|
|
67092
|
+
enrichedEvent.taskId = this.settings.meshActiveTaskId;
|
|
67093
|
+
}
|
|
67094
|
+
}
|
|
66994
67095
|
if (this.context?.emitProviderEvent) {
|
|
66995
67096
|
this.context.emitProviderEvent(enrichedEvent);
|
|
66996
67097
|
} else {
|