@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.mjs
CHANGED
|
@@ -2666,6 +2666,30 @@ __export(mesh_work_queue_exports, {
|
|
|
2666
2666
|
validateMeshTaskModeRequest: () => validateMeshTaskModeRequest
|
|
2667
2667
|
});
|
|
2668
2668
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
2669
|
+
function detectGitMutation(message) {
|
|
2670
|
+
const re = /\bgit\s+([a-z][a-z0-9-]*)/gi;
|
|
2671
|
+
let match;
|
|
2672
|
+
while ((match = re.exec(message)) !== null) {
|
|
2673
|
+
const sub = match[1].toLowerCase();
|
|
2674
|
+
if (GIT_MUTATION_SUBCOMMANDS.has(sub)) return true;
|
|
2675
|
+
if (sub === "stash") {
|
|
2676
|
+
const after = message.slice(re.lastIndex).match(/^\s+([a-z][a-z0-9-]*)/i);
|
|
2677
|
+
const next = after ? after[1].toLowerCase() : "";
|
|
2678
|
+
if (!GIT_STASH_READONLY_SUBCOMMANDS.has(next)) return true;
|
|
2679
|
+
} else if (sub === "checkout") {
|
|
2680
|
+
return true;
|
|
2681
|
+
} else if (sub === "submodule") {
|
|
2682
|
+
const after = message.slice(re.lastIndex).match(/^\s+([a-z][a-z0-9-]*)/i);
|
|
2683
|
+
const next = after ? after[1].toLowerCase() : "";
|
|
2684
|
+
if (next === "update" || next === "add" || next === "sync" || next === "deinit") return true;
|
|
2685
|
+
} else if (sub === "worktree") {
|
|
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 === "add" || next === "remove" || next === "move" || next === "prune") return true;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
return false;
|
|
2692
|
+
}
|
|
2669
2693
|
function normalizeMeshTaskMode(value) {
|
|
2670
2694
|
if (typeof value !== "string") return void 0;
|
|
2671
2695
|
const normalized = value.trim();
|
|
@@ -2679,7 +2703,11 @@ function validateMeshTaskModeRequest(mode, message) {
|
|
|
2679
2703
|
if (taskMode !== "live_debug_readonly") {
|
|
2680
2704
|
return { valid: true, taskMode, violations: [] };
|
|
2681
2705
|
}
|
|
2682
|
-
const
|
|
2706
|
+
const text = message || "";
|
|
2707
|
+
const violations = LIVE_DEBUG_READONLY_FORBIDDEN.filter((rule) => rule.pattern.test(text)).map((rule) => rule.label);
|
|
2708
|
+
if (detectGitMutation(text)) {
|
|
2709
|
+
violations.push("git_mutation");
|
|
2710
|
+
}
|
|
2683
2711
|
return {
|
|
2684
2712
|
valid: violations.length === 0,
|
|
2685
2713
|
taskMode,
|
|
@@ -3001,7 +3029,7 @@ function recordMeshToolCall(opts) {
|
|
|
3001
3029
|
return { rateLimitExceeded: false, callsInWindow: 0, advisory: null };
|
|
3002
3030
|
}
|
|
3003
3031
|
}
|
|
3004
|
-
var ACTIVE_MESH_QUEUE_STATUSES, HISTORICAL_MESH_QUEUE_STATUSES, MESH_TASK_MODES, LIVE_DEBUG_READONLY_FORBIDDEN, DEPENDENCY_FAILURE_TERMINALS;
|
|
3032
|
+
var 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;
|
|
3005
3033
|
var init_mesh_work_queue = __esm({
|
|
3006
3034
|
"src/mesh/mesh-work-queue.ts"() {
|
|
3007
3035
|
"use strict";
|
|
@@ -3013,13 +3041,35 @@ var init_mesh_work_queue = __esm({
|
|
|
3013
3041
|
MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
|
|
3014
3042
|
LIVE_DEBUG_READONLY_FORBIDDEN = [
|
|
3015
3043
|
{ 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 },
|
|
3016
|
-
{ 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 },
|
|
3017
3044
|
{ label: "checkpoint", pattern: /\b(checkpoint|mesh_checkpoint)\b/i },
|
|
3018
3045
|
{ 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 },
|
|
3019
3046
|
{ 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 },
|
|
3020
3047
|
{ 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 },
|
|
3021
3048
|
{ 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 }
|
|
3022
3049
|
];
|
|
3050
|
+
GIT_MUTATION_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
3051
|
+
"add",
|
|
3052
|
+
"commit",
|
|
3053
|
+
"push",
|
|
3054
|
+
"reset",
|
|
3055
|
+
"rebase",
|
|
3056
|
+
"clean",
|
|
3057
|
+
"switch",
|
|
3058
|
+
"merge",
|
|
3059
|
+
"tag",
|
|
3060
|
+
"restore",
|
|
3061
|
+
"rm",
|
|
3062
|
+
"mv",
|
|
3063
|
+
"cherry-pick",
|
|
3064
|
+
"revert",
|
|
3065
|
+
"pull",
|
|
3066
|
+
"fetch",
|
|
3067
|
+
"am",
|
|
3068
|
+
"apply",
|
|
3069
|
+
"gc",
|
|
3070
|
+
"prune"
|
|
3071
|
+
]);
|
|
3072
|
+
GIT_STASH_READONLY_SUBCOMMANDS = /* @__PURE__ */ new Set(["list", "show"]);
|
|
3023
3073
|
DEPENDENCY_FAILURE_TERMINALS = /* @__PURE__ */ new Set(["failed", "cancelled"]);
|
|
3024
3074
|
}
|
|
3025
3075
|
});
|
|
@@ -5836,12 +5886,11 @@ function refineTerminalEventFromLedger(meshId, pending) {
|
|
|
5836
5886
|
}
|
|
5837
5887
|
function reconcilePendingMeshCoordinatorEvents(meshId, events) {
|
|
5838
5888
|
const backfilled = refineTerminalEventFromLedger(meshId, events);
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
];
|
|
5889
|
+
const terminalJobIds = new Set(
|
|
5890
|
+
[...events.filter((event) => REFINE_TERMINAL_EVENTS.has(event.event)), ...backfilled].map((event) => readRefineJobId2(event)).filter(Boolean)
|
|
5891
|
+
);
|
|
5892
|
+
const reconciled = terminalJobIds.size === 0 ? events : events.filter((event) => !(event.event === "refine:accepted" && terminalJobIds.has(readRefineJobId2(event))));
|
|
5893
|
+
return backfilled.length === 0 ? reconciled : [...reconciled, ...backfilled];
|
|
5845
5894
|
}
|
|
5846
5895
|
function trimPendingEventsIfNeeded(path39) {
|
|
5847
5896
|
try {
|
|
@@ -6824,7 +6873,15 @@ function nodeHasActiveAssignment(meshId, nodeId) {
|
|
|
6824
6873
|
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
6825
6874
|
}
|
|
6826
6875
|
function sessionHasActiveAssignment(meshId, sessionId) {
|
|
6827
|
-
|
|
6876
|
+
if (getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedSessionId === sessionId)) {
|
|
6877
|
+
return true;
|
|
6878
|
+
}
|
|
6879
|
+
try {
|
|
6880
|
+
if (getActiveDirectDispatches(meshId).some((d) => d.sessionId === sessionId)) return true;
|
|
6881
|
+
if (hasUnterminalDirectDispatchLedgerEntry(meshId, sessionId)) return true;
|
|
6882
|
+
} catch {
|
|
6883
|
+
}
|
|
6884
|
+
return false;
|
|
6828
6885
|
}
|
|
6829
6886
|
function liveSessionCountForNode(components, meshId, nodeId) {
|
|
6830
6887
|
return components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
@@ -7191,6 +7248,9 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
|
|
|
7191
7248
|
function isMeshCoordinatorEvent(eventName) {
|
|
7192
7249
|
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
7193
7250
|
}
|
|
7251
|
+
function shouldForceInjectMeshEvent(eventName) {
|
|
7252
|
+
return typeof eventName === "string" && MESH_FORCE_INJECT_EVENTS.has(eventName);
|
|
7253
|
+
}
|
|
7194
7254
|
function injectMeshSystemMessage(components, args) {
|
|
7195
7255
|
const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
7196
7256
|
const eventNodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
@@ -7581,10 +7641,14 @@ function injectMeshSystemMessage(components, args) {
|
|
|
7581
7641
|
})) {
|
|
7582
7642
|
LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
7583
7643
|
}
|
|
7644
|
+
const forceInject = shouldForceInjectMeshEvent(args.event);
|
|
7584
7645
|
for (const coord of coordinatorInstances) {
|
|
7585
7646
|
const coordState = coord.getState();
|
|
7586
|
-
LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
7587
|
-
coord.onEvent("send_message", {
|
|
7647
|
+
LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}${forceInject ? " (force)" : ""}`);
|
|
7648
|
+
coord.onEvent("send_message", {
|
|
7649
|
+
input: { text: messageText, textFallback: messageText },
|
|
7650
|
+
...forceInject ? { force: true } : {}
|
|
7651
|
+
});
|
|
7588
7652
|
}
|
|
7589
7653
|
return { success: true, forwarded: coordinatorInstances.length };
|
|
7590
7654
|
}
|
|
@@ -7637,6 +7701,45 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
7637
7701
|
}
|
|
7638
7702
|
function setupMeshEventForwarding(components) {
|
|
7639
7703
|
components.instanceManager.onEvent((event) => {
|
|
7704
|
+
if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
|
|
7705
|
+
const flushInstanceId = readNonEmptyString2(event.instanceId);
|
|
7706
|
+
if (flushInstanceId) {
|
|
7707
|
+
const flushSource = components.instanceManager.getInstance(flushInstanceId);
|
|
7708
|
+
if (flushSource && flushSource.category === "cli") {
|
|
7709
|
+
const flushState = flushSource.getState();
|
|
7710
|
+
const flushSettings = flushState.settings && typeof flushState.settings === "object" ? flushState.settings : {};
|
|
7711
|
+
const coordinatorMeshId2 = readNonEmptyString2(flushSettings.meshCoordinatorFor);
|
|
7712
|
+
if (coordinatorMeshId2) {
|
|
7713
|
+
const status = readNonEmptyString2(flushState.status).toLowerCase();
|
|
7714
|
+
if (status === "idle") {
|
|
7715
|
+
try {
|
|
7716
|
+
const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
|
|
7717
|
+
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId2, localDaemonId);
|
|
7718
|
+
if (pendingEvents.length > 0) {
|
|
7719
|
+
LOG.info("MeshEvents", `Auto-flushing ${pendingEvents.length} pending coordinator event(s) for mesh ${coordinatorMeshId2} on coordinator idle`);
|
|
7720
|
+
for (const pending of pendingEvents) {
|
|
7721
|
+
if (!pending.coordinatorMessage) continue;
|
|
7722
|
+
const forcePending = shouldForceInjectMeshEvent(pending.event);
|
|
7723
|
+
flushSource.onEvent("send_message", {
|
|
7724
|
+
input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
|
|
7725
|
+
...forcePending ? { force: true } : {}
|
|
7726
|
+
});
|
|
7727
|
+
}
|
|
7728
|
+
}
|
|
7729
|
+
} catch (e) {
|
|
7730
|
+
LOG.warn("MeshEvents", `Failed to auto-flush pending coordinator events: ${e?.message || e}`);
|
|
7731
|
+
}
|
|
7732
|
+
}
|
|
7733
|
+
let hasDirectDispatch = false;
|
|
7734
|
+
try {
|
|
7735
|
+
hasDirectDispatch = getActiveDirectDispatches(coordinatorMeshId2).some((d) => d.sessionId === flushInstanceId) || hasUnterminalDirectDispatchLedgerEntry(coordinatorMeshId2, flushInstanceId);
|
|
7736
|
+
} catch {
|
|
7737
|
+
}
|
|
7738
|
+
if (!hasDirectDispatch) return;
|
|
7739
|
+
}
|
|
7740
|
+
}
|
|
7741
|
+
}
|
|
7742
|
+
}
|
|
7640
7743
|
if (!isMeshCoordinatorEvent(event.event)) return;
|
|
7641
7744
|
const instanceId = readNonEmptyString2(event.instanceId);
|
|
7642
7745
|
if (!instanceId) return;
|
|
@@ -7675,33 +7778,8 @@ function setupMeshEventForwarding(components) {
|
|
|
7675
7778
|
metadataEvent: event
|
|
7676
7779
|
});
|
|
7677
7780
|
});
|
|
7678
|
-
components.instanceManager.onEvent((event) => {
|
|
7679
|
-
if (event.event !== "agent:ready" && event.event !== "agent:generating_completed") return;
|
|
7680
|
-
const instanceId = readNonEmptyString2(event.instanceId);
|
|
7681
|
-
if (!instanceId) return;
|
|
7682
|
-
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
7683
|
-
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
7684
|
-
const state = sourceInstance.getState();
|
|
7685
|
-
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
7686
|
-
const coordinatorMeshId = readNonEmptyString2(settings.meshCoordinatorFor);
|
|
7687
|
-
if (!coordinatorMeshId) return;
|
|
7688
|
-
const status = readNonEmptyString2(state.status).toLowerCase();
|
|
7689
|
-
if (status !== "idle") return;
|
|
7690
|
-
try {
|
|
7691
|
-
const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
|
|
7692
|
-
const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId, localDaemonId);
|
|
7693
|
-
if (pendingEvents.length === 0) return;
|
|
7694
|
-
LOG.info("MeshEvents", `Auto-flushing ${pendingEvents.length} pending coordinator event(s) for mesh ${coordinatorMeshId} on coordinator idle`);
|
|
7695
|
-
for (const pending of pendingEvents) {
|
|
7696
|
-
if (!pending.coordinatorMessage) continue;
|
|
7697
|
-
sourceInstance.onEvent("send_message", { input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage } });
|
|
7698
|
-
}
|
|
7699
|
-
} catch (e) {
|
|
7700
|
-
LOG.warn("MeshEvents", `Failed to auto-flush pending coordinator events: ${e?.message || e}`);
|
|
7701
|
-
}
|
|
7702
|
-
});
|
|
7703
7781
|
}
|
|
7704
|
-
var 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;
|
|
7782
|
+
var 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;
|
|
7705
7783
|
var init_mesh_events_coordinator = __esm({
|
|
7706
7784
|
"src/mesh/mesh-events-coordinator.ts"() {
|
|
7707
7785
|
"use strict";
|
|
@@ -7746,6 +7824,15 @@ var init_mesh_events_coordinator = __esm({
|
|
|
7746
7824
|
"agent:stopped": "task_failed",
|
|
7747
7825
|
"monitor:long_generating": "task_stalled"
|
|
7748
7826
|
};
|
|
7827
|
+
MESH_FORCE_INJECT_EVENTS = /* @__PURE__ */ new Set([
|
|
7828
|
+
"agent:generating_completed",
|
|
7829
|
+
"agent:stopped",
|
|
7830
|
+
"agent:waiting_approval",
|
|
7831
|
+
"refine:completed",
|
|
7832
|
+
"refine:failed",
|
|
7833
|
+
"worktree_bootstrap_complete",
|
|
7834
|
+
"worktree_bootstrap_failed"
|
|
7835
|
+
]);
|
|
7749
7836
|
}
|
|
7750
7837
|
});
|
|
7751
7838
|
|
|
@@ -28365,7 +28452,12 @@ var FsmDriver = class {
|
|
|
28365
28452
|
const controls = this.deriveControls(state.id);
|
|
28366
28453
|
const title = modal?.title ?? this.deriveTitle(state, sections, lines.join("\n"));
|
|
28367
28454
|
const next = {
|
|
28368
|
-
|
|
28455
|
+
// status is derived from the FSM state itself (statusForState), NOT from
|
|
28456
|
+
// whether a modal was parsed this frame. A modal state whose buttons briefly
|
|
28457
|
+
// fail to parse (PTY repaint → deriveModal returns null) must still report
|
|
28458
|
+
// its authoritative status (e.g. 'approval'), so the adapter never collapses
|
|
28459
|
+
// an approval/busy state to idle on a transient modal-parse miss.
|
|
28460
|
+
state: { id: state.id, label: state.label, title, status: statusForState(state) },
|
|
28369
28461
|
modal,
|
|
28370
28462
|
controls
|
|
28371
28463
|
};
|
|
@@ -29466,20 +29558,18 @@ var SpecCliAdapter = class {
|
|
|
29466
29558
|
const state = this.latestState;
|
|
29467
29559
|
if (!state) return { status: "starting", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
|
|
29468
29560
|
const modal = this.latestModal;
|
|
29469
|
-
|
|
29470
|
-
if (modal) {
|
|
29561
|
+
if (state.status === "approval") {
|
|
29471
29562
|
return {
|
|
29472
29563
|
status: "waiting_approval",
|
|
29473
29564
|
messages: [],
|
|
29474
|
-
|
|
29475
|
-
|
|
29476
|
-
|
|
29477
|
-
},
|
|
29565
|
+
// Surface buttons when we have them; an approval state with no parsed
|
|
29566
|
+
// modal this frame still stays waiting_approval (no activeModal yet).
|
|
29567
|
+
activeModal: modal ? { message: modal.title ?? state.label, buttons: modal.buttons.map((b) => b.label) } : null,
|
|
29478
29568
|
activeInteractivePrompt: this.activeInteractivePrompt,
|
|
29479
29569
|
...sessionFields
|
|
29480
29570
|
};
|
|
29481
29571
|
}
|
|
29482
|
-
if (
|
|
29572
|
+
if (state.status === "generating") {
|
|
29483
29573
|
return { status: "generating", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
|
|
29484
29574
|
}
|
|
29485
29575
|
return { status: "idle", messages: [], activeModal: null, activeInteractivePrompt: this.activeInteractivePrompt, ...sessionFields };
|
|
@@ -30200,7 +30290,6 @@ var CliProviderInstance = class {
|
|
|
30200
30290
|
runtimeMessages = [];
|
|
30201
30291
|
lastPersistedHistoryMessages = [];
|
|
30202
30292
|
lastAcknowledgedUserInputAt = 0;
|
|
30203
|
-
externalBusyIdleFingerprint = "";
|
|
30204
30293
|
lastNativeSourceCanonicalCheckAt = 0;
|
|
30205
30294
|
lastNativeSourceCanonicalCacheKey = void 0;
|
|
30206
30295
|
cachedSqliteDb = null;
|
|
@@ -30331,10 +30420,6 @@ var CliProviderInstance = class {
|
|
|
30331
30420
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, Date.now());
|
|
30332
30421
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
30333
30422
|
let visibleStatus = parseErrorMessage || parsedStatus?.status === "error" ? "error" : autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
30334
|
-
const externalNativeFinal = this.getExternalNativeFinalReconciliation(parsedStatus?.messages, adapterStatus);
|
|
30335
|
-
if (externalNativeFinal && isCliGeneratingLikeStatus(visibleStatus)) {
|
|
30336
|
-
visibleStatus = "idle";
|
|
30337
|
-
}
|
|
30338
30423
|
if (isCliGeneratingLikeStatus(visibleStatus) && this.lastStatus === "idle") {
|
|
30339
30424
|
visibleStatus = "idle";
|
|
30340
30425
|
}
|
|
@@ -30567,7 +30652,8 @@ var CliProviderInstance = class {
|
|
|
30567
30652
|
assertProviderSupportsDeclaredInput(this.provider, input);
|
|
30568
30653
|
const promptText = buildCliStructuredInputPrompt(input);
|
|
30569
30654
|
if (promptText) {
|
|
30570
|
-
|
|
30655
|
+
const force = data?.force === true;
|
|
30656
|
+
void this.adapter.sendMessage(promptText, force ? { force: true } : {}).catch((e) => {
|
|
30571
30657
|
LOG.warn("CLI", `[${this.type}] send_message failed: ${e?.message || e}`);
|
|
30572
30658
|
});
|
|
30573
30659
|
}
|
|
@@ -30612,7 +30698,6 @@ var CliProviderInstance = class {
|
|
|
30612
30698
|
if (!content) return;
|
|
30613
30699
|
const receivedAt = Date.now();
|
|
30614
30700
|
this.lastAcknowledgedUserInputAt = receivedAt;
|
|
30615
|
-
this.externalBusyIdleFingerprint = "";
|
|
30616
30701
|
const dedupKey = `user_input_ack:${crypto4.createHash("sha256").update(`${this.instanceId}:${content}:${receivedAt}`).digest("hex").slice(0, 24)}`;
|
|
30617
30702
|
this.appendRuntimeMessage(buildChatMessage({
|
|
30618
30703
|
role: "user",
|
|
@@ -30761,50 +30846,6 @@ var CliProviderInstance = class {
|
|
|
30761
30846
|
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
30762
30847
|
return extractFinalSummaryFromMessages(evidence.messages);
|
|
30763
30848
|
}
|
|
30764
|
-
externalNativeFinalFingerprint(evidence) {
|
|
30765
|
-
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
30766
|
-
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
30767
|
-
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
30768
|
-
const content = lastVisible ? flattenContent(lastVisible.content).trim() : "";
|
|
30769
|
-
const receivedAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
30770
|
-
const probe = this.lastExternalCompletionProbe;
|
|
30771
|
-
return crypto4.createHash("sha256").update([
|
|
30772
|
-
this.type,
|
|
30773
|
-
this.providerSessionId || "",
|
|
30774
|
-
probe?.sourcePath || "",
|
|
30775
|
-
String(probe?.sourceMtimeMs || 0),
|
|
30776
|
-
String(receivedAt || 0),
|
|
30777
|
-
content.slice(-500)
|
|
30778
|
-
].join("\0")).digest("hex").slice(0, 24);
|
|
30779
|
-
}
|
|
30780
|
-
getExternalNativeFinalReconciliation(parsedMessages, adapterStatus) {
|
|
30781
|
-
const rawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
|
|
30782
|
-
if (!isCliGeneratingLikeStatus(rawStatus)) return null;
|
|
30783
|
-
if (hasNonEmptyCliModalButtons(adapterStatus?.activeModal ?? adapterStatus?.modal)) return null;
|
|
30784
|
-
const evidence = this.completionFinalAssistantEvidence(parsedMessages);
|
|
30785
|
-
if (evidence.source !== "external-native" || !evidence.present) return null;
|
|
30786
|
-
const messages = Array.isArray(evidence.messages) ? evidence.messages : [];
|
|
30787
|
-
const visibleMessages = messages.filter((message) => isUserFacingChatMessage(message));
|
|
30788
|
-
const lastVisible = visibleMessages[visibleMessages.length - 1];
|
|
30789
|
-
const lastMessageAt = lastVisible ? getMessageTime(lastVisible) : 0;
|
|
30790
|
-
const sourceMtimeMs = Number(this.lastExternalCompletionProbe?.sourceMtimeMs || 0);
|
|
30791
|
-
const minEvidenceAt = Math.max(
|
|
30792
|
-
this.startedAt > 0 ? this.startedAt - 5e3 : 0,
|
|
30793
|
-
this.generatingStartedAt > 0 ? this.generatingStartedAt - 5e3 : 0,
|
|
30794
|
-
this.lastAcknowledgedUserInputAt > 0 ? this.lastAcknowledgedUserInputAt - 1e3 : 0
|
|
30795
|
-
);
|
|
30796
|
-
if (minEvidenceAt > 0 && lastMessageAt > 0 && lastMessageAt < minEvidenceAt && sourceMtimeMs < minEvidenceAt) {
|
|
30797
|
-
return null;
|
|
30798
|
-
}
|
|
30799
|
-
const finalSummary = extractFinalSummaryFromMessages(evidence.messages);
|
|
30800
|
-
if (!finalSummary) return null;
|
|
30801
|
-
const fingerprint = this.externalNativeFinalFingerprint(evidence);
|
|
30802
|
-
if (fingerprint === this.externalBusyIdleFingerprint) {
|
|
30803
|
-
return { fingerprint, finalSummary, evidence };
|
|
30804
|
-
}
|
|
30805
|
-
this.externalBusyIdleFingerprint = fingerprint;
|
|
30806
|
-
return { fingerprint, finalSummary, evidence };
|
|
30807
|
-
}
|
|
30808
30849
|
buildCompletedFinalizationDiagnostic(args) {
|
|
30809
30850
|
let parsed = null;
|
|
30810
30851
|
let parseError;
|
|
@@ -30875,18 +30916,17 @@ var CliProviderInstance = class {
|
|
|
30875
30916
|
if (typeof adapterAny?.responseBuffer === "string" && adapterAny.responseBuffer.trim()) return false;
|
|
30876
30917
|
return true;
|
|
30877
30918
|
}
|
|
30878
|
-
getCompletedFinalizationBlock(latestVisibleStatus, pending
|
|
30919
|
+
getCompletedFinalizationBlock(latestVisibleStatus, pending) {
|
|
30879
30920
|
if (latestVisibleStatus !== "idle") return { reason: `status:${latestVisibleStatus}`, terminal: true };
|
|
30880
30921
|
const adapterAny = this.adapter;
|
|
30881
30922
|
const approvalResolvedIdle = pending.previousStatus === "waiting_approval";
|
|
30882
|
-
|
|
30883
|
-
if (!approvalResolvedIdle && !externalNativeFinal) {
|
|
30923
|
+
if (!approvalResolvedIdle) {
|
|
30884
30924
|
if (adapterAny?.isWaitingForResponse === true) return { reason: "adapter_waiting_for_response", terminal: true };
|
|
30885
30925
|
if (adapterAny?.currentTurnScope) return { reason: "adapter_turn_scope_active", terminal: true };
|
|
30886
30926
|
if (this.hasAdapterPendingResponse()) return { reason: "adapter_pending_response", terminal: true };
|
|
30887
30927
|
}
|
|
30888
30928
|
const partial = typeof this.adapter.getPartialResponse === "function" ? this.adapter.getPartialResponse() : "";
|
|
30889
|
-
if (
|
|
30929
|
+
if (typeof partial === "string" && partial.trim()) return { reason: "partial_response_pending", terminal: true };
|
|
30890
30930
|
let parsed;
|
|
30891
30931
|
try {
|
|
30892
30932
|
parsed = this.adapter.getScriptParsedStatus();
|
|
@@ -30896,7 +30936,6 @@ var CliProviderInstance = class {
|
|
|
30896
30936
|
const parsedStatus = typeof parsed?.status === "string" ? parsed.status : "unknown";
|
|
30897
30937
|
if (parsedStatus !== "idle") {
|
|
30898
30938
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
30899
|
-
if (externalNativeFinal && isCliGeneratingLikeStatus(parsedStatus)) return null;
|
|
30900
30939
|
if (this.shouldSuppressStaleParsedBusyStatus(parsed, adapterStatus)) return null;
|
|
30901
30940
|
return { reason: `parsed_status:${parsedStatus}`, terminal: isCliGeneratingLikeStatus(parsedStatus) };
|
|
30902
30941
|
}
|
|
@@ -30904,6 +30943,20 @@ var CliProviderInstance = class {
|
|
|
30904
30943
|
const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
|
|
30905
30944
|
const finalAssistantEvidence = this.completionFinalAssistantEvidence(parsed?.messages);
|
|
30906
30945
|
const allowMissingAssistantTimeout = !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.launchedByCoordinator);
|
|
30946
|
+
if (adapterOwnsMessagesElsewhere && finalAssistantEvidence.source === "external-native") {
|
|
30947
|
+
const prevProbe = (pending.transcriptProbeHistory || [])[(pending.transcriptProbeHistory?.length ?? 0) - 1];
|
|
30948
|
+
this.readExternalCompletionMessages();
|
|
30949
|
+
const settleProbe = this.lastExternalCompletionProbe;
|
|
30950
|
+
if (settleProbe && prevProbe) {
|
|
30951
|
+
const stillGrowing = settleProbe.msgCount > prevProbe.msgCount || settleProbe.lastRole === "assistant" && settleProbe.contentLen > prevProbe.contentLen;
|
|
30952
|
+
if (stillGrowing) {
|
|
30953
|
+
this.recordPendingTranscriptProbe(pending);
|
|
30954
|
+
return { reason: `transcript_settling:${prevProbe.contentLen}->${settleProbe.contentLen}`, terminal: false };
|
|
30955
|
+
}
|
|
30956
|
+
} else if (settleProbe) {
|
|
30957
|
+
this.recordPendingTranscriptProbe(pending);
|
|
30958
|
+
}
|
|
30959
|
+
}
|
|
30907
30960
|
LOG.debug("CLI", `[${this.type}] finalAssistantEvidence: present=${finalAssistantEvidence.present} source=${finalAssistantEvidence.source} adapterOwnsMessagesElsewhere=${adapterOwnsMessagesElsewhere} parsedStatus=${parsedStatus}`);
|
|
30908
30961
|
if (!finalAssistantEvidence.present) {
|
|
30909
30962
|
if (adapterOwnsMessagesElsewhere) {
|
|
@@ -30958,16 +31011,15 @@ var CliProviderInstance = class {
|
|
|
30958
31011
|
}
|
|
30959
31012
|
const latestStatus = this.adapter.getStatus({ allowParse: false });
|
|
30960
31013
|
const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
30961
|
-
const
|
|
30962
|
-
|
|
30963
|
-
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?.()}`);
|
|
31014
|
+
const latestVisibleStatus = latestAutoApproveActive || this.autoApproveBusy ? "generating" : latestStatus.status;
|
|
31015
|
+
LOG.debug("CLI", `[${this.type}] flush attempt: adapterStatus=${latestStatus.status} latestVisible=${latestVisibleStatus} generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse} hasPartial=${!!this.adapter.getPartialResponse?.()}`);
|
|
30964
31016
|
if (latestVisibleStatus !== "idle") {
|
|
30965
31017
|
LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
|
|
30966
31018
|
this.completedDebouncePending = null;
|
|
30967
31019
|
this.completedDebounceTimer = null;
|
|
30968
31020
|
return;
|
|
30969
31021
|
}
|
|
30970
|
-
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending
|
|
31022
|
+
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending);
|
|
30971
31023
|
if (block2) {
|
|
30972
31024
|
const blockReason = block2.reason;
|
|
30973
31025
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
@@ -31009,18 +31061,7 @@ var CliProviderInstance = class {
|
|
|
31009
31061
|
chatTitle: pending.chatTitle,
|
|
31010
31062
|
duration: pending.duration,
|
|
31011
31063
|
timestamp: pending.timestamp,
|
|
31012
|
-
finalSummary:
|
|
31013
|
-
...externalNativeFinal ? {
|
|
31014
|
-
completionDiagnostic: {
|
|
31015
|
-
providerType: this.type,
|
|
31016
|
-
sessionId: this.instanceId,
|
|
31017
|
-
providerSessionId: this.providerSessionId || null,
|
|
31018
|
-
reconciliationReason: "external_native_final_assistant_while_adapter_busy",
|
|
31019
|
-
finalAssistantPresent: true,
|
|
31020
|
-
finalAssistantEvidenceSource: externalNativeFinal.evidence.source,
|
|
31021
|
-
externalFinalFingerprint: externalNativeFinal.fingerprint
|
|
31022
|
-
}
|
|
31023
|
-
} : {}
|
|
31064
|
+
finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
|
|
31024
31065
|
});
|
|
31025
31066
|
this.completedDebouncePending = null;
|
|
31026
31067
|
this.completedDebounceTimer = null;
|
|
@@ -31076,9 +31117,8 @@ var CliProviderInstance = class {
|
|
|
31076
31117
|
const parsedStatus = null;
|
|
31077
31118
|
const rawStatus = adapterStatus.status;
|
|
31078
31119
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, now);
|
|
31079
|
-
const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, adapterStatus);
|
|
31080
31120
|
const autoApproveHoldIdle = this.autoApproveBusy && rawStatus === "idle";
|
|
31081
|
-
const newStatus =
|
|
31121
|
+
const newStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : rawStatus;
|
|
31082
31122
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
31083
31123
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
31084
31124
|
const partial = this.adapter.getPartialResponse();
|
|
@@ -39230,16 +39270,26 @@ function reconcileInlineMeshCache(cached, incoming) {
|
|
|
39230
39270
|
const nodeId = readInlineMeshNodeId(node);
|
|
39231
39271
|
if (nodeId) cachedById.set(nodeId, node);
|
|
39232
39272
|
}
|
|
39273
|
+
const mergedIncomingIds = /* @__PURE__ */ new Set();
|
|
39233
39274
|
const nodes = incomingNodes.map((incomingNode) => {
|
|
39234
39275
|
const nodeId = readInlineMeshNodeId(incomingNode);
|
|
39235
39276
|
const cachedNode = nodeId ? cachedById.get(nodeId) : void 0;
|
|
39236
39277
|
if (!cachedNode && preserveCachedMembership) return null;
|
|
39278
|
+
if (nodeId) mergedIncomingIds.add(nodeId);
|
|
39237
39279
|
if (!cachedNode) return incomingNode;
|
|
39238
39280
|
if (hasInlineMeshTransientNodeState(incomingNode)) {
|
|
39239
39281
|
return { ...cachedNode, ...incomingNode };
|
|
39240
39282
|
}
|
|
39241
39283
|
return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
|
|
39242
39284
|
}).filter(Boolean);
|
|
39285
|
+
if (preserveCachedMembership) {
|
|
39286
|
+
for (const cachedNode of cachedNodes) {
|
|
39287
|
+
const nodeId = readInlineMeshNodeId(cachedNode);
|
|
39288
|
+
if (nodeId && !mergedIncomingIds.has(nodeId)) {
|
|
39289
|
+
nodes.push(cachedNode);
|
|
39290
|
+
}
|
|
39291
|
+
}
|
|
39292
|
+
}
|
|
39243
39293
|
return {
|
|
39244
39294
|
...cached,
|
|
39245
39295
|
...incoming,
|
|
@@ -42154,6 +42204,18 @@ ${tail}` : ""
|
|
|
42154
42204
|
return { success: true };
|
|
42155
42205
|
}
|
|
42156
42206
|
case "launch_cli": {
|
|
42207
|
+
{
|
|
42208
|
+
const launchSettings = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
|
|
42209
|
+
const isMeshWorkerLaunch = !!launchSettings && (readStringValue(launchSettings.meshNodeFor) || launchSettings.launchedByCoordinator === true);
|
|
42210
|
+
const hasCoordinatorDaemonId = !!launchSettings && !!readStringValue(launchSettings.meshCoordinatorDaemonId);
|
|
42211
|
+
if (launchSettings && isMeshWorkerLaunch && !hasCoordinatorDaemonId) {
|
|
42212
|
+
try {
|
|
42213
|
+
const localDaemonId = readStringValue(loadConfig().machineId);
|
|
42214
|
+
if (localDaemonId) launchSettings.meshCoordinatorDaemonId = localDaemonId;
|
|
42215
|
+
} catch {
|
|
42216
|
+
}
|
|
42217
|
+
}
|
|
42218
|
+
}
|
|
42157
42219
|
const launchResult = await this.deps.cliManager.handleCliCommand(cmd, args);
|
|
42158
42220
|
const meshNodeId = readStringValue(args?.settings?.meshNodeId);
|
|
42159
42221
|
const meshId = readStringValue(args?.settings?.meshNodeFor);
|
|
@@ -43651,7 +43713,7 @@ ${tail}` : ""
|
|
|
43651
43713
|
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "worktree clone");
|
|
43652
43714
|
if (ownerFailure) return ownerFailure;
|
|
43653
43715
|
try {
|
|
43654
|
-
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
43716
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
43655
43717
|
const mesh = meshRecord?.mesh;
|
|
43656
43718
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
43657
43719
|
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
@@ -43702,6 +43764,8 @@ ${tail}` : ""
|
|
|
43702
43764
|
policy: { ...sourceNode.policy || {} }
|
|
43703
43765
|
});
|
|
43704
43766
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
43767
|
+
const inlineForReconcile = this.getCachedInlineMesh(meshId);
|
|
43768
|
+
if (inlineForReconcile) this.updateInlineMeshNode(meshId, inlineForReconcile, node);
|
|
43705
43769
|
this.invalidateAggregateMeshStatus(meshId);
|
|
43706
43770
|
}
|
|
43707
43771
|
const persistWorktreeSetupState = async (bootstrapState2) => {
|