@adhdev/daemon-core 0.9.82-rc.310 → 0.9.82-rc.311
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/commands/router.d.ts +4 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +525 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +517 -54
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-coordinator.d.ts +31 -0
- package/dist/mesh/mesh-runtime-store.d.ts +18 -0
- package/dist/mesh/mesh-work-queue.d.ts +23 -0
- package/dist/providers/spec/cli-adapter.d.ts +34 -3
- package/dist/providers/spec/types.d.ts +36 -0
- package/dist/repo-mesh-types.d.ts +97 -9
- package/package.json +2 -2
- package/src/commands/chat-commands.ts +10 -2
- package/src/commands/router.ts +139 -3
- package/src/commands/stream-commands.ts +8 -0
- package/src/config/chat-history.ts +9 -0
- package/src/config/mesh-config.ts +17 -1
- package/src/index.ts +13 -2
- package/src/mesh/mesh-events-coordinator.ts +165 -9
- package/src/mesh/mesh-runtime-store.ts +52 -0
- package/src/mesh/mesh-work-queue.ts +105 -1
- package/src/providers/spec/cli-adapter.ts +155 -13
- package/src/providers/spec/fsm-driver.ts +14 -1
- package/src/providers/spec/native-history-executor.ts +114 -22
- package/src/providers/spec/types.ts +37 -0
- package/src/repo-mesh-types.ts +128 -9
package/dist/index.js
CHANGED
|
@@ -31,6 +31,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
33
|
// src/repo-mesh-types.ts
|
|
34
|
+
function normalizeMeshSchedulingStrategy(value) {
|
|
35
|
+
if (typeof value !== "string") return DEFAULT_MESH_SCHEDULING_STRATEGY;
|
|
36
|
+
const trimmed = value.trim();
|
|
37
|
+
return MESH_SCHEDULING_STRATEGIES.includes(trimmed) ? trimmed : DEFAULT_MESH_SCHEDULING_STRATEGY;
|
|
38
|
+
}
|
|
39
|
+
function resolveNodeSchedulingPriority(nodePolicy) {
|
|
40
|
+
const raw = Number(nodePolicy?.schedulingPriority);
|
|
41
|
+
return Number.isFinite(raw) ? raw : 0;
|
|
42
|
+
}
|
|
43
|
+
function resolveAutoConvergeCodeChange(policy) {
|
|
44
|
+
return policy?.autoConvergeCodeChange === true;
|
|
45
|
+
}
|
|
34
46
|
function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy) {
|
|
35
47
|
if (typeof nodePolicy?.delegatedWorkerAutoApprove === "boolean") {
|
|
36
48
|
return nodePolicy.delegatedWorkerAutoApprove;
|
|
@@ -58,10 +70,19 @@ function resolveProviderMaxParallel(nodePolicy, providerType) {
|
|
|
58
70
|
if (!Number.isFinite(raw) || raw < 0) return void 0;
|
|
59
71
|
return Math.floor(raw);
|
|
60
72
|
}
|
|
61
|
-
var DEFAULT_MESH_POLICY;
|
|
73
|
+
var MESH_SCHEDULING_STRATEGIES, DEFAULT_MESH_SCHEDULING_STRATEGY, MESH_CONVERGE_REFINE_TAG, MESH_CONVERGE_FAST_FORWARD_TAG, DEFAULT_MESH_POLICY;
|
|
62
74
|
var init_repo_mesh_types = __esm({
|
|
63
75
|
"src/repo-mesh-types.ts"() {
|
|
64
76
|
"use strict";
|
|
77
|
+
MESH_SCHEDULING_STRATEGIES = [
|
|
78
|
+
"first_eligible",
|
|
79
|
+
"least_loaded",
|
|
80
|
+
"round_robin",
|
|
81
|
+
"priority_only"
|
|
82
|
+
];
|
|
83
|
+
DEFAULT_MESH_SCHEDULING_STRATEGY = "first_eligible";
|
|
84
|
+
MESH_CONVERGE_REFINE_TAG = "converge=refine";
|
|
85
|
+
MESH_CONVERGE_FAST_FORWARD_TAG = "converge=fast_forward";
|
|
65
86
|
DEFAULT_MESH_POLICY = {
|
|
66
87
|
requirePreTaskCheckpoint: false,
|
|
67
88
|
requirePostTaskCheckpoint: true,
|
|
@@ -295,10 +316,10 @@ function readInjected(value) {
|
|
|
295
316
|
}
|
|
296
317
|
function getDaemonBuildInfo() {
|
|
297
318
|
if (cached) return cached;
|
|
298
|
-
const commit = readInjected(true ? "
|
|
299
|
-
const commitShort = readInjected(true ? "
|
|
300
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
301
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
319
|
+
const commit = readInjected(true ? "3902f3d63eabe7b9e34d0e849dc0fed2fd66c026" : void 0) ?? "unknown";
|
|
320
|
+
const commitShort = readInjected(true ? "3902f3d6" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
321
|
+
const version = readInjected(true ? "0.9.82-rc.311" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
322
|
+
const builtAt = readInjected(true ? "2026-06-17T12:17:11.243Z" : void 0);
|
|
302
323
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
303
324
|
return cached;
|
|
304
325
|
}
|
|
@@ -1545,6 +1566,17 @@ function mergeMeshPolicy(base, patch) {
|
|
|
1545
1566
|
if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
|
|
1546
1567
|
policy.spawnedSessionVisibility = "visible";
|
|
1547
1568
|
}
|
|
1569
|
+
const normalizedStrategy = normalizeMeshSchedulingStrategy(policy.schedulingStrategy);
|
|
1570
|
+
if (normalizedStrategy === "first_eligible") {
|
|
1571
|
+
delete policy.schedulingStrategy;
|
|
1572
|
+
} else {
|
|
1573
|
+
policy.schedulingStrategy = normalizedStrategy;
|
|
1574
|
+
}
|
|
1575
|
+
if (policy.autoConvergeCodeChange === true) {
|
|
1576
|
+
policy.autoConvergeCodeChange = true;
|
|
1577
|
+
} else {
|
|
1578
|
+
delete policy.autoConvergeCodeChange;
|
|
1579
|
+
}
|
|
1548
1580
|
return policy;
|
|
1549
1581
|
}
|
|
1550
1582
|
function normalizeAutoFastForwardPolicy(value) {
|
|
@@ -2838,6 +2870,7 @@ __export(mesh_work_queue_exports, {
|
|
|
2838
2870
|
recordMeshToolCall: () => recordMeshToolCall,
|
|
2839
2871
|
recordTaskAutoLaunch: () => recordTaskAutoLaunch,
|
|
2840
2872
|
requeueTask: () => requeueTask,
|
|
2873
|
+
resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
|
|
2841
2874
|
updateDirectDispatchStatus: () => updateDirectDispatchStatus,
|
|
2842
2875
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
2843
2876
|
updateTaskStatus: () => updateTaskStatus,
|
|
@@ -2911,6 +2944,21 @@ function firstProviderPriority(policy) {
|
|
|
2911
2944
|
if (!Array.isArray(raw)) return void 0;
|
|
2912
2945
|
return raw.find((type) => typeof type === "string" && type.trim())?.trim();
|
|
2913
2946
|
}
|
|
2947
|
+
function roleCapabilityTags(policy, providerType) {
|
|
2948
|
+
const roles = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerRoles : void 0;
|
|
2949
|
+
if (!Array.isArray(roles)) return [];
|
|
2950
|
+
const wantedProvider = typeof providerType === "string" && providerType.trim() ? providerType.trim().toLowerCase() : "";
|
|
2951
|
+
const out = [];
|
|
2952
|
+
for (const entry of roles) {
|
|
2953
|
+
if (!entry || typeof entry !== "object") continue;
|
|
2954
|
+
const type = typeof entry.providerType === "string" ? entry.providerType.trim().toLowerCase() : "";
|
|
2955
|
+
const role = typeof entry.role === "string" ? entry.role.trim().toLowerCase() : "";
|
|
2956
|
+
if (!role) continue;
|
|
2957
|
+
if (wantedProvider && type && type !== wantedProvider) continue;
|
|
2958
|
+
out.push(`role=${role}`);
|
|
2959
|
+
}
|
|
2960
|
+
return out;
|
|
2961
|
+
}
|
|
2914
2962
|
function buildMeshNodeCapabilityTags(node, providerType) {
|
|
2915
2963
|
const provider = typeof providerType === "string" && providerType.trim() ? providerType.trim() : firstProviderPriority(node?.policy);
|
|
2916
2964
|
const worktreeBranch = typeof node?.worktreeBranch === "string" && node.worktreeBranch.trim() ? node.worktreeBranch.trim() : null;
|
|
@@ -2922,7 +2970,25 @@ function buildMeshNodeCapabilityTags(node, providerType) {
|
|
|
2922
2970
|
// Worktree nodes automatically expose a "worktree=<branch>" tag so that
|
|
2923
2971
|
// mesh_enqueue_task with required_tags: ["worktree=<branch>"] routes
|
|
2924
2972
|
// only to the matching worktree node.
|
|
2925
|
-
...node?.isLocalWorktree === true && worktreeBranch ? [`worktree=${worktreeBranch}`] : []
|
|
2973
|
+
...node?.isLocalWorktree === true && worktreeBranch ? [`worktree=${worktreeBranch}`] : [],
|
|
2974
|
+
// Convergence routing: advertise how this node can land its work onto base.
|
|
2975
|
+
// - converge=refine: local worktree nodes (on ANY machine — refine_mesh_node
|
|
2976
|
+
// now forwards to the owning daemon) can run the Refinery merge → push →
|
|
2977
|
+
// cleanup against their own checkout, so they accept code_change tasks.
|
|
2978
|
+
// - converge=fast_forward: non-worktree nodes (the machine itself) can only
|
|
2979
|
+
// ff/push an already-converged branch; they are NOT a destination for
|
|
2980
|
+
// code_change work (a worktree is created first, and that worktree node
|
|
2981
|
+
// receives the task instead). Reuses the ordinary required-tags filter —
|
|
2982
|
+
// the load-balancing scheduler auto-injects converge=refine for code_change
|
|
2983
|
+
// so such work is hard-filtered onto refine-capable nodes.
|
|
2984
|
+
...node?.isLocalWorktree === true ? ["converge=refine"] : ["converge=fast_forward"],
|
|
2985
|
+
// Role-based routing: advertise role=<x> for each (node, provider) role
|
|
2986
|
+
// declared in policy.providerRoles. Narrowed to the selected provider when
|
|
2987
|
+
// one is given so the chosen provider must match a task's required role;
|
|
2988
|
+
// when no provider is selected, all declared roles are advertised for the
|
|
2989
|
+
// node-level eligibility scan. Reuses the ordinary required-tags filter —
|
|
2990
|
+
// no separate role field/gate.
|
|
2991
|
+
...roleCapabilityTags(node?.policy, providerType)
|
|
2926
2992
|
]);
|
|
2927
2993
|
}
|
|
2928
2994
|
function nodeSatisfiesRequiredTags(requiredTags, capabilityTags) {
|
|
@@ -2931,6 +2997,18 @@ function nodeSatisfiesRequiredTags(requiredTags, capabilityTags) {
|
|
|
2931
2997
|
const available = new Set(normalizeMeshCapabilityTags(capabilityTags));
|
|
2932
2998
|
return required.every((tag) => available.has(tag));
|
|
2933
2999
|
}
|
|
3000
|
+
function resolveConvergeRequiredTags(meshId, taskMode, explicitRequiredTags, opts) {
|
|
3001
|
+
if (taskMode !== "code_change") return explicitRequiredTags;
|
|
3002
|
+
if (typeof opts?.targetNodeId === "string" && opts.targetNodeId.trim()) return explicitRequiredTags;
|
|
3003
|
+
let optedIn = false;
|
|
3004
|
+
try {
|
|
3005
|
+
optedIn = resolveAutoConvergeCodeChange(getMesh(meshId)?.policy);
|
|
3006
|
+
} catch {
|
|
3007
|
+
optedIn = false;
|
|
3008
|
+
}
|
|
3009
|
+
if (!optedIn) return explicitRequiredTags;
|
|
3010
|
+
return normalizeMeshCapabilityTags([...explicitRequiredTags, MESH_CONVERGE_REFINE_TAG]);
|
|
3011
|
+
}
|
|
2934
3012
|
function withQueueLock(_meshId, fn) {
|
|
2935
3013
|
return MeshRuntimeStore.getInstance().transaction(fn);
|
|
2936
3014
|
}
|
|
@@ -2989,7 +3067,15 @@ function enqueueTask(meshId, message, opts) {
|
|
|
2989
3067
|
taskMode: modeValidation.taskMode,
|
|
2990
3068
|
targetNodeId: opts?.targetNodeId,
|
|
2991
3069
|
targetSessionId: opts?.targetSessionId,
|
|
2992
|
-
|
|
3070
|
+
// Convergence routing (opt-in): auto-inject converge=refine for code_change
|
|
3071
|
+
// tasks so they hard-filter onto refine-capable worktree nodes. No-op unless
|
|
3072
|
+
// the mesh opts in; explicit target_node_id / required_tags are preserved.
|
|
3073
|
+
requiredTags: resolveConvergeRequiredTags(
|
|
3074
|
+
meshId,
|
|
3075
|
+
modeValidation.taskMode,
|
|
3076
|
+
normalizeMeshCapabilityTags(opts?.requiredTags),
|
|
3077
|
+
{ targetNodeId: opts?.targetNodeId }
|
|
3078
|
+
),
|
|
2993
3079
|
...dependsOn.length > 0 ? { dependsOn } : {},
|
|
2994
3080
|
...typeof opts?.missionId === "string" && opts.missionId.trim() ? { missionId: opts.missionId.trim() } : {},
|
|
2995
3081
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3250,6 +3336,7 @@ var init_mesh_work_queue = __esm({
|
|
|
3250
3336
|
"use strict";
|
|
3251
3337
|
import_crypto5 = require("crypto");
|
|
3252
3338
|
init_mesh_host_ownership();
|
|
3339
|
+
init_repo_mesh_types();
|
|
3253
3340
|
init_mesh_runtime_store();
|
|
3254
3341
|
init_mesh_config();
|
|
3255
3342
|
ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
|
|
@@ -3544,6 +3631,17 @@ var init_mesh_runtime_store = __esm({
|
|
|
3544
3631
|
|
|
3545
3632
|
CREATE INDEX IF NOT EXISTS idx_mesh_missions_mesh_status
|
|
3546
3633
|
ON mesh_missions(mesh_id, status, updated_at);
|
|
3634
|
+
|
|
3635
|
+
-- Load-balancing scheduler: per-mesh round-robin rotation cursor. When
|
|
3636
|
+
-- the schedulingStrategy is 'round_robin', several eligible nodes tied at
|
|
3637
|
+
-- the least load are rotated by this cursor so the tie-break winner cycles
|
|
3638
|
+
-- across scheduling passes instead of always favouring the same array-order
|
|
3639
|
+
-- node. Persisted (not a module Map) so rotation survives daemon restarts
|
|
3640
|
+
-- and stays a single source of truth across scheduling entry points.
|
|
3641
|
+
CREATE TABLE IF NOT EXISTS mesh_scheduler_cursor (
|
|
3642
|
+
mesh_id TEXT PRIMARY KEY,
|
|
3643
|
+
cursor INTEGER NOT NULL DEFAULT 0
|
|
3644
|
+
);
|
|
3547
3645
|
`);
|
|
3548
3646
|
}
|
|
3549
3647
|
hasCompletionFingerprint(fingerprint) {
|
|
@@ -3721,6 +3819,44 @@ var init_mesh_runtime_store = __esm({
|
|
|
3721
3819
|
`).get(meshId, nodeId);
|
|
3722
3820
|
return row !== void 0;
|
|
3723
3821
|
}
|
|
3822
|
+
/**
|
|
3823
|
+
* Count active (status='assigned') tasks on a node, regardless of provider or
|
|
3824
|
+
* task mode. This is the load metric for least-loaded / round-robin ranking:
|
|
3825
|
+
* the scheduler prefers the node with the fewest active assignments so
|
|
3826
|
+
* untargeted work spreads instead of piling onto whichever node asks first.
|
|
3827
|
+
*/
|
|
3828
|
+
nodeActiveAssignmentCount(meshId, nodeId) {
|
|
3829
|
+
const row = this.db.prepare(`
|
|
3830
|
+
SELECT COUNT(*) as count FROM mesh_queue
|
|
3831
|
+
WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id = ?
|
|
3832
|
+
`).get(meshId, nodeId);
|
|
3833
|
+
return row?.count ?? 0;
|
|
3834
|
+
}
|
|
3835
|
+
/**
|
|
3836
|
+
* Read the current per-mesh round-robin cursor (0 when unset). Used to rotate
|
|
3837
|
+
* the tie-break winner among nodes tied at the least load.
|
|
3838
|
+
*/
|
|
3839
|
+
getSchedulerCursor(meshId) {
|
|
3840
|
+
const row = this.db.prepare(
|
|
3841
|
+
"SELECT cursor FROM mesh_scheduler_cursor WHERE mesh_id = ?"
|
|
3842
|
+
).get(meshId);
|
|
3843
|
+
return row?.cursor ?? 0;
|
|
3844
|
+
}
|
|
3845
|
+
/**
|
|
3846
|
+
* Atomically advance the per-mesh round-robin cursor by one and return the
|
|
3847
|
+
* value that was current BEFORE the bump (the value the caller should rotate
|
|
3848
|
+
* by for this pass). UPSERT keeps it lock-free across concurrent passes.
|
|
3849
|
+
*/
|
|
3850
|
+
bumpSchedulerCursor(meshId) {
|
|
3851
|
+
return this.transaction(() => {
|
|
3852
|
+
const current = this.getSchedulerCursor(meshId);
|
|
3853
|
+
this.db.prepare(`
|
|
3854
|
+
INSERT INTO mesh_scheduler_cursor (mesh_id, cursor) VALUES (?, ?)
|
|
3855
|
+
ON CONFLICT(mesh_id) DO UPDATE SET cursor = excluded.cursor
|
|
3856
|
+
`).run(meshId, current + 1);
|
|
3857
|
+
return current;
|
|
3858
|
+
});
|
|
3859
|
+
}
|
|
3724
3860
|
/**
|
|
3725
3861
|
* Count active (status='assigned') tasks on a (node, provider) combination,
|
|
3726
3862
|
* matched by the assignedProviderType stamped on the payload at claim time.
|
|
@@ -8292,6 +8428,33 @@ function activeReadonlyAssignedCount(meshId) {
|
|
|
8292
8428
|
function nodeHasActiveAssignment(meshId, nodeId) {
|
|
8293
8429
|
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
8294
8430
|
}
|
|
8431
|
+
function nodeActiveLoad(meshId, nodeId) {
|
|
8432
|
+
return MeshRuntimeStore.getInstance().nodeActiveAssignmentCount(meshId, nodeId);
|
|
8433
|
+
}
|
|
8434
|
+
function resolveSchedulingStrategy(mesh) {
|
|
8435
|
+
return normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
|
|
8436
|
+
}
|
|
8437
|
+
function orderEligibleNodes(meshId, strategy, nodes, opts) {
|
|
8438
|
+
if (strategy === "first_eligible" || nodes.length <= 1) {
|
|
8439
|
+
return nodes;
|
|
8440
|
+
}
|
|
8441
|
+
const priorityOf = (n) => resolveNodeSchedulingPriority(n.node?.policy);
|
|
8442
|
+
let rotation = 0;
|
|
8443
|
+
if (strategy === "round_robin") {
|
|
8444
|
+
const cursor = opts?.bumpCursor ? MeshRuntimeStore.getInstance().bumpSchedulerCursor(meshId) : MeshRuntimeStore.getInstance().getSchedulerCursor(meshId);
|
|
8445
|
+
rotation = (cursor % nodes.length + nodes.length) % nodes.length;
|
|
8446
|
+
}
|
|
8447
|
+
const rotationRank = (index) => (index - rotation + nodes.length) % nodes.length;
|
|
8448
|
+
return [...nodes].sort((a, b) => {
|
|
8449
|
+
const prioDelta = priorityOf(b) - priorityOf(a);
|
|
8450
|
+
if (prioDelta !== 0) return prioDelta;
|
|
8451
|
+
if (strategy === "least_loaded" || strategy === "round_robin") {
|
|
8452
|
+
const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
|
|
8453
|
+
if (loadDelta !== 0) return loadDelta;
|
|
8454
|
+
}
|
|
8455
|
+
return rotationRank(a.index) - rotationRank(b.index);
|
|
8456
|
+
});
|
|
8457
|
+
}
|
|
8295
8458
|
function activeProviderAssignedCount(meshId, nodeId, providerType) {
|
|
8296
8459
|
return getQueue(meshId, { status: ["assigned"] }).filter((task) => task.assignedNodeId === nodeId && task.assignedProviderType === providerType).length;
|
|
8297
8460
|
}
|
|
@@ -8428,7 +8591,14 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
8428
8591
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "no_node_satisfies_required_tags", nodeId: task.targetNodeId });
|
|
8429
8592
|
continue;
|
|
8430
8593
|
}
|
|
8431
|
-
|
|
8594
|
+
const strategy = resolveSchedulingStrategy(mesh);
|
|
8595
|
+
const orderedCandidateNodes = strategy === "first_eligible" ? candidateNodes : orderEligibleNodes(
|
|
8596
|
+
meshId,
|
|
8597
|
+
strategy,
|
|
8598
|
+
candidateNodes.map((node, index) => ({ nodeId: readMeshNodeId(node), node, index })).filter((c) => c.nodeId),
|
|
8599
|
+
{ bumpCursor: true }
|
|
8600
|
+
).map((c) => c.node);
|
|
8601
|
+
for (const node of orderedCandidateNodes) {
|
|
8432
8602
|
const nodeId = readMeshNodeId(node);
|
|
8433
8603
|
if (!nodeId) continue;
|
|
8434
8604
|
const launchKey = `${meshId}:${nodeId}`;
|
|
@@ -8555,6 +8725,8 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
8555
8725
|
noIdleMeshSessionAvailable: true
|
|
8556
8726
|
};
|
|
8557
8727
|
}
|
|
8728
|
+
const strategy = resolveSchedulingStrategy(mesh);
|
|
8729
|
+
const localCandidates = [];
|
|
8558
8730
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
8559
8731
|
for (const inst of cliInstances) {
|
|
8560
8732
|
const state = inst.getState();
|
|
@@ -8577,7 +8749,7 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
8577
8749
|
const providerType = state.type || readNonEmptyString2(settings.providerType);
|
|
8578
8750
|
if (providerType) {
|
|
8579
8751
|
localIdleSessionsChecked += 1;
|
|
8580
|
-
|
|
8752
|
+
localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => readMeshNodeId(n) === nodeId) });
|
|
8581
8753
|
} else {
|
|
8582
8754
|
skippedSessions.push({
|
|
8583
8755
|
nodeId,
|
|
@@ -8591,18 +8763,49 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
8591
8763
|
remoteSessions = MeshRuntimeStore.getInstance().getRemoteIdleSessions();
|
|
8592
8764
|
} catch {
|
|
8593
8765
|
}
|
|
8766
|
+
const remoteCandidates = [];
|
|
8594
8767
|
for (const idle of remoteSessions) {
|
|
8595
8768
|
const node = mesh.nodes.find((n) => n.id === idle.nodeId);
|
|
8596
8769
|
if (node) {
|
|
8597
8770
|
remoteIdleSessionsChecked += 1;
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8771
|
+
remoteCandidates.push({ nodeId: idle.nodeId, sessionId: idle.sessionId, providerType: idle.providerType, origin: "remote", node });
|
|
8772
|
+
}
|
|
8773
|
+
}
|
|
8774
|
+
const assignIdleCandidate = (candidate) => {
|
|
8775
|
+
const assigned = tryAssignQueueTask(components, meshId, candidate.nodeId, candidate.sessionId, candidate.providerType);
|
|
8776
|
+
if (assigned && candidate.origin === "remote") {
|
|
8777
|
+
try {
|
|
8778
|
+
MeshRuntimeStore.getInstance().deleteRemoteIdleSession(candidate.nodeId, candidate.sessionId);
|
|
8779
|
+
} catch {
|
|
8604
8780
|
}
|
|
8605
8781
|
}
|
|
8782
|
+
};
|
|
8783
|
+
if (strategy === "first_eligible") {
|
|
8784
|
+
for (const candidate of localCandidates) assignIdleCandidate(candidate);
|
|
8785
|
+
for (const candidate of remoteCandidates) assignIdleCandidate(candidate);
|
|
8786
|
+
} else {
|
|
8787
|
+
const pool = [...localCandidates, ...remoteCandidates];
|
|
8788
|
+
const baseIndex = /* @__PURE__ */ new Map();
|
|
8789
|
+
pool.forEach((c, i) => {
|
|
8790
|
+
if (!baseIndex.has(c.nodeId)) baseIndex.set(c.nodeId, i);
|
|
8791
|
+
});
|
|
8792
|
+
const uniqueNodes = [...new Set(pool.map((c) => c.nodeId))].map((nodeId, index) => ({ nodeId, node: pool.find((c) => c.nodeId === nodeId)?.node, index }));
|
|
8793
|
+
const ranked = orderEligibleNodes(meshId, strategy, uniqueNodes, { bumpCursor: true });
|
|
8794
|
+
const rankIndex = new Map(ranked.map((r, i) => [r.nodeId, i]));
|
|
8795
|
+
const remaining = [...pool];
|
|
8796
|
+
while (remaining.length > 0) {
|
|
8797
|
+
remaining.sort((a, b) => {
|
|
8798
|
+
const aPrio = resolveNodeSchedulingPriority(a.node?.policy);
|
|
8799
|
+
const bPrio = resolveNodeSchedulingPriority(b.node?.policy);
|
|
8800
|
+
if (aPrio !== bPrio) return bPrio - aPrio;
|
|
8801
|
+
if (strategy === "least_loaded" || strategy === "round_robin") {
|
|
8802
|
+
const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
|
|
8803
|
+
if (loadDelta !== 0) return loadDelta;
|
|
8804
|
+
}
|
|
8805
|
+
return (rankIndex.get(a.nodeId) ?? 0) - (rankIndex.get(b.nodeId) ?? 0);
|
|
8806
|
+
});
|
|
8807
|
+
assignIdleCandidate(remaining.shift());
|
|
8808
|
+
}
|
|
8606
8809
|
}
|
|
8607
8810
|
autoLaunchStarted = await maybeAutoLaunchOneQueueSession(components, meshId, mesh);
|
|
8608
8811
|
const afterQueue = getQueue(meshId);
|
|
@@ -11976,7 +12179,7 @@ var init_cli_state_engine = __esm({
|
|
|
11976
12179
|
scheduleSettle() {
|
|
11977
12180
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
11978
12181
|
const epoch = this.responseEpoch;
|
|
11979
|
-
const
|
|
12182
|
+
const delay2 = Math.max(
|
|
11980
12183
|
this.timeouts.outputSettle,
|
|
11981
12184
|
this.submitPendingUntil > Date.now() ? this.submitPendingUntil - Date.now() + this.timeouts.outputSettle : 0
|
|
11982
12185
|
);
|
|
@@ -11984,7 +12187,7 @@ var init_cli_state_engine = __esm({
|
|
|
11984
12187
|
this.settleTimer = null;
|
|
11985
12188
|
if (epoch !== this.responseEpoch) return;
|
|
11986
12189
|
this.evaluateSettled(this.transport.getSnapshot());
|
|
11987
|
-
},
|
|
12190
|
+
}, delay2);
|
|
11988
12191
|
}
|
|
11989
12192
|
/** Called from sendMessage in transport once a turn scope is established. */
|
|
11990
12193
|
onTurnStarted(turnScope) {
|
|
@@ -15492,6 +15695,7 @@ __export(index_exports, {
|
|
|
15492
15695
|
DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
15493
15696
|
DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
15494
15697
|
DEFAULT_MESH_POLICY: () => DEFAULT_MESH_POLICY,
|
|
15698
|
+
DEFAULT_MESH_SCHEDULING_STRATEGY: () => DEFAULT_MESH_SCHEDULING_STRATEGY,
|
|
15495
15699
|
DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
|
|
15496
15700
|
DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
15497
15701
|
DEFAULT_SESSION_HOST_READY_TIMEOUT_MS: () => DEFAULT_SESSION_HOST_READY_TIMEOUT_MS,
|
|
@@ -15517,9 +15721,12 @@ __export(index_exports, {
|
|
|
15517
15721
|
InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
|
|
15518
15722
|
LOG: () => LOG,
|
|
15519
15723
|
MAX_LEDGER_SLICE_LIMIT: () => MAX_LEDGER_SLICE_LIMIT,
|
|
15724
|
+
MESH_CONVERGE_FAST_FORWARD_TAG: () => MESH_CONVERGE_FAST_FORWARD_TAG,
|
|
15725
|
+
MESH_CONVERGE_REFINE_TAG: () => MESH_CONVERGE_REFINE_TAG,
|
|
15520
15726
|
MESH_MISSION_STATUSES: () => MESH_MISSION_STATUSES,
|
|
15521
15727
|
MESH_REFINE_CONFIG_LOCATIONS: () => MESH_REFINE_CONFIG_LOCATIONS,
|
|
15522
15728
|
MESH_REFINE_CONFIG_SCHEMA: () => MESH_REFINE_CONFIG_SCHEMA,
|
|
15729
|
+
MESH_SCHEDULING_STRATEGIES: () => MESH_SCHEDULING_STRATEGIES,
|
|
15523
15730
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
|
|
15524
15731
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
|
|
15525
15732
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
@@ -15720,6 +15927,7 @@ __export(index_exports, {
|
|
|
15720
15927
|
normalizeManagedStatus: () => normalizeManagedStatus,
|
|
15721
15928
|
normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
|
|
15722
15929
|
normalizeMeshDaemonRole: () => normalizeMeshDaemonRole,
|
|
15930
|
+
normalizeMeshSchedulingStrategy: () => normalizeMeshSchedulingStrategy,
|
|
15723
15931
|
normalizeMeshTaskMode: () => normalizeMeshTaskMode,
|
|
15724
15932
|
normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
|
|
15725
15933
|
normalizeMessageParts: () => normalizeMessageParts,
|
|
@@ -15757,7 +15965,9 @@ __export(index_exports, {
|
|
|
15757
15965
|
resetConfig: () => resetConfig,
|
|
15758
15966
|
resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
|
|
15759
15967
|
resetState: () => resetState,
|
|
15968
|
+
resolveAutoConvergeCodeChange: () => resolveAutoConvergeCodeChange,
|
|
15760
15969
|
resolveChatMessageKind: () => resolveChatMessageKind,
|
|
15970
|
+
resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
|
|
15761
15971
|
resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
|
|
15762
15972
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
15763
15973
|
resolveDelegatedWorkerAutoApprove: () => resolveDelegatedWorkerAutoApprove,
|
|
@@ -15765,6 +15975,7 @@ __export(index_exports, {
|
|
|
15765
15975
|
resolveGitRepository: () => resolveGitRepository,
|
|
15766
15976
|
resolveMeshHostStatus: () => resolveMeshHostStatus,
|
|
15767
15977
|
resolveMeshRefineValidationPlan: () => resolveMeshRefineValidationPlan,
|
|
15978
|
+
resolveNodeSchedulingPriority: () => resolveNodeSchedulingPriority,
|
|
15768
15979
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
15769
15980
|
resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
|
|
15770
15981
|
resolveWorktreePath: () => resolveWorktreePath,
|
|
@@ -18139,9 +18350,9 @@ function readString6(value) {
|
|
|
18139
18350
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
18140
18351
|
}
|
|
18141
18352
|
function summarizeMessage(message) {
|
|
18142
|
-
const
|
|
18143
|
-
const title =
|
|
18144
|
-
return { title: title || "(untitled task)", summary:
|
|
18353
|
+
const oneLine2 = message.replace(/\s+/g, " ").trim();
|
|
18354
|
+
const title = oneLine2.length > 96 ? `${oneLine2.slice(0, 93)}...` : oneLine2;
|
|
18355
|
+
return { title: title || "(untitled task)", summary: oneLine2 };
|
|
18145
18356
|
}
|
|
18146
18357
|
function elapsedSince(value, now) {
|
|
18147
18358
|
const started = value ? new Date(value).getTime() : Number.NaN;
|
|
@@ -21247,6 +21458,11 @@ function collapseReplayAssistantTurns(messages, historyBehavior) {
|
|
|
21247
21458
|
continue;
|
|
21248
21459
|
}
|
|
21249
21460
|
if (message.role === "assistant") {
|
|
21461
|
+
const isActivity = message.kind === "tool" || message.kind === "terminal" || message.kind === "thought";
|
|
21462
|
+
if (isActivity) {
|
|
21463
|
+
collapsed.push(message);
|
|
21464
|
+
continue;
|
|
21465
|
+
}
|
|
21250
21466
|
if (sawAssistantSinceLastUser) continue;
|
|
21251
21467
|
sawAssistantSinceLastUser = true;
|
|
21252
21468
|
collapsed.push(message);
|
|
@@ -26390,7 +26606,8 @@ function buildReadChatCommandResult(payload, args, h) {
|
|
|
26390
26606
|
const sessionIdHint = typeof args?.targetSessionId === "string" ? args.targetSessionId : typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
26391
26607
|
const providerHint = typeof args?.cliType === "string" ? args.cliType : typeof args?.providerType === "string" ? args.providerType : typeof args?.agentType === "string" ? args.agentType : "";
|
|
26392
26608
|
const filteredMessages = h ? maybeHideCoordinatorPromptMessage(h, providerHint, sessionIdHint, messages) : messages;
|
|
26393
|
-
const
|
|
26609
|
+
const includeActivity = args?.includeActivity === true || args?.includeActivity === "true";
|
|
26610
|
+
const visibleMessages = includeActivity ? filteredMessages.filter((m) => isUserFacingChatMessage(m) || isActivityChatMessage(m)) : filterUserFacingChatMessages(filteredMessages);
|
|
26394
26611
|
const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
|
|
26395
26612
|
const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
|
|
26396
26613
|
const preservedPayloadFields = Object.fromEntries(Object.entries(payload).filter(([key]) => shouldPreserveReadChatPayloadField(key)));
|
|
@@ -28759,6 +28976,9 @@ function normalizeProviderScriptArgs(args, scriptName) {
|
|
|
28759
28976
|
}
|
|
28760
28977
|
function buildControlScriptResult(scriptName, payload) {
|
|
28761
28978
|
if (!payload || typeof payload !== "object") return {};
|
|
28979
|
+
if (payload.controlResult && typeof payload.controlResult === "object") {
|
|
28980
|
+
return { controlResult: payload.controlResult };
|
|
28981
|
+
}
|
|
28762
28982
|
const legacyListPayload = (() => {
|
|
28763
28983
|
if (Array.isArray(payload.options)) return payload;
|
|
28764
28984
|
if (/^listmodels$/i.test(scriptName) && Array.isArray(payload.models)) {
|
|
@@ -30609,12 +30829,12 @@ var FsmDriver = class {
|
|
|
30609
30829
|
scheduleSpawnPrime() {
|
|
30610
30830
|
const seqs = this.spec.send_on_spawn;
|
|
30611
30831
|
if (!Array.isArray(seqs) || seqs.length === 0) return;
|
|
30612
|
-
const
|
|
30832
|
+
const delay2 = Math.max(0, this.spec.send_on_spawn_delay_ms ?? 250);
|
|
30613
30833
|
setTimeout(() => {
|
|
30614
30834
|
for (const seq of seqs) {
|
|
30615
30835
|
if (typeof seq === "string" && seq.length > 0) this.adapter.send_keys(seq);
|
|
30616
30836
|
}
|
|
30617
|
-
},
|
|
30837
|
+
}, delay2);
|
|
30618
30838
|
}
|
|
30619
30839
|
dispatch(cmd) {
|
|
30620
30840
|
switch (cmd.kind) {
|
|
@@ -30980,11 +31200,11 @@ var FsmDriver = class {
|
|
|
30980
31200
|
const armed = this.delegateTimers.has(d.id);
|
|
30981
31201
|
const shouldFire = d.when_state === currentStateId;
|
|
30982
31202
|
if (shouldFire && !armed) {
|
|
30983
|
-
const
|
|
31203
|
+
const delay2 = d.after_duration_ms ?? 0;
|
|
30984
31204
|
const t = setTimeout(() => {
|
|
30985
31205
|
this.fireDelegate(d);
|
|
30986
31206
|
this.delegateTimers.delete(d.id);
|
|
30987
|
-
},
|
|
31207
|
+
}, delay2);
|
|
30988
31208
|
this.delegateTimers.set(d.id, t);
|
|
30989
31209
|
} else if (!shouldFire && armed) {
|
|
30990
31210
|
clearTimeout(this.delegateTimers.get(d.id));
|
|
@@ -31038,7 +31258,15 @@ var FsmDriver = class {
|
|
|
31038
31258
|
this.adapter.send_keys(a.keys);
|
|
31039
31259
|
return;
|
|
31040
31260
|
case "open_picker":
|
|
31041
|
-
|
|
31261
|
+
{
|
|
31262
|
+
const m = /^([\s\S]*?)([\r\n]+)$/.exec(a.trigger_keys);
|
|
31263
|
+
if (m && m[1]) {
|
|
31264
|
+
this.adapter.send_keys(m[1]);
|
|
31265
|
+
setTimeout(() => this.adapter.send_keys(m[2]), 200);
|
|
31266
|
+
} else {
|
|
31267
|
+
this.adapter.send_keys(a.trigger_keys);
|
|
31268
|
+
}
|
|
31269
|
+
}
|
|
31042
31270
|
this.pickerInProgress = { control_id: ctl.id, spec: ctl };
|
|
31043
31271
|
return;
|
|
31044
31272
|
case "attach_image": {
|
|
@@ -31223,8 +31451,7 @@ function executeJsonl(src, input) {
|
|
|
31223
31451
|
for (let i = 0; i < lines.length; i += 1) {
|
|
31224
31452
|
const rec = lines[i];
|
|
31225
31453
|
if (filter && !filter(rec)) continue;
|
|
31226
|
-
const msg
|
|
31227
|
-
if (msg) {
|
|
31454
|
+
for (const msg of projectMessages(rec, src.message_map, i, lines.length, mtime)) {
|
|
31228
31455
|
if (transcriptWorkspace) msg.workspace = transcriptWorkspace;
|
|
31229
31456
|
messages.push(msg);
|
|
31230
31457
|
}
|
|
@@ -31304,8 +31531,9 @@ function executeSqlite(src, input) {
|
|
|
31304
31531
|
const mtime = safeMtimeMs(resolved);
|
|
31305
31532
|
const messages = [];
|
|
31306
31533
|
for (let i = 0; i < messageRows.length; i += 1) {
|
|
31307
|
-
const msg
|
|
31308
|
-
|
|
31534
|
+
for (const msg of projectMessages(messageRows[i], src.message_map, i, messageRows.length, mtime)) {
|
|
31535
|
+
messages.push(msg);
|
|
31536
|
+
}
|
|
31309
31537
|
}
|
|
31310
31538
|
if (messages.length === 0) return null;
|
|
31311
31539
|
return {
|
|
@@ -31703,11 +31931,42 @@ function jsonPathGet(record, expr) {
|
|
|
31703
31931
|
}
|
|
31704
31932
|
return cur;
|
|
31705
31933
|
}
|
|
31706
|
-
function
|
|
31934
|
+
function projectMessages(record, map, index, total, sourceMtimeMs) {
|
|
31707
31935
|
const roleRaw = jsonPathGet(record, map.role);
|
|
31708
|
-
const contentRaw = jsonPathGet(record, map.content);
|
|
31709
31936
|
const role = normalizeRole(roleRaw);
|
|
31710
|
-
let
|
|
31937
|
+
let receivedAt = sourceMtimeMs - (total - 1 - index) * 1e3;
|
|
31938
|
+
if (map.timestamp_ms) {
|
|
31939
|
+
const tsRaw = jsonPathGet(record, map.timestamp_ms);
|
|
31940
|
+
const parsed = parseTimestamp(tsRaw);
|
|
31941
|
+
if (parsed != null) receivedAt = parsed;
|
|
31942
|
+
}
|
|
31943
|
+
const kindRaw = map.kind ? jsonPathGet(record, map.kind) : void 0;
|
|
31944
|
+
const kind = typeof kindRaw === "string" && kindRaw ? kindRaw : "standard";
|
|
31945
|
+
const out = [];
|
|
31946
|
+
if (map.tools) {
|
|
31947
|
+
const recordTool = projectToolBlock(record, role, map.tools);
|
|
31948
|
+
if (recordTool) {
|
|
31949
|
+
out.push({ ...recordTool, receivedAt });
|
|
31950
|
+
return out;
|
|
31951
|
+
}
|
|
31952
|
+
}
|
|
31953
|
+
const contentRaw = jsonPathGet(record, map.content);
|
|
31954
|
+
const content = cleanContent(stringifyContent(contentRaw), map);
|
|
31955
|
+
if (content) out.push({ role, content, receivedAt, kind });
|
|
31956
|
+
if (map.tools && Array.isArray(contentRaw)) {
|
|
31957
|
+
let nudge = 1;
|
|
31958
|
+
for (const block2 of contentRaw) {
|
|
31959
|
+
const tool = projectToolBlock(block2, role, map.tools);
|
|
31960
|
+
if (tool) {
|
|
31961
|
+
out.push({ ...tool, receivedAt: receivedAt + nudge });
|
|
31962
|
+
nudge += 1;
|
|
31963
|
+
}
|
|
31964
|
+
}
|
|
31965
|
+
}
|
|
31966
|
+
return out;
|
|
31967
|
+
}
|
|
31968
|
+
function cleanContent(input, map) {
|
|
31969
|
+
let content = input;
|
|
31711
31970
|
if (content && map.content_strip) {
|
|
31712
31971
|
for (const tag of map.content_strip) {
|
|
31713
31972
|
const safeTag = tag.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
@@ -31723,17 +31982,33 @@ function projectMessage(record, map, index, total, sourceMtimeMs) {
|
|
|
31723
31982
|
content = content.replace(open, "").replace(close, "");
|
|
31724
31983
|
}
|
|
31725
31984
|
}
|
|
31726
|
-
|
|
31727
|
-
|
|
31728
|
-
|
|
31729
|
-
|
|
31730
|
-
|
|
31731
|
-
|
|
31732
|
-
|
|
31985
|
+
return content ? content.trim() : "";
|
|
31986
|
+
}
|
|
31987
|
+
var DEFAULT_TOOL_CALL_TYPES = ["tool_use", "function_call", "custom_tool_call"];
|
|
31988
|
+
var DEFAULT_TOOL_RESULT_TYPES = ["tool_result", "function_call_output", "custom_tool_call_output"];
|
|
31989
|
+
function projectToolBlock(block2, role, tmap) {
|
|
31990
|
+
void role;
|
|
31991
|
+
if (block2 == null || typeof block2 !== "object") return null;
|
|
31992
|
+
const typeVal = String(jsonPathGet(block2, tmap.block_type || "$.type") ?? "");
|
|
31993
|
+
if (!typeVal) return null;
|
|
31994
|
+
const callTypes = tmap.call_types ?? DEFAULT_TOOL_CALL_TYPES;
|
|
31995
|
+
const resultTypes = tmap.result_types ?? DEFAULT_TOOL_RESULT_TYPES;
|
|
31996
|
+
if (callTypes.includes(typeVal)) {
|
|
31997
|
+
const name = String(jsonPathGet(block2, tmap.call_name || "$.name") ?? "tool").trim() || "tool";
|
|
31998
|
+
const args = oneLine(stringifyContent(jsonPathGet(block2, tmap.call_args || "$.input")), 240);
|
|
31999
|
+
const content = args ? `\u2197 ${name}: ${args}` : `\u2197 ${name}`;
|
|
32000
|
+
return { role: "assistant", content, receivedAt: 0, kind: "tool" };
|
|
32001
|
+
}
|
|
32002
|
+
if (resultTypes.includes(typeVal)) {
|
|
32003
|
+
const result = oneLine(stringifyContent(jsonPathGet(block2, tmap.result_content || "$.content")), 600);
|
|
32004
|
+
if (!result) return null;
|
|
32005
|
+
return { role: "assistant", content: `\u2198 ${result}`, receivedAt: 0, kind: "tool" };
|
|
31733
32006
|
}
|
|
31734
|
-
|
|
31735
|
-
|
|
31736
|
-
|
|
32007
|
+
return null;
|
|
32008
|
+
}
|
|
32009
|
+
function oneLine(s, max) {
|
|
32010
|
+
const flat = s.replace(/\s+/g, " ").trim();
|
|
32011
|
+
return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
|
|
31737
32012
|
}
|
|
31738
32013
|
function parseTimestamp(v) {
|
|
31739
32014
|
if (v == null) return null;
|
|
@@ -31874,6 +32149,9 @@ init_logger();
|
|
|
31874
32149
|
function stripAnsi3(text) {
|
|
31875
32150
|
return String(text || "").replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
31876
32151
|
}
|
|
32152
|
+
function delay(ms) {
|
|
32153
|
+
return new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
32154
|
+
}
|
|
31877
32155
|
var SpecCliAdapter = class _SpecCliAdapter {
|
|
31878
32156
|
cliType;
|
|
31879
32157
|
cliName;
|
|
@@ -32095,9 +32373,15 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
32095
32373
|
* drives the dispatch:
|
|
32096
32374
|
*
|
|
32097
32375
|
* send_keys → click_control (e.g. stop)
|
|
32098
|
-
* open_picker →
|
|
32099
|
-
*
|
|
32100
|
-
*
|
|
32376
|
+
* open_picker → two roles, driven by the screen, not a hardcoded list:
|
|
32377
|
+
* - LIST (no choice arg): open the picker, wait for it
|
|
32378
|
+
* to render, parse the on-screen options via
|
|
32379
|
+
* `extract_choices`, and return them as
|
|
32380
|
+
* `controlResult.options` (+ `currentValue`). This is
|
|
32381
|
+
* how the dashboard's Model/Mode controls learn what is
|
|
32382
|
+
* actually selectable in this CLI right now.
|
|
32383
|
+
* - SELECT (args.choiceIndex / args.choiceLabel): drive
|
|
32384
|
+
* the picker to that option using `submit_key`.
|
|
32101
32385
|
* attach_image → attach_image dispatch; expects args.blob (data url
|
|
32102
32386
|
* or base64) and args.mime
|
|
32103
32387
|
*
|
|
@@ -32122,11 +32406,128 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
32122
32406
|
this.driver.dispatch({ kind: "attach_image", blob, mime });
|
|
32123
32407
|
return Promise.resolve({ ok: true, effects: [{ type: "attached_image", controlId: ctl.id }] });
|
|
32124
32408
|
}
|
|
32409
|
+
if (action.type === "open_picker") {
|
|
32410
|
+
const choiceIndex = typeof flat.choiceIndex === "number" ? flat.choiceIndex : typeof flat.choiceIndex === "string" && flat.choiceIndex.trim() ? Number(flat.choiceIndex) : void 0;
|
|
32411
|
+
const choiceLabel = typeof flat.choiceLabel === "string" ? flat.choiceLabel : typeof flat.choice === "string" ? flat.choice : void 0;
|
|
32412
|
+
if (typeof choiceIndex === "number" && Number.isFinite(choiceIndex) || choiceLabel && choiceLabel.trim()) {
|
|
32413
|
+
return this.selectPickerChoice(ctl, action, choiceIndex, choiceLabel);
|
|
32414
|
+
}
|
|
32415
|
+
return this.openPickerAndListChoices(ctl, action);
|
|
32416
|
+
}
|
|
32125
32417
|
this.driver.dispatch({ kind: "click_control", control_id: ctl.id, payload: flat });
|
|
32126
|
-
|
|
32127
|
-
|
|
32128
|
-
|
|
32129
|
-
|
|
32418
|
+
return Promise.resolve({ ok: true, effects: [{ type: "sent_keys", controlId: ctl.id }] });
|
|
32419
|
+
}
|
|
32420
|
+
/**
|
|
32421
|
+
* Open an `open_picker` control and return the options the CLI is showing,
|
|
32422
|
+
* parsed live from the screen via `extract_choices`. Nothing is selected —
|
|
32423
|
+
* the picker is left open so a follow-up SELECT invoke can commit a choice.
|
|
32424
|
+
*/
|
|
32425
|
+
async openPickerAndListChoices(ctl, action) {
|
|
32426
|
+
this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
|
|
32427
|
+
const ready = await this.waitForPickerRendered(action);
|
|
32428
|
+
const options = this.extractPickerChoices(action);
|
|
32429
|
+
const currentValue = options.find((o) => o.current)?.label;
|
|
32430
|
+
return {
|
|
32431
|
+
ok: true,
|
|
32432
|
+
effects: [{ type: "opened_picker", controlId: ctl.id }],
|
|
32433
|
+
controlResult: {
|
|
32434
|
+
options: options.map((o) => ({ value: o.label, label: o.label, current: o.current })),
|
|
32435
|
+
...currentValue ? { currentValue } : {},
|
|
32436
|
+
source: "screen-parse",
|
|
32437
|
+
...ready ? {} : { warning: "picker_render_timeout" }
|
|
32438
|
+
}
|
|
32439
|
+
};
|
|
32440
|
+
}
|
|
32441
|
+
/**
|
|
32442
|
+
* Drive an already-listable picker to a specific option. The option can be
|
|
32443
|
+
* named (choiceLabel — matched against the parsed on-screen labels) or
|
|
32444
|
+
* positional (choiceIndex — the on-screen number). The actual keystrokes
|
|
32445
|
+
* come from the spec's `submit_key` with `{index}` substituted, so the spec
|
|
32446
|
+
* — not this code — decides how a selection is keyed for each CLI.
|
|
32447
|
+
*/
|
|
32448
|
+
async selectPickerChoice(ctl, action, choiceIndex, choiceLabel) {
|
|
32449
|
+
this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
|
|
32450
|
+
await this.waitForPickerRendered(action);
|
|
32451
|
+
const options = this.extractPickerChoices(action);
|
|
32452
|
+
let index = choiceIndex;
|
|
32453
|
+
if ((index == null || !Number.isFinite(index)) && choiceLabel) {
|
|
32454
|
+
const needle = choiceLabel.trim().toLowerCase();
|
|
32455
|
+
const match = options.find((o) => o.label.toLowerCase().includes(needle));
|
|
32456
|
+
if (!match) {
|
|
32457
|
+
return { ok: false, error: `choice not found on screen: ${choiceLabel}`, controlResult: { options: options.map((o) => ({ value: o.label, label: o.label })) } };
|
|
32458
|
+
}
|
|
32459
|
+
index = match.index;
|
|
32460
|
+
}
|
|
32461
|
+
if (index == null || !Number.isFinite(index)) {
|
|
32462
|
+
return { ok: false, error: "choiceIndex or choiceLabel required to select" };
|
|
32463
|
+
}
|
|
32464
|
+
const keys = (action.submit_key || "{index}\r").replace(/\{index\}/g, String(index));
|
|
32465
|
+
this.driver.dispatch({ kind: "pty_write", data: keys });
|
|
32466
|
+
const selected = options.find((o) => o.index === index);
|
|
32467
|
+
return {
|
|
32468
|
+
ok: true,
|
|
32469
|
+
effects: [{ type: "selected_choice", controlId: ctl.id }],
|
|
32470
|
+
controlResult: {
|
|
32471
|
+
ok: true,
|
|
32472
|
+
...selected ? { currentValue: selected.label } : {},
|
|
32473
|
+
selectedIndex: index
|
|
32474
|
+
}
|
|
32475
|
+
};
|
|
32476
|
+
}
|
|
32477
|
+
/** Poll the live screen until the picker's `wait_for` condition matches,
|
|
32478
|
+
* up to a short budget. Returns true if it rendered, false on timeout. */
|
|
32479
|
+
async waitForPickerRendered(action) {
|
|
32480
|
+
const wf = action.wait_for;
|
|
32481
|
+
if (!wf?.regex) {
|
|
32482
|
+
await delay(250);
|
|
32483
|
+
return true;
|
|
32484
|
+
}
|
|
32485
|
+
const re = new RegExp(wf.regex, wf.flags ?? "i");
|
|
32486
|
+
const deadline = Date.now() + 2500;
|
|
32487
|
+
while (Date.now() < deadline) {
|
|
32488
|
+
await delay(120);
|
|
32489
|
+
const hay = this.readScreenSectionText(wf.section);
|
|
32490
|
+
if (re.test(hay)) return true;
|
|
32491
|
+
}
|
|
32492
|
+
return false;
|
|
32493
|
+
}
|
|
32494
|
+
/** Parse the picker's `extract_choices` pattern against the live screen.
|
|
32495
|
+
* Each match yields { index, label, current }. `current` is true for the
|
|
32496
|
+
* line the CLI marks with its cursor glyph (❯ ›). Purely screen-driven —
|
|
32497
|
+
* no model/mode names are baked in. */
|
|
32498
|
+
extractPickerChoices(action) {
|
|
32499
|
+
const ec = action.extract_choices;
|
|
32500
|
+
if (!ec?.pattern) return [];
|
|
32501
|
+
const text = this.readScreenSectionText(ec.section);
|
|
32502
|
+
const out = [];
|
|
32503
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32504
|
+
for (const rawLine of text.split("\n")) {
|
|
32505
|
+
const line = rawLine.replace(/\r$/, "");
|
|
32506
|
+
const m = new RegExp(ec.pattern, ec.flags ?? "").exec(line);
|
|
32507
|
+
if (!m) continue;
|
|
32508
|
+
const idx = Number(m[1]);
|
|
32509
|
+
if (!Number.isFinite(idx) || seen.has(idx)) continue;
|
|
32510
|
+
const label = (m[2] ?? "").replace(/\s+/g, " ").trim();
|
|
32511
|
+
if (!label) continue;
|
|
32512
|
+
const current = /^\s*[❯›>]/.test(line) || /[✔✓●]\s*$/.test(label);
|
|
32513
|
+
seen.add(idx);
|
|
32514
|
+
out.push({ index: idx, label, current });
|
|
32515
|
+
}
|
|
32516
|
+
return out;
|
|
32517
|
+
}
|
|
32518
|
+
/** Live text of a named screen section (or the whole screen when no
|
|
32519
|
+
* section is named), resolved from the driver's current sections. */
|
|
32520
|
+
readScreenSectionText(sectionId) {
|
|
32521
|
+
try {
|
|
32522
|
+
const sections = this.driver.getSections();
|
|
32523
|
+
if (sectionId && sections) {
|
|
32524
|
+
const hit = sections.find((s) => s.id === sectionId);
|
|
32525
|
+
if (hit) return hit.text;
|
|
32526
|
+
}
|
|
32527
|
+
return this.driver.getScreen();
|
|
32528
|
+
} catch {
|
|
32529
|
+
return "";
|
|
32530
|
+
}
|
|
32130
32531
|
}
|
|
32131
32532
|
getDebugSnapshot() {
|
|
32132
32533
|
let screen = "";
|
|
@@ -42342,6 +42743,43 @@ function readMeshTimeoutEnvMs(name, defaultMs) {
|
|
|
42342
42743
|
}
|
|
42343
42744
|
var MESH_DIRECT_PROBE_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_TIMEOUT_MS", 25e3);
|
|
42344
42745
|
var MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS", 25e3);
|
|
42746
|
+
var MESH_DIRECT_PROBE_REUSE_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_REUSE_MS", 12e3);
|
|
42747
|
+
var MeshGitProbeCache = class {
|
|
42748
|
+
constructor(reuseMs, now = Date.now) {
|
|
42749
|
+
this.reuseMs = reuseMs;
|
|
42750
|
+
this.now = now;
|
|
42751
|
+
}
|
|
42752
|
+
inflight = /* @__PURE__ */ new Map();
|
|
42753
|
+
recent = /* @__PURE__ */ new Map();
|
|
42754
|
+
key(daemonId, workspace) {
|
|
42755
|
+
return `${daemonId}::${workspace}`;
|
|
42756
|
+
}
|
|
42757
|
+
/**
|
|
42758
|
+
* Run `probe` for this peer, but reuse a fresh recent result or an in-flight
|
|
42759
|
+
* probe for the same key when one is available. `probe` is only invoked when
|
|
42760
|
+
* neither gate is satisfied.
|
|
42761
|
+
*/
|
|
42762
|
+
async probe(daemonId, workspace, probe) {
|
|
42763
|
+
const key = this.key(daemonId, workspace);
|
|
42764
|
+
const cached2 = this.recent.get(key);
|
|
42765
|
+
if (cached2 && this.now() - cached2.at < this.reuseMs) {
|
|
42766
|
+
return cached2.value;
|
|
42767
|
+
}
|
|
42768
|
+
const existing = this.inflight.get(key);
|
|
42769
|
+
if (existing) return existing;
|
|
42770
|
+
const pending = (async () => {
|
|
42771
|
+
const result = await probe();
|
|
42772
|
+
if (result) this.recent.set(key, { at: this.now(), value: result });
|
|
42773
|
+
return result;
|
|
42774
|
+
})();
|
|
42775
|
+
this.inflight.set(key, pending);
|
|
42776
|
+
try {
|
|
42777
|
+
return await pending;
|
|
42778
|
+
} finally {
|
|
42779
|
+
if (this.inflight.get(key) === pending) this.inflight.delete(key);
|
|
42780
|
+
}
|
|
42781
|
+
}
|
|
42782
|
+
};
|
|
42345
42783
|
async function probeRemoteMeshGitStatus(args) {
|
|
42346
42784
|
if (!args.dispatchMeshCommand) return null;
|
|
42347
42785
|
const remoteResult = await Promise.race([
|
|
@@ -42435,7 +42873,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42435
42873
|
continue;
|
|
42436
42874
|
}
|
|
42437
42875
|
peerAttemptedCount += 1;
|
|
42438
|
-
const
|
|
42876
|
+
const runProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
42439
42877
|
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
42440
42878
|
daemonId,
|
|
42441
42879
|
workspace,
|
|
@@ -42443,6 +42881,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42443
42881
|
retryTimeoutMs: MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
|
|
42444
42882
|
getConnection: args.getMeshPeerConnectionStatus
|
|
42445
42883
|
});
|
|
42884
|
+
const remoteGit = args.probeCache ? await args.probeCache.probe(daemonId, workspace, runProbe) : await runProbe();
|
|
42446
42885
|
if (remoteGit) {
|
|
42447
42886
|
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
42448
42887
|
peerConfirmedCount += 1;
|
|
@@ -43765,6 +44204,10 @@ var DaemonCommandRouter = class {
|
|
|
43765
44204
|
inlineMeshCache = /* @__PURE__ */ new Map();
|
|
43766
44205
|
/** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
|
|
43767
44206
|
aggregateMeshStatusCache = /* @__PURE__ */ new Map();
|
|
44207
|
+
/** Shared per-peer git_status probe dedup + recently-probed reuse gate.
|
|
44208
|
+
* Spans separate mesh_status/get_mesh calls so the dashboard auto-retry
|
|
44209
|
+
* loop cannot storm a slow peer with back-to-back refreshUpstream probes. */
|
|
44210
|
+
meshGitProbeCache = new MeshGitProbeCache(MESH_DIRECT_PROBE_REUSE_MS);
|
|
43768
44211
|
/** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
|
|
43769
44212
|
runningRefineJobs = /* @__PURE__ */ new Map();
|
|
43770
44213
|
/** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
|
|
@@ -46667,7 +47110,8 @@ ${hintLines.join("\n")}` : "",
|
|
|
46667
47110
|
getMeshPeerConnectionStatus: this.deps.getMeshPeerConnectionStatus,
|
|
46668
47111
|
statusInstanceId: this.deps.statusInstanceId,
|
|
46669
47112
|
localMachineId: loadConfig().machineId || "",
|
|
46670
|
-
probeRemotePeers
|
|
47113
|
+
probeRemotePeers,
|
|
47114
|
+
probeCache: this.meshGitProbeCache
|
|
46671
47115
|
});
|
|
46672
47116
|
const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
|
|
46673
47117
|
const sourceOfTruth = {
|
|
@@ -47271,6 +47715,22 @@ ${hintLines.join("\n")}` : "",
|
|
|
47271
47715
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47272
47716
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
47273
47717
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
47718
|
+
{
|
|
47719
|
+
const meshRecordForForward = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
47720
|
+
const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
47721
|
+
const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
|
|
47722
|
+
const selfDaemonId = this.deps.statusInstanceId;
|
|
47723
|
+
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
|
|
47724
|
+
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
47725
|
+
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
47726
|
+
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
|
|
47727
|
+
...typeof args === "object" && args !== null ? args : {},
|
|
47728
|
+
coordinatorDaemonId: callerCoordinatorDaemonId || selfDaemonId,
|
|
47729
|
+
_meshDirectDispatch: true
|
|
47730
|
+
});
|
|
47731
|
+
return forwarded ?? { success: false, error: "no response from remote node" };
|
|
47732
|
+
}
|
|
47733
|
+
}
|
|
47274
47734
|
const isDryRun = args?.dryRun !== false && args?.execute !== true;
|
|
47275
47735
|
if (isDryRun) {
|
|
47276
47736
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
@@ -48243,6 +48703,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48243
48703
|
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
48244
48704
|
const localMachineId = loadConfig().machineId || "";
|
|
48245
48705
|
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
48706
|
+
const meshGitProbeCache = this.meshGitProbeCache;
|
|
48246
48707
|
const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
|
|
48247
48708
|
mesh,
|
|
48248
48709
|
meshSource: meshRecord.source,
|
|
@@ -48253,7 +48714,8 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48253
48714
|
// Standing-state model: only an explicit refresh fans
|
|
48254
48715
|
// out a blocking peer git probe. Default loads return
|
|
48255
48716
|
// held truth so one slow peer can't block the graph.
|
|
48256
|
-
probeRemotePeers: refreshRequested
|
|
48717
|
+
probeRemotePeers: refreshRequested,
|
|
48718
|
+
probeCache: meshGitProbeCache
|
|
48257
48719
|
}) : {
|
|
48258
48720
|
directEvidenceCount: 0,
|
|
48259
48721
|
localConfirmedCount: 0,
|
|
@@ -48414,7 +48876,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48414
48876
|
}
|
|
48415
48877
|
remoteProbeApplied = true;
|
|
48416
48878
|
} else if (refreshRequested && !isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
|
|
48417
|
-
const
|
|
48879
|
+
const runNodeProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
48418
48880
|
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
48419
48881
|
daemonId,
|
|
48420
48882
|
workspace,
|
|
@@ -48425,6 +48887,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48425
48887
|
status.connection = connection;
|
|
48426
48888
|
}
|
|
48427
48889
|
});
|
|
48890
|
+
const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
|
|
48428
48891
|
if (remoteGit) {
|
|
48429
48892
|
status.git = remoteGit;
|
|
48430
48893
|
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
@@ -57242,6 +57705,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57242
57705
|
DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
57243
57706
|
DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
57244
57707
|
DEFAULT_MESH_POLICY,
|
|
57708
|
+
DEFAULT_MESH_SCHEDULING_STRATEGY,
|
|
57245
57709
|
DEFAULT_SESSION_HOST_APP_NAME,
|
|
57246
57710
|
DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
57247
57711
|
DEFAULT_SESSION_HOST_READY_TIMEOUT_MS,
|
|
@@ -57267,9 +57731,12 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57267
57731
|
InMemoryGitSnapshotStore,
|
|
57268
57732
|
LOG,
|
|
57269
57733
|
MAX_LEDGER_SLICE_LIMIT,
|
|
57734
|
+
MESH_CONVERGE_FAST_FORWARD_TAG,
|
|
57735
|
+
MESH_CONVERGE_REFINE_TAG,
|
|
57270
57736
|
MESH_MISSION_STATUSES,
|
|
57271
57737
|
MESH_REFINE_CONFIG_LOCATIONS,
|
|
57272
57738
|
MESH_REFINE_CONFIG_SCHEMA,
|
|
57739
|
+
MESH_SCHEDULING_STRATEGIES,
|
|
57273
57740
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
|
|
57274
57741
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
|
|
57275
57742
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
@@ -57470,6 +57937,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57470
57937
|
normalizeManagedStatus,
|
|
57471
57938
|
normalizeMeshCapabilityTags,
|
|
57472
57939
|
normalizeMeshDaemonRole,
|
|
57940
|
+
normalizeMeshSchedulingStrategy,
|
|
57473
57941
|
normalizeMeshTaskMode,
|
|
57474
57942
|
normalizeMeshWorkerResult,
|
|
57475
57943
|
normalizeMessageParts,
|
|
@@ -57507,7 +57975,9 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57507
57975
|
resetConfig,
|
|
57508
57976
|
resetDebugRuntimeConfig,
|
|
57509
57977
|
resetState,
|
|
57978
|
+
resolveAutoConvergeCodeChange,
|
|
57510
57979
|
resolveChatMessageKind,
|
|
57980
|
+
resolveConvergeRequiredTags,
|
|
57511
57981
|
resolveCurrentGlobalInstallSurface,
|
|
57512
57982
|
resolveDebugRuntimeConfig,
|
|
57513
57983
|
resolveDelegatedWorkerAutoApprove,
|
|
@@ -57515,6 +57985,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57515
57985
|
resolveGitRepository,
|
|
57516
57986
|
resolveMeshHostStatus,
|
|
57517
57987
|
resolveMeshRefineValidationPlan,
|
|
57988
|
+
resolveNodeSchedulingPriority,
|
|
57518
57989
|
resolveSessionHostAppName,
|
|
57519
57990
|
resolveSessionHostAppNameResolution,
|
|
57520
57991
|
resolveWorktreePath,
|