@adhdev/daemon-core 0.9.82-rc.352 → 0.9.82-rc.354
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/handler.d.ts +15 -0
- package/dist/commands/router.d.ts +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +558 -364
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +555 -364
- package/dist/index.mjs.map +1 -1
- package/dist/providers/acp-provider-instance.d.ts +3 -0
- package/dist/providers/cli-provider-instance.d.ts +12 -0
- package/dist/providers/manual-attendance.d.ts +63 -0
- package/dist/providers/provider-instance.d.ts +8 -0
- package/package.json +2 -2
- package/src/commands/cli-manager.ts +33 -6
- package/src/commands/handler.ts +32 -0
- package/src/commands/router.ts +133 -33
- package/src/git/git-diff.ts +31 -14
- package/src/index.ts +5 -0
- package/src/providers/acp-provider-instance.ts +18 -1
- package/src/providers/cli-provider-instance.ts +54 -3
- package/src/providers/manual-attendance.ts +85 -0
- package/src/providers/provider-instance.ts +9 -0
package/dist/index.mjs
CHANGED
|
@@ -311,10 +311,10 @@ function readInjected(value) {
|
|
|
311
311
|
}
|
|
312
312
|
function getDaemonBuildInfo() {
|
|
313
313
|
if (cached) return cached;
|
|
314
|
-
const commit = readInjected(true ? "
|
|
315
|
-
const commitShort = readInjected(true ? "
|
|
316
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
317
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
314
|
+
const commit = readInjected(true ? "5d100a177f412ae29a58048f0a211c3928b06910" : void 0) ?? "unknown";
|
|
315
|
+
const commitShort = readInjected(true ? "5d100a17" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
316
|
+
const version = readInjected(true ? "0.9.82-rc.354" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
317
|
+
const builtAt = readInjected(true ? "2026-06-22T11:32:05.389Z" : void 0);
|
|
318
318
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
319
319
|
return cached;
|
|
320
320
|
}
|
|
@@ -1067,6 +1067,9 @@ __export(git_diff_exports, {
|
|
|
1067
1067
|
});
|
|
1068
1068
|
import { readFile, realpath as realpath2 } from "fs/promises";
|
|
1069
1069
|
import * as path2 from "path";
|
|
1070
|
+
function withCollectionTimeout(options) {
|
|
1071
|
+
return options.timeoutMs === void 0 ? { ...options, timeoutMs: GIT_STATUS_TIMEOUT_MS } : options;
|
|
1072
|
+
}
|
|
1070
1073
|
function validateBaseRef(ref) {
|
|
1071
1074
|
const trimmed = ref.trim();
|
|
1072
1075
|
if (!trimmed || trimmed.startsWith("-") || trimmed.includes("..") || !/^[A-Za-z0-9][A-Za-z0-9._/@-]*$/.test(trimmed)) {
|
|
@@ -1076,14 +1079,15 @@ function validateBaseRef(ref) {
|
|
|
1076
1079
|
}
|
|
1077
1080
|
async function getGitDiffSummary(workspace, options = {}) {
|
|
1078
1081
|
const lastCheckedAt = Date.now();
|
|
1082
|
+
const effectiveOptions = withCollectionTimeout(options);
|
|
1079
1083
|
try {
|
|
1080
|
-
const repo = await resolveGitRepository(workspace,
|
|
1084
|
+
const repo = await resolveGitRepository(workspace, effectiveOptions);
|
|
1081
1085
|
const repoRoot = repo.repoRoot;
|
|
1082
1086
|
if (options.baseRef) {
|
|
1083
1087
|
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
1084
1088
|
const [nameStatus, numstat] = await Promise.all([
|
|
1085
|
-
runGit(repo, ["diff", "--no-ext-diff", "--name-status", range, "--"], { ...
|
|
1086
|
-
runGit(repo, ["diff", "--no-ext-diff", "--numstat", range, "--"], { ...
|
|
1089
|
+
runGit(repo, ["diff", "--no-ext-diff", "--name-status", range, "--"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1090
|
+
runGit(repo, ["diff", "--no-ext-diff", "--numstat", range, "--"], { ...effectiveOptions, cwd: repoRoot })
|
|
1087
1091
|
]);
|
|
1088
1092
|
const outputBytes2 = byteLength(nameStatus.stdout + numstat.stdout);
|
|
1089
1093
|
const changes2 = combineDiffEntries(nameStatus.stdout, numstat.stdout, false);
|
|
@@ -1102,11 +1106,11 @@ async function getGitDiffSummary(workspace, options = {}) {
|
|
|
1102
1106
|
};
|
|
1103
1107
|
}
|
|
1104
1108
|
const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
|
|
1105
|
-
runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...
|
|
1106
|
-
runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...
|
|
1107
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...
|
|
1108
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...
|
|
1109
|
-
runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...
|
|
1109
|
+
runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1110
|
+
runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1111
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1112
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1113
|
+
runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...effectiveOptions, cwd: repoRoot })
|
|
1110
1114
|
]);
|
|
1111
1115
|
const outputBytes = byteLength(
|
|
1112
1116
|
unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
|
|
@@ -1148,13 +1152,14 @@ async function getGitDiffSummary(workspace, options = {}) {
|
|
|
1148
1152
|
}
|
|
1149
1153
|
async function getGitFileDiff(workspace, filePath, options = {}) {
|
|
1150
1154
|
const lastCheckedAt = Date.now();
|
|
1151
|
-
const
|
|
1155
|
+
const effectiveOptions = withCollectionTimeout(options);
|
|
1156
|
+
const repo = await resolveGitRepository(workspace, effectiveOptions);
|
|
1152
1157
|
const repoRoot = repo.repoRoot;
|
|
1153
1158
|
const selected = await resolveRepoFilePath(repoRoot, filePath);
|
|
1154
1159
|
const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
|
|
1155
1160
|
if (options.baseRef) {
|
|
1156
1161
|
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
1157
|
-
const result = await runGit(repo, ["diff", "--no-ext-diff", range, "--", selected.relativePath], { ...
|
|
1162
|
+
const result = await runGit(repo, ["diff", "--no-ext-diff", range, "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot });
|
|
1158
1163
|
const bounded2 = truncateText(result.stdout, maxBytes);
|
|
1159
1164
|
return {
|
|
1160
1165
|
workspace: repo.workspace,
|
|
@@ -1167,13 +1172,13 @@ async function getGitFileDiff(workspace, filePath, options = {}) {
|
|
|
1167
1172
|
};
|
|
1168
1173
|
}
|
|
1169
1174
|
const [unstaged, staged] = await Promise.all([
|
|
1170
|
-
runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...
|
|
1171
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...
|
|
1175
|
+
runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot }),
|
|
1176
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot })
|
|
1172
1177
|
]);
|
|
1173
1178
|
let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
|
|
1174
1179
|
if (!diff) {
|
|
1175
1180
|
const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
|
|
1176
|
-
...
|
|
1181
|
+
...effectiveOptions,
|
|
1177
1182
|
cwd: repoRoot
|
|
1178
1183
|
});
|
|
1179
1184
|
const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
|
|
@@ -2703,6 +2708,257 @@ var init_mesh_config = __esm({
|
|
|
2703
2708
|
}
|
|
2704
2709
|
});
|
|
2705
2710
|
|
|
2711
|
+
// ../mesh-shared/dist/index.mjs
|
|
2712
|
+
function readRecord(value) {
|
|
2713
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2714
|
+
}
|
|
2715
|
+
function readString3(...values) {
|
|
2716
|
+
for (const value of values) {
|
|
2717
|
+
if (typeof value !== "string") continue;
|
|
2718
|
+
const trimmed = value.trim();
|
|
2719
|
+
if (trimmed) return trimmed;
|
|
2720
|
+
}
|
|
2721
|
+
return void 0;
|
|
2722
|
+
}
|
|
2723
|
+
function readNumber(...values) {
|
|
2724
|
+
for (const value of values) {
|
|
2725
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2726
|
+
}
|
|
2727
|
+
return void 0;
|
|
2728
|
+
}
|
|
2729
|
+
function readBoolean(...values) {
|
|
2730
|
+
for (const value of values) {
|
|
2731
|
+
if (typeof value === "boolean") return value;
|
|
2732
|
+
}
|
|
2733
|
+
return void 0;
|
|
2734
|
+
}
|
|
2735
|
+
function joinRepoPath(root, relativePath) {
|
|
2736
|
+
const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
|
|
2737
|
+
const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
|
|
2738
|
+
if (!normalizedPath) return void 0;
|
|
2739
|
+
if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
|
|
2740
|
+
if (!normalizedRoot) return void 0;
|
|
2741
|
+
return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
|
|
2742
|
+
}
|
|
2743
|
+
function scoreGitUpstreamFreshness(status) {
|
|
2744
|
+
switch (status) {
|
|
2745
|
+
case "fresh":
|
|
2746
|
+
return 30;
|
|
2747
|
+
case "no_upstream":
|
|
2748
|
+
return 4;
|
|
2749
|
+
case "unchecked":
|
|
2750
|
+
case void 0:
|
|
2751
|
+
return 0;
|
|
2752
|
+
case "stale":
|
|
2753
|
+
return -10;
|
|
2754
|
+
case "unavailable":
|
|
2755
|
+
return -15;
|
|
2756
|
+
default:
|
|
2757
|
+
return 0;
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
function readGitSubmodules(value, parentRepoRoot) {
|
|
2761
|
+
if (!Array.isArray(value)) return void 0;
|
|
2762
|
+
const submodules = value.map((entry) => {
|
|
2763
|
+
const submodule = readRecord(entry);
|
|
2764
|
+
const path42 = readString3(submodule.path);
|
|
2765
|
+
const commit = readString3(submodule.commit);
|
|
2766
|
+
const repoPath = readString3(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path42);
|
|
2767
|
+
if (!path42 || !commit) return null;
|
|
2768
|
+
const result = {
|
|
2769
|
+
path: path42,
|
|
2770
|
+
commit,
|
|
2771
|
+
dirty: readBoolean(submodule.dirty) ?? false,
|
|
2772
|
+
outOfSync: readBoolean(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
2773
|
+
lastCheckedAt: readNumber(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now()
|
|
2774
|
+
};
|
|
2775
|
+
if (repoPath) result.repoPath = repoPath;
|
|
2776
|
+
const error = readString3(submodule.error);
|
|
2777
|
+
if (error) result.error = error;
|
|
2778
|
+
return result;
|
|
2779
|
+
}).filter((entry) => entry !== null);
|
|
2780
|
+
return submodules.length > 0 ? submodules : void 0;
|
|
2781
|
+
}
|
|
2782
|
+
function hasGitStatusEvidence(status) {
|
|
2783
|
+
return readBoolean(status.isGitRepo) !== void 0 || Boolean(readString3(status.branch, status.upstream, status.upstreamStatus, status.upstream_status, status.headCommit)) || Boolean(readString3(status.repoRoot, status.repo_root, status.workspace)) || readNumber(
|
|
2784
|
+
status.ahead,
|
|
2785
|
+
status.behind,
|
|
2786
|
+
status.staged,
|
|
2787
|
+
status.modified,
|
|
2788
|
+
status.untracked,
|
|
2789
|
+
status.deleted,
|
|
2790
|
+
status.renamed,
|
|
2791
|
+
status.lastCheckedAt,
|
|
2792
|
+
status.last_checked_at
|
|
2793
|
+
) !== void 0 || Array.isArray(status.submodules) && status.submodules.length > 0;
|
|
2794
|
+
}
|
|
2795
|
+
function normalizeGitStatus(status, node, options) {
|
|
2796
|
+
const explicitIsGitRepo = readBoolean(status.isGitRepo);
|
|
2797
|
+
if (!Object.keys(status).length || !hasGitStatusEvidence(status)) return void 0;
|
|
2798
|
+
const isGitRepo = explicitIsGitRepo ?? true;
|
|
2799
|
+
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((entry) => typeof entry === "string") : [];
|
|
2800
|
+
const conflictCount = readNumber(status.conflicts) ?? conflictFiles.length;
|
|
2801
|
+
const hasConflicts = readBoolean(status.hasConflicts) ?? conflictCount > 0;
|
|
2802
|
+
const repoRoot = readString3(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
|
|
2803
|
+
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
2804
|
+
const upstreamStatus = readString3(status.upstreamStatus, status.upstream_status);
|
|
2805
|
+
const upstreamFetchedAt = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
|
|
2806
|
+
const upstreamFetchError = readString3(status.upstreamFetchError, status.upstream_fetch_error);
|
|
2807
|
+
const error = readString3(status.error);
|
|
2808
|
+
const staged = readNumber(status.staged) ?? 0;
|
|
2809
|
+
const modified = readNumber(status.modified) ?? 0;
|
|
2810
|
+
const untracked = readNumber(status.untracked) ?? 0;
|
|
2811
|
+
const deleted = readNumber(status.deleted) ?? 0;
|
|
2812
|
+
const renamed = readNumber(status.renamed) ?? 0;
|
|
2813
|
+
return {
|
|
2814
|
+
workspace: readString3(status.workspace, node.workspace) || "",
|
|
2815
|
+
repoRoot: repoRoot ?? null,
|
|
2816
|
+
isGitRepo,
|
|
2817
|
+
branch: readString3(status.branch) ?? null,
|
|
2818
|
+
headCommit: readString3(status.headCommit) ?? null,
|
|
2819
|
+
headMessage: readString3(status.headMessage) ?? null,
|
|
2820
|
+
upstream: readString3(status.upstream) ?? null,
|
|
2821
|
+
upstreamStatus: upstreamStatus ?? "unchecked",
|
|
2822
|
+
...upstreamFetchedAt !== void 0 ? { upstreamFetchedAt } : {},
|
|
2823
|
+
...upstreamFetchError ? { upstreamFetchError } : {},
|
|
2824
|
+
ahead: readNumber(status.ahead) ?? 0,
|
|
2825
|
+
behind: readNumber(status.behind) ?? 0,
|
|
2826
|
+
staged,
|
|
2827
|
+
modified,
|
|
2828
|
+
untracked,
|
|
2829
|
+
deleted,
|
|
2830
|
+
renamed,
|
|
2831
|
+
dirty: readBoolean(status.dirty, status.isDirty, status.is_dirty) ?? (staged + modified + untracked + deleted + renamed > 0 || hasConflicts),
|
|
2832
|
+
hasConflicts,
|
|
2833
|
+
conflictFiles,
|
|
2834
|
+
stashCount: readNumber(status.stashCount, status.stash_count) ?? 0,
|
|
2835
|
+
lastCheckedAt: options?.lastCheckedAt ?? readNumber(status.lastCheckedAt, status.last_checked_at) ?? Date.now(),
|
|
2836
|
+
...submodules ? { submodules } : {},
|
|
2837
|
+
...error ? { error } : {}
|
|
2838
|
+
};
|
|
2839
|
+
}
|
|
2840
|
+
function scoreGitStatusCandidate(git) {
|
|
2841
|
+
if (!git) return Number.NEGATIVE_INFINITY;
|
|
2842
|
+
let score = 0;
|
|
2843
|
+
if (git.isGitRepo === true) score += 50;
|
|
2844
|
+
if (git.isGitRepo === false) score -= 10;
|
|
2845
|
+
if (git.branch) score += 20;
|
|
2846
|
+
if (git.headCommit) score += 20;
|
|
2847
|
+
if (git.upstream) score += 10;
|
|
2848
|
+
score += scoreGitUpstreamFreshness(git.upstreamStatus);
|
|
2849
|
+
if (typeof git.ahead === "number") score += 2;
|
|
2850
|
+
if (typeof git.behind === "number") score += 2;
|
|
2851
|
+
if (Array.isArray(git.submodules) && git.submodules.length > 0) score += 4 + git.submodules.length;
|
|
2852
|
+
if (git.error) score -= 20;
|
|
2853
|
+
return score;
|
|
2854
|
+
}
|
|
2855
|
+
function pickBestTransitGitStatus(node, options) {
|
|
2856
|
+
const rawGit = readRecord(node.lastGit ?? node.last_git);
|
|
2857
|
+
const gitResult = readRecord(rawGit.result);
|
|
2858
|
+
const directStatus = readRecord(rawGit.status);
|
|
2859
|
+
const nestedStatus = readRecord(gitResult.status);
|
|
2860
|
+
const rawProbe = readRecord(node.lastProbe ?? node.last_probe);
|
|
2861
|
+
const probeGit = readRecord(rawProbe.git);
|
|
2862
|
+
const probeGitResult = readRecord(probeGit.result);
|
|
2863
|
+
const probeDirectStatus = readRecord(probeGit.status);
|
|
2864
|
+
const probeNestedStatus = readRecord(probeGitResult.status);
|
|
2865
|
+
const lastCheckedAt = options?.lastCheckedAt;
|
|
2866
|
+
let best = null;
|
|
2867
|
+
for (const status of [directStatus, nestedStatus, probeDirectStatus, probeNestedStatus]) {
|
|
2868
|
+
const normalized = normalizeGitStatus(status, node, { lastCheckedAt: lastCheckedAt ?? Date.now() });
|
|
2869
|
+
if (!normalized) continue;
|
|
2870
|
+
const score = scoreGitStatusCandidate(normalized);
|
|
2871
|
+
if (!best || score > best.score) best = { git: normalized, score };
|
|
2872
|
+
}
|
|
2873
|
+
return best?.git;
|
|
2874
|
+
}
|
|
2875
|
+
function normalizeMeshNodeId(node) {
|
|
2876
|
+
const record = node && typeof node === "object" ? node : {};
|
|
2877
|
+
return readString3(record.id, record.nodeId, record.node_id);
|
|
2878
|
+
}
|
|
2879
|
+
function meshNodeIdMatches(node, candidateId) {
|
|
2880
|
+
if (!candidateId) return false;
|
|
2881
|
+
const trimmed = candidateId.trim();
|
|
2882
|
+
if (!trimmed) return false;
|
|
2883
|
+
return normalizeMeshNodeId(node) === trimmed;
|
|
2884
|
+
}
|
|
2885
|
+
function machineCoreFromDaemonId(id) {
|
|
2886
|
+
const trimmed = readString3(id);
|
|
2887
|
+
if (!trimmed) return void 0;
|
|
2888
|
+
for (const prefix of DAEMON_ID_PREFIXES) {
|
|
2889
|
+
if (trimmed.startsWith(prefix)) {
|
|
2890
|
+
const core = trimmed.slice(prefix.length).trim();
|
|
2891
|
+
return core || void 0;
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2894
|
+
return trimmed;
|
|
2895
|
+
}
|
|
2896
|
+
function daemonIdsEquivalent(a, b) {
|
|
2897
|
+
const coreA = machineCoreFromDaemonId(a);
|
|
2898
|
+
const coreB = machineCoreFromDaemonId(b);
|
|
2899
|
+
if (!coreA || !coreB) return false;
|
|
2900
|
+
return coreA === coreB;
|
|
2901
|
+
}
|
|
2902
|
+
function expandDaemonIdForms(ids) {
|
|
2903
|
+
const list = Array.isArray(ids) ? ids : ids != null ? [ids] : [];
|
|
2904
|
+
const out = [];
|
|
2905
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2906
|
+
const add = (value) => {
|
|
2907
|
+
if (!value || seen.has(value)) return;
|
|
2908
|
+
seen.add(value);
|
|
2909
|
+
out.push(value);
|
|
2910
|
+
};
|
|
2911
|
+
for (const raw of list) add(readString3(raw));
|
|
2912
|
+
for (const raw of list) {
|
|
2913
|
+
const core = machineCoreFromDaemonId(readString3(raw));
|
|
2914
|
+
if (!core || !core.startsWith("mach_")) continue;
|
|
2915
|
+
add(core);
|
|
2916
|
+
for (const prefix of DAEMON_ID_PREFIXES) add(`${prefix}${core}`);
|
|
2917
|
+
}
|
|
2918
|
+
return out;
|
|
2919
|
+
}
|
|
2920
|
+
function summarizeGitShape(status) {
|
|
2921
|
+
const record = readRecord(status);
|
|
2922
|
+
if (!Object.keys(record).length) return null;
|
|
2923
|
+
const submodules = Array.isArray(record.submodules) ? record.submodules.map((entry) => {
|
|
2924
|
+
const sub = readRecord(entry);
|
|
2925
|
+
return {
|
|
2926
|
+
path: readString3(sub.path) ?? null,
|
|
2927
|
+
commit: readString3(sub.commit)?.slice(0, 12) ?? null,
|
|
2928
|
+
dirty: readBoolean(sub.dirty) ?? false,
|
|
2929
|
+
outOfSync: readBoolean(sub.outOfSync, sub.out_of_sync) ?? false
|
|
2930
|
+
};
|
|
2931
|
+
}) : [];
|
|
2932
|
+
return {
|
|
2933
|
+
isGitRepo: readBoolean(record.isGitRepo),
|
|
2934
|
+
workspace: readString3(record.workspace) ?? null,
|
|
2935
|
+
repoRoot: readString3(record.repoRoot, record.repo_root) ?? null,
|
|
2936
|
+
branch: readString3(record.branch) ?? null,
|
|
2937
|
+
upstream: readString3(record.upstream) ?? null,
|
|
2938
|
+
upstreamStatus: readString3(record.upstreamStatus, record.upstream_status) ?? null,
|
|
2939
|
+
headCommit: readString3(record.headCommit, record.head_commit)?.slice(0, 12) ?? null,
|
|
2940
|
+
ahead: readNumber(record.ahead) ?? null,
|
|
2941
|
+
behind: readNumber(record.behind) ?? null,
|
|
2942
|
+
dirtyCounts: {
|
|
2943
|
+
staged: readNumber(record.staged) ?? 0,
|
|
2944
|
+
modified: readNumber(record.modified) ?? 0,
|
|
2945
|
+
untracked: readNumber(record.untracked) ?? 0,
|
|
2946
|
+
deleted: readNumber(record.deleted) ?? 0,
|
|
2947
|
+
renamed: readNumber(record.renamed) ?? 0
|
|
2948
|
+
},
|
|
2949
|
+
lastCheckedAt: readNumber(record.lastCheckedAt, record.last_checked_at) ?? null,
|
|
2950
|
+
submoduleCount: submodules.length,
|
|
2951
|
+
submodules
|
|
2952
|
+
};
|
|
2953
|
+
}
|
|
2954
|
+
var DAEMON_ID_PREFIXES;
|
|
2955
|
+
var init_dist = __esm({
|
|
2956
|
+
"../mesh-shared/dist/index.mjs"() {
|
|
2957
|
+
"use strict";
|
|
2958
|
+
DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2961
|
+
|
|
2706
2962
|
// src/mesh/coordinator-prompt.ts
|
|
2707
2963
|
var coordinator_prompt_exports = {};
|
|
2708
2964
|
__export(coordinator_prompt_exports, {
|
|
@@ -6310,10 +6566,10 @@ var init_mesh_missions = __esm({
|
|
|
6310
6566
|
});
|
|
6311
6567
|
|
|
6312
6568
|
// src/mesh/mesh-refine-status.ts
|
|
6313
|
-
function
|
|
6569
|
+
function readString4(value) {
|
|
6314
6570
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
6315
6571
|
}
|
|
6316
|
-
function
|
|
6572
|
+
function readRecord2(value) {
|
|
6317
6573
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
6318
6574
|
}
|
|
6319
6575
|
function eventStatus(event, fallback) {
|
|
@@ -6336,7 +6592,7 @@ function instructionForStatus(status) {
|
|
|
6336
6592
|
return "Refine job failed; inspect result/finalBranchConvergenceState in mesh_task_history, fix the blocker, then rerun mesh_refine_node when ready.";
|
|
6337
6593
|
}
|
|
6338
6594
|
function mergeJob(jobs, patch) {
|
|
6339
|
-
const jobId =
|
|
6595
|
+
const jobId = readString4(patch.jobId);
|
|
6340
6596
|
if (!jobId) return;
|
|
6341
6597
|
const previous = jobs.get(jobId);
|
|
6342
6598
|
const status = patch.status || previous?.status || "running";
|
|
@@ -6354,54 +6610,54 @@ function mergeJob(jobs, patch) {
|
|
|
6354
6610
|
function buildMeshAsyncRefineJobs(args) {
|
|
6355
6611
|
const jobs = /* @__PURE__ */ new Map();
|
|
6356
6612
|
for (const entry of args.ledgerEntries || []) {
|
|
6357
|
-
const payload =
|
|
6613
|
+
const payload = readRecord2(entry.payload);
|
|
6358
6614
|
if (payload?.source !== "refine_mesh_node_async_job") continue;
|
|
6359
|
-
const refineJob =
|
|
6360
|
-
const result =
|
|
6361
|
-
const finalState =
|
|
6362
|
-
const jobId =
|
|
6615
|
+
const refineJob = readRecord2(payload.refineJob);
|
|
6616
|
+
const result = readRecord2(payload.result);
|
|
6617
|
+
const finalState = readRecord2(payload.finalBranchConvergenceState) || readRecord2(result?.finalBranchConvergenceState);
|
|
6618
|
+
const jobId = readString4(refineJob?.jobId);
|
|
6363
6619
|
if (!jobId) continue;
|
|
6364
|
-
const status = ledgerStatus(entry.kind,
|
|
6620
|
+
const status = ledgerStatus(entry.kind, readString4(refineJob?.status));
|
|
6365
6621
|
mergeJob(jobs, {
|
|
6366
6622
|
jobId,
|
|
6367
|
-
interactionId:
|
|
6623
|
+
interactionId: readString4(refineJob?.interactionId),
|
|
6368
6624
|
status,
|
|
6369
|
-
meshId:
|
|
6370
|
-
nodeId:
|
|
6371
|
-
targetNodeId:
|
|
6372
|
-
targetDaemonId:
|
|
6373
|
-
workspace:
|
|
6374
|
-
branch:
|
|
6375
|
-
into:
|
|
6376
|
-
startedAt:
|
|
6377
|
-
completedAt:
|
|
6378
|
-
retryOfJobId:
|
|
6625
|
+
meshId: readString4(refineJob?.meshId) || args.meshId,
|
|
6626
|
+
nodeId: readString4(refineJob?.nodeId) || entry.nodeId,
|
|
6627
|
+
targetNodeId: readString4(refineJob?.nodeId) || entry.nodeId,
|
|
6628
|
+
targetDaemonId: readString4(refineJob?.targetDaemonId),
|
|
6629
|
+
workspace: readString4(refineJob?.workspace),
|
|
6630
|
+
branch: readString4(result?.branch) || readString4(finalState?.branch),
|
|
6631
|
+
into: readString4(result?.into) || readString4(finalState?.baseBranch),
|
|
6632
|
+
startedAt: readString4(refineJob?.startedAt),
|
|
6633
|
+
completedAt: readString4(refineJob?.completedAt),
|
|
6634
|
+
retryOfJobId: readString4(refineJob?.retryOfJobId) || readString4(payload.retryOfJobId),
|
|
6379
6635
|
lastLedgerKind: entry.kind,
|
|
6380
6636
|
lastUpdatedAt: entry.timestamp
|
|
6381
6637
|
});
|
|
6382
6638
|
}
|
|
6383
6639
|
for (const event of args.pendingEvents || []) {
|
|
6384
|
-
const metadata =
|
|
6640
|
+
const metadata = readRecord2(event.metadataEvent);
|
|
6385
6641
|
if (metadata?.source !== "refine_mesh_node_async_job") continue;
|
|
6386
|
-
const result =
|
|
6387
|
-
const finalState =
|
|
6388
|
-
const jobId =
|
|
6642
|
+
const result = readRecord2(metadata.result);
|
|
6643
|
+
const finalState = readRecord2(result?.finalBranchConvergenceState);
|
|
6644
|
+
const jobId = readString4(metadata.jobId);
|
|
6389
6645
|
if (!jobId) continue;
|
|
6390
|
-
const status = eventStatus(event.event,
|
|
6646
|
+
const status = eventStatus(event.event, readString4(metadata.status));
|
|
6391
6647
|
mergeJob(jobs, {
|
|
6392
6648
|
jobId,
|
|
6393
|
-
interactionId:
|
|
6649
|
+
interactionId: readString4(metadata.interactionId),
|
|
6394
6650
|
...status ? { status } : {},
|
|
6395
|
-
meshId:
|
|
6396
|
-
nodeId:
|
|
6397
|
-
targetNodeId:
|
|
6398
|
-
targetDaemonId:
|
|
6399
|
-
workspace:
|
|
6400
|
-
branch:
|
|
6401
|
-
into:
|
|
6402
|
-
startedAt:
|
|
6403
|
-
completedAt:
|
|
6404
|
-
retryOfJobId:
|
|
6651
|
+
meshId: readString4(metadata.meshId) || event.meshId || args.meshId,
|
|
6652
|
+
nodeId: readString4(metadata.nodeId) || event.nodeId,
|
|
6653
|
+
targetNodeId: readString4(metadata.nodeId) || event.nodeId,
|
|
6654
|
+
targetDaemonId: readString4(metadata.targetDaemonId),
|
|
6655
|
+
workspace: readString4(metadata.workspace) || event.workspace,
|
|
6656
|
+
branch: readString4(result?.branch) || readString4(finalState?.branch),
|
|
6657
|
+
into: readString4(result?.into) || readString4(finalState?.baseBranch),
|
|
6658
|
+
startedAt: readString4(metadata.startedAt),
|
|
6659
|
+
completedAt: readString4(metadata.completedAt),
|
|
6660
|
+
retryOfJobId: readString4(metadata.retryOfJobId),
|
|
6405
6661
|
lastEvent: event.event,
|
|
6406
6662
|
lastUpdatedAt: new Date(event.queuedAt).toISOString()
|
|
6407
6663
|
});
|
|
@@ -6462,10 +6718,10 @@ var mesh_review_inbox_exports = {};
|
|
|
6462
6718
|
__export(mesh_review_inbox_exports, {
|
|
6463
6719
|
deriveMeshReviewInboxItems: () => deriveMeshReviewInboxItems
|
|
6464
6720
|
});
|
|
6465
|
-
function
|
|
6721
|
+
function readString5(value) {
|
|
6466
6722
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
6467
6723
|
}
|
|
6468
|
-
function
|
|
6724
|
+
function readRecord3(value) {
|
|
6469
6725
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
6470
6726
|
}
|
|
6471
6727
|
function readStringArray3(value, max) {
|
|
@@ -6475,20 +6731,20 @@ function readStringArray3(value, max) {
|
|
|
6475
6731
|
}
|
|
6476
6732
|
function isLocalNodeStatus(node) {
|
|
6477
6733
|
if (node.isLocalWorktree === true) return true;
|
|
6478
|
-
const connection =
|
|
6479
|
-
return
|
|
6734
|
+
const connection = readRecord3(node.connection);
|
|
6735
|
+
return readString5(connection?.state) === "self";
|
|
6480
6736
|
}
|
|
6481
6737
|
function readNodeConvergence(node) {
|
|
6482
|
-
const convergence =
|
|
6483
|
-
const status =
|
|
6738
|
+
const convergence = readRecord3(node.branchConvergence);
|
|
6739
|
+
const status = readString5(convergence?.status);
|
|
6484
6740
|
if (!convergence || !status) return null;
|
|
6485
6741
|
return {
|
|
6486
6742
|
status,
|
|
6487
|
-
reason:
|
|
6488
|
-
nextStep:
|
|
6743
|
+
reason: readString5(convergence.reason),
|
|
6744
|
+
nextStep: readString5(convergence.nextStep),
|
|
6489
6745
|
needsConvergence: convergence.needsConvergence === true,
|
|
6490
|
-
branch:
|
|
6491
|
-
defaultBranch:
|
|
6746
|
+
branch: readString5(convergence.branch),
|
|
6747
|
+
defaultBranch: readString5(convergence.defaultBranch)
|
|
6492
6748
|
};
|
|
6493
6749
|
}
|
|
6494
6750
|
function isMergeCandidate(convergence) {
|
|
@@ -6496,15 +6752,15 @@ function isMergeCandidate(convergence) {
|
|
|
6496
6752
|
return convergence.status === "cleanup_candidate" && convergence.reason === "clean_non_default_worktree_branch";
|
|
6497
6753
|
}
|
|
6498
6754
|
function readWorkerArtifact(value) {
|
|
6499
|
-
const worker =
|
|
6755
|
+
const worker = readRecord3(value);
|
|
6500
6756
|
if (!worker) return null;
|
|
6501
6757
|
const changed = readStringArray3(worker.changedFiles, MAX_CHANGED_FILES);
|
|
6502
6758
|
return {
|
|
6503
|
-
status:
|
|
6504
|
-
...
|
|
6759
|
+
status: readString5(worker.status) ?? "unknown",
|
|
6760
|
+
...readString5(worker.classification) ? { classification: readString5(worker.classification) } : {},
|
|
6505
6761
|
changedFiles: changed.values,
|
|
6506
6762
|
...changed.truncated ? { changedFilesTruncated: true } : {},
|
|
6507
|
-
validationResults: Array.isArray(worker.validationResults) ? worker.validationResults.map((item) =>
|
|
6763
|
+
validationResults: Array.isArray(worker.validationResults) ? worker.validationResults.map((item) => readRecord3(item)).filter((item) => item !== null) : [],
|
|
6508
6764
|
errors: readStringArray3(worker.errors, 20).values,
|
|
6509
6765
|
requiresUserAction: worker.requiresUserAction === true
|
|
6510
6766
|
};
|
|
@@ -6518,43 +6774,43 @@ function resolveNodeEvidence(nodeId, ledgerEntries) {
|
|
|
6518
6774
|
for (let i = ledgerEntries.length - 1; i >= 0; i--) {
|
|
6519
6775
|
const entry = ledgerEntries[i];
|
|
6520
6776
|
if (entry.nodeId !== nodeId || !isTerminalLedgerKind(entry.kind)) continue;
|
|
6521
|
-
const payload =
|
|
6777
|
+
const payload = readRecord3(entry.payload) ?? {};
|
|
6522
6778
|
if (!evidence.available) {
|
|
6523
6779
|
if (payload.source === "refine_mesh_node_async_job") {
|
|
6524
|
-
const result =
|
|
6525
|
-
const validationSummary =
|
|
6780
|
+
const result = readRecord3(payload.result);
|
|
6781
|
+
const validationSummary = readRecord3(result?.validationSummary);
|
|
6526
6782
|
evidence = {
|
|
6527
6783
|
available: true,
|
|
6528
6784
|
kind: entry.kind,
|
|
6529
6785
|
source: "refine_job",
|
|
6530
6786
|
timestamp: entry.timestamp,
|
|
6531
6787
|
...entry.sessionId ? { sessionId: entry.sessionId } : {},
|
|
6532
|
-
bootstrap:
|
|
6788
|
+
bootstrap: readRecord3(validationSummary?.bootstrap),
|
|
6533
6789
|
validation: validationSummary ? Object.fromEntries(Object.entries(validationSummary).filter(([key]) => key !== "bootstrap")) : null,
|
|
6534
|
-
checkpoint:
|
|
6790
|
+
checkpoint: readRecord3(result?.checkpoint),
|
|
6535
6791
|
worker: null,
|
|
6536
|
-
...
|
|
6537
|
-
...
|
|
6792
|
+
...readRecord3(payload.finalBranchConvergenceState) ?? readRecord3(result?.finalBranchConvergenceState) ? { finalBranchConvergenceState: readRecord3(payload.finalBranchConvergenceState) ?? readRecord3(result?.finalBranchConvergenceState) } : {},
|
|
6793
|
+
...readRecord3(payload.refineJob) ? { refineJob: readRecord3(payload.refineJob) } : {}
|
|
6538
6794
|
};
|
|
6539
6795
|
} else {
|
|
6540
|
-
const envelope =
|
|
6796
|
+
const envelope = readRecord3(payload.evidence);
|
|
6541
6797
|
evidence = {
|
|
6542
6798
|
available: true,
|
|
6543
6799
|
kind: entry.kind,
|
|
6544
6800
|
source: "task_completion",
|
|
6545
6801
|
timestamp: entry.timestamp,
|
|
6546
|
-
...
|
|
6802
|
+
...readString5(payload.taskId) ? { taskId: readString5(payload.taskId) } : {},
|
|
6547
6803
|
...entry.sessionId ? { sessionId: entry.sessionId } : {},
|
|
6548
6804
|
bootstrap: null,
|
|
6549
|
-
validation:
|
|
6550
|
-
checkpoint:
|
|
6805
|
+
validation: readRecord3(envelope?.validation),
|
|
6806
|
+
checkpoint: readRecord3(envelope?.checkpoint),
|
|
6551
6807
|
worker: readWorkerArtifact(envelope?.workerResult ?? payload.workerResult)
|
|
6552
6808
|
};
|
|
6553
6809
|
}
|
|
6554
6810
|
}
|
|
6555
6811
|
if (!transcriptHandle) {
|
|
6556
|
-
const envelope =
|
|
6557
|
-
transcriptHandle =
|
|
6812
|
+
const envelope = readRecord3(payload.evidence);
|
|
6813
|
+
transcriptHandle = readRecord3(envelope?.transcriptHandle);
|
|
6558
6814
|
}
|
|
6559
6815
|
if (evidence.available && transcriptHandle) break;
|
|
6560
6816
|
}
|
|
@@ -6564,11 +6820,11 @@ function hasBlockedReviewRefineResult(nodeId, ledgerEntries) {
|
|
|
6564
6820
|
for (let i = ledgerEntries.length - 1; i >= 0; i--) {
|
|
6565
6821
|
const entry = ledgerEntries[i];
|
|
6566
6822
|
if (entry.nodeId !== nodeId || !isTerminalLedgerKind(entry.kind)) continue;
|
|
6567
|
-
const payload =
|
|
6823
|
+
const payload = readRecord3(entry.payload) ?? {};
|
|
6568
6824
|
if (payload.source !== "refine_mesh_node_async_job") continue;
|
|
6569
|
-
const result =
|
|
6570
|
-
const finalState =
|
|
6571
|
-
return
|
|
6825
|
+
const result = readRecord3(payload.result);
|
|
6826
|
+
const finalState = readRecord3(payload.finalBranchConvergenceState) ?? readRecord3(result?.finalBranchConvergenceState);
|
|
6827
|
+
return readString5(finalState?.status) === "blocked_review" || readString5(result?.code) === "blocked_review";
|
|
6572
6828
|
}
|
|
6573
6829
|
return false;
|
|
6574
6830
|
}
|
|
@@ -6577,7 +6833,7 @@ function deriveMeshReviewInboxItems(args) {
|
|
|
6577
6833
|
const excludedRemoteNodeIds = [];
|
|
6578
6834
|
const refineJobs = buildMeshAsyncRefineJobs({ ledgerEntries: args.ledgerEntries });
|
|
6579
6835
|
for (const node of args.nodes) {
|
|
6580
|
-
const nodeId =
|
|
6836
|
+
const nodeId = readString5(node.nodeId) ?? readString5(node.id);
|
|
6581
6837
|
if (!nodeId) continue;
|
|
6582
6838
|
if (!isLocalNodeStatus(node)) {
|
|
6583
6839
|
excludedRemoteNodeIds.push(nodeId);
|
|
@@ -6599,8 +6855,8 @@ function deriveMeshReviewInboxItems(args) {
|
|
|
6599
6855
|
) ?? null;
|
|
6600
6856
|
items.push({
|
|
6601
6857
|
nodeId,
|
|
6602
|
-
workspace:
|
|
6603
|
-
branch: convergence.branch ??
|
|
6858
|
+
workspace: readString5(node.workspace),
|
|
6859
|
+
branch: convergence.branch ?? readString5(node.worktreeBranch),
|
|
6604
6860
|
defaultBranch: convergence.defaultBranch,
|
|
6605
6861
|
isLocalWorktree: node.isLocalWorktree === true,
|
|
6606
6862
|
reviewReason,
|
|
@@ -7811,251 +8067,6 @@ var init_mesh_fast_forward = __esm({
|
|
|
7811
8067
|
}
|
|
7812
8068
|
});
|
|
7813
8069
|
|
|
7814
|
-
// ../mesh-shared/dist/index.mjs
|
|
7815
|
-
function readRecord3(value) {
|
|
7816
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
7817
|
-
}
|
|
7818
|
-
function readString5(...values) {
|
|
7819
|
-
for (const value of values) {
|
|
7820
|
-
if (typeof value !== "string") continue;
|
|
7821
|
-
const trimmed = value.trim();
|
|
7822
|
-
if (trimmed) return trimmed;
|
|
7823
|
-
}
|
|
7824
|
-
return void 0;
|
|
7825
|
-
}
|
|
7826
|
-
function readNumber(...values) {
|
|
7827
|
-
for (const value of values) {
|
|
7828
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
7829
|
-
}
|
|
7830
|
-
return void 0;
|
|
7831
|
-
}
|
|
7832
|
-
function readBoolean(...values) {
|
|
7833
|
-
for (const value of values) {
|
|
7834
|
-
if (typeof value === "boolean") return value;
|
|
7835
|
-
}
|
|
7836
|
-
return void 0;
|
|
7837
|
-
}
|
|
7838
|
-
function joinRepoPath(root, relativePath) {
|
|
7839
|
-
const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
|
|
7840
|
-
const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
|
|
7841
|
-
if (!normalizedPath) return void 0;
|
|
7842
|
-
if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
|
|
7843
|
-
if (!normalizedRoot) return void 0;
|
|
7844
|
-
return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
|
|
7845
|
-
}
|
|
7846
|
-
function scoreGitUpstreamFreshness(status) {
|
|
7847
|
-
switch (status) {
|
|
7848
|
-
case "fresh":
|
|
7849
|
-
return 30;
|
|
7850
|
-
case "no_upstream":
|
|
7851
|
-
return 4;
|
|
7852
|
-
case "unchecked":
|
|
7853
|
-
case void 0:
|
|
7854
|
-
return 0;
|
|
7855
|
-
case "stale":
|
|
7856
|
-
return -10;
|
|
7857
|
-
case "unavailable":
|
|
7858
|
-
return -15;
|
|
7859
|
-
default:
|
|
7860
|
-
return 0;
|
|
7861
|
-
}
|
|
7862
|
-
}
|
|
7863
|
-
function readGitSubmodules(value, parentRepoRoot) {
|
|
7864
|
-
if (!Array.isArray(value)) return void 0;
|
|
7865
|
-
const submodules = value.map((entry) => {
|
|
7866
|
-
const submodule = readRecord3(entry);
|
|
7867
|
-
const path42 = readString5(submodule.path);
|
|
7868
|
-
const commit = readString5(submodule.commit);
|
|
7869
|
-
const repoPath = readString5(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path42);
|
|
7870
|
-
if (!path42 || !commit) return null;
|
|
7871
|
-
const result = {
|
|
7872
|
-
path: path42,
|
|
7873
|
-
commit,
|
|
7874
|
-
dirty: readBoolean(submodule.dirty) ?? false,
|
|
7875
|
-
outOfSync: readBoolean(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
7876
|
-
lastCheckedAt: readNumber(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now()
|
|
7877
|
-
};
|
|
7878
|
-
if (repoPath) result.repoPath = repoPath;
|
|
7879
|
-
const error = readString5(submodule.error);
|
|
7880
|
-
if (error) result.error = error;
|
|
7881
|
-
return result;
|
|
7882
|
-
}).filter((entry) => entry !== null);
|
|
7883
|
-
return submodules.length > 0 ? submodules : void 0;
|
|
7884
|
-
}
|
|
7885
|
-
function hasGitStatusEvidence(status) {
|
|
7886
|
-
return readBoolean(status.isGitRepo) !== void 0 || Boolean(readString5(status.branch, status.upstream, status.upstreamStatus, status.upstream_status, status.headCommit)) || Boolean(readString5(status.repoRoot, status.repo_root, status.workspace)) || readNumber(
|
|
7887
|
-
status.ahead,
|
|
7888
|
-
status.behind,
|
|
7889
|
-
status.staged,
|
|
7890
|
-
status.modified,
|
|
7891
|
-
status.untracked,
|
|
7892
|
-
status.deleted,
|
|
7893
|
-
status.renamed,
|
|
7894
|
-
status.lastCheckedAt,
|
|
7895
|
-
status.last_checked_at
|
|
7896
|
-
) !== void 0 || Array.isArray(status.submodules) && status.submodules.length > 0;
|
|
7897
|
-
}
|
|
7898
|
-
function normalizeGitStatus(status, node, options) {
|
|
7899
|
-
const explicitIsGitRepo = readBoolean(status.isGitRepo);
|
|
7900
|
-
if (!Object.keys(status).length || !hasGitStatusEvidence(status)) return void 0;
|
|
7901
|
-
const isGitRepo = explicitIsGitRepo ?? true;
|
|
7902
|
-
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((entry) => typeof entry === "string") : [];
|
|
7903
|
-
const conflictCount = readNumber(status.conflicts) ?? conflictFiles.length;
|
|
7904
|
-
const hasConflicts = readBoolean(status.hasConflicts) ?? conflictCount > 0;
|
|
7905
|
-
const repoRoot = readString5(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
|
|
7906
|
-
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
7907
|
-
const upstreamStatus = readString5(status.upstreamStatus, status.upstream_status);
|
|
7908
|
-
const upstreamFetchedAt = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
|
|
7909
|
-
const upstreamFetchError = readString5(status.upstreamFetchError, status.upstream_fetch_error);
|
|
7910
|
-
const error = readString5(status.error);
|
|
7911
|
-
const staged = readNumber(status.staged) ?? 0;
|
|
7912
|
-
const modified = readNumber(status.modified) ?? 0;
|
|
7913
|
-
const untracked = readNumber(status.untracked) ?? 0;
|
|
7914
|
-
const deleted = readNumber(status.deleted) ?? 0;
|
|
7915
|
-
const renamed = readNumber(status.renamed) ?? 0;
|
|
7916
|
-
return {
|
|
7917
|
-
workspace: readString5(status.workspace, node.workspace) || "",
|
|
7918
|
-
repoRoot: repoRoot ?? null,
|
|
7919
|
-
isGitRepo,
|
|
7920
|
-
branch: readString5(status.branch) ?? null,
|
|
7921
|
-
headCommit: readString5(status.headCommit) ?? null,
|
|
7922
|
-
headMessage: readString5(status.headMessage) ?? null,
|
|
7923
|
-
upstream: readString5(status.upstream) ?? null,
|
|
7924
|
-
upstreamStatus: upstreamStatus ?? "unchecked",
|
|
7925
|
-
...upstreamFetchedAt !== void 0 ? { upstreamFetchedAt } : {},
|
|
7926
|
-
...upstreamFetchError ? { upstreamFetchError } : {},
|
|
7927
|
-
ahead: readNumber(status.ahead) ?? 0,
|
|
7928
|
-
behind: readNumber(status.behind) ?? 0,
|
|
7929
|
-
staged,
|
|
7930
|
-
modified,
|
|
7931
|
-
untracked,
|
|
7932
|
-
deleted,
|
|
7933
|
-
renamed,
|
|
7934
|
-
dirty: readBoolean(status.dirty, status.isDirty, status.is_dirty) ?? (staged + modified + untracked + deleted + renamed > 0 || hasConflicts),
|
|
7935
|
-
hasConflicts,
|
|
7936
|
-
conflictFiles,
|
|
7937
|
-
stashCount: readNumber(status.stashCount, status.stash_count) ?? 0,
|
|
7938
|
-
lastCheckedAt: options?.lastCheckedAt ?? readNumber(status.lastCheckedAt, status.last_checked_at) ?? Date.now(),
|
|
7939
|
-
...submodules ? { submodules } : {},
|
|
7940
|
-
...error ? { error } : {}
|
|
7941
|
-
};
|
|
7942
|
-
}
|
|
7943
|
-
function scoreGitStatusCandidate(git) {
|
|
7944
|
-
if (!git) return Number.NEGATIVE_INFINITY;
|
|
7945
|
-
let score = 0;
|
|
7946
|
-
if (git.isGitRepo === true) score += 50;
|
|
7947
|
-
if (git.isGitRepo === false) score -= 10;
|
|
7948
|
-
if (git.branch) score += 20;
|
|
7949
|
-
if (git.headCommit) score += 20;
|
|
7950
|
-
if (git.upstream) score += 10;
|
|
7951
|
-
score += scoreGitUpstreamFreshness(git.upstreamStatus);
|
|
7952
|
-
if (typeof git.ahead === "number") score += 2;
|
|
7953
|
-
if (typeof git.behind === "number") score += 2;
|
|
7954
|
-
if (Array.isArray(git.submodules) && git.submodules.length > 0) score += 4 + git.submodules.length;
|
|
7955
|
-
if (git.error) score -= 20;
|
|
7956
|
-
return score;
|
|
7957
|
-
}
|
|
7958
|
-
function pickBestTransitGitStatus(node, options) {
|
|
7959
|
-
const rawGit = readRecord3(node.lastGit ?? node.last_git);
|
|
7960
|
-
const gitResult = readRecord3(rawGit.result);
|
|
7961
|
-
const directStatus = readRecord3(rawGit.status);
|
|
7962
|
-
const nestedStatus = readRecord3(gitResult.status);
|
|
7963
|
-
const rawProbe = readRecord3(node.lastProbe ?? node.last_probe);
|
|
7964
|
-
const probeGit = readRecord3(rawProbe.git);
|
|
7965
|
-
const probeGitResult = readRecord3(probeGit.result);
|
|
7966
|
-
const probeDirectStatus = readRecord3(probeGit.status);
|
|
7967
|
-
const probeNestedStatus = readRecord3(probeGitResult.status);
|
|
7968
|
-
const lastCheckedAt = options?.lastCheckedAt;
|
|
7969
|
-
let best = null;
|
|
7970
|
-
for (const status of [directStatus, nestedStatus, probeDirectStatus, probeNestedStatus]) {
|
|
7971
|
-
const normalized = normalizeGitStatus(status, node, { lastCheckedAt: lastCheckedAt ?? Date.now() });
|
|
7972
|
-
if (!normalized) continue;
|
|
7973
|
-
const score = scoreGitStatusCandidate(normalized);
|
|
7974
|
-
if (!best || score > best.score) best = { git: normalized, score };
|
|
7975
|
-
}
|
|
7976
|
-
return best?.git;
|
|
7977
|
-
}
|
|
7978
|
-
function normalizeMeshNodeId(node) {
|
|
7979
|
-
const record = node && typeof node === "object" ? node : {};
|
|
7980
|
-
return readString5(record.id, record.nodeId, record.node_id);
|
|
7981
|
-
}
|
|
7982
|
-
function meshNodeIdMatches(node, candidateId) {
|
|
7983
|
-
if (!candidateId) return false;
|
|
7984
|
-
const trimmed = candidateId.trim();
|
|
7985
|
-
if (!trimmed) return false;
|
|
7986
|
-
return normalizeMeshNodeId(node) === trimmed;
|
|
7987
|
-
}
|
|
7988
|
-
function machineCoreFromDaemonId(id) {
|
|
7989
|
-
const trimmed = readString5(id);
|
|
7990
|
-
if (!trimmed) return void 0;
|
|
7991
|
-
for (const prefix of DAEMON_ID_PREFIXES) {
|
|
7992
|
-
if (trimmed.startsWith(prefix)) {
|
|
7993
|
-
const core = trimmed.slice(prefix.length).trim();
|
|
7994
|
-
return core || void 0;
|
|
7995
|
-
}
|
|
7996
|
-
}
|
|
7997
|
-
return trimmed;
|
|
7998
|
-
}
|
|
7999
|
-
function expandDaemonIdForms(ids) {
|
|
8000
|
-
const list = Array.isArray(ids) ? ids : ids != null ? [ids] : [];
|
|
8001
|
-
const out = [];
|
|
8002
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8003
|
-
const add = (value) => {
|
|
8004
|
-
if (!value || seen.has(value)) return;
|
|
8005
|
-
seen.add(value);
|
|
8006
|
-
out.push(value);
|
|
8007
|
-
};
|
|
8008
|
-
for (const raw of list) add(readString5(raw));
|
|
8009
|
-
for (const raw of list) {
|
|
8010
|
-
const core = machineCoreFromDaemonId(readString5(raw));
|
|
8011
|
-
if (!core || !core.startsWith("mach_")) continue;
|
|
8012
|
-
add(core);
|
|
8013
|
-
for (const prefix of DAEMON_ID_PREFIXES) add(`${prefix}${core}`);
|
|
8014
|
-
}
|
|
8015
|
-
return out;
|
|
8016
|
-
}
|
|
8017
|
-
function summarizeGitShape(status) {
|
|
8018
|
-
const record = readRecord3(status);
|
|
8019
|
-
if (!Object.keys(record).length) return null;
|
|
8020
|
-
const submodules = Array.isArray(record.submodules) ? record.submodules.map((entry) => {
|
|
8021
|
-
const sub = readRecord3(entry);
|
|
8022
|
-
return {
|
|
8023
|
-
path: readString5(sub.path) ?? null,
|
|
8024
|
-
commit: readString5(sub.commit)?.slice(0, 12) ?? null,
|
|
8025
|
-
dirty: readBoolean(sub.dirty) ?? false,
|
|
8026
|
-
outOfSync: readBoolean(sub.outOfSync, sub.out_of_sync) ?? false
|
|
8027
|
-
};
|
|
8028
|
-
}) : [];
|
|
8029
|
-
return {
|
|
8030
|
-
isGitRepo: readBoolean(record.isGitRepo),
|
|
8031
|
-
workspace: readString5(record.workspace) ?? null,
|
|
8032
|
-
repoRoot: readString5(record.repoRoot, record.repo_root) ?? null,
|
|
8033
|
-
branch: readString5(record.branch) ?? null,
|
|
8034
|
-
upstream: readString5(record.upstream) ?? null,
|
|
8035
|
-
upstreamStatus: readString5(record.upstreamStatus, record.upstream_status) ?? null,
|
|
8036
|
-
headCommit: readString5(record.headCommit, record.head_commit)?.slice(0, 12) ?? null,
|
|
8037
|
-
ahead: readNumber(record.ahead) ?? null,
|
|
8038
|
-
behind: readNumber(record.behind) ?? null,
|
|
8039
|
-
dirtyCounts: {
|
|
8040
|
-
staged: readNumber(record.staged) ?? 0,
|
|
8041
|
-
modified: readNumber(record.modified) ?? 0,
|
|
8042
|
-
untracked: readNumber(record.untracked) ?? 0,
|
|
8043
|
-
deleted: readNumber(record.deleted) ?? 0,
|
|
8044
|
-
renamed: readNumber(record.renamed) ?? 0
|
|
8045
|
-
},
|
|
8046
|
-
lastCheckedAt: readNumber(record.lastCheckedAt, record.last_checked_at) ?? null,
|
|
8047
|
-
submoduleCount: submodules.length,
|
|
8048
|
-
submodules
|
|
8049
|
-
};
|
|
8050
|
-
}
|
|
8051
|
-
var DAEMON_ID_PREFIXES;
|
|
8052
|
-
var init_dist = __esm({
|
|
8053
|
-
"../mesh-shared/dist/index.mjs"() {
|
|
8054
|
-
"use strict";
|
|
8055
|
-
DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
|
|
8056
|
-
}
|
|
8057
|
-
});
|
|
8058
|
-
|
|
8059
8070
|
// src/mesh/mesh-active-work.ts
|
|
8060
8071
|
function readString6(value) {
|
|
8061
8072
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
@@ -21435,6 +21446,7 @@ function getSavedProviderSessions(state, filters) {
|
|
|
21435
21446
|
|
|
21436
21447
|
// src/index.ts
|
|
21437
21448
|
init_mesh_config();
|
|
21449
|
+
init_dist();
|
|
21438
21450
|
init_coordinator_prompt();
|
|
21439
21451
|
init_mesh_missions();
|
|
21440
21452
|
init_mesh_task_stats();
|
|
@@ -27065,6 +27077,42 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
27065
27077
|
return fn() || null;
|
|
27066
27078
|
}
|
|
27067
27079
|
|
|
27080
|
+
// src/providers/manual-attendance.ts
|
|
27081
|
+
var AUTO_APPROVE_MANUAL_ATTENDANCE_SUPPRESS_MS = 6e4;
|
|
27082
|
+
var ManualAttendanceTracker = class {
|
|
27083
|
+
constructor(suppressMs = AUTO_APPROVE_MANUAL_ATTENDANCE_SUPPRESS_MS) {
|
|
27084
|
+
this.suppressMs = suppressMs;
|
|
27085
|
+
}
|
|
27086
|
+
lastInteractionAt = 0;
|
|
27087
|
+
/** Record that a human just drove this session by hand. */
|
|
27088
|
+
note(now = Date.now()) {
|
|
27089
|
+
this.lastInteractionAt = now;
|
|
27090
|
+
}
|
|
27091
|
+
/** True while a manual interaction is recent enough to suppress auto-approve. */
|
|
27092
|
+
isAttended(now = Date.now()) {
|
|
27093
|
+
return this.lastInteractionAt > 0 && now - this.lastInteractionAt < this.suppressMs;
|
|
27094
|
+
}
|
|
27095
|
+
/**
|
|
27096
|
+
* Milliseconds remaining in the current suppression window, or 0 when not
|
|
27097
|
+
* attended. Used to re-arm a re-check timer so auto-approve fires the moment
|
|
27098
|
+
* the window lapses even if the PTY/agent has since gone silent.
|
|
27099
|
+
*/
|
|
27100
|
+
remainingMs(now = Date.now()) {
|
|
27101
|
+
if (this.lastInteractionAt <= 0) return 0;
|
|
27102
|
+
return Math.max(0, this.suppressMs - (now - this.lastInteractionAt));
|
|
27103
|
+
}
|
|
27104
|
+
};
|
|
27105
|
+
var MANUAL_ATTENDANCE_COMMANDS = /* @__PURE__ */ new Set([
|
|
27106
|
+
"select_session",
|
|
27107
|
+
"open_panel",
|
|
27108
|
+
"invoke_provider_script",
|
|
27109
|
+
"set_mode",
|
|
27110
|
+
"change_model",
|
|
27111
|
+
"set_thought_level",
|
|
27112
|
+
"resolve_action",
|
|
27113
|
+
"pty_input"
|
|
27114
|
+
]);
|
|
27115
|
+
|
|
27068
27116
|
// src/commands/chat-commands.ts
|
|
27069
27117
|
init_contracts();
|
|
27070
27118
|
init_provider_input_support();
|
|
@@ -31404,11 +31452,38 @@ var DaemonCommandHandler = class {
|
|
|
31404
31452
|
setAgentStreamManager(manager) {
|
|
31405
31453
|
this._agentStream = manager;
|
|
31406
31454
|
}
|
|
31455
|
+
/**
|
|
31456
|
+
* When a command in the manual-attendance set arrives for a session this
|
|
31457
|
+
* daemon hosts, stamp the live instance so auto-approve holds while the user
|
|
31458
|
+
* drives the session by hand. Provider-common: the signal is the command
|
|
31459
|
+
* (foreground select_session / open_panel, controlbar invoke_provider_script
|
|
31460
|
+
* / set_mode / change_model / set_thought_level, manual resolve_action,
|
|
31461
|
+
* pty_input), never any CLI-specific modal text — so it works identically for
|
|
31462
|
+
* every CLI/ACP provider. send_chat is deliberately excluded because a
|
|
31463
|
+
* coordinator delegating a task to a worker also uses send_chat; counting it
|
|
31464
|
+
* would wrongly suppress the worker's delegated auto-approve. For a remote
|
|
31465
|
+
* mesh worker session the controlbar commands are forwarded to the owning
|
|
31466
|
+
* worker daemon, which runs this same hook there, so attendance is recorded
|
|
31467
|
+
* on the daemon that actually hosts the instance.
|
|
31468
|
+
*/
|
|
31469
|
+
noteManualAttendanceIfApplicable(cmd, args) {
|
|
31470
|
+
if (!MANUAL_ATTENDANCE_COMMANDS.has(cmd)) return;
|
|
31471
|
+
const sessionId = this._currentRoute.session?.sessionId || (typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "");
|
|
31472
|
+
if (!sessionId) return;
|
|
31473
|
+
const session = this._ctx.sessionRegistry?.get(sessionId);
|
|
31474
|
+
const instanceKey = session?.adapterKey || session?.instanceKey || sessionId;
|
|
31475
|
+
const instance = this._ctx.instanceManager?.getInstance(instanceKey);
|
|
31476
|
+
try {
|
|
31477
|
+
instance?.noteManualInteraction?.();
|
|
31478
|
+
} catch {
|
|
31479
|
+
}
|
|
31480
|
+
}
|
|
31407
31481
|
// ─── Command Dispatcher ──────────────────────────
|
|
31408
31482
|
async handle(cmd, args) {
|
|
31409
31483
|
this._currentRoute = this.resolveRoute(args);
|
|
31410
31484
|
const startedAt = Date.now();
|
|
31411
31485
|
this.logCommandStart(cmd, args);
|
|
31486
|
+
this.noteManualAttendanceIfApplicable(cmd, args);
|
|
31412
31487
|
let result;
|
|
31413
31488
|
if (isGitCommandName(cmd)) {
|
|
31414
31489
|
result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
|
|
@@ -35362,6 +35437,11 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35362
35437
|
// a settle gate was in progress. Drives AUTO_APPROVE_GATE_HYSTERESIS_MS so a
|
|
35363
35438
|
// brief generating flip does not immediately wipe the settle clock.
|
|
35364
35439
|
autoApproveInactiveSince = 0;
|
|
35440
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
35441
|
+
// this session from the dashboard, auto-approve holds so they can take manual
|
|
35442
|
+
// control. Background mesh workers are never attended → delegated auto-approve
|
|
35443
|
+
// is unaffected.
|
|
35444
|
+
manualAttendance = new ManualAttendanceTracker();
|
|
35365
35445
|
controlValues = {};
|
|
35366
35446
|
summaryMetadata = void 0;
|
|
35367
35447
|
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
@@ -35637,7 +35717,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35637
35717
|
}
|
|
35638
35718
|
getHotChatSessionState() {
|
|
35639
35719
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
35640
|
-
const autoApproveActive = adapterStatus.status
|
|
35720
|
+
const autoApproveActive = this.autoApproveEffectivelyActive(adapterStatus.status);
|
|
35641
35721
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
35642
35722
|
const visibleStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
35643
35723
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
@@ -35652,7 +35732,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35652
35732
|
}
|
|
35653
35733
|
getSessionModalState(sessionId) {
|
|
35654
35734
|
const adapterStatus = this.adapter.getStatus({ allowParse: true });
|
|
35655
|
-
const autoApproveActive = adapterStatus.status
|
|
35735
|
+
const autoApproveActive = this.autoApproveEffectivelyActive(adapterStatus.status);
|
|
35656
35736
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
35657
35737
|
const visibleStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
35658
35738
|
const dirName = workingDirBasename(this.workingDir);
|
|
@@ -35733,7 +35813,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35733
35813
|
} catch {
|
|
35734
35814
|
return null;
|
|
35735
35815
|
}
|
|
35736
|
-
if (adapterStatus.status === "waiting_approval" && !this.
|
|
35816
|
+
if (adapterStatus.status === "waiting_approval" && !this.autoApproveEffectivelyActive(adapterStatus.status)) {
|
|
35737
35817
|
return "waiting_approval";
|
|
35738
35818
|
}
|
|
35739
35819
|
return null;
|
|
@@ -36179,6 +36259,18 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36179
36259
|
this.lastApprovalEventFingerprint = "";
|
|
36180
36260
|
}
|
|
36181
36261
|
maybeAutoApproveStatus(adapterStatus, now = Date.now()) {
|
|
36262
|
+
if (adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove() && this.manualAttendance.isAttended(now)) {
|
|
36263
|
+
this.lastAutoApprovalSignature = "";
|
|
36264
|
+
this.pendingAutoApprovalSignature = "";
|
|
36265
|
+
this.pendingAutoApprovalSince = 0;
|
|
36266
|
+
this.autoApproveInactiveSince = 0;
|
|
36267
|
+
if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
|
|
36268
|
+
this.autoApproveSettleTimer = setTimeout(() => {
|
|
36269
|
+
this.autoApproveSettleTimer = null;
|
|
36270
|
+
this.recheckAutoApproveSettled();
|
|
36271
|
+
}, this.manualAttendance.remainingMs(now) + 20);
|
|
36272
|
+
return false;
|
|
36273
|
+
}
|
|
36182
36274
|
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
|
|
36183
36275
|
if (!autoApproveActive) {
|
|
36184
36276
|
this.lastAutoApprovalSignature = "";
|
|
@@ -36644,6 +36736,21 @@ ${effect.notification.body || ""}`.trim();
|
|
|
36644
36736
|
}
|
|
36645
36737
|
return false;
|
|
36646
36738
|
}
|
|
36739
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
36740
|
+
noteManualInteraction(now = Date.now()) {
|
|
36741
|
+
this.manualAttendance.note(now);
|
|
36742
|
+
}
|
|
36743
|
+
/**
|
|
36744
|
+
* Whether auto-approve should be treated as active *right now* for display
|
|
36745
|
+
* and firing decisions: the configured intent AND the user is not currently
|
|
36746
|
+
* attending this session by hand. When a human is attending, auto-approve is
|
|
36747
|
+
* held so the modal stays visible and they can drive it via the controlbar.
|
|
36748
|
+
* Provider-agnostic — the attendance signal is the command set, never any
|
|
36749
|
+
* CLI-specific modal text.
|
|
36750
|
+
*/
|
|
36751
|
+
autoApproveEffectivelyActive(status, now = Date.now()) {
|
|
36752
|
+
return status === "waiting_approval" && this.shouldAutoApprove() && !this.manualAttendance.isAttended(now);
|
|
36753
|
+
}
|
|
36647
36754
|
recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
|
|
36648
36755
|
this.appendRuntimeSystemMessage(
|
|
36649
36756
|
formatAutoApprovalMessage(modalMessage, buttonLabel),
|
|
@@ -37594,7 +37701,7 @@ var AcpProviderInstance = class {
|
|
|
37594
37701
|
input: tc.rawInput ? typeof tc.rawInput === "string" ? tc.rawInput : JSON.stringify(tc.rawInput) : void 0
|
|
37595
37702
|
});
|
|
37596
37703
|
}
|
|
37597
|
-
if (this.settings.autoApprove !== false) {
|
|
37704
|
+
if (this.settings.autoApprove !== false && !this.manualAttendance.isAttended()) {
|
|
37598
37705
|
const toolTitle = tc.title || tc.toolCallId || "tool call";
|
|
37599
37706
|
this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
|
|
37600
37707
|
this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
|
|
@@ -37825,6 +37932,15 @@ var AcpProviderInstance = class {
|
|
|
37825
37932
|
this.detectStatusTransition();
|
|
37826
37933
|
}
|
|
37827
37934
|
permissionResolvers = [];
|
|
37935
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
37936
|
+
// this session from the dashboard, auto-approve holds so they can decide on
|
|
37937
|
+
// the permission request themselves. Background workers are never attended →
|
|
37938
|
+
// delegated auto-approve is unaffected.
|
|
37939
|
+
manualAttendance = new ManualAttendanceTracker();
|
|
37940
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
37941
|
+
noteManualInteraction(now = Date.now()) {
|
|
37942
|
+
this.manualAttendance.note(now);
|
|
37943
|
+
}
|
|
37828
37944
|
async resolvePermission(approved) {
|
|
37829
37945
|
const resolver = this.permissionResolvers.shift();
|
|
37830
37946
|
if (resolver) {
|
|
@@ -38982,6 +39098,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38982
39098
|
);
|
|
38983
39099
|
continue;
|
|
38984
39100
|
}
|
|
39101
|
+
const restoredSettings = { ...this.providerLoader.getSettings(normalizedType) };
|
|
39102
|
+
const coordinatorEntry = getCoordinatorForSession(record.runtimeId);
|
|
39103
|
+
if (coordinatorEntry?.meshId) {
|
|
39104
|
+
restoredSettings.meshCoordinatorFor = coordinatorEntry.meshId;
|
|
39105
|
+
}
|
|
38985
39106
|
try {
|
|
38986
39107
|
await this.registerCliInstance(
|
|
38987
39108
|
record.runtimeId,
|
|
@@ -38990,7 +39111,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
38990
39111
|
record.workspace,
|
|
38991
39112
|
record.cliArgs,
|
|
38992
39113
|
resolvedProvider,
|
|
38993
|
-
|
|
39114
|
+
restoredSettings,
|
|
38994
39115
|
true,
|
|
38995
39116
|
{
|
|
38996
39117
|
providerSessionId: sessionBinding.providerSessionId,
|
|
@@ -39031,9 +39152,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39031
39152
|
}
|
|
39032
39153
|
}
|
|
39033
39154
|
}
|
|
39034
|
-
|
|
39035
|
-
|
|
39036
|
-
|
|
39155
|
+
if (!opts?.instanceKey) {
|
|
39156
|
+
for (const [k, a] of this.adapters) {
|
|
39157
|
+
if (a.cliType === agentType) {
|
|
39158
|
+
return { adapter: a, key: k };
|
|
39159
|
+
}
|
|
39037
39160
|
}
|
|
39038
39161
|
}
|
|
39039
39162
|
return null;
|
|
@@ -46390,7 +46513,14 @@ var MESH_FORWARDABLE_SESSION_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
46390
46513
|
"resolve_action",
|
|
46391
46514
|
"set_mode",
|
|
46392
46515
|
"change_model",
|
|
46393
|
-
"set_thought_level"
|
|
46516
|
+
"set_thought_level",
|
|
46517
|
+
// agent_command (send_chat / clear_history / stop) is session-scoped too: a command
|
|
46518
|
+
// explicitly naming a targetSessionId MUST reach that session wherever it lives, never a
|
|
46519
|
+
// different local session. Without forwarding, a misrouted/relayed send_chat for a REMOTE
|
|
46520
|
+
// worker session that reaches the wrong daemon used to fuzzy-inject the task body into that
|
|
46521
|
+
// daemon's own CLI session (TASKECHO coordinator self-echo). Forwarding to the owning daemon
|
|
46522
|
+
// delivers it to the real worker instead. (findAdapter is also fail-closed as the backstop.)
|
|
46523
|
+
"agent_command"
|
|
46394
46524
|
]);
|
|
46395
46525
|
var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
46396
46526
|
function normalizeCommandSource(source) {
|
|
@@ -46743,7 +46873,7 @@ var DaemonCommandRouter = class {
|
|
|
46743
46873
|
if (!collectMeshNodeHostedSessionIds(node).has(trimmed)) continue;
|
|
46744
46874
|
const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
|
|
46745
46875
|
if (!nodeDaemonId) continue;
|
|
46746
|
-
if (selfDaemonId && nodeDaemonId
|
|
46876
|
+
if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
|
|
46747
46877
|
return nodeDaemonId;
|
|
46748
46878
|
}
|
|
46749
46879
|
return void 0;
|
|
@@ -46898,6 +47028,38 @@ var DaemonCommandRouter = class {
|
|
|
46898
47028
|
if (record?.meta?.meshNodeId === nodeId) return true;
|
|
46899
47029
|
return false;
|
|
46900
47030
|
}
|
|
47031
|
+
/**
|
|
47032
|
+
* Best-effort recursive removal of a managed worktree directory.
|
|
47033
|
+
*
|
|
47034
|
+
* The git-registry de-registration is the safety-critical step of worktree
|
|
47035
|
+
* teardown; a leftover directory must never gate dropping the node from the
|
|
47036
|
+
* mesh. On Windows, `fs.rmSync` can throw EINVAL/EPERM/EBUSY on submodule
|
|
47037
|
+
* gitlink (`.git`) files, long paths, junctions, or while a just-stopped
|
|
47038
|
+
* delegate session is still releasing a handle/cwd on the directory. This
|
|
47039
|
+
* helper absorbs those errors (never throws), with bounded retries + backoff
|
|
47040
|
+
* to give handles time to release, and reports whether residue remains.
|
|
47041
|
+
*/
|
|
47042
|
+
async bestEffortRemoveWorktreeDir(dir) {
|
|
47043
|
+
if (!dir || !fs26.existsSync(dir)) return { removed: true, residue: false };
|
|
47044
|
+
const sleep3 = (ms) => new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
47045
|
+
const ABSORB = /* @__PURE__ */ new Set(["EINVAL", "EPERM", "EBUSY", "ENOTEMPTY", "EACCES", "EMFILE", "ENFILE"]);
|
|
47046
|
+
let lastErr;
|
|
47047
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
47048
|
+
try {
|
|
47049
|
+
fs26.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
47050
|
+
if (!fs26.existsSync(dir)) return { removed: true, residue: false };
|
|
47051
|
+
lastErr = new Error("directory still present after rmSync");
|
|
47052
|
+
} catch (e) {
|
|
47053
|
+
lastErr = e;
|
|
47054
|
+
const code = typeof e?.code === "string" ? e.code : "";
|
|
47055
|
+
if (code && !ABSORB.has(code)) {
|
|
47056
|
+
break;
|
|
47057
|
+
}
|
|
47058
|
+
}
|
|
47059
|
+
await sleep3(150 * (attempt + 1));
|
|
47060
|
+
}
|
|
47061
|
+
return fs26.existsSync(dir) ? { removed: false, residue: true, error: String(lastErr?.message || lastErr || "unknown rm error") } : { removed: true, residue: false };
|
|
47062
|
+
}
|
|
46901
47063
|
async cleanupLocalWorktreeNode(args) {
|
|
46902
47064
|
const workspace = typeof args.node?.workspace === "string" ? args.node.workspace.trim() : "";
|
|
46903
47065
|
if (!workspace) {
|
|
@@ -46952,11 +47114,31 @@ var DaemonCommandRouter = class {
|
|
|
46952
47114
|
const entries = await listWorktrees2(repoRoot);
|
|
46953
47115
|
const managedEntry = entries.find((entry) => normalizePath(entry.path) === actualPath);
|
|
46954
47116
|
if (!managedEntry) {
|
|
47117
|
+
try {
|
|
47118
|
+
const { execFile: execFile5 } = await import("child_process");
|
|
47119
|
+
const { promisify: promisify8 } = await import("util");
|
|
47120
|
+
const execFileAsync4 = promisify8(execFile5);
|
|
47121
|
+
await execFileAsync4("git", ["worktree", "prune"], {
|
|
47122
|
+
cwd: repoRoot,
|
|
47123
|
+
encoding: "utf8",
|
|
47124
|
+
timeout: 3e4,
|
|
47125
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
47126
|
+
windowsHide: true
|
|
47127
|
+
});
|
|
47128
|
+
} catch {
|
|
47129
|
+
}
|
|
47130
|
+
const rm = await this.bestEffortRemoveWorktreeDir(workspace);
|
|
46955
47131
|
return {
|
|
46956
|
-
success:
|
|
46957
|
-
|
|
46958
|
-
|
|
46959
|
-
|
|
47132
|
+
success: true,
|
|
47133
|
+
removedPath: workspace,
|
|
47134
|
+
repoRoot,
|
|
47135
|
+
reason: "worktree_unregistered_residue_recovered",
|
|
47136
|
+
recovered: true,
|
|
47137
|
+
...rm.residue ? {
|
|
47138
|
+
residue: true,
|
|
47139
|
+
residueWarning: `Worktree was already de-registered from git but the directory could not be fully removed (leftover residue at '${workspace}'): ${rm.error || "unknown error"}. The node will be dropped from the mesh; remove the directory manually if needed.`,
|
|
47140
|
+
residueError: rm.error
|
|
47141
|
+
} : {}
|
|
46960
47142
|
};
|
|
46961
47143
|
}
|
|
46962
47144
|
if (managedEntry.branch && managedEntry.branch !== args.node.worktreeBranch) {
|
|
@@ -47019,8 +47201,8 @@ var DaemonCommandRouter = class {
|
|
|
47019
47201
|
convergence: forceFallbackConvergence
|
|
47020
47202
|
};
|
|
47021
47203
|
} catch (deinitError) {
|
|
47204
|
+
const rm = await this.bestEffortRemoveWorktreeDir(workspace);
|
|
47022
47205
|
try {
|
|
47023
|
-
fs26.rmSync(workspace, { recursive: true, force: true });
|
|
47024
47206
|
await execFileAsync4("git", ["worktree", "prune"], {
|
|
47025
47207
|
cwd: repoRoot,
|
|
47026
47208
|
encoding: "utf8",
|
|
@@ -47028,23 +47210,22 @@ var DaemonCommandRouter = class {
|
|
|
47028
47210
|
maxBuffer: GIT_MAX_BUFFER_CLEANUP,
|
|
47029
47211
|
windowsHide: true
|
|
47030
47212
|
});
|
|
47031
|
-
|
|
47032
|
-
success: true,
|
|
47033
|
-
removedPath: workspace,
|
|
47034
|
-
repoRoot,
|
|
47035
|
-
fallback: "fs_rm_worktree_prune",
|
|
47036
|
-
forced: true,
|
|
47037
|
-
reason: "working_trees_containing_submodules",
|
|
47038
|
-
convergence: forceFallbackConvergence
|
|
47039
|
-
};
|
|
47040
|
-
} catch (rmError) {
|
|
47041
|
-
return {
|
|
47042
|
-
success: false,
|
|
47043
|
-
code: "mesh_worktree_cleanup_failed",
|
|
47044
|
-
error: `All removal fallbacks exhausted. deinit+remove: ${deinitError?.message || deinitError}; rmSync+prune: ${rmError?.message || rmError}`,
|
|
47045
|
-
recoveryHint: "Manually remove the worktree directory and run git worktree prune from the source repo."
|
|
47046
|
-
};
|
|
47213
|
+
} catch {
|
|
47047
47214
|
}
|
|
47215
|
+
return {
|
|
47216
|
+
success: true,
|
|
47217
|
+
removedPath: workspace,
|
|
47218
|
+
repoRoot,
|
|
47219
|
+
fallback: "fs_rm_worktree_prune",
|
|
47220
|
+
forced: true,
|
|
47221
|
+
reason: "working_trees_containing_submodules",
|
|
47222
|
+
convergence: forceFallbackConvergence,
|
|
47223
|
+
...rm.residue ? {
|
|
47224
|
+
residue: true,
|
|
47225
|
+
residueWarning: `Worktree was de-registered from git but the directory could not be fully removed (leftover residue at '${workspace}'): ${rm.error || "unknown error"}; deinit+remove first failed with: ${deinitError?.message || deinitError}. The node will be dropped from the mesh; remove the directory manually if needed.`,
|
|
47226
|
+
residueError: rm.error
|
|
47227
|
+
} : {}
|
|
47228
|
+
};
|
|
47048
47229
|
}
|
|
47049
47230
|
}
|
|
47050
47231
|
return {
|
|
@@ -50443,7 +50624,14 @@ ${hintLines.join("\n")}` : "",
|
|
|
50443
50624
|
} catch {
|
|
50444
50625
|
}
|
|
50445
50626
|
}
|
|
50446
|
-
|
|
50627
|
+
const residueWarning = worktreeCleanup?.residue === true && typeof worktreeCleanup?.residueWarning === "string" ? worktreeCleanup.residueWarning : void 0;
|
|
50628
|
+
return {
|
|
50629
|
+
success: true,
|
|
50630
|
+
removed,
|
|
50631
|
+
...residueWarning ? { residueWarning } : {},
|
|
50632
|
+
...sessionCleanup ? { sessionCleanup } : {},
|
|
50633
|
+
...worktreeCleanup ? { worktreeCleanup } : {}
|
|
50634
|
+
};
|
|
50447
50635
|
} catch (e) {
|
|
50448
50636
|
return { success: false, error: e.message };
|
|
50449
50637
|
}
|
|
@@ -60443,6 +60631,7 @@ export {
|
|
|
60443
60631
|
createNativeHistoryDispatcher,
|
|
60444
60632
|
createSessionDelivery,
|
|
60445
60633
|
createWorktree,
|
|
60634
|
+
daemonIdsEquivalent,
|
|
60446
60635
|
deleteDirectDispatchesByTaskId,
|
|
60447
60636
|
deleteMesh,
|
|
60448
60637
|
deriveMeshReviewInboxItems,
|
|
@@ -60456,6 +60645,7 @@ export {
|
|
|
60456
60645
|
ensureSessionHostReady,
|
|
60457
60646
|
evaluateFsm,
|
|
60458
60647
|
execNpmCommandSync,
|
|
60648
|
+
expandDaemonIdForms,
|
|
60459
60649
|
fastForwardMeshNode,
|
|
60460
60650
|
filterActivityChatMessages,
|
|
60461
60651
|
filterChatMessagesByVisibility,
|
|
@@ -60546,6 +60736,7 @@ export {
|
|
|
60546
60736
|
loadMeshWorktreeBootstrapConfig,
|
|
60547
60737
|
loadState,
|
|
60548
60738
|
logCommand,
|
|
60739
|
+
machineCoreFromDaemonId,
|
|
60549
60740
|
markSessionDeliveriesTerminal,
|
|
60550
60741
|
markSetupComplete,
|
|
60551
60742
|
markStaleDirectDispatches,
|