@chendpoc/pi-memory 0.2.3 → 0.3.1
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/README.md +92 -43
- package/dist/adapters/llm/standalone.js +1 -1
- package/dist/cli/init.js +20 -3
- package/dist/cli/parseArgs.d.ts +5 -2
- package/dist/cli/parseArgs.js +13 -0
- package/dist/cli/schedulerSync.d.ts +2 -0
- package/dist/cli/schedulerSync.js +26 -0
- package/dist/cli/status.d.ts +4 -40
- package/dist/cli/status.js +6 -230
- package/dist/cli/theme.d.ts +2 -0
- package/dist/cli/theme.js +8 -0
- package/dist/cli.js +5 -0
- package/dist/commands/status.js +2 -2
- package/dist/compact/parseMemoryExport.js +2 -1
- package/dist/compact/register.js +1 -1
- package/dist/compact/runSummary.js +1 -16
- package/dist/compact/subagentDelta.js +3 -5
- package/dist/consolidate/index.d.ts +1 -0
- package/dist/consolidate/index.js +1 -0
- package/dist/consolidate/mergeEntries.js +3 -3
- package/dist/consolidate/mergeMemoryEntries.d.ts +8 -0
- package/dist/consolidate/mergeMemoryEntries.js +23 -0
- package/dist/consolidate/mergePrompt.js +2 -2
- package/dist/consolidate/mergeWithLlm.js +2 -2
- package/dist/consolidate/runJob.d.ts +2 -2
- package/dist/consolidate/runJob.js +6 -12
- package/dist/consolidate/scheduler.d.ts +2 -2
- package/dist/consolidate/scheduler.js +1 -1
- package/dist/constants/env.d.ts +1 -0
- package/dist/constants/env.js +1 -0
- package/dist/constants/paths.d.ts +3 -1
- package/dist/constants/paths.js +6 -1
- package/dist/extension/createMemoryRuntime.d.ts +3 -0
- package/dist/extension/createMemoryRuntime.js +203 -0
- package/dist/extension/index.d.ts +2 -0
- package/dist/extension/index.js +1 -0
- package/dist/extension/lifecycle.d.ts +28 -0
- package/dist/extension/lifecycle.js +52 -0
- package/dist/extension/messageUtils.d.ts +4 -0
- package/dist/extension/messageUtils.js +18 -0
- package/dist/extension/types.d.ts +35 -0
- package/dist/extension/types.js +1 -0
- package/dist/index.d.ts +7 -9
- package/dist/index.js +7 -9
- package/dist/pi-extension.js +26 -236
- package/dist/preflight/episodic.js +13 -30
- package/dist/preflight/queryIntent.js +1 -1
- package/dist/preflight/render.js +1 -1
- package/dist/preflight/strip.d.ts +0 -1
- package/dist/preflight/strip.js +0 -24
- package/dist/redaction/index.d.ts +4 -0
- package/dist/redaction/index.js +3 -0
- package/dist/redaction/patterns/constants.d.ts +6 -0
- package/dist/redaction/patterns/constants.js +6 -0
- package/dist/redaction/patterns/crypto.d.ts +3 -0
- package/dist/redaction/patterns/crypto.js +17 -0
- package/dist/redaction/patterns/generic.d.ts +3 -0
- package/dist/redaction/patterns/generic.js +38 -0
- package/dist/redaction/patterns/index.d.ts +16 -0
- package/dist/redaction/patterns/index.js +23 -0
- package/dist/redaction/patterns/llm.d.ts +3 -0
- package/dist/redaction/patterns/llm.js +144 -0
- package/dist/redaction/patterns/platform.d.ts +3 -0
- package/dist/redaction/patterns/platform.js +87 -0
- package/dist/redaction/patterns/types.d.ts +18 -0
- package/dist/redaction/patterns/types.js +1 -0
- package/dist/redaction/redactText.d.ts +9 -0
- package/dist/redaction/redactText.js +31 -0
- package/dist/redaction/types.d.ts +19 -0
- package/dist/redaction/types.js +1 -0
- package/dist/redaction/utils.d.ts +28 -0
- package/dist/redaction/utils.js +106 -0
- package/dist/scheduler/index.d.ts +3 -0
- package/dist/scheduler/index.js +3 -0
- package/dist/scheduler/launchd.d.ts +14 -0
- package/dist/scheduler/launchd.js +69 -0
- package/dist/scheduler/launchdPlist.d.ts +14 -0
- package/dist/scheduler/launchdPlist.js +62 -0
- package/dist/scheduler/sync.d.ts +36 -0
- package/dist/scheduler/sync.js +79 -0
- package/dist/shutdown/enqueue.d.ts +1 -1
- package/dist/shutdown/enqueue.js +2 -5
- package/dist/shutdown/readQueue.js +1 -1
- package/dist/shutdown/runDrainJob.js +8 -37
- package/dist/shutdown/sessionReader.js +1 -14
- package/dist/sidecar/client.d.ts +6 -2
- package/dist/sidecar/client.js +49 -14
- package/dist/{preflight → sidecar}/queryCache.d.ts +1 -1
- package/dist/sidecar/reindexBridge.js +2 -2
- package/dist/sidecar/server/server.js +1 -1
- package/dist/sidecar/server/vec/chunkQuery.d.ts +4 -0
- package/dist/sidecar/server/vec/chunkQuery.js +46 -0
- package/dist/sidecar/server/vec/chunkReindex.d.ts +5 -0
- package/dist/sidecar/server/vec/chunkReindex.js +40 -0
- package/dist/sidecar/server/vec/embeddingCodec.d.ts +2 -0
- package/dist/sidecar/server/vec/embeddingCodec.js +6 -0
- package/dist/sidecar/server/vec/schema.d.ts +20 -0
- package/dist/sidecar/server/vec/schema.js +61 -0
- package/dist/sidecar/server/vec/store.d.ts +2 -13
- package/dist/sidecar/server/vec/store.js +12 -139
- package/dist/sidecar/sidecarManager.js +4 -58
- package/dist/sidecar/spawnLock.d.ts +2 -0
- package/dist/sidecar/spawnLock.js +57 -0
- package/dist/sidecar/syncIndex.d.ts +3 -0
- package/dist/sidecar/syncIndex.js +12 -0
- package/dist/sidecar/warmup.js +1 -1
- package/dist/status/copy.d.ts +2 -0
- package/dist/status/copy.js +2 -0
- package/dist/status/format.d.ts +7 -0
- package/dist/status/format.js +133 -0
- package/dist/status/gather.d.ts +2 -0
- package/dist/status/gather.js +88 -0
- package/dist/status/index.d.ts +4 -0
- package/dist/status/index.js +3 -0
- package/dist/status/types.d.ts +33 -0
- package/dist/status/types.js +1 -0
- package/dist/store/consolidatePort.d.ts +11 -0
- package/dist/store/consolidatePort.js +1 -0
- package/dist/store/index.d.ts +2 -0
- package/dist/store/index.js +1 -0
- package/dist/store/ingestEntries.d.ts +16 -0
- package/dist/store/ingestEntries.js +22 -0
- package/dist/{init/workspace.d.ts → store/initWorkspace.d.ts} +1 -1
- package/dist/{init/workspace.js → store/initWorkspace.js} +7 -5
- package/dist/store/listeners.d.ts +11 -0
- package/dist/store/listeners.js +27 -0
- package/dist/store/markdown/insert.d.ts +3 -0
- package/dist/store/markdown/insert.js +23 -0
- package/dist/store/memoryStore.d.ts +9 -22
- package/dist/store/memoryStore.js +71 -205
- package/dist/store/resolveEntries.d.ts +11 -0
- package/dist/store/resolveEntries.js +23 -0
- package/dist/store/types.d.ts +0 -1
- package/dist/store/writePath.d.ts +20 -0
- package/dist/store/writePath.js +123 -0
- package/dist/ui/memoryStatusWidget.d.ts +4 -8
- package/dist/ui/memoryStatusWidget.js +5 -17
- package/dist/utils/async.d.ts +11 -0
- package/dist/utils/async.js +24 -0
- package/dist/utils/index.d.ts +5 -1
- package/dist/utils/index.js +5 -1
- package/dist/{ipc/jsonlFramer.d.ts → utils/jsonl.d.ts} +1 -1
- package/dist/{ipc/jsonlFramer.js → utils/jsonl.js} +1 -1
- package/dist/utils/memory/index.d.ts +10 -0
- package/dist/utils/memory/index.js +43 -0
- package/dist/utils/paths.d.ts +4 -0
- package/dist/utils/paths.js +13 -3
- package/dist/utils/scheduler.d.ts +1 -1
- package/dist/utils/scheduler.js +6 -6
- package/dist/{preflight/session.d.ts → utils/session/index.d.ts} +1 -0
- package/dist/{preflight/session.js → utils/session/index.js} +5 -2
- package/doc/README-zh.md +445 -0
- package/package.json +9 -4
- package/scripts/postinstall.mjs +11 -1
- package/templates/com.pi.memory.consolidate.plist.example +41 -0
- package/templates/consolidate.cmd.example +15 -0
- package/templates/crontab.example +14 -0
- package/templates/schtasks.example.txt +34 -0
- package/dist/consolidate/entryKey.d.ts +0 -5
- package/dist/consolidate/entryKey.js +0 -4
- /package/dist/{preflight → sidecar}/queryCache.js +0 -0
package/dist/cli/status.js
CHANGED
|
@@ -1,234 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { getVecStore } from "../sidecar/server/vec/store.js";
|
|
7
|
-
import { createMemoryStore } from "../store/index.js";
|
|
8
|
-
import { pathExists } from "../utils/fs.js";
|
|
9
|
-
import { theme } from "./theme.js";
|
|
10
|
-
const plainPalette = {
|
|
11
|
-
dim: (text) => text,
|
|
12
|
-
ok: (text) => text,
|
|
13
|
-
bad: (text) => text,
|
|
14
|
-
warn: (text) => text,
|
|
15
|
-
};
|
|
16
|
-
export function cliStatusPalette() {
|
|
17
|
-
return {
|
|
18
|
-
dim: theme.dim,
|
|
19
|
-
ok: theme.ok,
|
|
20
|
-
bad: theme.bad,
|
|
21
|
-
warn: theme.warn,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export function piStatusPalette(theme) {
|
|
25
|
-
return {
|
|
26
|
-
dim: (text) => theme.fg("dim", text),
|
|
27
|
-
ok: (text) => theme.fg("success", text),
|
|
28
|
-
bad: (text) => theme.fg("error", text),
|
|
29
|
-
warn: (text) => theme.fg("warning", text),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function applyLocalVecStats(report, dbPath) {
|
|
33
|
-
const vec = getVecStore(dbPath);
|
|
34
|
-
report.vectorIndex.generation = vec.getIndexGeneration();
|
|
35
|
-
report.vectorIndex.chunkCount = vec.getChunkCount();
|
|
36
|
-
const meta = vec.getStoredEmbeddingMeta();
|
|
37
|
-
if (meta) {
|
|
38
|
-
report.vectorIndex.embeddingProvider = meta.provider;
|
|
39
|
-
report.vectorIndex.embeddingModel = meta.model;
|
|
40
|
-
report.vectorIndex.embeddingDim = meta.dim;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
function applySidecarVecStats(report, stats) {
|
|
44
|
-
report.vectorIndex.fromSidecar = true;
|
|
45
|
-
report.vectorIndex.generation = stats.index_generation;
|
|
46
|
-
report.vectorIndex.chunkCount = stats.chunk_count;
|
|
47
|
-
if (stats.embedding_provider && stats.embedding_model && stats.embedding_dim !== undefined) {
|
|
48
|
-
report.vectorIndex.embeddingProvider = stats.embedding_provider;
|
|
49
|
-
report.vectorIndex.embeddingModel = stats.embedding_model;
|
|
50
|
-
report.vectorIndex.embeddingDim = stats.embedding_dim;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
function embedderMatchesIndex(report) {
|
|
54
|
-
const { embeddingProvider, embeddingModel, embeddingDim } = report.vectorIndex;
|
|
55
|
-
if (!embeddingProvider || !embeddingModel || embeddingDim === undefined)
|
|
56
|
-
return true;
|
|
57
|
-
return (embeddingProvider === report.embedder.provider &&
|
|
58
|
-
embeddingModel === report.embedder.model &&
|
|
59
|
-
embeddingDim === report.embedder.dim);
|
|
60
|
-
}
|
|
61
|
-
function resolveConfiguredEmbedder(env) {
|
|
62
|
-
try {
|
|
63
|
-
const embedder = createEmbedder(env);
|
|
64
|
-
return { provider: embedder.provider, model: embedder.model, dim: embedder.dim };
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
const embedModel = env.embedder === "openai"
|
|
68
|
-
? env.openaiEmbedModel
|
|
69
|
-
: env.embedder === "ollama"
|
|
70
|
-
? env.ollamaEmbedModel
|
|
71
|
-
: "hash/dev";
|
|
72
|
-
const dim = env.embedder === "hash"
|
|
73
|
-
? (env.embedDimOverride ?? DEFAULT_HASH_EMBED_DIM)
|
|
74
|
-
: resolveEmbedDim(embedModel, env.embedDimOverride);
|
|
75
|
-
return { provider: env.embedder, model: embedModel, dim };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export async function gatherMemoryStatus(agentDir) {
|
|
79
|
-
const store = createMemoryStore({ agentDir });
|
|
80
|
-
await store.ensureInitialized();
|
|
81
|
-
const sidecar = resolveSidecarPaths(agentDir);
|
|
82
|
-
const env = readPiMemoryEnv();
|
|
83
|
-
const sidecarRunning = await ping(sidecar.socketPath);
|
|
84
|
-
const report = {
|
|
85
|
-
agentDir,
|
|
86
|
-
memory: await store.getStats(),
|
|
87
|
-
sidecar: {
|
|
88
|
-
socketPath: sidecar.socketPath,
|
|
89
|
-
running: sidecarRunning,
|
|
90
|
-
},
|
|
91
|
-
vectorIndex: {
|
|
92
|
-
dbPath: sidecar.dbPath,
|
|
93
|
-
exists: pathExists(sidecar.dbPath),
|
|
94
|
-
},
|
|
95
|
-
embedder: resolveConfiguredEmbedder(env),
|
|
96
|
-
};
|
|
97
|
-
if (!report.vectorIndex.exists)
|
|
98
|
-
return report;
|
|
99
|
-
if (sidecarRunning) {
|
|
100
|
-
const result = await fetchIndexStats(sidecar.socketPath);
|
|
101
|
-
if ("stats" in result) {
|
|
102
|
-
applySidecarVecStats(report, result.stats);
|
|
103
|
-
return report;
|
|
104
|
-
}
|
|
105
|
-
const hint = result.error.includes("unknown frame type")
|
|
106
|
-
? "restart sidecar (reload Pi session or pi-memory)"
|
|
107
|
-
: result.error;
|
|
108
|
-
report.vectorIndex.readError = hint;
|
|
109
|
-
return report;
|
|
110
|
-
}
|
|
111
|
-
try {
|
|
112
|
-
applyLocalVecStats(report, sidecar.dbPath);
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
report.vectorIndex.readError =
|
|
116
|
-
error instanceof Error ? error.message : "unable to open vector index (start sidecar)";
|
|
117
|
-
}
|
|
118
|
-
return report;
|
|
119
|
-
}
|
|
120
|
-
function formatVectorIndexLine(report) {
|
|
121
|
-
const { generation, chunkCount, readError } = report.vectorIndex;
|
|
122
|
-
if (readError) {
|
|
123
|
-
return `(unreadable: ${readError})`;
|
|
124
|
-
}
|
|
125
|
-
if (generation === undefined || chunkCount === undefined) {
|
|
126
|
-
return "(unknown — start sidecar or run pi-memory status again)";
|
|
127
|
-
}
|
|
128
|
-
return `gen=${generation} chunks=${chunkCount}`;
|
|
129
|
-
}
|
|
130
|
-
function formatIndexEmbedderLine(report, palette) {
|
|
131
|
-
const { embeddingProvider, embeddingModel, embeddingDim, chunkCount, readError } = report.vectorIndex;
|
|
132
|
-
if (readError) {
|
|
133
|
-
return palette.dim("(unavailable)");
|
|
134
|
-
}
|
|
135
|
-
if (!embeddingProvider || !embeddingModel || embeddingDim === undefined) {
|
|
136
|
-
if (chunkCount === 0) {
|
|
137
|
-
return palette.dim("(empty — reindex pending)");
|
|
138
|
-
}
|
|
139
|
-
return palette.dim("(no embedding meta — run reindex)");
|
|
140
|
-
}
|
|
141
|
-
const label = `${embeddingProvider}/${embeddingModel} (${embeddingDim}d)`;
|
|
142
|
-
if (embedderMatchesIndex(report)) {
|
|
143
|
-
return label;
|
|
144
|
-
}
|
|
145
|
-
return palette.warn(`${label} ≠ configured`);
|
|
146
|
-
}
|
|
147
|
-
function memoryStatusRows(report, palette = plainPalette) {
|
|
148
|
-
const lastConsolidated = report.memory.lastConsolidatedAt ?? "(never)";
|
|
149
|
-
const sidecarState = report.sidecar.running ? "running" : "not reachable";
|
|
150
|
-
const sidecarDetail = `${sidecarState} (${report.sidecar.socketPath})`;
|
|
151
|
-
const rows = [
|
|
152
|
-
{ label: "agent dir", value: () => report.agentDir },
|
|
153
|
-
{ label: "MEMORY lines", value: () => String(report.memory.lineCount) },
|
|
154
|
-
{ label: "entries", value: () => String(report.memory.entryCount) },
|
|
155
|
-
{ label: "overflow files", value: () => String(report.memory.overflowFileCount) },
|
|
156
|
-
{
|
|
157
|
-
label: "last consolidate",
|
|
158
|
-
value: () => !report.memory.lastConsolidatedAt ? palette.dim(lastConsolidated) : lastConsolidated,
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
label: "sidecar",
|
|
162
|
-
value: () => {
|
|
163
|
-
const state = report.sidecar.running ? palette.ok(sidecarState) : palette.bad(sidecarState);
|
|
164
|
-
return `${state} ${palette.dim(`(${report.sidecar.socketPath})`)}`;
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
];
|
|
168
|
-
if (!report.vectorIndex.exists) {
|
|
169
|
-
rows.push({
|
|
170
|
-
label: "vector index",
|
|
171
|
-
value: () => palette.dim("(missing — write MEMORY or start session)"),
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
rows.push({
|
|
176
|
-
label: "vector index",
|
|
177
|
-
value: () => {
|
|
178
|
-
const line = formatVectorIndexLine(report);
|
|
179
|
-
if (report.vectorIndex.readError)
|
|
180
|
-
return palette.bad(line);
|
|
181
|
-
if (report.vectorIndex.generation === undefined || report.vectorIndex.chunkCount === undefined) {
|
|
182
|
-
return palette.dim(line);
|
|
183
|
-
}
|
|
184
|
-
return line;
|
|
185
|
-
},
|
|
186
|
-
});
|
|
187
|
-
rows.push({
|
|
188
|
-
label: "index embedder",
|
|
189
|
-
value: () => formatIndexEmbedderLine(report, palette),
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
rows.push({
|
|
193
|
-
label: "configured embedder",
|
|
194
|
-
value: () => `${report.embedder.provider}/${report.embedder.model} (${report.embedder.dim}d)`,
|
|
195
|
-
});
|
|
196
|
-
return rows;
|
|
197
|
-
}
|
|
198
|
-
export function formatMemoryStatusSummary(report, palette, accent) {
|
|
199
|
-
const parts = [
|
|
200
|
-
accent("pi-memory"),
|
|
201
|
-
palette.dim(`entries=${report.memory.entryCount}`),
|
|
202
|
-
report.sidecar.running ? palette.ok("sidecar up") : palette.bad("sidecar down"),
|
|
203
|
-
];
|
|
204
|
-
if (!report.vectorIndex.exists) {
|
|
205
|
-
parts.push(palette.dim("no index"));
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
const vec = formatVectorIndexLine(report);
|
|
209
|
-
if (report.vectorIndex.readError) {
|
|
210
|
-
parts.push(palette.bad(vec));
|
|
211
|
-
}
|
|
212
|
-
else if (report.vectorIndex.generation === undefined || report.vectorIndex.chunkCount === undefined) {
|
|
213
|
-
parts.push(palette.dim(vec));
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
parts.push(vec);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return parts.join(palette.dim(" · "));
|
|
220
|
-
}
|
|
221
|
-
export function formatMemoryStatusLines(report) {
|
|
222
|
-
return memoryStatusRows(report).map(({ label, value }) => `${label.padEnd(16)} ${value()}`);
|
|
223
|
-
}
|
|
224
|
-
export function formatMemoryStatusTuiLines(report, palette, theme) {
|
|
225
|
-
return memoryStatusRows(report, palette).map(({ label, value }) => `${theme.fg("muted", label.padEnd(16))} ${value()}`);
|
|
226
|
-
}
|
|
1
|
+
import { cliStatusPalette } from "./theme.js";
|
|
2
|
+
import { printMemoryStatusRows } from "../status/format.js";
|
|
3
|
+
import { gatherMemoryStatus } from "../status/gather.js";
|
|
4
|
+
export { gatherMemoryStatus } from "../status/gather.js";
|
|
5
|
+
export { formatMemoryStatusLines, formatMemoryStatusSummary, formatMemoryStatusTuiLines, piStatusPalette, } from "../status/format.js";
|
|
227
6
|
export function printMemoryStatus(report, log) {
|
|
228
|
-
|
|
229
|
-
for (const { label, value } of memoryStatusRows(report, palette)) {
|
|
230
|
-
log.line(label, value());
|
|
231
|
-
}
|
|
7
|
+
printMemoryStatusRows(report, cliStatusPalette(), (label, value) => log.line(label, value));
|
|
232
8
|
}
|
|
233
9
|
export async function runStatusCommand(agentDir, log) {
|
|
234
10
|
const report = await gatherMemoryStatus(agentDir);
|
package/dist/cli/theme.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { StatusPalette } from "../status/types.js";
|
|
1
2
|
export declare function paint(fn: (text: string) => string, text: string, stream?: NodeJS.WriteStream): string;
|
|
2
3
|
export declare const theme: {
|
|
3
4
|
prefix: (stream?: NodeJS.WriteStream) => string;
|
|
@@ -11,3 +12,4 @@ export declare const theme: {
|
|
|
11
12
|
ok: (text: string, stream?: NodeJS.WriteStream) => string;
|
|
12
13
|
bad: (text: string, stream?: NodeJS.WriteStream) => string;
|
|
13
14
|
};
|
|
15
|
+
export declare function cliStatusPalette(): StatusPalette;
|
package/dist/cli/theme.js
CHANGED
|
@@ -17,3 +17,11 @@ export const theme = {
|
|
|
17
17
|
ok: (text, stream) => paint(chalk.green, text, stream),
|
|
18
18
|
bad: (text, stream) => paint(chalk.red, text, stream),
|
|
19
19
|
};
|
|
20
|
+
export function cliStatusPalette() {
|
|
21
|
+
return {
|
|
22
|
+
dim: theme.dim,
|
|
23
|
+
ok: theme.ok,
|
|
24
|
+
bad: theme.bad,
|
|
25
|
+
warn: theme.warn,
|
|
26
|
+
};
|
|
27
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import { runConsolidateCommand, runDrainShutdownQueueCommand, runMaintenanceComm
|
|
|
6
6
|
import { createCliLog } from "./cli/log.js";
|
|
7
7
|
import { CLI_HELP, parseCliArgs } from "./cli/parseArgs.js";
|
|
8
8
|
import { runInitCommand } from "./cli/init.js";
|
|
9
|
+
import { runSchedulerSyncCommand } from "./cli/schedulerSync.js";
|
|
9
10
|
import { runStatusCommand } from "./cli/status.js";
|
|
10
11
|
import { theme } from "./cli/theme.js";
|
|
11
12
|
import { createMemoryStore } from "./store/index.js";
|
|
@@ -24,6 +25,10 @@ async function main() {
|
|
|
24
25
|
const log = createCliLog({ verbose: true, debug: parsed.options.verbose });
|
|
25
26
|
return runInitCommand(agentDir, log);
|
|
26
27
|
}
|
|
28
|
+
if (parsed.command === "scheduler-sync") {
|
|
29
|
+
const log = createCliLog({ verbose: true, debug: parsed.options.verbose });
|
|
30
|
+
return runSchedulerSyncCommand(agentDir, log);
|
|
31
|
+
}
|
|
27
32
|
if (parsed.command === "status") {
|
|
28
33
|
const log = createCliLog({ verbose: true, debug: parsed.options.verbose });
|
|
29
34
|
return runStatusCommand(agentDir, log);
|
package/dist/commands/status.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { formatMemoryStatusLines, gatherMemoryStatus, } from "../
|
|
1
|
+
import { formatMemoryStatusLines, gatherMemoryStatus, } from "../status/index.js";
|
|
2
2
|
import { resolveMemoryAgentDir } from "../config/agentDir.js";
|
|
3
3
|
import { createMemoryStatusWidget } from "../ui/memoryStatusWidget.js";
|
|
4
4
|
import { parseMemoryStatusArgs } from "./parseMemoryStatusArgs.js";
|
|
@@ -7,7 +7,7 @@ export function resetMemoryStatusWidgetState() {
|
|
|
7
7
|
memoryStatusWidgetState = null;
|
|
8
8
|
}
|
|
9
9
|
function renderMemoryStatusWidget(ctx, state) {
|
|
10
|
-
ctx.ui.setWidget("pi-memory-status", (
|
|
10
|
+
ctx.ui.setWidget("pi-memory-status", (_tui, theme) => createMemoryStatusWidget(theme, state), {
|
|
11
11
|
placement: "aboveEditor",
|
|
12
12
|
});
|
|
13
13
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseMemoryMarkdown } from "../store/markdown/parse.js";
|
|
2
|
+
import { entryDedupeKey } from "../utils/memory/index.js";
|
|
2
3
|
import { MEMORY_SECTIONS } from "../store/types.js";
|
|
3
4
|
const MEMORY_EXPORT_HEADER_RE = /^##\s+Memory Export\s*$/im;
|
|
4
5
|
function extractMemoryExportBlock(summary) {
|
|
@@ -46,7 +47,7 @@ export function parseMemoryExport(summary) {
|
|
|
46
47
|
const entries = parseExportBullets(exportBody);
|
|
47
48
|
const seen = new Set();
|
|
48
49
|
return entries.filter((entry) => {
|
|
49
|
-
const key =
|
|
50
|
+
const key = entryDedupeKey(entry);
|
|
50
51
|
if (seen.has(key))
|
|
51
52
|
return false;
|
|
52
53
|
seen.add(key);
|
package/dist/compact/register.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isSubagentSession } from "../
|
|
1
|
+
import { isSubagentSession } from "../utils/session/index.js";
|
|
2
2
|
import { runDualPurposeCompactionSummary } from "./runSummary.js";
|
|
3
3
|
export function registerCompactHandlers(pi, deps) {
|
|
4
4
|
pi.on("session_before_compact", async (event, ctx) => {
|
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
import { convertToLlm, serializeConversation } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import {
|
|
2
|
+
import { stripPrivateMemoryFromMessages } from "../utils/memory/index.js";
|
|
3
3
|
import { buildCompactionSummaryPrompt } from "./summaryPrompt.js";
|
|
4
|
-
function stripPrivateMemoryFromMessages(messages) {
|
|
5
|
-
return messages.map((message) => {
|
|
6
|
-
if (message.role !== "user")
|
|
7
|
-
return message;
|
|
8
|
-
if (typeof message.content === "string") {
|
|
9
|
-
return { ...message, content: stripPrivateMemory(message.content) };
|
|
10
|
-
}
|
|
11
|
-
return {
|
|
12
|
-
...message,
|
|
13
|
-
content: message.content.map((block) => block.type === "text"
|
|
14
|
-
? { ...block, text: stripPrivateMemory(block.text) }
|
|
15
|
-
: block),
|
|
16
|
-
};
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
4
|
export async function runDualPurposeCompactionSummary(preparation, llm, signal) {
|
|
20
5
|
const allMessages = stripPrivateMemoryFromMessages([
|
|
21
6
|
...preparation.messagesToSummarize,
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
return `${entry.section}\0${entry.content.trim()}`;
|
|
3
|
-
}
|
|
1
|
+
import { entryDedupeKey } from "../utils/memory/index.js";
|
|
4
2
|
/** Keep only Memory Export facts not already present in MEMORY (parent/root dedup). */
|
|
5
3
|
export function filterCompactionDelta(entries, existing) {
|
|
6
|
-
const known = new Set(existing.map(
|
|
7
|
-
return entries.filter((entry) => !known.has(
|
|
4
|
+
const known = new Set(existing.map(entryDedupeKey));
|
|
5
|
+
return entries.filter((entry) => !known.has(entryDedupeKey(entry)));
|
|
8
6
|
}
|
|
9
7
|
/** Subagent clone: summary had export bullets but nothing new vs parent memory. */
|
|
10
8
|
export function shouldSkipSubagentCompactionIngest(parsed, delta) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { dedupeEntries } from "./mergeEntries.js";
|
|
2
2
|
export { mergeEntriesWithLlm } from "./mergeWithLlm.js";
|
|
3
|
+
export { mergeMemoryEntries, scheduleMergeMemoryEntriesInBackground, } from "./mergeMemoryEntries.js";
|
|
3
4
|
export { runConsolidateJob, type RunConsolidateJobOptions, type RunConsolidateJobResult } from "./runJob.js";
|
|
4
5
|
export { createConsolidateScheduler, startConsolidateInterval, type ConsolidateScheduler } from "./scheduler.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { dedupeEntries } from "./mergeEntries.js";
|
|
2
2
|
export { mergeEntriesWithLlm } from "./mergeWithLlm.js";
|
|
3
|
+
export { mergeMemoryEntries, scheduleMergeMemoryEntriesInBackground, } from "./mergeMemoryEntries.js";
|
|
3
4
|
export { runConsolidateJob } from "./runJob.js";
|
|
4
5
|
export { createConsolidateScheduler, startConsolidateInterval } from "./scheduler.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import orderBy from "
|
|
2
|
-
import { entryDedupeKey } from "
|
|
1
|
+
import { orderBy } from "es-toolkit";
|
|
2
|
+
import { entryDedupeKey } from "../utils/memory/index.js";
|
|
3
3
|
import { MEMORY_SECTIONS } from "../store/types.js";
|
|
4
4
|
const SECTION_RANK = new Map(MEMORY_SECTIONS.map((section, index) => [section, index]));
|
|
5
5
|
/** Rule-based dedupe before optional LLM merge. Prefer user-authored on conflict. */
|
|
@@ -12,5 +12,5 @@ export function dedupeEntries(entries) {
|
|
|
12
12
|
byKey.set(key, entry);
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
return orderBy([...byKey.values()], [(entry) => SECTION_RANK.get(entry.section) ?? MEMORY_SECTIONS.length]);
|
|
15
|
+
return orderBy([...byKey.values()], [(entry) => SECTION_RANK.get(entry.section) ?? MEMORY_SECTIONS.length], ["asc"]);
|
|
16
16
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LlmClient } from "../adapters/llm/types.js";
|
|
2
|
+
import type { ConsolidateStoreAccess } from "../store/consolidatePort.js";
|
|
3
|
+
/** Dedupe and optionally LLM-merge MEMORY entries, then rewrite Ground Truth under lock. */
|
|
4
|
+
export declare function mergeMemoryEntries(store: ConsolidateStoreAccess, llm: LlmClient): Promise<void>;
|
|
5
|
+
/** Fire-and-forget wrapper around {@link mergeMemoryEntries}. */
|
|
6
|
+
export declare function scheduleMergeMemoryEntriesInBackground(store: ConsolidateStoreAccess, llm: LlmClient, opts?: {
|
|
7
|
+
onComplete?: () => void | Promise<void>;
|
|
8
|
+
}): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { dedupeEntries } from "./mergeEntries.js";
|
|
2
|
+
import { mergeEntriesWithLlm } from "./mergeWithLlm.js";
|
|
3
|
+
/** Dedupe and optionally LLM-merge MEMORY entries, then rewrite Ground Truth under lock. */
|
|
4
|
+
export async function mergeMemoryEntries(store, llm) {
|
|
5
|
+
if (store.isConsolidating())
|
|
6
|
+
return;
|
|
7
|
+
await store.rewriteMemoryUnderLock(async (entries) => {
|
|
8
|
+
let merged = dedupeEntries(entries);
|
|
9
|
+
try {
|
|
10
|
+
merged = await mergeEntriesWithLlm(merged, llm);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// rule-based dedupe only
|
|
14
|
+
}
|
|
15
|
+
return merged;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/** Fire-and-forget wrapper around {@link mergeMemoryEntries}. */
|
|
19
|
+
export function scheduleMergeMemoryEntriesInBackground(store, llm, opts = {}) {
|
|
20
|
+
void mergeMemoryEntries(store, llm)
|
|
21
|
+
.then(() => opts.onComplete?.())
|
|
22
|
+
.catch(() => { });
|
|
23
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import groupBy from "
|
|
1
|
+
import { groupBy } from "es-toolkit";
|
|
2
2
|
import { formatEntryLine, formatSectionHeader } from "../store/markdown/format.js";
|
|
3
3
|
import { MEMORY_SECTIONS } from "../store/types.js";
|
|
4
4
|
export function formatEntriesForConsolidation(entries) {
|
|
5
|
-
const grouped = groupBy(entries,
|
|
5
|
+
const grouped = groupBy(entries, (entry) => entry.section);
|
|
6
6
|
const lines = [];
|
|
7
7
|
for (const section of MEMORY_SECTIONS) {
|
|
8
8
|
const sectionEntries = grouped[section] ?? [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import keyBy from "
|
|
1
|
+
import { keyBy } from "es-toolkit";
|
|
2
2
|
import { parseMemoryMarkdown } from "../store/markdown/parse.js";
|
|
3
|
-
import { entryDedupeKey } from "
|
|
3
|
+
import { entryDedupeKey } from "../utils/memory/index.js";
|
|
4
4
|
import { buildConsolidateMergePrompt, formatEntriesForConsolidation } from "./mergePrompt.js";
|
|
5
5
|
import { dedupeEntries } from "./mergeEntries.js";
|
|
6
6
|
function preserveUserAuthored(original, merged) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LlmClient } from "../adapters/llm/types.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ConsolidateStoreAccess } from "../store/consolidatePort.js";
|
|
3
3
|
export type ConsolidateJobStats = {
|
|
4
4
|
entriesBefore: number;
|
|
5
5
|
entriesAfter: number;
|
|
@@ -8,7 +8,7 @@ export type ConsolidateJobStats = {
|
|
|
8
8
|
indexGeneration?: number;
|
|
9
9
|
};
|
|
10
10
|
export type RunConsolidateJobOptions = {
|
|
11
|
-
store:
|
|
11
|
+
store: ConsolidateStoreAccess;
|
|
12
12
|
agentDir: string;
|
|
13
13
|
llm?: LlmClient | null;
|
|
14
14
|
cronFired?: boolean;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { reindex } from "../sidecar/client.js";
|
|
4
|
-
import { resolveSidecarPaths } from "../sidecar/paths.js";
|
|
1
|
+
import { syncSidecarIndex } from "../sidecar/syncIndex.js";
|
|
2
|
+
import { mergeMemoryEntries } from "./mergeMemoryEntries.js";
|
|
5
3
|
const NOOP_LLM = {
|
|
6
4
|
async complete() {
|
|
7
5
|
throw new Error("LLM unavailable");
|
|
@@ -9,12 +7,15 @@ const NOOP_LLM = {
|
|
|
9
7
|
};
|
|
10
8
|
export async function runConsolidateJob(opts) {
|
|
11
9
|
const llm = opts.llm ?? NOOP_LLM;
|
|
10
|
+
if (opts.store.isConsolidating()) {
|
|
11
|
+
return { status: "skipped", reason: "already_consolidating" };
|
|
12
|
+
}
|
|
12
13
|
if (!opts.force && !(await opts.store.shouldConsolidate(undefined, opts.cronFired))) {
|
|
13
14
|
return { status: "skipped", reason: "conditions_not_met" };
|
|
14
15
|
}
|
|
15
16
|
const before = await opts.store.getStats();
|
|
16
17
|
try {
|
|
17
|
-
await opts.store
|
|
18
|
+
await mergeMemoryEntries(opts.store, llm);
|
|
18
19
|
let indexGeneration;
|
|
19
20
|
if (opts.reindex !== false) {
|
|
20
21
|
indexGeneration = await syncSidecarIndex(opts.agentDir, opts.store);
|
|
@@ -38,10 +39,3 @@ export async function runConsolidateJob(opts) {
|
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
|
-
async function syncSidecarIndex(agentDir, store) {
|
|
42
|
-
const sidecar = resolveSidecarPaths(agentDir);
|
|
43
|
-
await ensureSidecarRunning(sidecar);
|
|
44
|
-
const result = await reindex(sidecar.socketPath, await store.exportForIndex());
|
|
45
|
-
sidecarQueryCache.onReindexComplete(agentDir, result.index_generation);
|
|
46
|
-
return result.index_generation;
|
|
47
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LlmClient } from "../adapters/llm/types.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ConsolidateStoreAccess } from "../store/consolidatePort.js";
|
|
3
3
|
export type ConsolidateScheduler = {
|
|
4
4
|
schedule(): void;
|
|
5
5
|
runNow(opts?: {
|
|
@@ -7,7 +7,7 @@ export type ConsolidateScheduler = {
|
|
|
7
7
|
}): Promise<void>;
|
|
8
8
|
};
|
|
9
9
|
export declare function createConsolidateScheduler(opts: {
|
|
10
|
-
getStore():
|
|
10
|
+
getStore(): ConsolidateStoreAccess | null;
|
|
11
11
|
getAgentDir(): string | null;
|
|
12
12
|
getLlm(): LlmClient | null;
|
|
13
13
|
debounceMs?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import debounce from "
|
|
1
|
+
import { debounce } from "es-toolkit";
|
|
2
2
|
import { DEFAULT_CONSOLIDATE_CHECK_INTERVAL_MS, DEFAULT_CONSOLIDATE_DEBOUNCE_MS } from "../constants/timing.js";
|
|
3
3
|
import { runConsolidateJob } from "./runJob.js";
|
|
4
4
|
export function createConsolidateScheduler(opts) {
|
package/dist/constants/env.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export declare const ENV_KEYS: {
|
|
|
30
30
|
readonly AGENT_DIR: "PI_MEMORY_AGENT_DIR";
|
|
31
31
|
readonly ENV_FILE: "PI_MEMORY_ENV_FILE";
|
|
32
32
|
readonly DEBUG: "PI_MEMORY_DEBUG";
|
|
33
|
+
readonly SKIP_SCHEDULER_SYNC: "PI_MEMORY_SKIP_SCHEDULER_SYNC";
|
|
33
34
|
};
|
|
34
35
|
/** Fallback OPENAI_API_KEY when PI_MEMORY_OPENAI_API_KEY unset. */
|
|
35
36
|
export declare const FALLBACK_OPENAI_API_KEY_ENV = "OPENAI_API_KEY";
|
package/dist/constants/env.js
CHANGED
|
@@ -29,6 +29,7 @@ export const ENV_KEYS = {
|
|
|
29
29
|
AGENT_DIR: "PI_MEMORY_AGENT_DIR",
|
|
30
30
|
ENV_FILE: "PI_MEMORY_ENV_FILE",
|
|
31
31
|
DEBUG: "PI_MEMORY_DEBUG",
|
|
32
|
+
SKIP_SCHEDULER_SYNC: "PI_MEMORY_SKIP_SCHEDULER_SYNC",
|
|
32
33
|
};
|
|
33
34
|
/** Fallback OPENAI_API_KEY when PI_MEMORY_OPENAI_API_KEY unset. */
|
|
34
35
|
export const FALLBACK_OPENAI_API_KEY_ENV = "OPENAI_API_KEY";
|
|
@@ -8,11 +8,13 @@ export declare const SIDECAR_SOCKET_FILE = "memory.sock";
|
|
|
8
8
|
export declare const SIDECAR_DB_FILE = "memory.vec.sqlite";
|
|
9
9
|
export declare const SIDECAR_PID_SUFFIX = ".pid";
|
|
10
10
|
export declare const SIDECAR_SPAWN_LOCK_FILE = "sidecar.spawn.lock";
|
|
11
|
-
/** Consolidate / maintenance scheduler log basenames (under
|
|
11
|
+
/** Consolidate / maintenance scheduler log basenames (under `<agentDir>/logs`). */
|
|
12
12
|
export declare const CONSOLIDATE_LOG_FILE = "maintenance.log";
|
|
13
13
|
export declare const CONSOLIDATE_ERR_LOG_FILE = "maintenance.err.log";
|
|
14
14
|
/** OS scheduler identifiers. */
|
|
15
15
|
export declare const LAUNCHD_LABEL = "com.pi.memory.maintenance";
|
|
16
|
+
/** Pre-0.3.x / dev labels removed during scheduler sync. */
|
|
17
|
+
export declare const LEGACY_LAUNCHD_LABELS: readonly ["dev.pi.memory-consolidate", "com.pi.memory.consolidate"];
|
|
16
18
|
export declare const SCHTASKS_TASK_NAME = "PiMemoryMaintenance";
|
|
17
19
|
export declare const SCHEDULER_TEMPLATE_FILES: {
|
|
18
20
|
readonly launchd: "com.pi.memory.consolidate.plist.example";
|
package/dist/constants/paths.js
CHANGED
|
@@ -8,11 +8,16 @@ export const SIDECAR_SOCKET_FILE = "memory.sock";
|
|
|
8
8
|
export const SIDECAR_DB_FILE = "memory.vec.sqlite";
|
|
9
9
|
export const SIDECAR_PID_SUFFIX = ".pid";
|
|
10
10
|
export const SIDECAR_SPAWN_LOCK_FILE = "sidecar.spawn.lock";
|
|
11
|
-
/** Consolidate / maintenance scheduler log basenames (under
|
|
11
|
+
/** Consolidate / maintenance scheduler log basenames (under `<agentDir>/logs`). */
|
|
12
12
|
export const CONSOLIDATE_LOG_FILE = "maintenance.log";
|
|
13
13
|
export const CONSOLIDATE_ERR_LOG_FILE = "maintenance.err.log";
|
|
14
14
|
/** OS scheduler identifiers. */
|
|
15
15
|
export const LAUNCHD_LABEL = "com.pi.memory.maintenance";
|
|
16
|
+
/** Pre-0.3.x / dev labels removed during scheduler sync. */
|
|
17
|
+
export const LEGACY_LAUNCHD_LABELS = [
|
|
18
|
+
"dev.pi.memory-consolidate",
|
|
19
|
+
"com.pi.memory.consolidate",
|
|
20
|
+
];
|
|
16
21
|
export const SCHTASKS_TASK_NAME = "PiMemoryMaintenance";
|
|
17
22
|
export const SCHEDULER_TEMPLATE_FILES = {
|
|
18
23
|
launchd: "com.pi.memory.consolidate.plist.example",
|