@pencil-agent/nano-mem 0.0.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/CLAUDE.md +258 -0
- package/README.md +146 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +90 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +46 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +48 -0
- package/dist/config.js.map +1 -0
- package/dist/consolidation.d.ts +13 -0
- package/dist/consolidation.d.ts.map +1 -0
- package/dist/consolidation.js +111 -0
- package/dist/consolidation.js.map +1 -0
- package/dist/engine.d.ts +67 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +492 -0
- package/dist/engine.js.map +1 -0
- package/dist/eviction.d.ts +16 -0
- package/dist/eviction.d.ts.map +1 -0
- package/dist/eviction.js +22 -0
- package/dist/eviction.js.map +1 -0
- package/dist/extension.d.ts +11 -0
- package/dist/extension.d.ts.map +1 -0
- package/dist/extension.js +264 -0
- package/dist/extension.js.map +1 -0
- package/dist/extraction.d.ts +10 -0
- package/dist/extraction.d.ts.map +1 -0
- package/dist/extraction.js +136 -0
- package/dist/extraction.js.map +1 -0
- package/dist/full-insights-html.d.ts +8 -0
- package/dist/full-insights-html.d.ts.map +1 -0
- package/dist/full-insights-html.js +311 -0
- package/dist/full-insights-html.js.map +1 -0
- package/dist/full-insights.d.ts +21 -0
- package/dist/full-insights.d.ts.map +1 -0
- package/dist/full-insights.js +327 -0
- package/dist/full-insights.js.map +1 -0
- package/dist/i18n.d.ts +50 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +169 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/insights-html.d.ts +8 -0
- package/dist/insights-html.d.ts.map +1 -0
- package/dist/insights-html.js +431 -0
- package/dist/insights-html.js.map +1 -0
- package/dist/linking.d.ts +11 -0
- package/dist/linking.d.ts.map +1 -0
- package/dist/linking.js +40 -0
- package/dist/linking.js.map +1 -0
- package/dist/privacy.d.ts +16 -0
- package/dist/privacy.d.ts.map +1 -0
- package/dist/privacy.js +52 -0
- package/dist/privacy.js.map +1 -0
- package/dist/scoring.d.ts +25 -0
- package/dist/scoring.d.ts.map +1 -0
- package/dist/scoring.js +63 -0
- package/dist/scoring.js.map +1 -0
- package/dist/store.d.ts +16 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +68 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +191 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/update.d.ts +14 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +126 -0
- package/dist/update.js.map +1 -0
- package/package.json +60 -0
- package/src/cli.ts +99 -0
- package/src/config.ts +72 -0
- package/src/consolidation.ts +127 -0
- package/src/engine.ts +699 -0
- package/src/eviction.ts +30 -0
- package/src/extension.ts +290 -0
- package/src/extraction.ts +152 -0
- package/src/full-insights-html.ts +342 -0
- package/src/full-insights.ts +396 -0
- package/src/i18n.ts +233 -0
- package/src/index.ts +50 -0
- package/src/insights-html.ts +476 -0
- package/src/linking.ts +43 -0
- package/src/privacy.ts +52 -0
- package/src/scoring.ts +94 -0
- package/src/store.ts +84 -0
- package/src/types.ts +209 -0
- package/src/update.ts +141 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: NanoPencil ExtensionAPI
|
|
3
|
+
* [OUTPUT]: Registers lifecycle hooks that drive NanoMemEngine
|
|
4
|
+
* [POS]: Thin adapter — bridges NanoPencil events to the host-agnostic engine
|
|
5
|
+
*
|
|
6
|
+
* This file is the ONLY module that depends on @pencil-agent/nano-pencil types.
|
|
7
|
+
* For non-NanoPencil hosts, import from the package root instead.
|
|
8
|
+
*/
|
|
9
|
+
import { writeFileSync } from "node:fs";
|
|
10
|
+
import { basename } from "node:path";
|
|
11
|
+
import { NanoMemEngine } from "./engine.js";
|
|
12
|
+
import { renderFullInsightsHtml } from "./full-insights-html.js";
|
|
13
|
+
import { extractTags } from "./scoring.js";
|
|
14
|
+
function withTimeout(promise, timeoutMs) {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const timer = setTimeout(() => resolve(undefined), timeoutMs);
|
|
17
|
+
promise
|
|
18
|
+
.then((value) => {
|
|
19
|
+
clearTimeout(timer);
|
|
20
|
+
resolve(value);
|
|
21
|
+
})
|
|
22
|
+
.catch(() => {
|
|
23
|
+
clearTimeout(timer);
|
|
24
|
+
resolve(undefined);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function getProject() {
|
|
29
|
+
const parts = process.cwd().split("/").filter(Boolean);
|
|
30
|
+
return parts.length >= 2
|
|
31
|
+
? `${parts[parts.length - 2]}/${parts[parts.length - 1]}`
|
|
32
|
+
: parts[parts.length - 1] || "default";
|
|
33
|
+
}
|
|
34
|
+
function getMessageText(msg) {
|
|
35
|
+
if (msg.role !== "user")
|
|
36
|
+
return "";
|
|
37
|
+
const c = msg.content;
|
|
38
|
+
if (typeof c === "string")
|
|
39
|
+
return c;
|
|
40
|
+
if (Array.isArray(c)) {
|
|
41
|
+
return c
|
|
42
|
+
.filter((b) => typeof b === "object" && b !== null && "type" in b)
|
|
43
|
+
.filter((b) => b.type === "text" && typeof b.text === "string")
|
|
44
|
+
.map((b) => b.text)
|
|
45
|
+
.join("\n");
|
|
46
|
+
}
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
function getAssistantMessageText(msg) {
|
|
50
|
+
if (msg.role !== "assistant")
|
|
51
|
+
return "";
|
|
52
|
+
const c = msg.content;
|
|
53
|
+
if (!Array.isArray(c))
|
|
54
|
+
return "";
|
|
55
|
+
return c
|
|
56
|
+
.filter((b) => typeof b === "object" && b !== null && "type" in b)
|
|
57
|
+
.filter((b) => b.type === "text" && typeof b.text === "string")
|
|
58
|
+
.map((b) => b.text)
|
|
59
|
+
.join("\n");
|
|
60
|
+
}
|
|
61
|
+
function buildTranscript(messages, maxMessages = 24, maxChars = 12000) {
|
|
62
|
+
const lines = [];
|
|
63
|
+
let total = 0;
|
|
64
|
+
const slice = messages.slice(-maxMessages);
|
|
65
|
+
for (const msg of slice) {
|
|
66
|
+
const text = msg.role === "user" ? getMessageText(msg) : getAssistantMessageText(msg);
|
|
67
|
+
if (!text.trim())
|
|
68
|
+
continue;
|
|
69
|
+
const prefix = msg.role === "user" ? "User: " : "Assistant: ";
|
|
70
|
+
const line = prefix + text.trim().replace(/\n/g, " ");
|
|
71
|
+
if (total + line.length > maxChars)
|
|
72
|
+
break;
|
|
73
|
+
lines.push(line);
|
|
74
|
+
total += line.length;
|
|
75
|
+
}
|
|
76
|
+
return lines.join("\n");
|
|
77
|
+
}
|
|
78
|
+
function extractObservation(toolName, args, result, isError) {
|
|
79
|
+
const filePath = (args.file_path ?? args.path ?? args.file);
|
|
80
|
+
switch (toolName) {
|
|
81
|
+
case "read":
|
|
82
|
+
return { file: filePath };
|
|
83
|
+
case "edit":
|
|
84
|
+
if (filePath) {
|
|
85
|
+
const old = String(args.old_string ?? "").slice(0, 50);
|
|
86
|
+
const nw = String(args.new_string ?? "").slice(0, 50);
|
|
87
|
+
return { file: filePath, observation: `Edit ${basename(filePath)}: "${old}" -> "${nw}"` };
|
|
88
|
+
}
|
|
89
|
+
return {};
|
|
90
|
+
case "write":
|
|
91
|
+
return filePath ? { file: filePath, observation: `Write ${basename(filePath)}` } : {};
|
|
92
|
+
case "bash": {
|
|
93
|
+
const cmd = String(args.command ?? "").slice(0, 100);
|
|
94
|
+
if (isError && typeof result === "string")
|
|
95
|
+
return { lesson: `\`${cmd}\` failed: ${result.slice(0, 120)}` };
|
|
96
|
+
return cmd ? { observation: `Run: ${cmd}` } : {};
|
|
97
|
+
}
|
|
98
|
+
case "grep":
|
|
99
|
+
case "find":
|
|
100
|
+
return { observation: `Search: ${String(args.pattern ?? args.glob ?? "")}` };
|
|
101
|
+
default:
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export default function nanomemExtension(pi) {
|
|
106
|
+
const project = getProject();
|
|
107
|
+
const ctxTags = extractTags(process.cwd());
|
|
108
|
+
const engine = new NanoMemEngine();
|
|
109
|
+
const pendingArgs = new Map();
|
|
110
|
+
const observations = [];
|
|
111
|
+
const filesModified = new Set();
|
|
112
|
+
const toolsUsed = {};
|
|
113
|
+
const errors = [];
|
|
114
|
+
let sessionId = `nm-${Date.now()}`;
|
|
115
|
+
let sessionGoal;
|
|
116
|
+
let cachedInjection;
|
|
117
|
+
let lastInjectionAt = 0;
|
|
118
|
+
let injectionRefreshInFlight;
|
|
119
|
+
const refreshInjection = async () => {
|
|
120
|
+
if (injectionRefreshInFlight)
|
|
121
|
+
return;
|
|
122
|
+
injectionRefreshInFlight = (async () => {
|
|
123
|
+
try {
|
|
124
|
+
const injection = await engine.getMemoryInjection(project, ctxTags);
|
|
125
|
+
cachedInjection = injection || undefined;
|
|
126
|
+
lastInjectionAt = Date.now();
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// keep previous cache
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
injectionRefreshInFlight = undefined;
|
|
133
|
+
}
|
|
134
|
+
})();
|
|
135
|
+
await injectionRefreshInFlight;
|
|
136
|
+
};
|
|
137
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
138
|
+
const file = ctx.sessionManager.getSessionFile();
|
|
139
|
+
if (file)
|
|
140
|
+
sessionId = basename(file, ".jsonl");
|
|
141
|
+
try {
|
|
142
|
+
await engine.consolidate();
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
/* silent */
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
pi.on("before_agent_start", async (event) => {
|
|
149
|
+
if (sessionGoal === undefined && event.prompt?.trim())
|
|
150
|
+
sessionGoal = event.prompt.trim().slice(0, 300);
|
|
151
|
+
const cacheFresh = cachedInjection && Date.now() - lastInjectionAt < 30_000;
|
|
152
|
+
if (cacheFresh) {
|
|
153
|
+
void refreshInjection();
|
|
154
|
+
return { systemPrompt: `${event.systemPrompt}\n\n${cachedInjection}` };
|
|
155
|
+
}
|
|
156
|
+
const freshInjection = await withTimeout(engine.getMemoryInjection(project, ctxTags), 600);
|
|
157
|
+
if (freshInjection) {
|
|
158
|
+
cachedInjection = freshInjection;
|
|
159
|
+
lastInjectionAt = Date.now();
|
|
160
|
+
return { systemPrompt: `${event.systemPrompt}\n\n${freshInjection}` };
|
|
161
|
+
}
|
|
162
|
+
void refreshInjection();
|
|
163
|
+
return undefined;
|
|
164
|
+
});
|
|
165
|
+
pi.on("tool_execution_start", async (event) => {
|
|
166
|
+
pendingArgs.set(event.toolCallId, event.args);
|
|
167
|
+
toolsUsed[event.toolName] = (toolsUsed[event.toolName] || 0) + 1;
|
|
168
|
+
});
|
|
169
|
+
pi.on("tool_execution_end", async (event) => {
|
|
170
|
+
const args = pendingArgs.get(event.toolCallId) ?? {};
|
|
171
|
+
pendingArgs.delete(event.toolCallId);
|
|
172
|
+
const { observation, lesson, file } = extractObservation(event.toolName, args, event.result, event.isError);
|
|
173
|
+
if (file)
|
|
174
|
+
filesModified.add(file);
|
|
175
|
+
if (observation)
|
|
176
|
+
observations.push(observation);
|
|
177
|
+
if (event.isError)
|
|
178
|
+
errors.push(lesson ?? `${event.toolName} failed`);
|
|
179
|
+
});
|
|
180
|
+
pi.on("agent_end", async (event, ctx) => {
|
|
181
|
+
const llmCtx = ctx;
|
|
182
|
+
if (llmCtx.completeSimple) {
|
|
183
|
+
engine.setLlmFn(async (systemPrompt, userMessage) => {
|
|
184
|
+
const out = await llmCtx.completeSimple?.(systemPrompt, userMessage);
|
|
185
|
+
return out ?? "";
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const transcript = buildTranscript(event.messages);
|
|
189
|
+
if (!transcript.trim())
|
|
190
|
+
return;
|
|
191
|
+
// Avoid blocking the main turn lifecycle (which delays next user message rendering).
|
|
192
|
+
void (async () => {
|
|
193
|
+
await engine.extractAndStore(transcript, project);
|
|
194
|
+
// Always try to extract work if there's meaningful conversation
|
|
195
|
+
// (not just tool activity)
|
|
196
|
+
const hasSubstantialConversation = transcript.length > 100;
|
|
197
|
+
const hadActivity = observations.length > 0 || errors.length > 0;
|
|
198
|
+
if (hadActivity || hasSubstantialConversation) {
|
|
199
|
+
await engine.extractAndStoreWork(transcript, project, sessionGoal);
|
|
200
|
+
}
|
|
201
|
+
})().catch(() => {
|
|
202
|
+
/* silent */
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
pi.on("session_shutdown", async () => {
|
|
206
|
+
// Save episode if there was tool activity OR substantial conversation goal
|
|
207
|
+
const hasActivity = observations.length > 0 || errors.length > 0;
|
|
208
|
+
const hasGoal = sessionGoal && sessionGoal.length > 10;
|
|
209
|
+
if (!hasActivity && !hasGoal)
|
|
210
|
+
return;
|
|
211
|
+
await engine.saveEpisode({
|
|
212
|
+
sessionId,
|
|
213
|
+
project,
|
|
214
|
+
date: new Date().toISOString().slice(0, 10),
|
|
215
|
+
summary: observations.slice(0, 10).join("; ") || sessionGoal?.slice(0, 100) || "Conversation session",
|
|
216
|
+
userGoal: sessionGoal,
|
|
217
|
+
filesModified: [...filesModified],
|
|
218
|
+
toolsUsed: { ...toolsUsed },
|
|
219
|
+
keyObservations: observations.slice(0, 20),
|
|
220
|
+
errors: [...errors],
|
|
221
|
+
tags: [...extractTags(project), ...extractTags([...filesModified].join(" "))],
|
|
222
|
+
importance: Math.min(10, 3 + errors.length * 2 + Math.min(observations.length, 5)),
|
|
223
|
+
consolidated: false,
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
pi.registerCommand("mem-search", {
|
|
227
|
+
description: "Search NanoMem memories",
|
|
228
|
+
handler: async (query, ctx) => {
|
|
229
|
+
const results = await engine.searchEntries(query || project);
|
|
230
|
+
if (!results.length) {
|
|
231
|
+
ctx.ui.notify("NanoMem: no matching memories found", "info");
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
for (const e of results.slice(0, 10))
|
|
235
|
+
ctx.ui.notify(`[${e.type}] ${e.content.slice(0, 80)}`, "info");
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
pi.registerCommand("mem-stats", {
|
|
239
|
+
description: "NanoMem memory statistics",
|
|
240
|
+
handler: async (_args, ctx) => {
|
|
241
|
+
const s = await engine.getStats();
|
|
242
|
+
ctx.ui.notify(`NanoMem: ${s.totalSessions} sessions | ${s.knowledge} knowledge | ${s.lessons} lessons | ${s.preferences} prefs | ${s.work} work | ${s.episodes} episodes`, "info");
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
pi.registerCommand("mem-insights", {
|
|
246
|
+
description: "Generate NanoMem full insights HTML report (uses LLM when available)",
|
|
247
|
+
handler: async (args, ctx) => {
|
|
248
|
+
const llmCtx = ctx;
|
|
249
|
+
if (llmCtx.completeSimple) {
|
|
250
|
+
engine.setLlmFn(async (systemPrompt, userMessage) => {
|
|
251
|
+
const out = await llmCtx.completeSimple?.(systemPrompt, userMessage);
|
|
252
|
+
return out ?? "";
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const outputPath = args?.trim() || "./nanomem-insights.html";
|
|
256
|
+
ctx.ui.notify("NanoMem: Generating full insights report...", "info");
|
|
257
|
+
const report = await engine.generateFullInsights();
|
|
258
|
+
const html = renderFullInsightsHtml(report, engine.cfg.locale);
|
|
259
|
+
writeFileSync(outputPath, html, "utf-8");
|
|
260
|
+
ctx.ui.notify(`NanoMem: Insights report written to ${outputPath}`, "info");
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: conversation text, LlmFn, config
|
|
3
|
+
* [OUTPUT]: extracted memory items (via LLM) or heuristic fallback
|
|
4
|
+
* [POS]: Dual-path extraction — LLM when available, regex heuristics otherwise
|
|
5
|
+
*/
|
|
6
|
+
import type { NanomemConfig } from "./config.js";
|
|
7
|
+
import type { ExtractedItem, ExtractedWork, LlmFn } from "./types.js";
|
|
8
|
+
export declare function extractMemories(conversation: string, cfg: NanomemConfig, llmFn?: LlmFn): Promise<ExtractedItem[]>;
|
|
9
|
+
export declare function extractWork(conversation: string, cfg: NanomemConfig, llmFn?: LlmFn): Promise<ExtractedWork | null>;
|
|
10
|
+
//# sourceMappingURL=extraction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../src/extraction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtE,wBAAsB,eAAe,CACpC,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,aAAa,EAClB,KAAK,CAAC,EAAE,KAAK,GACX,OAAO,CAAC,aAAa,EAAE,CAAC,CAG1B;AA0GD,wBAAsB,WAAW,CAChC,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,aAAa,EAClB,KAAK,CAAC,EAAE,KAAK,GACX,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAe/B"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: conversation text, LlmFn, config
|
|
3
|
+
* [OUTPUT]: extracted memory items (via LLM) or heuristic fallback
|
|
4
|
+
* [POS]: Dual-path extraction — LLM when available, regex heuristics otherwise
|
|
5
|
+
*/
|
|
6
|
+
import { PROMPTS } from "./i18n.js";
|
|
7
|
+
export async function extractMemories(conversation, cfg, llmFn) {
|
|
8
|
+
if (llmFn)
|
|
9
|
+
return extractWithLLM(conversation, cfg, llmFn);
|
|
10
|
+
return extractHeuristic(conversation);
|
|
11
|
+
}
|
|
12
|
+
async function extractWithLLM(conversation, cfg, llmFn) {
|
|
13
|
+
const p = PROMPTS[cfg.locale] ?? PROMPTS.en;
|
|
14
|
+
try {
|
|
15
|
+
const raw = await llmFn(p.extractionSystem, conversation);
|
|
16
|
+
const cleaned = raw
|
|
17
|
+
.replace(/```json?\n?/g, "")
|
|
18
|
+
.replace(/```/g, "")
|
|
19
|
+
.trim();
|
|
20
|
+
return JSON.parse(cleaned);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return extractHeuristic(conversation);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function extractHeuristic(text) {
|
|
27
|
+
const items = [];
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
const addItem = (type, content) => {
|
|
30
|
+
const trimmed = content.trim();
|
|
31
|
+
// Skip very short or already seen content
|
|
32
|
+
if (trimmed.length < 8 || seen.has(trimmed.toLowerCase()))
|
|
33
|
+
return;
|
|
34
|
+
seen.add(trimmed.toLowerCase());
|
|
35
|
+
items.push({ type, content: trimmed });
|
|
36
|
+
};
|
|
37
|
+
// Lesson patterns: errors, fixes, bugs, warnings, failures
|
|
38
|
+
const lessonPatterns = [
|
|
39
|
+
/(?:error|failed|failure)[:\s]+(.{10,120})/gi,
|
|
40
|
+
/(?:fix(?:ed)?|solved|resolved)[:\s]+(.{10,120})/gi,
|
|
41
|
+
/(?:bug|issue|problem)[:\s]+(.{10,120})/gi,
|
|
42
|
+
/(?:warning|caution)[:\s]+(.{10,80})/gi,
|
|
43
|
+
/(?:learned|remember|note)[:\s]+(.{10,120})/gi,
|
|
44
|
+
];
|
|
45
|
+
for (const pat of lessonPatterns) {
|
|
46
|
+
for (const match of text.matchAll(pat)) {
|
|
47
|
+
addItem("lesson", match[1]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Preference patterns: user style, naming, tool preferences
|
|
51
|
+
const prefPatterns = [
|
|
52
|
+
/(?:i (?:prefer|like|want|use|need)|please (?:always|never))\s+(.{5,80})/gi,
|
|
53
|
+
/(?:call me|my name is|i am called)\s+["']?([^"'\n]{2,30})["']?/gi,
|
|
54
|
+
/(?:always|never)\s+(?:use|do|add|include)\s+(.{5,60})/gi,
|
|
55
|
+
];
|
|
56
|
+
for (const pat of prefPatterns) {
|
|
57
|
+
for (const match of text.matchAll(pat)) {
|
|
58
|
+
addItem("preference", match[1]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Fact/Knowledge patterns: technical details, project structure, API info
|
|
62
|
+
const factPatterns = [
|
|
63
|
+
/(?:the (?:project|codebase|repo|app) (?:uses|has|contains))\s+(.{10,100})/gi,
|
|
64
|
+
/(?:this is a|we use|we have)\s+(.{10,80})\s+(?:project|app|system)/gi,
|
|
65
|
+
/(?:api|endpoint|route)[:\s]+(.{10,80})/gi,
|
|
66
|
+
/(?:config(?:uration)?|setting)[:\s]+(.{10,80})/gi,
|
|
67
|
+
/(?:version|v)\s*(\d+\.\d+(?:\.\d+)?)/gi,
|
|
68
|
+
];
|
|
69
|
+
for (const pat of factPatterns) {
|
|
70
|
+
for (const match of text.matchAll(pat)) {
|
|
71
|
+
addItem("fact", match[1]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Decision patterns: architectural choices, design decisions
|
|
75
|
+
const decisionPatterns = [
|
|
76
|
+
/(?:decided to|chose to|will use|going with)\s+(.{10,100})/gi,
|
|
77
|
+
/(?:because|since|reason)[:\s]+(.{15,100})/gi,
|
|
78
|
+
];
|
|
79
|
+
for (const pat of decisionPatterns) {
|
|
80
|
+
for (const match of text.matchAll(pat)) {
|
|
81
|
+
addItem("decision", match[1]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Pattern patterns: habitual user behaviors
|
|
85
|
+
const patternPatterns = [
|
|
86
|
+
/(?:i always|every time i|whenever i|my habit is|i consistently)\s+(.{10,100})/gi,
|
|
87
|
+
/(?:my approach to .{5,40} is always)\s+(.{5,80})/gi,
|
|
88
|
+
/(?:i make it a point to|i make sure to always)\s+(.{10,80})/gi,
|
|
89
|
+
];
|
|
90
|
+
for (const pat of patternPatterns) {
|
|
91
|
+
for (const match of text.matchAll(pat)) {
|
|
92
|
+
addItem("pattern", match[1]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Struggle patterns: failure experiences with resolution
|
|
96
|
+
const strugglePatterns = [
|
|
97
|
+
/(?:failed|tried .{3,30} times?|couldn't get .{5,40} to work).{0,60}(?:finally|solved|fixed|resolved)\s+(.{10,100})/gi,
|
|
98
|
+
/(?:after trying .{5,60}),?\s+(?:i solved it by|the solution was|fixed by)\s+(.{10,100})/gi,
|
|
99
|
+
/(?:struggled with .{5,40}).{0,40}(?:finally|eventually|in the end)\s+(.{10,100})/gi,
|
|
100
|
+
];
|
|
101
|
+
for (const pat of strugglePatterns) {
|
|
102
|
+
for (const match of text.matchAll(pat)) {
|
|
103
|
+
addItem("struggle", match[1]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return items.slice(0, 15);
|
|
107
|
+
}
|
|
108
|
+
export async function extractWork(conversation, cfg, llmFn) {
|
|
109
|
+
if (!llmFn)
|
|
110
|
+
return extractWorkHeuristic(conversation);
|
|
111
|
+
const p = PROMPTS[cfg.locale] ?? PROMPTS.en;
|
|
112
|
+
try {
|
|
113
|
+
const raw = await llmFn(p.workExtractionSystem, conversation);
|
|
114
|
+
const cleaned = raw
|
|
115
|
+
.replace(/```json?\n?/g, "")
|
|
116
|
+
.replace(/```/g, "")
|
|
117
|
+
.trim();
|
|
118
|
+
const result = JSON.parse(cleaned);
|
|
119
|
+
if (!result.goal && !result.summary)
|
|
120
|
+
return null;
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return extractWorkHeuristic(conversation);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function extractWorkHeuristic(text) {
|
|
128
|
+
const lines = text.split("\n").filter((l) => l.trim().length > 10);
|
|
129
|
+
if (lines.length < 3)
|
|
130
|
+
return null;
|
|
131
|
+
return {
|
|
132
|
+
goal: lines[0]?.slice(0, 100) ?? "unknown task",
|
|
133
|
+
summary: `Session with ${lines.length} exchanges`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=extraction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction.js","sourceRoot":"","sources":["../src/extraction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,YAAoB,EACpB,GAAkB,EAClB,KAAa;IAEb,IAAI,KAAK;QAAE,OAAO,cAAc,CAAC,YAAY,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3D,OAAO,gBAAgB,CAAC,YAAY,CAAC,CAAC;AACvC,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,YAAoB,EAAE,GAAkB,EAAE,KAAY;IACnF,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC;IAC5C,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,GAAG;aACjB,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;aAC3B,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;aACnB,IAAI,EAAE,CAAC;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,gBAAgB,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC;AACF,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACrC,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,OAAO,GAAG,CAAC,IAA2B,EAAE,OAAe,EAAE,EAAE;QAChE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,0CAA0C;QAC1C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO;QAClE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC;IAEF,2DAA2D;IAC3D,MAAM,cAAc,GAAG;QACtB,6CAA6C;QAC7C,mDAAmD;QACnD,0CAA0C;QAC1C,uCAAuC;QACvC,8CAA8C;KAC9C,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QAClC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAC9B,CAAC;IACF,CAAC;IAED,4DAA4D;IAC5D,MAAM,YAAY,GAAG;QACpB,2EAA2E;QAC3E,kEAAkE;QAClE,yDAAyD;KACzD,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAClC,CAAC;IACF,CAAC;IAED,0EAA0E;IAC1E,MAAM,YAAY,GAAG;QACpB,6EAA6E;QAC7E,sEAAsE;QACtE,0CAA0C;QAC1C,kDAAkD;QAClD,wCAAwC;KACxC,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAC5B,CAAC;IACF,CAAC;IAED,6DAA6D;IAC7D,MAAM,gBAAgB,GAAG;QACxB,6DAA6D;QAC7D,6CAA6C;KAC7C,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAED,4CAA4C;IAC5C,MAAM,eAAe,GAAG;QACvB,iFAAiF;QACjF,oDAAoD;QACpD,+DAA+D;KAC/D,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAC/B,CAAC;IACF,CAAC;IAED,yDAAyD;IACzD,MAAM,gBAAgB,GAAG;QACxB,sHAAsH;QACtH,2FAA2F;QAC3F,oFAAoF;KACpF,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,YAAoB,EACpB,GAAkB,EAClB,KAAa;IAEb,IAAI,CAAC,KAAK;QAAE,OAAO,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC;IAC5C,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,oBAAoB,EAAE,YAAY,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,GAAG;aACjB,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;aAC3B,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;aACnB,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QACjD,OAAO,MAAM,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;AACF,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACnE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO;QACN,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,cAAc;QAC/C,OAAO,EAAE,gBAAgB,KAAK,CAAC,MAAM,YAAY;KACjD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: FullInsightsReport, locale
|
|
3
|
+
* [OUTPUT]: Standalone HTML report with Remix Icon and charts
|
|
4
|
+
* [POS]: Pure renderer for full insights report
|
|
5
|
+
*/
|
|
6
|
+
import type { FullInsightsReport } from "./types.js";
|
|
7
|
+
export declare function renderFullInsightsHtml(report: FullInsightsReport, locale: string): string;
|
|
8
|
+
//# sourceMappingURL=full-insights-html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"full-insights-html.d.ts","sourceRoot":"","sources":["../src/full-insights-html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAGX,kBAAkB,EAIlB,MAAM,YAAY,CAAC;AAuCpB,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAgSzF"}
|