@adhdev/daemon-core 0.9.82-rc.253 → 0.9.82-rc.255
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 +185 -121
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +185 -121
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +0 -3
- package/dist/providers/spec/fsm-driver.d.ts +1 -0
- package/package.json +1 -1
- package/src/commands/router.ts +55 -1
- package/src/mesh/mesh-events-coordinator.ts +94 -35
- package/src/mesh/mesh-events-pending.ts +14 -6
- package/src/mesh/mesh-work-queue.ts +60 -2
- package/src/providers/cli-provider-instance.ts +49 -101
- package/src/providers/spec/cli-adapter.ts +12 -8
- package/src/providers/spec/fsm-driver.ts +8 -3
package/dist/index.js
CHANGED
|
@@ -2670,6 +2670,30 @@ __export(mesh_work_queue_exports, {
|
|
|
2670
2670
|
updateTaskStatus: () => updateTaskStatus,
|
|
2671
2671
|
validateMeshTaskModeRequest: () => validateMeshTaskModeRequest
|
|
2672
2672
|
});
|
|
2673
|
+
function detectGitMutation(message) {
|
|
2674
|
+
const re = /\bgit\s+([a-z][a-z0-9-]*)/gi;
|
|
2675
|
+
let match;
|
|
2676
|
+
while ((match = re.exec(message)) !== null) {
|
|
2677
|
+
const sub = match[1].toLowerCase();
|
|
2678
|
+
if (GIT_MUTATION_SUBCOMMANDS.has(sub)) return true;
|
|
2679
|
+
if (sub === "stash") {
|
|
2680
|
+
const after = message.slice(re.lastIndex).match(/^\s+([a-z][a-z0-9-]*)/i);
|
|
2681
|
+
const next = after ? after[1].toLowerCase() : "";
|
|
2682
|
+
if (!GIT_STASH_READONLY_SUBCOMMANDS.has(next)) return true;
|
|
2683
|
+
} else if (sub === "checkout") {
|
|
2684
|
+
return true;
|
|
2685
|
+
} else if (sub === "submodule") {
|
|
2686
|
+
const after = message.slice(re.lastIndex).match(/^\s+([a-z][a-z0-9-]*)/i);
|
|
2687
|
+
const next = after ? after[1].toLowerCase() : "";
|
|
2688
|
+
if (next === "update" || next === "add" || next === "sync" || next === "deinit") return true;
|
|
2689
|
+
} else if (sub === "worktree") {
|
|
2690
|
+
const after = message.slice(re.lastIndex).match(/^\s+([a-z][a-z0-9-]*)/i);
|
|
2691
|
+
const next = after ? after[1].toLowerCase() : "";
|
|
2692
|
+
if (next === "add" || next === "remove" || next === "move" || next === "prune") return true;
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
return false;
|
|
2696
|
+
}
|
|
2673
2697
|
function normalizeMeshTaskMode(value) {
|
|
2674
2698
|
if (typeof value !== "string") return void 0;
|
|
2675
2699
|
const normalized = value.trim();
|
|
@@ -2683,7 +2707,11 @@ function validateMeshTaskModeRequest(mode, message) {
|
|
|
2683
2707
|
if (taskMode !== "live_debug_readonly") {
|
|
2684
2708
|
return { valid: true, taskMode, violations: [] };
|
|
2685
2709
|
}
|
|
2686
|
-
const
|
|
2710
|
+
const text = message || "";
|
|
2711
|
+
const violations = LIVE_DEBUG_READONLY_FORBIDDEN.filter((rule) => rule.pattern.test(text)).map((rule) => rule.label);
|
|
2712
|
+
if (detectGitMutation(text)) {
|
|
2713
|
+
violations.push("git_mutation");
|
|
2714
|
+
}
|
|
2687
2715
|
return {
|
|
2688
2716
|
valid: violations.length === 0,
|
|
2689
2717
|
taskMode,
|
|
@@ -3005,7 +3033,7 @@ function recordMeshToolCall(opts) {
|
|
|
3005
3033
|
return { rateLimitExceeded: false, callsInWindow: 0, advisory: null };
|
|
3006
3034
|
}
|
|
3007
3035
|
}
|
|
3008
|
-
var import_crypto5, ACTIVE_MESH_QUEUE_STATUSES, HISTORICAL_MESH_QUEUE_STATUSES, MESH_TASK_MODES, LIVE_DEBUG_READONLY_FORBIDDEN, DEPENDENCY_FAILURE_TERMINALS;
|
|
3036
|
+
var import_crypto5, ACTIVE_MESH_QUEUE_STATUSES, HISTORICAL_MESH_QUEUE_STATUSES, MESH_TASK_MODES, LIVE_DEBUG_READONLY_FORBIDDEN, GIT_MUTATION_SUBCOMMANDS, GIT_STASH_READONLY_SUBCOMMANDS, DEPENDENCY_FAILURE_TERMINALS;
|
|
3009
3037
|
var init_mesh_work_queue = __esm({
|
|
3010
3038
|
"src/mesh/mesh-work-queue.ts"() {
|
|
3011
3039
|
"use strict";
|
|
@@ -3018,13 +3046,35 @@ var init_mesh_work_queue = __esm({
|
|
|
3018
3046
|
MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
|
|
3019
3047
|
LIVE_DEBUG_READONLY_FORBIDDEN = [
|
|
3020
3048
|
{ label: "source_edit", pattern: /\b(edit|modify|patch|apply\s+patch|write\s+(?:to\s+)?(?:file|source)|overwrite|delete\s+file|remove\s+file|create\s+file|touch\s+file)\b/i },
|
|
3021
|
-
{ label: "git_mutation", pattern: /\b(?:git\s+(?:add|commit|push|reset|rebase|clean|checkout|switch|merge|tag|restore|rm|mv|stash|worktree\s+(?:add|remove|move))|push\b)/i },
|
|
3022
3049
|
{ label: "checkpoint", pattern: /\b(checkpoint|mesh_checkpoint)\b/i },
|
|
3023
3050
|
{ label: "deploy_or_version_bump", pattern: /\b(deploy|wrangler\s+deploy|version[-\s]?bump|npm\s+version|release|npm\s+publish|yarn\s+publish|pnpm\s+publish)\b/i },
|
|
3024
3051
|
{ label: "destructive_shell", pattern: /\b(rm\s+-rf|mv\s+\S+\s+\S+|truncate\s|tee\s+\S+|sed\s+-i|shred\b)\b/i },
|
|
3025
3052
|
{ label: "package_install", pattern: /\b(npm\s+(?:install|i|add|link|uninstall|remove)|yarn\s+(?:add|remove|link)|pnpm\s+(?:add|remove|link)|pip\s+install|brew\s+install|apt\s+install|cargo\s+install)\b/i },
|
|
3026
3053
|
{ label: "container_mutation", pattern: /\b(docker\s+(?:build|run|exec|push|tag|rmi|rm|create|start|stop|kill)|kubectl\s+(?:apply|delete|patch|replace|create|scale))\b/i }
|
|
3027
3054
|
];
|
|
3055
|
+
GIT_MUTATION_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
3056
|
+
"add",
|
|
3057
|
+
"commit",
|
|
3058
|
+
"push",
|
|
3059
|
+
"reset",
|
|
3060
|
+
"rebase",
|
|
3061
|
+
"clean",
|
|
3062
|
+
"switch",
|
|
3063
|
+
"merge",
|
|
3064
|
+
"tag",
|
|
3065
|
+
"restore",
|
|
3066
|
+
"rm",
|
|
3067
|
+
"mv",
|
|
3068
|
+
"cherry-pick",
|
|
3069
|
+
"revert",
|
|
3070
|
+
"pull",
|
|
3071
|
+
"fetch",
|
|
3072
|
+
"am",
|
|
3073
|
+
"apply",
|
|
3074
|
+
"gc",
|
|
3075
|
+
"prune"
|
|
3076
|
+
]);
|
|
3077
|
+
GIT_STASH_READONLY_SUBCOMMANDS = /* @__PURE__ */ new Set(["list", "show"]);
|
|
3028
3078
|
DEPENDENCY_FAILURE_TERMINALS = /* @__PURE__ */ new Set(["failed", "cancelled"]);
|
|
3029
3079
|
}
|
|
3030
3080
|
});
|
|
@@ -5839,12 +5889,11 @@ function refineTerminalEventFromLedger(meshId, pending) {
|
|
|
5839
5889
|
}
|
|
5840
5890
|
function reconcilePendingMeshCoordinatorEvents(meshId, events) {
|
|
5841
5891
|
const backfilled = refineTerminalEventFromLedger(meshId, events);
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
];
|
|
5892
|
+
const terminalJobIds = new Set(
|
|
5893
|
+
[...events.filter((event) => REFINE_TERMINAL_EVENTS.has(event.event)), ...backfilled].map((event) => readRefineJobId2(event)).filter(Boolean)
|
|
5894
|
+
);
|
|
5895
|
+
const reconciled = terminalJobIds.size === 0 ? events : events.filter((event) => !(event.event === "refine:accepted" && terminalJobIds.has(readRefineJobId2(event))));
|
|
5896
|
+
return backfilled.length === 0 ? reconciled : [...reconciled, ...backfilled];
|
|
5848
5897
|
}
|
|
5849
5898
|
function trimPendingEventsIfNeeded(path39) {
|
|
5850
5899
|
try {
|
|
@@ -6830,7 +6879,15 @@ function nodeHasActiveAssignment(meshId, nodeId) {
|
|
|
6830
6879
|
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
6831
6880
|
}
|
|
6832
6881
|
function sessionHasActiveAssignment(meshId, sessionId) {
|
|
6833
|
-
|
|
6882
|
+
if (getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedSessionId === sessionId)) {
|
|
6883
|
+
return true;
|
|
6884
|
+
}
|
|
6885
|
+
try {
|
|
6886
|
+
if (getActiveDirectDispatches(meshId).some((d) => d.sessionId === sessionId)) return true;
|
|
6887
|
+
if (hasUnterminalDirectDispatchLedgerEntry(meshId, sessionId)) return true;
|
|
6888
|
+
} catch {
|
|
6889
|
+
}
|
|
6890
|
+
return false;
|
|
6834
6891
|
}
|
|
6835
6892
|
function liveSessionCountForNode(components, meshId, nodeId) {
|
|
6836
6893
|
return components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
@@ -7197,6 +7254,9 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
|
|
|
7197
7254
|
function isMeshCoordinatorEvent(eventName) {
|
|
7198
7255
|
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
7199
7256
|
}
|
|
7257
|
+
function shouldForceInjectMeshEvent(eventName) {
|
|
7258
|
+
return typeof eventName === "string" && MESH_FORCE_INJECT_EVENTS.has(eventName);
|
|
7259
|
+
}
|
|
7200
7260
|
function injectMeshSystemMessage(components, args) {
|
|
7201
7261
|
const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
7202
7262
|
const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
@@ -7587,10 +7647,14 @@ function injectMeshSystemMessage(components, args) {
|
|
|
7587
7647
|
})) {
|
|
7588
7648
|
LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
7589
7649
|
}
|
|
7650
|
+
const forceInject = shouldForceInjectMeshEvent(args.event);
|
|
7590
7651
|
for (const coord of coordinatorInstances) {
|
|
7591
7652
|
const coordState = coord.getState();
|
|
7592
|
-
LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
7593
|
-
coord.onEvent("send_message", {
|
|
7653
|
+
LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}${forceInject ? " (force)" : ""}`);
|
|
7654
|
+
coord.onEvent("send_message", {
|
|
7655
|
+
input: { text: messageText, textFallback: messageText },
|
|
7656
|
+
...forceInject ? { force: true } : {}
|
|
7657
|
+
});
|
|
7594
7658
|
}
|
|
7595
7659
|
return { success: true, forwarded: coordinatorInstances.length };
|
|
7596
7660
|
}
|
|
@@ -7643,6 +7707,45 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
7643
7707
|
}
|
|
7644
7708
|
function setupMeshEventForwarding(components) {
|
|
7645
7709
|
components.instanceManager.onEvent((event) => {
|
|
7710
|
+
if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
|
|
7711
|
+
const flushInstanceId = readNonEmptyString2(event.instanceId);
|
|
7712
|
+
if (flushInstanceId) {
|
|
7713
|
+
const flushSource = components.instanceManager.getInstance(flushInstanceId);
|
|
7714
|
+
if (flushSource && flushSource.category === "cli") {
|
|
7715
|
+
const flushState = flushSource.getState();
|
|
7716
|
+
const flushSettings = flushState.settings && typeof flushState.settings === "object" ? flushState.settings : {};
|
|
7717
|
+
const coordinatorMeshId2 = readNonEmptyString2(flushSettings.meshCoordinatorFor);
|
|
7718
|
+
if (coordinatorMeshId2) {
|
|
7719
|
+
const status = readNonEmptyString2(flushState.status).toLowerCase();
|
|
7720
|
+
if (status === "idle") {
|
|
7721
|
+
try {
|
|
7722
|
+
const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
|
|
7723
|
+
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId2, localDaemonId);
|
|
7724
|
+
if (pendingEvents.length > 0) {
|
|
7725
|
+
LOG.info("MeshEvents", `Auto-flushing ${pendingEvents.length} pending coordinator event(s) for mesh ${coordinatorMeshId2} on coordinator idle`);
|
|
7726
|
+
for (const pending of pendingEvents) {
|
|
7727
|
+
if (!pending.coordinatorMessage) continue;
|
|
7728
|
+
const forcePending = shouldForceInjectMeshEvent(pending.event);
|
|
7729
|
+
flushSource.onEvent("send_message", {
|
|
7730
|
+
input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
|
|
7731
|
+
...forcePending ? { force: true } : {}
|
|
7732
|
+
});
|
|
7733
|
+
}
|
|
7734
|
+
}
|
|
7735
|
+
} catch (e) {
|
|
7736
|
+
LOG.warn("MeshEvents", `Failed to auto-flush pending coordinator events: ${e?.message || e}`);
|
|
7737
|
+
}
|
|
7738
|
+
}
|
|
7739
|
+
let hasDirectDispatch = false;
|
|
7740
|
+
try {
|
|
7741
|
+
hasDirectDispatch = getActiveDirectDispatches(coordinatorMeshId2).some((d) => d.sessionId === flushInstanceId) || hasUnterminalDirectDispatchLedgerEntry(coordinatorMeshId2, flushInstanceId);
|
|
7742
|
+
} catch {
|
|
7743
|
+
}
|
|
7744
|
+
if (!hasDirectDispatch) return;
|
|
7745
|
+
}
|
|
7746
|
+
}
|
|
7747
|
+
}
|
|
7748
|
+
}
|
|
7646
7749
|
if (!isMeshCoordinatorEvent(event.event)) return;
|
|
7647
7750
|
const instanceId = readNonEmptyString2(event.instanceId);
|
|
7648
7751
|
if (!instanceId) return;
|
|
@@ -7681,33 +7784,8 @@ function setupMeshEventForwarding(components) {
|
|
|
7681
7784
|
metadataEvent: event
|
|
7682
7785
|
});
|
|
7683
7786
|
});
|
|
7684
|
-
components.instanceManager.onEvent((event) => {
|
|
7685
|
-
if (event.event !== "agent:ready" && event.event !== "agent:generating_completed") return;
|
|
7686
|
-
const instanceId = readNonEmptyString2(event.instanceId);
|
|
7687
|
-
if (!instanceId) return;
|
|
7688
|
-
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
7689
|
-
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
7690
|
-
const state = sourceInstance.getState();
|
|
7691
|
-
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
7692
|
-
const coordinatorMeshId = readNonEmptyString2(settings.meshCoordinatorFor);
|
|
7693
|
-
if (!coordinatorMeshId) return;
|
|
7694
|
-
const status = readNonEmptyString2(state.status).toLowerCase();
|
|
7695
|
-
if (status !== "idle") return;
|
|
7696
|
-
try {
|
|
7697
|
-
const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
|
|
7698
|
-
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId, localDaemonId);
|
|
7699
|
-
if (pendingEvents.length === 0) return;
|
|
7700
|
-
LOG.info("MeshEvents", `Auto-flushing ${pendingEvents.length} pending coordinator event(s) for mesh ${coordinatorMeshId} on coordinator idle`);
|
|
7701
|
-
for (const pending of pendingEvents) {
|
|
7702
|
-
if (!pending.coordinatorMessage) continue;
|
|
7703
|
-
sourceInstance.onEvent("send_message", { input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage } });
|
|
7704
|
-
}
|
|
7705
|
-
} catch (e) {
|
|
7706
|
-
LOG.warn("MeshEvents", `Failed to auto-flush pending coordinator events: ${e?.message || e}`);
|
|
7707
|
-
}
|
|
7708
|
-
});
|
|
7709
7787
|
}
|
|
7710
|
-
var import_fs10, REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND;
|
|
7788
|
+
var import_fs10, REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, MESH_FORCE_INJECT_EVENTS;
|
|
7711
7789
|
var init_mesh_events_coordinator = __esm({
|
|
7712
7790
|
"src/mesh/mesh-events-coordinator.ts"() {
|
|
7713
7791
|
"use strict";
|
|
@@ -7753,6 +7831,15 @@ var init_mesh_events_coordinator = __esm({
|
|
|
7753
7831
|
"agent:stopped": "task_failed",
|
|
7754
7832
|
"monitor:long_generating": "task_stalled"
|
|
7755
7833
|
};
|
|
7834
|
+
MESH_FORCE_INJECT_EVENTS = /* @__PURE__ */ new Set([
|
|
7835
|
+
"agent:generating_completed",
|
|
7836
|
+
"agent:stopped",
|
|
7837
|
+
"agent:waiting_approval",
|
|
7838
|
+
"refine:completed",
|
|
7839
|
+
"refine:failed",
|
|
7840
|
+
"worktree_bootstrap_complete",
|
|
7841
|
+
"worktree_bootstrap_failed"
|
|
7842
|
+
]);
|
|
7756
7843
|
}
|
|
7757
7844
|
});
|
|
7758
7845
|
|
|
@@ -28697,7 +28784,12 @@ var FsmDriver = class {
|
|
|
28697
28784
|
const controls = this.deriveControls(state.id);
|
|
28698
28785
|
const title = modal?.title ?? this.deriveTitle(state, sections, lines.join("\n"));
|
|
28699
28786
|
const next = {
|
|
28700
|
-
|
|
28787
|
+
// status is derived from the FSM state itself (statusForState), NOT from
|
|
28788
|
+
// whether a modal was parsed this frame. A modal state whose buttons briefly
|
|
28789
|
+
// fail to parse (PTY repaint → deriveModal returns null) must still report
|
|
28790
|
+
// its authoritative status (e.g. 'approval'), so the adapter never collapses
|
|
28791
|
+
// an approval/busy state to idle on a transient modal-parse miss.
|
|
28792
|
+
state: { id: state.id, label: state.label, title, status: statusForState(state) },
|
|
28701
28793
|
modal,
|
|
28702
28794
|
controls
|
|
28703
28795
|
};
|
|
@@ -29798,20 +29890,18 @@ var SpecCliAdapter = class {
|
|
|
29798
29890
|
const state = this.latestState;
|
|
29799
29891
|
if (!state) return { status: "starting", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
|
|
29800
29892
|
const modal = this.latestModal;
|
|
29801
|
-
|
|
29802
|
-
if (modal) {
|
|
29893
|
+
if (state.status === "approval") {
|
|
29803
29894
|
return {
|
|
29804
29895
|
status: "waiting_approval",
|
|
29805
29896
|
messages: [],
|
|
29806
|
-
|
|
29807
|
-
|
|
29808
|
-
|
|
29809
|
-
},
|
|
29897
|
+
// Surface buttons when we have them; an approval state with no parsed
|
|
29898
|
+
// modal this frame still stays waiting_approval (no activeModal yet).
|
|
29899
|
+
activeModal: modal ? { message: modal.title ?? state.label, buttons: modal.buttons.map((b) => b.label) } : null,
|
|
29810
29900
|
activeInteractivePrompt: this.activeInteractivePrompt,
|
|
29811
29901
|
...sessionFields
|
|
29812
29902
|
};
|
|
29813
29903
|
}
|
|
29814
|
-
if (
|
|
29904
|
+
if (state.status === "generating") {
|
|
29815
29905
|
return { status: "generating", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
|
|
29816
29906
|
}
|
|
29817
29907
|
return { status: "idle", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
|
|
@@ -30532,7 +30622,6 @@ var CliProviderInstance = class {
|
|
|
30532
30622
|
runtimeMessages = [];
|
|
30533
30623
|
lastPersistedHistoryMessages = [];
|
|
30534
30624
|
lastAcknowledgedUserInputAt = 0;
|
|
30535
|
-
externalBusyIdleFingerprint = "";
|
|
30536
30625
|
lastNativeSourceCanonicalCheckAt = 0;
|
|
30537
30626
|
lastNativeSourceCanonicalCacheKey = void 0;
|
|
30538
30627
|
cachedSqliteDb = null;
|
|
@@ -30663,10 +30752,6 @@ var CliProviderInstance = class {
|
|
|
30663
30752
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, Date.now());
|
|
30664
30753
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
30665
30754
|
let visibleStatus = parseErrorMessage || parsedStatus?.status === "error" ? "error" : autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
30666
|
-
const externalNativeFinal = this.getExternalNativeFinalReconciliation(parsedStatus?.messages, adapterStatus);
|
|
30667
|
-
if (externalNativeFinal && isCliGeneratingLikeStatus(visibleStatus)) {
|
|
30668
|
-
visibleStatus = "idle";
|
|
30669
|
-
}
|
|
30670
30755
|
if (isCliGeneratingLikeStatus(visibleStatus) && this.lastStatus === "idle") {
|
|
30671
30756
|
visibleStatus = "idle";
|
|
30672
30757
|
}
|
|
@@ -30899,7 +30984,8 @@ var CliProviderInstance = class {
|
|
|
30899
30984
|
assertProviderSupportsDeclaredInput(this.provider, input);
|
|
30900
30985
|
const promptText = buildCliStructuredInputPrompt(input);
|
|
30901
30986
|
if (promptText) {
|
|
30902
|
-
|
|
30987
|
+
const force = data?.force === true;
|
|
30988
|
+
void this.adapter.sendMessage(promptText, force ? { force: true } : {}).catch((e) => {
|
|
30903
30989
|
LOG.warn("CLI", `[${this.type}] send_message failed: ${e?.message || e}`);
|
|
30904
30990
|
});
|
|
30905
30991
|
}
|
|
@@ -30944,7 +31030,6 @@ var CliProviderInstance = class {
|
|
|
30944
31030
|
if (!content) return;
|
|
30945
31031
|
const receivedAt = Date.now();
|
|
30946
31032
|
this.lastAcknowledgedUserInputAt = receivedAt;
|
|
30947
|
-
this.externalBusyIdleFingerprint = "";
|
|
30948
31033
|
const dedupKey = `user_input_ack:${crypto4.createHash("sha256").update(`${this.instanceId}:${content}:${receivedAt}`).digest("hex").slice(0, 24)}`;
|
|
30949
31034
|
this.appendRuntimeMessage(buildChatMessage({
|
|
30950
31035
|
role: "user",
|
|
@@ -31093,50 +31178,6 @@ var CliProviderInstance = class {
|
|
|
31093
31178
|
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
31094
31179
|
return extractFinalSummaryFromMessages(evidence.messages);
|
|
31095
31180
|
}
|
|
31096
|
-
externalNativeFinalFingerprint(evidence) {
|
|
31097
|
-
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
31098
|
-
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
31099
|
-
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
31100
|
-
const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
|
|
31101
|
-
const receivedAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
31102
|
-
const probe = this.lastExternalCompletionProbe;
|
|
31103
|
-
return crypto4.createHash("sha256").update([
|
|
31104
|
-
this.type,
|
|
31105
|
-
this.providerSessionId || "",
|
|
31106
|
-
probe?.sourcePath || "",
|
|
31107
|
-
String(probe?.sourceMtimeMs || 0),
|
|
31108
|
-
String(receivedAt || 0),
|
|
31109
|
-
content.slice(-500)
|
|
31110
|
-
].join("\0")).digest("hex").slice(0, 24);
|
|
31111
|
-
}
|
|
31112
|
-
getExternalNativeFinalReconciliation(parsedMessages, adapterStatus) {
|
|
31113
|
-
const rawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
|
|
31114
|
-
if (!isCliGeneratingLikeStatus(rawStatus)) return null;
|
|
31115
|
-
if (hasNonEmptyCliModalButtons(adapterStatus?.activeModal ?? adapterStatus?.modal)) return null;
|
|
31116
|
-
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
31117
|
-
if (evidence.source !== "external-native" || !evidence.present) return null;
|
|
31118
|
-
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
31119
|
-
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
31120
|
-
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
31121
|
-
const lastMessageAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
31122
|
-
const sourceMtimeMs = Number(this.lastExternalCompletionProbe?.sourceMtimeMs || 0);
|
|
31123
|
-
const minEvidenceAt = Math.max(
|
|
31124
|
-
this.startedAt > 0 ? this.startedAt - 5e3 : 0,
|
|
31125
|
-
this.generatingStartedAt > 0 ? this.generatingStartedAt - 5e3 : 0,
|
|
31126
|
-
this.lastAcknowledgedUserInputAt > 0 ? this.lastAcknowledgedUserInputAt - 1e3 : 0
|
|
31127
|
-
);
|
|
31128
|
-
if (minEvidenceAt > 0 && lastMessageAt > 0 && lastMessageAt < minEvidenceAt && sourceMtimeMs < minEvidenceAt) {
|
|
31129
|
-
return null;
|
|
31130
|
-
}
|
|
31131
|
-
const finalSummary = extractFinalSummaryFromMessages(evidence.messages);
|
|
31132
|
-
if (!finalSummary) return null;
|
|
31133
|
-
const fingerprint = this.externalNativeFinalFingerprint(evidence);
|
|
31134
|
-
if (fingerprint === this.externalBusyIdleFingerprint) {
|
|
31135
|
-
return { fingerprint, finalSummary, evidence };
|
|
31136
|
-
}
|
|
31137
|
-
this.externalBusyIdleFingerprint = fingerprint;
|
|
31138
|
-
return { fingerprint, finalSummary, evidence };
|
|
31139
|
-
}
|
|
31140
31181
|
buildCompletedFinalizationDiagnostic(args) {
|
|
31141
31182
|
let parsed = null;
|
|
31142
31183
|
let parseError;
|
|
@@ -31207,18 +31248,17 @@ var CliProviderInstance = class {
|
|
|
31207
31248
|
if (typeof adapterAny?.responseBuffer === "string" && adapterAny.responseBuffer.trim()) return false;
|
|
31208
31249
|
return true;
|
|
31209
31250
|
}
|
|
31210
|
-
getCompletedFinalizationBlock(latestVisibleStatus, pending
|
|
31251
|
+
getCompletedFinalizationBlock(latestVisibleStatus, pending) {
|
|
31211
31252
|
if (latestVisibleStatus !== "idle") return { reason: `status:${latestVisibleStatus}`, terminal: true };
|
|
31212
31253
|
const adapterAny = this.adapter;
|
|
31213
31254
|
const approvalResolvedIdle = pending.previousStatus === "waiting_approval";
|
|
31214
|
-
|
|
31215
|
-
if (!approvalResolvedIdle && !externalNativeFinal) {
|
|
31255
|
+
if (!approvalResolvedIdle) {
|
|
31216
31256
|
if (adapterAny?.isWaitingForResponse === true) return { reason: "adapter_waiting_for_response", terminal: true };
|
|
31217
31257
|
if (adapterAny?.currentTurnScope) return { reason: "adapter_turn_scope_active", terminal: true };
|
|
31218
31258
|
if (this.hasAdapterPendingResponse()) return { reason: "adapter_pending_response", terminal: true };
|
|
31219
31259
|
}
|
|
31220
31260
|
const partial = typeof this.adapter.getPartialResponse === "function" ? this.adapter.getPartialResponse() : "";
|
|
31221
|
-
if (
|
|
31261
|
+
if (typeof partial === "string" && partial.trim()) return { reason: "partial_response_pending", terminal: true };
|
|
31222
31262
|
let parsed;
|
|
31223
31263
|
try {
|
|
31224
31264
|
parsed = this.adapter.getScriptParsedStatus();
|
|
@@ -31228,7 +31268,6 @@ var CliProviderInstance = class {
|
|
|
31228
31268
|
const parsedStatus = typeof parsed?.status === "string" ? parsed.status : "unknown";
|
|
31229
31269
|
if (parsedStatus !== "idle") {
|
|
31230
31270
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
31231
|
-
if (externalNativeFinal && isCliGeneratingLikeStatus(parsedStatus)) return null;
|
|
31232
31271
|
if (this.shouldSuppressStaleParsedBusyStatus(parsed, adapterStatus)) return null;
|
|
31233
31272
|
return { reason: `parsed_status:${parsedStatus}`, terminal: isCliGeneratingLikeStatus(parsedStatus) };
|
|
31234
31273
|
}
|
|
@@ -31236,6 +31275,20 @@ var CliProviderInstance = class {
|
|
|
31236
31275
|
const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
|
|
31237
31276
|
const finalAssistantEvidence = this.completionFinalAssistantEvidence(parsed?.messages);
|
|
31238
31277
|
const allowMissingAssistantTimeout = !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.launchedByCoordinator);
|
|
31278
|
+
if (adapterOwnsMessagesElsewhere && finalAssistantEvidence.source === "external-native") {
|
|
31279
|
+
const prevProbe = (pending.transcriptProbeHistory || [])[(pending.transcriptProbeHistory?.length ?? 0) - 1];
|
|
31280
|
+
this.readExternalCompletionMessages();
|
|
31281
|
+
const settleProbe = this.lastExternalCompletionProbe;
|
|
31282
|
+
if (settleProbe && prevProbe) {
|
|
31283
|
+
const stillGrowing = settleProbe.msgCount > prevProbe.msgCount || settleProbe.lastRole === "assistant" && settleProbe.contentLen > prevProbe.contentLen;
|
|
31284
|
+
if (stillGrowing) {
|
|
31285
|
+
this.recordPendingTranscriptProbe(pending);
|
|
31286
|
+
return { reason: `transcript_settling:${prevProbe.contentLen}->${settleProbe.contentLen}`, terminal: false };
|
|
31287
|
+
}
|
|
31288
|
+
} else if (settleProbe) {
|
|
31289
|
+
this.recordPendingTranscriptProbe(pending);
|
|
31290
|
+
}
|
|
31291
|
+
}
|
|
31239
31292
|
LOG.debug("CLI", `[${this.type}] finalAssistantEvidence: present=${finalAssistantEvidence.present} source=${finalAssistantEvidence.source} adapterOwnsMessagesElsewhere=${adapterOwnsMessagesElsewhere} parsedStatus=${parsedStatus}`);
|
|
31240
31293
|
if (!finalAssistantEvidence.present) {
|
|
31241
31294
|
if (adapterOwnsMessagesElsewhere) {
|
|
@@ -31290,16 +31343,15 @@ var CliProviderInstance = class {
|
|
|
31290
31343
|
}
|
|
31291
31344
|
const latestStatus = this.adapter.getStatus({ allowParse: false });
|
|
31292
31345
|
const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
31293
|
-
const
|
|
31294
|
-
|
|
31295
|
-
LOG.debug("CLI", `[${this.type}] flush attempt: adapterStatus=${latestStatus.status} latestVisible=${latestVisibleStatus} externalNativeFinal=${!!externalNativeFinal} generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse} hasPartial=${!!this.adapter.getPartialResponse?.()}`);
|
|
31346
|
+
const latestVisibleStatus = latestAutoApproveActive || this.autoApproveBusy ? "generating" : latestStatus.status;
|
|
31347
|
+
LOG.debug("CLI", `[${this.type}] flush attempt: adapterStatus=${latestStatus.status} latestVisible=${latestVisibleStatus} generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse} hasPartial=${!!this.adapter.getPartialResponse?.()}`);
|
|
31296
31348
|
if (latestVisibleStatus !== "idle") {
|
|
31297
31349
|
LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
|
|
31298
31350
|
this.completedDebouncePending = null;
|
|
31299
31351
|
this.completedDebounceTimer = null;
|
|
31300
31352
|
return;
|
|
31301
31353
|
}
|
|
31302
|
-
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending
|
|
31354
|
+
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending);
|
|
31303
31355
|
if (block2) {
|
|
31304
31356
|
const blockReason = block2.reason;
|
|
31305
31357
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
@@ -31341,18 +31393,7 @@ var CliProviderInstance = class {
|
|
|
31341
31393
|
chatTitle: pending.chatTitle,
|
|
31342
31394
|
duration: pending.duration,
|
|
31343
31395
|
timestamp: pending.timestamp,
|
|
31344
|
-
finalSummary:
|
|
31345
|
-
...externalNativeFinal ? {
|
|
31346
|
-
completionDiagnostic: {
|
|
31347
|
-
providerType: this.type,
|
|
31348
|
-
sessionId: this.instanceId,
|
|
31349
|
-
providerSessionId: this.providerSessionId || null,
|
|
31350
|
-
reconciliationReason: "external_native_final_assistant_while_adapter_busy",
|
|
31351
|
-
finalAssistantPresent: true,
|
|
31352
|
-
finalAssistantEvidenceSource: externalNativeFinal.evidence.source,
|
|
31353
|
-
externalFinalFingerprint: externalNativeFinal.fingerprint
|
|
31354
|
-
}
|
|
31355
|
-
} : {}
|
|
31396
|
+
finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
|
|
31356
31397
|
});
|
|
31357
31398
|
this.completedDebouncePending = null;
|
|
31358
31399
|
this.completedDebounceTimer = null;
|
|
@@ -31408,9 +31449,8 @@ var CliProviderInstance = class {
|
|
|
31408
31449
|
const parsedStatus = null;
|
|
31409
31450
|
const rawStatus = adapterStatus.status;
|
|
31410
31451
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, now);
|
|
31411
|
-
const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, adapterStatus);
|
|
31412
31452
|
const autoApproveHoldIdle = this.autoApproveBusy && rawStatus === "idle";
|
|
31413
|
-
const newStatus =
|
|
31453
|
+
const newStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : rawStatus;
|
|
31414
31454
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
31415
31455
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
31416
31456
|
const partial = this.adapter.getPartialResponse();
|
|
@@ -39557,16 +39597,26 @@ function reconcileInlineMeshCache(cached, incoming) {
|
|
|
39557
39597
|
const nodeId = readInlineMeshNodeId(node);
|
|
39558
39598
|
if (nodeId) cachedById.set(nodeId, node);
|
|
39559
39599
|
}
|
|
39600
|
+
const mergedIncomingIds = /* @__PURE__ */ new Set();
|
|
39560
39601
|
const nodes = incomingNodes.map((incomingNode) => {
|
|
39561
39602
|
const nodeId = readInlineMeshNodeId(incomingNode);
|
|
39562
39603
|
const cachedNode = nodeId ? cachedById.get(nodeId) : void 0;
|
|
39563
39604
|
if (!cachedNode && preserveCachedMembership) return null;
|
|
39605
|
+
if (nodeId) mergedIncomingIds.add(nodeId);
|
|
39564
39606
|
if (!cachedNode) return incomingNode;
|
|
39565
39607
|
if (hasInlineMeshTransientNodeState(incomingNode)) {
|
|
39566
39608
|
return { ...cachedNode, ...incomingNode };
|
|
39567
39609
|
}
|
|
39568
39610
|
return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
|
|
39569
39611
|
}).filter(Boolean);
|
|
39612
|
+
if (preserveCachedMembership) {
|
|
39613
|
+
for (const cachedNode of cachedNodes) {
|
|
39614
|
+
const nodeId = readInlineMeshNodeId(cachedNode);
|
|
39615
|
+
if (nodeId && !mergedIncomingIds.has(nodeId)) {
|
|
39616
|
+
nodes.push(cachedNode);
|
|
39617
|
+
}
|
|
39618
|
+
}
|
|
39619
|
+
}
|
|
39570
39620
|
return {
|
|
39571
39621
|
...cached,
|
|
39572
39622
|
...incoming,
|
|
@@ -42481,6 +42531,18 @@ ${tail}` : ""
|
|
|
42481
42531
|
return { success: true };
|
|
42482
42532
|
}
|
|
42483
42533
|
case "launch_cli": {
|
|
42534
|
+
{
|
|
42535
|
+
const launchSettings = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
|
|
42536
|
+
const isMeshWorkerLaunch = !!launchSettings && (readStringValue(launchSettings.meshNodeFor) || launchSettings.launchedByCoordinator === true);
|
|
42537
|
+
const hasCoordinatorDaemonId = !!launchSettings && !!readStringValue(launchSettings.meshCoordinatorDaemonId);
|
|
42538
|
+
if (launchSettings && isMeshWorkerLaunch && !hasCoordinatorDaemonId) {
|
|
42539
|
+
try {
|
|
42540
|
+
const localDaemonId = readStringValue(loadConfig().machineId);
|
|
42541
|
+
if (localDaemonId) launchSettings.meshCoordinatorDaemonId = localDaemonId;
|
|
42542
|
+
} catch {
|
|
42543
|
+
}
|
|
42544
|
+
}
|
|
42545
|
+
}
|
|
42484
42546
|
const launchResult = await this.deps.cliManager.handleCliCommand(cmd, args);
|
|
42485
42547
|
const meshNodeId = readStringValue(args?.settings?.meshNodeId);
|
|
42486
42548
|
const meshId = readStringValue(args?.settings?.meshNodeFor);
|
|
@@ -43978,7 +44040,7 @@ ${tail}` : ""
|
|
|
43978
44040
|
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "worktree clone");
|
|
43979
44041
|
if (ownerFailure) return ownerFailure;
|
|
43980
44042
|
try {
|
|
43981
|
-
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
44043
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
43982
44044
|
const mesh = meshRecord?.mesh;
|
|
43983
44045
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
43984
44046
|
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
@@ -44029,6 +44091,8 @@ ${tail}` : ""
|
|
|
44029
44091
|
policy: { ...sourceNode.policy || {} }
|
|
44030
44092
|
});
|
|
44031
44093
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
44094
|
+
const inlineForReconcile = this.getCachedInlineMesh(meshId);
|
|
44095
|
+
if (inlineForReconcile) this.updateInlineMeshNode(meshId, inlineForReconcile, node);
|
|
44032
44096
|
this.invalidateAggregateMeshStatus(meshId);
|
|
44033
44097
|
}
|
|
44034
44098
|
const persistWorktreeSetupState = async (bootstrapState2) => {
|