@chendpoc/pi-memory 0.1.11 → 0.1.13
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 +88 -16
- package/dist/cache/memoryCaches.d.ts +32 -0
- package/dist/cache/memoryCaches.d.ts.map +1 -0
- package/dist/cache/memoryCaches.js +59 -0
- package/dist/cache/memoryCaches.js.map +1 -0
- package/dist/cli.js +123 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +28 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +37 -1
- package/dist/config.js.map +1 -1
- package/dist/consolidation/enqueue.d.ts +33 -0
- package/dist/consolidation/enqueue.d.ts.map +1 -0
- package/dist/consolidation/enqueue.js +145 -0
- package/dist/consolidation/enqueue.js.map +1 -0
- package/dist/consolidation/index.d.ts +19 -0
- package/dist/consolidation/index.d.ts.map +1 -0
- package/dist/consolidation/index.js +15 -0
- package/dist/consolidation/index.js.map +1 -0
- package/dist/consolidation/lock.d.ts +5 -0
- package/dist/consolidation/lock.d.ts.map +1 -0
- package/dist/consolidation/lock.js +33 -0
- package/dist/consolidation/lock.js.map +1 -0
- package/dist/consolidation/log.d.ts +8 -0
- package/dist/consolidation/log.d.ts.map +1 -0
- package/dist/consolidation/log.js +32 -0
- package/dist/consolidation/log.js.map +1 -0
- package/dist/consolidation/memoryIndex.d.ts +18 -0
- package/dist/consolidation/memoryIndex.d.ts.map +1 -0
- package/dist/consolidation/memoryIndex.js +100 -0
- package/dist/consolidation/memoryIndex.js.map +1 -0
- package/dist/consolidation/phase2/runPhase2.d.ts +23 -0
- package/dist/consolidation/phase2/runPhase2.d.ts.map +1 -0
- package/dist/consolidation/phase2/runPhase2.js +196 -0
- package/dist/consolidation/phase2/runPhase2.js.map +1 -0
- package/dist/consolidation/scheduler/launchd.d.ts +5 -0
- package/dist/consolidation/scheduler/launchd.d.ts.map +1 -0
- package/dist/consolidation/scheduler/launchd.js +54 -0
- package/dist/consolidation/scheduler/launchd.js.map +1 -0
- package/dist/consolidation/scheduler/runConsolidate.d.ts +26 -0
- package/dist/consolidation/scheduler/runConsolidate.d.ts.map +1 -0
- package/dist/consolidation/scheduler/runConsolidate.js +83 -0
- package/dist/consolidation/scheduler/runConsolidate.js.map +1 -0
- package/dist/consolidation/scheduler/setupSchedule.d.ts +3 -0
- package/dist/consolidation/scheduler/setupSchedule.d.ts.map +1 -0
- package/dist/consolidation/scheduler/setupSchedule.js +79 -0
- package/dist/consolidation/scheduler/setupSchedule.js.map +1 -0
- package/dist/consolidation/scheduler/systemd.d.ts +9 -0
- package/dist/consolidation/scheduler/systemd.d.ts.map +1 -0
- package/dist/consolidation/scheduler/systemd.js +57 -0
- package/dist/consolidation/scheduler/systemd.js.map +1 -0
- package/dist/consolidation/scheduler/types.d.ts +24 -0
- package/dist/consolidation/scheduler/types.d.ts.map +1 -0
- package/dist/consolidation/scheduler/types.js +2 -0
- package/dist/consolidation/scheduler/types.js.map +1 -0
- package/dist/consolidation/scope.d.ts +12 -0
- package/dist/consolidation/scope.d.ts.map +1 -0
- package/dist/consolidation/scope.js +51 -0
- package/dist/consolidation/scope.js.map +1 -0
- package/dist/consolidation/stage1/deltaExtract.d.ts +3 -0
- package/dist/consolidation/stage1/deltaExtract.d.ts.map +1 -0
- package/dist/consolidation/stage1/deltaExtract.js +19 -0
- package/dist/consolidation/stage1/deltaExtract.js.map +1 -0
- package/dist/consolidation/stage1/drainQueue.d.ts +21 -0
- package/dist/consolidation/stage1/drainQueue.d.ts.map +1 -0
- package/dist/consolidation/stage1/drainQueue.js +113 -0
- package/dist/consolidation/stage1/drainQueue.js.map +1 -0
- package/dist/consolidation/stage1/extractSession.d.ts +6 -0
- package/dist/consolidation/stage1/extractSession.d.ts.map +1 -0
- package/dist/consolidation/stage1/extractSession.js +47 -0
- package/dist/consolidation/stage1/extractSession.js.map +1 -0
- package/dist/consolidation/stage1/store.d.ts +45 -0
- package/dist/consolidation/stage1/store.d.ts.map +1 -0
- package/dist/consolidation/stage1/store.js +297 -0
- package/dist/consolidation/stage1/store.js.map +1 -0
- package/dist/consolidation/types.d.ts +49 -0
- package/dist/consolidation/types.d.ts.map +1 -0
- package/dist/consolidation/types.js +2 -0
- package/dist/consolidation/types.js.map +1 -0
- package/dist/fallback/llmRerank.d.ts.map +1 -1
- package/dist/fallback/llmRerank.js +9 -1
- package/dist/fallback/llmRerank.js.map +1 -1
- package/dist/fallback/sessionIndex.d.ts.map +1 -1
- package/dist/fallback/sessionIndex.js +15 -63
- package/dist/fallback/sessionIndex.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/local/graphQuery.d.ts +10 -0
- package/dist/local/graphQuery.d.ts.map +1 -1
- package/dist/local/graphQuery.js +25 -0
- package/dist/local/graphQuery.js.map +1 -1
- package/dist/pi-extension.d.ts.map +1 -1
- package/dist/pi-extension.js +356 -22
- package/dist/pi-extension.js.map +1 -1
- package/dist/preflight/detectIntents.d.ts.map +1 -1
- package/dist/preflight/detectIntents.js +7 -0
- package/dist/preflight/detectIntents.js.map +1 -1
- package/dist/preflight/hook.d.ts +18 -0
- package/dist/preflight/hook.d.ts.map +1 -1
- package/dist/preflight/hook.js +52 -7
- package/dist/preflight/hook.js.map +1 -1
- package/dist/preflight/render.d.ts +16 -2
- package/dist/preflight/render.d.ts.map +1 -1
- package/dist/preflight/render.js +24 -4
- package/dist/preflight/render.js.map +1 -1
- package/dist/service.d.ts +16 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +57 -0
- package/dist/service.js.map +1 -1
- package/dist/session/activeBranch.d.ts +17 -0
- package/dist/session/activeBranch.d.ts.map +1 -0
- package/dist/session/activeBranch.js +251 -0
- package/dist/session/activeBranch.js.map +1 -0
- package/dist/settings.d.ts +5 -2
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +18 -1
- package/dist/settings.js.map +1 -1
- package/dist/tools/memoryAppend.d.ts +14 -4
- package/dist/tools/memoryAppend.d.ts.map +1 -1
- package/dist/tools/memoryAppend.js +46 -7
- package/dist/tools/memoryAppend.js.map +1 -1
- package/dist/tools/memoryRecall.d.ts +2 -2
- package/dist/tools/memoryRecall.d.ts.map +1 -1
- package/dist/tools/memoryRecall.js +35 -9
- package/dist/tools/memoryRecall.js.map +1 -1
- package/dist/trainer/extractFacts.d.ts +1 -1
- package/dist/trainer/index.d.ts +1 -1
- package/dist/trainer/index.d.ts.map +1 -1
- package/dist/trainer/index.js +1 -1
- package/dist/trainer/index.js.map +1 -1
- package/dist/trainer/scheduler.d.ts +2 -0
- package/dist/trainer/scheduler.d.ts.map +1 -1
- package/dist/trainer/scheduler.js +1 -0
- package/dist/trainer/scheduler.js.map +1 -1
- package/dist/trainer/sessionLoader.d.ts +3 -0
- package/dist/trainer/sessionLoader.d.ts.map +1 -1
- package/dist/trainer/sessionLoader.js +37 -74
- package/dist/trainer/sessionLoader.js.map +1 -1
- package/package.json +17 -4
- package/src/cache/memoryCaches.ts +72 -0
- package/src/cli.ts +144 -0
- package/src/config.ts +89 -1
- package/src/consolidation/enqueue.ts +205 -0
- package/src/consolidation/index.ts +90 -0
- package/src/consolidation/lock.ts +41 -0
- package/src/consolidation/log.ts +43 -0
- package/src/consolidation/memoryIndex.ts +127 -0
- package/src/consolidation/phase2/runPhase2.ts +255 -0
- package/src/consolidation/scheduler/launchd.ts +62 -0
- package/src/consolidation/scheduler/runConsolidate.ts +115 -0
- package/src/consolidation/scheduler/setupSchedule.ts +106 -0
- package/src/consolidation/scheduler/systemd.ts +78 -0
- package/src/consolidation/scheduler/types.ts +27 -0
- package/src/consolidation/scope.ts +58 -0
- package/src/consolidation/stage1/deltaExtract.ts +29 -0
- package/src/consolidation/stage1/drainQueue.ts +143 -0
- package/src/consolidation/stage1/extractSession.ts +58 -0
- package/src/consolidation/stage1/store.ts +411 -0
- package/src/consolidation/types.ts +52 -0
- package/src/fallback/llmRerank.ts +8 -1
- package/src/fallback/sessionIndex.ts +14 -51
- package/src/index.ts +8 -0
- package/src/local/graphQuery.ts +24 -0
- package/src/pi-extension.ts +393 -28
- package/src/preflight/detectIntents.ts +6 -0
- package/src/preflight/hook.ts +84 -7
- package/src/preflight/render.ts +35 -3
- package/src/service.ts +57 -0
- package/src/session/activeBranch.ts +294 -0
- package/src/settings.ts +37 -2
- package/src/tools/memoryAppend.ts +60 -7
- package/src/tools/memoryRecall.ts +33 -9
- package/src/trainer/index.ts +1 -1
- package/src/trainer/scheduler.ts +3 -0
- package/src/trainer/sessionLoader.ts +38 -87
|
@@ -55,7 +55,7 @@ export class MemoryRecallTool {
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
async run(argsJson: string, signal?: AbortSignal): Promise<ToolResult> {
|
|
58
|
+
async run(argsJson: string, signal?: AbortSignal, onProgress?: (msg: string) => void): Promise<ToolResult> {
|
|
59
59
|
const args = parseArgs(argsJson);
|
|
60
60
|
if ("error" in args) {
|
|
61
61
|
return { content: args.error, isError: true };
|
|
@@ -67,29 +67,53 @@ export class MemoryRecallTool {
|
|
|
67
67
|
return { content: validation, isError: true };
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
return this.runIntent(intent, signal);
|
|
70
|
+
return this.runIntent(intent, signal, onProgress);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
async runIntent(intent: QueryIntent, signal?: AbortSignal): Promise<ToolResult> {
|
|
73
|
+
async runIntent(intent: QueryIntent, signal?: AbortSignal, onProgress?: (msg: string) => void): Promise<ToolResult> {
|
|
74
74
|
if (this.service.status() !== "ready") {
|
|
75
75
|
return this.fallbackResult(intent, "service_unavailable", "fallback");
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
// Emit a progress message if the sidecar takes longer than 500 ms.
|
|
79
|
+
let progressTimer: ReturnType<typeof setTimeout> | null = null;
|
|
80
|
+
if (onProgress) {
|
|
81
|
+
progressTimer = setTimeout(() => {
|
|
82
|
+
onProgress("Querying episodic memory…");
|
|
83
|
+
}, 500);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let result;
|
|
87
|
+
try {
|
|
88
|
+
result = await this.service.query(intent, signal);
|
|
89
|
+
} finally {
|
|
90
|
+
if (progressTimer != null) clearTimeout(progressTimer);
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
if (result.transportError || result.errorClass === "unavailable") {
|
|
80
94
|
return this.fallbackResult(intent, "service_unavailable", "fallback");
|
|
81
95
|
}
|
|
82
96
|
|
|
83
97
|
if (result.errorClass === "retryable") {
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
let retryTimer: ReturnType<typeof setTimeout> | null = null;
|
|
99
|
+
if (onProgress) {
|
|
100
|
+
retryTimer = setTimeout(() => onProgress("Retrying memory query…"), 500);
|
|
101
|
+
}
|
|
102
|
+
let retryResult;
|
|
103
|
+
try {
|
|
104
|
+
await sleep(500, signal);
|
|
105
|
+
retryResult = await this.service.query(intent, signal);
|
|
106
|
+
} finally {
|
|
107
|
+
if (retryTimer != null) clearTimeout(retryTimer);
|
|
108
|
+
}
|
|
86
109
|
if (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
110
|
+
retryResult.transportError ||
|
|
111
|
+
retryResult.errorClass === "unavailable" ||
|
|
112
|
+
retryResult.errorClass === "retryable"
|
|
90
113
|
) {
|
|
91
114
|
return this.fallbackResult(intent, "retryable_failed", "fallback_after_retry");
|
|
92
115
|
}
|
|
116
|
+
result = retryResult;
|
|
93
117
|
}
|
|
94
118
|
|
|
95
119
|
if (result.errorClass === "permanent") {
|
package/src/trainer/index.ts
CHANGED
|
@@ -129,7 +129,7 @@ export async function trainBundle(
|
|
|
129
129
|
};
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
export { loadSessions } from "./sessionLoader.js";
|
|
132
|
+
export { loadSessionFile, loadSessions } from "./sessionLoader.js";
|
|
133
133
|
export type { LoadedSession, SessionTurn, SessionLoaderOptions } from "./sessionLoader.js";
|
|
134
134
|
export { extractFacts, extractFactsFromSessions, RELATION_CATALOG, ALL_RELATIONS } from "./extractFacts.js";
|
|
135
135
|
export type {
|
package/src/trainer/scheduler.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface SchedulerConfig {
|
|
|
5
5
|
interval: string | null;
|
|
6
6
|
/** Passed through to trainBundle. */
|
|
7
7
|
trainConfig?: Omit<TrainBundleConfig, "full" | "dryRun">;
|
|
8
|
+
/** Called after a successful train tick (no error). Use to notify MemoryService. */
|
|
9
|
+
onSuccess?: () => void;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export interface TrainScheduler {
|
|
@@ -69,6 +71,7 @@ export function createTrainScheduler(
|
|
|
69
71
|
full: false,
|
|
70
72
|
dryRun: false,
|
|
71
73
|
});
|
|
74
|
+
config.onSuccess?.();
|
|
72
75
|
} catch (err) {
|
|
73
76
|
error = err instanceof Error ? err.message : String(err);
|
|
74
77
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { messageText, parseJsonlSession as parseActiveBranchJsonl } from "../session/activeBranch.js";
|
|
4
5
|
|
|
5
6
|
export interface SessionTurn {
|
|
6
7
|
role: string;
|
|
@@ -14,6 +15,8 @@ export interface LoadedSession {
|
|
|
14
15
|
createdAt: string;
|
|
15
16
|
filePath: string;
|
|
16
17
|
modifiedAt: Date;
|
|
18
|
+
parentSessionFile?: string;
|
|
19
|
+
parentSessionId?: string;
|
|
17
20
|
turns: SessionTurn[];
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -29,39 +32,6 @@ interface PiSessionFile {
|
|
|
29
32
|
messages?: PiSessionMessage[];
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
interface JsonlSessionHeader {
|
|
33
|
-
type: "session";
|
|
34
|
-
id?: string;
|
|
35
|
-
timestamp?: string;
|
|
36
|
-
title?: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
interface JsonlMessageLine {
|
|
40
|
-
type: "message";
|
|
41
|
-
message?: {
|
|
42
|
-
role?: string;
|
|
43
|
-
content?: unknown;
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function messageText(content: unknown): string {
|
|
48
|
-
if (typeof content === "string") return content;
|
|
49
|
-
if (!Array.isArray(content)) return "";
|
|
50
|
-
const parts: string[] = [];
|
|
51
|
-
for (const block of content) {
|
|
52
|
-
if (typeof block === "string") {
|
|
53
|
-
parts.push(block);
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (block && typeof block === "object") {
|
|
57
|
-
const b = block as Record<string, unknown>;
|
|
58
|
-
if (typeof b.text === "string") parts.push(b.text);
|
|
59
|
-
else if (typeof b.content === "string") parts.push(b.content);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return parts.join("\n");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
35
|
export interface SessionLoaderOptions {
|
|
66
36
|
sessionsDir: string;
|
|
67
37
|
modifiedAfter?: Date | null;
|
|
@@ -94,49 +64,6 @@ async function collectSessionFiles(dir: string): Promise<string[]> {
|
|
|
94
64
|
return files;
|
|
95
65
|
}
|
|
96
66
|
|
|
97
|
-
function parseJsonlSession(raw: string, filePath: string): LoadedSession | null {
|
|
98
|
-
const lines = raw.split("\n").filter((l) => l.trim());
|
|
99
|
-
if (lines.length === 0) return null;
|
|
100
|
-
|
|
101
|
-
let header: JsonlSessionHeader | null = null;
|
|
102
|
-
const turns: SessionTurn[] = [];
|
|
103
|
-
let turnIndex = 0;
|
|
104
|
-
|
|
105
|
-
for (const line of lines) {
|
|
106
|
-
let obj: Record<string, unknown>;
|
|
107
|
-
try {
|
|
108
|
-
obj = JSON.parse(line) as Record<string, unknown>;
|
|
109
|
-
} catch {
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (obj.type === "session" && !header) {
|
|
114
|
-
header = obj as unknown as JsonlSessionHeader;
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (obj.type === "message") {
|
|
119
|
-
const msg = (obj as unknown as JsonlMessageLine).message;
|
|
120
|
-
if (!msg?.role || !msg.content) continue;
|
|
121
|
-
if (msg.role !== "user" && msg.role !== "assistant") continue;
|
|
122
|
-
const text = messageText(msg.content);
|
|
123
|
-
if (!text.trim()) continue;
|
|
124
|
-
turns.push({ role: msg.role, content: text, turnIndex: turnIndex++ });
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (turns.length === 0) return null;
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
id: header?.id ?? path.basename(filePath, path.extname(filePath)),
|
|
132
|
-
title: header?.title ?? "",
|
|
133
|
-
createdAt: header?.timestamp ?? "",
|
|
134
|
-
filePath,
|
|
135
|
-
modifiedAt: new Date(),
|
|
136
|
-
turns,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
67
|
function parseJsonSession(raw: string, filePath: string): LoadedSession | null {
|
|
141
68
|
let session: PiSessionFile;
|
|
142
69
|
try {
|
|
@@ -167,6 +94,16 @@ function parseJsonSession(raw: string, filePath: string): LoadedSession | null {
|
|
|
167
94
|
};
|
|
168
95
|
}
|
|
169
96
|
|
|
97
|
+
function parseJsonlSession(raw: string, filePath: string): LoadedSession | null {
|
|
98
|
+
const parsed = parseActiveBranchJsonl(raw, filePath);
|
|
99
|
+
if (!parsed) return null;
|
|
100
|
+
return {
|
|
101
|
+
...parsed,
|
|
102
|
+
filePath,
|
|
103
|
+
modifiedAt: new Date(),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
170
107
|
/**
|
|
171
108
|
* Scan session files (JSON + JSONL, recursive subdirectories), parse Pi session
|
|
172
109
|
* format, optionally filter by modified-after timestamp for incremental training.
|
|
@@ -190,17 +127,7 @@ export async function loadSessions(
|
|
|
190
127
|
if (!st.isFile()) continue;
|
|
191
128
|
if (modifiedAfter && st.mtime <= modifiedAfter) continue;
|
|
192
129
|
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
raw = await fs.readFile(filePath, "utf8");
|
|
196
|
-
} catch {
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const isJsonl = filePath.endsWith(".jsonl");
|
|
201
|
-
const parsed = isJsonl
|
|
202
|
-
? parseJsonlSession(raw, filePath)
|
|
203
|
-
: parseJsonSession(raw, filePath);
|
|
130
|
+
const parsed = await loadSessionFile(filePath);
|
|
204
131
|
|
|
205
132
|
if (!parsed) continue;
|
|
206
133
|
parsed.modifiedAt = st.mtime;
|
|
@@ -211,6 +138,30 @@ export async function loadSessions(
|
|
|
211
138
|
return deduplicateSessions(sessions);
|
|
212
139
|
}
|
|
213
140
|
|
|
141
|
+
export async function loadSessionFile(filePath: string): Promise<LoadedSession | null> {
|
|
142
|
+
let st: Awaited<ReturnType<typeof fs.stat>>;
|
|
143
|
+
try {
|
|
144
|
+
st = await fs.stat(filePath);
|
|
145
|
+
} catch {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
if (!st.isFile()) return null;
|
|
149
|
+
|
|
150
|
+
let raw: string;
|
|
151
|
+
try {
|
|
152
|
+
raw = await fs.readFile(filePath, "utf8");
|
|
153
|
+
} catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const parsed = filePath.endsWith(".jsonl")
|
|
158
|
+
? parseJsonlSession(raw, filePath)
|
|
159
|
+
: parseJsonSession(raw, filePath);
|
|
160
|
+
if (!parsed) return null;
|
|
161
|
+
parsed.modifiedAt = st.mtime;
|
|
162
|
+
return parsed;
|
|
163
|
+
}
|
|
164
|
+
|
|
214
165
|
function deduplicateSessions(sessions: LoadedSession[]): LoadedSession[] {
|
|
215
166
|
const seen = new Set<string>();
|
|
216
167
|
return sessions.filter((s) => {
|