@chendpoc/pi-memory 0.2.4 → 0.3.2

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.
Files changed (164) hide show
  1. package/README.md +92 -43
  2. package/dist/adapters/llm/standalone.js +1 -1
  3. package/dist/cli/init.js +20 -3
  4. package/dist/cli/parseArgs.d.ts +5 -2
  5. package/dist/cli/parseArgs.js +13 -0
  6. package/dist/cli/schedulerSync.d.ts +2 -0
  7. package/dist/cli/schedulerSync.js +26 -0
  8. package/dist/cli/status.d.ts +4 -40
  9. package/dist/cli/status.js +6 -230
  10. package/dist/cli/theme.d.ts +2 -0
  11. package/dist/cli/theme.js +8 -0
  12. package/dist/cli.js +5 -0
  13. package/dist/commands/status.js +2 -2
  14. package/dist/compact/parseMemoryExport.js +2 -1
  15. package/dist/compact/register.js +1 -1
  16. package/dist/compact/runSummary.js +1 -16
  17. package/dist/compact/subagentDelta.js +3 -5
  18. package/dist/consolidate/index.d.ts +1 -0
  19. package/dist/consolidate/index.js +1 -0
  20. package/dist/consolidate/mergeEntries.js +3 -3
  21. package/dist/consolidate/mergeMemoryEntries.d.ts +8 -0
  22. package/dist/consolidate/mergeMemoryEntries.js +23 -0
  23. package/dist/consolidate/mergePrompt.js +2 -2
  24. package/dist/consolidate/mergeWithLlm.js +2 -2
  25. package/dist/consolidate/runJob.d.ts +2 -2
  26. package/dist/consolidate/runJob.js +6 -12
  27. package/dist/consolidate/scheduler.d.ts +2 -2
  28. package/dist/consolidate/scheduler.js +1 -1
  29. package/dist/constants/env.d.ts +1 -0
  30. package/dist/constants/env.js +1 -0
  31. package/dist/constants/paths.d.ts +3 -1
  32. package/dist/constants/paths.js +6 -1
  33. package/dist/extension/createMemoryRuntime.d.ts +3 -0
  34. package/dist/extension/createMemoryRuntime.js +203 -0
  35. package/dist/extension/index.d.ts +2 -0
  36. package/dist/extension/index.js +1 -0
  37. package/dist/extension/lifecycle.d.ts +28 -0
  38. package/dist/extension/lifecycle.js +52 -0
  39. package/dist/extension/messageUtils.d.ts +4 -0
  40. package/dist/extension/messageUtils.js +18 -0
  41. package/dist/extension/types.d.ts +35 -0
  42. package/dist/extension/types.js +1 -0
  43. package/dist/index.d.ts +7 -9
  44. package/dist/index.js +7 -9
  45. package/dist/pi-extension.js +26 -236
  46. package/dist/preflight/episodic.js +13 -30
  47. package/dist/preflight/queryIntent.js +1 -1
  48. package/dist/preflight/render.js +1 -1
  49. package/dist/preflight/strip.d.ts +0 -1
  50. package/dist/preflight/strip.js +0 -24
  51. package/dist/redaction/index.d.ts +4 -0
  52. package/dist/redaction/index.js +3 -0
  53. package/dist/redaction/patterns/constants.d.ts +6 -0
  54. package/dist/redaction/patterns/constants.js +6 -0
  55. package/dist/redaction/patterns/crypto.d.ts +3 -0
  56. package/dist/redaction/patterns/crypto.js +17 -0
  57. package/dist/redaction/patterns/generic.d.ts +3 -0
  58. package/dist/redaction/patterns/generic.js +38 -0
  59. package/dist/redaction/patterns/index.d.ts +16 -0
  60. package/dist/redaction/patterns/index.js +23 -0
  61. package/dist/redaction/patterns/llm.d.ts +3 -0
  62. package/dist/redaction/patterns/llm.js +144 -0
  63. package/dist/redaction/patterns/platform.d.ts +3 -0
  64. package/dist/redaction/patterns/platform.js +87 -0
  65. package/dist/redaction/patterns/types.d.ts +18 -0
  66. package/dist/redaction/patterns/types.js +1 -0
  67. package/dist/redaction/redactText.d.ts +9 -0
  68. package/dist/redaction/redactText.js +31 -0
  69. package/dist/redaction/types.d.ts +19 -0
  70. package/dist/redaction/types.js +1 -0
  71. package/dist/redaction/utils.d.ts +28 -0
  72. package/dist/redaction/utils.js +106 -0
  73. package/dist/scheduler/index.d.ts +3 -0
  74. package/dist/scheduler/index.js +3 -0
  75. package/dist/scheduler/launchd.d.ts +14 -0
  76. package/dist/scheduler/launchd.js +69 -0
  77. package/dist/scheduler/launchdPlist.d.ts +14 -0
  78. package/dist/scheduler/launchdPlist.js +62 -0
  79. package/dist/scheduler/sync.d.ts +36 -0
  80. package/dist/scheduler/sync.js +79 -0
  81. package/dist/shutdown/enqueue.d.ts +1 -1
  82. package/dist/shutdown/enqueue.js +2 -5
  83. package/dist/shutdown/readQueue.js +1 -1
  84. package/dist/shutdown/runDrainJob.js +8 -37
  85. package/dist/shutdown/sessionReader.js +1 -14
  86. package/dist/sidecar/client.d.ts +6 -2
  87. package/dist/sidecar/client.js +49 -14
  88. package/dist/{preflight → sidecar}/queryCache.d.ts +1 -1
  89. package/dist/sidecar/reindexBridge.js +2 -2
  90. package/dist/sidecar/server/server.js +1 -1
  91. package/dist/sidecar/server/vec/chunkQuery.d.ts +4 -0
  92. package/dist/sidecar/server/vec/chunkQuery.js +46 -0
  93. package/dist/sidecar/server/vec/chunkReindex.d.ts +5 -0
  94. package/dist/sidecar/server/vec/chunkReindex.js +40 -0
  95. package/dist/sidecar/server/vec/embeddingCodec.d.ts +2 -0
  96. package/dist/sidecar/server/vec/embeddingCodec.js +6 -0
  97. package/dist/sidecar/server/vec/schema.d.ts +20 -0
  98. package/dist/sidecar/server/vec/schema.js +61 -0
  99. package/dist/sidecar/server/vec/store.d.ts +2 -13
  100. package/dist/sidecar/server/vec/store.js +12 -139
  101. package/dist/sidecar/sidecarManager.js +4 -58
  102. package/dist/sidecar/spawnLock.d.ts +2 -0
  103. package/dist/sidecar/spawnLock.js +57 -0
  104. package/dist/sidecar/syncIndex.d.ts +3 -0
  105. package/dist/sidecar/syncIndex.js +12 -0
  106. package/dist/sidecar/warmup.js +1 -1
  107. package/dist/status/copy.d.ts +2 -0
  108. package/dist/status/copy.js +2 -0
  109. package/dist/status/format.d.ts +7 -0
  110. package/dist/status/format.js +133 -0
  111. package/dist/status/gather.d.ts +2 -0
  112. package/dist/status/gather.js +88 -0
  113. package/dist/status/index.d.ts +4 -0
  114. package/dist/status/index.js +3 -0
  115. package/dist/status/types.d.ts +33 -0
  116. package/dist/status/types.js +1 -0
  117. package/dist/store/consolidatePort.d.ts +11 -0
  118. package/dist/store/consolidatePort.js +1 -0
  119. package/dist/store/index.d.ts +2 -0
  120. package/dist/store/index.js +1 -0
  121. package/dist/store/ingestEntries.d.ts +16 -0
  122. package/dist/store/ingestEntries.js +22 -0
  123. package/dist/{init/workspace.d.ts → store/initWorkspace.d.ts} +1 -1
  124. package/dist/{init/workspace.js → store/initWorkspace.js} +7 -5
  125. package/dist/store/listeners.d.ts +11 -0
  126. package/dist/store/listeners.js +27 -0
  127. package/dist/store/markdown/insert.d.ts +3 -0
  128. package/dist/store/markdown/insert.js +23 -0
  129. package/dist/store/memoryStore.d.ts +9 -22
  130. package/dist/store/memoryStore.js +71 -205
  131. package/dist/store/resolveEntries.d.ts +11 -0
  132. package/dist/store/resolveEntries.js +23 -0
  133. package/dist/store/types.d.ts +0 -1
  134. package/dist/store/writePath.d.ts +20 -0
  135. package/dist/store/writePath.js +123 -0
  136. package/dist/ui/memoryStatusWidget.d.ts +4 -8
  137. package/dist/ui/memoryStatusWidget.js +5 -17
  138. package/dist/utils/async.d.ts +11 -0
  139. package/dist/utils/async.js +24 -0
  140. package/dist/utils/index.d.ts +5 -1
  141. package/dist/utils/index.js +5 -1
  142. package/dist/{ipc/jsonlFramer.d.ts → utils/jsonl.d.ts} +1 -1
  143. package/dist/{ipc/jsonlFramer.js → utils/jsonl.js} +1 -1
  144. package/dist/utils/memory/index.d.ts +10 -0
  145. package/dist/utils/memory/index.js +43 -0
  146. package/dist/utils/paths.d.ts +4 -0
  147. package/dist/utils/paths.js +13 -3
  148. package/dist/utils/scheduler.d.ts +1 -1
  149. package/dist/utils/scheduler.js +6 -6
  150. package/dist/{preflight/session.d.ts → utils/session/index.d.ts} +1 -0
  151. package/dist/{preflight/session.js → utils/session/index.js} +5 -2
  152. package/doc/LAUNCH-KIT.md +229 -0
  153. package/doc/README-zh.md +445 -0
  154. package/doc/ROADMAP-zh.md +114 -0
  155. package/doc/ROADMAP.md +114 -0
  156. package/package.json +16 -4
  157. package/scripts/postinstall.mjs +11 -1
  158. package/templates/com.pi.memory.consolidate.plist.example +41 -0
  159. package/templates/consolidate.cmd.example +15 -0
  160. package/templates/crontab.example +14 -0
  161. package/templates/schtasks.example.txt +34 -0
  162. package/dist/consolidate/entryKey.d.ts +0 -5
  163. package/dist/consolidate/entryKey.js +0 -4
  164. /package/dist/{preflight → sidecar}/queryCache.js +0 -0
