@adhdev/daemon-core 0.9.82-rc.252 → 0.9.82-rc.254
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 +159 -121
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +159 -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 +34 -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 +22 -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
|
}
|
|
@@ -30958,16 +30997,15 @@ var CliProviderInstance = class {
|
|
|
30958
30997
|
}
|
|
30959
30998
|
const latestStatus = this.adapter.getStatus({ allowParse: false });
|
|
30960
30999
|
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?.()}`);
|
|
31000
|
+
const latestVisibleStatus = latestAutoApproveActive || this.autoApproveBusy ? "generating" : latestStatus.status;
|
|
31001
|
+
LOG.debug("CLI", `[${this.type}] flush attempt: adapterStatus=${latestStatus.status} latestVisible=${latestVisibleStatus} generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse} hasPartial=${!!this.adapter.getPartialResponse?.()}`);
|
|
30964
31002
|
if (latestVisibleStatus !== "idle") {
|
|
30965
31003
|
LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
|
|
30966
31004
|
this.completedDebouncePending = null;
|
|
30967
31005
|
this.completedDebounceTimer = null;
|
|
30968
31006
|
return;
|
|
30969
31007
|
}
|
|
30970
|
-
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending
|
|
31008
|
+
const block2 = this.getCompletedFinalizationBlock(latestVisibleStatus, pending);
|
|
30971
31009
|
if (block2) {
|
|
30972
31010
|
const blockReason = block2.reason;
|
|
30973
31011
|
const waitedMs = Date.now() - pending.firstObservedAt;
|
|
@@ -31009,18 +31047,7 @@ var CliProviderInstance = class {
|
|
|
31009
31047
|
chatTitle: pending.chatTitle,
|
|
31010
31048
|
duration: pending.duration,
|
|
31011
31049
|
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
|
-
} : {}
|
|
31050
|
+
finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
|
|
31024
31051
|
});
|
|
31025
31052
|
this.completedDebouncePending = null;
|
|
31026
31053
|
this.completedDebounceTimer = null;
|
|
@@ -31076,9 +31103,8 @@ var CliProviderInstance = class {
|
|
|
31076
31103
|
const parsedStatus = null;
|
|
31077
31104
|
const rawStatus = adapterStatus.status;
|
|
31078
31105
|
const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, now);
|
|
31079
|
-
const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, adapterStatus);
|
|
31080
31106
|
const autoApproveHoldIdle = this.autoApproveBusy && rawStatus === "idle";
|
|
31081
|
-
const newStatus =
|
|
31107
|
+
const newStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : rawStatus;
|
|
31082
31108
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
31083
31109
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
31084
31110
|
const partial = this.adapter.getPartialResponse();
|
|
@@ -39230,16 +39256,26 @@ function reconcileInlineMeshCache(cached, incoming) {
|
|
|
39230
39256
|
const nodeId = readInlineMeshNodeId(node);
|
|
39231
39257
|
if (nodeId) cachedById.set(nodeId, node);
|
|
39232
39258
|
}
|
|
39259
|
+
const mergedIncomingIds = /* @__PURE__ */ new Set();
|
|
39233
39260
|
const nodes = incomingNodes.map((incomingNode) => {
|
|
39234
39261
|
const nodeId = readInlineMeshNodeId(incomingNode);
|
|
39235
39262
|
const cachedNode = nodeId ? cachedById.get(nodeId) : void 0;
|
|
39236
39263
|
if (!cachedNode && preserveCachedMembership) return null;
|
|
39264
|
+
if (nodeId) mergedIncomingIds.add(nodeId);
|
|
39237
39265
|
if (!cachedNode) return incomingNode;
|
|
39238
39266
|
if (hasInlineMeshTransientNodeState(incomingNode)) {
|
|
39239
39267
|
return { ...cachedNode, ...incomingNode };
|
|
39240
39268
|
}
|
|
39241
39269
|
return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
|
|
39242
39270
|
}).filter(Boolean);
|
|
39271
|
+
if (preserveCachedMembership) {
|
|
39272
|
+
for (const cachedNode of cachedNodes) {
|
|
39273
|
+
const nodeId = readInlineMeshNodeId(cachedNode);
|
|
39274
|
+
if (nodeId && !mergedIncomingIds.has(nodeId)) {
|
|
39275
|
+
nodes.push(cachedNode);
|
|
39276
|
+
}
|
|
39277
|
+
}
|
|
39278
|
+
}
|
|
39243
39279
|
return {
|
|
39244
39280
|
...cached,
|
|
39245
39281
|
...incoming,
|
|
@@ -43651,7 +43687,7 @@ ${tail}` : ""
|
|
|
43651
43687
|
const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "worktree clone");
|
|
43652
43688
|
if (ownerFailure) return ownerFailure;
|
|
43653
43689
|
try {
|
|
43654
|
-
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
43690
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
43655
43691
|
const mesh = meshRecord?.mesh;
|
|
43656
43692
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
43657
43693
|
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
@@ -43702,6 +43738,8 @@ ${tail}` : ""
|
|
|
43702
43738
|
policy: { ...sourceNode.policy || {} }
|
|
43703
43739
|
});
|
|
43704
43740
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
43741
|
+
const inlineForReconcile = this.getCachedInlineMesh(meshId);
|
|
43742
|
+
if (inlineForReconcile) this.updateInlineMeshNode(meshId, inlineForReconcile, node);
|
|
43705
43743
|
this.invalidateAggregateMeshStatus(meshId);
|
|
43706
43744
|
}
|
|
43707
43745
|
const persistWorktreeSetupState = async (bootstrapState2) => {
|