@adhdev/daemon-standalone 1.0.58-rc.40 → 1.0.58-rc.42
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 +1261 -853
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -36911,10 +36911,10 @@ var require_dist3 = __commonJS({
|
|
|
36911
36911
|
}
|
|
36912
36912
|
function getDaemonBuildInfo() {
|
|
36913
36913
|
if (cached2) return cached2;
|
|
36914
|
-
const commit = readInjected(true ? "
|
|
36915
|
-
const commitShort = readInjected(true ? "
|
|
36916
|
-
const version2 = readInjected(true ? "1.0.58-rc.
|
|
36917
|
-
const builtAt = readInjected(true ? "2026-08-
|
|
36914
|
+
const commit = readInjected(true ? "2c1c52a4b48387753bcbd8c0b2d003d18fd5f544" : void 0) ?? "unknown";
|
|
36915
|
+
const commitShort = readInjected(true ? "2c1c52a4" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
36916
|
+
const version2 = readInjected(true ? "1.0.58-rc.42" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
36917
|
+
const builtAt = readInjected(true ? "2026-08-29T14:25:11.174Z" : void 0);
|
|
36918
36918
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
36919
36919
|
return cached2;
|
|
36920
36920
|
}
|
|
@@ -38708,6 +38708,48 @@ var require_dist3 = __commonJS({
|
|
|
38708
38708
|
MONTHLY_WINDOW_MINUTES = 43200;
|
|
38709
38709
|
}
|
|
38710
38710
|
});
|
|
38711
|
+
function isSecretLikeEnvKey(key2) {
|
|
38712
|
+
return SECRET_LIKE_KEY_PATTERN.test(key2);
|
|
38713
|
+
}
|
|
38714
|
+
function applyDaemonEnvOverrides(overrides, env2 = process.env, logFn = () => {
|
|
38715
|
+
}) {
|
|
38716
|
+
const result = {
|
|
38717
|
+
applied: {},
|
|
38718
|
+
skippedRejected: [],
|
|
38719
|
+
skippedExplicitEnv: [],
|
|
38720
|
+
unknownKeys: []
|
|
38721
|
+
};
|
|
38722
|
+
if (!overrides) return result;
|
|
38723
|
+
for (const [key2, value] of Object.entries(overrides)) {
|
|
38724
|
+
if (typeof key2 !== "string" || !key2.trim()) continue;
|
|
38725
|
+
if (typeof value !== "string") continue;
|
|
38726
|
+
if (isSecretLikeEnvKey(key2)) {
|
|
38727
|
+
result.skippedRejected.push(key2);
|
|
38728
|
+
logFn(`rejected secret-shaped key "${key2}" from config.envOverrides \u2014 identity/secret persistence is out of scope for this map`);
|
|
38729
|
+
continue;
|
|
38730
|
+
}
|
|
38731
|
+
if (typeof env2[key2] === "string" && env2[key2] !== "") {
|
|
38732
|
+
result.skippedExplicitEnv.push(key2);
|
|
38733
|
+
continue;
|
|
38734
|
+
}
|
|
38735
|
+
if (!KNOWN_FLAG_KEYS.has(key2)) {
|
|
38736
|
+
result.unknownKeys.push(key2);
|
|
38737
|
+
logFn(`applying unrecognized key "${key2}" from config.envOverrides \u2014 verify spelling if this doesn't take effect`);
|
|
38738
|
+
}
|
|
38739
|
+
env2[key2] = value;
|
|
38740
|
+
result.applied[key2] = value;
|
|
38741
|
+
}
|
|
38742
|
+
return result;
|
|
38743
|
+
}
|
|
38744
|
+
var SECRET_LIKE_KEY_PATTERN;
|
|
38745
|
+
var KNOWN_FLAG_KEYS;
|
|
38746
|
+
var init_env_overrides = __esm2({
|
|
38747
|
+
"src/config/env-overrides.ts"() {
|
|
38748
|
+
"use strict";
|
|
38749
|
+
SECRET_LIKE_KEY_PATTERN = /TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|API[_-]?KEY|PRIVATE[_-]?KEY|COOKIE/i;
|
|
38750
|
+
KNOWN_FLAG_KEYS = /* @__PURE__ */ new Set(["ADHDEV_WORKER_MCP"]);
|
|
38751
|
+
}
|
|
38752
|
+
});
|
|
38711
38753
|
var config_exports = {};
|
|
38712
38754
|
__export2(config_exports, {
|
|
38713
38755
|
clearAuthCredentials: () => clearAuthCredentials,
|
|
@@ -38753,6 +38795,17 @@ var require_dist3 = __commonJS({
|
|
|
38753
38795
|
}
|
|
38754
38796
|
return fallback;
|
|
38755
38797
|
}
|
|
38798
|
+
function normalizeEnvOverrides(value) {
|
|
38799
|
+
if (!isPlainObject2(value)) return {};
|
|
38800
|
+
const result = {};
|
|
38801
|
+
for (const [key2, raw] of Object.entries(value)) {
|
|
38802
|
+
if (typeof key2 !== "string" || !key2.trim()) continue;
|
|
38803
|
+
if (typeof raw !== "string") continue;
|
|
38804
|
+
if (isSecretLikeEnvKey(key2)) continue;
|
|
38805
|
+
result[key2] = raw;
|
|
38806
|
+
}
|
|
38807
|
+
return result;
|
|
38808
|
+
}
|
|
38756
38809
|
function normalizeMachineProviders(value) {
|
|
38757
38810
|
if (!isPlainObject2(value)) return {};
|
|
38758
38811
|
const result = {};
|
|
@@ -38813,7 +38866,8 @@ var require_dist3 = __commonJS({
|
|
|
38813
38866
|
// behavior-neutral for stale configs; anything absent or unknown
|
|
38814
38867
|
// resolves to THIS binary's build track instead of failing.
|
|
38815
38868
|
updateChannel: parsed.updateChannel === "preview" || parsed.updateChannel === "next" ? "preview" : parsed.updateChannel === "stable" || parsed.updateChannel === "latest" ? "stable" : TRACK,
|
|
38816
|
-
terminalSizingMode: parsed.terminalSizingMode === "fit" ? "fit" : "measured"
|
|
38869
|
+
terminalSizingMode: parsed.terminalSizingMode === "fit" ? "fit" : "measured",
|
|
38870
|
+
envOverrides: normalizeEnvOverrides(parsed.envOverrides)
|
|
38817
38871
|
};
|
|
38818
38872
|
}
|
|
38819
38873
|
function generateMachineId() {
|
|
@@ -38966,6 +39020,7 @@ var require_dist3 = __commonJS({
|
|
|
38966
39020
|
import_crypto2 = require("crypto");
|
|
38967
39021
|
init_config_dir();
|
|
38968
39022
|
init_track_identity();
|
|
39023
|
+
init_env_overrides();
|
|
38969
39024
|
DEFAULT_CONFIG = {
|
|
38970
39025
|
// Track-stamped default origin: identical to the historical literal on
|
|
38971
39026
|
// stable builds ('https://api.adhf.dev'); preview builds default to the
|
|
@@ -38992,7 +39047,8 @@ var require_dist3 = __commonJS({
|
|
|
38992
39047
|
ideSettings: {},
|
|
38993
39048
|
providerSourceMode: "normal",
|
|
38994
39049
|
updateChannel: "stable",
|
|
38995
|
-
terminalSizingMode: "measured"
|
|
39050
|
+
terminalSizingMode: "measured",
|
|
39051
|
+
envOverrides: {}
|
|
38996
39052
|
};
|
|
38997
39053
|
MACHINE_ID_PREFIX = "mach_";
|
|
38998
39054
|
}
|
|
@@ -39011,7 +39067,8 @@ var require_dist3 = __commonJS({
|
|
|
39011
39067
|
env: overrides.env ?? process.env,
|
|
39012
39068
|
spawn: overrides.spawn ?? ((command, args, options) => (0, import_node_child_process2.spawn)(command, args, {
|
|
39013
39069
|
env: options.env,
|
|
39014
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
39070
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
39071
|
+
windowsHide: true
|
|
39015
39072
|
})),
|
|
39016
39073
|
readFile: overrides.readFile ?? ((filePath) => (0, import_promises3.readFile)(filePath, "utf-8")),
|
|
39017
39074
|
setTimeout: overrides.setTimeout ?? ((handler, ms) => setTimeout(handler, ms)),
|
|
@@ -39792,6 +39849,7 @@ const shellArgs = process.platform === 'win32' ? ['/d', '/s', '/c', ORIGINAL_COM
|
|
|
39792
39849
|
|
|
39793
39850
|
const child = spawn(shell, shellArgs, {
|
|
39794
39851
|
stdio: ['pipe', 'inherit', 'inherit'],
|
|
39852
|
+
windowsHide: true,
|
|
39795
39853
|
windowsVerbatimArguments: process.platform === 'win32',
|
|
39796
39854
|
});
|
|
39797
39855
|
|
|
@@ -65502,7 +65560,7 @@ CREATE TABLE IF NOT EXISTS sq_archive (
|
|
|
65502
65560
|
`).run(meshId, nodeId, sessionId, providerType, expiresAt, metadata ? JSON.stringify(metadata) : null);
|
|
65503
65561
|
}
|
|
65504
65562
|
getRemoteIdleSessions(meshId) {
|
|
65505
|
-
const rows = this.db.prepare("SELECT node_id, session_id, provider_type, expires_at, metadata FROM remote_idle_sessions WHERE mesh_id = ?").all(meshId);
|
|
65563
|
+
const rows = this.db.prepare("SELECT node_id, session_id, provider_type, expires_at, metadata FROM remote_idle_sessions WHERE mesh_id = ? AND expires_at > ?").all(meshId, Date.now());
|
|
65506
65564
|
return rows.map((r) => ({
|
|
65507
65565
|
nodeId: r.node_id,
|
|
65508
65566
|
sessionId: r.session_id,
|
|
@@ -65514,6 +65572,11 @@ CREATE TABLE IF NOT EXISTS sq_archive (
|
|
|
65514
65572
|
deleteRemoteIdleSession(meshId, nodeId, sessionId) {
|
|
65515
65573
|
this.db.prepare("DELETE FROM remote_idle_sessions WHERE mesh_id = ? AND node_id = ? AND session_id = ?").run(meshId, nodeId, sessionId);
|
|
65516
65574
|
}
|
|
65575
|
+
// CLAIM-RETRY-LOOP-LIFECYCLE: deleteRemoteIdleSession above fires only on a successful
|
|
65576
|
+
// claim; called from remove_mesh_node to clear a node's row on removal instead.
|
|
65577
|
+
deleteRemoteIdleSessionsForNode(meshId, nodeId) {
|
|
65578
|
+
this.db.prepare("DELETE FROM remote_idle_sessions WHERE mesh_id = ? AND node_id = ?").run(meshId, nodeId);
|
|
65579
|
+
}
|
|
65517
65580
|
pruneExpiredRemoteIdleSessions() {
|
|
65518
65581
|
this.db.prepare("DELETE FROM remote_idle_sessions WHERE expires_at <= ?").run(Date.now());
|
|
65519
65582
|
}
|
|
@@ -78732,376 +78795,6 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
78732
78795
|
REMOTE_LAUNCH_READY_POLL_MS = 100;
|
|
78733
78796
|
}
|
|
78734
78797
|
});
|
|
78735
|
-
function isAnthropicProvider(providerType) {
|
|
78736
|
-
const p = typeof providerType === "string" ? providerType.trim().toLowerCase() : "";
|
|
78737
|
-
return p.length > 0 && ANTHROPIC_PROVIDER_TYPES.has(p);
|
|
78738
|
-
}
|
|
78739
|
-
function isAnthropicModel(model) {
|
|
78740
|
-
const m = typeof model === "string" ? model.trim().toLowerCase() : "";
|
|
78741
|
-
if (!m) return false;
|
|
78742
|
-
if (m.startsWith("claude") || m.startsWith("anthropic")) return true;
|
|
78743
|
-
return /^(opus|sonnet|haiku)(\b|[-_])/.test(m);
|
|
78744
|
-
}
|
|
78745
|
-
function isModelCompatibleWithProvider(model, providerType) {
|
|
78746
|
-
if (!isAnthropicModel(model)) return true;
|
|
78747
|
-
if (isAnthropicProvider(providerType)) return true;
|
|
78748
|
-
return false;
|
|
78749
|
-
}
|
|
78750
|
-
var ANTHROPIC_PROVIDER_TYPES;
|
|
78751
|
-
var init_model_provider_compat = __esm2({
|
|
78752
|
-
"src/mesh/model-provider-compat.ts"() {
|
|
78753
|
-
"use strict";
|
|
78754
|
-
ANTHROPIC_PROVIDER_TYPES = /* @__PURE__ */ new Set([
|
|
78755
|
-
"claude-cli"
|
|
78756
|
-
]);
|
|
78757
|
-
}
|
|
78758
|
-
});
|
|
78759
|
-
function encodeDuplicateMeshDispatchCode(holderSessionId) {
|
|
78760
|
-
const holder = typeof holderSessionId === "string" ? holderSessionId.trim() : "";
|
|
78761
|
-
return holder ? `${DUPLICATE_MESH_DISPATCH_CODE}:${holder}` : DUPLICATE_MESH_DISPATCH_CODE;
|
|
78762
|
-
}
|
|
78763
|
-
function classifyDuplicateMeshDispatch(err) {
|
|
78764
|
-
if (!err || typeof err !== "object") return null;
|
|
78765
|
-
const e = err;
|
|
78766
|
-
if (e.code === DUPLICATE_MESH_DISPATCH_CODE) {
|
|
78767
|
-
const holder = typeof e.holderSessionId === "string" ? e.holderSessionId.trim() : "";
|
|
78768
|
-
return holder ? { holderSessionId: holder } : {};
|
|
78769
|
-
}
|
|
78770
|
-
for (const raw of [e.meshCode, e.code]) {
|
|
78771
|
-
if (typeof raw !== "string") continue;
|
|
78772
|
-
if (raw !== DUPLICATE_MESH_DISPATCH_CODE && !raw.startsWith(`${DUPLICATE_MESH_DISPATCH_CODE}:`)) continue;
|
|
78773
|
-
const holder = raw.slice(DUPLICATE_MESH_DISPATCH_CODE.length + 1).trim();
|
|
78774
|
-
return holder ? { holderSessionId: holder } : {};
|
|
78775
|
-
}
|
|
78776
|
-
return null;
|
|
78777
|
-
}
|
|
78778
|
-
var DUPLICATE_MESH_DISPATCH_CODE;
|
|
78779
|
-
var DuplicateMeshDispatchError;
|
|
78780
|
-
var init_mesh_duplicate_dispatch = __esm2({
|
|
78781
|
-
"src/mesh/mesh-duplicate-dispatch.ts"() {
|
|
78782
|
-
"use strict";
|
|
78783
|
-
DUPLICATE_MESH_DISPATCH_CODE = "DUPLICATE_MESH_DISPATCH";
|
|
78784
|
-
DuplicateMeshDispatchError = class extends Error {
|
|
78785
|
-
code = DUPLICATE_MESH_DISPATCH_CODE;
|
|
78786
|
-
holderSessionId;
|
|
78787
|
-
constructor(message, info = {}) {
|
|
78788
|
-
super(message);
|
|
78789
|
-
this.name = "DuplicateMeshDispatchError";
|
|
78790
|
-
this.holderSessionId = info.holderSessionId;
|
|
78791
|
-
}
|
|
78792
|
-
};
|
|
78793
|
-
}
|
|
78794
|
-
});
|
|
78795
|
-
function acquireAutoFastForwardLease(workspace) {
|
|
78796
|
-
const key2 = normalizeMeshWorkspaceForCompare(workspace);
|
|
78797
|
-
if (!key2) return false;
|
|
78798
|
-
if (autoFastForwardWorkspaceLease.has(key2)) return false;
|
|
78799
|
-
autoFastForwardWorkspaceLease.add(key2);
|
|
78800
|
-
return true;
|
|
78801
|
-
}
|
|
78802
|
-
function releaseAutoFastForwardLease(workspace) {
|
|
78803
|
-
const key2 = normalizeMeshWorkspaceForCompare(workspace);
|
|
78804
|
-
if (key2) autoFastForwardWorkspaceLease.delete(key2);
|
|
78805
|
-
}
|
|
78806
|
-
function isWorkspaceAutoFastForwardInFlight(workspace) {
|
|
78807
|
-
const key2 = normalizeMeshWorkspaceForCompare(workspace || "");
|
|
78808
|
-
return !!key2 && autoFastForwardWorkspaceLease.has(key2);
|
|
78809
|
-
}
|
|
78810
|
-
function __resetIdleAutoFastForwardForTests() {
|
|
78811
|
-
idleAutoFastForwardLastAttempt.clear();
|
|
78812
|
-
continuousAutoFastForwardLastScan.clear();
|
|
78813
|
-
autoFastForwardWorkspaceLease.clear();
|
|
78814
|
-
}
|
|
78815
|
-
function isDirtyNode(node) {
|
|
78816
|
-
return node?.health === "dirty" || node?.git?.dirty === true;
|
|
78817
|
-
}
|
|
78818
|
-
function resolveAutoFastForwardPolicy(mesh) {
|
|
78819
|
-
const record2 = mesh?.policy?.autoFastForward && typeof mesh.policy.autoFastForward === "object" && !Array.isArray(mesh.policy.autoFastForward) ? mesh.policy.autoFastForward : {};
|
|
78820
|
-
const maxBehind = Number(record2.maxBehind);
|
|
78821
|
-
return {
|
|
78822
|
-
enabled: record2.enabled !== false,
|
|
78823
|
-
...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
|
|
78824
|
-
requireCleanSubmodules: record2.requireCleanSubmodules !== false,
|
|
78825
|
-
// Strict opt-in: absent/false → self-only (historical behavior). Only an
|
|
78826
|
-
// explicit `true` extends auto ff to remote owning-daemon nodes.
|
|
78827
|
-
remoteNodes: record2.remoteNodes === true,
|
|
78828
|
-
// Absent/anything-but-continuous → 'idle' (historical idle-edge-only detection).
|
|
78829
|
-
mode: record2.mode === "continuous" ? "continuous" : "idle"
|
|
78830
|
-
};
|
|
78831
|
-
}
|
|
78832
|
-
function dryRunSatisfiesAutoFastForwardPolicy(dryRun, policy) {
|
|
78833
|
-
if (!dryRun || dryRun.code !== "fast_forward_available" || dryRun.allowed !== true) return false;
|
|
78834
|
-
const behind = Number(dryRun.current?.behind);
|
|
78835
|
-
if (!Number.isFinite(behind) || behind <= 0) return false;
|
|
78836
|
-
if (policy.maxBehind !== void 0 && behind > policy.maxBehind) return false;
|
|
78837
|
-
if (policy.requireCleanSubmodules) {
|
|
78838
|
-
const submodules = Array.isArray(dryRun.current?.submodules) ? dryRun.current.submodules : [];
|
|
78839
|
-
if (submodules.some((submodule) => submodule?.dirty || submodule?.error)) return false;
|
|
78840
|
-
}
|
|
78841
|
-
return true;
|
|
78842
|
-
}
|
|
78843
|
-
function readNodeSubmoduleIgnorePaths(node) {
|
|
78844
|
-
return Array.isArray(node?.policy?.submoduleIgnorePaths) ? node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
|
|
78845
|
-
}
|
|
78846
|
-
function nodeIsAutoFastForwardEligible(components, meshId, nodeId, node, currentSessionId) {
|
|
78847
|
-
if (!node) return false;
|
|
78848
|
-
if (node.status === "disabled" || node.status === "removed") return false;
|
|
78849
|
-
if (node.readOnly === true || node.policy?.readOnly === true) return false;
|
|
78850
|
-
if (isWorktreeBootstrapStaleRunning(node)) return false;
|
|
78851
|
-
if (node.worktreeBootstrap?.status === "running") return false;
|
|
78852
|
-
if (nodeHasActiveMeshWork(components, meshId, nodeId, currentSessionId)) return false;
|
|
78853
|
-
return true;
|
|
78854
|
-
}
|
|
78855
|
-
function remoteNodeIsConnected(components, node) {
|
|
78856
|
-
const daemonId = readMeshNodeDaemonId(node ?? {});
|
|
78857
|
-
if (!daemonId) return false;
|
|
78858
|
-
const getPeerStatus = components.getMeshPeerConnectionStatus;
|
|
78859
|
-
if (getPeerStatus) {
|
|
78860
|
-
const snapshot = getPeerStatus(daemonId);
|
|
78861
|
-
return !!snapshot && String(snapshot.state) === "connected";
|
|
78862
|
-
}
|
|
78863
|
-
return readNonEmptyString(node?.connection?.state).toLowerCase() === "connected";
|
|
78864
|
-
}
|
|
78865
|
-
async function delegateRemoteAutoFastForward(components, args) {
|
|
78866
|
-
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
78867
|
-
if (!dispatchMeshCommand) return;
|
|
78868
|
-
if (!acquireAutoFastForwardLease(args.workspace)) return;
|
|
78869
|
-
const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
|
|
78870
|
-
const mesh = getMeshWithCache(components, args.meshId);
|
|
78871
|
-
const baseArgs = {
|
|
78872
|
-
meshId: args.meshId,
|
|
78873
|
-
nodeId: args.nodeId,
|
|
78874
|
-
workspace: args.workspace,
|
|
78875
|
-
inlineMesh: mesh,
|
|
78876
|
-
...submoduleIgnorePaths ? { submoduleIgnorePaths } : {},
|
|
78877
|
-
trigger: args.trigger,
|
|
78878
|
-
// Mirror the manual mesh_fast_forward_node update_submodules behavior: if the
|
|
78879
|
-
// ff-only merge moves a submodule gitlink, run `git submodule update --init
|
|
78880
|
-
// --recursive` in the same cycle so the checkout never drifts from the gitlink.
|
|
78881
|
-
// Without this, drift accumulates and self-blocks every subsequent auto-ff
|
|
78882
|
-
// (collectPreflightBlockers treats out-of-sync submodules as a hard blocker).
|
|
78883
|
-
updateSubmodules: true
|
|
78884
|
-
};
|
|
78885
|
-
try {
|
|
78886
|
-
const remoteDry = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
|
|
78887
|
-
...baseArgs,
|
|
78888
|
-
execute: false,
|
|
78889
|
-
dryRun: true
|
|
78890
|
-
});
|
|
78891
|
-
if (!dryRunSatisfiesAutoFastForwardPolicy(remoteDry, args.policy)) return;
|
|
78892
|
-
if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId)) return;
|
|
78893
|
-
const executed = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
|
|
78894
|
-
...baseArgs,
|
|
78895
|
-
execute: true,
|
|
78896
|
-
dryRun: false
|
|
78897
|
-
});
|
|
78898
|
-
if (executed?.executed === true) {
|
|
78899
|
-
LOG2.info("MeshFastForward", `Remote auto fast-forward executed for node ${args.nodeId} (daemon ${String(args.daemonId).slice(0, 12)}, trigger ${args.trigger})`);
|
|
78900
|
-
}
|
|
78901
|
-
} catch (e) {
|
|
78902
|
-
LOG2.warn("MeshFastForward", `Remote auto fast-forward delegation failed for ${args.nodeId}: ${e?.message || e}`);
|
|
78903
|
-
} finally {
|
|
78904
|
-
releaseAutoFastForwardLease(args.workspace);
|
|
78905
|
-
}
|
|
78906
|
-
}
|
|
78907
|
-
async function executeLocalAutoFastForward(args) {
|
|
78908
|
-
if (!acquireAutoFastForwardLease(args.workspace)) return;
|
|
78909
|
-
const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
|
|
78910
|
-
try {
|
|
78911
|
-
const dryRun = await fastForwardMeshNode({
|
|
78912
|
-
meshId: args.meshId,
|
|
78913
|
-
nodeId: args.nodeId,
|
|
78914
|
-
workspace: args.workspace,
|
|
78915
|
-
execute: false,
|
|
78916
|
-
dryRun: true,
|
|
78917
|
-
// See delegateRemoteAutoFastForward's updateSubmodules comment: mirrors the
|
|
78918
|
-
// manual tool so a gitlink-moving ff cannot leave the submodule drifted.
|
|
78919
|
-
updateSubmodules: true,
|
|
78920
|
-
submoduleIgnorePaths,
|
|
78921
|
-
trigger: args.trigger
|
|
78922
|
-
});
|
|
78923
|
-
if (!dryRunSatisfiesAutoFastForwardPolicy(dryRun, args.policy)) return;
|
|
78924
|
-
await fastForwardMeshNode({
|
|
78925
|
-
meshId: args.meshId,
|
|
78926
|
-
nodeId: args.nodeId,
|
|
78927
|
-
workspace: args.workspace,
|
|
78928
|
-
execute: true,
|
|
78929
|
-
dryRun: false,
|
|
78930
|
-
updateSubmodules: true,
|
|
78931
|
-
submoduleIgnorePaths,
|
|
78932
|
-
trigger: args.trigger
|
|
78933
|
-
});
|
|
78934
|
-
} catch (e) {
|
|
78935
|
-
LOG2.warn("MeshFastForward", `Idle auto fast-forward check failed for ${args.nodeId}: ${e?.message || e}`);
|
|
78936
|
-
} finally {
|
|
78937
|
-
releaseAutoFastForwardLease(args.workspace);
|
|
78938
|
-
}
|
|
78939
|
-
}
|
|
78940
|
-
async function maybeAutoFastForwardIdleNode(components, args) {
|
|
78941
|
-
const mesh = getMeshWithCache(components, args.meshId);
|
|
78942
|
-
const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
|
|
78943
|
-
const workspace = readNonEmptyString(node?.workspace);
|
|
78944
|
-
if (!workspace) return;
|
|
78945
|
-
const policy = resolveAutoFastForwardPolicy(mesh);
|
|
78946
|
-
if (!policy.enabled) return;
|
|
78947
|
-
if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
|
|
78948
|
-
const throttleKey = `${args.meshId}:${args.nodeId}`;
|
|
78949
|
-
const now = Date.now();
|
|
78950
|
-
const lastAttempt = idleAutoFastForwardLastAttempt.get(throttleKey) || 0;
|
|
78951
|
-
if (now - lastAttempt < IDLE_AUTO_FAST_FORWARD_THROTTLE_MS) return;
|
|
78952
|
-
idleAutoFastForwardLastAttempt.set(throttleKey, now);
|
|
78953
|
-
if (isLocalAutoLaunchNode(node)) {
|
|
78954
|
-
if (!(0, import_fs17.existsSync)(workspace)) return;
|
|
78955
|
-
await executeLocalAutoFastForward({ meshId: args.meshId, nodeId: args.nodeId, node, workspace, policy, trigger: "idle_auto" });
|
|
78956
|
-
return;
|
|
78957
|
-
}
|
|
78958
|
-
if (!policy.remoteNodes) return;
|
|
78959
|
-
const daemonId = readMeshNodeDaemonId(node ?? {});
|
|
78960
|
-
if (!daemonId || !components.dispatchMeshCommand) return;
|
|
78961
|
-
if (!remoteNodeIsConnected(components, node)) return;
|
|
78962
|
-
await delegateRemoteAutoFastForward(components, { meshId: args.meshId, nodeId: args.nodeId, node, daemonId, workspace, policy, trigger: "idle_auto" });
|
|
78963
|
-
}
|
|
78964
|
-
async function runContinuousAutoFastForwardScan(components, mesh) {
|
|
78965
|
-
if (!components.dispatchMeshCommand) return;
|
|
78966
|
-
const policy = resolveAutoFastForwardPolicy(mesh);
|
|
78967
|
-
if (!policy.enabled || !policy.remoteNodes || policy.mode !== "continuous") return;
|
|
78968
|
-
const meshId = readNonEmptyString(mesh?.id);
|
|
78969
|
-
if (!meshId) return;
|
|
78970
|
-
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
78971
|
-
const now = Date.now();
|
|
78972
|
-
for (const node of nodes) {
|
|
78973
|
-
const nodeId = normalizeMeshNodeId(node);
|
|
78974
|
-
if (!nodeId) continue;
|
|
78975
|
-
if (node?.isLocalWorktree === true) continue;
|
|
78976
|
-
if (isLocalAutoLaunchNode(node)) continue;
|
|
78977
|
-
const workspace = readNonEmptyString(node?.workspace);
|
|
78978
|
-
if (!workspace) continue;
|
|
78979
|
-
const daemonId = readMeshNodeDaemonId(node ?? {});
|
|
78980
|
-
if (!daemonId) continue;
|
|
78981
|
-
if (!nodeIsAutoFastForwardEligible(components, meshId, nodeId, node)) continue;
|
|
78982
|
-
if (!remoteNodeIsConnected(components, node)) continue;
|
|
78983
|
-
const cooldownKey = `${meshId}:${nodeId}`;
|
|
78984
|
-
const lastScan = continuousAutoFastForwardLastScan.get(cooldownKey) || 0;
|
|
78985
|
-
if (now - lastScan < CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS) continue;
|
|
78986
|
-
continuousAutoFastForwardLastScan.set(cooldownKey, now);
|
|
78987
|
-
await delegateRemoteAutoFastForward(components, { meshId, nodeId, node, daemonId, workspace, policy, trigger: "reconcile_auto" });
|
|
78988
|
-
}
|
|
78989
|
-
}
|
|
78990
|
-
async function runPendingCoordinatorCatchupScan(components, mesh) {
|
|
78991
|
-
const meshId = readNonEmptyString(mesh?.id);
|
|
78992
|
-
if (!meshId) return;
|
|
78993
|
-
const localIds = expandDaemonIdForms([
|
|
78994
|
-
readNonEmptyString(components.statusInstanceId),
|
|
78995
|
-
readNonEmptyString(loadConfig2().machineId)
|
|
78996
|
-
]);
|
|
78997
|
-
let markers = [];
|
|
78998
|
-
try {
|
|
78999
|
-
markers = drainPendingMeshCoordinatorEvents(
|
|
79000
|
-
meshId,
|
|
79001
|
-
localIds.length > 0 ? localIds : void 0,
|
|
79002
|
-
{ onlyEvents: /* @__PURE__ */ new Set(["coordinator_catchup"]) }
|
|
79003
|
-
);
|
|
79004
|
-
} catch (e) {
|
|
79005
|
-
LOG2.warn("MeshReconcile", `Coordinator-catchup drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
79006
|
-
return;
|
|
79007
|
-
}
|
|
79008
|
-
if (markers.length === 0) return;
|
|
79009
|
-
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
79010
|
-
for (const marker of markers) {
|
|
79011
|
-
const meta3 = marker.metadataEvent || {};
|
|
79012
|
-
const nodeId = readNonEmptyString(marker.nodeId) || readNonEmptyString(meta3.nodeId);
|
|
79013
|
-
const workspace = readNonEmptyString(marker.workspace) || readNonEmptyString(meta3.workspace);
|
|
79014
|
-
const baseBranch = readNonEmptyString(meta3.baseBranch);
|
|
79015
|
-
if (!workspace) continue;
|
|
79016
|
-
if (nodeId && nodeHasActiveMeshWork(components, meshId, nodeId)) {
|
|
79017
|
-
try {
|
|
79018
|
-
queuePendingMeshCoordinatorEvent(marker);
|
|
79019
|
-
} catch {
|
|
79020
|
-
}
|
|
79021
|
-
continue;
|
|
79022
|
-
}
|
|
79023
|
-
try {
|
|
79024
|
-
const ff = await fastForwardMeshNode({
|
|
79025
|
-
meshId,
|
|
79026
|
-
...nodeId ? { nodeId } : {},
|
|
79027
|
-
workspace,
|
|
79028
|
-
...baseBranch ? { branch: baseBranch } : {},
|
|
79029
|
-
mode: "merge",
|
|
79030
|
-
execute: true,
|
|
79031
|
-
// Same gitlink-drift-prevention rationale as executeLocalAutoFastForward /
|
|
79032
|
-
// delegateRemoteAutoFastForward — this path pushed the base branch itself,
|
|
79033
|
-
// so a submodule gitlink bump here is exactly as likely.
|
|
79034
|
-
updateSubmodules: true,
|
|
79035
|
-
trigger: "refine_post_push_catchup",
|
|
79036
|
-
allowAutoPublishSubmoduleMainCommits: mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true
|
|
79037
|
-
});
|
|
79038
|
-
LOG2.info("MeshReconcile", `Coordinator catch-up ff for ${meshId}/${nodeId || workspace}: ${ff.code} (executed=${ff.executed})`);
|
|
79039
|
-
} catch (e) {
|
|
79040
|
-
LOG2.warn("MeshReconcile", `Coordinator catch-up ff failed for ${meshId}/${nodeId || workspace}: ${e?.message || e}`);
|
|
79041
|
-
}
|
|
79042
|
-
}
|
|
79043
|
-
}
|
|
79044
|
-
var import_fs17;
|
|
79045
|
-
var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS;
|
|
79046
|
-
var idleAutoFastForwardLastAttempt;
|
|
79047
|
-
var CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS;
|
|
79048
|
-
var continuousAutoFastForwardLastScan;
|
|
79049
|
-
var autoFastForwardWorkspaceLease;
|
|
79050
|
-
var init_mesh_auto_fast_forward = __esm2({
|
|
79051
|
-
"src/mesh/mesh-auto-fast-forward.ts"() {
|
|
79052
|
-
"use strict";
|
|
79053
|
-
import_fs17 = require("fs");
|
|
79054
|
-
init_logger();
|
|
79055
|
-
init_config();
|
|
79056
|
-
init_mesh_fast_forward();
|
|
79057
|
-
init_dist();
|
|
79058
|
-
init_mesh_events_utils();
|
|
79059
|
-
init_mesh_node_identity();
|
|
79060
|
-
init_mesh_events_pending();
|
|
79061
|
-
init_worktree_bootstrap_config();
|
|
79062
|
-
init_mesh_queue_assignment();
|
|
79063
|
-
IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
|
|
79064
|
-
idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
|
|
79065
|
-
CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS = 45 * 1e3;
|
|
79066
|
-
continuousAutoFastForwardLastScan = /* @__PURE__ */ new Map();
|
|
79067
|
-
autoFastForwardWorkspaceLease = /* @__PURE__ */ new Set();
|
|
79068
|
-
}
|
|
79069
|
-
});
|
|
79070
|
-
function normalizeNodeIdKey(nodeId) {
|
|
79071
|
-
return normalizeMeshNodeId({ id: nodeId ?? void 0 }) ?? "";
|
|
79072
|
-
}
|
|
79073
|
-
function noteRecentlyClonedNode(nodeId, nowMs = Date.now()) {
|
|
79074
|
-
const key2 = normalizeNodeIdKey(nodeId);
|
|
79075
|
-
if (!key2) return;
|
|
79076
|
-
recentlyClonedNodeExpiry.set(key2, nowMs + CLONE_BOOTSTRAP_GRACE_MS);
|
|
79077
|
-
if (recentlyClonedNodeExpiry.size > MAX_TRACKED_CLONED_NODES) {
|
|
79078
|
-
const oldest = recentlyClonedNodeExpiry.keys().next().value;
|
|
79079
|
-
if (oldest !== void 0) recentlyClonedNodeExpiry.delete(oldest);
|
|
79080
|
-
}
|
|
79081
|
-
}
|
|
79082
|
-
function isWithinCloneBootstrapGrace(nodeId, nowMs = Date.now()) {
|
|
79083
|
-
const key2 = normalizeNodeIdKey(nodeId);
|
|
79084
|
-
if (!key2) return false;
|
|
79085
|
-
const expiry = recentlyClonedNodeExpiry.get(key2);
|
|
79086
|
-
if (expiry === void 0) return false;
|
|
79087
|
-
if (nowMs >= expiry) {
|
|
79088
|
-
recentlyClonedNodeExpiry.delete(key2);
|
|
79089
|
-
return false;
|
|
79090
|
-
}
|
|
79091
|
-
return true;
|
|
79092
|
-
}
|
|
79093
|
-
var CLONE_BOOTSTRAP_GRACE_MS;
|
|
79094
|
-
var recentlyClonedNodeExpiry;
|
|
79095
|
-
var MAX_TRACKED_CLONED_NODES;
|
|
79096
|
-
var init_mesh_clone_grace = __esm2({
|
|
79097
|
-
"src/mesh/mesh-clone-grace.ts"() {
|
|
79098
|
-
"use strict";
|
|
79099
|
-
init_dist();
|
|
79100
|
-
CLONE_BOOTSTRAP_GRACE_MS = 10 * 60 * 1e3;
|
|
79101
|
-
recentlyClonedNodeExpiry = /* @__PURE__ */ new Map();
|
|
79102
|
-
MAX_TRACKED_CLONED_NODES = 512;
|
|
79103
|
-
}
|
|
79104
|
-
});
|
|
79105
78798
|
function quotaClaimBlockKey(meshId, observation) {
|
|
79106
78799
|
return `${meshId}:${observation.nodeId}:${observation.sessionId}:${observation.providerType}`;
|
|
79107
78800
|
}
|
|
@@ -79118,30 +78811,41 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
79118
78811
|
if (oldest !== void 0) map3.delete(oldest);
|
|
79119
78812
|
}
|
|
79120
78813
|
}
|
|
79121
|
-
function logQuotaClaimBlockTransition(meshId, observation) {
|
|
78814
|
+
function logQuotaClaimBlockTransition(meshId, observation, phase = "blocked") {
|
|
79122
78815
|
const key2 = quotaClaimBlockKey(meshId, observation);
|
|
79123
|
-
const fingerprint = `${observation.block.reason}:${observation.block.window}:${observation.block.remainingPercent}:${observation.block.thresholdPercent}`;
|
|
78816
|
+
const fingerprint = `${phase}:${observation.block.reason}:${observation.block.window}:${observation.block.remainingPercent}:${observation.block.thresholdPercent}`;
|
|
79124
78817
|
if (lastQuotaClaimBlockLog.get(key2) === fingerprint) return;
|
|
79125
78818
|
const wasBlocked = lastQuotaClaimBlockLog.has(key2);
|
|
79126
78819
|
rememberBounded(lastQuotaClaimBlockLog, key2, fingerprint);
|
|
79127
|
-
|
|
78820
|
+
const overrideNote = phase === "overridden_by_pin" ? " (provider pinned by requiredTags \u2014 gate overridden to honor the pin)" : "";
|
|
78821
|
+
LOG2.info("MeshQueue", `QUOTA GATE: ${phase === "overridden_by_pin" ? "allowing" : "deferring"} queue claim for node ${observation.nodeId} (${observation.sessionId}): ${quotaClaimBlockDescription(observation.providerType, observation.block)}${overrideNote}${phase === "blocked" ? " \u2014 trying remaining provider candidates; the task stays pending only if none can claim" : ""}`);
|
|
79128
78822
|
try {
|
|
78823
|
+
const payload = {
|
|
78824
|
+
phase,
|
|
78825
|
+
nodeId: observation.nodeId,
|
|
78826
|
+
sessionId: observation.sessionId,
|
|
78827
|
+
providerType: observation.providerType,
|
|
78828
|
+
reason: observation.block.reason,
|
|
78829
|
+
window: observation.block.window,
|
|
78830
|
+
remainingPercent: observation.block.remainingPercent,
|
|
78831
|
+
thresholdPercent: observation.block.thresholdPercent,
|
|
78832
|
+
previouslyBlocked: wasBlocked
|
|
78833
|
+
};
|
|
78834
|
+
if (observation.context?.trigger) {
|
|
78835
|
+
payload.trigger = observation.context.trigger;
|
|
78836
|
+
}
|
|
78837
|
+
if (observation.context?.candidateTaskId) {
|
|
78838
|
+
payload.candidateTaskId = observation.context.candidateTaskId;
|
|
78839
|
+
}
|
|
78840
|
+
if (observation.context?.pinOverride) {
|
|
78841
|
+
payload.pinOverride = true;
|
|
78842
|
+
}
|
|
79129
78843
|
appendLedgerEntry(meshId, {
|
|
79130
78844
|
kind: "quota_claim_gate",
|
|
79131
78845
|
nodeId: observation.nodeId,
|
|
79132
78846
|
sessionId: observation.sessionId,
|
|
79133
78847
|
providerType: observation.providerType,
|
|
79134
|
-
payload
|
|
79135
|
-
phase: "blocked",
|
|
79136
|
-
nodeId: observation.nodeId,
|
|
79137
|
-
sessionId: observation.sessionId,
|
|
79138
|
-
providerType: observation.providerType,
|
|
79139
|
-
reason: observation.block.reason,
|
|
79140
|
-
window: observation.block.window,
|
|
79141
|
-
remainingPercent: observation.block.remainingPercent,
|
|
79142
|
-
thresholdPercent: observation.block.thresholdPercent,
|
|
79143
|
-
previouslyBlocked: wasBlocked
|
|
79144
|
-
}
|
|
78848
|
+
payload
|
|
79145
78849
|
});
|
|
79146
78850
|
} catch {
|
|
79147
78851
|
}
|
|
@@ -79275,301 +78979,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
79275
78979
|
AUTO_LAUNCH_LEDGER_DEDUP_MAX = 2e3;
|
|
79276
78980
|
}
|
|
79277
78981
|
});
|
|
79278
|
-
function isActionableSkipReason(reason) {
|
|
79279
|
-
if (!reason) return false;
|
|
79280
|
-
return ACTIONABLE_SKIP_REASON_PREFIXES.some((prefix) => reason === prefix || reason.startsWith(prefix));
|
|
79281
|
-
}
|
|
79282
|
-
function isTargetNodeTransientlyUnresolved(mesh, task) {
|
|
79283
|
-
const targetNodeId = readNonEmptyString(task.targetNodeId);
|
|
79284
|
-
if (!targetNodeId) return false;
|
|
79285
|
-
const node = Array.isArray(mesh?.nodes) ? mesh.nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
|
|
79286
|
-
if (node && node.worktreeBootstrap?.status === "running" && !isWorktreeBootstrapStaleRunning(node)) {
|
|
79287
|
-
return true;
|
|
79288
|
-
}
|
|
79289
|
-
return isWithinCloneBootstrapGrace(targetNodeId);
|
|
79290
|
-
}
|
|
79291
|
-
function targetPinAgeMs(task, nowMs = Date.now()) {
|
|
79292
|
-
const anchorMs = Date.parse(task.requeuedAt || task.createdAt || "");
|
|
79293
|
-
return Number.isFinite(anchorMs) ? nowMs - anchorMs : null;
|
|
79294
|
-
}
|
|
79295
|
-
function resolveTargetPinTtlVerdict(components, task, nowMs = Date.now()) {
|
|
79296
|
-
const wallAgeMs = targetPinAgeMs(task, nowMs);
|
|
79297
|
-
if (wallAgeMs === null) return { expired: false, ageMs: null, suspended: false };
|
|
79298
|
-
const targetSessionId = readNonEmptyString(task.targetSessionId);
|
|
79299
|
-
const key2 = `${task.meshId}::${task.id}`;
|
|
79300
|
-
const prior = targetPinGeneratingCreditMs.get(key2);
|
|
79301
|
-
const generating = !!targetSessionId && resolveSessionBusyVerdict(components, targetSessionId) === "GENERATING";
|
|
79302
|
-
let creditMs = prior?.creditMs ?? 0;
|
|
79303
|
-
if (generating && prior) {
|
|
79304
|
-
creditMs += Math.max(0, nowMs - prior.lastSeenMs);
|
|
79305
|
-
}
|
|
79306
|
-
targetPinGeneratingCreditMs.set(key2, { creditMs, lastSeenMs: nowMs });
|
|
79307
|
-
const unproductiveAgeMs = Math.max(0, wallAgeMs - creditMs);
|
|
79308
|
-
return {
|
|
79309
|
-
// A tick on which the addressee is OBSERVABLY GENERATING never expires the pin,
|
|
79310
|
-
// independently of the accumulated credit.
|
|
79311
|
-
//
|
|
79312
|
-
// The credit ledger alone is not sufficient here, and the difference is the
|
|
79313
|
-
// whole live defect. Credit only accrues from the SECOND observation onward
|
|
79314
|
-
// (the first has no prior interval to bank), and it is in-memory — so a pin
|
|
79315
|
-
// that crossed the wall-clock TTL while the daemon was not watching, or before
|
|
79316
|
-
// a restart, would arrive at its very first post-restart observation with zero
|
|
79317
|
-
// credit and expire on the spot, while the session it is addressed to is
|
|
79318
|
-
// visibly mid-turn. That is exactly the observed failure (`unclaimed 902s`
|
|
79319
|
-
// logged on an `agent:ready`, i.e. at the end of real work) reproduced by a
|
|
79320
|
-
// different route.
|
|
79321
|
-
//
|
|
79322
|
-
// Gating on the live verdict makes "is the addressee working right now?" the
|
|
79323
|
-
// decisive question and leaves the credit ledger as what it should be: an
|
|
79324
|
-
// optimisation that stops intermittent work from silently burning the budget.
|
|
79325
|
-
// It cannot make a pin immortal — the verdict is re-evaluated every tick from
|
|
79326
|
-
// live state and only a LOCAL, observably-generating session can produce it.
|
|
79327
|
-
expired: !generating && unproductiveAgeMs >= TARGET_SESSION_PIN_TTL_MS,
|
|
79328
|
-
ageMs: unproductiveAgeMs,
|
|
79329
|
-
suspended: generating
|
|
79330
|
-
};
|
|
79331
|
-
}
|
|
79332
|
-
function resolveDeadTargetVerdict(components, meshId, mesh, task) {
|
|
79333
|
-
const NOT_DEAD = { dead: false, nodeDead: false, reason: "" };
|
|
79334
|
-
const targetSessionId = readNonEmptyString(task.targetSessionId);
|
|
79335
|
-
const targetNodeId = readNonEmptyString(task.targetNodeId);
|
|
79336
|
-
if (!targetSessionId && !targetNodeId) return NOT_DEAD;
|
|
79337
|
-
const lastUpdateMs = Date.parse(task.updatedAt || task.createdAt || "");
|
|
79338
|
-
if (Number.isFinite(lastUpdateMs) && Date.now() - lastUpdateMs < DEAD_TARGET_GRACE_MS) return NOT_DEAD;
|
|
79339
|
-
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
79340
|
-
if (targetNodeId) {
|
|
79341
|
-
const nodePresent = nodes.some((n) => meshNodeIdMatches(n, targetNodeId));
|
|
79342
|
-
if (!nodePresent) {
|
|
79343
|
-
if (isTargetNodeTransientlyUnresolved(mesh, task)) return NOT_DEAD;
|
|
79344
|
-
return { dead: true, nodeDead: true, reason: "dead_target_node_absent" };
|
|
79345
|
-
}
|
|
79346
|
-
}
|
|
79347
|
-
if (targetSessionId) {
|
|
79348
|
-
const node = targetNodeId ? nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
|
|
79349
|
-
const nodeIsLocal = node ? isLocalAutoLaunchNode(node) : true;
|
|
79350
|
-
if (nodeIsLocal) {
|
|
79351
|
-
const verdict = resolveSessionBusyVerdict(components, targetSessionId);
|
|
79352
|
-
if (verdict === "UNKNOWN") {
|
|
79353
|
-
return { dead: true, nodeDead: false, reason: "dead_target_session_absent" };
|
|
79354
|
-
}
|
|
79355
|
-
}
|
|
79356
|
-
}
|
|
79357
|
-
return NOT_DEAD;
|
|
79358
|
-
}
|
|
79359
|
-
function retractActionableSkipIfPreviouslyNotified(meshId, taskId) {
|
|
79360
|
-
const dedupKey = `${meshId}:${taskId}`;
|
|
79361
|
-
if (!lastActionableSkipNotified.delete(dedupKey)) return;
|
|
79362
|
-
try {
|
|
79363
|
-
const coordinatorDaemonId = readNonEmptyString(loadConfig2().machineId) || void 0;
|
|
79364
|
-
const removed = retractPendingDispatchBlockedEvent(meshId, taskId, coordinatorDaemonId);
|
|
79365
|
-
if (removed > 0) {
|
|
79366
|
-
LOG2.info("MeshQueue", `Retracted ${removed} stale dispatch-blocked event(s) for task ${taskId} (mesh ${meshId}) \u2014 its blocker resolved`);
|
|
79367
|
-
}
|
|
79368
|
-
} catch (e) {
|
|
79369
|
-
LOG2.warn("MeshQueue", `Failed to retract stale dispatch-blocked event for task ${taskId} (mesh ${meshId}): ${e?.message || e}`);
|
|
79370
|
-
}
|
|
79371
|
-
}
|
|
79372
|
-
function resolveTaskDeliveryEvidence(meshId, taskId) {
|
|
79373
|
-
try {
|
|
79374
|
-
const store = MeshRuntimeStore.getInstance();
|
|
79375
|
-
if (store.taskDeliveryConsumed(meshId, taskId)) return "consumed";
|
|
79376
|
-
if (store.taskHasConfirmedDelivery(meshId, taskId)) return "delivered";
|
|
79377
|
-
} catch {
|
|
79378
|
-
return "delivered";
|
|
79379
|
-
}
|
|
79380
|
-
return "never_dispatched";
|
|
79381
|
-
}
|
|
79382
|
-
function actionableSkipGuidance(reason, evidence) {
|
|
79383
|
-
if (reason === "target_node_id_unmatched") return {
|
|
79384
|
-
summary: "it is pinned to a target node id that matches no node in the mesh (the node may have been removed, or its id form does not resolve)",
|
|
79385
|
-
nextAction: "Verify the target node still exists with mesh_status, then re-enqueue without the node pin or with a valid node id (or re-clone the node)."
|
|
79386
|
-
};
|
|
79387
|
-
if (reason === "no_node_satisfies_required_tags") return {
|
|
79388
|
-
summary: "no node in the mesh can satisfy the task's required capability tags",
|
|
79389
|
-
nextAction: "Relax the task's requiredTags, or add/launch a node whose provider produces the required capabilities."
|
|
79390
|
-
};
|
|
79391
|
-
if (reason === "mesh_convergence_target_is_worktree") return {
|
|
79392
|
-
summary: "it is a convergence task (base-only: merge \u2192 push \u2192 cleanup) but every candidate node is a worktree clone",
|
|
79393
|
-
nextAction: "Dispatch the convergence task to the base node, or run the deterministic fast-forward path (mesh_fast_forward_node / mesh_refine_node) instead."
|
|
79394
|
-
};
|
|
79395
|
-
if (reason.startsWith("remote_auto_launch")) return {
|
|
79396
|
-
summary: "the target node is on a remote daemon this coordinator cannot auto-launch a session on (no dispatch transport, or no coordinator daemon id to stamp)",
|
|
79397
|
-
nextAction: "Launch a session on that node yourself with mesh_launch_session, or ensure the remote daemon is connected over P2P."
|
|
79398
|
-
};
|
|
79399
|
-
if (reason.startsWith("provider") || reason === "missing_provider_priority") return {
|
|
79400
|
-
summary: `the current provider scan found no usable provider for this task (provider priority missing/unusable, or the provider loader is unavailable; ${reason})`,
|
|
79401
|
-
nextAction: "Check the node's providerPriority policy and that the required CLI/ACP provider is installed and enabled on that machine. Quota-gated candidates use a separate, self-resolving reason and are not proof of this configuration blocker."
|
|
79402
|
-
};
|
|
79403
|
-
if (reason === "dirty_workspace") return {
|
|
79404
|
-
summary: "the node's workspace is dirty, so auto-launch is blocked to avoid clobbering uncommitted changes",
|
|
79405
|
-
nextAction: "Clean or commit the node's working tree (or fast-forward it); the task will then auto-assign."
|
|
79406
|
-
};
|
|
79407
|
-
if (reason === PARKED_SKIP_REASON) {
|
|
79408
|
-
const base = "it was pinned to a specific session, that pin went stale, and the task is now PARKED \u2014 deliberately held for you rather than re-homed onto another session, because a delta written for one session's context becomes a context-free instruction anywhere else";
|
|
79409
|
-
if (evidence === "consumed") return {
|
|
79410
|
-
summary: `${base}. The delivery record shows the addressed session DID receive and start acting on this message, so the parked row is a bookkeeping remnant, not a lost delta`,
|
|
79411
|
-
nextAction: "Do NOT re-send it. Confirm with mesh_read_chat / mesh_read_terminal that the work is under way, then clear the park with mesh_queue_cancel (or requeue it only if you genuinely want it run again)."
|
|
79412
|
-
};
|
|
79413
|
-
if (evidence === "delivered") return {
|
|
79414
|
-
summary: `${base}. The message WAS handed to that session's transport but no turn start was echoed, so whether it acted on it is unconfirmed`,
|
|
79415
|
-
nextAction: "Check the session (mesh_read_chat / mesh_read_terminal) before acting. If it is already handling it, cancel the parked row; if not, mesh_queue_requeue with target_session_id=<live session> \u2014 and pass message=<rewritten instruction> if the situation moved on while it waited."
|
|
79416
|
-
};
|
|
79417
|
-
return {
|
|
79418
|
-
summary: `${base}. No delivery to that session was ever recorded, so the message did not reach it and the worker is still acting on its previous instructions`,
|
|
79419
|
-
nextAction: "Re-target it with mesh_queue_requeue(target_session_id=<live session>), or drop the pin with clear_target_session to let any compatible session take it. Re-read the work produced meanwhile and pass message=<rewritten instruction> if the delta is now partly stale; mesh_queue_cancel if it is moot."
|
|
79420
|
-
};
|
|
79421
|
-
}
|
|
79422
|
-
if (reason === "target_session_pin_expired") {
|
|
79423
|
-
if (evidence === "consumed") return {
|
|
79424
|
-
summary: "it was pinned to a specific session and the pin TTL expired before the queue row was claimed \u2014 but the delivery record shows this session DID receive and start acting on the message (a turn was started for it), so the queue row lagging is a bookkeeping gap, not a lost delta",
|
|
79425
|
-
nextAction: "Do NOT re-send it \u2014 the session already has this message and re-sending would run the same instruction twice. Check its current output (mesh_read_chat / mesh_read_terminal) to confirm the work is under way."
|
|
79426
|
-
};
|
|
79427
|
-
if (evidence === "delivered") return {
|
|
79428
|
-
summary: "it was pinned to a specific session and the pin TTL expired before the queue row was claimed; the message WAS handed to that session's transport, but the session never echoed a turn start, so whether it acted on it is unconfirmed",
|
|
79429
|
-
nextAction: "Verify before re-sending: check the session with mesh_read_chat / mesh_read_terminal. Re-send only if its output shows no sign of this message \u2014 it may already be acting on it, and re-sending would duplicate the instruction."
|
|
79430
|
-
};
|
|
79431
|
-
return {
|
|
79432
|
-
summary: "it was pinned to a specific session (a follow-up/delta for work already in flight) that never claimed it within the pin TTL, so the pin was cleared; no delivery to that session was ever recorded, so the message did not reach it",
|
|
79433
|
-
nextAction: "The addressed session never received this delta and is still acting on its previous instructions. Re-send it to that session once it is idle (or re-target it), and re-check the work it produced in the meantime."
|
|
79434
|
-
};
|
|
79435
|
-
}
|
|
79436
|
-
if (reason === SLOT_MODEL_ABSENT_SKIP_REASON) return {
|
|
79437
|
-
summary: "no capability slot on the node declares the model this task resolved to (its difficulty\u2192brain preset picked a model the node was never configured to run)",
|
|
79438
|
-
nextAction: "Re-enqueue with a difficulty/model the node's slots declare, target a node that declares this model, or add a slot for it. The task is NOT run on a substitute model \u2014 an undeclared model is never launched."
|
|
79439
|
-
};
|
|
79440
|
-
return {
|
|
79441
|
-
summary: `it cannot be dispatched (${reason})`,
|
|
79442
|
-
nextAction: "Inspect the node/mesh state with mesh_status and resolve the blocker, or re-enqueue the task."
|
|
79443
|
-
};
|
|
79444
|
-
}
|
|
79445
|
-
function notifyCoordinatorOfActionableSkip(meshId, taskId, reason, nodeId) {
|
|
79446
|
-
if (!isActionableSkipReason(reason)) return;
|
|
79447
|
-
if (reason === "target_node_id_unmatched" && isWithinCloneBootstrapGrace(readNonEmptyString(nodeId))) return;
|
|
79448
|
-
const dedupKey = `${meshId}:${taskId}`;
|
|
79449
|
-
if (lastActionableSkipNotified.get(dedupKey) === reason) return;
|
|
79450
|
-
lastActionableSkipNotified.set(dedupKey, reason);
|
|
79451
|
-
if (lastActionableSkipNotified.size > AUTO_LAUNCH_LEDGER_DEDUP_MAX) {
|
|
79452
|
-
const oldest = lastActionableSkipNotified.keys().next().value;
|
|
79453
|
-
if (oldest !== void 0) lastActionableSkipNotified.delete(oldest);
|
|
79454
|
-
}
|
|
79455
|
-
let task;
|
|
79456
|
-
try {
|
|
79457
|
-
task = getQueue(meshId).find((t) => t.id === taskId);
|
|
79458
|
-
} catch {
|
|
79459
|
-
}
|
|
79460
|
-
if (task && task.status !== "pending") {
|
|
79461
|
-
LOG2.info("MeshQueue", `Suppressed stale dispatch-blocked page for task ${taskId} (mesh ${meshId}): reason '${reason}' was computed against a pre-await snapshot, but the task is now '${task.status}'.`);
|
|
79462
|
-
lastActionableSkipNotified.delete(dedupKey);
|
|
79463
|
-
return;
|
|
79464
|
-
}
|
|
79465
|
-
const targetCoordinatorDaemonId = readNonEmptyString(loadConfig2().machineId);
|
|
79466
|
-
const targetCoordinatorSessionId = readNonEmptyString(task?.sourceCoordinatorSessionId);
|
|
79467
|
-
const nodeLabel = readNonEmptyString(nodeId) || readNonEmptyString(task?.targetNodeId);
|
|
79468
|
-
const evidence = reason === "target_session_pin_expired" || reason === PARKED_SKIP_REASON ? resolveTaskDeliveryEvidence(meshId, taskId) : void 0;
|
|
79469
|
-
const { summary, nextAction } = actionableSkipGuidance(reason, evidence);
|
|
79470
|
-
const providerAvailabilityResult = reason.startsWith("provider") || reason === "missing_provider_priority";
|
|
79471
|
-
const reachabilityResult = reason.startsWith("remote_auto_launch");
|
|
79472
|
-
const closing = reason === PARKED_SKIP_REASON ? `This task is claimable by NOBODY until you act on it \u2014 no session will pick it up and no timer will re-home it. It is held for ${Math.round(PARKED_TASK_RETENTION_MS / 36e5)}h and then failed (with another notification), so it is never silently discarded. Parked rows are listed under parkedTasks in mesh_view_queue, and any mesh_queue_requeue unparks it \u2014 including one that only rewrites its message.` : reason === "target_session_pin_expired" ? "The stale pin has already been cleared, so the task is now claimable by any compatible session \u2014 the action above is about the session it was originally addressed to." : providerAvailabilityResult ? "This result needs action if it persists: a later provider-status refresh or an already-starting usable session can clear it, but a genuinely missing, disabled, or misconfigured provider will keep the task pending until you fix that configuration." : reachabilityResult ? "This result needs action if it persists: the node reconnecting (or re-registering its daemon id) clears it on its own, but a node that stays unreachable will keep the task pending until you bring it back or re-target the task." : "This is an actionable blocker \u2014 it will NOT clear on its own; the task stays pending until you resolve it.";
|
|
79473
|
-
const coordinatorMessage = `[System] A queued mesh task${nodeLabel ? ` for node ${nodeLabel}` : ""} is not being dispatched because ${summary}. ${nextAction} ${closing}`;
|
|
79474
|
-
try {
|
|
79475
|
-
queuePendingMeshCoordinatorEvent({
|
|
79476
|
-
event: "mesh:dispatch_blocked",
|
|
79477
|
-
meshId,
|
|
79478
|
-
nodeLabel: nodeLabel || meshId,
|
|
79479
|
-
...nodeLabel ? { nodeId: nodeLabel } : {},
|
|
79480
|
-
metadataEvent: {
|
|
79481
|
-
source: "mesh_queue_dispatch_skip",
|
|
79482
|
-
taskId,
|
|
79483
|
-
reason,
|
|
79484
|
-
...nodeLabel ? { nodeId: nodeLabel } : {},
|
|
79485
|
-
coordinatorMessage
|
|
79486
|
-
},
|
|
79487
|
-
coordinatorMessage,
|
|
79488
|
-
queuedAt: Date.now(),
|
|
79489
|
-
...targetCoordinatorDaemonId ? { targetCoordinatorDaemonId } : {},
|
|
79490
|
-
...targetCoordinatorSessionId ? { targetCoordinatorSessionId } : {}
|
|
79491
|
-
});
|
|
79492
|
-
} catch (e) {
|
|
79493
|
-
LOG2.warn("MeshQueue", `Failed to surface actionable dispatch-skip (${reason}) for task ${taskId}: ${e?.message || e}`);
|
|
79494
|
-
}
|
|
79495
|
-
}
|
|
79496
|
-
var ACTIONABLE_SKIP_REASON_PREFIXES;
|
|
79497
|
-
var TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON;
|
|
79498
|
-
var lastActionableSkipNotified;
|
|
79499
|
-
var DEAD_TARGET_GRACE_MS;
|
|
79500
|
-
var TARGET_SESSION_PIN_TTL_MS;
|
|
79501
|
-
var targetPinGeneratingCreditMs;
|
|
79502
|
-
var init_mesh_skip_notify = __esm2({
|
|
79503
|
-
"src/mesh/mesh-skip-notify.ts"() {
|
|
79504
|
-
"use strict";
|
|
79505
|
-
init_logger();
|
|
79506
|
-
init_mesh_work_queue();
|
|
79507
|
-
init_mesh_runtime_store();
|
|
79508
|
-
init_dist();
|
|
79509
|
-
init_mesh_events_utils();
|
|
79510
|
-
init_mesh_events_pending();
|
|
79511
|
-
init_worktree_bootstrap_config();
|
|
79512
|
-
init_mesh_clone_grace();
|
|
79513
|
-
init_config();
|
|
79514
|
-
init_slot_model_enforcement();
|
|
79515
|
-
init_mesh_queue_assignment();
|
|
79516
|
-
init_mesh_queue_observability();
|
|
79517
|
-
init_mesh_task_parking();
|
|
79518
|
-
ACTIONABLE_SKIP_REASON_PREFIXES = [
|
|
79519
|
-
"target_node_id_unmatched",
|
|
79520
|
-
"no_node_satisfies_required_tags",
|
|
79521
|
-
"mesh_convergence_target_is_worktree",
|
|
79522
|
-
"remote_auto_launch_unsupported",
|
|
79523
|
-
"remote_auto_launch_no_coordinator_daemon_id",
|
|
79524
|
-
"missing_provider_priority",
|
|
79525
|
-
"provider_loader_unavailable",
|
|
79526
|
-
"provider_priority_unusable",
|
|
79527
|
-
"provider_unusable",
|
|
79528
|
-
"dirty_workspace",
|
|
79529
|
-
// TARGET-PIN-TTL EXPIRY: the task was pinned to a specific session (a delta —
|
|
79530
|
-
// a correction addressed to work already in flight) and that session never
|
|
79531
|
-
// claimed it within the TTL, so the pin was cleared. Unlike the transient
|
|
79532
|
-
// skips, this does NOT self-resolve into the intended outcome: the delta is
|
|
79533
|
-
// now claimable by ANY compatible session, i.e. it will not reach the session
|
|
79534
|
-
// it was written for. Previously this only bumped a metrics counter and wrote
|
|
79535
|
-
// a log, so the coordinator kept waiting for a delivery that could no longer
|
|
79536
|
-
// happen — measured live as 74min of silence while a worker continued on a
|
|
79537
|
-
// premise the delta was meant to correct. The coordinator must know its
|
|
79538
|
-
// addressed message lost its address.
|
|
79539
|
-
"target_session_pin_expired",
|
|
79540
|
-
// PIN-PARKING: the reason above's successor. The pin no longer CLEARS on expiry
|
|
79541
|
-
// (that silently re-homed a context-bound delta onto an arbitrary session); the
|
|
79542
|
-
// task PARKS instead — held, still addressed, claimable by nobody. That state is
|
|
79543
|
-
// by construction actionable and terminal-until-touched: nothing in the daemon
|
|
79544
|
-
// will ever move a parked task, so if the coordinator is not told, the work is
|
|
79545
|
-
// lost exactly as surely as if it had been dropped. Both reasons stay listed —
|
|
79546
|
-
// the old one so a version-skewed daemon's rows still page.
|
|
79547
|
-
PARKED_SKIP_REASON,
|
|
79548
|
-
// SLOT MODEL GUARD (absent): no slot on the node declares the task's model.
|
|
79549
|
-
// Permanent — no amount of waiting produces a slot, so the coordinator must
|
|
79550
|
-
// re-drive (adjust difficulty, target another node, ask the owner). Its
|
|
79551
|
-
// busy counterpart SLOT_MODEL_BUSY_SKIP_REASON is deliberately NOT listed:
|
|
79552
|
-
// that one clears on its own when the slot goes idle.
|
|
79553
|
-
SLOT_MODEL_ABSENT_SKIP_REASON
|
|
79554
|
-
// QUOTA GATE: 'provider_quota_session_low' / 'provider_quota_weekly_low' /
|
|
79555
|
-
// 'provider_quota_exhausted' / 'all_providers_quota_gated' are deliberately
|
|
79556
|
-
// NOT listed either — an exhausted quota window RESETS, so the block
|
|
79557
|
-
// self-resolves exactly like the slot-busy case; the task waits in the
|
|
79558
|
-
// queue and the coordinator is not paged (mesh-quota-routing.ts). The
|
|
79559
|
-
// all-gated reason exists precisely so this WAIT is never conflated with
|
|
79560
|
-
// the actionable 'provider_priority_unusable' above.
|
|
79561
|
-
];
|
|
79562
|
-
TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
|
|
79563
|
-
lastActionableSkipNotified = /* @__PURE__ */ new Map();
|
|
79564
|
-
DEAD_TARGET_GRACE_MS = 6e4;
|
|
79565
|
-
TARGET_SESSION_PIN_TTL_MS = 15 * 6e4;
|
|
79566
|
-
targetPinGeneratingCreditMs = /* @__PURE__ */ new Map();
|
|
79567
|
-
}
|
|
79568
|
-
});
|
|
79569
78982
|
function localCoordinatorDaemonId() {
|
|
79570
78983
|
return canonicalDaemonId(readNonEmptyString(loadConfig2().machineId));
|
|
79571
78984
|
}
|
|
79572
|
-
function
|
|
78985
|
+
function isIdleSessionState(state) {
|
|
79573
78986
|
const status = readNonEmptyString(state?.status).toLowerCase();
|
|
79574
78987
|
if (TERMINAL_SESSION_STATUSES.includes(status)) return false;
|
|
79575
78988
|
return status === "idle" || state?.activeChat?.status === "waiting_input";
|
|
@@ -79602,7 +79015,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
79602
79015
|
if (!originTaskId) continue;
|
|
79603
79016
|
const sessionId = readNonEmptyString(state?.instanceId);
|
|
79604
79017
|
if (!sessionId) continue;
|
|
79605
|
-
if (!
|
|
79018
|
+
if (!isIdleSessionState(state)) continue;
|
|
79606
79019
|
if (sessionHasActiveAssignment(meshId, sessionId)) continue;
|
|
79607
79020
|
const originTask = byId.get(originTaskId);
|
|
79608
79021
|
const assignedElsewhere = !!originTask && originTask.status === "assigned" && !!readNonEmptyString(originTask.assignedSessionId) && !sessionIdsEquivalent(readNonEmptyString(originTask.assignedSessionId), sessionId);
|
|
@@ -79852,166 +79265,872 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
79852
79265
|
});
|
|
79853
79266
|
}
|
|
79854
79267
|
}
|
|
79855
|
-
var DIFFICULTY_FLOOR_REPORT_AFTER_MS;
|
|
79856
|
-
var TASK_DIFFICULTY_FLOOR_REASON_PREFIX;
|
|
79857
|
-
var TASK_DIFFICULTY_FLOOR_REPORTED_PREFIX;
|
|
79858
|
-
var difficultyFloorTimeoutReported;
|
|
79859
|
-
var DIFFICULTY_FLOOR_REPORT_DEDUP_MAX;
|
|
79860
|
-
var CLASSIFIED_DIFFICULTIES;
|
|
79861
|
-
var init_mesh_difficulty_floor = __esm2({
|
|
79862
|
-
"src/mesh/mesh-difficulty-floor.ts"() {
|
|
79268
|
+
var DIFFICULTY_FLOOR_REPORT_AFTER_MS;
|
|
79269
|
+
var TASK_DIFFICULTY_FLOOR_REASON_PREFIX;
|
|
79270
|
+
var TASK_DIFFICULTY_FLOOR_REPORTED_PREFIX;
|
|
79271
|
+
var difficultyFloorTimeoutReported;
|
|
79272
|
+
var DIFFICULTY_FLOOR_REPORT_DEDUP_MAX;
|
|
79273
|
+
var CLASSIFIED_DIFFICULTIES;
|
|
79274
|
+
var init_mesh_difficulty_floor = __esm2({
|
|
79275
|
+
"src/mesh/mesh-difficulty-floor.ts"() {
|
|
79276
|
+
"use strict";
|
|
79277
|
+
init_mesh_work_queue();
|
|
79278
|
+
init_mesh_events_pending();
|
|
79279
|
+
init_slot_model_enforcement();
|
|
79280
|
+
init_mesh_quota_routing();
|
|
79281
|
+
init_dist();
|
|
79282
|
+
DIFFICULTY_FLOOR_REPORT_AFTER_MS = 10 * 6e4;
|
|
79283
|
+
TASK_DIFFICULTY_FLOOR_REASON_PREFIX = "task_difficulty_floor_";
|
|
79284
|
+
TASK_DIFFICULTY_FLOOR_REPORTED_PREFIX = "task_difficulty_floor_reported:";
|
|
79285
|
+
difficultyFloorTimeoutReported = /* @__PURE__ */ new Set();
|
|
79286
|
+
DIFFICULTY_FLOOR_REPORT_DEDUP_MAX = 2e3;
|
|
79287
|
+
CLASSIFIED_DIFFICULTIES = ["easy", "medium", "difficult"];
|
|
79288
|
+
}
|
|
79289
|
+
});
|
|
79290
|
+
function normalizeProviderPriority2(policy) {
|
|
79291
|
+
const raw = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerPriority : void 0;
|
|
79292
|
+
if (!Array.isArray(raw)) return [];
|
|
79293
|
+
const seen = /* @__PURE__ */ new Set();
|
|
79294
|
+
return raw.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean).filter((type2) => {
|
|
79295
|
+
if (seen.has(type2)) return false;
|
|
79296
|
+
seen.add(type2);
|
|
79297
|
+
return true;
|
|
79298
|
+
});
|
|
79299
|
+
}
|
|
79300
|
+
function isTerminalSessionStatus(status) {
|
|
79301
|
+
return ["stopped", "failed", "terminated", "exited", "closed"].includes(status);
|
|
79302
|
+
}
|
|
79303
|
+
function isIdleSessionState2(state) {
|
|
79304
|
+
const status = readNonEmptyString(state?.status).toLowerCase();
|
|
79305
|
+
if (isTerminalSessionStatus(status)) return false;
|
|
79306
|
+
return status === "idle" || state?.activeChat?.status === "waiting_input";
|
|
79307
|
+
}
|
|
79308
|
+
function sessionStateLooksActive(state) {
|
|
79309
|
+
const status = readNonEmptyString(state?.status).toLowerCase();
|
|
79310
|
+
const chatStatus = readNonEmptyString(state?.activeChat?.status).toLowerCase();
|
|
79311
|
+
const active = /* @__PURE__ */ new Set(["generating", "streaming", "no_progress", "long_generating", "working", "starting", "waiting_approval"]);
|
|
79312
|
+
return active.has(status) || active.has(chatStatus);
|
|
79313
|
+
}
|
|
79314
|
+
function nodeHasActiveMeshWork(components, meshId, nodeId, currentSessionId) {
|
|
79315
|
+
if (nodeHasActiveAssignment(meshId, nodeId)) return true;
|
|
79316
|
+
return components.instanceManager.getByCategory("cli").some((inst) => {
|
|
79317
|
+
const state = inst.getState();
|
|
79318
|
+
const settings = state.settings || {};
|
|
79319
|
+
if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
|
|
79320
|
+
const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
79321
|
+
if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
|
|
79322
|
+
const sessionId = readNonEmptyString(state.instanceId);
|
|
79323
|
+
if (currentSessionId && sessionIdsEquivalent(sessionId, currentSessionId) && isIdleSessionState2(state)) return false;
|
|
79324
|
+
return sessionStateLooksActive(state);
|
|
79325
|
+
});
|
|
79326
|
+
}
|
|
79327
|
+
function isLaunchableNode(node) {
|
|
79328
|
+
if (!node || node.status === "disabled" || node.status === "removed") return false;
|
|
79329
|
+
if (shouldDeferDispatchForBootstrap(node)) {
|
|
79330
|
+
return false;
|
|
79331
|
+
}
|
|
79332
|
+
return isMeshNodeHealthLaunchable(node);
|
|
79333
|
+
}
|
|
79334
|
+
function isLocalAutoLaunchNode(node) {
|
|
79335
|
+
const daemonId = readNonEmptyString(node?.daemonId);
|
|
79336
|
+
const machineId = readNonEmptyString(node?.machineId);
|
|
79337
|
+
const appConfig = loadConfig2();
|
|
79338
|
+
const localMachineId = readNonEmptyString(appConfig.machineId) || readNonEmptyString(appConfig.registeredMachineId);
|
|
79339
|
+
const daemonMatchesLocal = !daemonId || daemonIdsEquivalent(daemonId, localMachineId);
|
|
79340
|
+
const machineMatchesLocal = !machineId || daemonIdsEquivalent(machineId, localMachineId);
|
|
79341
|
+
if (node?.isLocalWorktree === true) {
|
|
79342
|
+
return daemonMatchesLocal && machineMatchesLocal;
|
|
79343
|
+
}
|
|
79344
|
+
if (daemonId || machineId) {
|
|
79345
|
+
return daemonMatchesLocal && machineMatchesLocal;
|
|
79346
|
+
}
|
|
79347
|
+
return true;
|
|
79348
|
+
}
|
|
79349
|
+
function isSessionActivelyGenerating(components, sessionId) {
|
|
79350
|
+
if (!sessionId) return false;
|
|
79351
|
+
const state = components.instanceManager?.getInstance?.(sessionId)?.getState?.();
|
|
79352
|
+
if (!state) return false;
|
|
79353
|
+
return sessionStateLooksActive(state);
|
|
79354
|
+
}
|
|
79355
|
+
function resolveSessionBusyVerdict(components, sessionId) {
|
|
79356
|
+
if (!sessionId) return "UNKNOWN";
|
|
79357
|
+
try {
|
|
79358
|
+
const instances = components.instanceManager?.getByCategory?.("cli") || [];
|
|
79359
|
+
const inst = instances.find((i) => {
|
|
79360
|
+
const sid = readNonEmptyString(i?.getState?.().instanceId);
|
|
79361
|
+
return sid && sessionIdsEquivalent(sid, sessionId);
|
|
79362
|
+
});
|
|
79363
|
+
if (!inst) return "UNKNOWN";
|
|
79364
|
+
const state = inst.getState?.();
|
|
79365
|
+
if (!state) return "UNKNOWN";
|
|
79366
|
+
return sessionStateLooksActive(state) ? "GENERATING" : "IDLE_CONFIRMED";
|
|
79367
|
+
} catch {
|
|
79368
|
+
return "UNKNOWN";
|
|
79369
|
+
}
|
|
79370
|
+
}
|
|
79371
|
+
function liveSessionCountForNode(components, meshId, nodeId) {
|
|
79372
|
+
const localInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
79373
|
+
const state = inst.getState();
|
|
79374
|
+
const settings = state.settings || {};
|
|
79375
|
+
if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
|
|
79376
|
+
const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
79377
|
+
if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
|
|
79378
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
79379
|
+
return !isTerminalSessionStatus(status);
|
|
79380
|
+
});
|
|
79381
|
+
let count = localInstances.length;
|
|
79382
|
+
const localSessionIds = localInstances.map((inst) => readNonEmptyString(inst.getState().instanceId)).filter(Boolean);
|
|
79383
|
+
for (const sid of inWindowAutoLaunchSessionIdsForNode(meshId, nodeId)) {
|
|
79384
|
+
if (!localSessionIds.some((local) => sessionIdsEquivalent(local, sid))) count += 1;
|
|
79385
|
+
}
|
|
79386
|
+
return count;
|
|
79387
|
+
}
|
|
79388
|
+
function nodeHasLiveSessionPendingClaim(components, meshId, nodeId, task, node) {
|
|
79389
|
+
if (inWindowAutoLaunchSessionIdsForNode(meshId, nodeId).length > 0) return true;
|
|
79390
|
+
const busySessionIds = new Set(
|
|
79391
|
+
getQueue(meshId, { status: ["assigned"] }).filter((task2) => daemonIdsEquivalent(task2.assignedNodeId, nodeId)).map((task2) => readNonEmptyString(task2.assignedSessionId)).filter(Boolean)
|
|
79392
|
+
);
|
|
79393
|
+
return components.instanceManager.getByCategory("cli").some((inst) => {
|
|
79394
|
+
const state = inst.getState();
|
|
79395
|
+
const settings = state.settings || {};
|
|
79396
|
+
if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
|
|
79397
|
+
if (readNonEmptyString(settings.meshCoordinatorFor) === meshId) return false;
|
|
79398
|
+
const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
79399
|
+
if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
|
|
79400
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
79401
|
+
if (isTerminalSessionStatus(status)) return false;
|
|
79402
|
+
const sessionId = readNonEmptyString(state.instanceId);
|
|
79403
|
+
if (sessionId && busySessionIds.has(sessionId)) return false;
|
|
79404
|
+
const sessionProviderType = state.type || readNonEmptyString(settings.providerType);
|
|
79405
|
+
if (task.requiredTags?.length) {
|
|
79406
|
+
if (sessionProviderType && !nodeSatisfiesRequiredTags(task.requiredTags, buildMeshNodeCapabilityTags(node, sessionProviderType))) {
|
|
79407
|
+
return false;
|
|
79408
|
+
}
|
|
79409
|
+
}
|
|
79410
|
+
const allowance = allowedClassifiedDifficultiesForSession(node, resolveNodeCapabilitySlots(node, meshId), sessionProviderType, readSessionModel(state));
|
|
79411
|
+
if (!taskMeetsSessionDifficultyFloor(task, allowance)) return false;
|
|
79412
|
+
return true;
|
|
79413
|
+
});
|
|
79414
|
+
}
|
|
79415
|
+
var init_mesh_candidacy_predicates = __esm2({
|
|
79416
|
+
"src/mesh/mesh-candidacy-predicates.ts"() {
|
|
79417
|
+
"use strict";
|
|
79418
|
+
init_config();
|
|
79419
|
+
init_mesh_work_queue();
|
|
79420
|
+
init_dist();
|
|
79421
|
+
init_mesh_events_utils();
|
|
79422
|
+
init_mesh_node_identity();
|
|
79423
|
+
init_worktree_bootstrap_config();
|
|
79424
|
+
init_mesh_autolaunch_integrity();
|
|
79425
|
+
init_mesh_scheduling_fitness();
|
|
79426
|
+
init_mesh_node_slots();
|
|
79427
|
+
init_mesh_difficulty_floor();
|
|
79428
|
+
}
|
|
79429
|
+
});
|
|
79430
|
+
function providerPinOverrideCandidateTaskId(meshId, providerType) {
|
|
79431
|
+
const pending = getQueue(meshId, { status: ["pending"] });
|
|
79432
|
+
for (const task of pending) {
|
|
79433
|
+
const tags = task.requiredTags ?? [];
|
|
79434
|
+
if (tags.includes(`provider=${providerType}`)) {
|
|
79435
|
+
return task.id;
|
|
79436
|
+
}
|
|
79437
|
+
}
|
|
79438
|
+
return void 0;
|
|
79439
|
+
}
|
|
79440
|
+
function evaluateQuotaClaimGateForAssignment(args) {
|
|
79441
|
+
const { meshId, nodeId, sessionId, providerType, trigger, node, mesh, providerLoader, quotaClaimTrace } = args;
|
|
79442
|
+
const pinCandidateTaskId = providerPinOverrideCandidateTaskId(meshId, providerType);
|
|
79443
|
+
const isPinOverride = !!pinCandidateTaskId;
|
|
79444
|
+
const quotaClaimBlock = evaluateProviderQuotaGate(node, providerType, mesh?.policy?.quotaRouting ?? null, Date.now(), quotaFactsContextForLiveRouting(mesh, isLocalAutoLaunchNode, providerLoader));
|
|
79445
|
+
if (quotaClaimTrace) quotaClaimTrace.evaluated += 1;
|
|
79446
|
+
if (quotaClaimBlock) {
|
|
79447
|
+
const observation = {
|
|
79448
|
+
nodeId,
|
|
79449
|
+
sessionId,
|
|
79450
|
+
providerType,
|
|
79451
|
+
block: quotaClaimBlock,
|
|
79452
|
+
context: { trigger, candidateTaskId: pinCandidateTaskId, pinOverride: isPinOverride }
|
|
79453
|
+
};
|
|
79454
|
+
if (isPinOverride) {
|
|
79455
|
+
logQuotaClaimBlockTransition(meshId, observation, "overridden_by_pin");
|
|
79456
|
+
return false;
|
|
79457
|
+
}
|
|
79458
|
+
logQuotaClaimBlockTransition(meshId, observation, "blocked");
|
|
79459
|
+
quotaClaimTrace?.blocked.push(observation);
|
|
79460
|
+
return true;
|
|
79461
|
+
}
|
|
79462
|
+
clearQuotaClaimBlockState(meshId, nodeId, sessionId, providerType);
|
|
79463
|
+
if (quotaClaimTrace) quotaClaimTrace.clear += 1;
|
|
79464
|
+
return false;
|
|
79465
|
+
}
|
|
79466
|
+
var init_mesh_queue_claim_gate = __esm2({
|
|
79467
|
+
"src/mesh/mesh-queue-claim-gate.ts"() {
|
|
79468
|
+
"use strict";
|
|
79469
|
+
init_mesh_quota_routing();
|
|
79470
|
+
init_mesh_queue_observability();
|
|
79471
|
+
init_mesh_work_queue();
|
|
79472
|
+
init_mesh_candidacy_predicates();
|
|
79473
|
+
}
|
|
79474
|
+
});
|
|
79475
|
+
function isAnthropicProvider(providerType) {
|
|
79476
|
+
const p = typeof providerType === "string" ? providerType.trim().toLowerCase() : "";
|
|
79477
|
+
return p.length > 0 && ANTHROPIC_PROVIDER_TYPES.has(p);
|
|
79478
|
+
}
|
|
79479
|
+
function isAnthropicModel(model) {
|
|
79480
|
+
const m = typeof model === "string" ? model.trim().toLowerCase() : "";
|
|
79481
|
+
if (!m) return false;
|
|
79482
|
+
if (m.startsWith("claude") || m.startsWith("anthropic")) return true;
|
|
79483
|
+
return /^(opus|sonnet|haiku)(\b|[-_])/.test(m);
|
|
79484
|
+
}
|
|
79485
|
+
function isModelCompatibleWithProvider(model, providerType) {
|
|
79486
|
+
if (!isAnthropicModel(model)) return true;
|
|
79487
|
+
if (isAnthropicProvider(providerType)) return true;
|
|
79488
|
+
return false;
|
|
79489
|
+
}
|
|
79490
|
+
var ANTHROPIC_PROVIDER_TYPES;
|
|
79491
|
+
var init_model_provider_compat = __esm2({
|
|
79492
|
+
"src/mesh/model-provider-compat.ts"() {
|
|
79493
|
+
"use strict";
|
|
79494
|
+
ANTHROPIC_PROVIDER_TYPES = /* @__PURE__ */ new Set([
|
|
79495
|
+
"claude-cli"
|
|
79496
|
+
]);
|
|
79497
|
+
}
|
|
79498
|
+
});
|
|
79499
|
+
function encodeDuplicateMeshDispatchCode(holderSessionId) {
|
|
79500
|
+
const holder = typeof holderSessionId === "string" ? holderSessionId.trim() : "";
|
|
79501
|
+
return holder ? `${DUPLICATE_MESH_DISPATCH_CODE}:${holder}` : DUPLICATE_MESH_DISPATCH_CODE;
|
|
79502
|
+
}
|
|
79503
|
+
function classifyDuplicateMeshDispatch(err) {
|
|
79504
|
+
if (!err || typeof err !== "object") return null;
|
|
79505
|
+
const e = err;
|
|
79506
|
+
if (e.code === DUPLICATE_MESH_DISPATCH_CODE) {
|
|
79507
|
+
const holder = typeof e.holderSessionId === "string" ? e.holderSessionId.trim() : "";
|
|
79508
|
+
return holder ? { holderSessionId: holder } : {};
|
|
79509
|
+
}
|
|
79510
|
+
for (const raw of [e.meshCode, e.code]) {
|
|
79511
|
+
if (typeof raw !== "string") continue;
|
|
79512
|
+
if (raw !== DUPLICATE_MESH_DISPATCH_CODE && !raw.startsWith(`${DUPLICATE_MESH_DISPATCH_CODE}:`)) continue;
|
|
79513
|
+
const holder = raw.slice(DUPLICATE_MESH_DISPATCH_CODE.length + 1).trim();
|
|
79514
|
+
return holder ? { holderSessionId: holder } : {};
|
|
79515
|
+
}
|
|
79516
|
+
return null;
|
|
79517
|
+
}
|
|
79518
|
+
var DUPLICATE_MESH_DISPATCH_CODE;
|
|
79519
|
+
var DuplicateMeshDispatchError;
|
|
79520
|
+
var init_mesh_duplicate_dispatch = __esm2({
|
|
79521
|
+
"src/mesh/mesh-duplicate-dispatch.ts"() {
|
|
79522
|
+
"use strict";
|
|
79523
|
+
DUPLICATE_MESH_DISPATCH_CODE = "DUPLICATE_MESH_DISPATCH";
|
|
79524
|
+
DuplicateMeshDispatchError = class extends Error {
|
|
79525
|
+
code = DUPLICATE_MESH_DISPATCH_CODE;
|
|
79526
|
+
holderSessionId;
|
|
79527
|
+
constructor(message, info = {}) {
|
|
79528
|
+
super(message);
|
|
79529
|
+
this.name = "DuplicateMeshDispatchError";
|
|
79530
|
+
this.holderSessionId = info.holderSessionId;
|
|
79531
|
+
}
|
|
79532
|
+
};
|
|
79533
|
+
}
|
|
79534
|
+
});
|
|
79535
|
+
function acquireAutoFastForwardLease(workspace) {
|
|
79536
|
+
const key2 = normalizeMeshWorkspaceForCompare(workspace);
|
|
79537
|
+
if (!key2) return false;
|
|
79538
|
+
if (autoFastForwardWorkspaceLease.has(key2)) return false;
|
|
79539
|
+
autoFastForwardWorkspaceLease.add(key2);
|
|
79540
|
+
return true;
|
|
79541
|
+
}
|
|
79542
|
+
function releaseAutoFastForwardLease(workspace) {
|
|
79543
|
+
const key2 = normalizeMeshWorkspaceForCompare(workspace);
|
|
79544
|
+
if (key2) autoFastForwardWorkspaceLease.delete(key2);
|
|
79545
|
+
}
|
|
79546
|
+
function isWorkspaceAutoFastForwardInFlight(workspace) {
|
|
79547
|
+
const key2 = normalizeMeshWorkspaceForCompare(workspace || "");
|
|
79548
|
+
return !!key2 && autoFastForwardWorkspaceLease.has(key2);
|
|
79549
|
+
}
|
|
79550
|
+
function __resetIdleAutoFastForwardForTests() {
|
|
79551
|
+
idleAutoFastForwardLastAttempt.clear();
|
|
79552
|
+
continuousAutoFastForwardLastScan.clear();
|
|
79553
|
+
autoFastForwardWorkspaceLease.clear();
|
|
79554
|
+
}
|
|
79555
|
+
function isDirtyNode(node) {
|
|
79556
|
+
return node?.health === "dirty" || node?.git?.dirty === true;
|
|
79557
|
+
}
|
|
79558
|
+
function resolveAutoFastForwardPolicy(mesh) {
|
|
79559
|
+
const record2 = mesh?.policy?.autoFastForward && typeof mesh.policy.autoFastForward === "object" && !Array.isArray(mesh.policy.autoFastForward) ? mesh.policy.autoFastForward : {};
|
|
79560
|
+
const maxBehind = Number(record2.maxBehind);
|
|
79561
|
+
return {
|
|
79562
|
+
enabled: record2.enabled !== false,
|
|
79563
|
+
...Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {},
|
|
79564
|
+
requireCleanSubmodules: record2.requireCleanSubmodules !== false,
|
|
79565
|
+
// Strict opt-in: absent/false → self-only (historical behavior). Only an
|
|
79566
|
+
// explicit `true` extends auto ff to remote owning-daemon nodes.
|
|
79567
|
+
remoteNodes: record2.remoteNodes === true,
|
|
79568
|
+
// Absent/anything-but-continuous → 'idle' (historical idle-edge-only detection).
|
|
79569
|
+
mode: record2.mode === "continuous" ? "continuous" : "idle"
|
|
79570
|
+
};
|
|
79571
|
+
}
|
|
79572
|
+
function dryRunSatisfiesAutoFastForwardPolicy(dryRun, policy) {
|
|
79573
|
+
if (!dryRun || dryRun.code !== "fast_forward_available" || dryRun.allowed !== true) return false;
|
|
79574
|
+
const behind = Number(dryRun.current?.behind);
|
|
79575
|
+
if (!Number.isFinite(behind) || behind <= 0) return false;
|
|
79576
|
+
if (policy.maxBehind !== void 0 && behind > policy.maxBehind) return false;
|
|
79577
|
+
if (policy.requireCleanSubmodules) {
|
|
79578
|
+
const submodules = Array.isArray(dryRun.current?.submodules) ? dryRun.current.submodules : [];
|
|
79579
|
+
if (submodules.some((submodule) => submodule?.dirty || submodule?.error)) return false;
|
|
79580
|
+
}
|
|
79581
|
+
return true;
|
|
79582
|
+
}
|
|
79583
|
+
function readNodeSubmoduleIgnorePaths(node) {
|
|
79584
|
+
return Array.isArray(node?.policy?.submoduleIgnorePaths) ? node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
|
|
79585
|
+
}
|
|
79586
|
+
function nodeIsAutoFastForwardEligible(components, meshId, nodeId, node, currentSessionId) {
|
|
79587
|
+
if (!node) return false;
|
|
79588
|
+
if (node.status === "disabled" || node.status === "removed") return false;
|
|
79589
|
+
if (node.readOnly === true || node.policy?.readOnly === true) return false;
|
|
79590
|
+
if (isWorktreeBootstrapStaleRunning(node)) return false;
|
|
79591
|
+
if (node.worktreeBootstrap?.status === "running") return false;
|
|
79592
|
+
if (nodeHasActiveMeshWork(components, meshId, nodeId, currentSessionId)) return false;
|
|
79593
|
+
return true;
|
|
79594
|
+
}
|
|
79595
|
+
function remoteNodeIsConnected(components, node) {
|
|
79596
|
+
const daemonId = readMeshNodeDaemonId(node ?? {});
|
|
79597
|
+
if (!daemonId) return false;
|
|
79598
|
+
const getPeerStatus = components.getMeshPeerConnectionStatus;
|
|
79599
|
+
if (getPeerStatus) {
|
|
79600
|
+
const snapshot = getPeerStatus(daemonId);
|
|
79601
|
+
return !!snapshot && String(snapshot.state) === "connected";
|
|
79602
|
+
}
|
|
79603
|
+
return readNonEmptyString(node?.connection?.state).toLowerCase() === "connected";
|
|
79604
|
+
}
|
|
79605
|
+
async function delegateRemoteAutoFastForward(components, args) {
|
|
79606
|
+
const dispatchMeshCommand = components.dispatchMeshCommand;
|
|
79607
|
+
if (!dispatchMeshCommand) return;
|
|
79608
|
+
if (!acquireAutoFastForwardLease(args.workspace)) return;
|
|
79609
|
+
const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
|
|
79610
|
+
const mesh = getMeshWithCache(components, args.meshId);
|
|
79611
|
+
const baseArgs = {
|
|
79612
|
+
meshId: args.meshId,
|
|
79613
|
+
nodeId: args.nodeId,
|
|
79614
|
+
workspace: args.workspace,
|
|
79615
|
+
inlineMesh: mesh,
|
|
79616
|
+
...submoduleIgnorePaths ? { submoduleIgnorePaths } : {},
|
|
79617
|
+
trigger: args.trigger,
|
|
79618
|
+
// Mirror the manual mesh_fast_forward_node update_submodules behavior: if the
|
|
79619
|
+
// ff-only merge moves a submodule gitlink, run `git submodule update --init
|
|
79620
|
+
// --recursive` in the same cycle so the checkout never drifts from the gitlink.
|
|
79621
|
+
// Without this, drift accumulates and self-blocks every subsequent auto-ff
|
|
79622
|
+
// (collectPreflightBlockers treats out-of-sync submodules as a hard blocker).
|
|
79623
|
+
updateSubmodules: true
|
|
79624
|
+
};
|
|
79625
|
+
try {
|
|
79626
|
+
const remoteDry = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
|
|
79627
|
+
...baseArgs,
|
|
79628
|
+
execute: false,
|
|
79629
|
+
dryRun: true
|
|
79630
|
+
});
|
|
79631
|
+
if (!dryRunSatisfiesAutoFastForwardPolicy(remoteDry, args.policy)) return;
|
|
79632
|
+
if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId)) return;
|
|
79633
|
+
const executed = await dispatchMeshCommand(args.daemonId, "fast_forward_mesh_node", {
|
|
79634
|
+
...baseArgs,
|
|
79635
|
+
execute: true,
|
|
79636
|
+
dryRun: false
|
|
79637
|
+
});
|
|
79638
|
+
if (executed?.executed === true) {
|
|
79639
|
+
LOG2.info("MeshFastForward", `Remote auto fast-forward executed for node ${args.nodeId} (daemon ${String(args.daemonId).slice(0, 12)}, trigger ${args.trigger})`);
|
|
79640
|
+
}
|
|
79641
|
+
} catch (e) {
|
|
79642
|
+
LOG2.warn("MeshFastForward", `Remote auto fast-forward delegation failed for ${args.nodeId}: ${e?.message || e}`);
|
|
79643
|
+
} finally {
|
|
79644
|
+
releaseAutoFastForwardLease(args.workspace);
|
|
79645
|
+
}
|
|
79646
|
+
}
|
|
79647
|
+
async function executeLocalAutoFastForward(args) {
|
|
79648
|
+
if (!acquireAutoFastForwardLease(args.workspace)) return;
|
|
79649
|
+
const submoduleIgnorePaths = readNodeSubmoduleIgnorePaths(args.node);
|
|
79650
|
+
try {
|
|
79651
|
+
const dryRun = await fastForwardMeshNode({
|
|
79652
|
+
meshId: args.meshId,
|
|
79653
|
+
nodeId: args.nodeId,
|
|
79654
|
+
workspace: args.workspace,
|
|
79655
|
+
execute: false,
|
|
79656
|
+
dryRun: true,
|
|
79657
|
+
// See delegateRemoteAutoFastForward's updateSubmodules comment: mirrors the
|
|
79658
|
+
// manual tool so a gitlink-moving ff cannot leave the submodule drifted.
|
|
79659
|
+
updateSubmodules: true,
|
|
79660
|
+
submoduleIgnorePaths,
|
|
79661
|
+
trigger: args.trigger
|
|
79662
|
+
});
|
|
79663
|
+
if (!dryRunSatisfiesAutoFastForwardPolicy(dryRun, args.policy)) return;
|
|
79664
|
+
await fastForwardMeshNode({
|
|
79665
|
+
meshId: args.meshId,
|
|
79666
|
+
nodeId: args.nodeId,
|
|
79667
|
+
workspace: args.workspace,
|
|
79668
|
+
execute: true,
|
|
79669
|
+
dryRun: false,
|
|
79670
|
+
updateSubmodules: true,
|
|
79671
|
+
submoduleIgnorePaths,
|
|
79672
|
+
trigger: args.trigger
|
|
79673
|
+
});
|
|
79674
|
+
} catch (e) {
|
|
79675
|
+
LOG2.warn("MeshFastForward", `Idle auto fast-forward check failed for ${args.nodeId}: ${e?.message || e}`);
|
|
79676
|
+
} finally {
|
|
79677
|
+
releaseAutoFastForwardLease(args.workspace);
|
|
79678
|
+
}
|
|
79679
|
+
}
|
|
79680
|
+
async function maybeAutoFastForwardIdleNode(components, args) {
|
|
79681
|
+
const mesh = getMeshWithCache(components, args.meshId);
|
|
79682
|
+
const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
|
|
79683
|
+
const workspace = readNonEmptyString(node?.workspace);
|
|
79684
|
+
if (!workspace) return;
|
|
79685
|
+
const policy = resolveAutoFastForwardPolicy(mesh);
|
|
79686
|
+
if (!policy.enabled) return;
|
|
79687
|
+
if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
|
|
79688
|
+
const throttleKey = `${args.meshId}:${args.nodeId}`;
|
|
79689
|
+
const now = Date.now();
|
|
79690
|
+
const lastAttempt = idleAutoFastForwardLastAttempt.get(throttleKey) || 0;
|
|
79691
|
+
if (now - lastAttempt < IDLE_AUTO_FAST_FORWARD_THROTTLE_MS) return;
|
|
79692
|
+
idleAutoFastForwardLastAttempt.set(throttleKey, now);
|
|
79693
|
+
if (isLocalAutoLaunchNode(node)) {
|
|
79694
|
+
if (!(0, import_fs17.existsSync)(workspace)) return;
|
|
79695
|
+
await executeLocalAutoFastForward({ meshId: args.meshId, nodeId: args.nodeId, node, workspace, policy, trigger: "idle_auto" });
|
|
79696
|
+
return;
|
|
79697
|
+
}
|
|
79698
|
+
if (!policy.remoteNodes) return;
|
|
79699
|
+
const daemonId = readMeshNodeDaemonId(node ?? {});
|
|
79700
|
+
if (!daemonId || !components.dispatchMeshCommand) return;
|
|
79701
|
+
if (!remoteNodeIsConnected(components, node)) return;
|
|
79702
|
+
await delegateRemoteAutoFastForward(components, { meshId: args.meshId, nodeId: args.nodeId, node, daemonId, workspace, policy, trigger: "idle_auto" });
|
|
79703
|
+
}
|
|
79704
|
+
async function runContinuousAutoFastForwardScan(components, mesh) {
|
|
79705
|
+
if (!components.dispatchMeshCommand) return;
|
|
79706
|
+
const policy = resolveAutoFastForwardPolicy(mesh);
|
|
79707
|
+
if (!policy.enabled || !policy.remoteNodes || policy.mode !== "continuous") return;
|
|
79708
|
+
const meshId = readNonEmptyString(mesh?.id);
|
|
79709
|
+
if (!meshId) return;
|
|
79710
|
+
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
79711
|
+
const now = Date.now();
|
|
79712
|
+
for (const node of nodes) {
|
|
79713
|
+
const nodeId = normalizeMeshNodeId(node);
|
|
79714
|
+
if (!nodeId) continue;
|
|
79715
|
+
if (node?.isLocalWorktree === true) continue;
|
|
79716
|
+
if (isLocalAutoLaunchNode(node)) continue;
|
|
79717
|
+
const workspace = readNonEmptyString(node?.workspace);
|
|
79718
|
+
if (!workspace) continue;
|
|
79719
|
+
const daemonId = readMeshNodeDaemonId(node ?? {});
|
|
79720
|
+
if (!daemonId) continue;
|
|
79721
|
+
if (!nodeIsAutoFastForwardEligible(components, meshId, nodeId, node)) continue;
|
|
79722
|
+
if (!remoteNodeIsConnected(components, node)) continue;
|
|
79723
|
+
const cooldownKey = `${meshId}:${nodeId}`;
|
|
79724
|
+
const lastScan = continuousAutoFastForwardLastScan.get(cooldownKey) || 0;
|
|
79725
|
+
if (now - lastScan < CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS) continue;
|
|
79726
|
+
continuousAutoFastForwardLastScan.set(cooldownKey, now);
|
|
79727
|
+
await delegateRemoteAutoFastForward(components, { meshId, nodeId, node, daemonId, workspace, policy, trigger: "reconcile_auto" });
|
|
79728
|
+
}
|
|
79729
|
+
}
|
|
79730
|
+
async function runPendingCoordinatorCatchupScan(components, mesh) {
|
|
79731
|
+
const meshId = readNonEmptyString(mesh?.id);
|
|
79732
|
+
if (!meshId) return;
|
|
79733
|
+
const localIds = expandDaemonIdForms([
|
|
79734
|
+
readNonEmptyString(components.statusInstanceId),
|
|
79735
|
+
readNonEmptyString(loadConfig2().machineId)
|
|
79736
|
+
]);
|
|
79737
|
+
let markers = [];
|
|
79738
|
+
try {
|
|
79739
|
+
markers = drainPendingMeshCoordinatorEvents(
|
|
79740
|
+
meshId,
|
|
79741
|
+
localIds.length > 0 ? localIds : void 0,
|
|
79742
|
+
{ onlyEvents: /* @__PURE__ */ new Set(["coordinator_catchup"]) }
|
|
79743
|
+
);
|
|
79744
|
+
} catch (e) {
|
|
79745
|
+
LOG2.warn("MeshReconcile", `Coordinator-catchup drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
79746
|
+
return;
|
|
79747
|
+
}
|
|
79748
|
+
if (markers.length === 0) return;
|
|
79749
|
+
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
79750
|
+
for (const marker of markers) {
|
|
79751
|
+
const meta3 = marker.metadataEvent || {};
|
|
79752
|
+
const nodeId = readNonEmptyString(marker.nodeId) || readNonEmptyString(meta3.nodeId);
|
|
79753
|
+
const workspace = readNonEmptyString(marker.workspace) || readNonEmptyString(meta3.workspace);
|
|
79754
|
+
const baseBranch = readNonEmptyString(meta3.baseBranch);
|
|
79755
|
+
if (!workspace) continue;
|
|
79756
|
+
if (nodeId && nodeHasActiveMeshWork(components, meshId, nodeId)) {
|
|
79757
|
+
try {
|
|
79758
|
+
queuePendingMeshCoordinatorEvent(marker);
|
|
79759
|
+
} catch {
|
|
79760
|
+
}
|
|
79761
|
+
continue;
|
|
79762
|
+
}
|
|
79763
|
+
try {
|
|
79764
|
+
const ff = await fastForwardMeshNode({
|
|
79765
|
+
meshId,
|
|
79766
|
+
...nodeId ? { nodeId } : {},
|
|
79767
|
+
workspace,
|
|
79768
|
+
...baseBranch ? { branch: baseBranch } : {},
|
|
79769
|
+
mode: "merge",
|
|
79770
|
+
execute: true,
|
|
79771
|
+
// Same gitlink-drift-prevention rationale as executeLocalAutoFastForward /
|
|
79772
|
+
// delegateRemoteAutoFastForward — this path pushed the base branch itself,
|
|
79773
|
+
// so a submodule gitlink bump here is exactly as likely.
|
|
79774
|
+
updateSubmodules: true,
|
|
79775
|
+
trigger: "refine_post_push_catchup",
|
|
79776
|
+
allowAutoPublishSubmoduleMainCommits: mesh?.policy?.allowAutoPublishSubmoduleMainCommits === true
|
|
79777
|
+
});
|
|
79778
|
+
LOG2.info("MeshReconcile", `Coordinator catch-up ff for ${meshId}/${nodeId || workspace}: ${ff.code} (executed=${ff.executed})`);
|
|
79779
|
+
} catch (e) {
|
|
79780
|
+
LOG2.warn("MeshReconcile", `Coordinator catch-up ff failed for ${meshId}/${nodeId || workspace}: ${e?.message || e}`);
|
|
79781
|
+
}
|
|
79782
|
+
}
|
|
79783
|
+
}
|
|
79784
|
+
var import_fs17;
|
|
79785
|
+
var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS;
|
|
79786
|
+
var idleAutoFastForwardLastAttempt;
|
|
79787
|
+
var CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS;
|
|
79788
|
+
var continuousAutoFastForwardLastScan;
|
|
79789
|
+
var autoFastForwardWorkspaceLease;
|
|
79790
|
+
var init_mesh_auto_fast_forward = __esm2({
|
|
79791
|
+
"src/mesh/mesh-auto-fast-forward.ts"() {
|
|
79792
|
+
"use strict";
|
|
79793
|
+
import_fs17 = require("fs");
|
|
79794
|
+
init_logger();
|
|
79795
|
+
init_config();
|
|
79796
|
+
init_mesh_fast_forward();
|
|
79797
|
+
init_dist();
|
|
79798
|
+
init_mesh_events_utils();
|
|
79799
|
+
init_mesh_node_identity();
|
|
79800
|
+
init_mesh_events_pending();
|
|
79801
|
+
init_worktree_bootstrap_config();
|
|
79802
|
+
init_mesh_queue_assignment();
|
|
79803
|
+
IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
|
|
79804
|
+
idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
|
|
79805
|
+
CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS = 45 * 1e3;
|
|
79806
|
+
continuousAutoFastForwardLastScan = /* @__PURE__ */ new Map();
|
|
79807
|
+
autoFastForwardWorkspaceLease = /* @__PURE__ */ new Set();
|
|
79808
|
+
}
|
|
79809
|
+
});
|
|
79810
|
+
function normalizeNodeIdKey(nodeId) {
|
|
79811
|
+
return normalizeMeshNodeId({ id: nodeId ?? void 0 }) ?? "";
|
|
79812
|
+
}
|
|
79813
|
+
function noteRecentlyClonedNode(nodeId, nowMs = Date.now()) {
|
|
79814
|
+
const key2 = normalizeNodeIdKey(nodeId);
|
|
79815
|
+
if (!key2) return;
|
|
79816
|
+
recentlyClonedNodeExpiry.set(key2, nowMs + CLONE_BOOTSTRAP_GRACE_MS);
|
|
79817
|
+
if (recentlyClonedNodeExpiry.size > MAX_TRACKED_CLONED_NODES) {
|
|
79818
|
+
const oldest = recentlyClonedNodeExpiry.keys().next().value;
|
|
79819
|
+
if (oldest !== void 0) recentlyClonedNodeExpiry.delete(oldest);
|
|
79820
|
+
}
|
|
79821
|
+
}
|
|
79822
|
+
function isWithinCloneBootstrapGrace(nodeId, nowMs = Date.now()) {
|
|
79823
|
+
const key2 = normalizeNodeIdKey(nodeId);
|
|
79824
|
+
if (!key2) return false;
|
|
79825
|
+
const expiry = recentlyClonedNodeExpiry.get(key2);
|
|
79826
|
+
if (expiry === void 0) return false;
|
|
79827
|
+
if (nowMs >= expiry) {
|
|
79828
|
+
recentlyClonedNodeExpiry.delete(key2);
|
|
79829
|
+
return false;
|
|
79830
|
+
}
|
|
79831
|
+
return true;
|
|
79832
|
+
}
|
|
79833
|
+
var CLONE_BOOTSTRAP_GRACE_MS;
|
|
79834
|
+
var recentlyClonedNodeExpiry;
|
|
79835
|
+
var MAX_TRACKED_CLONED_NODES;
|
|
79836
|
+
var init_mesh_clone_grace = __esm2({
|
|
79837
|
+
"src/mesh/mesh-clone-grace.ts"() {
|
|
79863
79838
|
"use strict";
|
|
79864
|
-
init_mesh_work_queue();
|
|
79865
|
-
init_mesh_events_pending();
|
|
79866
|
-
init_slot_model_enforcement();
|
|
79867
|
-
init_mesh_quota_routing();
|
|
79868
79839
|
init_dist();
|
|
79869
|
-
|
|
79870
|
-
|
|
79871
|
-
|
|
79872
|
-
difficultyFloorTimeoutReported = /* @__PURE__ */ new Set();
|
|
79873
|
-
DIFFICULTY_FLOOR_REPORT_DEDUP_MAX = 2e3;
|
|
79874
|
-
CLASSIFIED_DIFFICULTIES = ["easy", "medium", "difficult"];
|
|
79840
|
+
CLONE_BOOTSTRAP_GRACE_MS = 10 * 60 * 1e3;
|
|
79841
|
+
recentlyClonedNodeExpiry = /* @__PURE__ */ new Map();
|
|
79842
|
+
MAX_TRACKED_CLONED_NODES = 512;
|
|
79875
79843
|
}
|
|
79876
79844
|
});
|
|
79877
|
-
function
|
|
79878
|
-
|
|
79879
|
-
|
|
79880
|
-
const seen = /* @__PURE__ */ new Set();
|
|
79881
|
-
return raw.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean).filter((type2) => {
|
|
79882
|
-
if (seen.has(type2)) return false;
|
|
79883
|
-
seen.add(type2);
|
|
79884
|
-
return true;
|
|
79885
|
-
});
|
|
79886
|
-
}
|
|
79887
|
-
function isTerminalSessionStatus(status) {
|
|
79888
|
-
return ["stopped", "failed", "terminated", "exited", "closed"].includes(status);
|
|
79889
|
-
}
|
|
79890
|
-
function isIdleSessionState3(state) {
|
|
79891
|
-
const status = readNonEmptyString(state?.status).toLowerCase();
|
|
79892
|
-
if (isTerminalSessionStatus(status)) return false;
|
|
79893
|
-
return status === "idle" || state?.activeChat?.status === "waiting_input";
|
|
79845
|
+
function isActionableSkipReason(reason) {
|
|
79846
|
+
if (!reason) return false;
|
|
79847
|
+
return ACTIONABLE_SKIP_REASON_PREFIXES.some((prefix) => reason === prefix || reason.startsWith(prefix));
|
|
79894
79848
|
}
|
|
79895
|
-
function
|
|
79896
|
-
const
|
|
79897
|
-
|
|
79898
|
-
const
|
|
79899
|
-
|
|
79849
|
+
function isTargetNodeTransientlyUnresolved(mesh, task) {
|
|
79850
|
+
const targetNodeId = readNonEmptyString(task.targetNodeId);
|
|
79851
|
+
if (!targetNodeId) return false;
|
|
79852
|
+
const node = Array.isArray(mesh?.nodes) ? mesh.nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
|
|
79853
|
+
if (node && node.worktreeBootstrap?.status === "running" && !isWorktreeBootstrapStaleRunning(node)) {
|
|
79854
|
+
return true;
|
|
79855
|
+
}
|
|
79856
|
+
return isWithinCloneBootstrapGrace(targetNodeId);
|
|
79900
79857
|
}
|
|
79901
|
-
function
|
|
79902
|
-
|
|
79903
|
-
return
|
|
79904
|
-
const state = inst.getState();
|
|
79905
|
-
const settings = state.settings || {};
|
|
79906
|
-
if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
|
|
79907
|
-
const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
79908
|
-
if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
|
|
79909
|
-
const sessionId = readNonEmptyString(state.instanceId);
|
|
79910
|
-
if (currentSessionId && sessionIdsEquivalent(sessionId, currentSessionId) && isIdleSessionState3(state)) return false;
|
|
79911
|
-
return sessionStateLooksActive(state);
|
|
79912
|
-
});
|
|
79858
|
+
function targetPinAgeMs(task, nowMs = Date.now()) {
|
|
79859
|
+
const anchorMs = Date.parse(task.requeuedAt || task.createdAt || "");
|
|
79860
|
+
return Number.isFinite(anchorMs) ? nowMs - anchorMs : null;
|
|
79913
79861
|
}
|
|
79914
|
-
function
|
|
79915
|
-
|
|
79916
|
-
if (
|
|
79917
|
-
|
|
79862
|
+
function resolveTargetPinTtlVerdict(components, task, nowMs = Date.now()) {
|
|
79863
|
+
const wallAgeMs = targetPinAgeMs(task, nowMs);
|
|
79864
|
+
if (wallAgeMs === null) return { expired: false, ageMs: null, suspended: false };
|
|
79865
|
+
const targetSessionId = readNonEmptyString(task.targetSessionId);
|
|
79866
|
+
const key2 = `${task.meshId}::${task.id}`;
|
|
79867
|
+
const prior = targetPinGeneratingCreditMs.get(key2);
|
|
79868
|
+
const generating = !!targetSessionId && resolveSessionBusyVerdict(components, targetSessionId) === "GENERATING";
|
|
79869
|
+
let creditMs = prior?.creditMs ?? 0;
|
|
79870
|
+
if (generating && prior) {
|
|
79871
|
+
creditMs += Math.max(0, nowMs - prior.lastSeenMs);
|
|
79918
79872
|
}
|
|
79919
|
-
|
|
79873
|
+
targetPinGeneratingCreditMs.set(key2, { creditMs, lastSeenMs: nowMs });
|
|
79874
|
+
const unproductiveAgeMs = Math.max(0, wallAgeMs - creditMs);
|
|
79875
|
+
return {
|
|
79876
|
+
// A tick on which the addressee is OBSERVABLY GENERATING never expires the pin,
|
|
79877
|
+
// independently of the accumulated credit.
|
|
79878
|
+
//
|
|
79879
|
+
// The credit ledger alone is not sufficient here, and the difference is the
|
|
79880
|
+
// whole live defect. Credit only accrues from the SECOND observation onward
|
|
79881
|
+
// (the first has no prior interval to bank), and it is in-memory — so a pin
|
|
79882
|
+
// that crossed the wall-clock TTL while the daemon was not watching, or before
|
|
79883
|
+
// a restart, would arrive at its very first post-restart observation with zero
|
|
79884
|
+
// credit and expire on the spot, while the session it is addressed to is
|
|
79885
|
+
// visibly mid-turn. That is exactly the observed failure (`unclaimed 902s`
|
|
79886
|
+
// logged on an `agent:ready`, i.e. at the end of real work) reproduced by a
|
|
79887
|
+
// different route.
|
|
79888
|
+
//
|
|
79889
|
+
// Gating on the live verdict makes "is the addressee working right now?" the
|
|
79890
|
+
// decisive question and leaves the credit ledger as what it should be: an
|
|
79891
|
+
// optimisation that stops intermittent work from silently burning the budget.
|
|
79892
|
+
// It cannot make a pin immortal — the verdict is re-evaluated every tick from
|
|
79893
|
+
// live state and only a LOCAL, observably-generating session can produce it.
|
|
79894
|
+
expired: !generating && unproductiveAgeMs >= TARGET_SESSION_PIN_TTL_MS,
|
|
79895
|
+
ageMs: unproductiveAgeMs,
|
|
79896
|
+
suspended: generating
|
|
79897
|
+
};
|
|
79920
79898
|
}
|
|
79921
|
-
function
|
|
79922
|
-
const
|
|
79923
|
-
const
|
|
79924
|
-
const
|
|
79925
|
-
|
|
79926
|
-
const
|
|
79927
|
-
|
|
79928
|
-
|
|
79929
|
-
|
|
79899
|
+
function resolveDeadTargetVerdict(components, meshId, mesh, task) {
|
|
79900
|
+
const NOT_DEAD = { dead: false, nodeDead: false, reason: "" };
|
|
79901
|
+
const targetSessionId = readNonEmptyString(task.targetSessionId);
|
|
79902
|
+
const targetNodeId = readNonEmptyString(task.targetNodeId);
|
|
79903
|
+
if (!targetSessionId && !targetNodeId) return NOT_DEAD;
|
|
79904
|
+
const lastUpdateMs = Date.parse(task.updatedAt || task.createdAt || "");
|
|
79905
|
+
if (Number.isFinite(lastUpdateMs) && Date.now() - lastUpdateMs < DEAD_TARGET_GRACE_MS) return NOT_DEAD;
|
|
79906
|
+
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
79907
|
+
if (targetNodeId) {
|
|
79908
|
+
const nodePresent = nodes.some((n) => meshNodeIdMatches(n, targetNodeId));
|
|
79909
|
+
if (!nodePresent) {
|
|
79910
|
+
if (isTargetNodeTransientlyUnresolved(mesh, task)) return NOT_DEAD;
|
|
79911
|
+
return { dead: true, nodeDead: true, reason: "dead_target_node_absent" };
|
|
79912
|
+
}
|
|
79930
79913
|
}
|
|
79931
|
-
if (
|
|
79932
|
-
|
|
79914
|
+
if (targetSessionId) {
|
|
79915
|
+
const node = targetNodeId ? nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
|
|
79916
|
+
const nodeIsLocal = node ? isLocalAutoLaunchNode(node) : true;
|
|
79917
|
+
if (nodeIsLocal) {
|
|
79918
|
+
const verdict = resolveSessionBusyVerdict(components, targetSessionId);
|
|
79919
|
+
if (verdict === "UNKNOWN") {
|
|
79920
|
+
return { dead: true, nodeDead: false, reason: "dead_target_session_absent" };
|
|
79921
|
+
}
|
|
79922
|
+
}
|
|
79933
79923
|
}
|
|
79934
|
-
return
|
|
79924
|
+
return NOT_DEAD;
|
|
79935
79925
|
}
|
|
79936
|
-
function
|
|
79937
|
-
|
|
79938
|
-
|
|
79939
|
-
|
|
79940
|
-
|
|
79926
|
+
function retractActionableSkipIfPreviouslyNotified(meshId, taskId) {
|
|
79927
|
+
const dedupKey = `${meshId}:${taskId}`;
|
|
79928
|
+
if (!lastActionableSkipNotified.delete(dedupKey)) return;
|
|
79929
|
+
try {
|
|
79930
|
+
const coordinatorDaemonId = readNonEmptyString(loadConfig2().machineId) || void 0;
|
|
79931
|
+
const removed = retractPendingDispatchBlockedEvent(meshId, taskId, coordinatorDaemonId);
|
|
79932
|
+
if (removed > 0) {
|
|
79933
|
+
LOG2.info("MeshQueue", `Retracted ${removed} stale dispatch-blocked event(s) for task ${taskId} (mesh ${meshId}) \u2014 its blocker resolved`);
|
|
79934
|
+
}
|
|
79935
|
+
} catch (e) {
|
|
79936
|
+
LOG2.warn("MeshQueue", `Failed to retract stale dispatch-blocked event for task ${taskId} (mesh ${meshId}): ${e?.message || e}`);
|
|
79937
|
+
}
|
|
79941
79938
|
}
|
|
79942
|
-
function
|
|
79943
|
-
if (!sessionId) return "UNKNOWN";
|
|
79939
|
+
function resolveTaskDeliveryEvidence(meshId, taskId) {
|
|
79944
79940
|
try {
|
|
79945
|
-
const
|
|
79946
|
-
|
|
79947
|
-
|
|
79948
|
-
return sid && sessionIdsEquivalent(sid, sessionId);
|
|
79949
|
-
});
|
|
79950
|
-
if (!inst) return "UNKNOWN";
|
|
79951
|
-
const state = inst.getState?.();
|
|
79952
|
-
if (!state) return "UNKNOWN";
|
|
79953
|
-
return sessionStateLooksActive(state) ? "GENERATING" : "IDLE_CONFIRMED";
|
|
79941
|
+
const store = MeshRuntimeStore.getInstance();
|
|
79942
|
+
if (store.taskDeliveryConsumed(meshId, taskId)) return "consumed";
|
|
79943
|
+
if (store.taskHasConfirmedDelivery(meshId, taskId)) return "delivered";
|
|
79954
79944
|
} catch {
|
|
79955
|
-
return "
|
|
79945
|
+
return "delivered";
|
|
79956
79946
|
}
|
|
79947
|
+
return "never_dispatched";
|
|
79957
79948
|
}
|
|
79958
|
-
function
|
|
79959
|
-
|
|
79960
|
-
|
|
79961
|
-
|
|
79962
|
-
|
|
79963
|
-
|
|
79964
|
-
|
|
79965
|
-
|
|
79966
|
-
|
|
79967
|
-
|
|
79968
|
-
|
|
79969
|
-
|
|
79970
|
-
|
|
79971
|
-
|
|
79949
|
+
function actionableSkipGuidance(reason, evidence) {
|
|
79950
|
+
if (reason === "target_node_id_unmatched") return {
|
|
79951
|
+
summary: "it is pinned to a target node id that matches no node in the mesh (the node may have been removed, or its id form does not resolve)",
|
|
79952
|
+
nextAction: "Verify the target node still exists with mesh_status, then re-enqueue without the node pin or with a valid node id (or re-clone the node)."
|
|
79953
|
+
};
|
|
79954
|
+
if (reason === "no_node_satisfies_required_tags") return {
|
|
79955
|
+
summary: "no node in the mesh can satisfy the task's required capability tags",
|
|
79956
|
+
nextAction: "Relax the task's requiredTags, or add/launch a node whose provider produces the required capabilities."
|
|
79957
|
+
};
|
|
79958
|
+
if (reason === "mesh_convergence_target_is_worktree") return {
|
|
79959
|
+
summary: "it is a convergence task (base-only: merge \u2192 push \u2192 cleanup) but every candidate node is a worktree clone",
|
|
79960
|
+
nextAction: "Dispatch the convergence task to the base node, or run the deterministic fast-forward path (mesh_fast_forward_node / mesh_refine_node) instead."
|
|
79961
|
+
};
|
|
79962
|
+
if (reason.startsWith("remote_auto_launch")) return {
|
|
79963
|
+
summary: "the target node is on a remote daemon this coordinator cannot auto-launch a session on (no dispatch transport, or no coordinator daemon id to stamp)",
|
|
79964
|
+
nextAction: "Launch a session on that node yourself with mesh_launch_session, or ensure the remote daemon is connected over P2P."
|
|
79965
|
+
};
|
|
79966
|
+
if (reason.startsWith("provider") || reason === "missing_provider_priority") return {
|
|
79967
|
+
summary: `the current provider scan found no usable provider for this task (provider priority missing/unusable, or the provider loader is unavailable; ${reason})`,
|
|
79968
|
+
nextAction: "Check the node's providerPriority policy and that the required CLI/ACP provider is installed and enabled on that machine. Quota-gated candidates use a separate, self-resolving reason and are not proof of this configuration blocker."
|
|
79969
|
+
};
|
|
79970
|
+
if (reason === "dirty_workspace") return {
|
|
79971
|
+
summary: "the node's workspace is dirty, so auto-launch is blocked to avoid clobbering uncommitted changes",
|
|
79972
|
+
nextAction: "Clean or commit the node's working tree (or fast-forward it); the task will then auto-assign."
|
|
79973
|
+
};
|
|
79974
|
+
if (reason === PARKED_SKIP_REASON) {
|
|
79975
|
+
const base = "it was pinned to a specific session, that pin went stale, and the task is now PARKED \u2014 deliberately held for you rather than re-homed onto another session, because a delta written for one session's context becomes a context-free instruction anywhere else";
|
|
79976
|
+
if (evidence === "consumed") return {
|
|
79977
|
+
summary: `${base}. The delivery record shows the addressed session DID receive and start acting on this message, so the parked row is a bookkeeping remnant, not a lost delta`,
|
|
79978
|
+
nextAction: "Do NOT re-send it. Confirm with mesh_read_chat / mesh_read_terminal that the work is under way, then clear the park with mesh_queue_cancel (or requeue it only if you genuinely want it run again)."
|
|
79979
|
+
};
|
|
79980
|
+
if (evidence === "delivered") return {
|
|
79981
|
+
summary: `${base}. The message WAS handed to that session's transport but no turn start was echoed, so whether it acted on it is unconfirmed`,
|
|
79982
|
+
nextAction: "Check the session (mesh_read_chat / mesh_read_terminal) before acting. If it is already handling it, cancel the parked row; if not, mesh_queue_requeue with target_session_id=<live session> \u2014 and pass message=<rewritten instruction> if the situation moved on while it waited."
|
|
79983
|
+
};
|
|
79984
|
+
return {
|
|
79985
|
+
summary: `${base}. No delivery to that session was ever recorded, so the message did not reach it and the worker is still acting on its previous instructions`,
|
|
79986
|
+
nextAction: "Re-target it with mesh_queue_requeue(target_session_id=<live session>), or drop the pin with clear_target_session to let any compatible session take it. Re-read the work produced meanwhile and pass message=<rewritten instruction> if the delta is now partly stale; mesh_queue_cancel if it is moot."
|
|
79987
|
+
};
|
|
79972
79988
|
}
|
|
79973
|
-
|
|
79989
|
+
if (reason === "target_session_pin_expired") {
|
|
79990
|
+
if (evidence === "consumed") return {
|
|
79991
|
+
summary: "it was pinned to a specific session and the pin TTL expired before the queue row was claimed \u2014 but the delivery record shows this session DID receive and start acting on the message (a turn was started for it), so the queue row lagging is a bookkeeping gap, not a lost delta",
|
|
79992
|
+
nextAction: "Do NOT re-send it \u2014 the session already has this message and re-sending would run the same instruction twice. Check its current output (mesh_read_chat / mesh_read_terminal) to confirm the work is under way."
|
|
79993
|
+
};
|
|
79994
|
+
if (evidence === "delivered") return {
|
|
79995
|
+
summary: "it was pinned to a specific session and the pin TTL expired before the queue row was claimed; the message WAS handed to that session's transport, but the session never echoed a turn start, so whether it acted on it is unconfirmed",
|
|
79996
|
+
nextAction: "Verify before re-sending: check the session with mesh_read_chat / mesh_read_terminal. Re-send only if its output shows no sign of this message \u2014 it may already be acting on it, and re-sending would duplicate the instruction."
|
|
79997
|
+
};
|
|
79998
|
+
return {
|
|
79999
|
+
summary: "it was pinned to a specific session (a follow-up/delta for work already in flight) that never claimed it within the pin TTL, so the pin was cleared; no delivery to that session was ever recorded, so the message did not reach it",
|
|
80000
|
+
nextAction: "The addressed session never received this delta and is still acting on its previous instructions. Re-send it to that session once it is idle (or re-target it), and re-check the work it produced in the meantime."
|
|
80001
|
+
};
|
|
80002
|
+
}
|
|
80003
|
+
if (reason === SLOT_MODEL_ABSENT_SKIP_REASON) return {
|
|
80004
|
+
summary: "no capability slot on the node declares the model this task resolved to (its difficulty\u2192brain preset picked a model the node was never configured to run)",
|
|
80005
|
+
nextAction: "Re-enqueue with a difficulty/model the node's slots declare, target a node that declares this model, or add a slot for it. The task is NOT run on a substitute model \u2014 an undeclared model is never launched."
|
|
80006
|
+
};
|
|
80007
|
+
return {
|
|
80008
|
+
summary: `it cannot be dispatched (${reason})`,
|
|
80009
|
+
nextAction: "Inspect the node/mesh state with mesh_status and resolve the blocker, or re-enqueue the task."
|
|
80010
|
+
};
|
|
79974
80011
|
}
|
|
79975
|
-
function
|
|
79976
|
-
if (
|
|
79977
|
-
|
|
79978
|
-
|
|
79979
|
-
);
|
|
79980
|
-
|
|
79981
|
-
|
|
79982
|
-
const
|
|
79983
|
-
if (
|
|
79984
|
-
|
|
79985
|
-
|
|
79986
|
-
|
|
79987
|
-
|
|
79988
|
-
|
|
79989
|
-
|
|
79990
|
-
|
|
79991
|
-
|
|
79992
|
-
|
|
79993
|
-
|
|
79994
|
-
|
|
79995
|
-
|
|
79996
|
-
|
|
79997
|
-
|
|
79998
|
-
|
|
79999
|
-
|
|
80000
|
-
|
|
80012
|
+
function notifyCoordinatorOfActionableSkip(meshId, taskId, reason, nodeId) {
|
|
80013
|
+
if (!isActionableSkipReason(reason)) return;
|
|
80014
|
+
if (reason === "target_node_id_unmatched" && isWithinCloneBootstrapGrace(readNonEmptyString(nodeId))) return;
|
|
80015
|
+
const dedupKey = `${meshId}:${taskId}`;
|
|
80016
|
+
if (lastActionableSkipNotified.get(dedupKey) === reason) return;
|
|
80017
|
+
lastActionableSkipNotified.set(dedupKey, reason);
|
|
80018
|
+
if (lastActionableSkipNotified.size > AUTO_LAUNCH_LEDGER_DEDUP_MAX) {
|
|
80019
|
+
const oldest = lastActionableSkipNotified.keys().next().value;
|
|
80020
|
+
if (oldest !== void 0) lastActionableSkipNotified.delete(oldest);
|
|
80021
|
+
}
|
|
80022
|
+
let task;
|
|
80023
|
+
try {
|
|
80024
|
+
task = getQueue(meshId).find((t) => t.id === taskId);
|
|
80025
|
+
} catch {
|
|
80026
|
+
}
|
|
80027
|
+
if (task && task.status !== "pending") {
|
|
80028
|
+
LOG2.info("MeshQueue", `Suppressed stale dispatch-blocked page for task ${taskId} (mesh ${meshId}): reason '${reason}' was computed against a pre-await snapshot, but the task is now '${task.status}'.`);
|
|
80029
|
+
lastActionableSkipNotified.delete(dedupKey);
|
|
80030
|
+
return;
|
|
80031
|
+
}
|
|
80032
|
+
const targetCoordinatorDaemonId = readNonEmptyString(loadConfig2().machineId);
|
|
80033
|
+
const targetCoordinatorSessionId = readNonEmptyString(task?.sourceCoordinatorSessionId);
|
|
80034
|
+
const nodeLabel = readNonEmptyString(nodeId) || readNonEmptyString(task?.targetNodeId);
|
|
80035
|
+
const evidence = reason === "target_session_pin_expired" || reason === PARKED_SKIP_REASON ? resolveTaskDeliveryEvidence(meshId, taskId) : void 0;
|
|
80036
|
+
const { summary, nextAction } = actionableSkipGuidance(reason, evidence);
|
|
80037
|
+
const providerAvailabilityResult = reason.startsWith("provider") || reason === "missing_provider_priority";
|
|
80038
|
+
const reachabilityResult = reason.startsWith("remote_auto_launch");
|
|
80039
|
+
const closing = reason === PARKED_SKIP_REASON ? `This task is claimable by NOBODY until you act on it \u2014 no session will pick it up and no timer will re-home it. It is held for ${Math.round(PARKED_TASK_RETENTION_MS / 36e5)}h and then failed (with another notification), so it is never silently discarded. Parked rows are listed under parkedTasks in mesh_view_queue, and any mesh_queue_requeue unparks it \u2014 including one that only rewrites its message.` : reason === "target_session_pin_expired" ? "The stale pin has already been cleared, so the task is now claimable by any compatible session \u2014 the action above is about the session it was originally addressed to." : providerAvailabilityResult ? "This result needs action if it persists: a later provider-status refresh or an already-starting usable session can clear it, but a genuinely missing, disabled, or misconfigured provider will keep the task pending until you fix that configuration." : reachabilityResult ? "This result needs action if it persists: the node reconnecting (or re-registering its daemon id) clears it on its own, but a node that stays unreachable will keep the task pending until you bring it back or re-target the task." : "This is an actionable blocker \u2014 it will NOT clear on its own; the task stays pending until you resolve it.";
|
|
80040
|
+
const coordinatorMessage = `[System] A queued mesh task${nodeLabel ? ` for node ${nodeLabel}` : ""} is not being dispatched because ${summary}. ${nextAction} ${closing}`;
|
|
80041
|
+
try {
|
|
80042
|
+
queuePendingMeshCoordinatorEvent({
|
|
80043
|
+
event: "mesh:dispatch_blocked",
|
|
80044
|
+
meshId,
|
|
80045
|
+
nodeLabel: nodeLabel || meshId,
|
|
80046
|
+
...nodeLabel ? { nodeId: nodeLabel } : {},
|
|
80047
|
+
metadataEvent: {
|
|
80048
|
+
source: "mesh_queue_dispatch_skip",
|
|
80049
|
+
taskId,
|
|
80050
|
+
reason,
|
|
80051
|
+
...nodeLabel ? { nodeId: nodeLabel } : {},
|
|
80052
|
+
coordinatorMessage
|
|
80053
|
+
},
|
|
80054
|
+
coordinatorMessage,
|
|
80055
|
+
queuedAt: Date.now(),
|
|
80056
|
+
...targetCoordinatorDaemonId ? { targetCoordinatorDaemonId } : {},
|
|
80057
|
+
...targetCoordinatorSessionId ? { targetCoordinatorSessionId } : {}
|
|
80058
|
+
});
|
|
80059
|
+
} catch (e) {
|
|
80060
|
+
LOG2.warn("MeshQueue", `Failed to surface actionable dispatch-skip (${reason}) for task ${taskId}: ${e?.message || e}`);
|
|
80061
|
+
}
|
|
80001
80062
|
}
|
|
80002
|
-
var
|
|
80003
|
-
|
|
80063
|
+
var ACTIONABLE_SKIP_REASON_PREFIXES;
|
|
80064
|
+
var TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON;
|
|
80065
|
+
var lastActionableSkipNotified;
|
|
80066
|
+
var DEAD_TARGET_GRACE_MS;
|
|
80067
|
+
var TARGET_SESSION_PIN_TTL_MS;
|
|
80068
|
+
var targetPinGeneratingCreditMs;
|
|
80069
|
+
var init_mesh_skip_notify = __esm2({
|
|
80070
|
+
"src/mesh/mesh-skip-notify.ts"() {
|
|
80004
80071
|
"use strict";
|
|
80005
|
-
|
|
80072
|
+
init_logger();
|
|
80006
80073
|
init_mesh_work_queue();
|
|
80074
|
+
init_mesh_runtime_store();
|
|
80007
80075
|
init_dist();
|
|
80008
80076
|
init_mesh_events_utils();
|
|
80009
|
-
|
|
80077
|
+
init_mesh_events_pending();
|
|
80010
80078
|
init_worktree_bootstrap_config();
|
|
80011
|
-
|
|
80012
|
-
|
|
80013
|
-
|
|
80014
|
-
|
|
80079
|
+
init_mesh_clone_grace();
|
|
80080
|
+
init_config();
|
|
80081
|
+
init_slot_model_enforcement();
|
|
80082
|
+
init_mesh_queue_assignment();
|
|
80083
|
+
init_mesh_queue_observability();
|
|
80084
|
+
init_mesh_task_parking();
|
|
80085
|
+
ACTIONABLE_SKIP_REASON_PREFIXES = [
|
|
80086
|
+
"target_node_id_unmatched",
|
|
80087
|
+
"no_node_satisfies_required_tags",
|
|
80088
|
+
"mesh_convergence_target_is_worktree",
|
|
80089
|
+
"remote_auto_launch_unsupported",
|
|
80090
|
+
"remote_auto_launch_no_coordinator_daemon_id",
|
|
80091
|
+
"missing_provider_priority",
|
|
80092
|
+
"provider_loader_unavailable",
|
|
80093
|
+
"provider_priority_unusable",
|
|
80094
|
+
"provider_unusable",
|
|
80095
|
+
"dirty_workspace",
|
|
80096
|
+
// TARGET-PIN-TTL EXPIRY: the task was pinned to a specific session (a delta —
|
|
80097
|
+
// a correction addressed to work already in flight) and that session never
|
|
80098
|
+
// claimed it within the TTL, so the pin was cleared. Unlike the transient
|
|
80099
|
+
// skips, this does NOT self-resolve into the intended outcome: the delta is
|
|
80100
|
+
// now claimable by ANY compatible session, i.e. it will not reach the session
|
|
80101
|
+
// it was written for. Previously this only bumped a metrics counter and wrote
|
|
80102
|
+
// a log, so the coordinator kept waiting for a delivery that could no longer
|
|
80103
|
+
// happen — measured live as 74min of silence while a worker continued on a
|
|
80104
|
+
// premise the delta was meant to correct. The coordinator must know its
|
|
80105
|
+
// addressed message lost its address.
|
|
80106
|
+
"target_session_pin_expired",
|
|
80107
|
+
// PIN-PARKING: the reason above's successor. The pin no longer CLEARS on expiry
|
|
80108
|
+
// (that silently re-homed a context-bound delta onto an arbitrary session); the
|
|
80109
|
+
// task PARKS instead — held, still addressed, claimable by nobody. That state is
|
|
80110
|
+
// by construction actionable and terminal-until-touched: nothing in the daemon
|
|
80111
|
+
// will ever move a parked task, so if the coordinator is not told, the work is
|
|
80112
|
+
// lost exactly as surely as if it had been dropped. Both reasons stay listed —
|
|
80113
|
+
// the old one so a version-skewed daemon's rows still page.
|
|
80114
|
+
PARKED_SKIP_REASON,
|
|
80115
|
+
// SLOT MODEL GUARD (absent): no slot on the node declares the task's model.
|
|
80116
|
+
// Permanent — no amount of waiting produces a slot, so the coordinator must
|
|
80117
|
+
// re-drive (adjust difficulty, target another node, ask the owner). Its
|
|
80118
|
+
// busy counterpart SLOT_MODEL_BUSY_SKIP_REASON is deliberately NOT listed:
|
|
80119
|
+
// that one clears on its own when the slot goes idle.
|
|
80120
|
+
SLOT_MODEL_ABSENT_SKIP_REASON
|
|
80121
|
+
// QUOTA GATE: 'provider_quota_session_low' / 'provider_quota_weekly_low' /
|
|
80122
|
+
// 'provider_quota_exhausted' / 'all_providers_quota_gated' are deliberately
|
|
80123
|
+
// NOT listed either — an exhausted quota window RESETS, so the block
|
|
80124
|
+
// self-resolves exactly like the slot-busy case; the task waits in the
|
|
80125
|
+
// queue and the coordinator is not paged (mesh-quota-routing.ts). The
|
|
80126
|
+
// all-gated reason exists precisely so this WAIT is never conflated with
|
|
80127
|
+
// the actionable 'provider_priority_unusable' above.
|
|
80128
|
+
];
|
|
80129
|
+
TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
|
|
80130
|
+
lastActionableSkipNotified = /* @__PURE__ */ new Map();
|
|
80131
|
+
DEAD_TARGET_GRACE_MS = 6e4;
|
|
80132
|
+
TARGET_SESSION_PIN_TTL_MS = 15 * 6e4;
|
|
80133
|
+
targetPinGeneratingCreditMs = /* @__PURE__ */ new Map();
|
|
80015
80134
|
}
|
|
80016
80135
|
});
|
|
80017
80136
|
function liveSessionsForNode(components, meshId, nodeId) {
|
|
@@ -81141,7 +81260,7 @@ ${block2.text}`,
|
|
|
81141
81260
|
return void 0;
|
|
81142
81261
|
}
|
|
81143
81262
|
}
|
|
81144
|
-
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType, routingDecision, quotaClaimTrace) {
|
|
81263
|
+
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType, routingDecision, quotaClaimTrace, trigger = "queue_claim") {
|
|
81145
81264
|
const mesh = getMeshWithCache(components, meshId);
|
|
81146
81265
|
const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
|
|
81147
81266
|
if (routingDecision?.source !== "autoLaunch") {
|
|
@@ -81152,16 +81271,9 @@ ${block2.text}`,
|
|
|
81152
81271
|
noteClaimDeferredForNode(meshId, nodeId);
|
|
81153
81272
|
return false;
|
|
81154
81273
|
}
|
|
81155
|
-
|
|
81156
|
-
if (quotaClaimTrace) quotaClaimTrace.evaluated += 1;
|
|
81157
|
-
if (quotaClaimBlock) {
|
|
81158
|
-
const observation = { nodeId, sessionId, providerType, block: quotaClaimBlock };
|
|
81159
|
-
logQuotaClaimBlockTransition(meshId, observation);
|
|
81160
|
-
quotaClaimTrace?.blocked.push(observation);
|
|
81274
|
+
if (evaluateQuotaClaimGateForAssignment({ meshId, nodeId, sessionId, providerType, trigger, node, mesh, providerLoader: components.providerLoader, quotaClaimTrace })) {
|
|
81161
81275
|
return false;
|
|
81162
81276
|
}
|
|
81163
|
-
clearQuotaClaimBlockState(meshId, nodeId, sessionId, providerType);
|
|
81164
|
-
if (quotaClaimTrace) quotaClaimTrace.clear += 1;
|
|
81165
81277
|
const inlineBootstrapNode = (() => {
|
|
81166
81278
|
try {
|
|
81167
81279
|
const inlineMesh = components.router?.getCachedInlineMesh?.(meshId);
|
|
@@ -81694,7 +81806,7 @@ ${block2.text}`,
|
|
|
81694
81806
|
if (shouldRedriveDeferredClaim(meshId, alNodeId, alSessionId, () => isWorkspaceAutoFastForwardInFlight(readNonEmptyString(
|
|
81695
81807
|
(Array.isArray(mesh?.nodes) ? mesh.nodes.find((n) => meshNodeIdMatches(n, alNodeId)) : void 0)?.workspace
|
|
81696
81808
|
)))) {
|
|
81697
|
-
if (tryAssignQueueTask(components, meshId, alNodeId, alSessionId, alProvider)) {
|
|
81809
|
+
if (tryAssignQueueTask(components, meshId, alNodeId, alSessionId, alProvider, void 0, void 0, "auto_launch")) {
|
|
81698
81810
|
clearClaimDeferralForNode(meshId, alNodeId);
|
|
81699
81811
|
recordAutoLaunchEvent(meshId, { phase: "completed", taskId: task.id, reason: "fast_forward_deferred_claim_redriven", nodeId: alNodeId, sessionId: alSessionId });
|
|
81700
81812
|
LOG2.info("MeshQueue", `Auto-launch re-drove the auto-fast-forward-deferred claim for task ${task.id} into session ${alSessionId} on node ${alNodeId} (mesh ${meshId})`);
|
|
@@ -82014,7 +82126,7 @@ ${block2.text}`,
|
|
|
82014
82126
|
executedSlot: slotDecision.slot,
|
|
82015
82127
|
demotionReason
|
|
82016
82128
|
});
|
|
82017
|
-
tryAssignQueueTask(components, meshId, nodeId, sessionId, effectiveProviderType, routingDecision);
|
|
82129
|
+
tryAssignQueueTask(components, meshId, nodeId, sessionId, effectiveProviderType, routingDecision, void 0, "auto_launch");
|
|
82018
82130
|
return true;
|
|
82019
82131
|
} catch (e) {
|
|
82020
82132
|
markAutoLaunch(meshId, task.id, { status: "failed", error: e?.message || String(e), nodeId });
|
|
@@ -82072,7 +82184,7 @@ ${block2.text}`,
|
|
|
82072
82184
|
if (instMeshId !== meshId) continue;
|
|
82073
82185
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
82074
82186
|
if (!nodeId) continue;
|
|
82075
|
-
if (!
|
|
82187
|
+
if (!isIdleSessionState2(state)) {
|
|
82076
82188
|
const status = readNonEmptyString(state.status).toLowerCase();
|
|
82077
82189
|
skippedSessions.push({
|
|
82078
82190
|
nodeId,
|
|
@@ -82110,7 +82222,7 @@ ${block2.text}`,
|
|
|
82110
82222
|
}
|
|
82111
82223
|
const quotaClaimTrace = { blocked: [], evaluated: 0, clear: 0 };
|
|
82112
82224
|
const assignIdleCandidate = (candidate) => {
|
|
82113
|
-
const assigned = tryAssignQueueTask(components, meshId, candidate.nodeId, candidate.sessionId, candidate.providerType, void 0, quotaClaimTrace);
|
|
82225
|
+
const assigned = tryAssignQueueTask(components, meshId, candidate.nodeId, candidate.sessionId, candidate.providerType, void 0, quotaClaimTrace, "idle_claim_scan");
|
|
82114
82226
|
if (assigned && candidate.origin === "remote") {
|
|
82115
82227
|
try {
|
|
82116
82228
|
MeshRuntimeStore.getInstance().deleteRemoteIdleSession(meshId, candidate.nodeId, candidate.sessionId);
|
|
@@ -82190,7 +82302,7 @@ ${block2.text}`,
|
|
|
82190
82302
|
setImmediate(() => {
|
|
82191
82303
|
maybeAutoFastForwardIdleNode(components, args).finally(() => {
|
|
82192
82304
|
try {
|
|
82193
|
-
tryAssignQueueTask(components, args.meshId, args.nodeId, args.sessionId, args.providerType);
|
|
82305
|
+
tryAssignQueueTask(components, args.meshId, args.nodeId, args.sessionId, args.providerType, void 0, void 0, "idle_maintenance");
|
|
82194
82306
|
} catch (e) {
|
|
82195
82307
|
LOG2.warn("MeshQueue", `Failed to assign idle queue task after maintenance for ${args.nodeId}: ${e?.message || e}`);
|
|
82196
82308
|
}
|
|
@@ -82231,6 +82343,7 @@ ${block2.text}`,
|
|
|
82231
82343
|
init_mesh_node_slots();
|
|
82232
82344
|
init_mesh_daemon_slot_axis();
|
|
82233
82345
|
init_mesh_quota_routing();
|
|
82346
|
+
init_mesh_queue_claim_gate();
|
|
82234
82347
|
init_mesh_events_stale();
|
|
82235
82348
|
init_mesh_events_utils();
|
|
82236
82349
|
init_mesh_node_identity();
|
|
@@ -88213,6 +88326,97 @@ ${cleanBody}`;
|
|
|
88213
88326
|
init_chat_message_normalization();
|
|
88214
88327
|
}
|
|
88215
88328
|
});
|
|
88329
|
+
function flattenMessage(message) {
|
|
88330
|
+
const meta3 = message.meta && typeof message.meta === "object" ? message.meta : void 0;
|
|
88331
|
+
return {
|
|
88332
|
+
role: message.role,
|
|
88333
|
+
kind: message.kind,
|
|
88334
|
+
content: flattenContent(message.content),
|
|
88335
|
+
receivedAt: message.receivedAt,
|
|
88336
|
+
timestamp: message.timestamp,
|
|
88337
|
+
turnKey: message._turnKey,
|
|
88338
|
+
bubbleState: message.bubbleState,
|
|
88339
|
+
senderName: message.senderName,
|
|
88340
|
+
toolName: void 0,
|
|
88341
|
+
meta: meta3
|
|
88342
|
+
};
|
|
88343
|
+
}
|
|
88344
|
+
function buildTranscriptObservationFromReadChat(input) {
|
|
88345
|
+
if (!input.sessionId || !input.providerType) return null;
|
|
88346
|
+
return {
|
|
88347
|
+
sessionId: input.sessionId,
|
|
88348
|
+
historySessionId: input.historySessionId ?? null,
|
|
88349
|
+
providerType: input.providerType,
|
|
88350
|
+
providerSessionId: input.providerSessionId ?? null,
|
|
88351
|
+
status: input.status,
|
|
88352
|
+
providerObservedStatus: input.providerObservedStatus,
|
|
88353
|
+
title: input.title ?? null,
|
|
88354
|
+
activeModal: input.activeModal ?? null,
|
|
88355
|
+
activeInteractivePrompt: input.activeInteractivePrompt ?? null,
|
|
88356
|
+
turn: input.turn,
|
|
88357
|
+
provenance: input.provenance,
|
|
88358
|
+
messages: input.messages.map(flattenMessage),
|
|
88359
|
+
terminalMarkers: [],
|
|
88360
|
+
coverage: input.coverage
|
|
88361
|
+
};
|
|
88362
|
+
}
|
|
88363
|
+
var init_transcript_observation_builder = __esm2({
|
|
88364
|
+
"src/commands/transcript-observation-builder.ts"() {
|
|
88365
|
+
"use strict";
|
|
88366
|
+
init_contracts2();
|
|
88367
|
+
}
|
|
88368
|
+
});
|
|
88369
|
+
var TRANSCRIPT_REVISION_CHUNK_BYTES;
|
|
88370
|
+
var MAX_TRANSCRIPT_REVISION_ROWS;
|
|
88371
|
+
var MAX_TRANSCRIPT_REVISION_CHUNKS;
|
|
88372
|
+
var init_transcript_revision_codec = __esm2({
|
|
88373
|
+
"src/seqscribe/transcript-revision-codec.ts"() {
|
|
88374
|
+
"use strict";
|
|
88375
|
+
init_dist();
|
|
88376
|
+
init_dist2();
|
|
88377
|
+
TRANSCRIPT_REVISION_CHUNK_BYTES = 36 * 1024;
|
|
88378
|
+
MAX_TRANSCRIPT_REVISION_ROWS = 240;
|
|
88379
|
+
MAX_TRANSCRIPT_REVISION_CHUNKS = MAX_TRANSCRIPT_REVISION_ROWS - 2;
|
|
88380
|
+
}
|
|
88381
|
+
});
|
|
88382
|
+
var init_transcript_projection = __esm2({
|
|
88383
|
+
"src/seqscribe/transcript-projection.ts"() {
|
|
88384
|
+
"use strict";
|
|
88385
|
+
init_dist2();
|
|
88386
|
+
}
|
|
88387
|
+
});
|
|
88388
|
+
var init_transcript_observation = __esm2({
|
|
88389
|
+
"src/seqscribe/transcript-observation.ts"() {
|
|
88390
|
+
"use strict";
|
|
88391
|
+
init_dist2();
|
|
88392
|
+
}
|
|
88393
|
+
});
|
|
88394
|
+
var init_transcript_mode = __esm2({
|
|
88395
|
+
"src/seqscribe/transcript-mode.ts"() {
|
|
88396
|
+
"use strict";
|
|
88397
|
+
init_logger();
|
|
88398
|
+
}
|
|
88399
|
+
});
|
|
88400
|
+
function notifyTranscriptObservation(sessionId, observation) {
|
|
88401
|
+
activeService?.observe(sessionId, observation);
|
|
88402
|
+
}
|
|
88403
|
+
function markTranscriptSessionDirty(sessionId) {
|
|
88404
|
+
activeService?.markDirty(sessionId);
|
|
88405
|
+
}
|
|
88406
|
+
var import_node_crypto4;
|
|
88407
|
+
var activeService;
|
|
88408
|
+
var init_transcript_publisher = __esm2({
|
|
88409
|
+
"src/seqscribe/transcript-publisher.ts"() {
|
|
88410
|
+
"use strict";
|
|
88411
|
+
import_node_crypto4 = require("crypto");
|
|
88412
|
+
init_logger();
|
|
88413
|
+
init_transcript_revision_codec();
|
|
88414
|
+
init_transcript_projection();
|
|
88415
|
+
init_transcript_observation();
|
|
88416
|
+
init_transcript_mode();
|
|
88417
|
+
activeService = null;
|
|
88418
|
+
}
|
|
88419
|
+
});
|
|
88216
88420
|
function shouldPreserveReadChatPayloadField(key2) {
|
|
88217
88421
|
return key2 === "messageSource" || key2 === "transcriptProvenance";
|
|
88218
88422
|
}
|
|
@@ -88347,6 +88551,30 @@ ${cleanBody}`;
|
|
|
88347
88551
|
if (preservedPayloadFields.transcriptProvenance) {
|
|
88348
88552
|
preservedPayloadFields.transcriptProvenance = updateMessageSourceReturnedCount(preservedPayloadFields.transcriptProvenance, sync.messages.length);
|
|
88349
88553
|
}
|
|
88554
|
+
try {
|
|
88555
|
+
const observation = buildTranscriptObservationFromReadChat({
|
|
88556
|
+
sessionId: sessionIdHint || presentationSessionIdHint,
|
|
88557
|
+
historySessionId: typeof validatedPayload.historySessionId === "string" ? validatedPayload.historySessionId : null,
|
|
88558
|
+
providerType: providerHint || turnPresentation.providerType || "",
|
|
88559
|
+
providerSessionId: typeof validatedPayload.providerSessionId === "string" ? validatedPayload.providerSessionId : null,
|
|
88560
|
+
status: effectiveStatus,
|
|
88561
|
+
providerObservedStatus: legacyStatus,
|
|
88562
|
+
title: typeof validatedPayload.title === "string" ? validatedPayload.title : null,
|
|
88563
|
+
activeModal: validatedPayload.activeModal ?? null,
|
|
88564
|
+
activeInteractivePrompt: validatedPayload.activeInteractivePrompt ?? null,
|
|
88565
|
+
turn: turnPresentation.authority === "turn_reducer" ? turnPresentation : null,
|
|
88566
|
+
provenance: preservedPayloadFields,
|
|
88567
|
+
messages: visibleMessages,
|
|
88568
|
+
coverage: {
|
|
88569
|
+
mode: "full",
|
|
88570
|
+
totalMessageCount: messages.length,
|
|
88571
|
+
returnedMessageCount: visibleMessages.length,
|
|
88572
|
+
omittedBefore: false
|
|
88573
|
+
}
|
|
88574
|
+
});
|
|
88575
|
+
if (observation) notifyTranscriptObservation(observation.sessionId, observation);
|
|
88576
|
+
} catch {
|
|
88577
|
+
}
|
|
88350
88578
|
const returnedDebugReadChat = debugReadChat ? {
|
|
88351
88579
|
...debugReadChat,
|
|
88352
88580
|
fullMsgCount: typeof debugReadChat.fullMsgCount === "number" ? debugReadChat.fullMsgCount : messages.length,
|
|
@@ -88395,6 +88623,8 @@ ${cleanBody}`;
|
|
|
88395
88623
|
init_mesh_turn_presentation();
|
|
88396
88624
|
init_chat_message_normalization();
|
|
88397
88625
|
init_read_chat_message_filters();
|
|
88626
|
+
init_transcript_observation_builder();
|
|
88627
|
+
init_transcript_publisher();
|
|
88398
88628
|
}
|
|
88399
88629
|
});
|
|
88400
88630
|
function getMeshV2BackstopCounters() {
|
|
@@ -90685,8 +90915,9 @@ ${cleanBody}`;
|
|
|
90685
90915
|
for (const mesh of listMeshes()) {
|
|
90686
90916
|
const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
|
|
90687
90917
|
if (!daemonHostsMesh(mesh, selfIds)) continue;
|
|
90918
|
+
const nodeAwareMesh = getMeshWithCache(components, mesh.id) ?? mesh;
|
|
90688
90919
|
try {
|
|
90689
|
-
await pullRemoteNodeQueues(components,
|
|
90920
|
+
await pullRemoteNodeQueues(components, nodeAwareMesh, localDaemonId, selfIds);
|
|
90690
90921
|
} catch (e) {
|
|
90691
90922
|
LOG2.warn("MeshReconcile", `Remote node pull failed for mesh ${mesh.id}: ${e?.message || e}`);
|
|
90692
90923
|
}
|
|
@@ -96156,6 +96387,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
96156
96387
|
const result = await execFileAsync8(spawn7.file, spawn7.args, {
|
|
96157
96388
|
cwd,
|
|
96158
96389
|
encoding: "utf8",
|
|
96390
|
+
windowsHide: true,
|
|
96159
96391
|
timeout,
|
|
96160
96392
|
maxBuffer: candidate.outputLimitBytes || REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
|
|
96161
96393
|
env: { ...process.env, CI: process.env.CI || "1", ...refineGateChildEnv(), ...candidate.env || {} },
|
|
@@ -96201,6 +96433,7 @@ ${mergeTreeErr?.stderr || ""}`;
|
|
|
96201
96433
|
const result = await execFileAsync8(spawn7.file, spawn7.args, {
|
|
96202
96434
|
cwd,
|
|
96203
96435
|
encoding: "utf8",
|
|
96436
|
+
windowsHide: true,
|
|
96204
96437
|
timeout,
|
|
96205
96438
|
maxBuffer: candidate.outputLimitBytes || REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
|
|
96206
96439
|
env: { ...process.env, CI: process.env.CI || "1", ...refineGateChildEnv(), ...candidate.env || {} },
|
|
@@ -99723,6 +99956,7 @@ ${e?.stderr || ""}`;
|
|
|
99723
99956
|
appendLedgerEntry: () => appendLedgerEntry,
|
|
99724
99957
|
appendRecentActivity: () => appendRecentActivity,
|
|
99725
99958
|
appendRemoteLedgerEntries: () => appendRemoteLedgerEntries,
|
|
99959
|
+
applyDaemonEnvOverrides: () => applyDaemonEnvOverrides,
|
|
99726
99960
|
armBeacon: () => armBeacon,
|
|
99727
99961
|
assertNoDependencyCycle: () => assertNoDependencyCycle,
|
|
99728
99962
|
assertNoPlaintextHintTopics: () => assertNoPlaintextHintTopics,
|
|
@@ -99985,6 +100219,7 @@ ${e?.stderr || ""}`;
|
|
|
99985
100219
|
isPreviewReleaseChannel: () => isPreviewReleaseChannel,
|
|
99986
100220
|
isProjectedPayloadKey: () => isProjectedPayloadKey,
|
|
99987
100221
|
isRestartBlockingPresentation: () => isRestartBlockingPresentation,
|
|
100222
|
+
isSecretLikeEnvKey: () => isSecretLikeEnvKey,
|
|
99988
100223
|
isSessionHostLiveRuntime: () => import_session_host_core32.isSessionHostLiveRuntime,
|
|
99989
100224
|
isSessionHostRecoverySnapshot: () => import_session_host_core32.isSessionHostRecoverySnapshot,
|
|
99990
100225
|
isSetupComplete: () => isSetupComplete,
|
|
@@ -101617,6 +101852,7 @@ ${e?.stderr || ""}`;
|
|
|
101617
101852
|
};
|
|
101618
101853
|
init_git_worktree();
|
|
101619
101854
|
init_config();
|
|
101855
|
+
init_env_overrides();
|
|
101620
101856
|
init_config_dir();
|
|
101621
101857
|
init_embedded_path_health();
|
|
101622
101858
|
var os11 = __toESM2(require("os"));
|
|
@@ -106962,7 +107198,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
106962
107198
|
}
|
|
106963
107199
|
var fs21 = __toESM2(require("fs"));
|
|
106964
107200
|
var path30 = __toESM2(require("path"));
|
|
106965
|
-
var
|
|
107201
|
+
var import_node_crypto5 = require("crypto");
|
|
106966
107202
|
init_config();
|
|
106967
107203
|
init_logger();
|
|
106968
107204
|
init_debug_trace();
|
|
@@ -109105,7 +109341,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
109105
109341
|
function createChatDebugBundleId(targetSessionId) {
|
|
109106
109342
|
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "").replace("T", "T").replace("Z", "Z");
|
|
109107
109343
|
const sessionSegment = safeBundleIdSegment(targetSessionId, "unknown-session");
|
|
109108
|
-
return `chat-debug-${timestamp2}-${sessionSegment}-${(0,
|
|
109344
|
+
return `chat-debug-${timestamp2}-${sessionSegment}-${(0, import_node_crypto5.randomUUID)().slice(0, 8)}`;
|
|
109109
109345
|
}
|
|
109110
109346
|
function buildChatDebugBundleSummary(bundle) {
|
|
109111
109347
|
const target = bundle.target && typeof bundle.target === "object" ? bundle.target : {};
|
|
@@ -121552,8 +121788,102 @@ ${marker}`,
|
|
|
121552
121788
|
}
|
|
121553
121789
|
return out;
|
|
121554
121790
|
}
|
|
121791
|
+
var USER_RE = /^>\s+(\S.*)$/;
|
|
121792
|
+
var EMPTY_COMPOSER_RE = /^>\s*$/;
|
|
121793
|
+
var TOOL_RE = /^●\s+\S+/;
|
|
121794
|
+
var THOUGHT_RE = /^▸\s/;
|
|
121795
|
+
var RULE_RE = /^[─━═\-]{3,}\s*$/;
|
|
121796
|
+
var JSON_START_RE = /^\s*[{\[]/;
|
|
121797
|
+
var CHROME_RES = [
|
|
121798
|
+
RULE_RE,
|
|
121799
|
+
EMPTY_COMPOSER_RE,
|
|
121800
|
+
/^\s*\? for shortcuts/,
|
|
121801
|
+
/esc to cancel/i,
|
|
121802
|
+
/^Resume:\s+agy\b/i,
|
|
121803
|
+
/^Antigravity CLI\b/,
|
|
121804
|
+
/\(Google AI (?:Ultra|Pro|Free)\)/,
|
|
121805
|
+
/^\s*↑\/↓\s+Navigate/,
|
|
121806
|
+
/^Requesting permission for:/,
|
|
121807
|
+
/^Do you want to proceed\?/,
|
|
121808
|
+
/^Accept this file edit\?/,
|
|
121809
|
+
/^Allow (?:access to|creation of) this file\?/,
|
|
121810
|
+
/^Allow sandbox bypass/,
|
|
121811
|
+
/^Command\s*$/
|
|
121812
|
+
];
|
|
121813
|
+
function isChrome(line) {
|
|
121814
|
+
for (const re of CHROME_RES) {
|
|
121815
|
+
if (re.test(line)) return true;
|
|
121816
|
+
}
|
|
121817
|
+
return false;
|
|
121818
|
+
}
|
|
121819
|
+
function isIndented(line) {
|
|
121820
|
+
return /^\s+\S/.test(line);
|
|
121821
|
+
}
|
|
121822
|
+
function assistantMessage(content) {
|
|
121823
|
+
return {
|
|
121824
|
+
role: "assistant",
|
|
121825
|
+
kind: "standard",
|
|
121826
|
+
content,
|
|
121827
|
+
source: "assistant_text",
|
|
121828
|
+
userFacing: true,
|
|
121829
|
+
bubbleState: "final"
|
|
121830
|
+
};
|
|
121831
|
+
}
|
|
121832
|
+
function extractAntigravityScreenAssistantMessages(screenText) {
|
|
121833
|
+
const lines = String(screenText || "").split(/\r?\n/).map((l) => l.replace(/\s+$/, ""));
|
|
121834
|
+
const messages = [];
|
|
121835
|
+
let afterTool = false;
|
|
121836
|
+
let inUser = false;
|
|
121837
|
+
let inThought = false;
|
|
121838
|
+
let seenRole = false;
|
|
121839
|
+
const pushOrAppendAssistant = (text) => {
|
|
121840
|
+
const last = messages[messages.length - 1];
|
|
121841
|
+
if (last && last.role === "assistant" && typeof last.content === "string") {
|
|
121842
|
+
last.content = last.content ? `${last.content}
|
|
121843
|
+
${text}` : text;
|
|
121844
|
+
} else {
|
|
121845
|
+
messages.push(assistantMessage(text));
|
|
121846
|
+
}
|
|
121847
|
+
};
|
|
121848
|
+
for (const line of lines) {
|
|
121849
|
+
if (line.trim() === "") continue;
|
|
121850
|
+
if (isChrome(line)) continue;
|
|
121851
|
+
if (USER_RE.test(line)) {
|
|
121852
|
+
inUser = true;
|
|
121853
|
+
inThought = false;
|
|
121854
|
+
afterTool = false;
|
|
121855
|
+
seenRole = true;
|
|
121856
|
+
continue;
|
|
121857
|
+
}
|
|
121858
|
+
if (TOOL_RE.test(line)) {
|
|
121859
|
+
inUser = false;
|
|
121860
|
+
inThought = false;
|
|
121861
|
+
afterTool = true;
|
|
121862
|
+
seenRole = true;
|
|
121863
|
+
continue;
|
|
121864
|
+
}
|
|
121865
|
+
if (THOUGHT_RE.test(line)) {
|
|
121866
|
+
inUser = false;
|
|
121867
|
+
inThought = true;
|
|
121868
|
+
seenRole = true;
|
|
121869
|
+
continue;
|
|
121870
|
+
}
|
|
121871
|
+
if (!seenRole) continue;
|
|
121872
|
+
if (inUser && isIndented(line)) continue;
|
|
121873
|
+
if (inThought && isIndented(line) && !JSON_START_RE.test(line) && !afterTool) continue;
|
|
121874
|
+
if (afterTool || inThought && JSON_START_RE.test(line)) {
|
|
121875
|
+
const text = line.replace(/^\s+/, "");
|
|
121876
|
+
if (text) {
|
|
121877
|
+
pushOrAppendAssistant(text);
|
|
121878
|
+
inThought = false;
|
|
121879
|
+
inUser = false;
|
|
121880
|
+
}
|
|
121881
|
+
}
|
|
121882
|
+
}
|
|
121883
|
+
return messages.filter((m) => typeof m.content === "string" && m.content.trim().length > 0);
|
|
121884
|
+
}
|
|
121555
121885
|
var fs40 = __toESM2(require("fs"));
|
|
121556
|
-
var
|
|
121886
|
+
var import_node_crypto6 = require("crypto");
|
|
121557
121887
|
init_provider_cli_shared();
|
|
121558
121888
|
init_logger();
|
|
121559
121889
|
init_logger();
|
|
@@ -122007,7 +122337,7 @@ ${marker}`,
|
|
|
122007
122337
|
const bg = this.detectBackgroundTask();
|
|
122008
122338
|
return {
|
|
122009
122339
|
...status,
|
|
122010
|
-
messages: this.
|
|
122340
|
+
messages: this.readScreenAssistantMessages(),
|
|
122011
122341
|
...this.providerSessionId ? { providerSessionId: this.providerSessionId } : {},
|
|
122012
122342
|
backgroundTaskSupport: bg.support ?? "unknown",
|
|
122013
122343
|
...bg.active ? { backgroundTaskActive: true, backgroundTaskCount: bg.count, backgroundTaskIds: bg.ids } : {}
|
|
@@ -122121,7 +122451,7 @@ ${marker}`,
|
|
|
122121
122451
|
} catch {
|
|
122122
122452
|
}
|
|
122123
122453
|
const truncation = truncateToByteTailByLine(rawViewport, cap);
|
|
122124
|
-
const hash2 = (0,
|
|
122454
|
+
const hash2 = (0, import_node_crypto6.createHash)("sha256").update(rawViewport, "utf8").digest("hex").slice(0, 16);
|
|
122125
122455
|
return {
|
|
122126
122456
|
text: truncation.text,
|
|
122127
122457
|
cursor: { col: cursor.col, row: cursor.row },
|
|
@@ -122548,7 +122878,7 @@ ${marker}`,
|
|
|
122548
122878
|
} catch {
|
|
122549
122879
|
}
|
|
122550
122880
|
} else {
|
|
122551
|
-
messages = this.
|
|
122881
|
+
messages = this.readScreenAssistantMessages();
|
|
122552
122882
|
}
|
|
122553
122883
|
return {
|
|
122554
122884
|
cliType: this.cliType,
|
|
@@ -122761,6 +123091,29 @@ ${marker}`,
|
|
|
122761
123091
|
const match = clean2.match(/(?:gpt-|o\d|codex-)[^\n·]*·[^\n·]*·\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i);
|
|
122762
123092
|
return match?.[1] || this.providerSessionId;
|
|
122763
123093
|
}
|
|
123094
|
+
/**
|
|
123095
|
+
* PTY-scrape assistant bubbles for the live parse / spec-debug snapshot.
|
|
123096
|
+
*
|
|
123097
|
+
* Native-history remains the completion-path authority
|
|
123098
|
+
* (`chatMessagesOwnedExternally`). This scrape is the fail-closed
|
|
123099
|
+
* fallback the gate already consults via getScriptParsedStatus().messages
|
|
123100
|
+
* when the on-disk transcript has no final standard assistant — which is
|
|
123101
|
+
* the antigravity layout where the JSON report is on screen under
|
|
123102
|
+
* `● Bash(...)` but never lands as a step_type-15 field-20 answer.
|
|
123103
|
+
*/
|
|
123104
|
+
readScreenAssistantMessages() {
|
|
123105
|
+
if (this.cliType === "claude-cli") return this.readClaudeScreenAssistantMessages();
|
|
123106
|
+
if (this.cliType === "antigravity-cli") {
|
|
123107
|
+
let screenText = "";
|
|
123108
|
+
try {
|
|
123109
|
+
screenText = this.driver.snapshot();
|
|
123110
|
+
} catch {
|
|
123111
|
+
return [];
|
|
123112
|
+
}
|
|
123113
|
+
return extractAntigravityScreenAssistantMessages(screenText);
|
|
123114
|
+
}
|
|
123115
|
+
return [];
|
|
123116
|
+
}
|
|
122764
123117
|
readClaudeScreenAssistantMessages() {
|
|
122765
123118
|
if (this.cliType !== "claude-cli") return [];
|
|
122766
123119
|
let screenText = "";
|
|
@@ -123171,7 +123524,7 @@ ${marker}`,
|
|
|
123171
123524
|
} catch (e) {
|
|
123172
123525
|
}
|
|
123173
123526
|
} else {
|
|
123174
|
-
messages = this.
|
|
123527
|
+
messages = this.readScreenAssistantMessages();
|
|
123175
123528
|
}
|
|
123176
123529
|
const latestState = this.latestState;
|
|
123177
123530
|
const latestModal = this.latestModal;
|
|
@@ -131370,7 +131723,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
131370
131723
|
const { shouldDeferDispatchForBootstrap: shouldDeferDispatchForBootstrap2 } = await Promise.resolve().then(() => (init_worktree_bootstrap_config(), worktree_bootstrap_config_exports));
|
|
131371
131724
|
if (shouldDeferDispatchForBootstrap2(nodeObj)) {
|
|
131372
131725
|
const dispatchSessionState = dispatchSessionId ? ctx.deps.instanceManager?.getInstance?.(dispatchSessionId)?.getState?.() : void 0;
|
|
131373
|
-
const sessionConfirmedReady = !!dispatchSessionState &&
|
|
131726
|
+
const sessionConfirmedReady = !!dispatchSessionState && isIdleSessionState2(dispatchSessionState);
|
|
131374
131727
|
if (!sessionConfirmedReady) {
|
|
131375
131728
|
return {
|
|
131376
131729
|
success: false,
|
|
@@ -134821,7 +135174,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
134821
135174
|
}
|
|
134822
135175
|
async function execQuiet(command, options = {}) {
|
|
134823
135176
|
return new Promise((resolve32) => {
|
|
134824
|
-
(0, import_child_process12.exec)(command, options, (error48, stdout) => {
|
|
135177
|
+
(0, import_child_process12.exec)(command, { windowsHide: true, ...options }, (error48, stdout) => {
|
|
134825
135178
|
if (error48) return resolve32("");
|
|
134826
135179
|
resolve32(stdout.toString());
|
|
134827
135180
|
});
|
|
@@ -135396,6 +135749,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
135396
135749
|
init_worktree_bootstrap_config();
|
|
135397
135750
|
init_mesh_events();
|
|
135398
135751
|
init_mesh_clone_grace();
|
|
135752
|
+
init_mesh_events_utils();
|
|
135399
135753
|
init_config();
|
|
135400
135754
|
async function decideOssCloneSync(ossCtx, worktreeOssSha, sourceSha, rg) {
|
|
135401
135755
|
if (!worktreeOssSha || !sourceSha || worktreeOssSha === sourceSha) return "noop";
|
|
@@ -136311,6 +136665,13 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
136311
136665
|
if (cachedMesh) ctx.removeInlineMeshNode(meshId, cachedMesh, nodeId);
|
|
136312
136666
|
}
|
|
136313
136667
|
}
|
|
136668
|
+
if (removed) {
|
|
136669
|
+
try {
|
|
136670
|
+
const { MeshRuntimeStore: MeshRuntimeStore2 } = await Promise.resolve().then(() => (init_mesh_runtime_store(), mesh_runtime_store_exports));
|
|
136671
|
+
MeshRuntimeStore2.getInstance().deleteRemoteIdleSessionsForNode(meshId, nodeId);
|
|
136672
|
+
} catch {
|
|
136673
|
+
}
|
|
136674
|
+
}
|
|
136314
136675
|
if (worktreeCleanup && worktreeCleanup.success === true && worktreeCleanup.skipped !== true) {
|
|
136315
136676
|
try {
|
|
136316
136677
|
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
@@ -136411,6 +136772,14 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
136411
136772
|
if (forwardedNodeId) noteRecentlyClonedNode(forwardedNodeId);
|
|
136412
136773
|
return forwarded ?? { success: false, error: "no response from remote node" };
|
|
136413
136774
|
}
|
|
136775
|
+
const effectiveDaemonId = readMeshNodeDaemonId(sourceNode) || readNonEmptyString(ctx.deps.statusInstanceId) || void 0;
|
|
136776
|
+
const effectiveMachineId = readMeshNodeMachineId(sourceNode) || (() => {
|
|
136777
|
+
try {
|
|
136778
|
+
return readNonEmptyString(loadConfig2().machineId);
|
|
136779
|
+
} catch {
|
|
136780
|
+
return "";
|
|
136781
|
+
}
|
|
136782
|
+
})() || void 0;
|
|
136414
136783
|
const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
|
|
136415
136784
|
const worktreeBaseDir = typeof mesh.policy?.worktreeBaseDir === "string" && mesh.policy.worktreeBaseDir.trim() ? mesh.policy.worktreeBaseDir.trim() : void 0;
|
|
136416
136785
|
const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
@@ -136429,15 +136798,15 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
136429
136798
|
let node;
|
|
136430
136799
|
const { migrateProviderRolesToSlots: migrateProviderRolesToSlots2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
136431
136800
|
if (meshRecord.inline) {
|
|
136432
|
-
const { randomUUID:
|
|
136801
|
+
const { randomUUID: randomUUID23 } = await import("crypto");
|
|
136433
136802
|
const clonedPolicy = { ...sourceNode.policy || {} };
|
|
136434
136803
|
migrateProviderRolesToSlots2(clonedPolicy);
|
|
136435
136804
|
node = {
|
|
136436
|
-
id: `node_${
|
|
136805
|
+
id: `node_${randomUUID23().replace(/-/g, "")}`,
|
|
136437
136806
|
workspace: result.worktreePath,
|
|
136438
136807
|
repoRoot: result.worktreePath,
|
|
136439
|
-
daemonId:
|
|
136440
|
-
machineId:
|
|
136808
|
+
daemonId: effectiveDaemonId,
|
|
136809
|
+
machineId: effectiveMachineId,
|
|
136441
136810
|
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
136442
136811
|
policy: clonedPolicy,
|
|
136443
136812
|
isLocalWorktree: true,
|
|
@@ -136451,8 +136820,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
136451
136820
|
id: node.id,
|
|
136452
136821
|
workspace: result.worktreePath,
|
|
136453
136822
|
repoRoot: result.worktreePath,
|
|
136454
|
-
daemonId:
|
|
136455
|
-
machineId:
|
|
136823
|
+
daemonId: effectiveDaemonId,
|
|
136824
|
+
machineId: effectiveMachineId,
|
|
136456
136825
|
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
136457
136826
|
isLocalWorktree: true,
|
|
136458
136827
|
worktreeBranch: result.branch,
|
|
@@ -136468,8 +136837,8 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
136468
136837
|
node = addNode2(meshId, {
|
|
136469
136838
|
workspace: result.worktreePath,
|
|
136470
136839
|
repoRoot: result.worktreePath,
|
|
136471
|
-
daemonId:
|
|
136472
|
-
machineId:
|
|
136840
|
+
daemonId: effectiveDaemonId,
|
|
136841
|
+
machineId: effectiveMachineId,
|
|
136473
136842
|
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
136474
136843
|
isLocalWorktree: true,
|
|
136475
136844
|
worktreeBranch: result.branch,
|
|
@@ -141406,6 +141775,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
141406
141775
|
}
|
|
141407
141776
|
init_snapshot3();
|
|
141408
141777
|
init_runtime_defaults();
|
|
141778
|
+
init_transcript_publisher();
|
|
141409
141779
|
var DEFAULT_GIT_REFRESH_CONCURRENCY = 2;
|
|
141410
141780
|
var DEFAULT_CHAT_TAIL_FLUSH_DEBOUNCE_MS = 700;
|
|
141411
141781
|
var PUSH_TOPICS = ["machine.runtime", "session_host.diagnostics", "session.modal", "daemon.metadata"];
|
|
@@ -141759,6 +142129,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
141759
142129
|
markChatOutputActivity(sessionId) {
|
|
141760
142130
|
const cfg = this.opts.chatTail;
|
|
141761
142131
|
if (!sessionId || !(cfg?.isCliSession?.(sessionId) ?? false)) return;
|
|
142132
|
+
markTranscriptSessionDirty(sessionId);
|
|
141762
142133
|
this.chatOutputActiveAt.set(sessionId, this.now());
|
|
141763
142134
|
if (this.chatOutputFlushTimer) return;
|
|
141764
142135
|
if (cfg?.scheduleGate && !cfg.scheduleGate()) return;
|
|
@@ -142252,7 +142623,17 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
142252
142623
|
parityRan: seqscribe.parityRan === true,
|
|
142253
142624
|
parityMissingInShadowBucket: count(seqscribe.parityMissingInShadowBucket),
|
|
142254
142625
|
parityExtraInShadowBucket: count(seqscribe.parityExtraInShadowBucket),
|
|
142255
|
-
parityFieldMismatchBucket: count(seqscribe.parityFieldMismatchBucket)
|
|
142626
|
+
parityFieldMismatchBucket: count(seqscribe.parityFieldMismatchBucket),
|
|
142627
|
+
// §8 unit 2. transcriptParityPersistentMismatchBucket stays LOCAL-ONLY,
|
|
142628
|
+
// absent here — same asymmetry as parityPersistentMismatchBucket above.
|
|
142629
|
+
transcriptPublish: seqscribe.transcriptPublish === true,
|
|
142630
|
+
transcriptPublishedBucket: count(seqscribe.transcriptPublishedBucket),
|
|
142631
|
+
transcriptPublishFailedBucket: count(seqscribe.transcriptPublishFailedBucket),
|
|
142632
|
+
transcriptDedupedBucket: count(seqscribe.transcriptDedupedBucket),
|
|
142633
|
+
transcriptOversizedBucket: count(seqscribe.transcriptOversizedBucket),
|
|
142634
|
+
transcriptDroppedBucket: count(seqscribe.transcriptDroppedBucket),
|
|
142635
|
+
transcriptParityRan: seqscribe.transcriptParityRan === true,
|
|
142636
|
+
transcriptParityMismatchBucket: count(seqscribe.transcriptParityMismatchBucket)
|
|
142256
142637
|
};
|
|
142257
142638
|
}
|
|
142258
142639
|
function buildCloudStatusReportPayload(sessions, p2p, timestamp2, seqscribe) {
|
|
@@ -146835,6 +147216,7 @@ async (params) => {
|
|
|
146835
147216
|
cwd: providerDir,
|
|
146836
147217
|
stdio: ["pipe", "pipe", "pipe"],
|
|
146837
147218
|
shell: spawn7.shell ?? false,
|
|
147219
|
+
windowsHide: true,
|
|
146838
147220
|
env: { ...process.env, ...spawn7.env || {} }
|
|
146839
147221
|
});
|
|
146840
147222
|
ctx.autoImplProcess = child2;
|
|
@@ -147011,6 +147393,7 @@ async (params) => {
|
|
|
147011
147393
|
child = spawnFn(isWin ? "cmd.exe" : "sh", [isWin ? "/c" : "-c", shellCmd], {
|
|
147012
147394
|
cwd: providerDir,
|
|
147013
147395
|
shell: false,
|
|
147396
|
+
windowsHide: true,
|
|
147014
147397
|
timeout: 9e5,
|
|
147015
147398
|
stdio: ["pipe", "pipe", "pipe"],
|
|
147016
147399
|
env: {
|
|
@@ -148163,6 +148546,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
148163
148546
|
try {
|
|
148164
148547
|
const child = spawnFn(spawn7.command, [...spawn7.args || []], {
|
|
148165
148548
|
shell: spawn7.shell ?? false,
|
|
148549
|
+
windowsHide: true,
|
|
148166
148550
|
timeout: 5e3,
|
|
148167
148551
|
stdio: ["pipe", "pipe", "pipe"]
|
|
148168
148552
|
});
|
|
@@ -148678,6 +149062,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
148678
149062
|
const args = [...spawn7.args || [], message];
|
|
148679
149063
|
const child = spawnFn(spawn7.command, args, {
|
|
148680
149064
|
shell: spawn7.shell ?? false,
|
|
149065
|
+
windowsHide: true,
|
|
148681
149066
|
timeout,
|
|
148682
149067
|
stdio: ["pipe", "pipe", "pipe"],
|
|
148683
149068
|
env: { ...process.env, ...spawn7.env || {} }
|
|
@@ -150057,6 +150442,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
150057
150442
|
try {
|
|
150058
150443
|
const { stdout } = await execAsync4(`"${ide.cliCommand}" --list-extensions`, {
|
|
150059
150444
|
encoding: "utf-8",
|
|
150445
|
+
windowsHide: true,
|
|
150060
150446
|
timeout: 15e3
|
|
150061
150447
|
});
|
|
150062
150448
|
const installed = stdout.trim().split("\n").map((e) => e.trim().toLowerCase());
|
|
@@ -150234,6 +150620,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
150234
150620
|
init_logger();
|
|
150235
150621
|
init_runtime_defaults();
|
|
150236
150622
|
init_config();
|
|
150623
|
+
init_env_overrides();
|
|
150237
150624
|
init_config_dir();
|
|
150238
150625
|
init_contract();
|
|
150239
150626
|
init_mesh_events();
|
|
@@ -151107,6 +151494,18 @@ data: ${JSON.stringify(msg.data)}
|
|
|
151107
151494
|
parityMissingInShadowBucket: bucket(opts.parity?.missingInShadow ?? 0, BACKLOG_BUCKETS),
|
|
151108
151495
|
parityExtraInShadowBucket: bucket(opts.parity?.extraInShadow ?? 0, BACKLOG_BUCKETS),
|
|
151109
151496
|
parityFieldMismatchBucket: bucket(opts.parity?.fieldMismatch ?? 0, BACKLOG_BUCKETS),
|
|
151497
|
+
transcriptPublish: opts.transcript?.active ?? false,
|
|
151498
|
+
transcriptPublishedBucket: bucket(opts.transcript?.published ?? 0, BACKLOG_BUCKETS),
|
|
151499
|
+
transcriptPublishFailedBucket: bucket(opts.transcript?.publishFailed ?? 0, BACKLOG_BUCKETS),
|
|
151500
|
+
transcriptDedupedBucket: bucket(opts.transcript?.deduped ?? 0, BACKLOG_BUCKETS),
|
|
151501
|
+
transcriptOversizedBucket: bucket(opts.transcript?.oversized ?? 0, BACKLOG_BUCKETS),
|
|
151502
|
+
transcriptDroppedBucket: bucket(opts.transcript?.dropped ?? 0, BACKLOG_BUCKETS),
|
|
151503
|
+
transcriptParityRan: (opts.transcriptParity?.runs ?? 0) > 0,
|
|
151504
|
+
transcriptParityMismatchBucket: bucket(opts.transcriptParity?.mismatches ?? 0, BACKLOG_BUCKETS),
|
|
151505
|
+
transcriptParityPersistentMismatchBucket: bucket(
|
|
151506
|
+
opts.transcriptParity?.persistentMismatches ?? 0,
|
|
151507
|
+
BACKLOG_BUCKETS
|
|
151508
|
+
),
|
|
151110
151509
|
...localDiagnostics
|
|
151111
151510
|
};
|
|
151112
151511
|
}
|
|
@@ -151532,6 +151931,15 @@ data: ${JSON.stringify(msg.data)}
|
|
|
151532
151931
|
installProviderProcessShim();
|
|
151533
151932
|
installGlobalInterceptor();
|
|
151534
151933
|
loadMeshCoordinatorRegistry();
|
|
151934
|
+
const envOverrideResult = applyDaemonEnvOverrides(
|
|
151935
|
+
loadConfig2().envOverrides,
|
|
151936
|
+
process.env,
|
|
151937
|
+
(msg) => LOG2.warn("EnvOverrides", msg)
|
|
151938
|
+
);
|
|
151939
|
+
const appliedOverrideKeys = Object.keys(envOverrideResult.applied);
|
|
151940
|
+
if (appliedOverrideKeys.length > 0) {
|
|
151941
|
+
LOG2.info("EnvOverrides", `Applied ${appliedOverrideKeys.length} persisted env override(s) from config.json: ${appliedOverrideKeys.join(", ")}`);
|
|
151942
|
+
}
|
|
151535
151943
|
const upgradeFailureNotice = readUpgradeFailureNotice();
|
|
151536
151944
|
if (upgradeFailureNotice) {
|
|
151537
151945
|
const age = upgradeFailureNotice.ageLabel ? `${upgradeFailureNotice.ageLabel}, recorded ${upgradeFailureNotice.recordedAt}` : "recorded at an unknown time";
|