@@ -0,0 +1,20 @@
1
+ import type { MarkdownMemoryBackend } from "./backend.js";
2
+ import type { ParsedEntry, ResolvedMemory, StoreMemoryEntry } from "./types.js";
3
+ export type WritePathDeps = {
4
+ backend: MarkdownMemoryBackend;
5
+ memoryFile: string;
6
+ agentDir: string;
7
+ maxLines: number;
8
+ createId: () => string;
9
+ newAutoFilePath: () => string;
10
+ readResolvedUnlocked: () => Promise<ResolvedMemory>;
11
+ };
12
+ export declare function normalizeEntry(entry: StoreMemoryEntry, createId: () => string): StoreMemoryEntry;
13
+ /** Ground Truth ingress gate: normalize → redact → skip if empty. */
14
+ export declare function prepareEntryForWrite(entry: StoreMemoryEntry, createId: () => string): StoreMemoryEntry | null;
15
+ export declare function tryAppendUnlocked(deps: WritePathDeps, entry: StoreMemoryEntry): Promise<boolean>;
16
+ /** Physical write only; entry must already pass prepareEntryForWrite. */
17
+ export declare function appendOneUnlocked(deps: WritePathDeps, entry: StoreMemoryEntry): Promise<void>;
18
+ export declare function appendIfAbsentUnlocked(deps: WritePathDeps, entry: StoreMemoryEntry): Promise<boolean>;
19
+ export declare function appendToOverflowUnlocked(deps: WritePathDeps, entry: StoreMemoryEntry, main: string): Promise<void>;
20
+ export declare function rewriteEntriesUnlocked(deps: WritePathDeps, entries: ParsedEntry[]): Promise<void>;
@@ -0,0 +1,123 @@
1
+ import { isEmptyAfterRedaction, redactText } from "../redaction/redactText.js";
2
+ import { pathBasename } from "../utils/fs.js";
3
+ import { debugMemory } from "../utils/debugLog.js";
4
+ import { formatTimestamp } from "../utils/time.js";
5
+ import { countLines, formatEntryLine, formatSectionHeader } from "./markdown/format.js";
6
+ import { insertEntryIntoMarkdown } from "./markdown/insert.js";
7
+ import { MEMORY_SECTIONS } from "./types.js";
8
+ export function normalizeEntry(entry, createId) {
9
+ return {
10
+ ...entry,
11
+ id: entry.id || createId(),
12
+ timestamp: entry.timestamp || formatTimestamp(),
13
+ };
14
+ }
15
+ /** Ground Truth ingress gate: normalize → redact → skip if empty. */
16
+ export function prepareEntryForWrite(entry, createId) {
17
+ const normalized = normalizeEntry(entry, createId);
18
+ try {
19
+ const result = redactText(normalized.content);
20
+ const prepared = { ...normalized, content: result.text };
21
+ if (isEmptyAfterRedaction(prepared.content)) {
22
+ debugMemory("write", "write_skipped", {
23
+ reason: "redaction_empty",
24
+ entryId: prepared.id,
25
+ });
26
+ return null;
27
+ }
28
+ if (result.mutated) {
29
+ debugMemory("write", "write_redacted", {
30
+ hitCount: result.hitCount,
31
+ secretHits: result.secretHits,
32
+ piiHits: result.piiHits,
33
+ entryId: prepared.id,
34
+ policyVersion: result.policyVersion,
35
+ });
36
+ }
37
+ return prepared;
38
+ }
39
+ catch {
40
+ debugMemory("write", "write_skipped", {
41
+ reason: "redaction_error",
42
+ entryId: normalized.id,
43
+ });
44
+ return null;
45
+ }
46
+ }
47
+ export async function tryAppendUnlocked(deps, entry) {
48
+ const prepared = prepareEntryForWrite(entry, deps.createId);
49
+ if (!prepared)
50
+ return false;
51
+ await appendOneUnlocked(deps, prepared);
52
+ return true;
53
+ }
54
+ /** Physical write only; entry must already pass prepareEntryForWrite. */
55
+ export async function appendOneUnlocked(deps, entry) {
56
+ const main = await deps.backend.readText(deps.memoryFile);
57
+ if (countLines(main) >= deps.maxLines) {
58
+ await appendToOverflowUnlocked(deps, entry, main);
59
+ return;
60
+ }
61
+ const next = insertEntryIntoMarkdown(main, entry);
62
+ if (countLines(next) > deps.maxLines) {
63
+ await appendToOverflowUnlocked(deps, entry, main);
64
+ return;
65
+ }
66
+ await deps.backend.writeText(deps.memoryFile, next);
67
+ }
68
+ export async function appendIfAbsentUnlocked(deps, entry) {
69
+ const prepared = prepareEntryForWrite(entry, deps.createId);
70
+ if (!prepared)
71
+ return false;
72
+ const resolved = await deps.readResolvedUnlocked();
73
+ const exists = resolved.entries.some((item) => item.section === prepared.section && item.content.trim() === prepared.content.trim());
74
+ if (exists)
75
+ return false;
76
+ await appendOneUnlocked(deps, prepared);
77
+ return true;
78
+ }
79
+ export async function appendToOverflowUnlocked(deps, entry, main) {
80
+ const autoFiles = await deps.backend.listAutoFiles(deps.agentDir);
81
+ let targetName = autoFiles.at(-1);
82
+ let targetPath = targetName
83
+ ? deps.backend.autoFilePath(deps.agentDir, targetName)
84
+ : deps.newAutoFilePath();
85
+ if (!targetName) {
86
+ targetName = pathBasename(targetPath);
87
+ await deps.backend.writeText(targetPath, `${formatSectionHeader(entry.section)}\n\n`);
88
+ }
89
+ let overflowContent = await deps.backend.readText(targetPath);
90
+ const line = formatEntryLine(entry);
91
+ overflowContent = overflowContent.trimEnd() + `\n${line}\n`;
92
+ await deps.backend.writeText(targetPath, overflowContent);
93
+ const pointer = `- (overflow) → ${targetName}`;
94
+ if (!main.includes(pointer)) {
95
+ const withPointer = `${main.trimEnd()}\n${pointer}\n`;
96
+ await deps.backend.writeText(deps.memoryFile, withPointer);
97
+ }
98
+ }
99
+ export async function rewriteEntriesUnlocked(deps, entries) {
100
+ const grouped = new Map();
101
+ for (const section of MEMORY_SECTIONS)
102
+ grouped.set(section, []);
103
+ for (const entry of entries) {
104
+ grouped.get(entry.section)?.push(entry);
105
+ }
106
+ const lines = [];
107
+ for (const section of MEMORY_SECTIONS) {
108
+ lines.push(formatSectionHeader(section), "");
109
+ for (const entry of grouped.get(section) ?? []) {
110
+ lines.push(formatEntryLine({
111
+ id: entry.id,
112
+ section: entry.section,
113
+ content: entry.content,
114
+ userAuthored: entry.userAuthored,
115
+ timestamp: entry.timestamp,
116
+ }));
117
+ }
118
+ lines.push("");
119
+ }
120
+ await deps.backend.writeText(deps.memoryFile, `${lines.join("\n").trimEnd()}\n`);
121
+ const autoFiles = await deps.backend.listAutoFiles(deps.agentDir);
122
+ await Promise.all(autoFiles.map((fileName) => deps.backend.deleteAutoFile(deps.backend.autoFilePath(deps.agentDir, fileName))));
123
+ }
@@ -1,19 +1,15 @@
1
1
  import type { Theme } from "@earendil-works/pi-coding-agent";
