@adhdev/daemon-core 0.9.82-rc.508 → 0.9.82-rc.509
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/config/mesh-config.d.ts +12 -0
- package/dist/index.js +246 -80
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +246 -80
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-node-slots.d.ts +22 -0
- package/dist/mesh/mesh-runtime-store.d.ts +2 -2
- package/dist/mesh/mesh-scheduling-runtime.d.ts +5 -1
- package/dist/mesh/mesh-work-queue.d.ts +3 -3
- package/dist/providers/cli-provider-instance-types.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +54 -0
- package/dist/repo-mesh-types.d.ts +30 -29
- package/package.json +3 -3
- package/src/commands/med-family/mesh-crud.ts +24 -14
- package/src/config/mesh-config.ts +71 -24
- package/src/mesh/coordinator-prompt.ts +19 -14
- package/src/mesh/mesh-node-slots.ts +52 -0
- package/src/mesh/mesh-queue-assignment.ts +23 -23
- package/src/mesh/mesh-runtime-store.ts +3 -3
- package/src/mesh/mesh-scheduling-runtime.ts +24 -9
- package/src/mesh/mesh-work-queue.ts +3 -3
- package/src/providers/cli-provider-instance-types.ts +15 -0
- package/src/providers/cli-provider-instance.ts +174 -2
- package/src/repo-mesh-types.ts +39 -38
package/dist/index.mjs
CHANGED
|
@@ -117,20 +117,20 @@ function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy) {
|
|
|
117
117
|
}
|
|
118
118
|
return true;
|
|
119
119
|
}
|
|
120
|
-
function resolveProviderMaxParallel(
|
|
120
|
+
function resolveProviderMaxParallel(slots, providerType) {
|
|
121
121
|
const wanted = typeof providerType === "string" ? providerType.trim().toLowerCase() : "";
|
|
122
122
|
if (!wanted) return void 0;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
for (const
|
|
126
|
-
if (!
|
|
127
|
-
const type = typeof
|
|
123
|
+
if (!Array.isArray(slots)) return void 0;
|
|
124
|
+
let total;
|
|
125
|
+
for (const slot of slots) {
|
|
126
|
+
if (!slot || typeof slot !== "object") continue;
|
|
127
|
+
const type = typeof slot.provider === "string" ? slot.provider.trim().toLowerCase() : "";
|
|
128
128
|
if (!type || type !== wanted) continue;
|
|
129
|
-
const raw = Number(
|
|
130
|
-
if (!Number.isFinite(raw) || raw < 0)
|
|
131
|
-
|
|
129
|
+
const raw = Number(slot.maxParallel);
|
|
130
|
+
if (!Number.isFinite(raw) || raw < 0) continue;
|
|
131
|
+
total = (total ?? 0) + Math.floor(raw);
|
|
132
132
|
}
|
|
133
|
-
return
|
|
133
|
+
return total;
|
|
134
134
|
}
|
|
135
135
|
var MESH_SCHEDULING_STRATEGIES, DEFAULT_MESH_SCHEDULING_STRATEGY, MESH_CONVERGE_REFINE_TAG, MESH_CONVERGE_FAST_FORWARD_TAG, DEFAULT_MESH_POLICY, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES, DIRTY_WORKSPACE_BEHAVIORS, MESH_MAX_PARALLEL_TASKS_MIN, MESH_MAX_PARALLEL_TASKS_MAX, DEFAULT_MESH_READONLY_MULTIPLIER;
|
|
136
136
|
var init_repo_mesh_types = __esm({
|
|
@@ -412,10 +412,10 @@ function readInjected(value) {
|
|
|
412
412
|
}
|
|
413
413
|
function getDaemonBuildInfo() {
|
|
414
414
|
if (cached) return cached;
|
|
415
|
-
const commit = readInjected(true ? "
|
|
416
|
-
const commitShort = readInjected(true ? "
|
|
417
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
418
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
415
|
+
const commit = readInjected(true ? "8ebe4d4bcdc658e11253a51a28237d392aa4d978" : void 0) ?? "unknown";
|
|
416
|
+
const commitShort = readInjected(true ? "8ebe4d4b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
417
|
+
const version = readInjected(true ? "0.9.82-rc.509" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
418
|
+
const builtAt = readInjected(true ? "2026-07-13T02:51:57.282Z" : void 0);
|
|
419
419
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
420
420
|
return cached;
|
|
421
421
|
}
|
|
@@ -2842,12 +2842,6 @@ function normalizeNodeCapabilitySlots(raw) {
|
|
|
2842
2842
|
function deriveSlotsFromLegacy(input) {
|
|
2843
2843
|
const priority = Array.isArray(input.providerPriority) ? input.providerPriority.filter((p) => typeof p === "string" && !!p.trim()).map((p) => p.trim()) : [];
|
|
2844
2844
|
if (priority.length === 0) return [];
|
|
2845
|
-
const roleCap = /* @__PURE__ */ new Map();
|
|
2846
|
-
for (const role of input.providerRoles || []) {
|
|
2847
|
-
if (role && typeof role.providerType === "string" && Number.isFinite(role.maxParallel)) {
|
|
2848
|
-
roleCap.set(role.providerType.trim(), Math.floor(Number(role.maxParallel)));
|
|
2849
|
-
}
|
|
2850
|
-
}
|
|
2851
2845
|
const brains = input.difficultyBrains || {};
|
|
2852
2846
|
const byProvider = /* @__PURE__ */ new Map();
|
|
2853
2847
|
const shared = [];
|
|
@@ -2869,13 +2863,11 @@ function deriveSlotsFromLegacy(input) {
|
|
|
2869
2863
|
const difficulty = applied.map((a) => a.difficulty);
|
|
2870
2864
|
const model = applied.find((a) => a.model)?.model;
|
|
2871
2865
|
const thinkingLevel = applied.find((a) => a.thinkingLevel)?.thinkingLevel;
|
|
2872
|
-
const maxParallel = roleCap.get(provider);
|
|
2873
2866
|
return {
|
|
2874
2867
|
provider,
|
|
2875
2868
|
...model ? { model } : {},
|
|
2876
2869
|
...thinkingLevel ? { thinkingLevel } : {},
|
|
2877
|
-
...difficulty.length ? { difficulty } : {}
|
|
2878
|
-
...maxParallel !== void 0 ? { maxParallel } : {}
|
|
2870
|
+
...difficulty.length ? { difficulty } : {}
|
|
2879
2871
|
};
|
|
2880
2872
|
});
|
|
2881
2873
|
}
|
|
@@ -3043,6 +3035,7 @@ __export(mesh_config_exports, {
|
|
|
3043
3035
|
listMagiKindPanels: () => listMagiKindPanels,
|
|
3044
3036
|
listMeshes: () => listMeshes,
|
|
3045
3037
|
markMeshHostPairingJoined: () => markMeshHostPairingJoined,
|
|
3038
|
+
migrateProviderRolesToSlots: () => migrateProviderRolesToSlots,
|
|
3046
3039
|
normalizeCapabilityTags: () => normalizeCapabilityTags,
|
|
3047
3040
|
normalizeMagiSlots: () => normalizeMagiSlots,
|
|
3048
3041
|
normalizeRepoIdentity: () => normalizeRepoIdentity,
|
|
@@ -3084,23 +3077,51 @@ function migrateLoadedMeshConfig(config) {
|
|
|
3084
3077
|
for (const mesh of config.meshes) {
|
|
3085
3078
|
if (!mesh || !Array.isArray(mesh.nodes)) continue;
|
|
3086
3079
|
for (const node of mesh.nodes) {
|
|
3087
|
-
if (
|
|
3080
|
+
if (migrateProviderRolesToSlots(node?.policy)) changed = true;
|
|
3088
3081
|
}
|
|
3089
3082
|
}
|
|
3090
3083
|
return changed;
|
|
3091
3084
|
}
|
|
3092
|
-
function
|
|
3093
|
-
if (!policy || typeof policy !== "object") return false;
|
|
3094
|
-
const
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3085
|
+
function migrateProviderRolesToSlots(policy) {
|
|
3086
|
+
if (!policy || typeof policy !== "object" || Array.isArray(policy)) return false;
|
|
3087
|
+
const p = policy;
|
|
3088
|
+
const rawRoles = p.providerRoles;
|
|
3089
|
+
if (!Array.isArray(rawRoles)) return false;
|
|
3090
|
+
const roleCap = /* @__PURE__ */ new Map();
|
|
3091
|
+
for (const entry of rawRoles) {
|
|
3092
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
3093
|
+
const rec = entry;
|
|
3094
|
+
const provider = typeof rec.providerType === "string" ? rec.providerType.trim() : "";
|
|
3095
|
+
if (!provider) continue;
|
|
3096
|
+
const cap = Number(rec.maxParallel);
|
|
3097
|
+
if (!Number.isFinite(cap) || cap < 0) continue;
|
|
3098
|
+
roleCap.set(provider.toLowerCase(), { provider, cap: Math.floor(cap) });
|
|
3099
|
+
}
|
|
3100
|
+
const explicitSlots = Array.isArray(p.slots) ? normalizeNodeCapabilitySlots(p.slots) : [];
|
|
3101
|
+
if (explicitSlots.length) {
|
|
3102
|
+
for (const { provider, cap } of roleCap.values()) {
|
|
3103
|
+
const target = explicitSlots.find((s2) => s2.provider.trim().toLowerCase() === provider.toLowerCase() && s2.maxParallel === void 0);
|
|
3104
|
+
if (target) target.maxParallel = cap;
|
|
3105
|
+
}
|
|
3106
|
+
p.slots = explicitSlots;
|
|
3107
|
+
} else if (roleCap.size) {
|
|
3108
|
+
let difficultyBrains;
|
|
3109
|
+
try {
|
|
3110
|
+
difficultyBrains = getDifficultyBrains();
|
|
3111
|
+
} catch {
|
|
3112
|
+
difficultyBrains = void 0;
|
|
3113
|
+
}
|
|
3114
|
+
const priority = Array.isArray(p.providerPriority) ? p.providerPriority.map((t) => typeof t === "string" ? t.trim() : "").filter(Boolean) : [];
|
|
3115
|
+
const derived = deriveSlotsFromLegacy({ providerPriority: priority, difficultyBrains });
|
|
3116
|
+
const slots = derived.length ? derived : [...roleCap.values()].map((r) => ({ provider: r.provider }));
|
|
3117
|
+
for (const slot of slots) {
|
|
3118
|
+
const match = roleCap.get(slot.provider.trim().toLowerCase());
|
|
3119
|
+
if (match && slot.maxParallel === void 0) slot.maxParallel = match.cap;
|
|
3101
3120
|
}
|
|
3121
|
+
p.slots = slots;
|
|
3102
3122
|
}
|
|
3103
|
-
|
|
3123
|
+
delete p.providerRoles;
|
|
3124
|
+
return true;
|
|
3104
3125
|
}
|
|
3105
3126
|
function normalizeCapabilityTags(value) {
|
|
3106
3127
|
if (!Array.isArray(value)) return void 0;
|
|
@@ -3555,6 +3576,39 @@ var init_mesh_config = __esm({
|
|
|
3555
3576
|
}
|
|
3556
3577
|
});
|
|
3557
3578
|
|
|
3579
|
+
// src/mesh/mesh-node-slots.ts
|
|
3580
|
+
function normalizeProviderPriority(policy) {
|
|
3581
|
+
const raw = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerPriority : void 0;
|
|
3582
|
+
if (!Array.isArray(raw)) return [];
|
|
3583
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3584
|
+
return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
|
|
3585
|
+
if (seen.has(type)) return false;
|
|
3586
|
+
seen.add(type);
|
|
3587
|
+
return true;
|
|
3588
|
+
});
|
|
3589
|
+
}
|
|
3590
|
+
function resolveNodeCapabilitySlots(node) {
|
|
3591
|
+
const explicit = normalizeNodeCapabilitySlots(node?.policy?.slots);
|
|
3592
|
+
if (explicit.length) return explicit;
|
|
3593
|
+
let difficultyBrains;
|
|
3594
|
+
try {
|
|
3595
|
+
difficultyBrains = getDifficultyBrains();
|
|
3596
|
+
} catch {
|
|
3597
|
+
difficultyBrains = void 0;
|
|
3598
|
+
}
|
|
3599
|
+
return deriveSlotsFromLegacy({
|
|
3600
|
+
providerPriority: normalizeProviderPriority(node?.policy),
|
|
3601
|
+
difficultyBrains
|
|
3602
|
+
});
|
|
3603
|
+
}
|
|
3604
|
+
var init_mesh_node_slots = __esm({
|
|
3605
|
+
"src/mesh/mesh-node-slots.ts"() {
|
|
3606
|
+
"use strict";
|
|
3607
|
+
init_dist();
|
|
3608
|
+
init_mesh_config();
|
|
3609
|
+
}
|
|
3610
|
+
});
|
|
3611
|
+
|
|
3558
3612
|
// src/mesh/coordinator-prompt.ts
|
|
3559
3613
|
var coordinator_prompt_exports = {};
|
|
3560
3614
|
__export(coordinator_prompt_exports, {
|
|
@@ -3741,13 +3795,20 @@ function buildNodeConfigSection(mesh) {
|
|
|
3741
3795
|
const explicitMachineLabel = typeof n.machineLabel === "string" ? n.machineLabel : "";
|
|
3742
3796
|
const explicitLabel = explicitMachineLabel ? ` label: **${explicitMachineLabel}** |` : "";
|
|
3743
3797
|
const providerPriority = n.policy?.providerPriority?.length ? ` | providers: ${n.policy.providerPriority.join(", ")}` : "";
|
|
3744
|
-
const
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3798
|
+
const nodeSlots = resolveNodeCapabilitySlots(n);
|
|
3799
|
+
const seenCapProvider = /* @__PURE__ */ new Set();
|
|
3800
|
+
const providerCaps = [];
|
|
3801
|
+
for (const slot of nodeSlots) {
|
|
3802
|
+
const type = typeof slot?.provider === "string" ? slot.provider.trim() : "";
|
|
3803
|
+
if (!type) continue;
|
|
3804
|
+
const key2 = type.toLowerCase();
|
|
3805
|
+
if (seenCapProvider.has(key2)) continue;
|
|
3806
|
+
seenCapProvider.add(key2);
|
|
3807
|
+
const cap = resolveProviderMaxParallel(nodeSlots, type);
|
|
3808
|
+
if (cap === void 0) continue;
|
|
3809
|
+
providerCaps.push(`${type} (max ${cap})`);
|
|
3810
|
+
}
|
|
3811
|
+
const providerRolesSuffix = providerCaps.length ? ` | caps: ${providerCaps.join(", ")}` : "";
|
|
3751
3812
|
lines.push(`- ${explicitLabel} nodeId: \`${n.id}\` | workspace: \`${n.workspace}\`${n.daemonId ? ` | daemon: \`${n.daemonId}\`` : ""}${providerPriority}${providerRolesSuffix}${suffix}`);
|
|
3752
3813
|
const routingTags = [];
|
|
3753
3814
|
const custom = Array.isArray(n.capabilities) ? n.capabilities : [];
|
|
@@ -3956,6 +4017,7 @@ var init_coordinator_prompt = __esm({
|
|
|
3956
4017
|
"use strict";
|
|
3957
4018
|
init_repo_mesh_types();
|
|
3958
4019
|
init_mesh_config();
|
|
4020
|
+
init_mesh_node_slots();
|
|
3959
4021
|
init_dist();
|
|
3960
4022
|
PROMPT_SOFT_CAP_BYTES = 60 * 1024;
|
|
3961
4023
|
OPERATING_NOTES_PROMPT_CAP = 20;
|
|
@@ -7156,8 +7218,8 @@ var init_mesh_runtime_store = __esm({
|
|
|
7156
7218
|
/**
|
|
7157
7219
|
* Count active (status='assigned') tasks on a (node, provider) combination,
|
|
7158
7220
|
* matched by the assignedProviderType stamped on the payload at claim time.
|
|
7159
|
-
* Drives the per-(node, provider) maxParallel cap (
|
|
7160
|
-
*
|
|
7221
|
+
* Drives the per-(node, provider) maxParallel cap (summed across a provider's
|
|
7222
|
+
* slots[].maxParallel). The active-assignment set for a single node is tiny, so
|
|
7161
7223
|
* parsing payloads here is cheap and avoids a schema migration. Pre-cap legacy
|
|
7162
7224
|
* rows (no provider stamp) and other providers on the same node do not consume
|
|
7163
7225
|
* this provider's budget, so the cap is fully backward compatible.
|
|
@@ -12907,15 +12969,22 @@ function buildMeshSchedulingRuntime(mesh, queue) {
|
|
|
12907
12969
|
if (globalWriteCapReached) capReasons.push("global_max_parallel_tasks_reached");
|
|
12908
12970
|
if ((writeAssignedByNode.get(nodeId) ?? 0) > 0) capReasons.push("node_has_active_assignment");
|
|
12909
12971
|
let providerRoles;
|
|
12910
|
-
const
|
|
12911
|
-
|
|
12972
|
+
const slots = resolveNodeCapabilitySlots(rawNode);
|
|
12973
|
+
const cappedProviders = [];
|
|
12974
|
+
const seenProvider = /* @__PURE__ */ new Set();
|
|
12975
|
+
for (const slot of slots) {
|
|
12976
|
+
const providerType = typeof slot?.provider === "string" ? slot.provider.trim() : "";
|
|
12977
|
+
if (!providerType) continue;
|
|
12978
|
+
const key2 = providerType.toLowerCase();
|
|
12979
|
+
if (seenProvider.has(key2)) continue;
|
|
12980
|
+
seenProvider.add(key2);
|
|
12981
|
+
if (resolveProviderMaxParallel(slots, providerType) !== void 0) cappedProviders.push(providerType);
|
|
12982
|
+
}
|
|
12983
|
+
if (cappedProviders.length) {
|
|
12912
12984
|
const byProvider = providerCountByNode.get(nodeId);
|
|
12913
12985
|
providerRoles = [];
|
|
12914
|
-
for (const
|
|
12915
|
-
|
|
12916
|
-
const providerType = typeof role.providerType === "string" ? role.providerType.trim() : "";
|
|
12917
|
-
if (!providerType) continue;
|
|
12918
|
-
const maxParallel = resolveProviderMaxParallel(policy, providerType);
|
|
12986
|
+
for (const providerType of cappedProviders) {
|
|
12987
|
+
const maxParallel = resolveProviderMaxParallel(slots, providerType);
|
|
12919
12988
|
const activeAssigned = byProvider?.get(providerType) ?? 0;
|
|
12920
12989
|
const capReached = maxParallel !== void 0 && activeAssigned >= maxParallel;
|
|
12921
12990
|
providerRoles.push({
|
|
@@ -12956,6 +13025,7 @@ var init_mesh_scheduling_runtime = __esm({
|
|
|
12956
13025
|
"use strict";
|
|
12957
13026
|
init_repo_mesh_types();
|
|
12958
13027
|
init_dist();
|
|
13028
|
+
init_mesh_node_slots();
|
|
12959
13029
|
init_mesh_work_queue();
|
|
12960
13030
|
}
|
|
12961
13031
|
});
|
|
@@ -15780,7 +15850,7 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
15780
15850
|
return false;
|
|
15781
15851
|
}
|
|
15782
15852
|
const capabilityTags = buildMeshNodeCapabilityTags(node, providerType);
|
|
15783
|
-
const providerMaxParallel = resolveProviderMaxParallel(node
|
|
15853
|
+
const providerMaxParallel = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node), providerType);
|
|
15784
15854
|
const nodeIsWorktree = node?.isLocalWorktree === true;
|
|
15785
15855
|
const task = claimNextTask(meshId, nodeId, sessionId, capabilityTags, {
|
|
15786
15856
|
providerType,
|
|
@@ -16038,7 +16108,7 @@ function sweepExpiredCooldowns() {
|
|
|
16038
16108
|
if (now >= until) autoLaunchCooldownUntil.delete(key2);
|
|
16039
16109
|
}
|
|
16040
16110
|
}
|
|
16041
|
-
function
|
|
16111
|
+
function normalizeProviderPriority2(policy) {
|
|
16042
16112
|
const raw = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerPriority : void 0;
|
|
16043
16113
|
if (!Array.isArray(raw)) return [];
|
|
16044
16114
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -16152,21 +16222,6 @@ function buildSchedulingPool(localCandidates, remoteCandidates) {
|
|
|
16152
16222
|
}));
|
|
16153
16223
|
return { pool, uniqueNodes };
|
|
16154
16224
|
}
|
|
16155
|
-
function resolveNodeCapabilitySlots(node) {
|
|
16156
|
-
const explicit = normalizeNodeCapabilitySlots(node?.policy?.slots);
|
|
16157
|
-
if (explicit.length) return explicit;
|
|
16158
|
-
let difficultyBrains;
|
|
16159
|
-
try {
|
|
16160
|
-
difficultyBrains = getDifficultyBrains();
|
|
16161
|
-
} catch {
|
|
16162
|
-
difficultyBrains = void 0;
|
|
16163
|
-
}
|
|
16164
|
-
return deriveSlotsFromLegacy({
|
|
16165
|
-
providerPriority: normalizeProviderPriority(node?.policy),
|
|
16166
|
-
providerRoles: Array.isArray(node?.policy?.providerRoles) ? node.policy.providerRoles : void 0,
|
|
16167
|
-
difficultyBrains
|
|
16168
|
-
});
|
|
16169
|
-
}
|
|
16170
16225
|
function scoreSlotForTask(slot, task) {
|
|
16171
16226
|
let score = 1;
|
|
16172
16227
|
const diff = isMeshTaskDifficulty(task.difficulty) ? task.difficulty : void 0;
|
|
@@ -16293,6 +16348,7 @@ function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
|
|
|
16293
16348
|
const state = inst.getState();
|
|
16294
16349
|
const settings = state.settings || {};
|
|
16295
16350
|
if (readNonEmptyString2(settings.meshNodeFor) !== meshId) return false;
|
|
16351
|
+
if (readNonEmptyString2(settings.meshCoordinatorFor) === meshId) return false;
|
|
16296
16352
|
const instNodeId = readNonEmptyString2(settings.meshNodeId) || readNonEmptyString2(settings.nodeId);
|
|
16297
16353
|
if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
|
|
16298
16354
|
const status = readNonEmptyString2(state.status).toLowerCase();
|
|
@@ -16497,7 +16553,7 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
16497
16553
|
if (task.targetNodeId && !meshNodeIdMatches(node, task.targetNodeId)) return false;
|
|
16498
16554
|
if (task.taskMode === "convergence" && node?.isLocalWorktree === true) return false;
|
|
16499
16555
|
if (task.requiredTags?.length) {
|
|
16500
|
-
const priorities =
|
|
16556
|
+
const priorities = normalizeProviderPriority2(node?.policy);
|
|
16501
16557
|
const providerCandidates = priorities.length ? priorities : [void 0];
|
|
16502
16558
|
return providerCandidates.some(
|
|
16503
16559
|
(p) => nodeSatisfiesRequiredTags(task.requiredTags, buildMeshNodeCapabilityTags(node, p))
|
|
@@ -16584,7 +16640,7 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
16584
16640
|
if (rawEffectiveModel && effectiveModel === void 0) {
|
|
16585
16641
|
LOG.info("MeshQueue", `CODEX-400 GUARD: dropped incompatible launch model '${rawEffectiveModel}' for non-Anthropic provider '${resolved.providerType}' on node ${nodeId} (task ${task.id}); provider will use its own default model`);
|
|
16586
16642
|
}
|
|
16587
|
-
const providerCap = resolveProviderMaxParallel(node
|
|
16643
|
+
const providerCap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node), resolved.providerType);
|
|
16588
16644
|
if (providerCap !== void 0 && activeProviderAssignedCount(meshId, nodeId, resolved.providerType) >= providerCap) {
|
|
16589
16645
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_provider_parallel_reached", nodeId, providerType: resolved.providerType });
|
|
16590
16646
|
continue;
|
|
@@ -16907,6 +16963,7 @@ var init_mesh_queue_assignment = __esm({
|
|
|
16907
16963
|
init_mesh_warmup_deadline();
|
|
16908
16964
|
init_repo_mesh_types();
|
|
16909
16965
|
init_dist();
|
|
16966
|
+
init_mesh_node_slots();
|
|
16910
16967
|
init_mesh_events_stale();
|
|
16911
16968
|
init_mesh_events_utils();
|
|
16912
16969
|
init_mesh_node_identity();
|
|
@@ -45336,6 +45393,7 @@ var STATUS_HYDRATION_TAIL_LIMIT = 200;
|
|
|
45336
45393
|
var COMPLETED_FINALIZATION_RETRY_MS = 1e3;
|
|
45337
45394
|
var COMPLETED_FINALIZATION_MAX_WAIT_MS = 3e4;
|
|
45338
45395
|
var NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 4e3;
|
|
45396
|
+
var PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS = 1200;
|
|
45339
45397
|
var BACKGROUND_TASK_HOLD_MAX_MS = 5 * 6e4;
|
|
45340
45398
|
var USER_INPUT_ACK_DEDUP_WINDOW_MS = 6e4;
|
|
45341
45399
|
var STARTUP_GRACE_IDLE_COLLAPSE_WINDOW_MS = 12e3;
|
|
@@ -45578,6 +45636,39 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45578
45636
|
* the nudge was NOT deferred) and leaked to the coordinator.
|
|
45579
45637
|
*/
|
|
45580
45638
|
static AUTO_APPROVE_MASK_STALL_MS = 10500;
|
|
45639
|
+
/**
|
|
45640
|
+
* AUTOAPPROVE-FLAP-INBOX-MISSING: sticky-approval overlay window. Same time-tick
|
|
45641
|
+
* hold idea as the FALSE-IDLE completion gate — an approval signal that was
|
|
45642
|
+
* DOMINANT within this recent window is re-presented across a momentary busy blip
|
|
45643
|
+
* instead of collapsing.
|
|
45644
|
+
*
|
|
45645
|
+
* RCA (live 2026-07-13): a claude-cli worker sitting at a Bash approval modal
|
|
45646
|
+
* ("Do you want to proceed? ❯1.Yes") flaps waiting_approval↔busy on a ~2-3s period.
|
|
45647
|
+
* The spec `approval→busy` transition fires whenever the footer/modal approval
|
|
45648
|
+
* markers momentarily drop out of their parsed sections while the PRIOR command's
|
|
45649
|
+
* residual spinner text ("✳ Checking vendor drift…") still matches the busy regex.
|
|
45650
|
+
* On the busy frame the adapter reports status='generating', activeModal=null. That
|
|
45651
|
+
* corrupts THREE consumers at once: (1) mesh_active_work samples 'generating' →
|
|
45652
|
+
* collectPendingApprovals never sees 'awaiting_approval' → mesh_list_pending_approvals
|
|
45653
|
+
* count:0 (inbox miss); (2) the auto-approve settle gate is torn down each busy phase
|
|
45654
|
+
* so the 600ms settle never accrues → auto-approve never fires; (3) a mesh_approve
|
|
45655
|
+
* landing on a busy frame hits "Not in approval state". The existing FLAP machinery
|
|
45656
|
+
* (AUTO_APPROVE_FLAP_CONTINUITY_MS) only keeps the settle gate warm while status is
|
|
45657
|
+
* STILL waiting_approval (buttons scrolled out) — it does nothing once the FSM fully
|
|
45658
|
+
* commits to 'busy', and it never stabilises the status the inbox samples.
|
|
45659
|
+
*
|
|
45660
|
+
* Fix: when the raw adapter status flaps to generating/busy/idle but a
|
|
45661
|
+
* waiting_approval WITH a concrete modal was observed within this window, overlay
|
|
45662
|
+
* the cached modal and report status='waiting_approval'. This stabilized status
|
|
45663
|
+
* feeds getState (→ inbox), detectStatusTransition (→ event emission), and
|
|
45664
|
+
* maybeAutoApproveStatus (→ settle gate) uniformly, so the approval both registers
|
|
45665
|
+
* in the inbox and settles for auto-approve across the flap. Bounded (a genuine
|
|
45666
|
+
* resume that never returns to approval unmasks after this window) and scoped at the
|
|
45667
|
+
* call site to autonomous mesh sessions. 4000ms bridges the observed ~2-3s flap with
|
|
45668
|
+
* margin while staying well under AUTO_APPROVE_MASK_STALL_MS (a truly stalled/absent
|
|
45669
|
+
* approval still surfaces).
|
|
45670
|
+
*/
|
|
45671
|
+
static APPROVAL_STICKY_FLAP_MS = 4e3;
|
|
45581
45672
|
/**
|
|
45582
45673
|
* FALSE-IDLE (inter-approval quiet valley): grace window after an auto-approve
|
|
45583
45674
|
* (or mesh_approve) RESOLVES a modal during which a subsequent generating→idle
|
|
@@ -45681,6 +45772,14 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45681
45772
|
// signature) while a genuinely closed modal — buttons empty continuously past
|
|
45682
45773
|
// the continuity window — is still recognised and resets the gate.
|
|
45683
45774
|
autoApproveLastModalSeenAt = 0;
|
|
45775
|
+
// AUTOAPPROVE-FLAP-INBOX-MISSING sticky-approval overlay (see APPROVAL_STICKY_FLAP_MS).
|
|
45776
|
+
// The wall-clock of the last frame where the RAW adapter reported waiting_approval with
|
|
45777
|
+
// a CONCRETE modal (buttons present), the cached modal to re-present across a busy blip,
|
|
45778
|
+
// and the approvalEntrySeq at that frame (so a stabilized frame carries the right seq to
|
|
45779
|
+
// the emission-dedup fingerprint). All zero/null when no recent concrete approval.
|
|
45780
|
+
approvalStickyLastConcreteAt = 0;
|
|
45781
|
+
approvalStickyModal = null;
|
|
45782
|
+
approvalStickyEntrySeq = 0;
|
|
45684
45783
|
// STATUS-MISMATCH: wall-clock when the CURRENT auto-approve episode (waiting_approval
|
|
45685
45784
|
// + shouldAutoApprove) first began wanting to mask. Unlike pendingAutoApprovalSince it
|
|
45686
45785
|
// is NOT reset when the modal signature changes (a still-streaming/flapping prompt) and
|
|
@@ -45822,7 +45921,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
45822
45921
|
}
|
|
45823
45922
|
}
|
|
45824
45923
|
getState() {
|
|
45825
|
-
const adapterStatus = this.adapter.getStatus();
|
|
45924
|
+
const adapterStatus = this.stabilizeFlappingApprovalStatus(this.adapter.getStatus());
|
|
45826
45925
|
if (Object.prototype.hasOwnProperty.call(adapterStatus, "activeInteractivePrompt")) {
|
|
45827
45926
|
this.activeInteractivePrompt = adapterStatus.activeInteractivePrompt ?? null;
|
|
45828
45927
|
}
|
|
@@ -46686,6 +46785,9 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
46686
46785
|
return null;
|
|
46687
46786
|
}
|
|
46688
46787
|
if (this.type === "antigravity-cli") {
|
|
46788
|
+
if (allowMissingAssistantTimeout) {
|
|
46789
|
+
return { reason: "missing_final_assistant", terminal: false, holdForTranscript: true };
|
|
46790
|
+
}
|
|
46689
46791
|
return null;
|
|
46690
46792
|
}
|
|
46691
46793
|
if (allowMissingAssistantTimeout && pending.previousStatus === "waiting_approval") {
|
|
@@ -46717,6 +46819,19 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
46717
46819
|
}
|
|
46718
46820
|
} catch {
|
|
46719
46821
|
}
|
|
46822
|
+
if (allowMissingAssistantTimeout && !adapterOwnsMessagesElsewhere && finalAssistantEvidence.source === "parsed") {
|
|
46823
|
+
try {
|
|
46824
|
+
const outStatus = this.adapter.getStatus({ allowParse: false });
|
|
46825
|
+
const lastOutputAt = typeof outStatus?.lastOutputAt === "number" && Number.isFinite(outStatus.lastOutputAt) ? outStatus.lastOutputAt : void 0;
|
|
46826
|
+
if (typeof lastOutputAt === "number") {
|
|
46827
|
+
const quietMs = Date.now() - lastOutputAt;
|
|
46828
|
+
if (quietMs < PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS) {
|
|
46829
|
+
return { reason: "parsed_final_assistant_quiet_dwell", terminal: false };
|
|
46830
|
+
}
|
|
46831
|
+
}
|
|
46832
|
+
} catch {
|
|
46833
|
+
}
|
|
46834
|
+
}
|
|
46720
46835
|
return null;
|
|
46721
46836
|
}
|
|
46722
46837
|
// (FALSEIDLE-a) Positive, structural proof that the latest approval entry was resolved
|
|
@@ -47138,6 +47253,53 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
47138
47253
|
...opts.completionDiagnostic !== void 0 ? { completionDiagnostic: opts.completionDiagnostic } : {}
|
|
47139
47254
|
});
|
|
47140
47255
|
}
|
|
47256
|
+
/**
|
|
47257
|
+
* AUTOAPPROVE-FLAP-INBOX-MISSING sticky-approval overlay. Returns the adapterStatus a
|
|
47258
|
+
* flap-prone claude-cli approval SHOULD present this frame — either the raw status
|
|
47259
|
+
* unchanged, or, when the raw status has momentarily flapped OFF a recently-dominant
|
|
47260
|
+
* concrete approval, a synthetic `waiting_approval` re-presenting the cached modal.
|
|
47261
|
+
*
|
|
47262
|
+
* Records the concrete approval whenever the raw status is waiting_approval WITH
|
|
47263
|
+
* buttons. On a subsequent non-approval frame (the spec `approval→busy` flap), if that
|
|
47264
|
+
* concrete approval was seen within APPROVAL_STICKY_FLAP_MS AND the engine has NOT
|
|
47265
|
+
* resolved a modal since (lastApprovalResolvedAt not advanced past the sticky start),
|
|
47266
|
+
* overlay the cached modal + waiting_approval so the inbox / auto-approve / mesh_approve
|
|
47267
|
+
* all see the stable approval. A genuine resolution (auto-approve or mesh_approve fires
|
|
47268
|
+
* resolveModal → lastApprovalResolvedAt advances) clears the sticky immediately, so a
|
|
47269
|
+
* legitimate post-approval resume is NEVER masked as a lingering approval. Bounded by the
|
|
47270
|
+
* window, and scoped to autonomous mesh sessions (a foreground/attended or non-mesh
|
|
47271
|
+
* session, where a human answers the prompt, is returned untouched).
|
|
47272
|
+
*/
|
|
47273
|
+
stabilizeFlappingApprovalStatus(adapterStatus, now = Date.now()) {
|
|
47274
|
+
if (!this.isAutonomousMeshSession() || !this.shouldAutoApprove()) return adapterStatus;
|
|
47275
|
+
const rawStatus = adapterStatus?.status;
|
|
47276
|
+
const resolvedAt = typeof this.adapter?.lastApprovalResolvedAt === "number" ? this.adapter.lastApprovalResolvedAt : 0;
|
|
47277
|
+
if (rawStatus === "waiting_approval") {
|
|
47278
|
+
if (hasNonEmptyCliModalButtons(adapterStatus?.activeModal)) {
|
|
47279
|
+
this.approvalStickyLastConcreteAt = now;
|
|
47280
|
+
this.approvalStickyModal = adapterStatus.activeModal;
|
|
47281
|
+
this.approvalStickyEntrySeq = typeof adapterStatus?.approvalEntrySeq === "number" ? adapterStatus.approvalEntrySeq : this.approvalStickyEntrySeq;
|
|
47282
|
+
}
|
|
47283
|
+
return adapterStatus;
|
|
47284
|
+
}
|
|
47285
|
+
if (this.approvalStickyLastConcreteAt > 0 && this.approvalStickyModal) {
|
|
47286
|
+
const withinWindow = now - this.approvalStickyLastConcreteAt < _CliProviderInstance.APPROVAL_STICKY_FLAP_MS;
|
|
47287
|
+
const resolvedSinceAnchor = resolvedAt >= this.approvalStickyLastConcreteAt;
|
|
47288
|
+
if (withinWindow && !resolvedSinceAnchor) {
|
|
47289
|
+
return {
|
|
47290
|
+
...adapterStatus,
|
|
47291
|
+
status: "waiting_approval",
|
|
47292
|
+
activeModal: this.approvalStickyModal,
|
|
47293
|
+
...this.approvalStickyEntrySeq ? { approvalEntrySeq: this.approvalStickyEntrySeq } : {},
|
|
47294
|
+
approvalStickyOverlay: true
|
|
47295
|
+
};
|
|
47296
|
+
}
|
|
47297
|
+
this.approvalStickyLastConcreteAt = 0;
|
|
47298
|
+
this.approvalStickyModal = null;
|
|
47299
|
+
this.approvalStickyEntrySeq = 0;
|
|
47300
|
+
}
|
|
47301
|
+
return adapterStatus;
|
|
47302
|
+
}
|
|
47141
47303
|
maybeAutoApproveStatus(adapterStatus, now = Date.now()) {
|
|
47142
47304
|
if (adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove() && this.manualAttendance.isAttended(now)) {
|
|
47143
47305
|
this.lastAutoApprovalSignature = "";
|
|
@@ -47367,7 +47529,7 @@ ${buttons.join("\n")}`;
|
|
|
47367
47529
|
}
|
|
47368
47530
|
detectStatusTransition() {
|
|
47369
47531
|
const now = Date.now();
|
|
47370
|
-
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
47532
|
+
const adapterStatus = this.stabilizeFlappingApprovalStatus(this.adapter.getStatus({ allowParse: false }), now);
|
|
47371
47533
|
const adapterProviderSessionId = normalizeProviderSessionId(
|
|
47372
47534
|
this.provider,
|
|
47373
47535
|
typeof adapterStatus?.providerSessionId === "string" ? adapterStatus.providerSessionId : ""
|
|
@@ -55661,7 +55823,7 @@ var meshCrudHandlers = {
|
|
|
55661
55823
|
const ownerFailure = await ctx.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "node addition");
|
|
55662
55824
|
if (ownerFailure) return ownerFailure;
|
|
55663
55825
|
try {
|
|
55664
|
-
const { addNode: addNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
55826
|
+
const { addNode: addNode2, migrateProviderRolesToSlots: migrateProviderRolesToSlots2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
55665
55827
|
const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
|
|
55666
55828
|
const readOnly = args?.readOnly === true;
|
|
55667
55829
|
const providerRoles = normalizeProviderRoles(args?.providerRoles);
|
|
@@ -55670,6 +55832,7 @@ var meshCrudHandlers = {
|
|
|
55670
55832
|
...providerPriority.length ? { providerPriority } : {},
|
|
55671
55833
|
...providerRoles.length ? { providerRoles } : {}
|
|
55672
55834
|
};
|
|
55835
|
+
if (providerRoles.length) migrateProviderRolesToSlots2(policy);
|
|
55673
55836
|
const role = normalizeMeshDaemonRole(args?.role);
|
|
55674
55837
|
const daemonId = typeof args?.daemonId === "string" && args.daemonId.trim() ? args.daemonId.trim() : void 0;
|
|
55675
55838
|
const machineId = typeof args?.machineId === "string" && args.machineId.trim() ? args.machineId.trim() : void 0;
|
|
@@ -55698,7 +55861,7 @@ var meshCrudHandlers = {
|
|
|
55698
55861
|
const ownerFailure = await ctx.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "node update");
|
|
55699
55862
|
if (ownerFailure) return ownerFailure;
|
|
55700
55863
|
try {
|
|
55701
|
-
const { updateNode: updateNode2, normalizeCapabilityTags: normalizeCapabilityTags2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
55864
|
+
const { updateNode: updateNode2, normalizeCapabilityTags: normalizeCapabilityTags2, migrateProviderRolesToSlots: migrateProviderRolesToSlots2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
55702
55865
|
const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
|
|
55703
55866
|
if (Array.isArray(args?.providerPriority)) {
|
|
55704
55867
|
const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
|
|
@@ -55711,12 +55874,10 @@ var meshCrudHandlers = {
|
|
|
55711
55874
|
}
|
|
55712
55875
|
if (Array.isArray(args?.providerRoles)) {
|
|
55713
55876
|
const providerRoles = normalizeProviderRoles(args.providerRoles);
|
|
55714
|
-
if (providerRoles.length)
|
|
55715
|
-
|
|
55716
|
-
} else {
|
|
55717
|
-
delete policy.providerRoles;
|
|
55718
|
-
}
|
|
55877
|
+
if (providerRoles.length) policy.providerRoles = providerRoles;
|
|
55878
|
+
else delete policy.providerRoles;
|
|
55719
55879
|
}
|
|
55880
|
+
migrateProviderRolesToSlots2(policy);
|
|
55720
55881
|
const patch = { policy };
|
|
55721
55882
|
if (typeof args?.systemPrompt === "string") {
|
|
55722
55883
|
const trimmed = args.systemPrompt.trim();
|
|
@@ -55988,8 +56149,11 @@ var meshCrudHandlers = {
|
|
|
55988
56149
|
console.log(`[mesh] clone_mesh_node base sync: ${result.baseSync.action} (startRef=${result.baseSync.startRef})`);
|
|
55989
56150
|
}
|
|
55990
56151
|
let node;
|
|
56152
|
+
const { migrateProviderRolesToSlots: migrateProviderRolesToSlots2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
55991
56153
|
if (meshRecord.inline) {
|
|
55992
56154
|
const { randomUUID: randomUUID15 } = await import("crypto");
|
|
56155
|
+
const clonedPolicy = { ...sourceNode.policy || {} };
|
|
56156
|
+
migrateProviderRolesToSlots2(clonedPolicy);
|
|
55993
56157
|
node = {
|
|
55994
56158
|
id: `node_${randomUUID15().replace(/-/g, "")}`,
|
|
55995
56159
|
workspace: result.worktreePath,
|
|
@@ -55997,7 +56161,7 @@ var meshCrudHandlers = {
|
|
|
55997
56161
|
daemonId: sourceNode.daemonId,
|
|
55998
56162
|
machineId: sourceNode.machineId ?? sourceNode.machine_id,
|
|
55999
56163
|
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
56000
|
-
policy:
|
|
56164
|
+
policy: clonedPolicy,
|
|
56001
56165
|
isLocalWorktree: true,
|
|
56002
56166
|
worktreeBranch: result.branch,
|
|
56003
56167
|
clonedFromNodeId: sourceNodeId
|
|
@@ -56005,6 +56169,8 @@ var meshCrudHandlers = {
|
|
|
56005
56169
|
ctx.updateInlineMeshNode(meshId, mesh, node);
|
|
56006
56170
|
} else {
|
|
56007
56171
|
const { addNode: addNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
56172
|
+
const clonedPolicy = { ...sourceNode.policy || {} };
|
|
56173
|
+
migrateProviderRolesToSlots2(clonedPolicy);
|
|
56008
56174
|
node = addNode2(meshId, {
|
|
56009
56175
|
workspace: result.worktreePath,
|
|
56010
56176
|
repoRoot: result.worktreePath,
|
|
@@ -56014,7 +56180,7 @@ var meshCrudHandlers = {
|
|
|
56014
56180
|
isLocalWorktree: true,
|
|
56015
56181
|
worktreeBranch: result.branch,
|
|
56016
56182
|
clonedFromNodeId: sourceNodeId,
|
|
56017
|
-
policy:
|
|
56183
|
+
policy: clonedPolicy
|
|
56018
56184
|
});
|
|
56019
56185
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
56020
56186
|
const inlineForReconcile = ctx.getCachedInlineMesh(meshId);
|