@adhdev/daemon-standalone 1.0.18-rc.7 → 1.0.18-rc.9
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/index.js +245 -57
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/vendor/mcp-server/index.js +22 -2
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/index.js
CHANGED
|
@@ -30265,10 +30265,10 @@ var require_dist3 = __commonJS({
|
|
|
30265
30265
|
}
|
|
30266
30266
|
function getDaemonBuildInfo() {
|
|
30267
30267
|
if (cached2) return cached2;
|
|
30268
|
-
const commit = readInjected(true ? "
|
|
30269
|
-
const commitShort = readInjected(true ? "
|
|
30270
|
-
const version2 = readInjected(true ? "1.0.18-rc.
|
|
30271
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
30268
|
+
const commit = readInjected(true ? "3a1a0d16c0dd7ce3df15591fbe30b7e8638ab876" : void 0) ?? "unknown";
|
|
30269
|
+
const commitShort = readInjected(true ? "3a1a0d16" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30270
|
+
const version2 = readInjected(true ? "1.0.18-rc.9" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30271
|
+
const builtAt = readInjected(true ? "2026-07-22T05:27:46.385Z" : void 0);
|
|
30272
30272
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30273
30273
|
return cached2;
|
|
30274
30274
|
}
|
|
@@ -39779,40 +39779,113 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
39779
39779
|
if (!category) return true;
|
|
39780
39780
|
return !(category in OPERATING_NOTE_CATEGORY_TTL_DAYS);
|
|
39781
39781
|
}
|
|
39782
|
-
function
|
|
39782
|
+
function deriveSubjectKey(note) {
|
|
39783
|
+
const explicit = typeof note.subjectKey === "string" ? note.subjectKey.trim().toLowerCase() : "";
|
|
39784
|
+
if (explicit) return explicit;
|
|
39785
|
+
const text = typeof note.text === "string" ? note.text.trimStart() : "";
|
|
39786
|
+
const m = /^\[([^\]]{1,80})\]/.exec(text);
|
|
39787
|
+
const tag = m ? m[1].trim().toLowerCase() : "";
|
|
39788
|
+
return tag || void 0;
|
|
39789
|
+
}
|
|
39790
|
+
function foldSameClassNotes(ranked) {
|
|
39791
|
+
const out = [];
|
|
39792
|
+
const survivorByKey = /* @__PURE__ */ new Map();
|
|
39793
|
+
for (const note of ranked) {
|
|
39794
|
+
const subject = deriveSubjectKey(note);
|
|
39795
|
+
const foldable = !note.pinned && !!note.category && !!subject;
|
|
39796
|
+
if (foldable) {
|
|
39797
|
+
const key2 = `${note.category}\0${subject}`;
|
|
39798
|
+
const existing = survivorByKey.get(key2);
|
|
39799
|
+
if (existing !== void 0) {
|
|
39800
|
+
const survivor = out[existing];
|
|
39801
|
+
survivor.subsumedCount += 1;
|
|
39802
|
+
if (typeof note.noteId === "string" && note.noteId) survivor.subsumedIds.push(note.noteId);
|
|
39803
|
+
continue;
|
|
39804
|
+
}
|
|
39805
|
+
survivorByKey.set(key2, out.length);
|
|
39806
|
+
}
|
|
39807
|
+
out.push({ note, subsumedIds: [], subsumedCount: 0 });
|
|
39808
|
+
}
|
|
39809
|
+
return out;
|
|
39810
|
+
}
|
|
39811
|
+
function renderedNoteBytes(folded) {
|
|
39812
|
+
return byteLength2(renderOperatingNoteLine(folded));
|
|
39813
|
+
}
|
|
39814
|
+
function selectOperatingNotesForPrompt(notes, now, cap = OPERATING_NOTES_PROMPT_CAP, byteBudget = OPERATING_NOTE_INJECTION_BYTE_BUDGET) {
|
|
39783
39815
|
const valid = Array.isArray(notes) ? notes.filter((n) => n && typeof n.text === "string" && n.text.trim()) : [];
|
|
39784
|
-
|
|
39816
|
+
let kept = valid.map((note, index) => ({ note, index })).filter(({ note }) => note.pinned || !isNoteExpired(note, now));
|
|
39817
|
+
const supersededAtIndex = /* @__PURE__ */ new Map();
|
|
39818
|
+
for (const { note, index } of kept) {
|
|
39819
|
+
const target = typeof note.supersedes === "string" ? note.supersedes.trim().toLowerCase() : "";
|
|
39820
|
+
if (!target) continue;
|
|
39821
|
+
const prev = supersededAtIndex.get(target);
|
|
39822
|
+
if (prev === void 0 || index > prev) supersededAtIndex.set(target, index);
|
|
39823
|
+
}
|
|
39824
|
+
if (supersededAtIndex.size > 0) {
|
|
39825
|
+
kept = kept.filter(({ note, index }) => {
|
|
39826
|
+
if (note.pinned) return true;
|
|
39827
|
+
const byId = typeof note.noteId === "string" ? note.noteId.trim().toLowerCase() : "";
|
|
39828
|
+
const bySubject = deriveSubjectKey(note);
|
|
39829
|
+
const supIdx = Math.max(
|
|
39830
|
+
byId ? supersededAtIndex.get(byId) ?? -1 : -1,
|
|
39831
|
+
bySubject ? supersededAtIndex.get(bySubject) ?? -1 : -1
|
|
39832
|
+
);
|
|
39833
|
+
return !(supIdx > index);
|
|
39834
|
+
});
|
|
39835
|
+
}
|
|
39785
39836
|
const rank = (n) => n.pinned ? 0 : isDurableCategory(n.category) ? 1 : 2;
|
|
39786
39837
|
kept.sort((a, b) => {
|
|
39787
39838
|
const r = rank(a.note) - rank(b.note);
|
|
39788
39839
|
if (r !== 0) return r;
|
|
39789
39840
|
return b.index - a.index;
|
|
39790
39841
|
});
|
|
39791
|
-
const
|
|
39792
|
-
const shown =
|
|
39842
|
+
const folded = foldSameClassNotes(kept.map((k) => k.note));
|
|
39843
|
+
const shown = [];
|
|
39844
|
+
let usedBytes = 0;
|
|
39845
|
+
let usedCount = 0;
|
|
39846
|
+
for (const entry of folded) {
|
|
39847
|
+
if (entry.note.pinned) {
|
|
39848
|
+
shown.push(entry);
|
|
39849
|
+
usedBytes += renderedNoteBytes(entry);
|
|
39850
|
+
usedCount += 1;
|
|
39851
|
+
continue;
|
|
39852
|
+
}
|
|
39853
|
+
if (usedCount >= cap) break;
|
|
39854
|
+
const bytes = renderedNoteBytes(entry);
|
|
39855
|
+
if (usedCount > 0 && usedBytes + bytes > byteBudget) break;
|
|
39856
|
+
shown.push(entry);
|
|
39857
|
+
usedBytes += bytes;
|
|
39858
|
+
usedCount += 1;
|
|
39859
|
+
}
|
|
39860
|
+
const omittedCount = Math.max(0, folded.length - shown.length);
|
|
39793
39861
|
return { shown, omittedCount };
|
|
39794
39862
|
}
|
|
39795
|
-
function
|
|
39796
|
-
const
|
|
39797
|
-
if (!hasAny) return "";
|
|
39863
|
+
function renderOperatingNoteLine(folded) {
|
|
39864
|
+
const n = folded.note;
|
|
39798
39865
|
const categoryLabel = {
|
|
39799
39866
|
provider_quirk: "provider quirk",
|
|
39800
39867
|
pattern_to_avoid: "pattern to avoid",
|
|
39801
39868
|
recovery_lesson: "recovery lesson"
|
|
39802
39869
|
};
|
|
39870
|
+
const pin = n.pinned ? "\u{1F4CC} " : "";
|
|
39871
|
+
const cat = n.category && categoryLabel[n.category] ? `[${categoryLabel[n.category]}] ` : "";
|
|
39872
|
+
const fold = folded.subsumedCount > 0 ? ` _(+${folded.subsumedCount} earlier same-subject note${folded.subsumedCount === 1 ? "" : "s"} folded${folded.subsumedIds.length ? `: ${folded.subsumedIds.join(", ")}` : ""})_` : "";
|
|
39873
|
+
return `- ${pin}${cat}${truncateNote(n.text.trim())}${fold}`;
|
|
39874
|
+
}
|
|
39875
|
+
function buildOperatingNotesSection(notes, now = Date.now()) {
|
|
39876
|
+
const hasAny = Array.isArray(notes) ? notes.some((n) => n && typeof n.text === "string" && n.text.trim()) : false;
|
|
39877
|
+
if (!hasAny) return "";
|
|
39803
39878
|
const { shown, omittedCount } = selectOperatingNotesForPrompt(notes ?? [], now);
|
|
39804
39879
|
if (shown.length === 0) return "";
|
|
39805
39880
|
const lines = ["## Operating Notes", ""];
|
|
39806
39881
|
lines.push("Lessons earlier coordinators on this mesh recorded via `mesh_record_note`. Treat them as accumulated operating knowledge \u2014 apply them. When you learn a durable lesson (a provider quirk, a pattern to avoid, a recovery lesson), record it with `mesh_record_note` so future coordinators inherit it.");
|
|
39807
39882
|
lines.push("");
|
|
39808
|
-
for (const
|
|
39809
|
-
|
|
39810
|
-
const cat = n.category && categoryLabel[n.category] ? `[${categoryLabel[n.category]}] ` : "";
|
|
39811
|
-
lines.push(`- ${pin}${cat}${truncateNote(n.text.trim())}`);
|
|
39883
|
+
for (const entry of shown) {
|
|
39884
|
+
lines.push(renderOperatingNoteLine(entry));
|
|
39812
39885
|
}
|
|
39813
39886
|
if (omittedCount > 0) {
|
|
39814
39887
|
lines.push("");
|
|
39815
|
-
lines.push(`_${omittedCount} lower-priority note${omittedCount === 1 ? "" : "s"} omitted (kept in ledger; expired
|
|
39888
|
+
lines.push(`_${omittedCount} lower-priority note${omittedCount === 1 ? "" : "s"} omitted to fit the injection cap/byte-budget (kept in ledger; expired, superseded, and same-subject-folded notes are also hidden from this list but retained for audit; prune with \`mesh_forget_note\`)._`);
|
|
39816
39889
|
}
|
|
39817
39890
|
return lines.join("\n");
|
|
39818
39891
|
}
|
|
@@ -39942,6 +40015,7 @@ When you compose the task message you dispatch to a node, include these requirem
|
|
|
39942
40015
|
var PROMPT_SOFT_CAP_BYTES;
|
|
39943
40016
|
var OPERATING_NOTES_PROMPT_CAP;
|
|
39944
40017
|
var OPERATING_NOTE_MAX_CHARS;
|
|
40018
|
+
var OPERATING_NOTE_INJECTION_BYTE_BUDGET;
|
|
39945
40019
|
var TOOLS_SECTION;
|
|
39946
40020
|
var TOOL_EXPOSURE_PREFLIGHT_SECTION;
|
|
39947
40021
|
var WORKFLOW_SECTION;
|
|
@@ -39960,6 +40034,7 @@ When you compose the task message you dispatch to a node, include these requirem
|
|
|
39960
40034
|
PROMPT_SOFT_CAP_BYTES = 60 * 1024;
|
|
39961
40035
|
OPERATING_NOTES_PROMPT_CAP = 20;
|
|
39962
40036
|
OPERATING_NOTE_MAX_CHARS = 300;
|
|
40037
|
+
OPERATING_NOTE_INJECTION_BYTE_BUDGET = 6 * 1024;
|
|
39963
40038
|
TOOLS_SECTION = `## Available Tools
|
|
39964
40039
|
|
|
39965
40040
|
| Tool | Purpose |
|
|
@@ -41751,9 +41826,13 @@ ${rendered}`, "utf-8");
|
|
|
41751
41826
|
...typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {},
|
|
41752
41827
|
...typeof value.sourceCoordinator === "string" ? { sourceCoordinator: value.sourceCoordinator } : {},
|
|
41753
41828
|
// Operating-notes lifecycle: a repo-declared note may pin itself or set an
|
|
41754
|
-
// explicit expiry, same as a runtime-recorded one.
|
|
41829
|
+
// explicit expiry, same as a runtime-recorded one. Phase 2 (b)/(c): it may
|
|
41830
|
+
// also declare supersedes/subjectKey to retire an earlier note or group
|
|
41831
|
+
// same-subject notes for folding.
|
|
41755
41832
|
...value.pinned === true ? { pinned: true } : {},
|
|
41756
|
-
...typeof value.expiresAt === "string" ? { expiresAt: value.expiresAt } : {}
|
|
41833
|
+
...typeof value.expiresAt === "string" ? { expiresAt: value.expiresAt } : {},
|
|
41834
|
+
...typeof value.supersedes === "string" ? { supersedes: value.supersedes } : {},
|
|
41835
|
+
...typeof value.subjectKey === "string" ? { subjectKey: value.subjectKey } : {}
|
|
41757
41836
|
};
|
|
41758
41837
|
}
|
|
41759
41838
|
function normalizeRepoMeshDeclarativeConfig(parsed) {
|
|
@@ -46516,6 +46595,33 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
46516
46595
|
}
|
|
46517
46596
|
return isWithinCloneBootstrapGrace(targetNodeId);
|
|
46518
46597
|
}
|
|
46598
|
+
function resolveDeadTargetVerdict(components, meshId, mesh, task) {
|
|
46599
|
+
const NOT_DEAD = { dead: false, nodeDead: false, reason: "" };
|
|
46600
|
+
const targetSessionId = readNonEmptyString(task.targetSessionId);
|
|
46601
|
+
const targetNodeId = readNonEmptyString(task.targetNodeId);
|
|
46602
|
+
if (!targetSessionId && !targetNodeId) return NOT_DEAD;
|
|
46603
|
+
const lastUpdateMs = Date.parse(task.updatedAt || task.createdAt || "");
|
|
46604
|
+
if (Number.isFinite(lastUpdateMs) && Date.now() - lastUpdateMs < DEAD_TARGET_GRACE_MS) return NOT_DEAD;
|
|
46605
|
+
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
46606
|
+
if (targetNodeId) {
|
|
46607
|
+
const nodePresent = nodes.some((n) => meshNodeIdMatches(n, targetNodeId));
|
|
46608
|
+
if (!nodePresent) {
|
|
46609
|
+
if (isTargetNodeTransientlyUnresolved(mesh, task)) return NOT_DEAD;
|
|
46610
|
+
return { dead: true, nodeDead: true, reason: "dead_target_node_absent" };
|
|
46611
|
+
}
|
|
46612
|
+
}
|
|
46613
|
+
if (targetSessionId) {
|
|
46614
|
+
const node = targetNodeId ? nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
|
|
46615
|
+
const nodeIsLocal = node ? isLocalAutoLaunchNode(node) : true;
|
|
46616
|
+
if (nodeIsLocal) {
|
|
46617
|
+
const verdict = resolveSessionBusyVerdict(components, targetSessionId);
|
|
46618
|
+
if (verdict === "UNKNOWN") {
|
|
46619
|
+
return { dead: true, nodeDead: false, reason: "dead_target_session_absent" };
|
|
46620
|
+
}
|
|
46621
|
+
}
|
|
46622
|
+
}
|
|
46623
|
+
return NOT_DEAD;
|
|
46624
|
+
}
|
|
46519
46625
|
function retractActionableSkipIfPreviouslyNotified(meshId, taskId) {
|
|
46520
46626
|
const dedupKey = `${meshId}:${taskId}`;
|
|
46521
46627
|
if (!lastActionableSkipNotified.delete(dedupKey)) return;
|
|
@@ -47033,6 +47139,21 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
47033
47139
|
continue;
|
|
47034
47140
|
}
|
|
47035
47141
|
if (task.targetSessionId) {
|
|
47142
|
+
const deadTarget = resolveDeadTargetVerdict(components, meshId, mesh, task);
|
|
47143
|
+
if (deadTarget.dead) {
|
|
47144
|
+
const requeued = requeueTask(meshId, task.id, {
|
|
47145
|
+
reason: deadTarget.reason,
|
|
47146
|
+
clearTargetSession: true,
|
|
47147
|
+
// Keep the node pin if only the SESSION died on a still-live node; clear it
|
|
47148
|
+
// when the NODE itself is absent (nothing to pin to).
|
|
47149
|
+
clearTargetNode: deadTarget.nodeDead
|
|
47150
|
+
});
|
|
47151
|
+
if (requeued) {
|
|
47152
|
+
LOG2.warn("MeshQueue", `DEAD-TARGET-SELFHEAL: task ${task.id} (mesh ${meshId}) was pinned to a dead target (${deadTarget.reason}); requeued${deadTarget.nodeDead ? " and unpinned node" : ""} (requeueCount=${requeued.requeueCount ?? "?"}, status=${requeued.status}).`);
|
|
47153
|
+
}
|
|
47154
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_dead_requeued" });
|
|
47155
|
+
continue;
|
|
47156
|
+
}
|
|
47036
47157
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_constraint" });
|
|
47037
47158
|
continue;
|
|
47038
47159
|
}
|
|
@@ -47628,6 +47749,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
47628
47749
|
var ACTIONABLE_SKIP_REASON_PREFIXES;
|
|
47629
47750
|
var TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON;
|
|
47630
47751
|
var lastActionableSkipNotified;
|
|
47752
|
+
var DEAD_TARGET_GRACE_MS;
|
|
47631
47753
|
var init_mesh_queue_assignment = __esm2({
|
|
47632
47754
|
"src/mesh/mesh-queue-assignment.ts"() {
|
|
47633
47755
|
"use strict";
|
|
@@ -47689,6 +47811,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
47689
47811
|
];
|
|
47690
47812
|
TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
|
|
47691
47813
|
lastActionableSkipNotified = /* @__PURE__ */ new Map();
|
|
47814
|
+
DEAD_TARGET_GRACE_MS = 6e4;
|
|
47692
47815
|
}
|
|
47693
47816
|
});
|
|
47694
47817
|
function readSettings(state) {
|
|
@@ -73169,6 +73292,40 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
73169
73292
|
var POINTER_NAME = ".adhdev-current";
|
|
73170
73293
|
var STABLE_FILES = [POINTER_NAME, "adhdev.cmd", "adhdev.ps1", "adhdev"];
|
|
73171
73294
|
var DEFAULT_HEALTH_PORT = 19222;
|
|
73295
|
+
function fetchLocalJson(port, pathname) {
|
|
73296
|
+
return new Promise((resolve27) => {
|
|
73297
|
+
const req = http2.get(`http://127.0.0.1:${port}${pathname}`, { timeout: 1500 }, (res) => {
|
|
73298
|
+
let body = "";
|
|
73299
|
+
res.setEncoding("utf8");
|
|
73300
|
+
res.on("data", (chunk) => {
|
|
73301
|
+
body += chunk;
|
|
73302
|
+
});
|
|
73303
|
+
res.on("end", () => resolve27({ ok: res.statusCode === 200, body }));
|
|
73304
|
+
});
|
|
73305
|
+
req.on("timeout", () => req.destroy());
|
|
73306
|
+
req.on("error", () => resolve27({ ok: false, body: "" }));
|
|
73307
|
+
});
|
|
73308
|
+
}
|
|
73309
|
+
async function fetchLocalHealth(port) {
|
|
73310
|
+
const { ok, body } = await fetchLocalJson(port, "/health");
|
|
73311
|
+
if (!ok) return { ok: false };
|
|
73312
|
+
try {
|
|
73313
|
+
const pid = Number(JSON.parse(body)?.pid);
|
|
73314
|
+
return { ok: true, pid: Number.isFinite(pid) ? pid : void 0 };
|
|
73315
|
+
} catch {
|
|
73316
|
+
return { ok: false };
|
|
73317
|
+
}
|
|
73318
|
+
}
|
|
73319
|
+
async function fetchLocalStatusVersion(port) {
|
|
73320
|
+
const { ok, body } = await fetchLocalJson(port, "/api/v1/status");
|
|
73321
|
+
if (!ok) return void 0;
|
|
73322
|
+
try {
|
|
73323
|
+
const version2 = JSON.parse(body)?.status?.version;
|
|
73324
|
+
return typeof version2 === "string" ? version2 : void 0;
|
|
73325
|
+
} catch {
|
|
73326
|
+
return void 0;
|
|
73327
|
+
}
|
|
73328
|
+
}
|
|
73172
73329
|
var ADHDEV_OWNED_MARKERS = [
|
|
73173
73330
|
"session-host-daemon",
|
|
73174
73331
|
"node_modules/adhdev",
|
|
@@ -73446,6 +73603,8 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
73446
73603
|
}
|
|
73447
73604
|
}
|
|
73448
73605
|
function createDefaultWindowsAtomicHooks(options) {
|
|
73606
|
+
const healthPort = options.healthPort ?? DEFAULT_HEALTH_PORT;
|
|
73607
|
+
const healthTimeoutMs = options.healthTimeoutMs ?? 3e4;
|
|
73449
73608
|
return {
|
|
73450
73609
|
install: (stagedPrefix, portableNode) => {
|
|
73451
73610
|
const env2 = {
|
|
@@ -73456,7 +73615,7 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
73456
73615
|
};
|
|
73457
73616
|
const pathKey = Object.keys(env2).find((key2) => key2.toLowerCase() === "path") || "Path";
|
|
73458
73617
|
env2[pathKey] = `${path20.dirname(portableNode)};${env2[pathKey] || ""}`;
|
|
73459
|
-
(0, import_child_process6.execFileSync)(portableNode, [
|
|
73618
|
+
const installOutput = String((0, import_child_process6.execFileSync)(portableNode, [
|
|
73460
73619
|
options.npmCliPath,
|
|
73461
73620
|
"install",
|
|
73462
73621
|
"-g",
|
|
@@ -73471,7 +73630,8 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
73471
73630
|
maxBuffer: 20 * 1024 * 1024,
|
|
73472
73631
|
windowsHide: true,
|
|
73473
73632
|
env: env2
|
|
73474
|
-
});
|
|
73633
|
+
}));
|
|
73634
|
+
if (installOutput.trim()) options.log(installOutput.trim());
|
|
73475
73635
|
},
|
|
73476
73636
|
restart: (portableNode, stagedCliEntry) => {
|
|
73477
73637
|
const restartArgv = options.restartArgv.map((arg, index) => index === 0 ? stagedCliEntry : arg);
|
|
@@ -73498,28 +73658,12 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
73498
73658
|
child.unref();
|
|
73499
73659
|
},
|
|
73500
73660
|
waitForHealth: async (pid, targetVersion) => {
|
|
73501
|
-
const deadline = Date.now() +
|
|
73661
|
+
const deadline = Date.now() + healthTimeoutMs;
|
|
73502
73662
|
while (Date.now() < deadline) {
|
|
73503
|
-
const
|
|
73504
|
-
|
|
73505
|
-
|
|
73506
|
-
|
|
73507
|
-
res.on("data", (chunk) => {
|
|
73508
|
-
body += chunk;
|
|
73509
|
-
});
|
|
73510
|
-
res.on("end", () => {
|
|
73511
|
-
let responsePid;
|
|
73512
|
-
try {
|
|
73513
|
-
responsePid = Number(JSON.parse(body)?.pid);
|
|
73514
|
-
} catch {
|
|
73515
|
-
}
|
|
73516
|
-
resolve27({ ok: res.statusCode === 200, pid: responsePid, body });
|
|
73517
|
-
});
|
|
73518
|
-
});
|
|
73519
|
-
req.on("timeout", () => req.destroy());
|
|
73520
|
-
req.on("error", () => resolve27({ ok: false }));
|
|
73521
|
-
});
|
|
73522
|
-
if (result.ok && result.pid === pid && result.body?.includes(targetVersion)) return true;
|
|
73663
|
+
const liveness = await fetchLocalHealth(healthPort);
|
|
73664
|
+
const alive = liveness.ok && liveness.pid === pid;
|
|
73665
|
+
const version2 = alive ? await fetchLocalStatusVersion(healthPort) : void 0;
|
|
73666
|
+
if (alive && version2 === targetVersion) return true;
|
|
73523
73667
|
await new Promise((resolve27) => setTimeout(resolve27, 500));
|
|
73524
73668
|
}
|
|
73525
73669
|
return false;
|
|
@@ -73946,22 +74090,31 @@ ${body}
|
|
|
73946
74090
|
`Cannot upgrade: owned processes still running under current prefix: ${preStop.survivors.map((s2) => s2.pid).join(", ")}`
|
|
73947
74091
|
);
|
|
73948
74092
|
}
|
|
73949
|
-
|
|
73950
|
-
|
|
73951
|
-
|
|
73952
|
-
targetVersion: payload.targetVersion,
|
|
73953
|
-
portableNode,
|
|
73954
|
-
excludePids: upgradePids,
|
|
73955
|
-
hooks: createDefaultWindowsAtomicHooks({
|
|
74093
|
+
try {
|
|
74094
|
+
await performWindowsAtomicUpgrade({
|
|
74095
|
+
layout: windowsInstallerLayout,
|
|
73956
74096
|
packageName: payload.packageName,
|
|
73957
74097
|
targetVersion: payload.targetVersion,
|
|
73958
|
-
|
|
73959
|
-
|
|
73960
|
-
|
|
73961
|
-
|
|
73962
|
-
|
|
73963
|
-
|
|
73964
|
-
|
|
74098
|
+
portableNode,
|
|
74099
|
+
excludePids: upgradePids,
|
|
74100
|
+
hooks: createDefaultWindowsAtomicHooks({
|
|
74101
|
+
packageName: payload.packageName,
|
|
74102
|
+
targetVersion: payload.targetVersion,
|
|
74103
|
+
npmCliPath,
|
|
74104
|
+
restartArgv,
|
|
74105
|
+
cwd: payload.cwd || process.cwd(),
|
|
74106
|
+
env: Object.fromEntries(Object.entries(process.env).filter(([key2]) => key2 !== UPGRADE_HELPER_ENV)),
|
|
74107
|
+
log: appendUpgradeLog
|
|
74108
|
+
})
|
|
74109
|
+
});
|
|
74110
|
+
} catch (error48) {
|
|
74111
|
+
emitUpgradeFailureNotice([
|
|
74112
|
+
`adhdev ${payload.packageName}@${payload.targetVersion} upgrade failed and was rolled back: ${error48?.message || String(error48)}`,
|
|
74113
|
+
`Previous version preserved (active prefix: ${windowsInstallerLayout.activePrefix}).`,
|
|
74114
|
+
"See daemon-upgrade.log for the full install/health trace. The next daemon start will retry."
|
|
74115
|
+
]);
|
|
74116
|
+
throw error48;
|
|
74117
|
+
}
|
|
73965
74118
|
try {
|
|
73966
74119
|
fs15.unlinkSync(getUpgradeFailureNoticePath());
|
|
73967
74120
|
} catch {
|
|
@@ -78806,6 +78959,16 @@ ${body}
|
|
|
78806
78959
|
generatingDebounceTimer = null;
|
|
78807
78960
|
generatingDebouncePending = null;
|
|
78808
78961
|
lastApprovalEventFingerprint = "";
|
|
78962
|
+
// INTERACTIVE-PROMPT-PUSH: edge-trigger key for the AskUserQuestion / waiting_choice
|
|
78963
|
+
// notification. An AskUserQuestion prompt is surfaced only as a display-only
|
|
78964
|
+
// `waiting_choice` overlay in getState(); the raw adapter status stays idle/generating,
|
|
78965
|
+
// so detectStatusTransition()'s status-keyed arms never fire and no push-worthy
|
|
78966
|
+
// agent:* event is emitted — the owner misses the "ACTION REQUIRED" prompt when the
|
|
78967
|
+
// app is backgrounded. We emit one agent:waiting_approval on ENTRY into the prompt
|
|
78968
|
+
// state (reusing the existing server push path, no cloud change) and dedupe on this
|
|
78969
|
+
// key so repeated status ticks with the same prompt do not re-fire. '' means no
|
|
78970
|
+
// prompt is currently active (cleared when the prompt is answered/gone).
|
|
78971
|
+
lastInteractivePromptEventKey = "";
|
|
78809
78972
|
autoApproveBusy = false;
|
|
78810
78973
|
autoApproveBusyTimer = null;
|
|
78811
78974
|
lastAutoApprovalSignature = "";
|
|
@@ -81176,6 +81339,25 @@ ${buttons.join("\n")}`;
|
|
|
81176
81339
|
}
|
|
81177
81340
|
this.lastStatus = newStatus;
|
|
81178
81341
|
}
|
|
81342
|
+
const interactivePrompt = adapterStatus.activeInteractivePrompt ?? null;
|
|
81343
|
+
if (interactivePrompt && newStatus !== "waiting_approval") {
|
|
81344
|
+
const firstQuestion = interactivePrompt.questions?.[0];
|
|
81345
|
+
const promptKey = `${interactivePrompt.promptId}::${firstQuestion?.question ?? ""}`;
|
|
81346
|
+
if (promptKey !== this.lastInteractivePromptEventKey) {
|
|
81347
|
+
this.lastInteractivePromptEventKey = promptKey;
|
|
81348
|
+
const modalMessage = firstQuestion ? firstQuestion.header ? `${firstQuestion.header}: ${firstQuestion.question}` : firstQuestion.question : void 0;
|
|
81349
|
+
const modalButtons = firstQuestion?.options?.map((option) => option.label);
|
|
81350
|
+
this.pushEvent({
|
|
81351
|
+
event: "agent:waiting_approval",
|
|
81352
|
+
chatTitle,
|
|
81353
|
+
timestamp: now,
|
|
81354
|
+
modalMessage,
|
|
81355
|
+
modalButtons
|
|
81356
|
+
});
|
|
81357
|
+
}
|
|
81358
|
+
} else if (!interactivePrompt && this.lastInteractivePromptEventKey) {
|
|
81359
|
+
this.lastInteractivePromptEventKey = "";
|
|
81360
|
+
}
|
|
81179
81361
|
const firstTurnStartedAt = typeof this.adapter?.currentTurnStartedAt === "number" ? this.adapter.currentTurnStartedAt : 0;
|
|
81180
81362
|
const collapsedAt = this.startupGraceCollapseAt;
|
|
81181
81363
|
const turnStartedWithinCollapseWindow = collapsedAt !== null && firstTurnStartedAt > 0 && firstTurnStartedAt >= collapsedAt && firstTurnStartedAt - collapsedAt < STARTUP_GRACE_IDLE_COLLAPSE_WINDOW_MS;
|
|
@@ -90604,7 +90786,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
90604
90786
|
const buildOperatingNotesBestEffort = async (id) => {
|
|
90605
90787
|
try {
|
|
90606
90788
|
const { readOperatingNotes: readOperatingNotes2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
90607
|
-
const noteEntries = readOperatingNotes2(id, { tail:
|
|
90789
|
+
const noteEntries = readOperatingNotes2(id, { tail: 100 });
|
|
90608
90790
|
const notes = noteEntries.map((e) => {
|
|
90609
90791
|
const p = e.payload || {};
|
|
90610
90792
|
const text = typeof p.text === "string" ? p.text.trim() : "";
|
|
@@ -90619,7 +90801,13 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
|
|
|
90619
90801
|
// injection-side selection can honor them. Legacy notes lack
|
|
90620
90802
|
// these → pinned defaults false, expiry governed by category TTL.
|
|
90621
90803
|
pinned: p.pinned === true,
|
|
90622
|
-
...typeof p.expiresAt === "string" ? { expiresAt: p.expiresAt } : {}
|
|
90804
|
+
...typeof p.expiresAt === "string" ? { expiresAt: p.expiresAt } : {},
|
|
90805
|
+
// Phase 2 (b)/(c): thread the ledger id + supersedes/subjectKey
|
|
90806
|
+
// so version-supersede targeting and same-class folding work.
|
|
90807
|
+
// Legacy notes lack them → no supersede, fold by leading [tag].
|
|
90808
|
+
noteId: e.id,
|
|
90809
|
+
...typeof p.supersedes === "string" ? { supersedes: p.supersedes } : {},
|
|
90810
|
+
...typeof p.subjectKey === "string" ? { subjectKey: p.subjectKey } : {}
|
|
90623
90811
|
};
|
|
90624
90812
|
}).filter((n) => n !== null);
|
|
90625
90813
|
return notes.length ? notes : void 0;
|