@adhdev/daemon-core 0.9.82-rc.310 → 0.9.82-rc.312
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 +19 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1070 -263
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1069 -270
- package/dist/index.mjs.map +1 -1
- package/dist/logging/log-redactor.d.ts +24 -0
- package/dist/logging/log-tail-reader.d.ts +46 -0
- 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 +103 -9
- package/package.json +2 -2
- package/src/commands/chat-commands.ts +10 -2
- package/src/commands/router.ts +323 -6
- 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 +16 -2
- package/src/logging/log-redactor.ts +100 -0
- package/src/logging/log-tail-reader.ts +220 -0
- package/src/mesh/coordinator-prompt.ts +1 -0
- 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 +134 -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 ? "35facf0367dbbe37f25a3b5589287dc757ee6213" : void 0) ?? "unknown";
|
|
320
|
+
const commitShort = readInjected(true ? "35facf03" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
321
|
+
const version = readInjected(true ? "0.9.82-rc.312" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
322
|
+
const builtAt = readInjected(true ? "2026-06-17T22:48:50.124Z" : 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) {
|
|
@@ -2086,6 +2118,7 @@ var init_coordinator_prompt = __esm({
|
|
|
2086
2118
|
| \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
|
|
2087
2119
|
| \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
|
|
2088
2120
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
2121
|
+
| \`mesh_read_node_logs\` | Fetch a remote node's daemon log tail directly over P2P (grep/since/byte-bounded, secrets redacted) \u2014 no session/PowerShell needed to debug a node's daemon |
|
|
2089
2122
|
| \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
|
|
2090
2123
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
2091
2124
|
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
@@ -2838,6 +2871,7 @@ __export(mesh_work_queue_exports, {
|
|
|
2838
2871
|
recordMeshToolCall: () => recordMeshToolCall,
|
|
2839
2872
|
recordTaskAutoLaunch: () => recordTaskAutoLaunch,
|
|
2840
2873
|
requeueTask: () => requeueTask,
|
|
2874
|
+
resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
|
|
2841
2875
|
updateDirectDispatchStatus: () => updateDirectDispatchStatus,
|
|
2842
2876
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
2843
2877
|
updateTaskStatus: () => updateTaskStatus,
|
|
@@ -2911,6 +2945,21 @@ function firstProviderPriority(policy) {
|
|
|
2911
2945
|
if (!Array.isArray(raw)) return void 0;
|
|
2912
2946
|
return raw.find((type) => typeof type === "string" && type.trim())?.trim();
|
|
2913
2947
|
}
|
|
2948
|
+
function roleCapabilityTags(policy, providerType) {
|
|
2949
|
+
const roles = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerRoles : void 0;
|
|
2950
|
+
if (!Array.isArray(roles)) return [];
|
|
2951
|
+
const wantedProvider = typeof providerType === "string" && providerType.trim() ? providerType.trim().toLowerCase() : "";
|
|
2952
|
+
const out = [];
|
|
2953
|
+
for (const entry of roles) {
|
|
2954
|
+
if (!entry || typeof entry !== "object") continue;
|
|
2955
|
+
const type = typeof entry.providerType === "string" ? entry.providerType.trim().toLowerCase() : "";
|
|
2956
|
+
const role = typeof entry.role === "string" ? entry.role.trim().toLowerCase() : "";
|
|
2957
|
+
if (!role) continue;
|
|
2958
|
+
if (wantedProvider && type && type !== wantedProvider) continue;
|
|
2959
|
+
out.push(`role=${role}`);
|
|
2960
|
+
}
|
|
2961
|
+
return out;
|
|
2962
|
+
}
|
|
2914
2963
|
function buildMeshNodeCapabilityTags(node, providerType) {
|
|
2915
2964
|
const provider = typeof providerType === "string" && providerType.trim() ? providerType.trim() : firstProviderPriority(node?.policy);
|
|
2916
2965
|
const worktreeBranch = typeof node?.worktreeBranch === "string" && node.worktreeBranch.trim() ? node.worktreeBranch.trim() : null;
|
|
@@ -2922,7 +2971,25 @@ function buildMeshNodeCapabilityTags(node, providerType) {
|
|
|
2922
2971
|
// Worktree nodes automatically expose a "worktree=<branch>" tag so that
|
|
2923
2972
|
// mesh_enqueue_task with required_tags: ["worktree=<branch>"] routes
|
|
2924
2973
|
// only to the matching worktree node.
|
|
2925
|
-
...node?.isLocalWorktree === true && worktreeBranch ? [`worktree=${worktreeBranch}`] : []
|
|
2974
|
+
...node?.isLocalWorktree === true && worktreeBranch ? [`worktree=${worktreeBranch}`] : [],
|
|
2975
|
+
// Convergence routing: advertise how this node can land its work onto base.
|
|
2976
|
+
// - converge=refine: local worktree nodes (on ANY machine — refine_mesh_node
|
|
2977
|
+
// now forwards to the owning daemon) can run the Refinery merge → push →
|
|
2978
|
+
// cleanup against their own checkout, so they accept code_change tasks.
|
|
2979
|
+
// - converge=fast_forward: non-worktree nodes (the machine itself) can only
|
|
2980
|
+
// ff/push an already-converged branch; they are NOT a destination for
|
|
2981
|
+
// code_change work (a worktree is created first, and that worktree node
|
|
2982
|
+
// receives the task instead). Reuses the ordinary required-tags filter —
|
|
2983
|
+
// the load-balancing scheduler auto-injects converge=refine for code_change
|
|
2984
|
+
// so such work is hard-filtered onto refine-capable nodes.
|
|
2985
|
+
...node?.isLocalWorktree === true ? ["converge=refine"] : ["converge=fast_forward"],
|
|
2986
|
+
// Role-based routing: advertise role=<x> for each (node, provider) role
|
|
2987
|
+
// declared in policy.providerRoles. Narrowed to the selected provider when
|
|
2988
|
+
// one is given so the chosen provider must match a task's required role;
|
|
2989
|
+
// when no provider is selected, all declared roles are advertised for the
|
|
2990
|
+
// node-level eligibility scan. Reuses the ordinary required-tags filter —
|
|
2991
|
+
// no separate role field/gate.
|
|
2992
|
+
...roleCapabilityTags(node?.policy, providerType)
|
|
2926
2993
|
]);
|
|
2927
2994
|
}
|
|
2928
2995
|
function nodeSatisfiesRequiredTags(requiredTags, capabilityTags) {
|
|
@@ -2931,6 +2998,18 @@ function nodeSatisfiesRequiredTags(requiredTags, capabilityTags) {
|
|
|
2931
2998
|
const available = new Set(normalizeMeshCapabilityTags(capabilityTags));
|
|
2932
2999
|
return required.every((tag) => available.has(tag));
|
|
2933
3000
|
}
|
|
3001
|
+
function resolveConvergeRequiredTags(meshId, taskMode, explicitRequiredTags, opts) {
|
|
3002
|
+
if (taskMode !== "code_change") return explicitRequiredTags;
|
|
3003
|
+
if (typeof opts?.targetNodeId === "string" && opts.targetNodeId.trim()) return explicitRequiredTags;
|
|
3004
|
+
let optedIn = false;
|
|
3005
|
+
try {
|
|
3006
|
+
optedIn = resolveAutoConvergeCodeChange(getMesh(meshId)?.policy);
|
|
3007
|
+
} catch {
|
|
3008
|
+
optedIn = false;
|
|
3009
|
+
}
|
|
3010
|
+
if (!optedIn) return explicitRequiredTags;
|
|
3011
|
+
return normalizeMeshCapabilityTags([...explicitRequiredTags, MESH_CONVERGE_REFINE_TAG]);
|
|
3012
|
+
}
|
|
2934
3013
|
function withQueueLock(_meshId, fn) {
|
|
2935
3014
|
return MeshRuntimeStore.getInstance().transaction(fn);
|
|
2936
3015
|
}
|
|
@@ -2989,7 +3068,15 @@ function enqueueTask(meshId, message, opts) {
|
|
|
2989
3068
|
taskMode: modeValidation.taskMode,
|
|
2990
3069
|
targetNodeId: opts?.targetNodeId,
|
|
2991
3070
|
targetSessionId: opts?.targetSessionId,
|
|
2992
|
-
|
|
3071
|
+
// Convergence routing (opt-in): auto-inject converge=refine for code_change
|
|
3072
|
+
// tasks so they hard-filter onto refine-capable worktree nodes. No-op unless
|
|
3073
|
+
// the mesh opts in; explicit target_node_id / required_tags are preserved.
|
|
3074
|
+
requiredTags: resolveConvergeRequiredTags(
|
|
3075
|
+
meshId,
|
|
3076
|
+
modeValidation.taskMode,
|
|
3077
|
+
normalizeMeshCapabilityTags(opts?.requiredTags),
|
|
3078
|
+
{ targetNodeId: opts?.targetNodeId }
|
|
3079
|
+
),
|
|
2993
3080
|
...dependsOn.length > 0 ? { dependsOn } : {},
|
|
2994
3081
|
...typeof opts?.missionId === "string" && opts.missionId.trim() ? { missionId: opts.missionId.trim() } : {},
|
|
2995
3082
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3250,6 +3337,7 @@ var init_mesh_work_queue = __esm({
|
|
|
3250
3337
|
"use strict";
|
|
3251
3338
|
import_crypto5 = require("crypto");
|
|
3252
3339
|
init_mesh_host_ownership();
|
|
3340
|
+
init_repo_mesh_types();
|
|
3253
3341
|
init_mesh_runtime_store();
|
|
3254
3342
|
init_mesh_config();
|
|
3255
3343
|
ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
|
|
@@ -3544,6 +3632,17 @@ var init_mesh_runtime_store = __esm({
|
|
|
3544
3632
|
|
|
3545
3633
|
CREATE INDEX IF NOT EXISTS idx_mesh_missions_mesh_status
|
|
3546
3634
|
ON mesh_missions(mesh_id, status, updated_at);
|
|
3635
|
+
|
|
3636
|
+
-- Load-balancing scheduler: per-mesh round-robin rotation cursor. When
|
|
3637
|
+
-- the schedulingStrategy is 'round_robin', several eligible nodes tied at
|
|
3638
|
+
-- the least load are rotated by this cursor so the tie-break winner cycles
|
|
3639
|
+
-- across scheduling passes instead of always favouring the same array-order
|
|
3640
|
+
-- node. Persisted (not a module Map) so rotation survives daemon restarts
|
|
3641
|
+
-- and stays a single source of truth across scheduling entry points.
|
|
3642
|
+
CREATE TABLE IF NOT EXISTS mesh_scheduler_cursor (
|
|
3643
|
+
mesh_id TEXT PRIMARY KEY,
|
|
3644
|
+
cursor INTEGER NOT NULL DEFAULT 0
|
|
3645
|
+
);
|
|
3547
3646
|
`);
|
|
3548
3647
|
}
|
|
3549
3648
|
hasCompletionFingerprint(fingerprint) {
|
|
@@ -3721,6 +3820,44 @@ var init_mesh_runtime_store = __esm({
|
|
|
3721
3820
|
`).get(meshId, nodeId);
|
|
3722
3821
|
return row !== void 0;
|
|
3723
3822
|
}
|
|
3823
|
+
/**
|
|
3824
|
+
* Count active (status='assigned') tasks on a node, regardless of provider or
|
|
3825
|
+
* task mode. This is the load metric for least-loaded / round-robin ranking:
|
|
3826
|
+
* the scheduler prefers the node with the fewest active assignments so
|
|
3827
|
+
* untargeted work spreads instead of piling onto whichever node asks first.
|
|
3828
|
+
*/
|
|
3829
|
+
nodeActiveAssignmentCount(meshId, nodeId) {
|
|
3830
|
+
const row = this.db.prepare(`
|
|
3831
|
+
SELECT COUNT(*) as count FROM mesh_queue
|
|
3832
|
+
WHERE mesh_id = ? AND status = 'assigned' AND assigned_node_id = ?
|
|
3833
|
+
`).get(meshId, nodeId);
|
|
3834
|
+
return row?.count ?? 0;
|
|
3835
|
+
}
|
|
3836
|
+
/**
|
|
3837
|
+
* Read the current per-mesh round-robin cursor (0 when unset). Used to rotate
|
|
3838
|
+
* the tie-break winner among nodes tied at the least load.
|
|
3839
|
+
*/
|
|
3840
|
+
getSchedulerCursor(meshId) {
|
|
3841
|
+
const row = this.db.prepare(
|
|
3842
|
+
"SELECT cursor FROM mesh_scheduler_cursor WHERE mesh_id = ?"
|
|
3843
|
+
).get(meshId);
|
|
3844
|
+
return row?.cursor ?? 0;
|
|
3845
|
+
}
|
|
3846
|
+
/**
|
|
3847
|
+
* Atomically advance the per-mesh round-robin cursor by one and return the
|
|
3848
|
+
* value that was current BEFORE the bump (the value the caller should rotate
|
|
3849
|
+
* by for this pass). UPSERT keeps it lock-free across concurrent passes.
|
|
3850
|
+
*/
|
|
3851
|
+
bumpSchedulerCursor(meshId) {
|
|
3852
|
+
return this.transaction(() => {
|
|
3853
|
+
const current = this.getSchedulerCursor(meshId);
|
|
3854
|
+
this.db.prepare(`
|
|
3855
|
+
INSERT INTO mesh_scheduler_cursor (mesh_id, cursor) VALUES (?, ?)
|
|
3856
|
+
ON CONFLICT(mesh_id) DO UPDATE SET cursor = excluded.cursor
|
|
3857
|
+
`).run(meshId, current + 1);
|
|
3858
|
+
return current;
|
|
3859
|
+
});
|
|
3860
|
+
}
|
|
3724
3861
|
/**
|
|
3725
3862
|
* Count active (status='assigned') tasks on a (node, provider) combination,
|
|
3726
3863
|
* matched by the assignedProviderType stamped on the payload at claim time.
|
|
@@ -5689,8 +5826,8 @@ function stripCoordinatorWrapperFile(filePath) {
|
|
|
5689
5826
|
const remaining = (existing.slice(0, openIdx) + existing.slice(closeIdx + CLOSE.length)).replace(/^\s*\n+/, "").replace(/\n+\s*$/, "");
|
|
5690
5827
|
if (!remaining.trim()) {
|
|
5691
5828
|
try {
|
|
5692
|
-
const
|
|
5693
|
-
|
|
5829
|
+
const fs31 = require("fs");
|
|
5830
|
+
fs31.unlinkSync(filePath);
|
|
5694
5831
|
} catch {
|
|
5695
5832
|
}
|
|
5696
5833
|
} else {
|
|
@@ -8292,6 +8429,33 @@ function activeReadonlyAssignedCount(meshId) {
|
|
|
8292
8429
|
function nodeHasActiveAssignment(meshId, nodeId) {
|
|
8293
8430
|
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
8294
8431
|
}
|
|
8432
|
+
function nodeActiveLoad(meshId, nodeId) {
|
|
8433
|
+
return MeshRuntimeStore.getInstance().nodeActiveAssignmentCount(meshId, nodeId);
|
|
8434
|
+
}
|
|
8435
|
+
function resolveSchedulingStrategy(mesh) {
|
|
8436
|
+
return normalizeMeshSchedulingStrategy(mesh?.policy?.schedulingStrategy);
|
|
8437
|
+
}
|
|
8438
|
+
function orderEligibleNodes(meshId, strategy, nodes, opts) {
|
|
8439
|
+
if (strategy === "first_eligible" || nodes.length <= 1) {
|
|
8440
|
+
return nodes;
|
|
8441
|
+
}
|
|
8442
|
+
const priorityOf = (n) => resolveNodeSchedulingPriority(n.node?.policy);
|
|
8443
|
+
let rotation = 0;
|
|
8444
|
+
if (strategy === "round_robin") {
|
|
8445
|
+
const cursor = opts?.bumpCursor ? MeshRuntimeStore.getInstance().bumpSchedulerCursor(meshId) : MeshRuntimeStore.getInstance().getSchedulerCursor(meshId);
|
|
8446
|
+
rotation = (cursor % nodes.length + nodes.length) % nodes.length;
|
|
8447
|
+
}
|
|
8448
|
+
const rotationRank = (index) => (index - rotation + nodes.length) % nodes.length;
|
|
8449
|
+
return [...nodes].sort((a, b) => {
|
|
8450
|
+
const prioDelta = priorityOf(b) - priorityOf(a);
|
|
8451
|
+
if (prioDelta !== 0) return prioDelta;
|
|
8452
|
+
if (strategy === "least_loaded" || strategy === "round_robin") {
|
|
8453
|
+
const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
|
|
8454
|
+
if (loadDelta !== 0) return loadDelta;
|
|
8455
|
+
}
|
|
8456
|
+
return rotationRank(a.index) - rotationRank(b.index);
|
|
8457
|
+
});
|
|
8458
|
+
}
|
|
8295
8459
|
function activeProviderAssignedCount(meshId, nodeId, providerType) {
|
|
8296
8460
|
return getQueue(meshId, { status: ["assigned"] }).filter((task) => task.assignedNodeId === nodeId && task.assignedProviderType === providerType).length;
|
|
8297
8461
|
}
|
|
@@ -8428,7 +8592,14 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
8428
8592
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "no_node_satisfies_required_tags", nodeId: task.targetNodeId });
|
|
8429
8593
|
continue;
|
|
8430
8594
|
}
|
|
8431
|
-
|
|
8595
|
+
const strategy = resolveSchedulingStrategy(mesh);
|
|
8596
|
+
const orderedCandidateNodes = strategy === "first_eligible" ? candidateNodes : orderEligibleNodes(
|
|
8597
|
+
meshId,
|
|
8598
|
+
strategy,
|
|
8599
|
+
candidateNodes.map((node, index) => ({ nodeId: readMeshNodeId(node), node, index })).filter((c) => c.nodeId),
|
|
8600
|
+
{ bumpCursor: true }
|
|
8601
|
+
).map((c) => c.node);
|
|
8602
|
+
for (const node of orderedCandidateNodes) {
|
|
8432
8603
|
const nodeId = readMeshNodeId(node);
|
|
8433
8604
|
if (!nodeId) continue;
|
|
8434
8605
|
const launchKey = `${meshId}:${nodeId}`;
|
|
@@ -8555,6 +8726,8 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
8555
8726
|
noIdleMeshSessionAvailable: true
|
|
8556
8727
|
};
|
|
8557
8728
|
}
|
|
8729
|
+
const strategy = resolveSchedulingStrategy(mesh);
|
|
8730
|
+
const localCandidates = [];
|
|
8558
8731
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
8559
8732
|
for (const inst of cliInstances) {
|
|
8560
8733
|
const state = inst.getState();
|
|
@@ -8577,7 +8750,7 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
8577
8750
|
const providerType = state.type || readNonEmptyString2(settings.providerType);
|
|
8578
8751
|
if (providerType) {
|
|
8579
8752
|
localIdleSessionsChecked += 1;
|
|
8580
|
-
|
|
8753
|
+
localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => readMeshNodeId(n) === nodeId) });
|
|
8581
8754
|
} else {
|
|
8582
8755
|
skippedSessions.push({
|
|
8583
8756
|
nodeId,
|
|
@@ -8591,18 +8764,49 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
8591
8764
|
remoteSessions = MeshRuntimeStore.getInstance().getRemoteIdleSessions();
|
|
8592
8765
|
} catch {
|
|
8593
8766
|
}
|
|
8767
|
+
const remoteCandidates = [];
|
|
8594
8768
|
for (const idle of remoteSessions) {
|
|
8595
8769
|
const node = mesh.nodes.find((n) => n.id === idle.nodeId);
|
|
8596
8770
|
if (node) {
|
|
8597
8771
|
remoteIdleSessionsChecked += 1;
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8772
|
+
remoteCandidates.push({ nodeId: idle.nodeId, sessionId: idle.sessionId, providerType: idle.providerType, origin: "remote", node });
|
|
8773
|
+
}
|
|
8774
|
+
}
|
|
8775
|
+
const assignIdleCandidate = (candidate) => {
|
|
8776
|
+
const assigned = tryAssignQueueTask(components, meshId, candidate.nodeId, candidate.sessionId, candidate.providerType);
|
|
8777
|
+
if (assigned && candidate.origin === "remote") {
|
|
8778
|
+
try {
|
|
8779
|
+
MeshRuntimeStore.getInstance().deleteRemoteIdleSession(candidate.nodeId, candidate.sessionId);
|
|
8780
|
+
} catch {
|
|
8604
8781
|
}
|
|
8605
8782
|
}
|
|
8783
|
+
};
|
|
8784
|
+
if (strategy === "first_eligible") {
|
|
8785
|
+
for (const candidate of localCandidates) assignIdleCandidate(candidate);
|
|
8786
|
+
for (const candidate of remoteCandidates) assignIdleCandidate(candidate);
|
|
8787
|
+
} else {
|
|
8788
|
+
const pool = [...localCandidates, ...remoteCandidates];
|
|
8789
|
+
const baseIndex = /* @__PURE__ */ new Map();
|
|
8790
|
+
pool.forEach((c, i) => {
|
|
8791
|
+
if (!baseIndex.has(c.nodeId)) baseIndex.set(c.nodeId, i);
|
|
8792
|
+
});
|
|
8793
|
+
const uniqueNodes = [...new Set(pool.map((c) => c.nodeId))].map((nodeId, index) => ({ nodeId, node: pool.find((c) => c.nodeId === nodeId)?.node, index }));
|
|
8794
|
+
const ranked = orderEligibleNodes(meshId, strategy, uniqueNodes, { bumpCursor: true });
|
|
8795
|
+
const rankIndex = new Map(ranked.map((r, i) => [r.nodeId, i]));
|
|
8796
|
+
const remaining = [...pool];
|
|
8797
|
+
while (remaining.length > 0) {
|
|
8798
|
+
remaining.sort((a, b) => {
|
|
8799
|
+
const aPrio = resolveNodeSchedulingPriority(a.node?.policy);
|
|
8800
|
+
const bPrio = resolveNodeSchedulingPriority(b.node?.policy);
|
|
8801
|
+
if (aPrio !== bPrio) return bPrio - aPrio;
|
|
8802
|
+
if (strategy === "least_loaded" || strategy === "round_robin") {
|
|
8803
|
+
const loadDelta = nodeActiveLoad(meshId, a.nodeId) - nodeActiveLoad(meshId, b.nodeId);
|
|
8804
|
+
if (loadDelta !== 0) return loadDelta;
|
|
8805
|
+
}
|
|
8806
|
+
return (rankIndex.get(a.nodeId) ?? 0) - (rankIndex.get(b.nodeId) ?? 0);
|
|
8807
|
+
});
|
|
8808
|
+
assignIdleCandidate(remaining.shift());
|
|
8809
|
+
}
|
|
8606
8810
|
}
|
|
8607
8811
|
autoLaunchStarted = await maybeAutoLaunchOneQueueSession(components, meshId, mesh);
|
|
8608
8812
|
const afterQueue = getQueue(meshId);
|
|
@@ -10655,8 +10859,8 @@ var init_pty_transport = __esm({
|
|
|
10655
10859
|
let cwd = options.cwd;
|
|
10656
10860
|
if (cwd) {
|
|
10657
10861
|
try {
|
|
10658
|
-
const
|
|
10659
|
-
const stat2 =
|
|
10862
|
+
const fs31 = require("fs");
|
|
10863
|
+
const stat2 = fs31.statSync(cwd);
|
|
10660
10864
|
if (!stat2.isDirectory()) cwd = os11.homedir();
|
|
10661
10865
|
} catch {
|
|
10662
10866
|
cwd = os11.homedir();
|
|
@@ -10763,9 +10967,9 @@ function findBinary(name) {
|
|
|
10763
10967
|
for (const ext of exes) {
|
|
10764
10968
|
const fullPath = path17.join(p, trimmed + ext);
|
|
10765
10969
|
try {
|
|
10766
|
-
const
|
|
10767
|
-
if (
|
|
10768
|
-
const stat2 =
|
|
10970
|
+
const fs31 = require("fs");
|
|
10971
|
+
if (fs31.existsSync(fullPath)) {
|
|
10972
|
+
const stat2 = fs31.statSync(fullPath);
|
|
10769
10973
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
10770
10974
|
return fullPath;
|
|
10771
10975
|
}
|
|
@@ -10779,12 +10983,12 @@ function findBinary(name) {
|
|
|
10779
10983
|
function isScriptBinary(binaryPath) {
|
|
10780
10984
|
if (!path17.isAbsolute(binaryPath)) return false;
|
|
10781
10985
|
try {
|
|
10782
|
-
const
|
|
10783
|
-
const resolved =
|
|
10986
|
+
const fs31 = require("fs");
|
|
10987
|
+
const resolved = fs31.realpathSync(binaryPath);
|
|
10784
10988
|
const head = Buffer.alloc(8);
|
|
10785
|
-
const fd =
|
|
10786
|
-
|
|
10787
|
-
|
|
10989
|
+
const fd = fs31.openSync(resolved, "r");
|
|
10990
|
+
fs31.readSync(fd, head, 0, 8, 0);
|
|
10991
|
+
fs31.closeSync(fd);
|
|
10788
10992
|
let i = 0;
|
|
10789
10993
|
if (head[0] === 239 && head[1] === 187 && head[2] === 191) i = 3;
|
|
10790
10994
|
return head[i] === 35 && head[i + 1] === 33;
|
|
@@ -10795,12 +10999,12 @@ function isScriptBinary(binaryPath) {
|
|
|
10795
10999
|
function looksLikeMachOOrElf(filePath) {
|
|
10796
11000
|
if (!path17.isAbsolute(filePath)) return false;
|
|
10797
11001
|
try {
|
|
10798
|
-
const
|
|
10799
|
-
const resolved =
|
|
11002
|
+
const fs31 = require("fs");
|
|
11003
|
+
const resolved = fs31.realpathSync(filePath);
|
|
10800
11004
|
const buf = Buffer.alloc(8);
|
|
10801
|
-
const fd =
|
|
10802
|
-
|
|
10803
|
-
|
|
11005
|
+
const fd = fs31.openSync(resolved, "r");
|
|
11006
|
+
fs31.readSync(fd, buf, 0, 8, 0);
|
|
11007
|
+
fs31.closeSync(fd);
|
|
10804
11008
|
let i = 0;
|
|
10805
11009
|
if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) i = 3;
|
|
10806
11010
|
const b = buf.subarray(i);
|
|
@@ -11976,7 +12180,7 @@ var init_cli_state_engine = __esm({
|
|
|
11976
12180
|
scheduleSettle() {
|
|
11977
12181
|
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
11978
12182
|
const epoch = this.responseEpoch;
|
|
11979
|
-
const
|
|
12183
|
+
const delay2 = Math.max(
|
|
11980
12184
|
this.timeouts.outputSettle,
|
|
11981
12185
|
this.submitPendingUntil > Date.now() ? this.submitPendingUntil - Date.now() + this.timeouts.outputSettle : 0
|
|
11982
12186
|
);
|
|
@@ -11984,7 +12188,7 @@ var init_cli_state_engine = __esm({
|
|
|
11984
12188
|
this.settleTimer = null;
|
|
11985
12189
|
if (epoch !== this.responseEpoch) return;
|
|
11986
12190
|
this.evaluateSettled(this.transport.getSnapshot());
|
|
11987
|
-
},
|
|
12191
|
+
}, delay2);
|
|
11988
12192
|
}
|
|
11989
12193
|
/** Called from sendMessage in transport once a turn scope is established. */
|
|
11990
12194
|
onTurnStarted(turnScope) {
|
|
@@ -15492,6 +15696,7 @@ __export(index_exports, {
|
|
|
15492
15696
|
DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
15493
15697
|
DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
15494
15698
|
DEFAULT_MESH_POLICY: () => DEFAULT_MESH_POLICY,
|
|
15699
|
+
DEFAULT_MESH_SCHEDULING_STRATEGY: () => DEFAULT_MESH_SCHEDULING_STRATEGY,
|
|
15495
15700
|
DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
|
|
15496
15701
|
DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
15497
15702
|
DEFAULT_SESSION_HOST_READY_TIMEOUT_MS: () => DEFAULT_SESSION_HOST_READY_TIMEOUT_MS,
|
|
@@ -15517,9 +15722,12 @@ __export(index_exports, {
|
|
|
15517
15722
|
InMemoryGitSnapshotStore: () => InMemoryGitSnapshotStore,
|
|
15518
15723
|
LOG: () => LOG,
|
|
15519
15724
|
MAX_LEDGER_SLICE_LIMIT: () => MAX_LEDGER_SLICE_LIMIT,
|
|
15725
|
+
MESH_CONVERGE_FAST_FORWARD_TAG: () => MESH_CONVERGE_FAST_FORWARD_TAG,
|
|
15726
|
+
MESH_CONVERGE_REFINE_TAG: () => MESH_CONVERGE_REFINE_TAG,
|
|
15520
15727
|
MESH_MISSION_STATUSES: () => MESH_MISSION_STATUSES,
|
|
15521
15728
|
MESH_REFINE_CONFIG_LOCATIONS: () => MESH_REFINE_CONFIG_LOCATIONS,
|
|
15522
15729
|
MESH_REFINE_CONFIG_SCHEMA: () => MESH_REFINE_CONFIG_SCHEMA,
|
|
15730
|
+
MESH_SCHEDULING_STRATEGIES: () => MESH_SCHEDULING_STRATEGIES,
|
|
15523
15731
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
|
|
15524
15732
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
|
|
15525
15733
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS: () => MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
@@ -15720,6 +15928,7 @@ __export(index_exports, {
|
|
|
15720
15928
|
normalizeManagedStatus: () => normalizeManagedStatus,
|
|
15721
15929
|
normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
|
|
15722
15930
|
normalizeMeshDaemonRole: () => normalizeMeshDaemonRole,
|
|
15931
|
+
normalizeMeshSchedulingStrategy: () => normalizeMeshSchedulingStrategy,
|
|
15723
15932
|
normalizeMeshTaskMode: () => normalizeMeshTaskMode,
|
|
15724
15933
|
normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
|
|
15725
15934
|
normalizeMessageParts: () => normalizeMessageParts,
|
|
@@ -15757,7 +15966,9 @@ __export(index_exports, {
|
|
|
15757
15966
|
resetConfig: () => resetConfig,
|
|
15758
15967
|
resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
|
|
15759
15968
|
resetState: () => resetState,
|
|
15969
|
+
resolveAutoConvergeCodeChange: () => resolveAutoConvergeCodeChange,
|
|
15760
15970
|
resolveChatMessageKind: () => resolveChatMessageKind,
|
|
15971
|
+
resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
|
|
15761
15972
|
resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
|
|
15762
15973
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
15763
15974
|
resolveDelegatedWorkerAutoApprove: () => resolveDelegatedWorkerAutoApprove,
|
|
@@ -15765,6 +15976,7 @@ __export(index_exports, {
|
|
|
15765
15976
|
resolveGitRepository: () => resolveGitRepository,
|
|
15766
15977
|
resolveMeshHostStatus: () => resolveMeshHostStatus,
|
|
15767
15978
|
resolveMeshRefineValidationPlan: () => resolveMeshRefineValidationPlan,
|
|
15979
|
+
resolveNodeSchedulingPriority: () => resolveNodeSchedulingPriority,
|
|
15768
15980
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
15769
15981
|
resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
|
|
15770
15982
|
resolveWorktreePath: () => resolveWorktreePath,
|
|
@@ -18139,9 +18351,9 @@ function readString6(value) {
|
|
|
18139
18351
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
18140
18352
|
}
|
|
18141
18353
|
function summarizeMessage(message) {
|
|
18142
|
-
const
|
|
18143
|
-
const title =
|
|
18144
|
-
return { title: title || "(untitled task)", summary:
|
|
18354
|
+
const oneLine2 = message.replace(/\s+/g, " ").trim();
|
|
18355
|
+
const title = oneLine2.length > 96 ? `${oneLine2.slice(0, 93)}...` : oneLine2;
|
|
18356
|
+
return { title: title || "(untitled task)", summary: oneLine2 };
|
|
18145
18357
|
}
|
|
18146
18358
|
function elapsedSince(value, now) {
|
|
18147
18359
|
const started = value ? new Date(value).getTime() : Number.NaN;
|
|
@@ -21247,6 +21459,11 @@ function collapseReplayAssistantTurns(messages, historyBehavior) {
|
|
|
21247
21459
|
continue;
|
|
21248
21460
|
}
|
|
21249
21461
|
if (message.role === "assistant") {
|
|
21462
|
+
const isActivity = message.kind === "tool" || message.kind === "terminal" || message.kind === "thought";
|
|
21463
|
+
if (isActivity) {
|
|
21464
|
+
collapsed.push(message);
|
|
21465
|
+
continue;
|
|
21466
|
+
}
|
|
21250
21467
|
if (sawAssistantSinceLastUser) continue;
|
|
21251
21468
|
sawAssistantSinceLastUser = true;
|
|
21252
21469
|
collapsed.push(message);
|
|
@@ -26390,7 +26607,8 @@ function buildReadChatCommandResult(payload, args, h) {
|
|
|
26390
26607
|
const sessionIdHint = typeof args?.targetSessionId === "string" ? args.targetSessionId : typeof args?.sessionId === "string" ? args.sessionId : "";
|
|
26391
26608
|
const providerHint = typeof args?.cliType === "string" ? args.cliType : typeof args?.providerType === "string" ? args.providerType : typeof args?.agentType === "string" ? args.agentType : "";
|
|
26392
26609
|
const filteredMessages = h ? maybeHideCoordinatorPromptMessage(h, providerHint, sessionIdHint, messages) : messages;
|
|
26393
|
-
const
|
|
26610
|
+
const includeActivity = args?.includeActivity === true || args?.includeActivity === "true";
|
|
26611
|
+
const visibleMessages = includeActivity ? filteredMessages.filter((m) => isUserFacingChatMessage(m) || isActivityChatMessage(m)) : filterUserFacingChatMessages(filteredMessages);
|
|
26394
26612
|
const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
|
|
26395
26613
|
const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
|
|
26396
26614
|
const preservedPayloadFields = Object.fromEntries(Object.entries(payload).filter(([key]) => shouldPreserveReadChatPayloadField(key)));
|
|
@@ -28759,6 +28977,9 @@ function normalizeProviderScriptArgs(args, scriptName) {
|
|
|
28759
28977
|
}
|
|
28760
28978
|
function buildControlScriptResult(scriptName, payload) {
|
|
28761
28979
|
if (!payload || typeof payload !== "object") return {};
|
|
28980
|
+
if (payload.controlResult && typeof payload.controlResult === "object") {
|
|
28981
|
+
return { controlResult: payload.controlResult };
|
|
28982
|
+
}
|
|
28762
28983
|
const legacyListPayload = (() => {
|
|
28763
28984
|
if (Array.isArray(payload.options)) return payload;
|
|
28764
28985
|
if (/^listmodels$/i.test(scriptName) && Array.isArray(payload.models)) {
|
|
@@ -29621,7 +29842,7 @@ var DaemonCommandHandler = class {
|
|
|
29621
29842
|
return { success: false, error: "invalid type" };
|
|
29622
29843
|
}
|
|
29623
29844
|
const https = require("https");
|
|
29624
|
-
const
|
|
29845
|
+
const fs31 = require("fs");
|
|
29625
29846
|
const path41 = require("path");
|
|
29626
29847
|
const crypto6 = require("crypto");
|
|
29627
29848
|
const REGISTRY = "https://api.adhf.dev/api/v1/registry";
|
|
@@ -29665,7 +29886,7 @@ var DaemonCommandHandler = class {
|
|
|
29665
29886
|
if (!targetDir.startsWith(installRootResolved + path41.sep)) {
|
|
29666
29887
|
return { success: false, error: "install path escaped upstream root" };
|
|
29667
29888
|
}
|
|
29668
|
-
|
|
29889
|
+
fs31.mkdirSync(targetDir, { recursive: true });
|
|
29669
29890
|
let manifestProbe = {};
|
|
29670
29891
|
try {
|
|
29671
29892
|
manifestProbe = JSON.parse(manifestBody);
|
|
@@ -29690,7 +29911,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
29690
29911
|
}
|
|
29691
29912
|
const targetFile = isV1 ? "provider.v1.json" : "provider.json";
|
|
29692
29913
|
const targetPath = path41.join(targetDir, targetFile);
|
|
29693
|
-
|
|
29914
|
+
fs31.writeFileSync(targetPath, manifestBody, "utf-8");
|
|
29694
29915
|
const manifestJson = JSON.parse(manifestBody);
|
|
29695
29916
|
const scriptFetch = await this.fetchProviderSources(
|
|
29696
29917
|
manifestJson,
|
|
@@ -29760,7 +29981,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
29760
29981
|
const repo = source.repo;
|
|
29761
29982
|
const ref = source.ref;
|
|
29762
29983
|
const https = require("https");
|
|
29763
|
-
const
|
|
29984
|
+
const fs31 = require("fs");
|
|
29764
29985
|
const path41 = require("path");
|
|
29765
29986
|
function fetchJson(url, timeoutMs) {
|
|
29766
29987
|
return new Promise((resolve24, reject) => {
|
|
@@ -29844,8 +30065,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
29844
30065
|
const relInside = entry.path.startsWith(sharedDirRel + "/") ? entry.path.slice(sharedDirRel.length + 1) : entry.path;
|
|
29845
30066
|
const outPath = path41.resolve(path41.join(sharedTargetDir, relInside));
|
|
29846
30067
|
if (!outPath.startsWith(path41.resolve(sharedTargetDir) + path41.sep)) continue;
|
|
29847
|
-
|
|
29848
|
-
|
|
30068
|
+
fs31.mkdirSync(path41.dirname(outPath), { recursive: true });
|
|
30069
|
+
fs31.writeFileSync(outPath, body);
|
|
29849
30070
|
fetchedCount++;
|
|
29850
30071
|
} catch (e) {
|
|
29851
30072
|
errors.push(`fetch shared ${entry.path}: ${e?.message ?? e}`);
|
|
@@ -29883,8 +30104,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
29883
30104
|
errors.push(`refusing to write outside targetDir: ${entry.path}`);
|
|
29884
30105
|
continue;
|
|
29885
30106
|
}
|
|
29886
|
-
|
|
29887
|
-
|
|
30107
|
+
fs31.mkdirSync(path41.dirname(outPath), { recursive: true });
|
|
30108
|
+
fs31.writeFileSync(outPath, body);
|
|
29888
30109
|
fetchedCount++;
|
|
29889
30110
|
} catch (e) {
|
|
29890
30111
|
errors.push(`fetch ${entry.path}: ${e?.message ?? e}`);
|
|
@@ -29912,7 +30133,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
29912
30133
|
if (!["cli", "ide", "extension", "acp"].includes(category)) {
|
|
29913
30134
|
return { success: false, error: `unknown category: ${category}` };
|
|
29914
30135
|
}
|
|
29915
|
-
const
|
|
30136
|
+
const fs31 = require("fs");
|
|
29916
30137
|
const path41 = require("path");
|
|
29917
30138
|
try {
|
|
29918
30139
|
const installRoot = this.getUpstreamInstallRoot();
|
|
@@ -29921,10 +30142,10 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
29921
30142
|
if (!targetDir.startsWith(installRootResolved + path41.sep)) {
|
|
29922
30143
|
return { success: false, error: "refusing to delete outside upstream root" };
|
|
29923
30144
|
}
|
|
29924
|
-
if (!
|
|
30145
|
+
if (!fs31.existsSync(targetDir)) {
|
|
29925
30146
|
return { success: false, error: "not installed" };
|
|
29926
30147
|
}
|
|
29927
|
-
|
|
30148
|
+
fs31.rmSync(targetDir, { recursive: true, force: true });
|
|
29928
30149
|
if (this._ctx.providerLoader) {
|
|
29929
30150
|
this._ctx.providerLoader.reload();
|
|
29930
30151
|
this._ctx.providerLoader.registerToDetector();
|
|
@@ -29940,28 +30161,28 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
29940
30161
|
* the UI and by the update checker.
|
|
29941
30162
|
*/
|
|
29942
30163
|
handleListInstalledProviders(_args) {
|
|
29943
|
-
const
|
|
30164
|
+
const fs31 = require("fs");
|
|
29944
30165
|
const path41 = require("path");
|
|
29945
30166
|
const installRoot = this.getUpstreamInstallRoot();
|
|
29946
|
-
if (!
|
|
30167
|
+
if (!fs31.existsSync(installRoot)) return { success: true, providers: [] };
|
|
29947
30168
|
const CATEGORIES = ["cli", "ide", "extension", "acp"];
|
|
29948
30169
|
const items = [];
|
|
29949
30170
|
for (const category of CATEGORIES) {
|
|
29950
30171
|
const categoryDir = path41.join(installRoot, category);
|
|
29951
|
-
if (!
|
|
30172
|
+
if (!fs31.existsSync(categoryDir)) continue;
|
|
29952
30173
|
let entries;
|
|
29953
30174
|
try {
|
|
29954
|
-
entries =
|
|
30175
|
+
entries = fs31.readdirSync(categoryDir);
|
|
29955
30176
|
} catch {
|
|
29956
30177
|
continue;
|
|
29957
30178
|
}
|
|
29958
30179
|
for (const type of entries) {
|
|
29959
30180
|
const v1Path = path41.join(categoryDir, type, "provider.v1.json");
|
|
29960
30181
|
const v0Path = path41.join(categoryDir, type, "provider.json");
|
|
29961
|
-
const manifestPath =
|
|
30182
|
+
const manifestPath = fs31.existsSync(v1Path) ? v1Path : fs31.existsSync(v0Path) ? v0Path : null;
|
|
29962
30183
|
if (!manifestPath) continue;
|
|
29963
30184
|
try {
|
|
29964
|
-
const m = JSON.parse(
|
|
30185
|
+
const m = JSON.parse(fs31.readFileSync(manifestPath, "utf-8"));
|
|
29965
30186
|
items.push({
|
|
29966
30187
|
type,
|
|
29967
30188
|
category,
|
|
@@ -30072,7 +30293,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
30072
30293
|
if (!/^@[a-z0-9_-]+$/i.test(requestedName)) {
|
|
30073
30294
|
return { success: false, error: "name must match @[a-z0-9_-]+" };
|
|
30074
30295
|
}
|
|
30075
|
-
const
|
|
30296
|
+
const fs31 = require("fs");
|
|
30076
30297
|
const path41 = require("path");
|
|
30077
30298
|
const { spawnSync: spawnSync2 } = require("child_process");
|
|
30078
30299
|
const file = ext.loadExternalSources();
|
|
@@ -30083,8 +30304,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
30083
30304
|
return { success: false, error: `source url+ref already registered (use a different name to track another ref)` };
|
|
30084
30305
|
}
|
|
30085
30306
|
const sourceDir = path41.join(ext.externalRoot(), requestedName);
|
|
30086
|
-
if (!
|
|
30087
|
-
if (
|
|
30307
|
+
if (!fs31.existsSync(ext.externalRoot())) fs31.mkdirSync(ext.externalRoot(), { recursive: true });
|
|
30308
|
+
if (fs31.existsSync(sourceDir)) {
|
|
30088
30309
|
return { success: false, error: `directory already exists: ${sourceDir} (rename or remove first)` };
|
|
30089
30310
|
}
|
|
30090
30311
|
const clone = spawnSync2("git", ["clone", "--depth=1", "--branch", ref, "--", url, sourceDir], {
|
|
@@ -30094,7 +30315,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
30094
30315
|
});
|
|
30095
30316
|
if (clone.status !== 0) {
|
|
30096
30317
|
try {
|
|
30097
|
-
|
|
30318
|
+
fs31.rmSync(sourceDir, { recursive: true, force: true });
|
|
30098
30319
|
} catch {
|
|
30099
30320
|
}
|
|
30100
30321
|
return { success: false, error: `git clone failed: ${(clone.stderr || clone.stdout || "").trim() || "unknown error"}` };
|
|
@@ -30138,15 +30359,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
30138
30359
|
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
30139
30360
|
if (!name) return { success: false, error: "name is required" };
|
|
30140
30361
|
const ext = (init_external_sources(), __toCommonJS(external_sources_exports));
|
|
30141
|
-
const
|
|
30362
|
+
const fs31 = require("fs");
|
|
30142
30363
|
const path41 = require("path");
|
|
30143
30364
|
const file = ext.loadExternalSources();
|
|
30144
30365
|
const match = file.sources.find((s) => s.name === name);
|
|
30145
30366
|
if (!match) return { success: false, error: `source "${name}" not registered` };
|
|
30146
30367
|
const sourceDir = path41.join(ext.externalRoot(), name);
|
|
30147
|
-
if (
|
|
30368
|
+
if (fs31.existsSync(sourceDir)) {
|
|
30148
30369
|
try {
|
|
30149
|
-
|
|
30370
|
+
fs31.rmSync(sourceDir, { recursive: true, force: true });
|
|
30150
30371
|
} catch (e) {
|
|
30151
30372
|
return { success: false, error: `failed to delete ${sourceDir}: ${e?.message || e}` };
|
|
30152
30373
|
}
|
|
@@ -30609,12 +30830,12 @@ var FsmDriver = class {
|
|
|
30609
30830
|
scheduleSpawnPrime() {
|
|
30610
30831
|
const seqs = this.spec.send_on_spawn;
|
|
30611
30832
|
if (!Array.isArray(seqs) || seqs.length === 0) return;
|
|
30612
|
-
const
|
|
30833
|
+
const delay2 = Math.max(0, this.spec.send_on_spawn_delay_ms ?? 250);
|
|
30613
30834
|
setTimeout(() => {
|
|
30614
30835
|
for (const seq of seqs) {
|
|
30615
30836
|
if (typeof seq === "string" && seq.length > 0) this.adapter.send_keys(seq);
|
|
30616
30837
|
}
|
|
30617
|
-
},
|
|
30838
|
+
}, delay2);
|
|
30618
30839
|
}
|
|
30619
30840
|
dispatch(cmd) {
|
|
30620
30841
|
switch (cmd.kind) {
|
|
@@ -30980,11 +31201,11 @@ var FsmDriver = class {
|
|
|
30980
31201
|
const armed = this.delegateTimers.has(d.id);
|
|
30981
31202
|
const shouldFire = d.when_state === currentStateId;
|
|
30982
31203
|
if (shouldFire && !armed) {
|
|
30983
|
-
const
|
|
31204
|
+
const delay2 = d.after_duration_ms ?? 0;
|
|
30984
31205
|
const t = setTimeout(() => {
|
|
30985
31206
|
this.fireDelegate(d);
|
|
30986
31207
|
this.delegateTimers.delete(d.id);
|
|
30987
|
-
},
|
|
31208
|
+
}, delay2);
|
|
30988
31209
|
this.delegateTimers.set(d.id, t);
|
|
30989
31210
|
} else if (!shouldFire && armed) {
|
|
30990
31211
|
clearTimeout(this.delegateTimers.get(d.id));
|
|
@@ -31038,7 +31259,15 @@ var FsmDriver = class {
|
|
|
31038
31259
|
this.adapter.send_keys(a.keys);
|
|
31039
31260
|
return;
|
|
31040
31261
|
case "open_picker":
|
|
31041
|
-
|
|
31262
|
+
{
|
|
31263
|
+
const m = /^([\s\S]*?)([\r\n]+)$/.exec(a.trigger_keys);
|
|
31264
|
+
if (m && m[1]) {
|
|
31265
|
+
this.adapter.send_keys(m[1]);
|
|
31266
|
+
setTimeout(() => this.adapter.send_keys(m[2]), 200);
|
|
31267
|
+
} else {
|
|
31268
|
+
this.adapter.send_keys(a.trigger_keys);
|
|
31269
|
+
}
|
|
31270
|
+
}
|
|
31042
31271
|
this.pickerInProgress = { control_id: ctl.id, spec: ctl };
|
|
31043
31272
|
return;
|
|
31044
31273
|
case "attach_image": {
|
|
@@ -31223,8 +31452,7 @@ function executeJsonl(src, input) {
|
|
|
31223
31452
|
for (let i = 0; i < lines.length; i += 1) {
|
|
31224
31453
|
const rec = lines[i];
|
|
31225
31454
|
if (filter && !filter(rec)) continue;
|
|
31226
|
-
const msg
|
|
31227
|
-
if (msg) {
|
|
31455
|
+
for (const msg of projectMessages(rec, src.message_map, i, lines.length, mtime)) {
|
|
31228
31456
|
if (transcriptWorkspace) msg.workspace = transcriptWorkspace;
|
|
31229
31457
|
messages.push(msg);
|
|
31230
31458
|
}
|
|
@@ -31304,8 +31532,9 @@ function executeSqlite(src, input) {
|
|
|
31304
31532
|
const mtime = safeMtimeMs(resolved);
|
|
31305
31533
|
const messages = [];
|
|
31306
31534
|
for (let i = 0; i < messageRows.length; i += 1) {
|
|
31307
|
-
const msg
|
|
31308
|
-
|
|
31535
|
+
for (const msg of projectMessages(messageRows[i], src.message_map, i, messageRows.length, mtime)) {
|
|
31536
|
+
messages.push(msg);
|
|
31537
|
+
}
|
|
31309
31538
|
}
|
|
31310
31539
|
if (messages.length === 0) return null;
|
|
31311
31540
|
return {
|
|
@@ -31703,11 +31932,42 @@ function jsonPathGet(record, expr) {
|
|
|
31703
31932
|
}
|
|
31704
31933
|
return cur;
|
|
31705
31934
|
}
|
|
31706
|
-
function
|
|
31935
|
+
function projectMessages(record, map, index, total, sourceMtimeMs) {
|
|
31707
31936
|
const roleRaw = jsonPathGet(record, map.role);
|
|
31708
|
-
const contentRaw = jsonPathGet(record, map.content);
|
|
31709
31937
|
const role = normalizeRole(roleRaw);
|
|
31710
|
-
let
|
|
31938
|
+
let receivedAt = sourceMtimeMs - (total - 1 - index) * 1e3;
|
|
31939
|
+
if (map.timestamp_ms) {
|
|
31940
|
+
const tsRaw = jsonPathGet(record, map.timestamp_ms);
|
|
31941
|
+
const parsed = parseTimestamp(tsRaw);
|
|
31942
|
+
if (parsed != null) receivedAt = parsed;
|
|
31943
|
+
}
|
|
31944
|
+
const kindRaw = map.kind ? jsonPathGet(record, map.kind) : void 0;
|
|
31945
|
+
const kind = typeof kindRaw === "string" && kindRaw ? kindRaw : "standard";
|
|
31946
|
+
const out = [];
|
|
31947
|
+
if (map.tools) {
|
|
31948
|
+
const recordTool = projectToolBlock(record, role, map.tools);
|
|
31949
|
+
if (recordTool) {
|
|
31950
|
+
out.push({ ...recordTool, receivedAt });
|
|
31951
|
+
return out;
|
|
31952
|
+
}
|
|
31953
|
+
}
|
|
31954
|
+
const contentRaw = jsonPathGet(record, map.content);
|
|
31955
|
+
const content = cleanContent(stringifyContent(contentRaw), map);
|
|
31956
|
+
if (content) out.push({ role, content, receivedAt, kind });
|
|
31957
|
+
if (map.tools && Array.isArray(contentRaw)) {
|
|
31958
|
+
let nudge = 1;
|
|
31959
|
+
for (const block2 of contentRaw) {
|
|
31960
|
+
const tool = projectToolBlock(block2, role, map.tools);
|
|
31961
|
+
if (tool) {
|
|
31962
|
+
out.push({ ...tool, receivedAt: receivedAt + nudge });
|
|
31963
|
+
nudge += 1;
|
|
31964
|
+
}
|
|
31965
|
+
}
|
|
31966
|
+
}
|
|
31967
|
+
return out;
|
|
31968
|
+
}
|
|
31969
|
+
function cleanContent(input, map) {
|
|
31970
|
+
let content = input;
|
|
31711
31971
|
if (content && map.content_strip) {
|
|
31712
31972
|
for (const tag of map.content_strip) {
|
|
31713
31973
|
const safeTag = tag.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
@@ -31723,17 +31983,33 @@ function projectMessage(record, map, index, total, sourceMtimeMs) {
|
|
|
31723
31983
|
content = content.replace(open, "").replace(close, "");
|
|
31724
31984
|
}
|
|
31725
31985
|
}
|
|
31726
|
-
|
|
31727
|
-
|
|
31728
|
-
|
|
31729
|
-
|
|
31730
|
-
|
|
31731
|
-
|
|
31732
|
-
|
|
31986
|
+
return content ? content.trim() : "";
|
|
31987
|
+
}
|
|
31988
|
+
var DEFAULT_TOOL_CALL_TYPES = ["tool_use", "function_call", "custom_tool_call"];
|
|
31989
|
+
var DEFAULT_TOOL_RESULT_TYPES = ["tool_result", "function_call_output", "custom_tool_call_output"];
|
|
31990
|
+
function projectToolBlock(block2, role, tmap) {
|
|
31991
|
+
void role;
|
|
31992
|
+
if (block2 == null || typeof block2 !== "object") return null;
|
|
31993
|
+
const typeVal = String(jsonPathGet(block2, tmap.block_type || "$.type") ?? "");
|
|
31994
|
+
if (!typeVal) return null;
|
|
31995
|
+
const callTypes = tmap.call_types ?? DEFAULT_TOOL_CALL_TYPES;
|
|
31996
|
+
const resultTypes = tmap.result_types ?? DEFAULT_TOOL_RESULT_TYPES;
|
|
31997
|
+
if (callTypes.includes(typeVal)) {
|
|
31998
|
+
const name = String(jsonPathGet(block2, tmap.call_name || "$.name") ?? "tool").trim() || "tool";
|
|
31999
|
+
const args = oneLine(stringifyContent(jsonPathGet(block2, tmap.call_args || "$.input")), 240);
|
|
32000
|
+
const content = args ? `\u2197 ${name}: ${args}` : `\u2197 ${name}`;
|
|
32001
|
+
return { role: "assistant", content, receivedAt: 0, kind: "tool" };
|
|
32002
|
+
}
|
|
32003
|
+
if (resultTypes.includes(typeVal)) {
|
|
32004
|
+
const result = oneLine(stringifyContent(jsonPathGet(block2, tmap.result_content || "$.content")), 600);
|
|
32005
|
+
if (!result) return null;
|
|
32006
|
+
return { role: "assistant", content: `\u2198 ${result}`, receivedAt: 0, kind: "tool" };
|
|
31733
32007
|
}
|
|
31734
|
-
|
|
31735
|
-
|
|
31736
|
-
|
|
32008
|
+
return null;
|
|
32009
|
+
}
|
|
32010
|
+
function oneLine(s, max) {
|
|
32011
|
+
const flat = s.replace(/\s+/g, " ").trim();
|
|
32012
|
+
return flat.length > max ? flat.slice(0, max - 1) + "\u2026" : flat;
|
|
31737
32013
|
}
|
|
31738
32014
|
function parseTimestamp(v) {
|
|
31739
32015
|
if (v == null) return null;
|
|
@@ -31874,6 +32150,9 @@ init_logger();
|
|
|
31874
32150
|
function stripAnsi3(text) {
|
|
31875
32151
|
return String(text || "").replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
31876
32152
|
}
|
|
32153
|
+
function delay(ms) {
|
|
32154
|
+
return new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
32155
|
+
}
|
|
31877
32156
|
var SpecCliAdapter = class _SpecCliAdapter {
|
|
31878
32157
|
cliType;
|
|
31879
32158
|
cliName;
|
|
@@ -32095,9 +32374,15 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
32095
32374
|
* drives the dispatch:
|
|
32096
32375
|
*
|
|
32097
32376
|
* send_keys → click_control (e.g. stop)
|
|
32098
|
-
* open_picker →
|
|
32099
|
-
*
|
|
32100
|
-
*
|
|
32377
|
+
* open_picker → two roles, driven by the screen, not a hardcoded list:
|
|
32378
|
+
* - LIST (no choice arg): open the picker, wait for it
|
|
32379
|
+
* to render, parse the on-screen options via
|
|
32380
|
+
* `extract_choices`, and return them as
|
|
32381
|
+
* `controlResult.options` (+ `currentValue`). This is
|
|
32382
|
+
* how the dashboard's Model/Mode controls learn what is
|
|
32383
|
+
* actually selectable in this CLI right now.
|
|
32384
|
+
* - SELECT (args.choiceIndex / args.choiceLabel): drive
|
|
32385
|
+
* the picker to that option using `submit_key`.
|
|
32101
32386
|
* attach_image → attach_image dispatch; expects args.blob (data url
|
|
32102
32387
|
* or base64) and args.mime
|
|
32103
32388
|
*
|
|
@@ -32122,11 +32407,128 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
32122
32407
|
this.driver.dispatch({ kind: "attach_image", blob, mime });
|
|
32123
32408
|
return Promise.resolve({ ok: true, effects: [{ type: "attached_image", controlId: ctl.id }] });
|
|
32124
32409
|
}
|
|
32410
|
+
if (action.type === "open_picker") {
|
|
32411
|
+
const choiceIndex = typeof flat.choiceIndex === "number" ? flat.choiceIndex : typeof flat.choiceIndex === "string" && flat.choiceIndex.trim() ? Number(flat.choiceIndex) : void 0;
|
|
32412
|
+
const choiceLabel = typeof flat.choiceLabel === "string" ? flat.choiceLabel : typeof flat.choice === "string" ? flat.choice : void 0;
|
|
32413
|
+
if (typeof choiceIndex === "number" && Number.isFinite(choiceIndex) || choiceLabel && choiceLabel.trim()) {
|
|
32414
|
+
return this.selectPickerChoice(ctl, action, choiceIndex, choiceLabel);
|
|
32415
|
+
}
|
|
32416
|
+
return this.openPickerAndListChoices(ctl, action);
|
|
32417
|
+
}
|
|
32125
32418
|
this.driver.dispatch({ kind: "click_control", control_id: ctl.id, payload: flat });
|
|
32126
|
-
|
|
32127
|
-
|
|
32128
|
-
|
|
32129
|
-
|
|
32419
|
+
return Promise.resolve({ ok: true, effects: [{ type: "sent_keys", controlId: ctl.id }] });
|
|
32420
|
+
}
|
|
32421
|
+
/**
|
|
32422
|
+
* Open an `open_picker` control and return the options the CLI is showing,
|
|
32423
|
+
* parsed live from the screen via `extract_choices`. Nothing is selected —
|
|
32424
|
+
* the picker is left open so a follow-up SELECT invoke can commit a choice.
|
|
32425
|
+
*/
|
|
32426
|
+
async openPickerAndListChoices(ctl, action) {
|
|
32427
|
+
this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
|
|
32428
|
+
const ready = await this.waitForPickerRendered(action);
|
|
32429
|
+
const options = this.extractPickerChoices(action);
|
|
32430
|
+
const currentValue = options.find((o) => o.current)?.label;
|
|
32431
|
+
return {
|
|
32432
|
+
ok: true,
|
|
32433
|
+
effects: [{ type: "opened_picker", controlId: ctl.id }],
|
|
32434
|
+
controlResult: {
|
|
32435
|
+
options: options.map((o) => ({ value: o.label, label: o.label, current: o.current })),
|
|
32436
|
+
...currentValue ? { currentValue } : {},
|
|
32437
|
+
source: "screen-parse",
|
|
32438
|
+
...ready ? {} : { warning: "picker_render_timeout" }
|
|
32439
|
+
}
|
|
32440
|
+
};
|
|
32441
|
+
}
|
|
32442
|
+
/**
|
|
32443
|
+
* Drive an already-listable picker to a specific option. The option can be
|
|
32444
|
+
* named (choiceLabel — matched against the parsed on-screen labels) or
|
|
32445
|
+
* positional (choiceIndex — the on-screen number). The actual keystrokes
|
|
32446
|
+
* come from the spec's `submit_key` with `{index}` substituted, so the spec
|
|
32447
|
+
* — not this code — decides how a selection is keyed for each CLI.
|
|
32448
|
+
*/
|
|
32449
|
+
async selectPickerChoice(ctl, action, choiceIndex, choiceLabel) {
|
|
32450
|
+
this.driver.dispatch({ kind: "click_control", control_id: ctl.id });
|
|
32451
|
+
await this.waitForPickerRendered(action);
|
|
32452
|
+
const options = this.extractPickerChoices(action);
|
|
32453
|
+
let index = choiceIndex;
|
|
32454
|
+
if ((index == null || !Number.isFinite(index)) && choiceLabel) {
|
|
32455
|
+
const needle = choiceLabel.trim().toLowerCase();
|
|
32456
|
+
const match = options.find((o) => o.label.toLowerCase().includes(needle));
|
|
32457
|
+
if (!match) {
|
|
32458
|
+
return { ok: false, error: `choice not found on screen: ${choiceLabel}`, controlResult: { options: options.map((o) => ({ value: o.label, label: o.label })) } };
|
|
32459
|
+
}
|
|
32460
|
+
index = match.index;
|
|
32461
|
+
}
|
|
32462
|
+
if (index == null || !Number.isFinite(index)) {
|
|
32463
|
+
return { ok: false, error: "choiceIndex or choiceLabel required to select" };
|
|
32464
|
+
}
|
|
32465
|
+
const keys = (action.submit_key || "{index}\r").replace(/\{index\}/g, String(index));
|
|
32466
|
+
this.driver.dispatch({ kind: "pty_write", data: keys });
|
|
32467
|
+
const selected = options.find((o) => o.index === index);
|
|
32468
|
+
return {
|
|
32469
|
+
ok: true,
|
|
32470
|
+
effects: [{ type: "selected_choice", controlId: ctl.id }],
|
|
32471
|
+
controlResult: {
|
|
32472
|
+
ok: true,
|
|
32473
|
+
...selected ? { currentValue: selected.label } : {},
|
|
32474
|
+
selectedIndex: index
|
|
32475
|
+
}
|
|
32476
|
+
};
|
|
32477
|
+
}
|
|
32478
|
+
/** Poll the live screen until the picker's `wait_for` condition matches,
|
|
32479
|
+
* up to a short budget. Returns true if it rendered, false on timeout. */
|
|
32480
|
+
async waitForPickerRendered(action) {
|
|
32481
|
+
const wf = action.wait_for;
|
|
32482
|
+
if (!wf?.regex) {
|
|
32483
|
+
await delay(250);
|
|
32484
|
+
return true;
|
|
32485
|
+
}
|
|
32486
|
+
const re = new RegExp(wf.regex, wf.flags ?? "i");
|
|
32487
|
+
const deadline = Date.now() + 2500;
|
|
32488
|
+
while (Date.now() < deadline) {
|
|
32489
|
+
await delay(120);
|
|
32490
|
+
const hay = this.readScreenSectionText(wf.section);
|
|
32491
|
+
if (re.test(hay)) return true;
|
|
32492
|
+
}
|
|
32493
|
+
return false;
|
|
32494
|
+
}
|
|
32495
|
+
/** Parse the picker's `extract_choices` pattern against the live screen.
|
|
32496
|
+
* Each match yields { index, label, current }. `current` is true for the
|
|
32497
|
+
* line the CLI marks with its cursor glyph (❯ ›). Purely screen-driven —
|
|
32498
|
+
* no model/mode names are baked in. */
|
|
32499
|
+
extractPickerChoices(action) {
|
|
32500
|
+
const ec = action.extract_choices;
|
|
32501
|
+
if (!ec?.pattern) return [];
|
|
32502
|
+
const text = this.readScreenSectionText(ec.section);
|
|
32503
|
+
const out = [];
|
|
32504
|
+
const seen = /* @__PURE__ */ new Set();
|
|
32505
|
+
for (const rawLine of text.split("\n")) {
|
|
32506
|
+
const line = rawLine.replace(/\r$/, "");
|
|
32507
|
+
const m = new RegExp(ec.pattern, ec.flags ?? "").exec(line);
|
|
32508
|
+
if (!m) continue;
|
|
32509
|
+
const idx = Number(m[1]);
|
|
32510
|
+
if (!Number.isFinite(idx) || seen.has(idx)) continue;
|
|
32511
|
+
const label = (m[2] ?? "").replace(/\s+/g, " ").trim();
|
|
32512
|
+
if (!label) continue;
|
|
32513
|
+
const current = /^\s*[❯›>]/.test(line) || /[✔✓●]\s*$/.test(label);
|
|
32514
|
+
seen.add(idx);
|
|
32515
|
+
out.push({ index: idx, label, current });
|
|
32516
|
+
}
|
|
32517
|
+
return out;
|
|
32518
|
+
}
|
|
32519
|
+
/** Live text of a named screen section (or the whole screen when no
|
|
32520
|
+
* section is named), resolved from the driver's current sections. */
|
|
32521
|
+
readScreenSectionText(sectionId) {
|
|
32522
|
+
try {
|
|
32523
|
+
const sections = this.driver.getSections();
|
|
32524
|
+
if (sectionId && sections) {
|
|
32525
|
+
const hit = sections.find((s) => s.id === sectionId);
|
|
32526
|
+
if (hit) return hit.text;
|
|
32527
|
+
}
|
|
32528
|
+
return this.driver.getScreen();
|
|
32529
|
+
} catch {
|
|
32530
|
+
return "";
|
|
32531
|
+
}
|
|
32130
32532
|
}
|
|
32131
32533
|
getDebugSnapshot() {
|
|
32132
32534
|
let screen = "";
|
|
@@ -39077,7 +39479,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
39077
39479
|
}
|
|
39078
39480
|
if (providerDir) {
|
|
39079
39481
|
try {
|
|
39080
|
-
const
|
|
39482
|
+
const fs31 = require("fs");
|
|
39081
39483
|
const path41 = require("path");
|
|
39082
39484
|
const candidates = [];
|
|
39083
39485
|
if (Array.isArray(base.compatibility)) {
|
|
@@ -39089,13 +39491,13 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
39089
39491
|
}
|
|
39090
39492
|
candidates.push(path41.join(providerDir, "specs", "default.json"));
|
|
39091
39493
|
candidates.push(path41.join(providerDir, "spec.json"));
|
|
39092
|
-
const specPath = candidates.find((p) =>
|
|
39494
|
+
const specPath = candidates.find((p) => fs31.existsSync(p));
|
|
39093
39495
|
if (specPath) {
|
|
39094
39496
|
resolved._resolvedSpecPath = specPath;
|
|
39095
39497
|
let specControls;
|
|
39096
39498
|
let nh;
|
|
39097
39499
|
try {
|
|
39098
|
-
const rawSpec = JSON.parse(
|
|
39500
|
+
const rawSpec = JSON.parse(fs31.readFileSync(specPath, "utf8"));
|
|
39099
39501
|
specControls = rawSpec.control_bar;
|
|
39100
39502
|
nh = rawSpec.native_history;
|
|
39101
39503
|
} catch {
|
|
@@ -39120,7 +39522,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
39120
39522
|
reader = (input) => executeNativeHistory(nh, input);
|
|
39121
39523
|
} else if (nh.override_path) {
|
|
39122
39524
|
const overrideFile = path41.resolve(providerDir, nh.override_path);
|
|
39123
|
-
if (
|
|
39525
|
+
if (fs31.existsSync(overrideFile)) {
|
|
39124
39526
|
try {
|
|
39125
39527
|
registerProviderScriptRootSafely(path41.dirname(path41.dirname(providerDir)));
|
|
39126
39528
|
delete require.cache[require.resolve(overrideFile)];
|
|
@@ -40305,7 +40707,7 @@ async function detectCurrentWorkspace(ideId) {
|
|
|
40305
40707
|
}
|
|
40306
40708
|
} else if (plat === "win32") {
|
|
40307
40709
|
try {
|
|
40308
|
-
const
|
|
40710
|
+
const fs31 = require("fs");
|
|
40309
40711
|
const appNameMap = getMacAppIdentifiers();
|
|
40310
40712
|
const appName = appNameMap[ideId];
|
|
40311
40713
|
if (appName) {
|
|
@@ -40314,8 +40716,8 @@ async function detectCurrentWorkspace(ideId) {
|
|
|
40314
40716
|
appName,
|
|
40315
40717
|
"storage.json"
|
|
40316
40718
|
);
|
|
40317
|
-
if (
|
|
40318
|
-
const data = JSON.parse(
|
|
40719
|
+
if (fs31.existsSync(storagePath)) {
|
|
40720
|
+
const data = JSON.parse(fs31.readFileSync(storagePath, "utf-8"));
|
|
40319
40721
|
const workspaces = data?.openedPathsList?.workspaces3 || data?.openedPathsList?.entries || [];
|
|
40320
40722
|
if (workspaces.length > 0) {
|
|
40321
40723
|
const recent = workspaces[0];
|
|
@@ -40647,6 +41049,210 @@ cleanOldFiles();
|
|
|
40647
41049
|
// src/commands/router.ts
|
|
40648
41050
|
var yaml3 = __toESM(require("js-yaml"));
|
|
40649
41051
|
init_logger();
|
|
41052
|
+
|
|
41053
|
+
// src/logging/log-tail-reader.ts
|
|
41054
|
+
var fs23 = __toESM(require("fs"));
|
|
41055
|
+
init_logger();
|
|
41056
|
+
var DEFAULT_TAIL_BYTES = 64 * 1024;
|
|
41057
|
+
var MAX_TAIL_BYTES = 128 * 1024;
|
|
41058
|
+
var READ_CHUNK_BYTES = 64 * 1024;
|
|
41059
|
+
function resolveLogPath(date) {
|
|
41060
|
+
if (date instanceof Date) return getCurrentDaemonLogPath(date);
|
|
41061
|
+
if (typeof date === "string" && date.trim()) {
|
|
41062
|
+
const parsed = /* @__PURE__ */ new Date(`${date.trim()}T00:00:00.000Z`);
|
|
41063
|
+
if (!Number.isNaN(parsed.getTime())) return getCurrentDaemonLogPath(parsed);
|
|
41064
|
+
}
|
|
41065
|
+
return getCurrentDaemonLogPath();
|
|
41066
|
+
}
|
|
41067
|
+
function clampTailBytes(tailBytes) {
|
|
41068
|
+
if (!Number.isFinite(tailBytes) || tailBytes <= 0) return DEFAULT_TAIL_BYTES;
|
|
41069
|
+
return Math.min(Math.floor(tailBytes), MAX_TAIL_BYTES);
|
|
41070
|
+
}
|
|
41071
|
+
function readByteBoundedTail(filePath, limitBytes) {
|
|
41072
|
+
const fd = fs23.openSync(filePath, "r");
|
|
41073
|
+
try {
|
|
41074
|
+
const stat2 = fs23.fstatSync(fd);
|
|
41075
|
+
const size = stat2.size;
|
|
41076
|
+
if (size === 0) return { text: "", truncated: false, bytesReturned: 0 };
|
|
41077
|
+
const want = Math.min(limitBytes, size);
|
|
41078
|
+
let start = size - want;
|
|
41079
|
+
const truncated = start > 0;
|
|
41080
|
+
const buffers = [];
|
|
41081
|
+
let position = start;
|
|
41082
|
+
while (position < size) {
|
|
41083
|
+
const chunkSize = Math.min(READ_CHUNK_BYTES, size - position);
|
|
41084
|
+
const chunk = Buffer.alloc(chunkSize);
|
|
41085
|
+
fs23.readSync(fd, chunk, 0, chunkSize, position);
|
|
41086
|
+
buffers.push(chunk);
|
|
41087
|
+
position += chunkSize;
|
|
41088
|
+
}
|
|
41089
|
+
let buf = Buffer.concat(buffers);
|
|
41090
|
+
if (truncated) {
|
|
41091
|
+
const firstNewline = buf.indexOf(10);
|
|
41092
|
+
if (firstNewline >= 0) {
|
|
41093
|
+
buf = buf.subarray(firstNewline + 1);
|
|
41094
|
+
}
|
|
41095
|
+
}
|
|
41096
|
+
return { text: buf.toString("utf-8"), truncated, bytesReturned: buf.length };
|
|
41097
|
+
} finally {
|
|
41098
|
+
fs23.closeSync(fd);
|
|
41099
|
+
}
|
|
41100
|
+
}
|
|
41101
|
+
function parseLineEpochMs(line, fileDate) {
|
|
41102
|
+
const m = line.match(/^\[(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?\]/);
|
|
41103
|
+
if (!m) {
|
|
41104
|
+
const iso = line.match(/\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?/);
|
|
41105
|
+
if (iso) {
|
|
41106
|
+
const t = Date.parse(iso[0].replace(" ", "T"));
|
|
41107
|
+
return Number.isNaN(t) ? null : t;
|
|
41108
|
+
}
|
|
41109
|
+
return null;
|
|
41110
|
+
}
|
|
41111
|
+
const d = new Date(fileDate);
|
|
41112
|
+
d.setHours(Number(m[1]), Number(m[2]), Number(m[3]), m[4] ? Number(m[4].padEnd(3, "0")) : 0);
|
|
41113
|
+
return d.getTime();
|
|
41114
|
+
}
|
|
41115
|
+
function readDaemonLogTail(args = {}) {
|
|
41116
|
+
const platform10 = process.platform;
|
|
41117
|
+
const limitBytes = clampTailBytes(args.tailBytes);
|
|
41118
|
+
let logPath = resolveLogPath(args.date);
|
|
41119
|
+
if (!fs23.existsSync(logPath)) {
|
|
41120
|
+
const backup = logPath.replace(/\.log$/, ".1.log");
|
|
41121
|
+
if (fs23.existsSync(backup)) {
|
|
41122
|
+
logPath = backup;
|
|
41123
|
+
} else {
|
|
41124
|
+
return {
|
|
41125
|
+
success: false,
|
|
41126
|
+
error: `No daemon log file at ${logPath} (dir: ${getDaemonLogDir()})`,
|
|
41127
|
+
lines: [],
|
|
41128
|
+
truncated: false,
|
|
41129
|
+
logPath,
|
|
41130
|
+
platform: platform10,
|
|
41131
|
+
bytesReturned: 0,
|
|
41132
|
+
filtered: false
|
|
41133
|
+
};
|
|
41134
|
+
}
|
|
41135
|
+
}
|
|
41136
|
+
let raw;
|
|
41137
|
+
try {
|
|
41138
|
+
raw = readByteBoundedTail(logPath, limitBytes);
|
|
41139
|
+
} catch (e) {
|
|
41140
|
+
return {
|
|
41141
|
+
success: false,
|
|
41142
|
+
error: `Failed to read ${logPath}: ${e?.message ?? String(e)}`,
|
|
41143
|
+
lines: [],
|
|
41144
|
+
truncated: false,
|
|
41145
|
+
logPath,
|
|
41146
|
+
platform: platform10,
|
|
41147
|
+
bytesReturned: 0,
|
|
41148
|
+
filtered: false
|
|
41149
|
+
};
|
|
41150
|
+
}
|
|
41151
|
+
let lines = raw.text.split("\n");
|
|
41152
|
+
if (lines.length && lines[lines.length - 1] === "") lines.pop();
|
|
41153
|
+
const rawCount = lines.length;
|
|
41154
|
+
if (Number.isFinite(args.sinceMs)) {
|
|
41155
|
+
const fileDate = args.date instanceof Date ? args.date : typeof args.date === "string" && args.date.trim() ? /* @__PURE__ */ new Date(`${args.date.trim()}T00:00:00.000Z`) : /* @__PURE__ */ new Date();
|
|
41156
|
+
const floor = args.sinceMs;
|
|
41157
|
+
lines = lines.filter((line) => {
|
|
41158
|
+
const ts2 = parseLineEpochMs(line, fileDate);
|
|
41159
|
+
return ts2 === null || ts2 >= floor;
|
|
41160
|
+
});
|
|
41161
|
+
}
|
|
41162
|
+
let appliedGrep;
|
|
41163
|
+
if (typeof args.grep === "string" && args.grep.trim()) {
|
|
41164
|
+
appliedGrep = args.grep.trim();
|
|
41165
|
+
let re = null;
|
|
41166
|
+
try {
|
|
41167
|
+
re = new RegExp(appliedGrep, "i");
|
|
41168
|
+
} catch {
|
|
41169
|
+
re = null;
|
|
41170
|
+
}
|
|
41171
|
+
if (re) {
|
|
41172
|
+
const compiled = re;
|
|
41173
|
+
lines = lines.filter((line) => compiled.test(line));
|
|
41174
|
+
} else {
|
|
41175
|
+
const needle = appliedGrep.toLowerCase();
|
|
41176
|
+
lines = lines.filter((line) => line.toLowerCase().includes(needle));
|
|
41177
|
+
}
|
|
41178
|
+
}
|
|
41179
|
+
return {
|
|
41180
|
+
success: true,
|
|
41181
|
+
lines,
|
|
41182
|
+
truncated: raw.truncated,
|
|
41183
|
+
logPath,
|
|
41184
|
+
platform: platform10,
|
|
41185
|
+
bytesReturned: raw.bytesReturned,
|
|
41186
|
+
filtered: lines.length !== rawCount,
|
|
41187
|
+
...appliedGrep ? { grep: appliedGrep } : {}
|
|
41188
|
+
};
|
|
41189
|
+
}
|
|
41190
|
+
|
|
41191
|
+
// src/logging/log-redactor.ts
|
|
41192
|
+
var MASK = "\u2022\u2022\u2022\u2022redacted";
|
|
41193
|
+
function maskKeepTail(token) {
|
|
41194
|
+
if (token.length <= 8) return MASK;
|
|
41195
|
+
return `${MASK}${token.slice(-4)}`;
|
|
41196
|
+
}
|
|
41197
|
+
var RULES = [
|
|
41198
|
+
// `JWT_SECRET=...`, `TOKEN=...`, `API_KEY=...`, `password: ...` env/config dumps.
|
|
41199
|
+
// Captures the key + delimiter and masks only the value.
|
|
41200
|
+
{
|
|
41201
|
+
name: "key_value_secret",
|
|
41202
|
+
pattern: /\b([A-Z0-9_]*(?:SECRET|TOKEN|API[_-]?KEY|PASSWORD|PASSWD|PRIVATE[_-]?KEY|CREDENTIAL|CLIENT[_-]?SECRET)[A-Z0-9_]*)(\s*[:=]\s*)(["']?)([^\s"',;]+)\3/gi,
|
|
41203
|
+
replace: (_m, key, delim, quote) => `${key}${delim}${quote}${MASK}${quote}`
|
|
41204
|
+
},
|
|
41205
|
+
// Authorization: Bearer <token>
|
|
41206
|
+
{
|
|
41207
|
+
name: "bearer_token",
|
|
41208
|
+
pattern: /\b(Bearer\s+)([A-Za-z0-9._\-+/=]{8,})/g,
|
|
41209
|
+
replace: (_m, prefix, token) => `${prefix}${maskKeepTail(token)}`
|
|
41210
|
+
},
|
|
41211
|
+
// ADHDev credential prefixes: API key (adk_), machine secret (adm_), provider key (adp_).
|
|
41212
|
+
{
|
|
41213
|
+
name: "adhdev_prefixed_secret",
|
|
41214
|
+
pattern: /\b(ad[kmp]_)([A-Za-z0-9]{6,})/g,
|
|
41215
|
+
replace: (_m, prefix, token) => `${prefix}${maskKeepTail(prefix + token)}`
|
|
41216
|
+
},
|
|
41217
|
+
// JWT: three base64url segments separated by dots, header starts with eyJ.
|
|
41218
|
+
{
|
|
41219
|
+
name: "jwt",
|
|
41220
|
+
pattern: /\beyJ[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{4,}/g,
|
|
41221
|
+
replace: () => MASK
|
|
41222
|
+
},
|
|
41223
|
+
// TURN credential: a long credential value following a `credential` key in
|
|
41224
|
+
// any common shape — `credential: x`, `credential=x`, or `credential "x"`.
|
|
41225
|
+
// Mask the credential value only, preserving the key + delimiter/quote.
|
|
41226
|
+
{
|
|
41227
|
+
name: "turn_credential",
|
|
41228
|
+
pattern: /\b(credential["']?\s*(?:[:=]\s*)?["']?)([^\s"',;]{6,})/gi,
|
|
41229
|
+
replace: (_m, prefix) => `${prefix}${MASK}`
|
|
41230
|
+
},
|
|
41231
|
+
// TURN REST username:credential of the form `<expiry-ts>:<base64hmac>`,
|
|
41232
|
+
// where the hmac part is long base64. Mask the hmac.
|
|
41233
|
+
{
|
|
41234
|
+
name: "turn_rest_pair",
|
|
41235
|
+
pattern: /\b(\d{10,}:)([A-Za-z0-9+/]{20,}={0,2})\b/g,
|
|
41236
|
+
replace: (_m, prefix) => `${prefix}${MASK}`
|
|
41237
|
+
}
|
|
41238
|
+
];
|
|
41239
|
+
function redactLogLine(line) {
|
|
41240
|
+
if (!line) return line;
|
|
41241
|
+
let out = line;
|
|
41242
|
+
for (const rule of RULES) {
|
|
41243
|
+
try {
|
|
41244
|
+
out = out.replace(rule.pattern, rule.replace);
|
|
41245
|
+
} catch {
|
|
41246
|
+
}
|
|
41247
|
+
}
|
|
41248
|
+
return out;
|
|
41249
|
+
}
|
|
41250
|
+
function redactLogLines(lines) {
|
|
41251
|
+
return lines.map((line) => redactLogLine(line));
|
|
41252
|
+
}
|
|
41253
|
+
var LOG_REDACTION_RULE_NAMES = RULES.map((r) => r.name);
|
|
41254
|
+
|
|
41255
|
+
// src/commands/router.ts
|
|
40650
41256
|
init_mesh_coordinator();
|
|
40651
41257
|
init_mesh_events();
|
|
40652
41258
|
init_mesh_routing();
|
|
@@ -41291,21 +41897,21 @@ init_build_info();
|
|
|
41291
41897
|
// src/commands/upgrade-helper.ts
|
|
41292
41898
|
var import_child_process8 = require("child_process");
|
|
41293
41899
|
var import_child_process9 = require("child_process");
|
|
41294
|
-
var
|
|
41900
|
+
var fs24 = __toESM(require("fs"));
|
|
41295
41901
|
var os27 = __toESM(require("os"));
|
|
41296
41902
|
var path35 = __toESM(require("path"));
|
|
41297
41903
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
41298
41904
|
function getUpgradeLogPath() {
|
|
41299
41905
|
const home = os27.homedir();
|
|
41300
41906
|
const dir = path35.join(home, ".adhdev");
|
|
41301
|
-
|
|
41907
|
+
fs24.mkdirSync(dir, { recursive: true });
|
|
41302
41908
|
return path35.join(dir, "daemon-upgrade.log");
|
|
41303
41909
|
}
|
|
41304
41910
|
function appendUpgradeLog(message) {
|
|
41305
41911
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
41306
41912
|
`;
|
|
41307
41913
|
try {
|
|
41308
|
-
|
|
41914
|
+
fs24.appendFileSync(getUpgradeLogPath(), line, "utf8");
|
|
41309
41915
|
} catch {
|
|
41310
41916
|
}
|
|
41311
41917
|
}
|
|
@@ -41313,12 +41919,12 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
41313
41919
|
const binDir = path35.dirname(nodeExecutable);
|
|
41314
41920
|
if (platform10 === "win32") {
|
|
41315
41921
|
const npmCliPath = path35.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
41316
|
-
if (
|
|
41922
|
+
if (fs24.existsSync(npmCliPath)) {
|
|
41317
41923
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
41318
41924
|
}
|
|
41319
41925
|
for (const candidate of ["npm.exe", "npm"]) {
|
|
41320
41926
|
const candidatePath = path35.join(binDir, candidate);
|
|
41321
|
-
if (
|
|
41927
|
+
if (fs24.existsSync(candidatePath)) {
|
|
41322
41928
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
41323
41929
|
}
|
|
41324
41930
|
}
|
|
@@ -41326,7 +41932,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
41326
41932
|
}
|
|
41327
41933
|
for (const candidate of ["npm"]) {
|
|
41328
41934
|
const candidatePath = path35.join(binDir, candidate);
|
|
41329
|
-
if (
|
|
41935
|
+
if (fs24.existsSync(candidatePath)) {
|
|
41330
41936
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
41331
41937
|
}
|
|
41332
41938
|
}
|
|
@@ -41336,12 +41942,12 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
41336
41942
|
if (!currentCliPath) return null;
|
|
41337
41943
|
let resolvedPath = currentCliPath;
|
|
41338
41944
|
try {
|
|
41339
|
-
resolvedPath =
|
|
41945
|
+
resolvedPath = fs24.realpathSync.native(currentCliPath);
|
|
41340
41946
|
} catch {
|
|
41341
41947
|
}
|
|
41342
41948
|
let currentDir = resolvedPath;
|
|
41343
41949
|
try {
|
|
41344
|
-
if (
|
|
41950
|
+
if (fs24.statSync(resolvedPath).isFile()) {
|
|
41345
41951
|
currentDir = path35.dirname(resolvedPath);
|
|
41346
41952
|
}
|
|
41347
41953
|
} catch {
|
|
@@ -41350,8 +41956,8 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
41350
41956
|
while (true) {
|
|
41351
41957
|
const packageJsonPath = path35.join(currentDir, "package.json");
|
|
41352
41958
|
try {
|
|
41353
|
-
if (
|
|
41354
|
-
const parsed = JSON.parse(
|
|
41959
|
+
if (fs24.existsSync(packageJsonPath)) {
|
|
41960
|
+
const parsed = JSON.parse(fs24.readFileSync(packageJsonPath, "utf8"));
|
|
41355
41961
|
if (parsed?.name === packageName) {
|
|
41356
41962
|
const normalized = currentDir.replace(/\\/g, "/");
|
|
41357
41963
|
return normalized.includes("/node_modules/") ? currentDir : null;
|
|
@@ -41500,8 +42106,8 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
41500
42106
|
function stopSessionHostProcesses(appName) {
|
|
41501
42107
|
const pidFile = path35.join(os27.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
41502
42108
|
try {
|
|
41503
|
-
if (
|
|
41504
|
-
const pid = Number.parseInt(
|
|
42109
|
+
if (fs24.existsSync(pidFile)) {
|
|
42110
|
+
const pid = Number.parseInt(fs24.readFileSync(pidFile, "utf8").trim(), 10);
|
|
41505
42111
|
if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
|
|
41506
42112
|
killPid(pid);
|
|
41507
42113
|
}
|
|
@@ -41509,7 +42115,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
41509
42115
|
} catch {
|
|
41510
42116
|
} finally {
|
|
41511
42117
|
try {
|
|
41512
|
-
|
|
42118
|
+
fs24.unlinkSync(pidFile);
|
|
41513
42119
|
} catch {
|
|
41514
42120
|
}
|
|
41515
42121
|
}
|
|
@@ -41517,7 +42123,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
41517
42123
|
function removeDaemonPidFile() {
|
|
41518
42124
|
const pidFile = path35.join(os27.homedir(), ".adhdev", "daemon.pid");
|
|
41519
42125
|
try {
|
|
41520
|
-
|
|
42126
|
+
fs24.unlinkSync(pidFile);
|
|
41521
42127
|
} catch {
|
|
41522
42128
|
}
|
|
41523
42129
|
}
|
|
@@ -41535,23 +42141,23 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
41535
42141
|
if (pkgName.startsWith("@")) {
|
|
41536
42142
|
const [scope, name] = pkgName.split("/");
|
|
41537
42143
|
const scopeDir = path35.join(npmRoot, scope);
|
|
41538
|
-
if (!
|
|
41539
|
-
for (const entry of
|
|
42144
|
+
if (!fs24.existsSync(scopeDir)) return;
|
|
42145
|
+
for (const entry of fs24.readdirSync(scopeDir)) {
|
|
41540
42146
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
41541
|
-
|
|
42147
|
+
fs24.rmSync(path35.join(scopeDir, entry), { recursive: true, force: true });
|
|
41542
42148
|
appendUpgradeLog(`Removed stale scoped staging dir: ${path35.join(scopeDir, entry)}`);
|
|
41543
42149
|
}
|
|
41544
42150
|
} else {
|
|
41545
|
-
for (const entry of
|
|
42151
|
+
for (const entry of fs24.readdirSync(npmRoot)) {
|
|
41546
42152
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
41547
|
-
|
|
42153
|
+
fs24.rmSync(path35.join(npmRoot, entry), { recursive: true, force: true });
|
|
41548
42154
|
appendUpgradeLog(`Removed stale staging dir: ${path35.join(npmRoot, entry)}`);
|
|
41549
42155
|
}
|
|
41550
42156
|
}
|
|
41551
|
-
if (
|
|
41552
|
-
for (const entry of
|
|
42157
|
+
if (fs24.existsSync(binDir)) {
|
|
42158
|
+
for (const entry of fs24.readdirSync(binDir)) {
|
|
41553
42159
|
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
41554
|
-
|
|
42160
|
+
fs24.rmSync(path35.join(binDir, entry), { recursive: true, force: true });
|
|
41555
42161
|
appendUpgradeLog(`Removed stale bin staging entry: ${path35.join(binDir, entry)}`);
|
|
41556
42162
|
}
|
|
41557
42163
|
}
|
|
@@ -41642,7 +42248,7 @@ init_mesh_work_queue();
|
|
|
41642
42248
|
init_repo_mesh_types();
|
|
41643
42249
|
var import_os3 = require("os");
|
|
41644
42250
|
var import_path11 = require("path");
|
|
41645
|
-
var
|
|
42251
|
+
var fs25 = __toESM(require("fs"));
|
|
41646
42252
|
var import_node_child_process6 = require("child_process");
|
|
41647
42253
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
41648
42254
|
var CHANNEL_SERVER_URL = {
|
|
@@ -41968,6 +42574,12 @@ function inlineMeshCarriesTransientNodeTruth(inlineMesh) {
|
|
|
41968
42574
|
function readInlineMeshNodeId(node) {
|
|
41969
42575
|
return normalizeMeshNodeId(node) ?? "";
|
|
41970
42576
|
}
|
|
42577
|
+
function isDeadLocalWorktreeNode(node) {
|
|
42578
|
+
if (node?.isLocalWorktree !== true) return false;
|
|
42579
|
+
const workspace = readStringValue(node?.workspace);
|
|
42580
|
+
if (!workspace) return false;
|
|
42581
|
+
return !fs25.existsSync(workspace);
|
|
42582
|
+
}
|
|
41971
42583
|
function foldMeshNodeIdentityToCanonical(node) {
|
|
41972
42584
|
if (!node || typeof node !== "object" || Array.isArray(node)) return node;
|
|
41973
42585
|
const canonical = normalizeMeshNodeId(node);
|
|
@@ -42214,7 +42826,7 @@ function summarizeInlineMeshBranchConvergence(nodes) {
|
|
|
42214
42826
|
const followUps = nodes.filter((node) => {
|
|
42215
42827
|
if (readObjectRecord(node.branchConvergence).needsConvergence !== true) return false;
|
|
42216
42828
|
const workspace = typeof node.workspace === "string" ? node.workspace : "";
|
|
42217
|
-
if (workspace && !
|
|
42829
|
+
if (workspace && !fs25.existsSync(workspace)) return false;
|
|
42218
42830
|
return true;
|
|
42219
42831
|
}).map((node) => {
|
|
42220
42832
|
const convergence = readObjectRecord(node.branchConvergence);
|
|
@@ -42342,6 +42954,43 @@ function readMeshTimeoutEnvMs(name, defaultMs) {
|
|
|
42342
42954
|
}
|
|
42343
42955
|
var MESH_DIRECT_PROBE_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_TIMEOUT_MS", 25e3);
|
|
42344
42956
|
var MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS", 25e3);
|
|
42957
|
+
var MESH_DIRECT_PROBE_REUSE_MS = readMeshTimeoutEnvMs("MESH_DIRECT_PROBE_REUSE_MS", 12e3);
|
|
42958
|
+
var MeshGitProbeCache = class {
|
|
42959
|
+
constructor(reuseMs, now = Date.now) {
|
|
42960
|
+
this.reuseMs = reuseMs;
|
|
42961
|
+
this.now = now;
|
|
42962
|
+
}
|
|
42963
|
+
inflight = /* @__PURE__ */ new Map();
|
|
42964
|
+
recent = /* @__PURE__ */ new Map();
|
|
42965
|
+
key(daemonId, workspace) {
|
|
42966
|
+
return `${daemonId}::${workspace}`;
|
|
42967
|
+
}
|
|
42968
|
+
/**
|
|
42969
|
+
* Run `probe` for this peer, but reuse a fresh recent result or an in-flight
|
|
42970
|
+
* probe for the same key when one is available. `probe` is only invoked when
|
|
42971
|
+
* neither gate is satisfied.
|
|
42972
|
+
*/
|
|
42973
|
+
async probe(daemonId, workspace, probe) {
|
|
42974
|
+
const key = this.key(daemonId, workspace);
|
|
42975
|
+
const cached2 = this.recent.get(key);
|
|
42976
|
+
if (cached2 && this.now() - cached2.at < this.reuseMs) {
|
|
42977
|
+
return cached2.value;
|
|
42978
|
+
}
|
|
42979
|
+
const existing = this.inflight.get(key);
|
|
42980
|
+
if (existing) return existing;
|
|
42981
|
+
const pending = (async () => {
|
|
42982
|
+
const result = await probe();
|
|
42983
|
+
if (result) this.recent.set(key, { at: this.now(), value: result });
|
|
42984
|
+
return result;
|
|
42985
|
+
})();
|
|
42986
|
+
this.inflight.set(key, pending);
|
|
42987
|
+
try {
|
|
42988
|
+
return await pending;
|
|
42989
|
+
} finally {
|
|
42990
|
+
if (this.inflight.get(key) === pending) this.inflight.delete(key);
|
|
42991
|
+
}
|
|
42992
|
+
}
|
|
42993
|
+
};
|
|
42345
42994
|
async function probeRemoteMeshGitStatus(args) {
|
|
42346
42995
|
if (!args.dispatchMeshCommand) return null;
|
|
42347
42996
|
const remoteResult = await Promise.race([
|
|
@@ -42385,7 +43034,8 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42385
43034
|
peerAttemptedCount: 0,
|
|
42386
43035
|
peerConfirmedCount: 0,
|
|
42387
43036
|
standingEvidenceCount: 0,
|
|
42388
|
-
unavailableNodeIds: []
|
|
43037
|
+
unavailableNodeIds: [],
|
|
43038
|
+
deadNodeIds: []
|
|
42389
43039
|
};
|
|
42390
43040
|
}
|
|
42391
43041
|
const selectedCoordinatorNodeId = readStringValue(
|
|
@@ -42398,6 +43048,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42398
43048
|
let peerConfirmedCount = 0;
|
|
42399
43049
|
let standingEvidenceCount = 0;
|
|
42400
43050
|
const unavailableNodeIds = [];
|
|
43051
|
+
const deadNodeIds = [];
|
|
42401
43052
|
for (const [nodeIndex, node] of nodes.entries()) {
|
|
42402
43053
|
const nodeId = normalizeMeshNodeId(node) || `node_${nodeIndex}`;
|
|
42403
43054
|
const workspace = readStringValue(node?.workspace);
|
|
@@ -42407,11 +43058,18 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42407
43058
|
) || Boolean(
|
|
42408
43059
|
daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
|
|
42409
43060
|
) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
|
|
43061
|
+
const isSelfDaemonNode = Boolean(
|
|
43062
|
+
daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
|
|
43063
|
+
);
|
|
43064
|
+
if ((isSelfNode || isSelfDaemonNode) && isDeadLocalWorktreeNode(node)) {
|
|
43065
|
+
deadNodeIds.push(nodeId);
|
|
43066
|
+
continue;
|
|
43067
|
+
}
|
|
42410
43068
|
if (!workspace) {
|
|
42411
43069
|
if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
|
|
42412
43070
|
continue;
|
|
42413
43071
|
}
|
|
42414
|
-
if (
|
|
43072
|
+
if (fs25.existsSync(workspace)) {
|
|
42415
43073
|
try {
|
|
42416
43074
|
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
42417
43075
|
if (localGit?.isGitRepo) {
|
|
@@ -42435,7 +43093,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42435
43093
|
continue;
|
|
42436
43094
|
}
|
|
42437
43095
|
peerAttemptedCount += 1;
|
|
42438
|
-
const
|
|
43096
|
+
const runProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
42439
43097
|
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
42440
43098
|
daemonId,
|
|
42441
43099
|
workspace,
|
|
@@ -42443,6 +43101,7 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42443
43101
|
retryTimeoutMs: MESH_DIRECT_PROBE_RETRY_TIMEOUT_MS,
|
|
42444
43102
|
getConnection: args.getMeshPeerConnectionStatus
|
|
42445
43103
|
});
|
|
43104
|
+
const remoteGit = args.probeCache ? await args.probeCache.probe(daemonId, workspace, runProbe) : await runProbe();
|
|
42446
43105
|
if (remoteGit) {
|
|
42447
43106
|
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
42448
43107
|
peerConfirmedCount += 1;
|
|
@@ -42456,7 +43115,8 @@ async function hydrateInlineMeshDirectTruth(args) {
|
|
|
42456
43115
|
peerAttemptedCount,
|
|
42457
43116
|
peerConfirmedCount,
|
|
42458
43117
|
standingEvidenceCount,
|
|
42459
|
-
unavailableNodeIds
|
|
43118
|
+
unavailableNodeIds,
|
|
43119
|
+
deadNodeIds
|
|
42460
43120
|
};
|
|
42461
43121
|
}
|
|
42462
43122
|
function summarizeMeshSessionRecord(record) {
|
|
@@ -42515,7 +43175,7 @@ function readLiveMeshNodeWorkspace(args) {
|
|
|
42515
43175
|
}
|
|
42516
43176
|
function collectLiveMeshSessionRecords(args) {
|
|
42517
43177
|
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
42518
|
-
const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true && !!nodeWorkspace && !
|
|
43178
|
+
const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true && !!nodeWorkspace && !fs25.existsSync(nodeWorkspace);
|
|
42519
43179
|
const matches = args.liveSessionRecords.filter((record) => {
|
|
42520
43180
|
const recordNodeId = readStringValue(record?.meta?.meshNodeId);
|
|
42521
43181
|
if (recordNodeId && recordNodeId !== args.nodeId) return false;
|
|
@@ -42542,7 +43202,7 @@ function buildHistoricalMeshSessions(args) {
|
|
|
42542
43202
|
const workspace = readStringValue(node?.workspace);
|
|
42543
43203
|
if (nodeId) liveNodeIds.add(nodeId);
|
|
42544
43204
|
if (workspace) liveWorkspaces.add(workspace);
|
|
42545
|
-
if (nodeId && node?.isLocalWorktree === true && workspace && !
|
|
43205
|
+
if (nodeId && node?.isLocalWorktree === true && workspace && !fs25.existsSync(workspace)) {
|
|
42546
43206
|
missingLocalWorktreeNodeIds.add(nodeId);
|
|
42547
43207
|
}
|
|
42548
43208
|
}
|
|
@@ -42902,7 +43562,7 @@ function isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit) {
|
|
|
42902
43562
|
if (!baseCommit || !branchCommit) return false;
|
|
42903
43563
|
if (baseCommit === branchCommit) return true;
|
|
42904
43564
|
try {
|
|
42905
|
-
if (!
|
|
43565
|
+
if (!fs25.existsSync(submoduleRepoPath)) return false;
|
|
42906
43566
|
(0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${baseCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
42907
43567
|
(0, import_node_child_process6.execFileSync)("git", ["cat-file", "-e", `${branchCommit}^{commit}`], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
42908
43568
|
(0, import_node_child_process6.execFileSync)("git", ["merge-base", "--is-ancestor", baseCommit, branchCommit], { cwd: submoduleRepoPath, stdio: "ignore" });
|
|
@@ -43019,7 +43679,7 @@ function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderC
|
|
|
43019
43679
|
return newTree || void 0;
|
|
43020
43680
|
} finally {
|
|
43021
43681
|
try {
|
|
43022
|
-
|
|
43682
|
+
fs25.rmSync(tmpIndex, { force: true });
|
|
43023
43683
|
} catch {
|
|
43024
43684
|
}
|
|
43025
43685
|
}
|
|
@@ -43094,7 +43754,7 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
43094
43754
|
return newTree || void 0;
|
|
43095
43755
|
} finally {
|
|
43096
43756
|
try {
|
|
43097
|
-
|
|
43757
|
+
fs25.rmSync(tmpIndex, { force: true });
|
|
43098
43758
|
} catch {
|
|
43099
43759
|
}
|
|
43100
43760
|
}
|
|
@@ -43200,7 +43860,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
|
|
|
43200
43860
|
return { stdout: String(stdout || ""), stderr: String(stderr || ""), refspec };
|
|
43201
43861
|
};
|
|
43202
43862
|
const importCommitFromWorktreeSubmodule = async (submodulePath, worktreeSubmodulePath, commit) => {
|
|
43203
|
-
if (!
|
|
43863
|
+
if (!fs25.existsSync(worktreeSubmodulePath)) return false;
|
|
43204
43864
|
try {
|
|
43205
43865
|
await runGit3(worktreeSubmodulePath, ["cat-file", "-e", `${commit}^{commit}`]);
|
|
43206
43866
|
} catch {
|
|
@@ -43223,7 +43883,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
|
|
|
43223
43883
|
reachable: false
|
|
43224
43884
|
};
|
|
43225
43885
|
try {
|
|
43226
|
-
if (!
|
|
43886
|
+
if (!fs25.existsSync(submodulePath)) {
|
|
43227
43887
|
entry.error = `Submodule checkout missing at ${gitlink.path}`;
|
|
43228
43888
|
entry.publishRequired = true;
|
|
43229
43889
|
if (options.allowAutoPublishSubmoduleMainCommits === true) {
|
|
@@ -43460,9 +44120,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
43460
44120
|
return ["npm", "pnpm", "yarn", "bun"].includes(command) && candidate.args.some((arg) => arg === "run" || arg === "test" || arg === "exec");
|
|
43461
44121
|
};
|
|
43462
44122
|
const dependenciesLikelyMissing = (cwd) => {
|
|
43463
|
-
if (!
|
|
43464
|
-
if (
|
|
43465
|
-
return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) =>
|
|
44123
|
+
if (!fs25.existsSync((0, import_path11.join)(cwd, "package.json"))) return false;
|
|
44124
|
+
if (fs25.existsSync((0, import_path11.join)(cwd, "node_modules"))) return false;
|
|
44125
|
+
return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) => fs25.existsSync((0, import_path11.join)(cwd, lock)));
|
|
43466
44126
|
};
|
|
43467
44127
|
if (runLegacyBootstrapCommands) {
|
|
43468
44128
|
summary.bootstrap = { stage: "legacy" };
|
|
@@ -43564,9 +44224,9 @@ function resolveHermesUserHome() {
|
|
|
43564
44224
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
43565
44225
|
const sourceHome = resolveHermesUserHome();
|
|
43566
44226
|
const sourceConfigPath = (0, import_path11.join)(sourceHome, "config.yaml");
|
|
43567
|
-
if (!
|
|
44227
|
+
if (!fs25.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
43568
44228
|
if ((0, import_path11.resolve)(sourceConfigPath) === (0, import_path11.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
43569
|
-
const parsed = parseMeshCoordinatorMcpConfig(
|
|
44229
|
+
const parsed = parseMeshCoordinatorMcpConfig(fs25.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
43570
44230
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
43571
44231
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
43572
44232
|
}
|
|
@@ -43603,9 +44263,9 @@ function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
|
43603
44263
|
for (const fileName of [".env", "auth.json"]) {
|
|
43604
44264
|
const sourcePath = (0, import_path11.join)(sourceHome, fileName);
|
|
43605
44265
|
const targetPath = (0, import_path11.join)(targetHome, fileName);
|
|
43606
|
-
if (!
|
|
44266
|
+
if (!fs25.existsSync(sourcePath)) continue;
|
|
43607
44267
|
try {
|
|
43608
|
-
|
|
44268
|
+
fs25.copyFileSync(sourcePath, targetPath);
|
|
43609
44269
|
} catch (error) {
|
|
43610
44270
|
LOG.warn("MeshCoordinator", `Could not copy Hermes ${fileName} into isolated coordinator home: ${error?.message || error}`);
|
|
43611
44271
|
}
|
|
@@ -43763,8 +44423,21 @@ var DaemonCommandRouter = class {
|
|
|
43763
44423
|
* Allows the MCP server to query mesh data via get_mesh even when
|
|
43764
44424
|
* the mesh doesn't exist in the local meshes.json file. */
|
|
43765
44425
|
inlineMeshCache = /* @__PURE__ */ new Map();
|
|
44426
|
+
/** Tombstones for inline mesh nodes removed via remove_mesh_node, keyed by
|
|
44427
|
+
* meshId → set of removed nodeIds. The dashboard keeps echoing the removed
|
|
44428
|
+
* node in the inlineMesh it attaches to every command; without a tombstone,
|
|
44429
|
+
* reconcileInlineMeshCache MERGEs it straight back (resurrection). A
|
|
44430
|
+
* tombstoned node is skipped during reconcile only while its workspace is
|
|
44431
|
+
* absent from disk — a genuine re-registration (same nodeId, workspace back
|
|
44432
|
+
* on disk) clears the tombstone and merges normally, preserving clone
|
|
44433
|
+
* worktree visibility and legitimate node re-creation. */
|
|
44434
|
+
removedInlineMeshNodeIds = /* @__PURE__ */ new Map();
|
|
43766
44435
|
/** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
|
|
43767
44436
|
aggregateMeshStatusCache = /* @__PURE__ */ new Map();
|
|
44437
|
+
/** Shared per-peer git_status probe dedup + recently-probed reuse gate.
|
|
44438
|
+
* Spans separate mesh_status/get_mesh calls so the dashboard auto-retry
|
|
44439
|
+
* loop cannot storm a slow peer with back-to-back refreshUpstream probes. */
|
|
44440
|
+
meshGitProbeCache = new MeshGitProbeCache(MESH_DIRECT_PROBE_REUSE_MS);
|
|
43768
44441
|
/** In-memory async Refinery jobs keyed by meshId:nodeId to reject/return duplicate in-flight requests. */
|
|
43769
44442
|
runningRefineJobs = /* @__PURE__ */ new Map();
|
|
43770
44443
|
/** Terminal async Refinery jobs preserve a clear answer after the worktree node has been removed. */
|
|
@@ -43792,10 +44465,23 @@ var DaemonCommandRouter = class {
|
|
|
43792
44465
|
const unavailableNodeIds = /* @__PURE__ */ new Set();
|
|
43793
44466
|
const sourceOfTruth = readObjectRecord(snapshot.sourceOfTruth);
|
|
43794
44467
|
const directPeerTruth = readObjectRecord(sourceOfTruth.directPeerTruth);
|
|
44468
|
+
const deadNodeIds = /* @__PURE__ */ new Set();
|
|
44469
|
+
for (const node of mesh.nodes) {
|
|
44470
|
+
if (!isDeadLocalWorktreeNode(node)) continue;
|
|
44471
|
+
const deadId = readInlineMeshNodeId(node);
|
|
44472
|
+
if (deadId) deadNodeIds.add(deadId);
|
|
44473
|
+
}
|
|
44474
|
+
let droppedDeadUnavailable = false;
|
|
43795
44475
|
for (const entry of Array.isArray(directPeerTruth.unavailableNodeIds) ? directPeerTruth.unavailableNodeIds : []) {
|
|
43796
44476
|
const nodeId = readStringValue(entry);
|
|
43797
|
-
if (nodeId)
|
|
44477
|
+
if (!nodeId) continue;
|
|
44478
|
+
if (deadNodeIds.has(nodeId)) {
|
|
44479
|
+
droppedDeadUnavailable = true;
|
|
44480
|
+
continue;
|
|
44481
|
+
}
|
|
44482
|
+
unavailableNodeIds.add(nodeId);
|
|
43798
44483
|
}
|
|
44484
|
+
if (droppedDeadUnavailable) changed = true;
|
|
43799
44485
|
const nodes = snapshot.nodes.map((statusNode) => {
|
|
43800
44486
|
const nodeId = normalizeMeshNodeId(statusNode);
|
|
43801
44487
|
const inlineNode = nodeId ? inlineNodesById.get(nodeId) : void 0;
|
|
@@ -43910,7 +44596,10 @@ var DaemonCommandRouter = class {
|
|
|
43910
44596
|
}
|
|
43911
44597
|
warmInlineMeshCache(meshId, inlineMesh) {
|
|
43912
44598
|
if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
|
|
43913
|
-
const sanitizedInlineMesh =
|
|
44599
|
+
const sanitizedInlineMesh = this.applyInlineMeshNodeTombstones(
|
|
44600
|
+
meshId,
|
|
44601
|
+
sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(inlineMesh))
|
|
44602
|
+
);
|
|
43914
44603
|
const cached2 = this.inlineMeshCache.get(meshId);
|
|
43915
44604
|
if (cached2) {
|
|
43916
44605
|
const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
|
|
@@ -43926,7 +44615,10 @@ var DaemonCommandRouter = class {
|
|
|
43926
44615
|
const cached3 = this.getCachedInlineMesh(meshId);
|
|
43927
44616
|
if (cached3) {
|
|
43928
44617
|
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
43929
|
-
const merged = reconcileInlineMeshCache(
|
|
44618
|
+
const merged = reconcileInlineMeshCache(
|
|
44619
|
+
cached3,
|
|
44620
|
+
this.applyInlineMeshNodeTombstones(meshId, inlineMesh)
|
|
44621
|
+
);
|
|
43930
44622
|
this.inlineMeshCache.set(meshId, sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(merged)));
|
|
43931
44623
|
return { mesh: merged, inline: true, source: "inline_cache" };
|
|
43932
44624
|
}
|
|
@@ -43977,12 +44669,49 @@ var DaemonCommandRouter = class {
|
|
|
43977
44669
|
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
43978
44670
|
const idx = mesh.nodes.findIndex((entry) => meshNodeIdMatches(entry, nodeId));
|
|
43979
44671
|
if (idx === -1) return false;
|
|
44672
|
+
const canonicalNodeId = readInlineMeshNodeId(mesh.nodes[idx]) || nodeId;
|
|
43980
44673
|
mesh.nodes.splice(idx, 1);
|
|
43981
44674
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43982
44675
|
this.inlineMeshCache.set(meshId, mesh);
|
|
44676
|
+
this.tombstoneRemovedInlineMeshNode(meshId, canonicalNodeId);
|
|
44677
|
+
if (canonicalNodeId !== nodeId) this.tombstoneRemovedInlineMeshNode(meshId, nodeId);
|
|
43983
44678
|
this.invalidateAggregateMeshStatus(meshId);
|
|
43984
44679
|
return true;
|
|
43985
44680
|
}
|
|
44681
|
+
tombstoneRemovedInlineMeshNode(meshId, nodeId) {
|
|
44682
|
+
if (!nodeId) return;
|
|
44683
|
+
let set = this.removedInlineMeshNodeIds.get(meshId);
|
|
44684
|
+
if (!set) {
|
|
44685
|
+
set = /* @__PURE__ */ new Set();
|
|
44686
|
+
this.removedInlineMeshNodeIds.set(meshId, set);
|
|
44687
|
+
}
|
|
44688
|
+
set.add(nodeId);
|
|
44689
|
+
}
|
|
44690
|
+
/** Filter an incoming inline mesh against this mesh's tombstones before it is
|
|
44691
|
+
* reconciled into the cache. A tombstoned node is dropped only while its
|
|
44692
|
+
* workspace is still absent from disk; if the workspace is back (genuine
|
|
44693
|
+
* re-registration), the tombstone is cleared and the node merges normally. */
|
|
44694
|
+
applyInlineMeshNodeTombstones(meshId, incoming) {
|
|
44695
|
+
const tombstones = this.removedInlineMeshNodeIds.get(meshId);
|
|
44696
|
+
if (!tombstones?.size || !incoming || typeof incoming !== "object" || !Array.isArray(incoming.nodes)) {
|
|
44697
|
+
return incoming;
|
|
44698
|
+
}
|
|
44699
|
+
let dropped = false;
|
|
44700
|
+
const nodes = incoming.nodes.filter((node) => {
|
|
44701
|
+
const nodeId = readInlineMeshNodeId(node);
|
|
44702
|
+
if (!nodeId || !tombstones.has(nodeId)) return true;
|
|
44703
|
+
const workspace = readStringValue(node?.workspace);
|
|
44704
|
+
if (workspace && fs25.existsSync(workspace)) {
|
|
44705
|
+
tombstones.delete(nodeId);
|
|
44706
|
+
return true;
|
|
44707
|
+
}
|
|
44708
|
+
dropped = true;
|
|
44709
|
+
return false;
|
|
44710
|
+
});
|
|
44711
|
+
if (tombstones.size === 0) this.removedInlineMeshNodeIds.delete(meshId);
|
|
44712
|
+
if (!dropped) return incoming;
|
|
44713
|
+
return { ...incoming, nodes };
|
|
44714
|
+
}
|
|
43986
44715
|
normalizeMeshSessionCleanupMode(value) {
|
|
43987
44716
|
return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
|
|
43988
44717
|
}
|
|
@@ -44005,13 +44734,13 @@ var DaemonCommandRouter = class {
|
|
|
44005
44734
|
recoveryHint: "Inspect the mesh node record before removing it, or remove stale metadata manually only after confirming no managed worktree remains."
|
|
44006
44735
|
};
|
|
44007
44736
|
}
|
|
44008
|
-
const worktreeExists =
|
|
44737
|
+
const worktreeExists = fs25.existsSync(workspace);
|
|
44009
44738
|
const sourceNode = args.node?.clonedFromNodeId ? args.mesh?.nodes?.find((n) => meshNodeIdMatches(n, args.node.clonedFromNodeId)) : args.mesh?.nodes?.find((n) => !n.isLocalWorktree);
|
|
44010
44739
|
const repoRoot = typeof sourceNode?.repoRoot === "string" && sourceNode.repoRoot.trim() ? sourceNode.repoRoot.trim() : typeof sourceNode?.workspace === "string" && sourceNode.workspace.trim() ? sourceNode.workspace.trim() : "";
|
|
44011
44740
|
if (!worktreeExists) {
|
|
44012
44741
|
return { success: true, skipped: true, removedPath: workspace, repoRoot: repoRoot || void 0, reason: "worktree_path_missing" };
|
|
44013
44742
|
}
|
|
44014
|
-
if (!repoRoot || !
|
|
44743
|
+
if (!repoRoot || !fs25.existsSync(repoRoot)) {
|
|
44015
44744
|
return {
|
|
44016
44745
|
success: false,
|
|
44017
44746
|
code: "mesh_worktree_cleanup_missing_source_repo",
|
|
@@ -44031,7 +44760,7 @@ var DaemonCommandRouter = class {
|
|
|
44031
44760
|
const normalizePath = (value) => {
|
|
44032
44761
|
const resolved = (0, import_path11.resolve)(value);
|
|
44033
44762
|
try {
|
|
44034
|
-
return
|
|
44763
|
+
return fs25.realpathSync(resolved);
|
|
44035
44764
|
} catch {
|
|
44036
44765
|
return resolved;
|
|
44037
44766
|
}
|
|
@@ -44117,7 +44846,7 @@ var DaemonCommandRouter = class {
|
|
|
44117
44846
|
};
|
|
44118
44847
|
} catch (deinitError) {
|
|
44119
44848
|
try {
|
|
44120
|
-
|
|
44849
|
+
fs25.rmSync(workspace, { recursive: true, force: true });
|
|
44121
44850
|
await execFileAsync4("git", ["worktree", "prune"], {
|
|
44122
44851
|
cwd: repoRoot,
|
|
44123
44852
|
encoding: "utf8",
|
|
@@ -45896,8 +46625,8 @@ ${hintLines.join("\n")}` : "",
|
|
|
45896
46625
|
if (sinceTs > 0) {
|
|
45897
46626
|
return { success: true, logs: [], totalBuffered: 0 };
|
|
45898
46627
|
}
|
|
45899
|
-
if (
|
|
45900
|
-
const content =
|
|
46628
|
+
if (fs25.existsSync(LOG_PATH)) {
|
|
46629
|
+
const content = fs25.readFileSync(LOG_PATH, "utf-8");
|
|
45901
46630
|
const allLines = content.split("\n");
|
|
45902
46631
|
const recent = allLines.slice(-count).join("\n");
|
|
45903
46632
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
@@ -46442,14 +47171,14 @@ ${hintLines.join("\n")}` : "",
|
|
|
46442
47171
|
// Settings page in the dashboard reads/writes via these two
|
|
46443
47172
|
// commands instead of going through fs from the browser.
|
|
46444
47173
|
case "list_coordinator_prompts": {
|
|
46445
|
-
const
|
|
47174
|
+
const fs31 = await import("fs");
|
|
46446
47175
|
const path41 = await import("path");
|
|
46447
47176
|
const os30 = await import("os");
|
|
46448
47177
|
const dir = path41.join(os30.homedir(), ".adhdev", "coordinator-prompts");
|
|
46449
47178
|
const entries = {};
|
|
46450
47179
|
try {
|
|
46451
|
-
if (
|
|
46452
|
-
for (const name of
|
|
47180
|
+
if (fs31.existsSync(dir)) {
|
|
47181
|
+
for (const name of fs31.readdirSync(dir)) {
|
|
46453
47182
|
const matchOverride = name.match(/^([a-zA-Z0-9_.-]+)\.md$/);
|
|
46454
47183
|
const matchAppend = name.match(/^([a-zA-Z0-9_.-]+)\.append\.md$/);
|
|
46455
47184
|
const m = matchAppend || matchOverride;
|
|
@@ -46459,7 +47188,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
46459
47188
|
const full = path41.join(dir, name);
|
|
46460
47189
|
let content = "";
|
|
46461
47190
|
try {
|
|
46462
|
-
content =
|
|
47191
|
+
content = fs31.readFileSync(full, "utf8");
|
|
46463
47192
|
} catch {
|
|
46464
47193
|
}
|
|
46465
47194
|
if (!entries[key]) entries[key] = { override: "", append: "" };
|
|
@@ -46473,7 +47202,7 @@ ${hintLines.join("\n")}` : "",
|
|
|
46473
47202
|
return { success: true, dir, entries };
|
|
46474
47203
|
}
|
|
46475
47204
|
case "write_coordinator_prompt": {
|
|
46476
|
-
const
|
|
47205
|
+
const fs31 = await import("fs");
|
|
46477
47206
|
const path41 = await import("path");
|
|
46478
47207
|
const os30 = await import("os");
|
|
46479
47208
|
const key = typeof args?.key === "string" ? args.key.trim() : "";
|
|
@@ -46486,11 +47215,11 @@ ${hintLines.join("\n")}` : "",
|
|
|
46486
47215
|
const filename = kind === "append" ? `${key}.append.md` : `${key}.md`;
|
|
46487
47216
|
const full = path41.join(dir, filename);
|
|
46488
47217
|
try {
|
|
46489
|
-
|
|
47218
|
+
fs31.mkdirSync(dir, { recursive: true });
|
|
46490
47219
|
if (content.trim()) {
|
|
46491
|
-
|
|
46492
|
-
} else if (
|
|
46493
|
-
|
|
47220
|
+
fs31.writeFileSync(full, content, { encoding: "utf8", mode: 384 });
|
|
47221
|
+
} else if (fs31.existsSync(full)) {
|
|
47222
|
+
fs31.unlinkSync(full);
|
|
46494
47223
|
}
|
|
46495
47224
|
return { success: true, path: full, kind, key };
|
|
46496
47225
|
} catch (error) {
|
|
@@ -46667,7 +47396,8 @@ ${hintLines.join("\n")}` : "",
|
|
|
46667
47396
|
getMeshPeerConnectionStatus: this.deps.getMeshPeerConnectionStatus,
|
|
46668
47397
|
statusInstanceId: this.deps.statusInstanceId,
|
|
46669
47398
|
localMachineId: loadConfig().machineId || "",
|
|
46670
|
-
probeRemotePeers
|
|
47399
|
+
probeRemotePeers,
|
|
47400
|
+
probeCache: this.meshGitProbeCache
|
|
46671
47401
|
});
|
|
46672
47402
|
const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
|
|
46673
47403
|
const sourceOfTruth = {
|
|
@@ -47267,10 +47997,75 @@ ${hintLines.join("\n")}` : "",
|
|
|
47267
47997
|
});
|
|
47268
47998
|
return result;
|
|
47269
47999
|
}
|
|
48000
|
+
case "get_mesh_node_logs": {
|
|
48001
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
48002
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
48003
|
+
let nodeDaemonId;
|
|
48004
|
+
if (meshId && nodeId) {
|
|
48005
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48006
|
+
const node = meshRecord?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
48007
|
+
nodeDaemonId = typeof node?.daemonId === "string" ? node.daemonId.trim() : void 0;
|
|
48008
|
+
}
|
|
48009
|
+
const selfDaemonId = this.deps.statusInstanceId;
|
|
48010
|
+
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
|
|
48011
|
+
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
48012
|
+
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "get_mesh_node_logs", {
|
|
48013
|
+
...typeof args === "object" && args !== null ? args : {},
|
|
48014
|
+
_meshDirectDispatch: true
|
|
48015
|
+
});
|
|
48016
|
+
return forwarded ?? { success: false, error: "no response from remote node" };
|
|
48017
|
+
}
|
|
48018
|
+
const rawTailBytes = Number(args?.tailBytes);
|
|
48019
|
+
const tail = readDaemonLogTail({
|
|
48020
|
+
date: typeof args?.date === "string" ? args.date : void 0,
|
|
48021
|
+
tailBytes: Number.isFinite(rawTailBytes) ? Math.min(rawTailBytes, MAX_TAIL_BYTES) : void 0,
|
|
48022
|
+
grep: typeof args?.grep === "string" ? args.grep : void 0,
|
|
48023
|
+
sinceMs: Number.isFinite(Number(args?.sinceMs)) ? Number(args?.sinceMs) : void 0
|
|
48024
|
+
});
|
|
48025
|
+
if (!tail.success) {
|
|
48026
|
+
return {
|
|
48027
|
+
success: false,
|
|
48028
|
+
error: tail.error || "failed to read daemon log tail",
|
|
48029
|
+
nodeId,
|
|
48030
|
+
logPath: tail.logPath,
|
|
48031
|
+
platform: tail.platform
|
|
48032
|
+
};
|
|
48033
|
+
}
|
|
48034
|
+
const redactedLines = redactLogLines(tail.lines);
|
|
48035
|
+
return {
|
|
48036
|
+
success: true,
|
|
48037
|
+
nodeId,
|
|
48038
|
+
daemonId: selfDaemonId,
|
|
48039
|
+
logPath: tail.logPath,
|
|
48040
|
+
platform: tail.platform,
|
|
48041
|
+
lines: redactedLines,
|
|
48042
|
+
lineCount: redactedLines.length,
|
|
48043
|
+
truncated: tail.truncated,
|
|
48044
|
+
filtered: tail.filtered,
|
|
48045
|
+
bytesReturned: tail.bytesReturned,
|
|
48046
|
+
...tail.grep ? { grep: tail.grep } : {}
|
|
48047
|
+
};
|
|
48048
|
+
}
|
|
47270
48049
|
case "refine_mesh_node": {
|
|
47271
48050
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47272
48051
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
47273
48052
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
48053
|
+
{
|
|
48054
|
+
const meshRecordForForward = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48055
|
+
const forwardNode = meshRecordForForward?.mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
48056
|
+
const nodeDaemonId = typeof forwardNode?.daemonId === "string" ? forwardNode.daemonId.trim() : void 0;
|
|
48057
|
+
const selfDaemonId = this.deps.statusInstanceId;
|
|
48058
|
+
const isRemote = nodeDaemonId && selfDaemonId && nodeDaemonId !== selfDaemonId;
|
|
48059
|
+
if (isRemote && this.deps.dispatchMeshCommand && !args?._meshDirectDispatch) {
|
|
48060
|
+
const callerCoordinatorDaemonId = typeof args?.coordinatorDaemonId === "string" && args.coordinatorDaemonId.trim() ? args.coordinatorDaemonId.trim() : void 0;
|
|
48061
|
+
const forwarded = await this.deps.dispatchMeshCommand(nodeDaemonId, "refine_mesh_node", {
|
|
48062
|
+
...typeof args === "object" && args !== null ? args : {},
|
|
48063
|
+
coordinatorDaemonId: callerCoordinatorDaemonId || selfDaemonId,
|
|
48064
|
+
_meshDirectDispatch: true
|
|
48065
|
+
});
|
|
48066
|
+
return forwarded ?? { success: false, error: "no response from remote node" };
|
|
48067
|
+
}
|
|
48068
|
+
}
|
|
47274
48069
|
const isDryRun = args?.dryRun !== false && args?.execute !== true;
|
|
47275
48070
|
if (isDryRun) {
|
|
47276
48071
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
@@ -47918,15 +48713,15 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
47918
48713
|
}
|
|
47919
48714
|
if (cliType === "codex-cli") {
|
|
47920
48715
|
const repoMcpConfigPath = (0, import_path11.join)(workspace, ".mcp.json");
|
|
47921
|
-
if (
|
|
48716
|
+
if (fs25.existsSync(repoMcpConfigPath)) {
|
|
47922
48717
|
try {
|
|
47923
48718
|
const repoMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
47924
|
-
|
|
48719
|
+
fs25.readFileSync(repoMcpConfigPath, "utf-8"),
|
|
47925
48720
|
"claude_mcp_json"
|
|
47926
48721
|
);
|
|
47927
48722
|
const existingServers2 = repoMcpConfig.mcpServers;
|
|
47928
48723
|
if (existingServers2 && typeof existingServers2 === "object" && !Array.isArray(existingServers2) && existingServers2[coordinatorSetup.serverName]) {
|
|
47929
|
-
|
|
48724
|
+
fs25.writeFileSync(repoMcpConfigPath, serializeMeshCoordinatorMcpConfig({
|
|
47930
48725
|
...repoMcpConfig,
|
|
47931
48726
|
mcpServers: {
|
|
47932
48727
|
...existingServers2,
|
|
@@ -48042,7 +48837,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48042
48837
|
workspace
|
|
48043
48838
|
};
|
|
48044
48839
|
}
|
|
48045
|
-
const { existsSync:
|
|
48840
|
+
const { existsSync: existsSync44, readFileSync: readFileSync35, writeFileSync: writeFileSync23, copyFileSync: copyFileSync4, mkdirSync: mkdirSync21 } = await import("fs");
|
|
48046
48841
|
const { dirname: dirname14 } = await import("path");
|
|
48047
48842
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
48048
48843
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -48085,7 +48880,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48085
48880
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
48086
48881
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
48087
48882
|
}
|
|
48088
|
-
const hadExistingMcpConfig =
|
|
48883
|
+
const hadExistingMcpConfig = existsSync44(mcpConfigPath);
|
|
48089
48884
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
48090
48885
|
if (hermesBaseConfig) {
|
|
48091
48886
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname14(mcpConfigPath));
|
|
@@ -48243,6 +49038,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48243
49038
|
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
48244
49039
|
const localMachineId = loadConfig().machineId || "";
|
|
48245
49040
|
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
49041
|
+
const meshGitProbeCache = this.meshGitProbeCache;
|
|
48246
49042
|
const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
|
|
48247
49043
|
mesh,
|
|
48248
49044
|
meshSource: meshRecord.source,
|
|
@@ -48253,14 +49049,16 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48253
49049
|
// Standing-state model: only an explicit refresh fans
|
|
48254
49050
|
// out a blocking peer git probe. Default loads return
|
|
48255
49051
|
// held truth so one slow peer can't block the graph.
|
|
48256
|
-
probeRemotePeers: refreshRequested
|
|
49052
|
+
probeRemotePeers: refreshRequested,
|
|
49053
|
+
probeCache: meshGitProbeCache
|
|
48257
49054
|
}) : {
|
|
48258
49055
|
directEvidenceCount: 0,
|
|
48259
49056
|
localConfirmedCount: 0,
|
|
48260
49057
|
peerAttemptedCount: 0,
|
|
48261
49058
|
peerConfirmedCount: 0,
|
|
48262
49059
|
standingEvidenceCount: 0,
|
|
48263
|
-
unavailableNodeIds: []
|
|
49060
|
+
unavailableNodeIds: [],
|
|
49061
|
+
deadNodeIds: []
|
|
48264
49062
|
};
|
|
48265
49063
|
const passivePeerTruthNotAttempted = requireDirectPeerTruth && !refreshRequested && directTruth.directEvidenceCount > 0 && directTruth.peerAttemptedCount === 0;
|
|
48266
49064
|
const effectiveDirectTruth = passivePeerTruthNotAttempted ? { ...directTruth, unavailableNodeIds: [] } : directTruth;
|
|
@@ -48400,7 +49198,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48400
49198
|
}
|
|
48401
49199
|
}
|
|
48402
49200
|
if (workspace) {
|
|
48403
|
-
if (!
|
|
49201
|
+
if (!fs25.existsSync(workspace)) {
|
|
48404
49202
|
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
48405
49203
|
let remoteProbeApplied = false;
|
|
48406
49204
|
if (inlineTransitGit) {
|
|
@@ -48414,7 +49212,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48414
49212
|
}
|
|
48415
49213
|
remoteProbeApplied = true;
|
|
48416
49214
|
} else if (refreshRequested && !isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
|
|
48417
|
-
const
|
|
49215
|
+
const runNodeProbe = () => probeRemoteMeshGitStatusWithRetry({
|
|
48418
49216
|
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
48419
49217
|
daemonId,
|
|
48420
49218
|
workspace,
|
|
@@ -48425,6 +49223,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48425
49223
|
status.connection = connection;
|
|
48426
49224
|
}
|
|
48427
49225
|
});
|
|
49226
|
+
const remoteGit = await meshGitProbeCache.probe(daemonId, workspace, runNodeProbe);
|
|
48428
49227
|
if (remoteGit) {
|
|
48429
49228
|
status.git = remoteGit;
|
|
48430
49229
|
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
@@ -48490,7 +49289,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48490
49289
|
const pendingCoordinatorEvents = getPendingMeshCoordinatorEvents(meshId, callerCoordinatorDaemonId);
|
|
48491
49290
|
const unroutableDeliveries = getRecentUnroutableDeliveries();
|
|
48492
49291
|
const previewFreshness = (() => {
|
|
48493
|
-
const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate &&
|
|
49292
|
+
const localRepoRoot = nodeStatuses.map((node) => readStringValue(node?.git?.repoRoot, node?.repoRoot, node?.workspace)).find((candidate) => !!candidate && fs25.existsSync(candidate));
|
|
48494
49293
|
return localRepoRoot ? buildPreviewFreshness(localRepoRoot) : void 0;
|
|
48495
49294
|
})();
|
|
48496
49295
|
const asyncRefineJobs = buildMeshAsyncRefineJobs({
|
|
@@ -48585,7 +49384,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48585
49384
|
const { deriveMeshReviewInboxItems: deriveMeshReviewInboxItems2 } = await Promise.resolve().then(() => (init_mesh_review_inbox(), mesh_review_inbox_exports));
|
|
48586
49385
|
const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48587
49386
|
const { getGitDiffSummary: getGitDiffSummary2 } = await Promise.resolve().then(() => (init_git_diff(), git_diff_exports));
|
|
48588
|
-
const { existsSync:
|
|
49387
|
+
const { existsSync: existsSync44 } = await import("fs");
|
|
48589
49388
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48590
49389
|
const mesh = meshRecord?.mesh;
|
|
48591
49390
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
@@ -48604,7 +49403,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
48604
49403
|
const derivation = deriveMeshReviewInboxItems2({ nodes: nodeStatuses, ledgerEntries });
|
|
48605
49404
|
for (const item of derivation.items) {
|
|
48606
49405
|
const workspace = item.workspace;
|
|
48607
|
-
if (!workspace || !
|
|
49406
|
+
if (!workspace || !existsSync44(workspace)) continue;
|
|
48608
49407
|
const baseRef = item.defaultBranch ? `origin/${item.defaultBranch}` : "origin/main";
|
|
48609
49408
|
try {
|
|
48610
49409
|
const diffResult = await getGitDiffSummary2(workspace, { baseRef, maxFiles: 100 });
|
|
@@ -50350,7 +51149,7 @@ var ProviderInstanceManager = class {
|
|
|
50350
51149
|
};
|
|
50351
51150
|
|
|
50352
51151
|
// src/providers/version-archive.ts
|
|
50353
|
-
var
|
|
51152
|
+
var fs26 = __toESM(require("fs"));
|
|
50354
51153
|
var path36 = __toESM(require("path"));
|
|
50355
51154
|
var os28 = __toESM(require("os"));
|
|
50356
51155
|
var import_os4 = require("os");
|
|
@@ -50364,8 +51163,8 @@ var VersionArchive = class {
|
|
|
50364
51163
|
}
|
|
50365
51164
|
load() {
|
|
50366
51165
|
try {
|
|
50367
|
-
if (
|
|
50368
|
-
this.history = JSON.parse(
|
|
51166
|
+
if (fs26.existsSync(ARCHIVE_PATH)) {
|
|
51167
|
+
this.history = JSON.parse(fs26.readFileSync(ARCHIVE_PATH, "utf-8"));
|
|
50369
51168
|
}
|
|
50370
51169
|
} catch {
|
|
50371
51170
|
this.history = {};
|
|
@@ -50402,8 +51201,8 @@ var VersionArchive = class {
|
|
|
50402
51201
|
}
|
|
50403
51202
|
save() {
|
|
50404
51203
|
try {
|
|
50405
|
-
|
|
50406
|
-
|
|
51204
|
+
fs26.mkdirSync(path36.dirname(ARCHIVE_PATH), { recursive: true });
|
|
51205
|
+
fs26.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
50407
51206
|
} catch {
|
|
50408
51207
|
}
|
|
50409
51208
|
}
|
|
@@ -50428,8 +51227,8 @@ function findBinary2(name) {
|
|
|
50428
51227
|
for (const ext of exes) {
|
|
50429
51228
|
const fullPath = path36.join(p, name + ext);
|
|
50430
51229
|
try {
|
|
50431
|
-
if (
|
|
50432
|
-
const stat2 =
|
|
51230
|
+
if (fs26.existsSync(fullPath)) {
|
|
51231
|
+
const stat2 = fs26.statSync(fullPath);
|
|
50433
51232
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
50434
51233
|
return fullPath;
|
|
50435
51234
|
}
|
|
@@ -50476,9 +51275,9 @@ function checkPathExists2(paths) {
|
|
|
50476
51275
|
if (p.includes("*")) {
|
|
50477
51276
|
const home = os28.homedir();
|
|
50478
51277
|
const resolved = p.replace(/\*/g, home.split(path36.sep).pop() || "");
|
|
50479
|
-
if (
|
|
51278
|
+
if (fs26.existsSync(resolved)) return resolved;
|
|
50480
51279
|
} else {
|
|
50481
|
-
if (
|
|
51280
|
+
if (fs26.existsSync(p)) return p;
|
|
50482
51281
|
}
|
|
50483
51282
|
}
|
|
50484
51283
|
return null;
|
|
@@ -50486,7 +51285,7 @@ function checkPathExists2(paths) {
|
|
|
50486
51285
|
async function getMacAppVersion(appPath) {
|
|
50487
51286
|
if ((0, import_os4.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
50488
51287
|
const plistPath = path36.join(appPath, "Contents", "Info.plist");
|
|
50489
|
-
if (!
|
|
51288
|
+
if (!fs26.existsSync(plistPath)) return null;
|
|
50490
51289
|
const raw = await runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
50491
51290
|
return raw || null;
|
|
50492
51291
|
}
|
|
@@ -50512,7 +51311,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
50512
51311
|
let resolvedBin = cliBin;
|
|
50513
51312
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
50514
51313
|
const bundled = path36.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
50515
|
-
if (provider.cli &&
|
|
51314
|
+
if (provider.cli && fs26.existsSync(bundled)) resolvedBin = bundled;
|
|
50516
51315
|
}
|
|
50517
51316
|
info.installed = !!(appPath || resolvedBin);
|
|
50518
51317
|
info.path = appPath || null;
|
|
@@ -50551,7 +51350,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
50551
51350
|
|
|
50552
51351
|
// src/daemon/dev-server.ts
|
|
50553
51352
|
var http2 = __toESM(require("http"));
|
|
50554
|
-
var
|
|
51353
|
+
var fs30 = __toESM(require("fs"));
|
|
50555
51354
|
var path40 = __toESM(require("path"));
|
|
50556
51355
|
init_config();
|
|
50557
51356
|
|
|
@@ -50902,7 +51701,7 @@ async (params) => {
|
|
|
50902
51701
|
init_logger();
|
|
50903
51702
|
|
|
50904
51703
|
// src/daemon/dev-cdp-handlers.ts
|
|
50905
|
-
var
|
|
51704
|
+
var fs27 = __toESM(require("fs"));
|
|
50906
51705
|
var path37 = __toESM(require("path"));
|
|
50907
51706
|
init_logger();
|
|
50908
51707
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
@@ -51083,17 +51882,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
51083
51882
|
}
|
|
51084
51883
|
let scriptsPath = "";
|
|
51085
51884
|
const directScripts = path37.join(dir, "scripts.js");
|
|
51086
|
-
if (
|
|
51885
|
+
if (fs27.existsSync(directScripts)) {
|
|
51087
51886
|
scriptsPath = directScripts;
|
|
51088
51887
|
} else {
|
|
51089
51888
|
const scriptsDir = path37.join(dir, "scripts");
|
|
51090
|
-
if (
|
|
51091
|
-
const versions =
|
|
51092
|
-
return
|
|
51889
|
+
if (fs27.existsSync(scriptsDir)) {
|
|
51890
|
+
const versions = fs27.readdirSync(scriptsDir).filter((d) => {
|
|
51891
|
+
return fs27.statSync(path37.join(scriptsDir, d)).isDirectory();
|
|
51093
51892
|
}).sort().reverse();
|
|
51094
51893
|
for (const ver of versions) {
|
|
51095
51894
|
const p = path37.join(scriptsDir, ver, "scripts.js");
|
|
51096
|
-
if (
|
|
51895
|
+
if (fs27.existsSync(p)) {
|
|
51097
51896
|
scriptsPath = p;
|
|
51098
51897
|
break;
|
|
51099
51898
|
}
|
|
@@ -51105,7 +51904,7 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
51105
51904
|
return;
|
|
51106
51905
|
}
|
|
51107
51906
|
try {
|
|
51108
|
-
const source =
|
|
51907
|
+
const source = fs27.readFileSync(scriptsPath, "utf-8");
|
|
51109
51908
|
const hints = {};
|
|
51110
51909
|
const funcRegex = /module\.exports\.(\w+)\s*=\s*function\s+\w+\s*\(params\)/g;
|
|
51111
51910
|
let match;
|
|
@@ -51920,7 +52719,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
51920
52719
|
}
|
|
51921
52720
|
|
|
51922
52721
|
// src/daemon/dev-cli-debug.ts
|
|
51923
|
-
var
|
|
52722
|
+
var fs28 = __toESM(require("fs"));
|
|
51924
52723
|
var path38 = __toESM(require("path"));
|
|
51925
52724
|
function slugifyFixtureName(value) {
|
|
51926
52725
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -51936,10 +52735,10 @@ function getCliFixtureDir(ctx, type) {
|
|
|
51936
52735
|
function readCliFixture(ctx, type, name) {
|
|
51937
52736
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
51938
52737
|
const filePath = path38.join(fixtureDir, `${name}.json`);
|
|
51939
|
-
if (!
|
|
52738
|
+
if (!fs28.existsSync(filePath)) {
|
|
51940
52739
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
51941
52740
|
}
|
|
51942
|
-
return JSON.parse(
|
|
52741
|
+
return JSON.parse(fs28.readFileSync(filePath, "utf-8"));
|
|
51943
52742
|
}
|
|
51944
52743
|
function getExerciseTranscriptText(result) {
|
|
51945
52744
|
const parts = [];
|
|
@@ -52684,7 +53483,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
52684
53483
|
return;
|
|
52685
53484
|
}
|
|
52686
53485
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
52687
|
-
|
|
53486
|
+
fs28.mkdirSync(fixtureDir, { recursive: true });
|
|
52688
53487
|
const name = slugifyFixtureName(String(body?.name || `${type}-${Date.now()}`));
|
|
52689
53488
|
const result = await runCliExerciseInternal(ctx, { ...request, type });
|
|
52690
53489
|
const fixture = {
|
|
@@ -52712,7 +53511,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
52712
53511
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
52713
53512
|
};
|
|
52714
53513
|
const filePath = path38.join(fixtureDir, `${name}.json`);
|
|
52715
|
-
|
|
53514
|
+
fs28.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
52716
53515
|
ctx.json(res, 200, {
|
|
52717
53516
|
saved: true,
|
|
52718
53517
|
name,
|
|
@@ -52730,14 +53529,14 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
52730
53529
|
async function handleCliFixtureList(ctx, type, _req, res) {
|
|
52731
53530
|
try {
|
|
52732
53531
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
52733
|
-
if (!
|
|
53532
|
+
if (!fs28.existsSync(fixtureDir)) {
|
|
52734
53533
|
ctx.json(res, 200, { fixtures: [], count: 0 });
|
|
52735
53534
|
return;
|
|
52736
53535
|
}
|
|
52737
|
-
const fixtures =
|
|
53536
|
+
const fixtures = fs28.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
52738
53537
|
const fullPath = path38.join(fixtureDir, file);
|
|
52739
53538
|
try {
|
|
52740
|
-
const raw = JSON.parse(
|
|
53539
|
+
const raw = JSON.parse(fs28.readFileSync(fullPath, "utf-8"));
|
|
52741
53540
|
return {
|
|
52742
53541
|
name: raw.name || file.replace(/\.json$/i, ""),
|
|
52743
53542
|
path: fullPath,
|
|
@@ -52870,7 +53669,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
52870
53669
|
}
|
|
52871
53670
|
|
|
52872
53671
|
// src/daemon/dev-auto-implement.ts
|
|
52873
|
-
var
|
|
53672
|
+
var fs29 = __toESM(require("fs"));
|
|
52874
53673
|
var path39 = __toESM(require("path"));
|
|
52875
53674
|
var os29 = __toESM(require("os"));
|
|
52876
53675
|
var import_session_host_core8 = require("@adhdev/session-host-core");
|
|
@@ -52919,10 +53718,10 @@ function resolveAutoImplReference(ctx, category, requestedReference, targetType)
|
|
|
52919
53718
|
return fallback?.type || null;
|
|
52920
53719
|
}
|
|
52921
53720
|
function getLatestScriptVersionDir(scriptsDir) {
|
|
52922
|
-
if (!
|
|
52923
|
-
const versions =
|
|
53721
|
+
if (!fs29.existsSync(scriptsDir)) return null;
|
|
53722
|
+
const versions = fs29.readdirSync(scriptsDir).filter((d) => {
|
|
52924
53723
|
try {
|
|
52925
|
-
return
|
|
53724
|
+
return fs29.statSync(path39.join(scriptsDir, d)).isDirectory();
|
|
52926
53725
|
} catch {
|
|
52927
53726
|
return false;
|
|
52928
53727
|
}
|
|
@@ -52944,13 +53743,13 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
52944
53743
|
if (!sourceDir) {
|
|
52945
53744
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
52946
53745
|
}
|
|
52947
|
-
if (!
|
|
52948
|
-
|
|
52949
|
-
|
|
53746
|
+
if (!fs29.existsSync(desiredDir)) {
|
|
53747
|
+
fs29.mkdirSync(path39.dirname(desiredDir), { recursive: true });
|
|
53748
|
+
fs29.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
52950
53749
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
52951
53750
|
}
|
|
52952
53751
|
const providerJson = path39.join(desiredDir, "provider.json");
|
|
52953
|
-
if (!
|
|
53752
|
+
if (!fs29.existsSync(providerJson)) {
|
|
52954
53753
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
52955
53754
|
}
|
|
52956
53755
|
return { dir: desiredDir };
|
|
@@ -52958,15 +53757,15 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
52958
53757
|
function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
52959
53758
|
if (!referenceType) return {};
|
|
52960
53759
|
const refDir = ctx.findProviderDir(referenceType);
|
|
52961
|
-
if (!refDir || !
|
|
53760
|
+
if (!refDir || !fs29.existsSync(refDir)) return {};
|
|
52962
53761
|
const referenceScripts = {};
|
|
52963
53762
|
const scriptsDir = path39.join(refDir, "scripts");
|
|
52964
53763
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
52965
53764
|
if (!latestDir) return referenceScripts;
|
|
52966
|
-
for (const file of
|
|
53765
|
+
for (const file of fs29.readdirSync(latestDir)) {
|
|
52967
53766
|
if (!file.endsWith(".js")) continue;
|
|
52968
53767
|
try {
|
|
52969
|
-
referenceScripts[file] =
|
|
53768
|
+
referenceScripts[file] = fs29.readFileSync(path39.join(latestDir, file), "utf-8");
|
|
52970
53769
|
} catch {
|
|
52971
53770
|
}
|
|
52972
53771
|
}
|
|
@@ -53075,15 +53874,15 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
53075
53874
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
53076
53875
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
53077
53876
|
const tmpDir = path39.join(os29.tmpdir(), "adhdev-autoimpl");
|
|
53078
|
-
if (!
|
|
53877
|
+
if (!fs29.existsSync(tmpDir)) fs29.mkdirSync(tmpDir, { recursive: true });
|
|
53079
53878
|
const promptFile = path39.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
53080
|
-
|
|
53879
|
+
fs29.writeFileSync(promptFile, prompt, "utf-8");
|
|
53081
53880
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
53082
53881
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
53083
53882
|
const spawn4 = agentProvider?.spawn;
|
|
53084
53883
|
if (!spawn4?.command) {
|
|
53085
53884
|
try {
|
|
53086
|
-
|
|
53885
|
+
fs29.unlinkSync(promptFile);
|
|
53087
53886
|
} catch {
|
|
53088
53887
|
}
|
|
53089
53888
|
ctx.json(res, 400, { error: `Agent '${agent}' has no spawn config. Select a CLI provider with a spawn configuration.` });
|
|
@@ -53185,7 +53984,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
53185
53984
|
} catch {
|
|
53186
53985
|
}
|
|
53187
53986
|
try {
|
|
53188
|
-
|
|
53987
|
+
fs29.unlinkSync(promptFile);
|
|
53189
53988
|
} catch {
|
|
53190
53989
|
}
|
|
53191
53990
|
ctx.log(`Auto-implement (ACP) ${success ? "completed" : "failed"}: ${type} (exit: ${code})`);
|
|
@@ -53411,7 +54210,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
53411
54210
|
}
|
|
53412
54211
|
});
|
|
53413
54212
|
try {
|
|
53414
|
-
|
|
54213
|
+
fs29.unlinkSync(promptFile);
|
|
53415
54214
|
} catch {
|
|
53416
54215
|
}
|
|
53417
54216
|
ctx.log(`Auto-implement ${success ? "completed" : "failed"}: ${type} (exit: ${code})${verificationSummary ? ` verify=${verificationSummary.pass ? "pass" : "fail"}` : ""}`);
|
|
@@ -53516,10 +54315,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
53516
54315
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
53517
54316
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
53518
54317
|
lines.push("");
|
|
53519
|
-
for (const file of
|
|
54318
|
+
for (const file of fs29.readdirSync(latestScriptsDir)) {
|
|
53520
54319
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
53521
54320
|
try {
|
|
53522
|
-
const content =
|
|
54321
|
+
const content = fs29.readFileSync(path39.join(latestScriptsDir, file), "utf-8");
|
|
53523
54322
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
53524
54323
|
lines.push("```javascript");
|
|
53525
54324
|
lines.push(content);
|
|
@@ -53529,14 +54328,14 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
53529
54328
|
}
|
|
53530
54329
|
}
|
|
53531
54330
|
}
|
|
53532
|
-
const refFiles =
|
|
54331
|
+
const refFiles = fs29.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
53533
54332
|
if (refFiles.length > 0) {
|
|
53534
54333
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
53535
54334
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
53536
54335
|
lines.push("");
|
|
53537
54336
|
for (const file of refFiles) {
|
|
53538
54337
|
try {
|
|
53539
|
-
const content =
|
|
54338
|
+
const content = fs29.readFileSync(path39.join(latestScriptsDir, file), "utf-8");
|
|
53540
54339
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
53541
54340
|
lines.push("```javascript");
|
|
53542
54341
|
lines.push(content);
|
|
@@ -53581,7 +54380,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
53581
54380
|
const loadGuide = (name) => {
|
|
53582
54381
|
try {
|
|
53583
54382
|
const p = path39.join(docsDir, name);
|
|
53584
|
-
if (
|
|
54383
|
+
if (fs29.existsSync(p)) return fs29.readFileSync(p, "utf-8");
|
|
53585
54384
|
} catch {
|
|
53586
54385
|
}
|
|
53587
54386
|
return null;
|
|
@@ -53825,11 +54624,11 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
53825
54624
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
53826
54625
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
53827
54626
|
lines.push("");
|
|
53828
|
-
for (const file of
|
|
54627
|
+
for (const file of fs29.readdirSync(latestScriptsDir)) {
|
|
53829
54628
|
if (!file.endsWith(".js")) continue;
|
|
53830
54629
|
if (!targetFileNames.has(file)) continue;
|
|
53831
54630
|
try {
|
|
53832
|
-
const content =
|
|
54631
|
+
const content = fs29.readFileSync(path39.join(latestScriptsDir, file), "utf-8");
|
|
53833
54632
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
53834
54633
|
lines.push("```javascript");
|
|
53835
54634
|
lines.push(content);
|
|
@@ -53838,14 +54637,14 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
53838
54637
|
} catch {
|
|
53839
54638
|
}
|
|
53840
54639
|
}
|
|
53841
|
-
const refFiles =
|
|
54640
|
+
const refFiles = fs29.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
53842
54641
|
if (refFiles.length > 0) {
|
|
53843
54642
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
53844
54643
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
53845
54644
|
lines.push("");
|
|
53846
54645
|
for (const file of refFiles) {
|
|
53847
54646
|
try {
|
|
53848
|
-
const content =
|
|
54647
|
+
const content = fs29.readFileSync(path39.join(latestScriptsDir, file), "utf-8");
|
|
53849
54648
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
53850
54649
|
lines.push("```javascript");
|
|
53851
54650
|
lines.push(content);
|
|
@@ -53882,7 +54681,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
53882
54681
|
const loadGuide = (name) => {
|
|
53883
54682
|
try {
|
|
53884
54683
|
const p = path39.join(docsDir, name);
|
|
53885
|
-
if (
|
|
54684
|
+
if (fs29.existsSync(p)) return fs29.readFileSync(p, "utf-8");
|
|
53886
54685
|
} catch {
|
|
53887
54686
|
}
|
|
53888
54687
|
return null;
|
|
@@ -54622,7 +55421,7 @@ var DevServer = class _DevServer {
|
|
|
54622
55421
|
path40.join(process.cwd(), "packages/web-devconsole/dist")
|
|
54623
55422
|
];
|
|
54624
55423
|
for (const dir of candidates) {
|
|
54625
|
-
if (
|
|
55424
|
+
if (fs30.existsSync(path40.join(dir, "index.html"))) return dir;
|
|
54626
55425
|
}
|
|
54627
55426
|
return null;
|
|
54628
55427
|
}
|
|
@@ -54634,7 +55433,7 @@ var DevServer = class _DevServer {
|
|
|
54634
55433
|
}
|
|
54635
55434
|
const htmlPath = path40.join(distDir, "index.html");
|
|
54636
55435
|
try {
|
|
54637
|
-
const html =
|
|
55436
|
+
const html = fs30.readFileSync(htmlPath, "utf-8");
|
|
54638
55437
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
54639
55438
|
res.end(html);
|
|
54640
55439
|
} catch (e) {
|
|
@@ -54664,7 +55463,7 @@ var DevServer = class _DevServer {
|
|
|
54664
55463
|
return;
|
|
54665
55464
|
}
|
|
54666
55465
|
try {
|
|
54667
|
-
const content =
|
|
55466
|
+
const content = fs30.readFileSync(filePath);
|
|
54668
55467
|
const ext = path40.extname(filePath);
|
|
54669
55468
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
54670
55469
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
@@ -54773,14 +55572,14 @@ var DevServer = class _DevServer {
|
|
|
54773
55572
|
const files = [];
|
|
54774
55573
|
const scan = (d, prefix) => {
|
|
54775
55574
|
try {
|
|
54776
|
-
for (const entry of
|
|
55575
|
+
for (const entry of fs30.readdirSync(d, { withFileTypes: true })) {
|
|
54777
55576
|
if (entry.name.startsWith(".") || entry.name.endsWith(".bak")) continue;
|
|
54778
55577
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
54779
55578
|
if (entry.isDirectory()) {
|
|
54780
55579
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
54781
55580
|
scan(path40.join(d, entry.name), rel);
|
|
54782
55581
|
} else {
|
|
54783
|
-
const stat2 =
|
|
55582
|
+
const stat2 = fs30.statSync(path40.join(d, entry.name));
|
|
54784
55583
|
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
54785
55584
|
}
|
|
54786
55585
|
}
|
|
@@ -54808,11 +55607,11 @@ var DevServer = class _DevServer {
|
|
|
54808
55607
|
this.json(res, 403, { error: "Forbidden" });
|
|
54809
55608
|
return;
|
|
54810
55609
|
}
|
|
54811
|
-
if (!
|
|
55610
|
+
if (!fs30.existsSync(fullPath) || fs30.statSync(fullPath).isDirectory()) {
|
|
54812
55611
|
this.json(res, 404, { error: `File not found: ${filePath}` });
|
|
54813
55612
|
return;
|
|
54814
55613
|
}
|
|
54815
|
-
const content =
|
|
55614
|
+
const content = fs30.readFileSync(fullPath, "utf-8");
|
|
54816
55615
|
this.json(res, 200, { type, path: filePath, content, lines: content.split("\n").length });
|
|
54817
55616
|
}
|
|
54818
55617
|
/** POST /api/providers/:type/file — write a file { path, content } */
|
|
@@ -54834,9 +55633,9 @@ var DevServer = class _DevServer {
|
|
|
54834
55633
|
return;
|
|
54835
55634
|
}
|
|
54836
55635
|
try {
|
|
54837
|
-
if (
|
|
54838
|
-
|
|
54839
|
-
|
|
55636
|
+
if (fs30.existsSync(fullPath)) fs30.copyFileSync(fullPath, fullPath + ".bak");
|
|
55637
|
+
fs30.mkdirSync(path40.dirname(fullPath), { recursive: true });
|
|
55638
|
+
fs30.writeFileSync(fullPath, content, "utf-8");
|
|
54840
55639
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
54841
55640
|
this.providerLoader.reload();
|
|
54842
55641
|
this.json(res, 200, { saved: true, path: filePath, chars: content.length });
|
|
@@ -54853,8 +55652,8 @@ var DevServer = class _DevServer {
|
|
|
54853
55652
|
}
|
|
54854
55653
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
54855
55654
|
const p = path40.join(dir, name);
|
|
54856
|
-
if (
|
|
54857
|
-
const source =
|
|
55655
|
+
if (fs30.existsSync(p)) {
|
|
55656
|
+
const source = fs30.readFileSync(p, "utf-8");
|
|
54858
55657
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
54859
55658
|
return;
|
|
54860
55659
|
}
|
|
@@ -54873,11 +55672,11 @@ var DevServer = class _DevServer {
|
|
|
54873
55672
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
54874
55673
|
return;
|
|
54875
55674
|
}
|
|
54876
|
-
const target =
|
|
55675
|
+
const target = fs30.existsSync(path40.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
54877
55676
|
const targetPath = path40.join(dir, target);
|
|
54878
55677
|
try {
|
|
54879
|
-
if (
|
|
54880
|
-
|
|
55678
|
+
if (fs30.existsSync(targetPath)) fs30.copyFileSync(targetPath, targetPath + ".bak");
|
|
55679
|
+
fs30.writeFileSync(targetPath, source, "utf-8");
|
|
54881
55680
|
this.log(`Saved provider: ${targetPath} (${source.length} chars)`);
|
|
54882
55681
|
this.providerLoader.reload();
|
|
54883
55682
|
this.json(res, 200, { saved: true, path: targetPath, chars: source.length });
|
|
@@ -55022,20 +55821,20 @@ var DevServer = class _DevServer {
|
|
|
55022
55821
|
let targetDir;
|
|
55023
55822
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
55024
55823
|
const jsonPath = path40.join(targetDir, "provider.json");
|
|
55025
|
-
if (
|
|
55824
|
+
if (fs30.existsSync(jsonPath)) {
|
|
55026
55825
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
55027
55826
|
return;
|
|
55028
55827
|
}
|
|
55029
55828
|
try {
|
|
55030
55829
|
const result = generateFiles(type, name, category, { cdpPorts, cli, processName, installPath, binary, extensionId, version, osPaths, processNames });
|
|
55031
|
-
|
|
55032
|
-
|
|
55830
|
+
fs30.mkdirSync(targetDir, { recursive: true });
|
|
55831
|
+
fs30.writeFileSync(jsonPath, result["provider.json"], "utf-8");
|
|
55033
55832
|
const createdFiles = ["provider.json"];
|
|
55034
55833
|
if (result.files) {
|
|
55035
55834
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
55036
55835
|
const fullPath = path40.join(targetDir, relPath);
|
|
55037
|
-
|
|
55038
|
-
|
|
55836
|
+
fs30.mkdirSync(path40.dirname(fullPath), { recursive: true });
|
|
55837
|
+
fs30.writeFileSync(fullPath, content, "utf-8");
|
|
55039
55838
|
createdFiles.push(relPath);
|
|
55040
55839
|
}
|
|
55041
55840
|
}
|
|
@@ -55084,10 +55883,10 @@ var DevServer = class _DevServer {
|
|
|
55084
55883
|
}
|
|
55085
55884
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
55086
55885
|
getLatestScriptVersionDir(scriptsDir) {
|
|
55087
|
-
if (!
|
|
55088
|
-
const versions =
|
|
55886
|
+
if (!fs30.existsSync(scriptsDir)) return null;
|
|
55887
|
+
const versions = fs30.readdirSync(scriptsDir).filter((d) => {
|
|
55089
55888
|
try {
|
|
55090
|
-
return
|
|
55889
|
+
return fs30.statSync(path40.join(scriptsDir, d)).isDirectory();
|
|
55091
55890
|
} catch {
|
|
55092
55891
|
return false;
|
|
55093
55892
|
}
|
|
@@ -55109,13 +55908,13 @@ var DevServer = class _DevServer {
|
|
|
55109
55908
|
if (!sourceDir) {
|
|
55110
55909
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
55111
55910
|
}
|
|
55112
|
-
if (!
|
|
55113
|
-
|
|
55114
|
-
|
|
55911
|
+
if (!fs30.existsSync(desiredDir)) {
|
|
55912
|
+
fs30.mkdirSync(path40.dirname(desiredDir), { recursive: true });
|
|
55913
|
+
fs30.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
55115
55914
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
55116
55915
|
}
|
|
55117
55916
|
const providerJson = path40.join(desiredDir, "provider.json");
|
|
55118
|
-
if (!
|
|
55917
|
+
if (!fs30.existsSync(providerJson)) {
|
|
55119
55918
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
55120
55919
|
}
|
|
55121
55920
|
return { dir: desiredDir };
|
|
@@ -55158,10 +55957,10 @@ var DevServer = class _DevServer {
|
|
|
55158
55957
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
55159
55958
|
lines.push("These are the ONLY files you are allowed to modify. Replace the TODO stubs with working implementations.");
|
|
55160
55959
|
lines.push("");
|
|
55161
|
-
for (const file of
|
|
55960
|
+
for (const file of fs30.readdirSync(latestScriptsDir)) {
|
|
55162
55961
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
55163
55962
|
try {
|
|
55164
|
-
const content =
|
|
55963
|
+
const content = fs30.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
55165
55964
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
55166
55965
|
lines.push("```javascript");
|
|
55167
55966
|
lines.push(content);
|
|
@@ -55171,14 +55970,14 @@ var DevServer = class _DevServer {
|
|
|
55171
55970
|
}
|
|
55172
55971
|
}
|
|
55173
55972
|
}
|
|
55174
|
-
const refFiles =
|
|
55973
|
+
const refFiles = fs30.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
55175
55974
|
if (refFiles.length > 0) {
|
|
55176
55975
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
55177
55976
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
55178
55977
|
lines.push("");
|
|
55179
55978
|
for (const file of refFiles) {
|
|
55180
55979
|
try {
|
|
55181
|
-
const content =
|
|
55980
|
+
const content = fs30.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
55182
55981
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
55183
55982
|
lines.push("```javascript");
|
|
55184
55983
|
lines.push(content);
|
|
@@ -55223,7 +56022,7 @@ var DevServer = class _DevServer {
|
|
|
55223
56022
|
const loadGuide = (name) => {
|
|
55224
56023
|
try {
|
|
55225
56024
|
const p = path40.join(docsDir, name);
|
|
55226
|
-
if (
|
|
56025
|
+
if (fs30.existsSync(p)) return fs30.readFileSync(p, "utf-8");
|
|
55227
56026
|
} catch {
|
|
55228
56027
|
}
|
|
55229
56028
|
return null;
|
|
@@ -55404,11 +56203,11 @@ var DevServer = class _DevServer {
|
|
|
55404
56203
|
lines.push("## \u270F\uFE0F Target Files (EDIT THESE)");
|
|
55405
56204
|
lines.push("These are the ONLY files you are allowed to modify. Replace TODO or heuristic-only logic with working PTY-aware implementations.");
|
|
55406
56205
|
lines.push("");
|
|
55407
|
-
for (const file of
|
|
56206
|
+
for (const file of fs30.readdirSync(latestScriptsDir)) {
|
|
55408
56207
|
if (!file.endsWith(".js")) continue;
|
|
55409
56208
|
if (!targetFileNames.has(file)) continue;
|
|
55410
56209
|
try {
|
|
55411
|
-
const content =
|
|
56210
|
+
const content = fs30.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
55412
56211
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
55413
56212
|
lines.push("```javascript");
|
|
55414
56213
|
lines.push(content);
|
|
@@ -55417,14 +56216,14 @@ var DevServer = class _DevServer {
|
|
|
55417
56216
|
} catch {
|
|
55418
56217
|
}
|
|
55419
56218
|
}
|
|
55420
|
-
const refFiles =
|
|
56219
|
+
const refFiles = fs30.readdirSync(latestScriptsDir).filter((f) => f.endsWith(".js") && !targetFileNames.has(f));
|
|
55421
56220
|
if (refFiles.length > 0) {
|
|
55422
56221
|
lines.push("## \u{1F512} Other Scripts (REFERENCE ONLY \u2014 DO NOT EDIT)");
|
|
55423
56222
|
lines.push("These files are shown for context only. Do NOT modify them under any circumstances.");
|
|
55424
56223
|
lines.push("");
|
|
55425
56224
|
for (const file of refFiles) {
|
|
55426
56225
|
try {
|
|
55427
|
-
const content =
|
|
56226
|
+
const content = fs30.readFileSync(path40.join(latestScriptsDir, file), "utf-8");
|
|
55428
56227
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
55429
56228
|
lines.push("```javascript");
|
|
55430
56229
|
lines.push(content);
|
|
@@ -55461,7 +56260,7 @@ var DevServer = class _DevServer {
|
|
|
55461
56260
|
const loadGuide = (name) => {
|
|
55462
56261
|
try {
|
|
55463
56262
|
const p = path40.join(docsDir, name);
|
|
55464
|
-
if (
|
|
56263
|
+
if (fs30.existsSync(p)) return fs30.readFileSync(p, "utf-8");
|
|
55465
56264
|
} catch {
|
|
55466
56265
|
}
|
|
55467
56266
|
return null;
|
|
@@ -56562,8 +57361,8 @@ async function installExtension(ide, extension) {
|
|
|
56562
57361
|
const res = await fetch(extension.vsixUrl);
|
|
56563
57362
|
if (res.ok) {
|
|
56564
57363
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
56565
|
-
const
|
|
56566
|
-
|
|
57364
|
+
const fs31 = await import("fs");
|
|
57365
|
+
fs31.writeFileSync(vsixPath, buffer);
|
|
56567
57366
|
return new Promise((resolve24) => {
|
|
56568
57367
|
const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
|
|
56569
57368
|
(0, import_child_process11.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
|
|
@@ -57242,6 +58041,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57242
58041
|
DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
57243
58042
|
DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
57244
58043
|
DEFAULT_MESH_POLICY,
|
|
58044
|
+
DEFAULT_MESH_SCHEDULING_STRATEGY,
|
|
57245
58045
|
DEFAULT_SESSION_HOST_APP_NAME,
|
|
57246
58046
|
DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
57247
58047
|
DEFAULT_SESSION_HOST_READY_TIMEOUT_MS,
|
|
@@ -57267,9 +58067,12 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57267
58067
|
InMemoryGitSnapshotStore,
|
|
57268
58068
|
LOG,
|
|
57269
58069
|
MAX_LEDGER_SLICE_LIMIT,
|
|
58070
|
+
MESH_CONVERGE_FAST_FORWARD_TAG,
|
|
58071
|
+
MESH_CONVERGE_REFINE_TAG,
|
|
57270
58072
|
MESH_MISSION_STATUSES,
|
|
57271
58073
|
MESH_REFINE_CONFIG_LOCATIONS,
|
|
57272
58074
|
MESH_REFINE_CONFIG_SCHEMA,
|
|
58075
|
+
MESH_SCHEDULING_STRATEGIES,
|
|
57273
58076
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
|
|
57274
58077
|
MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
|
|
57275
58078
|
MIN_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
@@ -57470,6 +58273,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57470
58273
|
normalizeManagedStatus,
|
|
57471
58274
|
normalizeMeshCapabilityTags,
|
|
57472
58275
|
normalizeMeshDaemonRole,
|
|
58276
|
+
normalizeMeshSchedulingStrategy,
|
|
57473
58277
|
normalizeMeshTaskMode,
|
|
57474
58278
|
normalizeMeshWorkerResult,
|
|
57475
58279
|
normalizeMessageParts,
|
|
@@ -57507,7 +58311,9 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57507
58311
|
resetConfig,
|
|
57508
58312
|
resetDebugRuntimeConfig,
|
|
57509
58313
|
resetState,
|
|
58314
|
+
resolveAutoConvergeCodeChange,
|
|
57510
58315
|
resolveChatMessageKind,
|
|
58316
|
+
resolveConvergeRequiredTags,
|
|
57511
58317
|
resolveCurrentGlobalInstallSurface,
|
|
57512
58318
|
resolveDebugRuntimeConfig,
|
|
57513
58319
|
resolveDelegatedWorkerAutoApprove,
|
|
@@ -57515,6 +58321,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
57515
58321
|
resolveGitRepository,
|
|
57516
58322
|
resolveMeshHostStatus,
|
|
57517
58323
|
resolveMeshRefineValidationPlan,
|
|
58324
|
+
resolveNodeSchedulingPriority,
|
|
57518
58325
|
resolveSessionHostAppName,
|
|
57519
58326
|
resolveSessionHostAppNameResolution,
|
|
57520
58327
|
resolveWorktreePath,
|