@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.js
CHANGED
|
@@ -316,10 +316,10 @@ function readInjected(value) {
|
|
|
316
316
|
}
|
|
317
317
|
function getDaemonBuildInfo() {
|
|
318
318
|
if (cached) return cached;
|
|
319
|
-
const commit = readInjected(true ? "
|
|
320
|
-
const commitShort = readInjected(true ? "
|
|
321
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
322
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
319
|
+
const commit = readInjected(true ? "5d100a177f412ae29a58048f0a211c3928b06910" : void 0) ?? "unknown";
|
|
320
|
+
const commitShort = readInjected(true ? "5d100a17" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
321
|
+
const version = readInjected(true ? "0.9.82-rc.354" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
322
|
+
const builtAt = readInjected(true ? "2026-06-22T11:32:05.389Z" : void 0);
|
|
323
323
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
324
324
|
return cached;
|
|
325
325
|
}
|
|
@@ -1070,6 +1070,9 @@ __export(git_diff_exports, {
|
|
|
1070
1070
|
getGitDiffSummary: () => getGitDiffSummary,
|
|
1071
1071
|
getGitFileDiff: () => getGitFileDiff
|
|
1072
1072
|
});
|
|
1073
|
+
function withCollectionTimeout(options) {
|
|
1074
|
+
return options.timeoutMs === void 0 ? { ...options, timeoutMs: GIT_STATUS_TIMEOUT_MS } : options;
|
|
1075
|
+
}
|
|
1073
1076
|
function validateBaseRef(ref) {
|
|
1074
1077
|
const trimmed = ref.trim();
|
|
1075
1078
|
if (!trimmed || trimmed.startsWith("-") || trimmed.includes("..") || !/^[A-Za-z0-9][A-Za-z0-9._/@-]*$/.test(trimmed)) {
|
|
@@ -1079,14 +1082,15 @@ function validateBaseRef(ref) {
|
|
|
1079
1082
|
}
|
|
1080
1083
|
async function getGitDiffSummary(workspace, options = {}) {
|
|
1081
1084
|
const lastCheckedAt = Date.now();
|
|
1085
|
+
const effectiveOptions = withCollectionTimeout(options);
|
|
1082
1086
|
try {
|
|
1083
|
-
const repo = await resolveGitRepository(workspace,
|
|
1087
|
+
const repo = await resolveGitRepository(workspace, effectiveOptions);
|
|
1084
1088
|
const repoRoot = repo.repoRoot;
|
|
1085
1089
|
if (options.baseRef) {
|
|
1086
1090
|
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
1087
1091
|
const [nameStatus, numstat] = await Promise.all([
|
|
1088
|
-
runGit(repo, ["diff", "--no-ext-diff", "--name-status", range, "--"], { ...
|
|
1089
|
-
runGit(repo, ["diff", "--no-ext-diff", "--numstat", range, "--"], { ...
|
|
1092
|
+
runGit(repo, ["diff", "--no-ext-diff", "--name-status", range, "--"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1093
|
+
runGit(repo, ["diff", "--no-ext-diff", "--numstat", range, "--"], { ...effectiveOptions, cwd: repoRoot })
|
|
1090
1094
|
]);
|
|
1091
1095
|
const outputBytes2 = byteLength(nameStatus.stdout + numstat.stdout);
|
|
1092
1096
|
const changes2 = combineDiffEntries(nameStatus.stdout, numstat.stdout, false);
|
|
@@ -1105,11 +1109,11 @@ async function getGitDiffSummary(workspace, options = {}) {
|
|
|
1105
1109
|
};
|
|
1106
1110
|
}
|
|
1107
1111
|
const [unstagedNameStatus, unstagedNumstat, stagedNameStatus, stagedNumstat, untracked] = await Promise.all([
|
|
1108
|
-
runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...
|
|
1109
|
-
runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...
|
|
1110
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...
|
|
1111
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...
|
|
1112
|
-
runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...
|
|
1112
|
+
runGit(repo, ["diff", "--no-ext-diff", "--name-status"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1113
|
+
runGit(repo, ["diff", "--no-ext-diff", "--numstat"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1114
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--name-status"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1115
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--numstat"], { ...effectiveOptions, cwd: repoRoot }),
|
|
1116
|
+
runGit(repo, ["ls-files", "--others", "--exclude-standard"], { ...effectiveOptions, cwd: repoRoot })
|
|
1113
1117
|
]);
|
|
1114
1118
|
const outputBytes = byteLength(
|
|
1115
1119
|
unstagedNameStatus.stdout + unstagedNumstat.stdout + stagedNameStatus.stdout + stagedNumstat.stdout + untracked.stdout
|
|
@@ -1151,13 +1155,14 @@ async function getGitDiffSummary(workspace, options = {}) {
|
|
|
1151
1155
|
}
|
|
1152
1156
|
async function getGitFileDiff(workspace, filePath, options = {}) {
|
|
1153
1157
|
const lastCheckedAt = Date.now();
|
|
1154
|
-
const
|
|
1158
|
+
const effectiveOptions = withCollectionTimeout(options);
|
|
1159
|
+
const repo = await resolveGitRepository(workspace, effectiveOptions);
|
|
1155
1160
|
const repoRoot = repo.repoRoot;
|
|
1156
1161
|
const selected = await resolveRepoFilePath(repoRoot, filePath);
|
|
1157
1162
|
const maxBytes = normalizePositiveInteger(options.maxBytes, DEFAULT_MAX_BYTES);
|
|
1158
1163
|
if (options.baseRef) {
|
|
1159
1164
|
const range = `${validateBaseRef(options.baseRef)}...HEAD`;
|
|
1160
|
-
const result = await runGit(repo, ["diff", "--no-ext-diff", range, "--", selected.relativePath], { ...
|
|
1165
|
+
const result = await runGit(repo, ["diff", "--no-ext-diff", range, "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot });
|
|
1161
1166
|
const bounded2 = truncateText(result.stdout, maxBytes);
|
|
1162
1167
|
return {
|
|
1163
1168
|
workspace: repo.workspace,
|
|
@@ -1170,13 +1175,13 @@ async function getGitFileDiff(workspace, filePath, options = {}) {
|
|
|
1170
1175
|
};
|
|
1171
1176
|
}
|
|
1172
1177
|
const [unstaged, staged] = await Promise.all([
|
|
1173
|
-
runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...
|
|
1174
|
-
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...
|
|
1178
|
+
runGit(repo, ["diff", "--no-ext-diff", "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot }),
|
|
1179
|
+
runGit(repo, ["diff", "--cached", "--no-ext-diff", "--", selected.relativePath], { ...effectiveOptions, cwd: repoRoot })
|
|
1175
1180
|
]);
|
|
1176
1181
|
let diff = [unstaged.stdout, staged.stdout].filter((part) => part.length > 0).join("\n");
|
|
1177
1182
|
if (!diff) {
|
|
1178
1183
|
const untracked = await runGit(repo, ["ls-files", "--others", "--exclude-standard", "--", selected.relativePath], {
|
|
1179
|
-
...
|
|
1184
|
+
...effectiveOptions,
|
|
1180
1185
|
cwd: repoRoot
|
|
1181
1186
|
});
|
|
1182
1187
|
const untrackedFiles = untracked.stdout.split("\n").filter(Boolean);
|
|
@@ -2708,6 +2713,257 @@ var init_mesh_config = __esm({
|
|
|
2708
2713
|
}
|
|
2709
2714
|
});
|
|
2710
2715
|
|
|
2716
|
+
// ../mesh-shared/dist/index.mjs
|
|
2717
|
+
function readRecord(value) {
|
|
2718
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2719
|
+
}
|
|
2720
|
+
function readString3(...values) {
|
|
2721
|
+
for (const value of values) {
|
|
2722
|
+
if (typeof value !== "string") continue;
|
|
2723
|
+
const trimmed = value.trim();
|
|
2724
|
+
if (trimmed) return trimmed;
|
|
2725
|
+
}
|
|
2726
|
+
return void 0;
|
|
2727
|
+
}
|
|
2728
|
+
function readNumber(...values) {
|
|
2729
|
+
for (const value of values) {
|
|
2730
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2731
|
+
}
|
|
2732
|
+
return void 0;
|
|
2733
|
+
}
|
|
2734
|
+
function readBoolean(...values) {
|
|
2735
|
+
for (const value of values) {
|
|
2736
|
+
if (typeof value === "boolean") return value;
|
|
2737
|
+
}
|
|
2738
|
+
return void 0;
|
|
2739
|
+
}
|
|
2740
|
+
function joinRepoPath(root, relativePath) {
|
|
2741
|
+
const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
|
|
2742
|
+
const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
|
|
2743
|
+
if (!normalizedPath) return void 0;
|
|
2744
|
+
if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
|
|
2745
|
+
if (!normalizedRoot) return void 0;
|
|
2746
|
+
return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
|
|
2747
|
+
}
|
|
2748
|
+
function scoreGitUpstreamFreshness(status) {
|
|
2749
|
+
switch (status) {
|
|
2750
|
+
case "fresh":
|
|
2751
|
+
return 30;
|
|
2752
|
+
case "no_upstream":
|
|
2753
|
+
return 4;
|
|
2754
|
+
case "unchecked":
|
|
2755
|
+
case void 0:
|
|
2756
|
+
return 0;
|
|
2757
|
+
case "stale":
|
|
2758
|
+
return -10;
|
|
2759
|
+
case "unavailable":
|
|
2760
|
+
return -15;
|
|
2761
|
+
default:
|
|
2762
|
+
return 0;
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
function readGitSubmodules(value, parentRepoRoot) {
|
|
2766
|
+
if (!Array.isArray(value)) return void 0;
|
|
2767
|
+
const submodules = value.map((entry) => {
|
|
2768
|
+
const submodule = readRecord(entry);
|
|
2769
|
+
const path42 = readString3(submodule.path);
|
|
2770
|
+
const commit = readString3(submodule.commit);
|
|
2771
|
+
const repoPath = readString3(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path42);
|
|
2772
|
+
if (!path42 || !commit) return null;
|
|
2773
|
+
const result = {
|
|
2774
|
+
path: path42,
|
|
2775
|
+
commit,
|
|
2776
|
+
dirty: readBoolean(submodule.dirty) ?? false,
|
|
2777
|
+
outOfSync: readBoolean(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
2778
|
+
lastCheckedAt: readNumber(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now()
|
|
2779
|
+
};
|
|
2780
|
+
if (repoPath) result.repoPath = repoPath;
|
|
2781
|
+
const error = readString3(submodule.error);
|
|
2782
|
+
if (error) result.error = error;
|
|
2783
|
+
return result;
|
|
2784
|
+
}).filter((entry) => entry !== null);
|
|
2785
|
+
return submodules.length > 0 ? submodules : void 0;
|
|
2786
|
+
}
|
|
2787
|
+
function hasGitStatusEvidence(status) {
|
|
2788
|
+
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(
|
|
2789
|
+
status.ahead,
|
|
2790
|
+
status.behind,
|
|
2791
|
+
status.staged,
|
|
2792
|
+
status.modified,
|
|
2793
|
+
status.untracked,
|
|
2794
|
+
status.deleted,
|
|
2795
|
+
status.renamed,
|
|
2796
|
+
status.lastCheckedAt,
|
|
2797
|
+
status.last_checked_at
|
|
2798
|
+
) !== void 0 || Array.isArray(status.submodules) && status.submodules.length > 0;
|
|
2799
|
+
}
|
|
2800
|
+
function normalizeGitStatus(status, node, options) {
|
|
2801
|
+
const explicitIsGitRepo = readBoolean(status.isGitRepo);
|
|
2802
|
+
if (!Object.keys(status).length || !hasGitStatusEvidence(status)) return void 0;
|
|
2803
|
+
const isGitRepo = explicitIsGitRepo ?? true;
|
|
2804
|
+
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((entry) => typeof entry === "string") : [];
|
|
2805
|
+
const conflictCount = readNumber(status.conflicts) ?? conflictFiles.length;
|
|
2806
|
+
const hasConflicts = readBoolean(status.hasConflicts) ?? conflictCount > 0;
|
|
2807
|
+
const repoRoot = readString3(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
|
|
2808
|
+
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
2809
|
+
const upstreamStatus = readString3(status.upstreamStatus, status.upstream_status);
|
|
2810
|
+
const upstreamFetchedAt = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
|
|
2811
|
+
const upstreamFetchError = readString3(status.upstreamFetchError, status.upstream_fetch_error);
|
|
2812
|
+
const error = readString3(status.error);
|
|
2813
|
+
const staged = readNumber(status.staged) ?? 0;
|
|
2814
|
+
const modified = readNumber(status.modified) ?? 0;
|
|
2815
|
+
const untracked = readNumber(status.untracked) ?? 0;
|
|
2816
|
+
const deleted = readNumber(status.deleted) ?? 0;
|
|
2817
|
+
const renamed = readNumber(status.renamed) ?? 0;
|
|
2818
|
+
return {
|
|
2819
|
+
workspace: readString3(status.workspace, node.workspace) || "",
|
|
2820
|
+
repoRoot: repoRoot ?? null,
|
|
2821
|
+
isGitRepo,
|
|
2822
|
+
branch: readString3(status.branch) ?? null,
|
|
2823
|
+
headCommit: readString3(status.headCommit) ?? null,
|
|
2824
|
+
headMessage: readString3(status.headMessage) ?? null,
|
|
2825
|
+
upstream: readString3(status.upstream) ?? null,
|
|
2826
|
+
upstreamStatus: upstreamStatus ?? "unchecked",
|
|
2827
|
+
...upstreamFetchedAt !== void 0 ? { upstreamFetchedAt } : {},
|
|
2828
|
+
...upstreamFetchError ? { upstreamFetchError } : {},
|
|
2829
|
+
ahead: readNumber(status.ahead) ?? 0,
|
|
2830
|
+
behind: readNumber(status.behind) ?? 0,
|
|
2831
|
+
staged,
|
|
2832
|
+
modified,
|
|
2833
|
+
untracked,
|
|
2834
|
+
deleted,
|
|
2835
|
+
renamed,
|
|
2836
|
+
dirty: readBoolean(status.dirty, status.isDirty, status.is_dirty) ?? (staged + modified + untracked + deleted + renamed > 0 || hasConflicts),
|
|
2837
|
+
hasConflicts,
|
|
2838
|
+
conflictFiles,
|
|
2839
|
+
stashCount: readNumber(status.stashCount, status.stash_count) ?? 0,
|
|
2840
|
+
lastCheckedAt: options?.lastCheckedAt ?? readNumber(status.lastCheckedAt, status.last_checked_at) ?? Date.now(),
|
|
2841
|
+
...submodules ? { submodules } : {},
|
|
2842
|
+
...error ? { error } : {}
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2845
|
+
function scoreGitStatusCandidate(git) {
|
|
2846
|
+
if (!git) return Number.NEGATIVE_INFINITY;
|
|
2847
|
+
let score = 0;
|
|
2848
|
+
if (git.isGitRepo === true) score += 50;
|
|
2849
|
+
if (git.isGitRepo === false) score -= 10;
|
|
2850
|
+
if (git.branch) score += 20;
|
|
2851
|
+
if (git.headCommit) score += 20;
|
|
2852
|
+
if (git.upstream) score += 10;
|
|
2853
|
+
score += scoreGitUpstreamFreshness(git.upstreamStatus);
|
|
2854
|
+
if (typeof git.ahead === "number") score += 2;
|
|
2855
|
+
if (typeof git.behind === "number") score += 2;
|
|
2856
|
+
if (Array.isArray(git.submodules) && git.submodules.length > 0) score += 4 + git.submodules.length;
|
|
2857
|
+
if (git.error) score -= 20;
|
|
2858
|
+
return score;
|
|
2859
|
+
}
|
|
2860
|
+
function pickBestTransitGitStatus(node, options) {
|
|
2861
|
+
const rawGit = readRecord(node.lastGit ?? node.last_git);
|
|
2862
|
+
const gitResult = readRecord(rawGit.result);
|
|
2863
|
+
const directStatus = readRecord(rawGit.status);
|
|
2864
|
+
const nestedStatus = readRecord(gitResult.status);
|
|
2865
|
+
const rawProbe = readRecord(node.lastProbe ?? node.last_probe);
|
|
2866
|
+
const probeGit = readRecord(rawProbe.git);
|
|
2867
|
+
const probeGitResult = readRecord(probeGit.result);
|
|
2868
|
+
const probeDirectStatus = readRecord(probeGit.status);
|
|
2869
|
+
const probeNestedStatus = readRecord(probeGitResult.status);
|
|
2870
|
+
const lastCheckedAt = options?.lastCheckedAt;
|
|
2871
|
+
let best = null;
|
|
2872
|
+
for (const status of [directStatus, nestedStatus, probeDirectStatus, probeNestedStatus]) {
|
|
2873
|
+
const normalized = normalizeGitStatus(status, node, { lastCheckedAt: lastCheckedAt ?? Date.now() });
|
|
2874
|
+
if (!normalized) continue;
|
|
2875
|
+
const score = scoreGitStatusCandidate(normalized);
|
|
2876
|
+
if (!best || score > best.score) best = { git: normalized, score };
|
|
2877
|
+
}
|
|
2878
|
+
return best?.git;
|
|
2879
|
+
}
|
|
2880
|
+
function normalizeMeshNodeId(node) {
|
|
2881
|
+
const record = node && typeof node === "object" ? node : {};
|
|
2882
|
+
return readString3(record.id, record.nodeId, record.node_id);
|
|
2883
|
+
}
|
|
2884
|
+
function meshNodeIdMatches(node, candidateId) {
|
|
2885
|
+
if (!candidateId) return false;
|
|
2886
|
+
const trimmed = candidateId.trim();
|
|
2887
|
+
if (!trimmed) return false;
|
|
2888
|
+
return normalizeMeshNodeId(node) === trimmed;
|
|
2889
|
+
}
|
|
2890
|
+
function machineCoreFromDaemonId(id) {
|
|
2891
|
+
const trimmed = readString3(id);
|
|
2892
|
+
if (!trimmed) return void 0;
|
|
2893
|
+
for (const prefix of DAEMON_ID_PREFIXES) {
|
|
2894
|
+
if (trimmed.startsWith(prefix)) {
|
|
2895
|
+
const core = trimmed.slice(prefix.length).trim();
|
|
2896
|
+
return core || void 0;
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
return trimmed;
|
|
2900
|
+
}
|
|
2901
|
+
function daemonIdsEquivalent(a, b) {
|
|
2902
|
+
const coreA = machineCoreFromDaemonId(a);
|
|
2903
|
+
const coreB = machineCoreFromDaemonId(b);
|
|
2904
|
+
if (!coreA || !coreB) return false;
|
|
2905
|
+
return coreA === coreB;
|
|
2906
|
+
}
|
|
2907
|
+
function expandDaemonIdForms(ids) {
|
|
2908
|
+
const list = Array.isArray(ids) ? ids : ids != null ? [ids] : [];
|
|
2909
|
+
const out = [];
|
|
2910
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2911
|
+
const add = (value) => {
|
|
2912
|
+
if (!value || seen.has(value)) return;
|
|
2913
|
+
seen.add(value);
|
|
2914
|
+
out.push(value);
|
|
2915
|
+
};
|
|
2916
|
+
for (const raw of list) add(readString3(raw));
|
|
2917
|
+
for (const raw of list) {
|
|
2918
|
+
const core = machineCoreFromDaemonId(readString3(raw));
|
|
2919
|
+
if (!core || !core.startsWith("mach_")) continue;
|
|
2920
|
+
add(core);
|
|
2921
|
+
for (const prefix of DAEMON_ID_PREFIXES) add(`${prefix}${core}`);
|
|
2922
|
+
}
|
|
2923
|
+
return out;
|
|
2924
|
+
}
|
|
2925
|
+
function summarizeGitShape(status) {
|
|
2926
|
+
const record = readRecord(status);
|
|
2927
|
+
if (!Object.keys(record).length) return null;
|
|
2928
|
+
const submodules = Array.isArray(record.submodules) ? record.submodules.map((entry) => {
|
|
2929
|
+
const sub = readRecord(entry);
|
|
2930
|
+
return {
|
|
2931
|
+
path: readString3(sub.path) ?? null,
|
|
2932
|
+
commit: readString3(sub.commit)?.slice(0, 12) ?? null,
|
|
2933
|
+
dirty: readBoolean(sub.dirty) ?? false,
|
|
2934
|
+
outOfSync: readBoolean(sub.outOfSync, sub.out_of_sync) ?? false
|
|
2935
|
+
};
|
|
2936
|
+
}) : [];
|
|
2937
|
+
return {
|
|
2938
|
+
isGitRepo: readBoolean(record.isGitRepo),
|
|
2939
|
+
workspace: readString3(record.workspace) ?? null,
|
|
2940
|
+
repoRoot: readString3(record.repoRoot, record.repo_root) ?? null,
|
|
2941
|
+
branch: readString3(record.branch) ?? null,
|
|
2942
|
+
upstream: readString3(record.upstream) ?? null,
|
|
2943
|
+
upstreamStatus: readString3(record.upstreamStatus, record.upstream_status) ?? null,
|
|
2944
|
+
headCommit: readString3(record.headCommit, record.head_commit)?.slice(0, 12) ?? null,
|
|
2945
|
+
ahead: readNumber(record.ahead) ?? null,
|
|
2946
|
+
behind: readNumber(record.behind) ?? null,
|
|
2947
|
+
dirtyCounts: {
|
|
2948
|
+
staged: readNumber(record.staged) ?? 0,
|
|
2949
|
+
modified: readNumber(record.modified) ?? 0,
|
|
2950
|
+
untracked: readNumber(record.untracked) ?? 0,
|
|
2951
|
+
deleted: readNumber(record.deleted) ?? 0,
|
|
2952
|
+
renamed: readNumber(record.renamed) ?? 0
|
|
2953
|
+
},
|
|
2954
|
+
lastCheckedAt: readNumber(record.lastCheckedAt, record.last_checked_at) ?? null,
|
|
2955
|
+
submoduleCount: submodules.length,
|
|
2956
|
+
submodules
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2959
|
+
var DAEMON_ID_PREFIXES;
|
|
2960
|
+
var init_dist = __esm({
|
|
2961
|
+
"../mesh-shared/dist/index.mjs"() {
|
|
2962
|
+
"use strict";
|
|
2963
|
+
DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
|
|
2964
|
+
}
|
|
2965
|
+
});
|
|
2966
|
+
|
|
2711
2967
|
// src/mesh/coordinator-prompt.ts
|
|
2712
2968
|
var coordinator_prompt_exports = {};
|
|
2713
2969
|
__export(coordinator_prompt_exports, {
|
|
@@ -6316,10 +6572,10 @@ var init_mesh_missions = __esm({
|
|
|
6316
6572
|
});
|
|
6317
6573
|
|
|
6318
6574
|
// src/mesh/mesh-refine-status.ts
|
|
6319
|
-
function
|
|
6575
|
+
function readString4(value) {
|
|
6320
6576
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
6321
6577
|
}
|
|
6322
|
-
function
|
|
6578
|
+
function readRecord2(value) {
|
|
6323
6579
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
6324
6580
|
}
|
|
6325
6581
|
function eventStatus(event, fallback) {
|
|
@@ -6342,7 +6598,7 @@ function instructionForStatus(status) {
|
|
|
6342
6598
|
return "Refine job failed; inspect result/finalBranchConvergenceState in mesh_task_history, fix the blocker, then rerun mesh_refine_node when ready.";
|
|
6343
6599
|
}
|
|
6344
6600
|
function mergeJob(jobs, patch) {
|
|
6345
|
-
const jobId =
|
|
6601
|
+
const jobId = readString4(patch.jobId);
|
|
6346
6602
|
if (!jobId) return;
|
|
6347
6603
|
const previous = jobs.get(jobId);
|
|
6348
6604
|
const status = patch.status || previous?.status || "running";
|
|
@@ -6360,54 +6616,54 @@ function mergeJob(jobs, patch) {
|
|
|
6360
6616
|
function buildMeshAsyncRefineJobs(args) {
|
|
6361
6617
|
const jobs = /* @__PURE__ */ new Map();
|
|
6362
6618
|
for (const entry of args.ledgerEntries || []) {
|
|
6363
|
-
const payload =
|
|
6619
|
+
const payload = readRecord2(entry.payload);
|
|
6364
6620
|
if (payload?.source !== "refine_mesh_node_async_job") continue;
|
|
6365
|
-
const refineJob =
|
|
6366
|
-
const result =
|
|
6367
|
-
const finalState =
|
|
6368
|
-
const jobId =
|
|
6621
|
+
const refineJob = readRecord2(payload.refineJob);
|
|
6622
|
+
const result = readRecord2(payload.result);
|
|
6623
|
+
const finalState = readRecord2(payload.finalBranchConvergenceState) || readRecord2(result?.finalBranchConvergenceState);
|
|
6624
|
+
const jobId = readString4(refineJob?.jobId);
|
|
6369
6625
|
if (!jobId) continue;
|
|
6370
|
-
const status = ledgerStatus(entry.kind,
|
|
6626
|
+
const status = ledgerStatus(entry.kind, readString4(refineJob?.status));
|
|
6371
6627
|
mergeJob(jobs, {
|
|
6372
6628
|
jobId,
|
|
6373
|
-
interactionId:
|
|
6629
|
+
interactionId: readString4(refineJob?.interactionId),
|
|
6374
6630
|
status,
|
|
6375
|
-
meshId:
|
|
6376
|
-
nodeId:
|
|
6377
|
-
targetNodeId:
|
|
6378
|
-
targetDaemonId:
|
|
6379
|
-
workspace:
|
|
6380
|
-
branch:
|
|
6381
|
-
into:
|
|
6382
|
-
startedAt:
|
|
6383
|
-
completedAt:
|
|
6384
|
-
retryOfJobId:
|
|
6631
|
+
meshId: readString4(refineJob?.meshId) || args.meshId,
|
|
6632
|
+
nodeId: readString4(refineJob?.nodeId) || entry.nodeId,
|
|
6633
|
+
targetNodeId: readString4(refineJob?.nodeId) || entry.nodeId,
|
|
6634
|
+
targetDaemonId: readString4(refineJob?.targetDaemonId),
|
|
6635
|
+
workspace: readString4(refineJob?.workspace),
|
|
6636
|
+
branch: readString4(result?.branch) || readString4(finalState?.branch),
|
|
6637
|
+
into: readString4(result?.into) || readString4(finalState?.baseBranch),
|
|
6638
|
+
startedAt: readString4(refineJob?.startedAt),
|
|
6639
|
+
completedAt: readString4(refineJob?.completedAt),
|
|
6640
|
+
retryOfJobId: readString4(refineJob?.retryOfJobId) || readString4(payload.retryOfJobId),
|
|
6385
6641
|
lastLedgerKind: entry.kind,
|
|
6386
6642
|
lastUpdatedAt: entry.timestamp
|
|
6387
6643
|
});
|
|
6388
6644
|
}
|
|
6389
6645
|
for (const event of args.pendingEvents || []) {
|
|
6390
|
-
const metadata =
|
|
6646
|
+
const metadata = readRecord2(event.metadataEvent);
|
|
6391
6647
|
if (metadata?.source !== "refine_mesh_node_async_job") continue;
|
|
6392
|
-
const result =
|
|
6393
|
-
const finalState =
|
|
6394
|
-
const jobId =
|
|
6648
|
+
const result = readRecord2(metadata.result);
|
|
6649
|
+
const finalState = readRecord2(result?.finalBranchConvergenceState);
|
|
6650
|
+
const jobId = readString4(metadata.jobId);
|
|
6395
6651
|
if (!jobId) continue;
|
|
6396
|
-
const status = eventStatus(event.event,
|
|
6652
|
+
const status = eventStatus(event.event, readString4(metadata.status));
|
|
6397
6653
|
mergeJob(jobs, {
|
|
6398
6654
|
jobId,
|
|
6399
|
-
interactionId:
|
|
6655
|
+
interactionId: readString4(metadata.interactionId),
|
|
6400
6656
|
...status ? { status } : {},
|
|
6401
|
-
meshId:
|
|
6402
|
-
nodeId:
|
|
6403
|
-
targetNodeId:
|
|
6404
|
-
targetDaemonId:
|
|
6405
|
-
workspace:
|
|
6406
|
-
branch:
|
|
6407
|
-
into:
|
|
6408
|
-
startedAt:
|
|
6409
|
-
completedAt:
|
|
6410
|
-
retryOfJobId:
|
|
6657
|
+
meshId: readString4(metadata.meshId) || event.meshId || args.meshId,
|
|
6658
|
+
nodeId: readString4(metadata.nodeId) || event.nodeId,
|
|
6659
|
+
targetNodeId: readString4(metadata.nodeId) || event.nodeId,
|
|
6660
|
+
targetDaemonId: readString4(metadata.targetDaemonId),
|
|
6661
|
+
workspace: readString4(metadata.workspace) || event.workspace,
|
|
6662
|
+
branch: readString4(result?.branch) || readString4(finalState?.branch),
|
|
6663
|
+
into: readString4(result?.into) || readString4(finalState?.baseBranch),
|
|
6664
|
+
startedAt: readString4(metadata.startedAt),
|
|
6665
|
+
completedAt: readString4(metadata.completedAt),
|
|
6666
|
+
retryOfJobId: readString4(metadata.retryOfJobId),
|
|
6411
6667
|
lastEvent: event.event,
|
|
6412
6668
|
lastUpdatedAt: new Date(event.queuedAt).toISOString()
|
|
6413
6669
|
});
|
|
@@ -6468,10 +6724,10 @@ var mesh_review_inbox_exports = {};
|
|
|
6468
6724
|
__export(mesh_review_inbox_exports, {
|
|
6469
6725
|
deriveMeshReviewInboxItems: () => deriveMeshReviewInboxItems
|
|
6470
6726
|
});
|
|
6471
|
-
function
|
|
6727
|
+
function readString5(value) {
|
|
6472
6728
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
6473
6729
|
}
|
|
6474
|
-
function
|
|
6730
|
+
function readRecord3(value) {
|
|
6475
6731
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
6476
6732
|
}
|
|
6477
6733
|
function readStringArray3(value, max) {
|
|
@@ -6481,20 +6737,20 @@ function readStringArray3(value, max) {
|
|
|
6481
6737
|
}
|
|
6482
6738
|
function isLocalNodeStatus(node) {
|
|
6483
6739
|
if (node.isLocalWorktree === true) return true;
|
|
6484
|
-
const connection =
|
|
6485
|
-
return
|
|
6740
|
+
const connection = readRecord3(node.connection);
|
|
6741
|
+
return readString5(connection?.state) === "self";
|
|
6486
6742
|
}
|
|
6487
6743
|
function readNodeConvergence(node) {
|
|
6488
|
-
const convergence =
|
|
6489
|
-
const status =
|
|
6744
|
+
const convergence = readRecord3(node.branchConvergence);
|
|
6745
|
+
const status = readString5(convergence?.status);
|
|
6490
6746
|
if (!convergence || !status) return null;
|
|
6491
6747
|
return {
|
|
6492
6748
|
status,
|
|
6493
|
-
reason:
|
|
6494
|
-
nextStep:
|
|
6749
|
+
reason: readString5(convergence.reason),
|
|
6750
|
+
nextStep: readString5(convergence.nextStep),
|
|
6495
6751
|
needsConvergence: convergence.needsConvergence === true,
|
|
6496
|
-
branch:
|
|
6497
|
-
defaultBranch:
|
|
6752
|
+
branch: readString5(convergence.branch),
|
|
6753
|
+
defaultBranch: readString5(convergence.defaultBranch)
|
|
6498
6754
|
};
|
|
6499
6755
|
}
|
|
6500
6756
|
function isMergeCandidate(convergence) {
|
|
@@ -6502,15 +6758,15 @@ function isMergeCandidate(convergence) {
|
|
|
6502
6758
|
return convergence.status === "cleanup_candidate" && convergence.reason === "clean_non_default_worktree_branch";
|
|
6503
6759
|
}
|
|
6504
6760
|
function readWorkerArtifact(value) {
|
|
6505
|
-
const worker =
|
|
6761
|
+
const worker = readRecord3(value);
|
|
6506
6762
|
if (!worker) return null;
|
|
6507
6763
|
const changed = readStringArray3(worker.changedFiles, MAX_CHANGED_FILES);
|
|
6508
6764
|
return {
|
|
6509
|
-
status:
|
|
6510
|
-
...
|
|
6765
|
+
status: readString5(worker.status) ?? "unknown",
|
|
6766
|
+
...readString5(worker.classification) ? { classification: readString5(worker.classification) } : {},
|
|
6511
6767
|
changedFiles: changed.values,
|
|
6512
6768
|
...changed.truncated ? { changedFilesTruncated: true } : {},
|
|
6513
|
-
validationResults: Array.isArray(worker.validationResults) ? worker.validationResults.map((item) =>
|
|
6769
|
+
validationResults: Array.isArray(worker.validationResults) ? worker.validationResults.map((item) => readRecord3(item)).filter((item) => item !== null) : [],
|
|
6514
6770
|
errors: readStringArray3(worker.errors, 20).values,
|
|
6515
6771
|
requiresUserAction: worker.requiresUserAction === true
|
|
6516
6772
|
};
|
|
@@ -6524,43 +6780,43 @@ function resolveNodeEvidence(nodeId, ledgerEntries) {
|
|
|
6524
6780
|
for (let i = ledgerEntries.length - 1; i >= 0; i--) {
|
|
6525
6781
|
const entry = ledgerEntries[i];
|
|
6526
6782
|
if (entry.nodeId !== nodeId || !isTerminalLedgerKind(entry.kind)) continue;
|
|
6527
|
-
const payload =
|
|
6783
|
+
const payload = readRecord3(entry.payload) ?? {};
|
|
6528
6784
|
if (!evidence.available) {
|
|
6529
6785
|
if (payload.source === "refine_mesh_node_async_job") {
|
|
6530
|
-
const result =
|
|
6531
|
-
const validationSummary =
|
|
6786
|
+
const result = readRecord3(payload.result);
|
|
6787
|
+
const validationSummary = readRecord3(result?.validationSummary);
|
|
6532
6788
|
evidence = {
|
|
6533
6789
|
available: true,
|
|
6534
6790
|
kind: entry.kind,
|
|
6535
6791
|
source: "refine_job",
|
|
6536
6792
|
timestamp: entry.timestamp,
|
|
6537
6793
|
...entry.sessionId ? { sessionId: entry.sessionId } : {},
|
|
6538
|
-
bootstrap:
|
|
6794
|
+
bootstrap: readRecord3(validationSummary?.bootstrap),
|
|
6539
6795
|
validation: validationSummary ? Object.fromEntries(Object.entries(validationSummary).filter(([key]) => key !== "bootstrap")) : null,
|
|
6540
|
-
checkpoint:
|
|
6796
|
+
checkpoint: readRecord3(result?.checkpoint),
|
|
6541
6797
|
worker: null,
|
|
6542
|
-
...
|
|
6543
|
-
...
|
|
6798
|
+
...readRecord3(payload.finalBranchConvergenceState) ?? readRecord3(result?.finalBranchConvergenceState) ? { finalBranchConvergenceState: readRecord3(payload.finalBranchConvergenceState) ?? readRecord3(result?.finalBranchConvergenceState) } : {},
|
|
6799
|
+
...readRecord3(payload.refineJob) ? { refineJob: readRecord3(payload.refineJob) } : {}
|
|
6544
6800
|
};
|
|
6545
6801
|
} else {
|
|
6546
|
-
const envelope =
|
|
6802
|
+
const envelope = readRecord3(payload.evidence);
|
|
6547
6803
|
evidence = {
|
|
6548
6804
|
available: true,
|
|
6549
6805
|
kind: entry.kind,
|
|
6550
6806
|
source: "task_completion",
|
|
6551
6807
|
timestamp: entry.timestamp,
|
|
6552
|
-
...
|
|
6808
|
+
...readString5(payload.taskId) ? { taskId: readString5(payload.taskId) } : {},
|
|
6553
6809
|
...entry.sessionId ? { sessionId: entry.sessionId } : {},
|
|
6554
6810
|
bootstrap: null,
|
|
6555
|
-
validation:
|
|
6556
|
-
checkpoint:
|
|
6811
|
+
validation: readRecord3(envelope?.validation),
|
|
6812
|
+
checkpoint: readRecord3(envelope?.checkpoint),
|
|
6557
6813
|
worker: readWorkerArtifact(envelope?.workerResult ?? payload.workerResult)
|
|
6558
6814
|
};
|
|
6559
6815
|
}
|
|
6560
6816
|
}
|
|
6561
6817
|
if (!transcriptHandle) {
|
|
6562
|
-
const envelope =
|
|
6563
|
-
transcriptHandle =
|
|
6818
|
+
const envelope = readRecord3(payload.evidence);
|
|
6819
|
+
transcriptHandle = readRecord3(envelope?.transcriptHandle);
|
|
6564
6820
|
}
|
|
6565
6821
|
if (evidence.available && transcriptHandle) break;
|
|
6566
6822
|
}
|
|
@@ -6570,11 +6826,11 @@ function hasBlockedReviewRefineResult(nodeId, ledgerEntries) {
|
|
|
6570
6826
|
for (let i = ledgerEntries.length - 1; i >= 0; i--) {
|
|
6571
6827
|
const entry = ledgerEntries[i];
|
|
6572
6828
|
if (entry.nodeId !== nodeId || !isTerminalLedgerKind(entry.kind)) continue;
|
|
6573
|
-
const payload =
|
|
6829
|
+
const payload = readRecord3(entry.payload) ?? {};
|
|
6574
6830
|
if (payload.source !== "refine_mesh_node_async_job") continue;
|
|
6575
|
-
const result =
|
|
6576
|
-
const finalState =
|
|
6577
|
-
return
|
|
6831
|
+
const result = readRecord3(payload.result);
|
|
6832
|
+
const finalState = readRecord3(payload.finalBranchConvergenceState) ?? readRecord3(result?.finalBranchConvergenceState);
|
|
6833
|
+
return readString5(finalState?.status) === "blocked_review" || readString5(result?.code) === "blocked_review";
|
|
6578
6834
|
}
|
|
6579
6835
|
return false;
|
|
6580
6836
|
}
|
|
@@ -6583,7 +6839,7 @@ function deriveMeshReviewInboxItems(args) {
|
|
|
6583
6839
|
const excludedRemoteNodeIds = [];
|
|
6584
6840
|
const refineJobs = buildMeshAsyncRefineJobs({ ledgerEntries: args.ledgerEntries });
|
|
6585
6841
|
for (const node of args.nodes) {
|
|
6586
|
-
const nodeId =
|
|
6842
|
+
const nodeId = readString5(node.nodeId) ?? readString5(node.id);
|
|
6587
6843
|
if (!nodeId) continue;
|
|
6588
6844
|
if (!isLocalNodeStatus(node)) {
|
|
6589
6845
|
excludedRemoteNodeIds.push(nodeId);
|
|
@@ -6605,8 +6861,8 @@ function deriveMeshReviewInboxItems(args) {
|
|
|
6605
6861
|
) ?? null;
|
|
6606
6862
|
items.push({
|
|
6607
6863
|
nodeId,
|
|
6608
|
-
workspace:
|
|
6609
|
-
branch: convergence.branch ??
|
|
6864
|
+
workspace: readString5(node.workspace),
|
|
6865
|
+
branch: convergence.branch ?? readString5(node.worktreeBranch),
|
|
6610
6866
|
defaultBranch: convergence.defaultBranch,
|
|
6611
6867
|
isLocalWorktree: node.isLocalWorktree === true,
|
|
6612
6868
|
reviewReason,
|
|
@@ -7817,251 +8073,6 @@ var init_mesh_fast_forward = __esm({
|
|
|
7817
8073
|
}
|
|
7818
8074
|
});
|
|
7819
8075
|
|
|
7820
|
-
// ../mesh-shared/dist/index.mjs
|
|
7821
|
-
function readRecord3(value) {
|
|
7822
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
7823
|
-
}
|
|
7824
|
-
function readString5(...values) {
|
|
7825
|
-
for (const value of values) {
|
|
7826
|
-
if (typeof value !== "string") continue;
|
|
7827
|
-
const trimmed = value.trim();
|
|
7828
|
-
if (trimmed) return trimmed;
|
|
7829
|
-
}
|
|
7830
|
-
return void 0;
|
|
7831
|
-
}
|
|
7832
|
-
function readNumber(...values) {
|
|
7833
|
-
for (const value of values) {
|
|
7834
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
7835
|
-
}
|
|
7836
|
-
return void 0;
|
|
7837
|
-
}
|
|
7838
|
-
function readBoolean(...values) {
|
|
7839
|
-
for (const value of values) {
|
|
7840
|
-
if (typeof value === "boolean") return value;
|
|
7841
|
-
}
|
|
7842
|
-
return void 0;
|
|
7843
|
-
}
|
|
7844
|
-
function joinRepoPath(root, relativePath) {
|
|
7845
|
-
const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
|
|
7846
|
-
const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
|
|
7847
|
-
if (!normalizedPath) return void 0;
|
|
7848
|
-
if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
|
|
7849
|
-
if (!normalizedRoot) return void 0;
|
|
7850
|
-
return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
|
|
7851
|
-
}
|
|
7852
|
-
function scoreGitUpstreamFreshness(status) {
|
|
7853
|
-
switch (status) {
|
|
7854
|
-
case "fresh":
|
|
7855
|
-
return 30;
|
|
7856
|
-
case "no_upstream":
|
|
7857
|
-
return 4;
|
|
7858
|
-
case "unchecked":
|
|
7859
|
-
case void 0:
|
|
7860
|
-
return 0;
|
|
7861
|
-
case "stale":
|
|
7862
|
-
return -10;
|
|
7863
|
-
case "unavailable":
|
|
7864
|
-
return -15;
|
|
7865
|
-
default:
|
|
7866
|
-
return 0;
|
|
7867
|
-
}
|
|
7868
|
-
}
|
|
7869
|
-
function readGitSubmodules(value, parentRepoRoot) {
|
|
7870
|
-
if (!Array.isArray(value)) return void 0;
|
|
7871
|
-
const submodules = value.map((entry) => {
|
|
7872
|
-
const submodule = readRecord3(entry);
|
|
7873
|
-
const path42 = readString5(submodule.path);
|
|
7874
|
-
const commit = readString5(submodule.commit);
|
|
7875
|
-
const repoPath = readString5(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path42);
|
|
7876
|
-
if (!path42 || !commit) return null;
|
|
7877
|
-
const result = {
|
|
7878
|
-
path: path42,
|
|
7879
|
-
commit,
|
|
7880
|
-
dirty: readBoolean(submodule.dirty) ?? false,
|
|
7881
|
-
outOfSync: readBoolean(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
7882
|
-
lastCheckedAt: readNumber(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now()
|
|
7883
|
-
};
|
|
7884
|
-
if (repoPath) result.repoPath = repoPath;
|
|
7885
|
-
const error = readString5(submodule.error);
|
|
7886
|
-
if (error) result.error = error;
|
|
7887
|
-
return result;
|
|
7888
|
-
}).filter((entry) => entry !== null);
|
|
7889
|
-
return submodules.length > 0 ? submodules : void 0;
|
|
7890
|
-
}
|
|
7891
|
-
function hasGitStatusEvidence(status) {
|
|
7892
|
-
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(
|
|
7893
|
-
status.ahead,
|
|
7894
|
-
status.behind,
|
|
7895
|
-
status.staged,
|
|
7896
|
-
status.modified,
|
|
7897
|
-
status.untracked,
|
|
7898
|
-
status.deleted,
|
|
7899
|
-
status.renamed,
|
|
7900
|
-
status.lastCheckedAt,
|
|
7901
|
-
status.last_checked_at
|
|
7902
|
-
) !== void 0 || Array.isArray(status.submodules) && status.submodules.length > 0;
|
|
7903
|
-
}
|
|
7904
|
-
function normalizeGitStatus(status, node, options) {
|
|
7905
|
-
const explicitIsGitRepo = readBoolean(status.isGitRepo);
|
|
7906
|
-
if (!Object.keys(status).length || !hasGitStatusEvidence(status)) return void 0;
|
|
7907
|
-
const isGitRepo = explicitIsGitRepo ?? true;
|
|
7908
|
-
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((entry) => typeof entry === "string") : [];
|
|
7909
|
-
const conflictCount = readNumber(status.conflicts) ?? conflictFiles.length;
|
|
7910
|
-
const hasConflicts = readBoolean(status.hasConflicts) ?? conflictCount > 0;
|
|
7911
|
-
const repoRoot = readString5(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
|
|
7912
|
-
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
7913
|
-
const upstreamStatus = readString5(status.upstreamStatus, status.upstream_status);
|
|
7914
|
-
const upstreamFetchedAt = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
|
|
7915
|
-
const upstreamFetchError = readString5(status.upstreamFetchError, status.upstream_fetch_error);
|
|
7916
|
-
const error = readString5(status.error);
|
|
7917
|
-
const staged = readNumber(status.staged) ?? 0;
|
|
7918
|
-
const modified = readNumber(status.modified) ?? 0;
|
|
7919
|
-
const untracked = readNumber(status.untracked) ?? 0;
|
|
7920
|
-
const deleted = readNumber(status.deleted) ?? 0;
|
|
7921
|
-
const renamed = readNumber(status.renamed) ?? 0;
|
|
7922
|
-
return {
|
|
7923
|
-
workspace: readString5(status.workspace, node.workspace) || "",
|
|
7924
|
-
repoRoot: repoRoot ?? null,
|
|
7925
|
-
isGitRepo,
|
|
7926
|
-
branch: readString5(status.branch) ?? null,
|
|
7927
|
-
headCommit: readString5(status.headCommit) ?? null,
|
|
7928
|
-
headMessage: readString5(status.headMessage) ?? null,
|
|
7929
|
-
upstream: readString5(status.upstream) ?? null,
|
|
7930
|
-
upstreamStatus: upstreamStatus ?? "unchecked",
|
|
7931
|
-
...upstreamFetchedAt !== void 0 ? { upstreamFetchedAt } : {},
|
|
7932
|
-
...upstreamFetchError ? { upstreamFetchError } : {},
|
|
7933
|
-
ahead: readNumber(status.ahead) ?? 0,
|
|
7934
|
-
behind: readNumber(status.behind) ?? 0,
|
|
7935
|
-
staged,
|
|
7936
|
-
modified,
|
|
7937
|
-
untracked,
|
|
7938
|
-
deleted,
|
|
7939
|
-
renamed,
|
|
7940
|
-
dirty: readBoolean(status.dirty, status.isDirty, status.is_dirty) ?? (staged + modified + untracked + deleted + renamed > 0 || hasConflicts),
|
|
7941
|
-
hasConflicts,
|
|
7942
|
-
conflictFiles,
|
|
7943
|
-
stashCount: readNumber(status.stashCount, status.stash_count) ?? 0,
|
|
7944
|
-
lastCheckedAt: options?.lastCheckedAt ?? readNumber(status.lastCheckedAt, status.last_checked_at) ?? Date.now(),
|
|
7945
|
-
...submodules ? { submodules } : {},
|
|
7946
|
-
...error ? { error } : {}
|
|
7947
|
-
};
|
|
7948
|
-
}
|
|
7949
|
-
function scoreGitStatusCandidate(git) {
|
|
7950
|
-
if (!git) return Number.NEGATIVE_INFINITY;
|
|
7951
|
-
let score = 0;
|
|
7952
|
-
if (git.isGitRepo === true) score += 50;
|
|
7953
|
-
if (git.isGitRepo === false) score -= 10;
|
|
7954
|
-
if (git.branch) score += 20;
|
|
7955
|
-
if (git.headCommit) score += 20;
|
|
7956
|
-
if (git.upstream) score += 10;
|
|
7957
|
-
score += scoreGitUpstreamFreshness(git.upstreamStatus);
|
|
7958
|
-
if (typeof git.ahead === "number") score += 2;
|
|
7959
|
-
if (typeof git.behind === "number") score += 2;
|
|
7960
|
-
if (Array.isArray(git.submodules) && git.submodules.length > 0) score += 4 + git.submodules.length;
|
|
7961
|
-
if (git.error) score -= 20;
|
|
7962
|
-
return score;
|
|
7963
|
-
}
|
|
7964
|
-
function pickBestTransitGitStatus(node, options) {
|
|
7965
|
-
const rawGit = readRecord3(node.lastGit ?? node.last_git);
|
|
7966
|
-
const gitResult = readRecord3(rawGit.result);
|
|
7967
|
-
const directStatus = readRecord3(rawGit.status);
|
|
7968
|
-
const nestedStatus = readRecord3(gitResult.status);
|
|
7969
|
-
const rawProbe = readRecord3(node.lastProbe ?? node.last_probe);
|
|
7970
|
-
const probeGit = readRecord3(rawProbe.git);
|
|
7971
|
-
const probeGitResult = readRecord3(probeGit.result);
|
|
7972
|
-
const probeDirectStatus = readRecord3(probeGit.status);
|
|
7973
|
-
const probeNestedStatus = readRecord3(probeGitResult.status);
|
|
7974
|
-
const lastCheckedAt = options?.lastCheckedAt;
|
|
7975
|
-
let best = null;
|
|
7976
|
-
for (const status of [directStatus, nestedStatus, probeDirectStatus, probeNestedStatus]) {
|
|
7977
|
-
const normalized = normalizeGitStatus(status, node, { lastCheckedAt: lastCheckedAt ?? Date.now() });
|
|
7978
|
-
if (!normalized) continue;
|
|
7979
|
-
const score = scoreGitStatusCandidate(normalized);
|
|
7980
|
-
if (!best || score > best.score) best = { git: normalized, score };
|
|
7981
|
-
}
|
|
7982
|
-
return best?.git;
|
|
7983
|
-
}
|
|
7984
|
-
function normalizeMeshNodeId(node) {
|
|
7985
|
-
const record = node && typeof node === "object" ? node : {};
|
|
7986
|
-
return readString5(record.id, record.nodeId, record.node_id);
|
|
7987
|
-
}
|
|
7988
|
-
function meshNodeIdMatches(node, candidateId) {
|
|
7989
|
-
if (!candidateId) return false;
|
|
7990
|
-
const trimmed = candidateId.trim();
|
|
7991
|
-
if (!trimmed) return false;
|
|
7992
|
-
return normalizeMeshNodeId(node) === trimmed;
|
|
7993
|
-
}
|
|
7994
|
-
function machineCoreFromDaemonId(id) {
|
|
7995
|
-
const trimmed = readString5(id);
|
|
7996
|
-
if (!trimmed) return void 0;
|
|
7997
|
-
for (const prefix of DAEMON_ID_PREFIXES) {
|
|
7998
|
-
if (trimmed.startsWith(prefix)) {
|
|
7999
|
-
const core = trimmed.slice(prefix.length).trim();
|
|
8000
|
-
return core || void 0;
|
|
8001
|
-
}
|
|
8002
|
-
}
|
|
8003
|
-
return trimmed;
|
|
8004
|
-
}
|
|
8005
|
-
function expandDaemonIdForms(ids) {
|
|
8006
|
-
const list = Array.isArray(ids) ? ids : ids != null ? [ids] : [];
|
|
8007
|
-
const out = [];
|
|
8008
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8009
|
-
const add = (value) => {
|
|
8010
|
-
if (!value || seen.has(value)) return;
|
|
8011
|
-
seen.add(value);
|
|
8012
|
-
out.push(value);
|
|
8013
|
-
};
|
|
8014
|
-
for (const raw of list) add(readString5(raw));
|
|
8015
|
-
for (const raw of list) {
|
|
8016
|
-
const core = machineCoreFromDaemonId(readString5(raw));
|
|
8017
|
-
if (!core || !core.startsWith("mach_")) continue;
|
|
8018
|
-
add(core);
|
|
8019
|
-
for (const prefix of DAEMON_ID_PREFIXES) add(`${prefix}${core}`);
|
|
8020
|
-
}
|
|
8021
|
-
return out;
|
|
8022
|
-
}
|
|
8023
|
-
function summarizeGitShape(status) {
|
|
8024
|
-
const record = readRecord3(status);
|
|
8025
|
-
if (!Object.keys(record).length) return null;
|
|
8026
|
-
const submodules = Array.isArray(record.submodules) ? record.submodules.map((entry) => {
|
|
8027
|
-
const sub = readRecord3(entry);
|
|
8028
|
-
return {
|
|
8029
|
-
path: readString5(sub.path) ?? null,
|
|
8030
|
-
commit: readString5(sub.commit)?.slice(0, 12) ?? null,
|
|
8031
|
-
dirty: readBoolean(sub.dirty) ?? false,
|
|
8032
|
-
outOfSync: readBoolean(sub.outOfSync, sub.out_of_sync) ?? false
|
|
8033
|
-
};
|
|
8034
|
-
}) : [];
|
|
8035
|
-
return {
|
|
8036
|
-
isGitRepo: readBoolean(record.isGitRepo),
|
|
8037
|
-
workspace: readString5(record.workspace) ?? null,
|
|
8038
|
-
repoRoot: readString5(record.repoRoot, record.repo_root) ?? null,
|
|
8039
|
-
branch: readString5(record.branch) ?? null,
|
|
8040
|
-
upstream: readString5(record.upstream) ?? null,
|
|
8041
|
-
upstreamStatus: readString5(record.upstreamStatus, record.upstream_status) ?? null,
|
|
8042
|
-
headCommit: readString5(record.headCommit, record.head_commit)?.slice(0, 12) ?? null,
|
|
8043
|
-
ahead: readNumber(record.ahead) ?? null,
|
|
8044
|
-
behind: readNumber(record.behind) ?? null,
|
|
8045
|
-
dirtyCounts: {
|
|
8046
|
-
staged: readNumber(record.staged) ?? 0,
|
|
8047
|
-
modified: readNumber(record.modified) ?? 0,
|
|
8048
|
-
untracked: readNumber(record.untracked) ?? 0,
|
|
8049
|
-
deleted: readNumber(record.deleted) ?? 0,
|
|
8050
|
-
renamed: readNumber(record.renamed) ?? 0
|
|
8051
|
-
},
|
|
8052
|
-
lastCheckedAt: readNumber(record.lastCheckedAt, record.last_checked_at) ?? null,
|
|
8053
|
-
submoduleCount: submodules.length,
|
|
8054
|
-
submodules
|
|
8055
|
-
};
|
|
8056
|
-
}
|
|
8057
|
-
var DAEMON_ID_PREFIXES;
|
|
8058
|
-
var init_dist = __esm({
|
|
8059
|
-
"../mesh-shared/dist/index.mjs"() {
|
|
8060
|
-
"use strict";
|
|
8061
|
-
DAEMON_ID_PREFIXES = ["daemon_", "standalone_"];
|
|
8062
|
-
}
|
|
8063
|
-
});
|
|
8064
|
-
|
|
8065
8076
|
// src/mesh/mesh-active-work.ts
|
|
8066
8077
|
function readString6(value) {
|
|
8067
8078
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
@@ -20339,6 +20350,7 @@ __export(index_exports, {
|
|
|
20339
20350
|
createNativeHistoryDispatcher: () => createNativeHistoryDispatcher,
|
|
20340
20351
|
createSessionDelivery: () => createSessionDelivery,
|
|
20341
20352
|
createWorktree: () => createWorktree,
|
|
20353
|
+
daemonIdsEquivalent: () => daemonIdsEquivalent,
|
|
20342
20354
|
deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
|
|
20343
20355
|
deleteMesh: () => deleteMesh,
|
|
20344
20356
|
deriveMeshReviewInboxItems: () => deriveMeshReviewInboxItems,
|
|
@@ -20352,6 +20364,7 @@ __export(index_exports, {
|
|
|
20352
20364
|
ensureSessionHostReady: () => ensureSessionHostReady,
|
|
20353
20365
|
evaluateFsm: () => evaluateFsm,
|
|
20354
20366
|
execNpmCommandSync: () => execNpmCommandSync,
|
|
20367
|
+
expandDaemonIdForms: () => expandDaemonIdForms,
|
|
20355
20368
|
fastForwardMeshNode: () => fastForwardMeshNode,
|
|
20356
20369
|
filterActivityChatMessages: () => filterActivityChatMessages,
|
|
20357
20370
|
filterChatMessagesByVisibility: () => filterChatMessagesByVisibility,
|
|
@@ -20442,6 +20455,7 @@ __export(index_exports, {
|
|
|
20442
20455
|
loadMeshWorktreeBootstrapConfig: () => loadMeshWorktreeBootstrapConfig,
|
|
20443
20456
|
loadState: () => loadState,
|
|
20444
20457
|
logCommand: () => logCommand,
|
|
20458
|
+
machineCoreFromDaemonId: () => machineCoreFromDaemonId,
|
|
20445
20459
|
markSessionDeliveriesTerminal: () => markSessionDeliveriesTerminal,
|
|
20446
20460
|
markSetupComplete: () => markSetupComplete,
|
|
20447
20461
|
markStaleDirectDispatches: () => markStaleDirectDispatches,
|
|
@@ -21800,6 +21814,7 @@ function getSavedProviderSessions(state, filters) {
|
|
|
21800
21814
|
|
|
21801
21815
|
// src/index.ts
|
|
21802
21816
|
init_mesh_config();
|
|
21817
|
+
init_dist();
|
|
21803
21818
|
init_coordinator_prompt();
|
|
21804
21819
|
init_mesh_missions();
|
|
21805
21820
|
init_mesh_task_stats();
|
|
@@ -27430,6 +27445,42 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
27430
27445
|
return fn() || null;
|
|
27431
27446
|
}
|
|
27432
27447
|
|
|
27448
|
+
// src/providers/manual-attendance.ts
|
|
27449
|
+
var AUTO_APPROVE_MANUAL_ATTENDANCE_SUPPRESS_MS = 6e4;
|
|
27450
|
+
var ManualAttendanceTracker = class {
|
|
27451
|
+
constructor(suppressMs = AUTO_APPROVE_MANUAL_ATTENDANCE_SUPPRESS_MS) {
|
|
27452
|
+
this.suppressMs = suppressMs;
|
|
27453
|
+
}
|
|
27454
|
+
lastInteractionAt = 0;
|
|
27455
|
+
/** Record that a human just drove this session by hand. */
|
|
27456
|
+
note(now = Date.now()) {
|
|
27457
|
+
this.lastInteractionAt = now;
|
|
27458
|
+
}
|
|
27459
|
+
/** True while a manual interaction is recent enough to suppress auto-approve. */
|
|
27460
|
+
isAttended(now = Date.now()) {
|
|
27461
|
+
return this.lastInteractionAt > 0 && now - this.lastInteractionAt < this.suppressMs;
|
|
27462
|
+
}
|
|
27463
|
+
/**
|
|
27464
|
+
* Milliseconds remaining in the current suppression window, or 0 when not
|
|
27465
|
+
* attended. Used to re-arm a re-check timer so auto-approve fires the moment
|
|
27466
|
+
* the window lapses even if the PTY/agent has since gone silent.
|
|
27467
|
+
*/
|
|
27468
|
+
remainingMs(now = Date.now()) {
|
|
27469
|
+
if (this.lastInteractionAt <= 0) return 0;
|
|
27470
|
+
return Math.max(0, this.suppressMs - (now - this.lastInteractionAt));
|
|
27471
|
+
}
|
|
27472
|
+
};
|
|
27473
|
+
var MANUAL_ATTENDANCE_COMMANDS = /* @__PURE__ */ new Set([
|
|
27474
|
+
"select_session",
|
|
27475
|
+
"open_panel",
|
|
27476
|
+
"invoke_provider_script",
|
|
27477
|
+
"set_mode",
|
|
27478
|
+
"change_model",
|
|
27479
|
+
"set_thought_level",
|
|
27480
|
+
"resolve_action",
|
|
27481
|
+
"pty_input"
|
|
27482
|
+
]);
|
|
27483
|
+
|
|
27433
27484
|
// src/commands/chat-commands.ts
|
|
27434
27485
|
var fs7 = __toESM(require("fs"));
|
|
27435
27486
|
var os10 = __toESM(require("os"));
|
|
@@ -31769,11 +31820,38 @@ var DaemonCommandHandler = class {
|
|
|
31769
31820
|
setAgentStreamManager(manager) {
|
|
31770
31821
|
this._agentStream = manager;
|
|
31771
31822
|
}
|
|
31823
|
+
/**
|
|
31824
|
+
* When a command in the manual-attendance set arrives for a session this
|
|
31825
|
+
* daemon hosts, stamp the live instance so auto-approve holds while the user
|
|
31826
|
+
* drives the session by hand. Provider-common: the signal is the command
|
|
31827
|
+
* (foreground select_session / open_panel, controlbar invoke_provider_script
|
|
31828
|
+
* / set_mode / change_model / set_thought_level, manual resolve_action,
|
|
31829
|
+
* pty_input), never any CLI-specific modal text — so it works identically for
|
|
31830
|
+
* every CLI/ACP provider. send_chat is deliberately excluded because a
|
|
31831
|
+
* coordinator delegating a task to a worker also uses send_chat; counting it
|
|
31832
|
+
* would wrongly suppress the worker's delegated auto-approve. For a remote
|
|
31833
|
+
* mesh worker session the controlbar commands are forwarded to the owning
|
|
31834
|
+
* worker daemon, which runs this same hook there, so attendance is recorded
|
|
31835
|
+
* on the daemon that actually hosts the instance.
|
|
31836
|
+
*/
|
|
31837
|
+
noteManualAttendanceIfApplicable(cmd, args) {
|
|
31838
|
+
if (!MANUAL_ATTENDANCE_COMMANDS.has(cmd)) return;
|
|
31839
|
+
const sessionId = this._currentRoute.session?.sessionId || (typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "");
|
|
31840
|
+
if (!sessionId) return;
|
|
31841
|
+
const session = this._ctx.sessionRegistry?.get(sessionId);
|
|
31842
|
+
const instanceKey = session?.adapterKey || session?.instanceKey || sessionId;
|
|
31843
|
+
const instance = this._ctx.instanceManager?.getInstance(instanceKey);
|
|
31844
|
+
try {
|
|
31845
|
+
instance?.noteManualInteraction?.();
|
|
31846
|
+
} catch {
|
|
31847
|
+
}
|
|
31848
|
+
}
|
|
31772
31849
|
// ─── Command Dispatcher ──────────────────────────
|
|
31773
31850
|
async handle(cmd, args) {
|
|
31774
31851
|
this._currentRoute = this.resolveRoute(args);
|
|
31775
31852
|
const startedAt = Date.now();
|
|
31776
31853
|
this.logCommandStart(cmd, args);
|
|
31854
|
+
this.noteManualAttendanceIfApplicable(cmd, args);
|
|
31777
31855
|
let result;
|
|
31778
31856
|
if (isGitCommandName(cmd)) {
|
|
31779
31857
|
result = await handleGitCommand(cmd, args, this._ctx.gitCommandServices);
|
|
@@ -35727,6 +35805,11 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35727
35805
|
// a settle gate was in progress. Drives AUTO_APPROVE_GATE_HYSTERESIS_MS so a
|
|
35728
35806
|
// brief generating flip does not immediately wipe the settle clock.
|
|
35729
35807
|
autoApproveInactiveSince = 0;
|
|
35808
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
35809
|
+
// this session from the dashboard, auto-approve holds so they can take manual
|
|
35810
|
+
// control. Background mesh workers are never attended → delegated auto-approve
|
|
35811
|
+
// is unaffected.
|
|
35812
|
+
manualAttendance = new ManualAttendanceTracker();
|
|
35730
35813
|
controlValues = {};
|
|
35731
35814
|
summaryMetadata = void 0;
|
|
35732
35815
|
appliedEffectKeys = /* @__PURE__ */ new Set();
|
|
@@ -36002,7 +36085,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36002
36085
|
}
|
|
36003
36086
|
getHotChatSessionState() {
|
|
36004
36087
|
const adapterStatus = this.adapter.getStatus({ allowParse: false });
|
|
36005
|
-
const autoApproveActive = adapterStatus.status
|
|
36088
|
+
const autoApproveActive = this.autoApproveEffectivelyActive(adapterStatus.status);
|
|
36006
36089
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
36007
36090
|
const visibleStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
36008
36091
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
@@ -36017,7 +36100,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36017
36100
|
}
|
|
36018
36101
|
getSessionModalState(sessionId) {
|
|
36019
36102
|
const adapterStatus = this.adapter.getStatus({ allowParse: true });
|
|
36020
|
-
const autoApproveActive = adapterStatus.status
|
|
36103
|
+
const autoApproveActive = this.autoApproveEffectivelyActive(adapterStatus.status);
|
|
36021
36104
|
const autoApproveHoldIdle = this.autoApproveBusy && adapterStatus.status === "idle";
|
|
36022
36105
|
const visibleStatus = autoApproveActive || autoApproveHoldIdle ? "generating" : adapterStatus.status;
|
|
36023
36106
|
const dirName = workingDirBasename(this.workingDir);
|
|
@@ -36098,7 +36181,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36098
36181
|
} catch {
|
|
36099
36182
|
return null;
|
|
36100
36183
|
}
|
|
36101
|
-
if (adapterStatus.status === "waiting_approval" && !this.
|
|
36184
|
+
if (adapterStatus.status === "waiting_approval" && !this.autoApproveEffectivelyActive(adapterStatus.status)) {
|
|
36102
36185
|
return "waiting_approval";
|
|
36103
36186
|
}
|
|
36104
36187
|
return null;
|
|
@@ -36544,6 +36627,18 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
36544
36627
|
this.lastApprovalEventFingerprint = "";
|
|
36545
36628
|
}
|
|
36546
36629
|
maybeAutoApproveStatus(adapterStatus, now = Date.now()) {
|
|
36630
|
+
if (adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove() && this.manualAttendance.isAttended(now)) {
|
|
36631
|
+
this.lastAutoApprovalSignature = "";
|
|
36632
|
+
this.pendingAutoApprovalSignature = "";
|
|
36633
|
+
this.pendingAutoApprovalSince = 0;
|
|
36634
|
+
this.autoApproveInactiveSince = 0;
|
|
36635
|
+
if (this.autoApproveSettleTimer) clearTimeout(this.autoApproveSettleTimer);
|
|
36636
|
+
this.autoApproveSettleTimer = setTimeout(() => {
|
|
36637
|
+
this.autoApproveSettleTimer = null;
|
|
36638
|
+
this.recheckAutoApproveSettled();
|
|
36639
|
+
}, this.manualAttendance.remainingMs(now) + 20);
|
|
36640
|
+
return false;
|
|
36641
|
+
}
|
|
36547
36642
|
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
|
|
36548
36643
|
if (!autoApproveActive) {
|
|
36549
36644
|
this.lastAutoApprovalSignature = "";
|
|
@@ -37009,6 +37104,21 @@ ${effect.notification.body || ""}`.trim();
|
|
|
37009
37104
|
}
|
|
37010
37105
|
return false;
|
|
37011
37106
|
}
|
|
37107
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
37108
|
+
noteManualInteraction(now = Date.now()) {
|
|
37109
|
+
this.manualAttendance.note(now);
|
|
37110
|
+
}
|
|
37111
|
+
/**
|
|
37112
|
+
* Whether auto-approve should be treated as active *right now* for display
|
|
37113
|
+
* and firing decisions: the configured intent AND the user is not currently
|
|
37114
|
+
* attending this session by hand. When a human is attending, auto-approve is
|
|
37115
|
+
* held so the modal stays visible and they can drive it via the controlbar.
|
|
37116
|
+
* Provider-agnostic — the attendance signal is the command set, never any
|
|
37117
|
+
* CLI-specific modal text.
|
|
37118
|
+
*/
|
|
37119
|
+
autoApproveEffectivelyActive(status, now = Date.now()) {
|
|
37120
|
+
return status === "waiting_approval" && this.shouldAutoApprove() && !this.manualAttendance.isAttended(now);
|
|
37121
|
+
}
|
|
37012
37122
|
recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
|
|
37013
37123
|
this.appendRuntimeSystemMessage(
|
|
37014
37124
|
formatAutoApprovalMessage(modalMessage, buttonLabel),
|
|
@@ -37954,7 +38064,7 @@ var AcpProviderInstance = class {
|
|
|
37954
38064
|
input: tc.rawInput ? typeof tc.rawInput === "string" ? tc.rawInput : JSON.stringify(tc.rawInput) : void 0
|
|
37955
38065
|
});
|
|
37956
38066
|
}
|
|
37957
|
-
if (this.settings.autoApprove !== false) {
|
|
38067
|
+
if (this.settings.autoApprove !== false && !this.manualAttendance.isAttended()) {
|
|
37958
38068
|
const toolTitle = tc.title || tc.toolCallId || "tool call";
|
|
37959
38069
|
this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
|
|
37960
38070
|
this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
|
|
@@ -38185,6 +38295,15 @@ var AcpProviderInstance = class {
|
|
|
38185
38295
|
this.detectStatusTransition();
|
|
38186
38296
|
}
|
|
38187
38297
|
permissionResolvers = [];
|
|
38298
|
+
// Provider-common manual-attendance signal: while a human is actively driving
|
|
38299
|
+
// this session from the dashboard, auto-approve holds so they can decide on
|
|
38300
|
+
// the permission request themselves. Background workers are never attended →
|
|
38301
|
+
// delegated auto-approve is unaffected.
|
|
38302
|
+
manualAttendance = new ManualAttendanceTracker();
|
|
38303
|
+
/** @see ProviderInstance.noteManualInteraction */
|
|
38304
|
+
noteManualInteraction(now = Date.now()) {
|
|
38305
|
+
this.manualAttendance.note(now);
|
|
38306
|
+
}
|
|
38188
38307
|
async resolvePermission(approved) {
|
|
38189
38308
|
const resolver = this.permissionResolvers.shift();
|
|
38190
38309
|
if (resolver) {
|
|
@@ -39342,6 +39461,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39342
39461
|
);
|
|
39343
39462
|
continue;
|
|
39344
39463
|
}
|
|
39464
|
+
const restoredSettings = { ...this.providerLoader.getSettings(normalizedType) };
|
|
39465
|
+
const coordinatorEntry = getCoordinatorForSession(record.runtimeId);
|
|
39466
|
+
if (coordinatorEntry?.meshId) {
|
|
39467
|
+
restoredSettings.meshCoordinatorFor = coordinatorEntry.meshId;
|
|
39468
|
+
}
|
|
39345
39469
|
try {
|
|
39346
39470
|
await this.registerCliInstance(
|
|
39347
39471
|
record.runtimeId,
|
|
@@ -39350,7 +39474,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39350
39474
|
record.workspace,
|
|
39351
39475
|
record.cliArgs,
|
|
39352
39476
|
resolvedProvider,
|
|
39353
|
-
|
|
39477
|
+
restoredSettings,
|
|
39354
39478
|
true,
|
|
39355
39479
|
{
|
|
39356
39480
|
providerSessionId: sessionBinding.providerSessionId,
|
|
@@ -39391,9 +39515,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
39391
39515
|
}
|
|
39392
39516
|
}
|
|
39393
39517
|
}
|
|
39394
|
-
|
|
39395
|
-
|
|
39396
|
-
|
|
39518
|
+
if (!opts?.instanceKey) {
|
|
39519
|
+
for (const [k, a] of this.adapters) {
|
|
39520
|
+
if (a.cliType === agentType) {
|
|
39521
|
+
return { adapter: a, key: k };
|
|
39522
|
+
}
|
|
39397
39523
|
}
|
|
39398
39524
|
}
|
|
39399
39525
|
return null;
|
|
@@ -46750,7 +46876,14 @@ var MESH_FORWARDABLE_SESSION_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
46750
46876
|
"resolve_action",
|
|
46751
46877
|
"set_mode",
|
|
46752
46878
|
"change_model",
|
|
46753
|
-
"set_thought_level"
|
|
46879
|
+
"set_thought_level",
|
|
46880
|
+
// agent_command (send_chat / clear_history / stop) is session-scoped too: a command
|
|
46881
|
+
// explicitly naming a targetSessionId MUST reach that session wherever it lives, never a
|
|
46882
|
+
// different local session. Without forwarding, a misrouted/relayed send_chat for a REMOTE
|
|
46883
|
+
// worker session that reaches the wrong daemon used to fuzzy-inject the task body into that
|
|
46884
|
+
// daemon's own CLI session (TASKECHO coordinator self-echo). Forwarding to the owning daemon
|
|
46885
|
+
// delivers it to the real worker instead. (findAdapter is also fail-closed as the backstop.)
|
|
46886
|
+
"agent_command"
|
|
46754
46887
|
]);
|
|
46755
46888
|
var READ_DEBUG_ENABLED2 = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
46756
46889
|
function normalizeCommandSource(source) {
|
|
@@ -47103,7 +47236,7 @@ var DaemonCommandRouter = class {
|
|
|
47103
47236
|
if (!collectMeshNodeHostedSessionIds(node).has(trimmed)) continue;
|
|
47104
47237
|
const nodeDaemonId = readMeshNodeDaemonId(readObjectRecord(node));
|
|
47105
47238
|
if (!nodeDaemonId) continue;
|
|
47106
|
-
if (selfDaemonId && nodeDaemonId
|
|
47239
|
+
if (selfDaemonId && daemonIdsEquivalent(nodeDaemonId, selfDaemonId)) return void 0;
|
|
47107
47240
|
return nodeDaemonId;
|
|
47108
47241
|
}
|
|
47109
47242
|
return void 0;
|
|
@@ -47258,6 +47391,38 @@ var DaemonCommandRouter = class {
|
|
|
47258
47391
|
if (record?.meta?.meshNodeId === nodeId) return true;
|
|
47259
47392
|
return false;
|
|
47260
47393
|
}
|
|
47394
|
+
/**
|
|
47395
|
+
* Best-effort recursive removal of a managed worktree directory.
|
|
47396
|
+
*
|
|
47397
|
+
* The git-registry de-registration is the safety-critical step of worktree
|
|
47398
|
+
* teardown; a leftover directory must never gate dropping the node from the
|
|
47399
|
+
* mesh. On Windows, `fs.rmSync` can throw EINVAL/EPERM/EBUSY on submodule
|
|
47400
|
+
* gitlink (`.git`) files, long paths, junctions, or while a just-stopped
|
|
47401
|
+
* delegate session is still releasing a handle/cwd on the directory. This
|
|
47402
|
+
* helper absorbs those errors (never throws), with bounded retries + backoff
|
|
47403
|
+
* to give handles time to release, and reports whether residue remains.
|
|
47404
|
+
*/
|
|
47405
|
+
async bestEffortRemoveWorktreeDir(dir) {
|
|
47406
|
+
if (!dir || !fs26.existsSync(dir)) return { removed: true, residue: false };
|
|
47407
|
+
const sleep3 = (ms) => new Promise((resolve24) => setTimeout(resolve24, ms));
|
|
47408
|
+
const ABSORB = /* @__PURE__ */ new Set(["EINVAL", "EPERM", "EBUSY", "ENOTEMPTY", "EACCES", "EMFILE", "ENFILE"]);
|
|
47409
|
+
let lastErr;
|
|
47410
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
47411
|
+
try {
|
|
47412
|
+
fs26.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
47413
|
+
if (!fs26.existsSync(dir)) return { removed: true, residue: false };
|
|
47414
|
+
lastErr = new Error("directory still present after rmSync");
|
|
47415
|
+
} catch (e) {
|
|
47416
|
+
lastErr = e;
|
|
47417
|
+
const code = typeof e?.code === "string" ? e.code : "";
|
|
47418
|
+
if (code && !ABSORB.has(code)) {
|
|
47419
|
+
break;
|
|
47420
|
+
}
|
|
47421
|
+
}
|
|
47422
|
+
await sleep3(150 * (attempt + 1));
|
|
47423
|
+
}
|
|
47424
|
+
return fs26.existsSync(dir) ? { removed: false, residue: true, error: String(lastErr?.message || lastErr || "unknown rm error") } : { removed: true, residue: false };
|
|
47425
|
+
}
|
|
47261
47426
|
async cleanupLocalWorktreeNode(args) {
|
|
47262
47427
|
const workspace = typeof args.node?.workspace === "string" ? args.node.workspace.trim() : "";
|
|
47263
47428
|
if (!workspace) {
|
|
@@ -47312,11 +47477,31 @@ var DaemonCommandRouter = class {
|
|
|
47312
47477
|
const entries = await listWorktrees2(repoRoot);
|
|
47313
47478
|
const managedEntry = entries.find((entry) => normalizePath(entry.path) === actualPath);
|
|
47314
47479
|
if (!managedEntry) {
|
|
47480
|
+
try {
|
|
47481
|
+
const { execFile: execFile5 } = await import("child_process");
|
|
47482
|
+
const { promisify: promisify8 } = await import("util");
|
|
47483
|
+
const execFileAsync4 = promisify8(execFile5);
|
|
47484
|
+
await execFileAsync4("git", ["worktree", "prune"], {
|
|
47485
|
+
cwd: repoRoot,
|
|
47486
|
+
encoding: "utf8",
|
|
47487
|
+
timeout: 3e4,
|
|
47488
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
47489
|
+
windowsHide: true
|
|
47490
|
+
});
|
|
47491
|
+
} catch {
|
|
47492
|
+
}
|
|
47493
|
+
const rm = await this.bestEffortRemoveWorktreeDir(workspace);
|
|
47315
47494
|
return {
|
|
47316
|
-
success:
|
|
47317
|
-
|
|
47318
|
-
|
|
47319
|
-
|
|
47495
|
+
success: true,
|
|
47496
|
+
removedPath: workspace,
|
|
47497
|
+
repoRoot,
|
|
47498
|
+
reason: "worktree_unregistered_residue_recovered",
|
|
47499
|
+
recovered: true,
|
|
47500
|
+
...rm.residue ? {
|
|
47501
|
+
residue: true,
|
|
47502
|
+
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.`,
|
|
47503
|
+
residueError: rm.error
|
|
47504
|
+
} : {}
|
|
47320
47505
|
};
|
|
47321
47506
|
}
|
|
47322
47507
|
if (managedEntry.branch && managedEntry.branch !== args.node.worktreeBranch) {
|
|
@@ -47379,8 +47564,8 @@ var DaemonCommandRouter = class {
|
|
|
47379
47564
|
convergence: forceFallbackConvergence
|
|
47380
47565
|
};
|
|
47381
47566
|
} catch (deinitError) {
|
|
47567
|
+
const rm = await this.bestEffortRemoveWorktreeDir(workspace);
|
|
47382
47568
|
try {
|
|
47383
|
-
fs26.rmSync(workspace, { recursive: true, force: true });
|
|
47384
47569
|
await execFileAsync4("git", ["worktree", "prune"], {
|
|
47385
47570
|
cwd: repoRoot,
|
|
47386
47571
|
encoding: "utf8",
|
|
@@ -47388,23 +47573,22 @@ var DaemonCommandRouter = class {
|
|
|
47388
47573
|
maxBuffer: GIT_MAX_BUFFER_CLEANUP,
|
|
47389
47574
|
windowsHide: true
|
|
47390
47575
|
});
|
|
47391
|
-
|
|
47392
|
-
success: true,
|
|
47393
|
-
removedPath: workspace,
|
|
47394
|
-
repoRoot,
|
|
47395
|
-
fallback: "fs_rm_worktree_prune",
|
|
47396
|
-
forced: true,
|
|
47397
|
-
reason: "working_trees_containing_submodules",
|
|
47398
|
-
convergence: forceFallbackConvergence
|
|
47399
|
-
};
|
|
47400
|
-
} catch (rmError) {
|
|
47401
|
-
return {
|
|
47402
|
-
success: false,
|
|
47403
|
-
code: "mesh_worktree_cleanup_failed",
|
|
47404
|
-
error: `All removal fallbacks exhausted. deinit+remove: ${deinitError?.message || deinitError}; rmSync+prune: ${rmError?.message || rmError}`,
|
|
47405
|
-
recoveryHint: "Manually remove the worktree directory and run git worktree prune from the source repo."
|
|
47406
|
-
};
|
|
47576
|
+
} catch {
|
|
47407
47577
|
}
|
|
47578
|
+
return {
|
|
47579
|
+
success: true,
|
|
47580
|
+
removedPath: workspace,
|
|
47581
|
+
repoRoot,
|
|
47582
|
+
fallback: "fs_rm_worktree_prune",
|
|
47583
|
+
forced: true,
|
|
47584
|
+
reason: "working_trees_containing_submodules",
|
|
47585
|
+
convergence: forceFallbackConvergence,
|
|
47586
|
+
...rm.residue ? {
|
|
47587
|
+
residue: true,
|
|
47588
|
+
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.`,
|
|
47589
|
+
residueError: rm.error
|
|
47590
|
+
} : {}
|
|
47591
|
+
};
|
|
47408
47592
|
}
|
|
47409
47593
|
}
|
|
47410
47594
|
return {
|
|
@@ -50803,7 +50987,14 @@ ${hintLines.join("\n")}` : "",
|
|
|
50803
50987
|
} catch {
|
|
50804
50988
|
}
|
|
50805
50989
|
}
|
|
50806
|
-
|
|
50990
|
+
const residueWarning = worktreeCleanup?.residue === true && typeof worktreeCleanup?.residueWarning === "string" ? worktreeCleanup.residueWarning : void 0;
|
|
50991
|
+
return {
|
|
50992
|
+
success: true,
|
|
50993
|
+
removed,
|
|
50994
|
+
...residueWarning ? { residueWarning } : {},
|
|
50995
|
+
...sessionCleanup ? { sessionCleanup } : {},
|
|
50996
|
+
...worktreeCleanup ? { worktreeCleanup } : {}
|
|
50997
|
+
};
|
|
50807
50998
|
} catch (e) {
|
|
50808
50999
|
return { success: false, error: e.message };
|
|
50809
51000
|
}
|
|
@@ -60797,6 +60988,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
60797
60988
|
createNativeHistoryDispatcher,
|
|
60798
60989
|
createSessionDelivery,
|
|
60799
60990
|
createWorktree,
|
|
60991
|
+
daemonIdsEquivalent,
|
|
60800
60992
|
deleteDirectDispatchesByTaskId,
|
|
60801
60993
|
deleteMesh,
|
|
60802
60994
|
deriveMeshReviewInboxItems,
|
|
@@ -60810,6 +61002,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
60810
61002
|
ensureSessionHostReady,
|
|
60811
61003
|
evaluateFsm,
|
|
60812
61004
|
execNpmCommandSync,
|
|
61005
|
+
expandDaemonIdForms,
|
|
60813
61006
|
fastForwardMeshNode,
|
|
60814
61007
|
filterActivityChatMessages,
|
|
60815
61008
|
filterChatMessagesByVisibility,
|
|
@@ -60900,6 +61093,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
60900
61093
|
loadMeshWorktreeBootstrapConfig,
|
|
60901
61094
|
loadState,
|
|
60902
61095
|
logCommand,
|
|
61096
|
+
machineCoreFromDaemonId,
|
|
60903
61097
|
markSessionDeliveriesTerminal,
|
|
60904
61098
|
markSetupComplete,
|
|
60905
61099
|
markStaleDirectDispatches,
|