2
- import type { Component, TUI } from "@earendil-works/pi-tui";
3
- import type { MemoryStatusReport } from "../cli/status.js";
2
+ import type { Component } from "@earendil-works/pi-tui";
3
+ import { type MemoryStatusReport } from "../status/index.js";
4
4
  export type MemoryStatusWidgetState = {
5
5
  report: MemoryStatusReport;
6
6
  expanded: boolean;
7
7
  };
8
8
  export declare class MemoryStatusWidget implements Component {
9
9
  private readonly theme;
10
- private state;
11
- private cachedWidth?;
12
- private cachedLines?;
13
- private version;
14
- private cachedVersion;
10
+ private readonly state;
15
11
  constructor(theme: Theme, state: MemoryStatusWidgetState);
16
12
  invalidate(): void;
17
13
  render(width: number): string[];
18
14
  }
19
- export declare function createMemoryStatusWidget(_tui: TUI, theme: Theme, state: MemoryStatusWidgetState): MemoryStatusWidget;
15
+ export declare function createMemoryStatusWidget(theme: Theme, state: MemoryStatusWidgetState): MemoryStatusWidget;
@@ -1,5 +1,5 @@
1
1
  import { truncateToWidth } from "@earendil-works/pi-tui";
2
- import { formatMemoryStatusSummary, formatMemoryStatusTuiLines, piStatusPalette, } from "../cli/status.js";
2
+ import { MEMORY_STATUS_COLLAPSE_HINT, MEMORY_STATUS_EXPAND_HINT, formatMemoryStatusSummary, formatMemoryStatusTuiLines, piStatusPalette, } from "../status/index.js";
3
3
  function formatHeader(theme, width) {
4
4
  const title = theme.fg("accent", theme.bold("pi-memory status"));
5
5
  const fill = Math.max(0, width - title.length - 2);
@@ -10,26 +10,17 @@ function formatHeader(theme, width) {
10
10
  export class MemoryStatusWidget {
11
11
  theme;
12
12
  state;
13
- cachedWidth;
14
- cachedLines;
15
- version = 0;
16
- cachedVersion = -1;
17
13
  constructor(theme, state) {
18
14
  this.theme = theme;
19
15
  this.state = state;
20
16
  }
21
- invalidate() {
22
- this.cachedLines = undefined;
23
- }
17
+ invalidate() { }
24
18
  render(width) {
25
- if (this.cachedLines && this.cachedWidth === width && this.cachedVersion === this.version) {
26
- return this.cachedLines;
27
- }
28
19
  const palette = piStatusPalette(this.theme);
29
20
  const lines = [];
30
21
  if (!this.state.expanded) {
31
22
  const summary = formatMemoryStatusSummary(this.state.report, palette, (text) => this.theme.fg("accent", text));
32
- const hint = this.theme.fg("dim", " (/memory-status to expand)");
23
+ const hint = this.theme.fg("dim", MEMORY_STATUS_EXPAND_HINT);
33
24
  lines.push(truncateToWidth(`${summary}${hint}`, width));
34
25
  }
35
26
  else {
@@ -37,14 +28,11 @@ export class MemoryStatusWidget {
37
28
  for (const line of formatMemoryStatusTuiLines(this.state.report, palette, this.theme)) {
38
29
  lines.push(truncateToWidth(` ${line}`, width));
39
30
  }
40
- lines.push(truncateToWidth(this.theme.fg("dim", " /memory-status to collapse · /memory-status hide to dismiss"), width));
31
+ lines.push(truncateToWidth(this.theme.fg("dim", MEMORY_STATUS_COLLAPSE_HINT), width));
41
32
  }
42
- this.cachedLines = lines;
43
- this.cachedWidth = width;
44
- this.cachedVersion = this.version;
45
33
  return lines;
46
34
  }
47
35
  }
48
- export function createMemoryStatusWidget(_tui, theme, state) {
36
+ export function createMemoryStatusWidget(theme, state) {
49
37
  return new MemoryStatusWidget(theme, state);
50
38
  }
@@ -0,0 +1,11 @@
1
+ export declare const PREFLIGHT_ABORTED_MESSAGE = "aborted";
2
+ export declare const PREFLIGHT_TIMEOUT_MESSAGE = "preflight timeout";
3
+ /** Throw when `signal` is already aborted (matches legacy preflight fail-fast). */
4
+ export declare function throwIfAborted(signal?: AbortSignal, message?: string): void;
5
+ /**
6
+ * Merge a budget timeout with an optional caller `AbortSignal`.
7
+ * Uses Node built-ins: AbortSignal.timeout + AbortSignal.any.
8
+ */
9
+ export declare function mergeAbortSignals(timeoutMs: number, userSignal?: AbortSignal): AbortSignal;
10
+ /** Preflight budget + extension cancel. Alias for {@link mergeAbortSignals}. */
11
+ export declare function preflightAbortSignal(budgetMs: number, userSignal?: AbortSignal): AbortSignal;
@@ -0,0 +1,24 @@
1
+ export const PREFLIGHT_ABORTED_MESSAGE = "aborted";
2
+ export const PREFLIGHT_TIMEOUT_MESSAGE = "preflight timeout";
3
+ /** Throw when `signal` is already aborted (matches legacy preflight fail-fast). */
4
+ export function throwIfAborted(signal, message = PREFLIGHT_ABORTED_MESSAGE) {
5
+ if (signal?.aborted) {
6
+ throw new Error(message);
7
+ }
8
+ }
9
+ /**
10
+ * Merge a budget timeout with an optional caller `AbortSignal`.
11
+ * Uses Node built-ins: AbortSignal.timeout + AbortSignal.any.
12
+ */
13
+ export function mergeAbortSignals(timeoutMs, userSignal) {
14
+ throwIfAborted(userSignal);
15
+ if (timeoutMs <= 0) {
16
+ throw new Error(PREFLIGHT_TIMEOUT_MESSAGE);
17
+ }
18
+ const timeout = AbortSignal.timeout(timeoutMs);
19
+ return userSignal ? AbortSignal.any([timeout, userSignal]) : timeout;
20
+ }
21
+ /** Preflight budget + extension cancel. Alias for {@link mergeAbortSignals}. */
22
+ export function preflightAbortSignal(budgetMs, userSignal) {
23
+ return mergeAbortSignals(budgetMs, userSignal);
24
+ }
@@ -1,7 +1,11 @@
1
1
  export { getPlatform, isMacOS, isUnixLike, isWindows, type PiMemoryPlatform, } from "./platform.js";
2
- export { CONFIG_DIR_NAME, defaultMemoryAgentDir, defaultPiConfigDir, defaultPiMemoryEnvFile, defaultPiLogsDir, expandHomePath, getAgentDir, mkdirOptions, secureDirMode, secureFileMode, } from "./paths.js";
2
+ export { CONFIG_DIR_NAME, defaultConsolidateErrLogPath, defaultConsolidateLogPath, defaultMemoryAgentDir, defaultPiConfigDir, defaultPiMemoryEnvFile, defaultPiLogsDir, expandHomePath, getAgentDir, mkdirOptions, resolveConsolidateErrLogPath, resolveConsolidateLogPath, resolvePiLogsDir, secureDirMode, secureFileMode, } from "./paths.js";
3
3
  export { appendText, canRead, ensureDir, ensureDirSync, ensureFile, isENOENT, joinPath, listDir, pathBasename, pathDirname, pathExists, readText, readTextRequired, removeFile, writeText, } from "./fs.js";
4
4
  export { cleanupSocketFiles, removeSocketFile, secureSocketPath } from "./socket.js";
5
5
  export { debugMemory, isMemoryDebugEnabled } from "./debugLog.js";
6
6
  export { daysSince, epochTimestamp, formatLocalDate, formatTimestamp, now, nowMs, parseTime, remainingMs, type TimeInput, } from "./time.js";
7
7
  export { buildConsolidateCliArgs, buildMaintenanceCliArgs, defaultConsolidateSchedulerPaths, formatConsolidateCronLine, formatMaintenanceCronLine, getConsolidateSchedulerKind, getConsolidateTemplateNames, type ConsolidateCliInvocation, type ConsolidateSchedulerKind, type ConsolidateSchedulerPaths, type ConsolidateTemplateName, } from "./scheduler.js";
8
+ export { mergeAbortSignals, preflightAbortSignal, PREFLIGHT_ABORTED_MESSAGE, PREFLIGHT_TIMEOUT_MESSAGE, throwIfAborted, } from "./async.js";
9
+ export { JsonlFramer, parseJsonlLine, serializeJsonlFrame } from "./jsonl.js";
10
+ export { entryDedupeKey, stripPrivateMemory, stripPrivateMemoryFromMessages } from "./memory/index.js";
11
+ export { isSubagentSession, readParentSession } from "./session/index.js";
@@ -1,7 +1,11 @@
1
1
  export { getPlatform, isMacOS, isUnixLike, isWindows, } from "./platform.js";
2
- export { CONFIG_DIR_NAME, defaultMemoryAgentDir, defaultPiConfigDir, defaultPiMemoryEnvFile, defaultPiLogsDir, expandHomePath, getAgentDir, mkdirOptions, secureDirMode, secureFileMode, } from "./paths.js";
2
+ export { CONFIG_DIR_NAME, defaultConsolidateErrLogPath, defaultConsolidateLogPath, defaultMemoryAgentDir, defaultPiConfigDir, defaultPiMemoryEnvFile, defaultPiLogsDir, expandHomePath, getAgentDir, mkdirOptions, resolveConsolidateErrLogPath, resolveConsolidateLogPath, resolvePiLogsDir, secureDirMode, secureFileMode, } from "./paths.js";
3
3
  export { appendText, canRead, ensureDir, ensureDirSync, ensureFile, isENOENT, joinPath, listDir, pathBasename, pathDirname, pathExists, readText, readTextRequired, removeFile, writeText, } from "./fs.js";
4
4
  export { cleanupSocketFiles, removeSocketFile, secureSocketPath } from "./socket.js";
5
5
  export { debugMemory, isMemoryDebugEnabled } from "./debugLog.js";
6
6
  export { daysSince, epochTimestamp, formatLocalDate, formatTimestamp, now, nowMs, parseTime, remainingMs, } from "./time.js";
7
7
  export { buildConsolidateCliArgs, buildMaintenanceCliArgs, defaultConsolidateSchedulerPaths, formatConsolidateCronLine, formatMaintenanceCronLine, getConsolidateSchedulerKind, getConsolidateTemplateNames, } from "./scheduler.js";
8
+ export { mergeAbortSignals, preflightAbortSignal, PREFLIGHT_ABORTED_MESSAGE, PREFLIGHT_TIMEOUT_MESSAGE, throwIfAborted, } from "./async.js";
9
+ export { JsonlFramer, parseJsonlLine, serializeJsonlFrame } from "./jsonl.js";
10
+ export { entryDedupeKey, stripPrivateMemory, stripPrivateMemoryFromMessages } from "./memory/index.js";
11
+ export { isSubagentSession, readParentSession } from "./session/index.js";
@@ -1,4 +1,4 @@
1
- /** Incremental JSONL (one JSON object per line) framing for UDS IPC. */
1
+ /** Incremental JSONL (one JSON object per line) framing for UDS IPC and queue files. */
2
2
  export declare class JsonlFramer {
3
3
  private buffer;
4
4
  push(chunk: string): string[];
@@ -1,4 +1,4 @@
1
- /** Incremental JSONL (one JSON object per line) framing for UDS IPC. */
1
+ /** Incremental JSONL (one JSON object per line) framing for UDS IPC and queue files. */
2
2
  export class JsonlFramer {
3
3
  buffer = "";
4
4
  push(chunk) {
@@ -0,0 +1,10 @@
1
+ import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
+ /** Stable dedupe key for memory entries (section + trimmed content). */
3
+ export declare function entryDedupeKey(entry: {
4
+ section: string;
5
+ content: string;
6
+ }): string;
7
+ /** Remove `<private_memory>...</private_memory>` blocks from plain text. */
8
+ export declare function stripPrivateMemory(text: string): string;
9
+ /** Strip private memory tags from user message text blocks before compaction or drain. */
10
+ export declare function stripPrivateMemoryFromMessages(messages: AgentMessage[]): AgentMessage[];
@@ -0,0 +1,43 @@
1
+ import { PRIVATE_MEMORY_CLOSE, PRIVATE_MEMORY_OPEN } from "../../constants/preflight.js";
2
+ /** Stable dedupe key for memory entries (section + trimmed content). */
3
+ export function entryDedupeKey(entry) {
4
+ return `${entry.section}\0${entry.content.trim()}`;
5
+ }
6
+ /** Remove `<private_memory>...</private_memory>` blocks from plain text. */
7
+ export function stripPrivateMemory(text) {
8
+ let s = text;
9
+ for (;;) {
10
+ const i = s.indexOf(PRIVATE_MEMORY_OPEN);
11
+ if (i < 0)
12
+ return s;
13
+ const rel = s.indexOf(PRIVATE_MEMORY_CLOSE, i);
14
+ if (rel < 0)
15
+ return s;
16
+ let end = rel + PRIVATE_MEMORY_CLOSE.length;
17
+ while (end < s.length && /[\n\r \t]/.test(s[end]))
18
+ end++;
19
+ let start = i;
20
+ while (start > 0 && /[ \t]/.test(s[start - 1]))
21
+ start--;
22
+ if (start > 0 && s[start - 1] === "\n") {
23
+ start--;
24
+ if (start > 0 && s[start - 1] === "\r")
25
+ start--;
26
+ }
27
+ s = s.slice(0, start) + s.slice(end);
28
+ }
29
+ }
30
+ /** Strip private memory tags from user message text blocks before compaction or drain. */
31
+ export function stripPrivateMemoryFromMessages(messages) {
32
+ return messages.map((message) => {
33
+ if (message.role !== "user")
34
+ return message;
35
+ if (typeof message.content === "string") {
36
+ return { ...message, content: stripPrivateMemory(message.content) };
37
+ }
38
+ return {
39
+ ...message,
40
+ content: message.content.map((block) => block.type === "text" ? { ...block, text: stripPrivateMemory(block.text) } : block),
41
+ };
42
+ });
43
+ }
@@ -8,8 +8,12 @@ export declare function defaultPiConfigDir(): string;
8
8
  export declare function defaultMemoryAgentDir(): string;
9
9
  /** pi-memory config: ~/.pi/agent/pi-memory.env */
10
10
  export declare function defaultPiMemoryEnvFile(): string;
11
+ /** Maintenance logs live under the memory agent dir (`<agentDir>/logs`). */
12
+ export declare function resolvePiLogsDir(agentDir: string): string;
11
13
  export declare function defaultPiLogsDir(): string;
14
+ export declare function resolveConsolidateLogPath(agentDir: string): string;
12
15
  export declare function defaultConsolidateLogPath(): string;
16
+ export declare function resolveConsolidateErrLogPath(agentDir: string): string;
13
17
  export declare function defaultConsolidateErrLogPath(): string;
14
18
  /** Directory mode for agent / socket parent dirs (Unix only; ignored on Windows). */
15
19
  export declare function secureDirMode(): number | undefined;
@@ -27,14 +27,24 @@ export function defaultMemoryAgentDir() {
27
27
  export function defaultPiMemoryEnvFile() {
28
28
  return join(getAgentDir(), PI_MEMORY_ENV_FILE_NAME);
29
29
  }
30
+ /** Maintenance logs live under the memory agent dir (`<agentDir>/logs`). */
31
+ export function resolvePiLogsDir(agentDir) {
32
+ return join(agentDir, PI_LOGS_SUBDIR);
33
+ }
30
34
  export function defaultPiLogsDir() {
31
- return join(defaultPiConfigDir(), PI_LOGS_SUBDIR);
35
+ return resolvePiLogsDir(defaultMemoryAgentDir());
36
+ }
37
+ export function resolveConsolidateLogPath(agentDir) {
38
+ return join(resolvePiLogsDir(agentDir), CONSOLIDATE_LOG_FILE);
32
39
  }
33
40
  export function defaultConsolidateLogPath() {
34
- return join(defaultPiLogsDir(), CONSOLIDATE_LOG_FILE);
41
+ return resolveConsolidateLogPath(defaultMemoryAgentDir());
42
+ }
43
+ export function resolveConsolidateErrLogPath(agentDir) {
44
+ return join(resolvePiLogsDir(agentDir), CONSOLIDATE_ERR_LOG_FILE);
35
45
  }
36
46
  export function defaultConsolidateErrLogPath() {
37
- return join(defaultPiLogsDir(), CONSOLIDATE_ERR_LOG_FILE);
47
+ return resolveConsolidateErrLogPath(defaultMemoryAgentDir());
38
48
  }
39
49
  /** Directory mode for agent / socket parent dirs (Unix only; ignored on Windows). */
40
50
  export function secureDirMode() {
@@ -10,7 +10,7 @@ export type ConsolidateSchedulerPaths = {
10
10
  stdoutLog: string;
11
11
  stderrLog: string;
12
12
  };
13
- export declare function defaultConsolidateSchedulerPaths(): ConsolidateSchedulerPaths;
13
+ export declare function defaultConsolidateSchedulerPaths(agentDir?: string): ConsolidateSchedulerPaths;
14
14
  export type ConsolidateCliInvocation = {
15
15
  nodePath: string;
16
16
  cliPath: string;
@@ -1,5 +1,5 @@
1
1
  import { LAUNCHD_LABEL, SCHEDULER_TEMPLATE_FILES, SCHTASKS_TASK_NAME, } from "../constants/paths.js";
2
- import { defaultConsolidateErrLogPath, defaultConsolidateLogPath, defaultMemoryAgentDir, defaultPiMemoryEnvFile, defaultPiLogsDir, } from "./paths.js";
2
+ import { defaultMemoryAgentDir, defaultPiMemoryEnvFile, resolveConsolidateErrLogPath, resolveConsolidateLogPath, resolvePiLogsDir, } from "./paths.js";
3
3
  import { getPlatform, isMacOS, isWindows } from "./platform.js";
4
4
  /** Recommended OS scheduler for daily consolidate on this platform. */
5
5
  export function getConsolidateSchedulerKind(platform = getPlatform()) {
@@ -9,13 +9,13 @@ export function getConsolidateSchedulerKind(platform = getPlatform()) {
9
9
  return "schtasks";
10
10
  return "crontab";
11
11
  }
12
- export function defaultConsolidateSchedulerPaths() {
12
+ export function defaultConsolidateSchedulerPaths(agentDir = defaultMemoryAgentDir()) {
13
13
  return {
14
- agentDir: defaultMemoryAgentDir(),
14
+ agentDir,
15
15
  envFile: defaultPiMemoryEnvFile(),
16
- logsDir: defaultPiLogsDir(),
17
- stdoutLog: defaultConsolidateLogPath(),
18
- stderrLog: defaultConsolidateErrLogPath(),
16
+ logsDir: resolvePiLogsDir(agentDir),
17
+ stdoutLog: resolveConsolidateLogPath(agentDir),
18
+ stderrLog: resolveConsolidateErrLogPath(agentDir),
19
19
  };
20
20
  }
21
21
  /** argv for `pi-memory maintenance` (OS scheduler / wrapper scripts). */
@@ -1,2 +1,3 @@
1
1
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ export declare function readParentSession(header: Record<string, unknown> | null): string | undefined;
2
3
  export declare function isSubagentSession(ctx: ExtensionContext): boolean;
@@ -1,5 +1,8 @@
1
+ export function readParentSession(header) {
2
+ const parent = header?.parentSession ?? header?.parent_session;
3
+ return typeof parent === "string" && parent.trim().length > 0 ? parent.trim() : undefined;
4
+ }
1
5
  export function isSubagentSession(ctx) {
2
6
  const header = ctx.sessionManager.getHeader();
3
- const parent = header?.parentSession ?? header?.parent_session;
4
- return typeof parent === "string" && parent.trim().length > 0;
7
+ return readParentSession(header) !== undefined;
5
8
  }