@adhdev/daemon-standalone 1.0.18-rc.7 → 1.0.18-rc.8

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 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 ? "068ae7b54eceb85bb9843d2c7654c3d4687fce75" : void 0) ?? "unknown";
30269
- const commitShort = readInjected(true ? "068ae7b5" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30270
- const version2 = readInjected(true ? "1.0.18-rc.7" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30271
- const builtAt = readInjected(true ? "2026-07-22T02:35:12.533Z" : void 0);
30268
+ const commit = readInjected(true ? "ebf45e12869e32286272a11046f70914784f3f04" : void 0) ?? "unknown";
30269
+ const commitShort = readInjected(true ? "ebf45e12" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
30270
+ const version2 = readInjected(true ? "1.0.18-rc.8" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
30271
+ const builtAt = readInjected(true ? "2026-07-22T04:23:14.120Z" : 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 selectOperatingNotesForPrompt(notes, now, cap = OPERATING_NOTES_PROMPT_CAP) {
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
- const kept = valid.map((note, index) => ({ note, index })).filter(({ note }) => note.pinned || !isNoteExpired(note, now));
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 omittedCount = Math.max(0, kept.length - cap);
39792
- const shown = (omittedCount > 0 ? kept.slice(0, cap) : kept).map((k) => k.note);
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 buildOperatingNotesSection(notes, now = Date.now()) {
39796
- const hasAny = Array.isArray(notes) ? notes.some((n) => n && typeof n.text === "string" && n.text.trim()) : false;
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 n of shown) {
39809
- const pin = n.pinned ? "\u{1F4CC} " : "";
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-and-unpinned notes are also hidden from this list but retained for audit; prune with \`mesh_forget_note\`)._`);
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) {
@@ -78806,6 +78885,16 @@ ${body}
78806
78885
  generatingDebounceTimer = null;
78807
78886
  generatingDebouncePending = null;
78808
78887
  lastApprovalEventFingerprint = "";
78888
+ // INTERACTIVE-PROMPT-PUSH: edge-trigger key for the AskUserQuestion / waiting_choice
78889
+ // notification. An AskUserQuestion prompt is surfaced only as a display-only
78890
+ // `waiting_choice` overlay in getState(); the raw adapter status stays idle/generating,
78891
+ // so detectStatusTransition()'s status-keyed arms never fire and no push-worthy
78892
+ // agent:* event is emitted — the owner misses the "ACTION REQUIRED" prompt when the
78893
+ // app is backgrounded. We emit one agent:waiting_approval on ENTRY into the prompt
78894
+ // state (reusing the existing server push path, no cloud change) and dedupe on this
78895
+ // key so repeated status ticks with the same prompt do not re-fire. '' means no
78896
+ // prompt is currently active (cleared when the prompt is answered/gone).
78897
+ lastInteractivePromptEventKey = "";
78809
78898
  autoApproveBusy = false;
78810
78899
  autoApproveBusyTimer = null;
78811
78900
  lastAutoApprovalSignature = "";
@@ -81176,6 +81265,25 @@ ${buttons.join("\n")}`;
81176
81265
  }
81177
81266
  this.lastStatus = newStatus;
81178
81267
  }
81268
+ const interactivePrompt = adapterStatus.activeInteractivePrompt ?? null;
81269
+ if (interactivePrompt && newStatus !== "waiting_approval") {
81270
+ const firstQuestion = interactivePrompt.questions?.[0];
81271
+ const promptKey = `${interactivePrompt.promptId}::${firstQuestion?.question ?? ""}`;
81272
+ if (promptKey !== this.lastInteractivePromptEventKey) {
81273
+ this.lastInteractivePromptEventKey = promptKey;
81274
+ const modalMessage = firstQuestion ? firstQuestion.header ? `${firstQuestion.header}: ${firstQuestion.question}` : firstQuestion.question : void 0;
81275
+ const modalButtons = firstQuestion?.options?.map((option) => option.label);
81276
+ this.pushEvent({
81277
+ event: "agent:waiting_approval",
81278
+ chatTitle,
81279
+ timestamp: now,
81280
+ modalMessage,
81281
+ modalButtons
81282
+ });
81283
+ }
81284
+ } else if (!interactivePrompt && this.lastInteractivePromptEventKey) {
81285
+ this.lastInteractivePromptEventKey = "";
81286
+ }
81179
81287
  const firstTurnStartedAt = typeof this.adapter?.currentTurnStartedAt === "number" ? this.adapter.currentTurnStartedAt : 0;
81180
81288
  const collapsedAt = this.startupGraceCollapseAt;
81181
81289
  const turnStartedWithinCollapseWindow = collapsedAt !== null && firstTurnStartedAt > 0 && firstTurnStartedAt >= collapsedAt && firstTurnStartedAt - collapsedAt < STARTUP_GRACE_IDLE_COLLAPSE_WINDOW_MS;
@@ -90604,7 +90712,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
90604
90712
  const buildOperatingNotesBestEffort = async (id) => {
90605
90713
  try {
90606
90714
  const { readOperatingNotes: readOperatingNotes2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
90607
- const noteEntries = readOperatingNotes2(id, { tail: 20 });
90715
+ const noteEntries = readOperatingNotes2(id, { tail: 100 });
90608
90716
  const notes = noteEntries.map((e) => {
90609
90717
  const p = e.payload || {};
90610
90718
  const text = typeof p.text === "string" ? p.text.trim() : "";
@@ -90619,7 +90727,13 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
90619
90727
  // injection-side selection can honor them. Legacy notes lack
90620
90728
  // these → pinned defaults false, expiry governed by category TTL.
90621
90729
  pinned: p.pinned === true,
90622
- ...typeof p.expiresAt === "string" ? { expiresAt: p.expiresAt } : {}
90730
+ ...typeof p.expiresAt === "string" ? { expiresAt: p.expiresAt } : {},
90731
+ // Phase 2 (b)/(c): thread the ledger id + supersedes/subjectKey
90732
+ // so version-supersede targeting and same-class folding work.
90733
+ // Legacy notes lack them → no supersede, fold by leading [tag].
90734
+ noteId: e.id,
90735
+ ...typeof p.supersedes === "string" ? { supersedes: p.supersedes } : {},
90736
+ ...typeof p.subjectKey === "string" ? { subjectKey: p.subjectKey } : {}
90623
90737
  };
90624
90738
  }).filter((n) => n !== null);
90625
90739
  return notes.length ? notes : void 0;