@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.
Files changed (93) hide show
  1. package/CLAUDE.md +258 -0
  2. package/README.md +146 -0
  3. package/dist/cli.d.ts +8 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +90 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config.d.ts +46 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +48 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/consolidation.d.ts +13 -0
  12. package/dist/consolidation.d.ts.map +1 -0
  13. package/dist/consolidation.js +111 -0
  14. package/dist/consolidation.js.map +1 -0
  15. package/dist/engine.d.ts +67 -0
  16. package/dist/engine.d.ts.map +1 -0
  17. package/dist/engine.js +492 -0
  18. package/dist/engine.js.map +1 -0
  19. package/dist/eviction.d.ts +16 -0
  20. package/dist/eviction.d.ts.map +1 -0
  21. package/dist/eviction.js +22 -0
  22. package/dist/eviction.js.map +1 -0
  23. package/dist/extension.d.ts +11 -0
  24. package/dist/extension.d.ts.map +1 -0
  25. package/dist/extension.js +264 -0
  26. package/dist/extension.js.map +1 -0
  27. package/dist/extraction.d.ts +10 -0
  28. package/dist/extraction.d.ts.map +1 -0
  29. package/dist/extraction.js +136 -0
  30. package/dist/extraction.js.map +1 -0
  31. package/dist/full-insights-html.d.ts +8 -0
  32. package/dist/full-insights-html.d.ts.map +1 -0
  33. package/dist/full-insights-html.js +311 -0
  34. package/dist/full-insights-html.js.map +1 -0
  35. package/dist/full-insights.d.ts +21 -0
  36. package/dist/full-insights.d.ts.map +1 -0
  37. package/dist/full-insights.js +327 -0
  38. package/dist/full-insights.js.map +1 -0
  39. package/dist/i18n.d.ts +50 -0
  40. package/dist/i18n.d.ts.map +1 -0
  41. package/dist/i18n.js +169 -0
  42. package/dist/i18n.js.map +1 -0
  43. package/dist/index.d.ts +18 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +14 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/insights-html.d.ts +8 -0
  48. package/dist/insights-html.d.ts.map +1 -0
  49. package/dist/insights-html.js +431 -0
  50. package/dist/insights-html.js.map +1 -0
  51. package/dist/linking.d.ts +11 -0
  52. package/dist/linking.d.ts.map +1 -0
  53. package/dist/linking.js +40 -0
  54. package/dist/linking.js.map +1 -0
  55. package/dist/privacy.d.ts +16 -0
  56. package/dist/privacy.d.ts.map +1 -0
  57. package/dist/privacy.js +52 -0
  58. package/dist/privacy.js.map +1 -0
  59. package/dist/scoring.d.ts +25 -0
  60. package/dist/scoring.d.ts.map +1 -0
  61. package/dist/scoring.js +63 -0
  62. package/dist/scoring.js.map +1 -0
  63. package/dist/store.d.ts +16 -0
  64. package/dist/store.d.ts.map +1 -0
  65. package/dist/store.js +68 -0
  66. package/dist/store.js.map +1 -0
  67. package/dist/types.d.ts +191 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +7 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/update.d.ts +14 -0
  72. package/dist/update.d.ts.map +1 -0
  73. package/dist/update.js +126 -0
  74. package/dist/update.js.map +1 -0
  75. package/package.json +60 -0
  76. package/src/cli.ts +99 -0
  77. package/src/config.ts +72 -0
  78. package/src/consolidation.ts +127 -0
  79. package/src/engine.ts +699 -0
  80. package/src/eviction.ts +30 -0
  81. package/src/extension.ts +290 -0
  82. package/src/extraction.ts +152 -0
  83. package/src/full-insights-html.ts +342 -0
  84. package/src/full-insights.ts +396 -0
  85. package/src/i18n.ts +233 -0
  86. package/src/index.ts +50 -0
  87. package/src/insights-html.ts +476 -0
  88. package/src/linking.ts +43 -0
  89. package/src/privacy.ts +52 -0
  90. package/src/scoring.ts +94 -0
  91. package/src/store.ts +84 -0
  92. package/src/types.ts +209 -0
  93. package/src/update.ts +141 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,258 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ NanoMem is a TypeScript-based persistent memory management system for AI assistants. It implements a sophisticated memory architecture with spaced repetition, intelligent eviction, privacy controls, and AI-powered memory extraction.
8
+
9
+ **Key characteristics:**
10
+ - Pure TypeScript ESM modules (no build step, requires Node.js 20+ with TypeScript execution via tsx or similar)
11
+ - JSON file-based persistence in `~/.nanomem/memory`
12
+ - Pluggable LLM integration - works with any LLM provider via a simple function signature
13
+ - Bilingual support (English/Chinese) for prompts and UI
14
+
15
+ ## Running the Code
16
+
17
+ This project uses `.ts` imports and requires TypeScript execution:
18
+
19
+ ```bash
20
+ # Run the CLI directly with tsx
21
+ npx tsx cli.ts stats
22
+ npx tsx cli.ts search "query"
23
+ npx tsx cli.ts insights
24
+
25
+ # Or use node with --loader
26
+ node --loader tsx cli.ts stats
27
+ ```
28
+
29
+ ## Environment Configuration
30
+
31
+ Configure via environment variables:
32
+
33
+ - `NANOMEM_TOKEN_BUDGET` - Total token budget for memory injection (default: 6000)
34
+ - `NANOMEM_MEMORY_DIR` - Directory for JSON storage (default: `~/.nanomem/memory`)
35
+ - `NANOMEM_LOCALE` - Language locale: `en` or `zh` (default: `en`)
36
+
37
+ ## Architecture Overview
38
+
39
+ The codebase follows a clean layered architecture with clear module boundaries:
40
+
41
+ ### Core Engine (`engine.ts`)
42
+ The `NanoMemEngine` class is the main API facade. It orchestrates all other modules and provides:
43
+ - Memory extraction and storage from conversations
44
+ - Episode management and consolidation
45
+ - Memory retrieval with budget-aware injection
46
+ - Statistics and insights generation
47
+
48
+ ### Memory Storage (`store.ts`)
49
+ JSON-based persistence with automatic directory creation. Stores data in separate files:
50
+ - `knowledge.json` - Facts, entities, decisions
51
+ - `lessons.json` - Lessons learned
52
+ - `preferences.json` - User preferences
53
+ - `facets.json` - Patterns and struggles (behavioral insights)
54
+ - `work.json` - Work/task history
55
+ - `episodes/*.json` - Session summaries
56
+ - `meta.json` - Metadata (session count, last consolidation)
57
+
58
+ ### Memory Types (`types.ts`)
59
+
60
+ **MemoryEntry** - Core memory types:
61
+ - `fact` - Technical knowledge, project structure, API details
62
+ - `lesson` - Mistakes, solutions, debugging insights
63
+ - `preference` - User style, naming, tool preferences
64
+ - `decision` - Architectural choices, design trade-offs
65
+ - `entity` - Named entities (people, services, etc.)
66
+ - `pattern` - Habitual user behaviors (with `facetData`)
67
+ - `struggle` - Failure experiences with resolution (with `facetData`)
68
+
69
+ **FacetData** - Structured data for behavioral insights:
70
+ ```typescript
71
+ type FacetData =
72
+ | { kind: "pattern"; trigger: string; behavior: string }
73
+ | { kind: "struggle"; problem: string; attempts: string[]; solution: string }
74
+ ```
75
+
76
+ **Episode** - Session summaries with metadata (files, tools, errors, observations)
77
+
78
+ **WorkEntry** - Task-oriented memories with goal and summary
79
+
80
+ ### Key Algorithms
81
+
82
+ **Spaced Repetition** (`scoring.ts`, `engine.ts`):
83
+ - Memory `strength` grows with each successful recall (Ebbinghaus model)
84
+ - Growth factor configurable via `strengthGrowthFactor` (default: 1.5)
85
+ - Strength used in retrieval scoring
86
+
87
+ **Scoring System** (`scoring.ts`):
88
+ - Stanford-style retrieval scoring with three components:
89
+ - `recency` - Based on `strength` (half-life decay)
90
+ - `importance` - Explicit 1-10 rating
91
+ - `relevance` - Tag overlap with context
92
+ - Weights configurable via `scoreWeights`
93
+
94
+ **Eviction** (`eviction.ts`):
95
+ - Utility-based eviction: combines access frequency and base impact
96
+ - Different half-life values per memory type (configurable)
97
+ - Enforces `maxEntries` limits per memory type
98
+
99
+ **Memory Linking** (`linking.ts`):
100
+ - A-MEM style relationship discovery between memories
101
+ - Uses tag overlap and semantic similarity
102
+ - Related memories shown in injection: `fact content [→ related; summaries]`
103
+
104
+ ### Dual-Path Extraction (`extraction.ts`)
105
+
106
+ The system works with or without an LLM:
107
+ 1. **LLM path**: Uses `LlmFn` to extract structured memories from conversations
108
+ 2. **Heuristic fallback**: Pattern-based extraction when no LLM available
109
+
110
+ ### Privacy & Scoping (`privacy.ts`)
111
+
112
+ - **PII filtering**: Basic PII redaction from memories
113
+ - **Scoping**: Multi-user support via `MemoryScope` (`userId`, `agentId`)
114
+ - **TTL**: Time-to-live based auto-eviction
115
+ - **Scope filtering**: All retrieval operations respect scope
116
+
117
+ ### Consolidation (`consolidation.ts`)
118
+
119
+ - Batch processing of episode summaries into long-term memories
120
+ - Runs automatically on session start
121
+ - Marks episodes as `consolidated: true`
122
+
123
+ ### Internationalization (`i18n.ts`)
124
+
125
+ All user-facing strings and LLM prompts support English and Chinese:
126
+ - Extraction prompts
127
+ - Injection section headers
128
+ - Memory behavior instructions
129
+ - Insights generation prompts
130
+
131
+ ## Extension Integration (`extension.ts`)
132
+
133
+ The only module depending on `@pencil-agent/nano-pencil`. Bridges NanoPencil events to the engine:
134
+
135
+ **Lifecycle hooks:**
136
+ - `session_start` - Triggers consolidation
137
+ - `before_agent_start` - Injects memory into system prompt
138
+ - `tool_execution_start/end` - Tracks tool usage and observations
139
+ - `agent_end` - Extracts memories from conversation
140
+ - `session_shutdown` - Saves episode summary
141
+
142
+ **Registered commands:**
143
+ - `mem-search <query>` - Search memories
144
+ - `mem-stats` - Show statistics
145
+ - `mem-insights [path]` - Generate HTML report
146
+
147
+ ## Configuration System (`config.ts`)
148
+
149
+ Comprehensive configuration via `getConfig(overrides)`:
150
+
151
+ ```typescript
152
+ {
153
+ memoryDir: string, // Storage location
154
+ tokenBudget: number, // Total tokens for injection
155
+ budget: { // Allocation ratios per memory type
156
+ lessons: number,
157
+ knowledge: number,
158
+ episodes: number,
159
+ preferences: number,
160
+ work: number,
161
+ facets: number
162
+ },
163
+ halfLife: Record<string, number>, // Decay rates per type
164
+ maxEntries: {...}, // Capacity limits per type
165
+ consolidationThreshold: number, // Episodes before consolidation
166
+ scoreWeights: { recency, importance, relevance },
167
+ evictionWeights: { accessFrequency, baseImpact },
168
+ defaultScope?: MemoryScope,
169
+ locale: "en" | "zh",
170
+ strengthGrowthFactor: number
171
+ }
172
+ ```
173
+
174
+ ## Memory Injection Format
175
+
176
+ Generated memory injection follows this structure:
177
+
178
+ ```markdown
179
+ ## Long-term Memory
180
+
181
+ ### Lessons Learned
182
+ - lesson content
183
+
184
+ ### Knowledge Base
185
+ - fact content [→ related; summaries]
186
+
187
+ ### Recent Sessions
188
+ - [date] project: summary (Goal: user goal)
189
+
190
+ ### User Preferences
191
+ - preference content
192
+
193
+ ### Work History
194
+ - [date] goal: summary
195
+
196
+ ### Behavioral Patterns
197
+ - When trigger → behavior
198
+
199
+ ### Past Struggles
200
+ - Problem: problem | Tried: attempt1, attempt2 | Solved: solution
201
+
202
+ ---
203
+ IMPORTANT: These memories are your personal recollections...
204
+ (memory behavior instructions - natural memory usage)
205
+ ```
206
+
207
+ ## Important Patterns
208
+
209
+ ### POS Comments
210
+ Each file has a `[POS]` comment explaining its position in the architecture. These describe the module's role and dependencies.
211
+
212
+ ### LLM Function Type
213
+ ```typescript
214
+ type LlmFn = (systemPrompt: string, userMessage: string) => Promise<string>;
215
+ ```
216
+ Simple async function - host products provide their own LLM integration.
217
+
218
+ ### Graceful Degradation
219
+ The system works without an LLM through heuristic extraction. LLM features fail silently and fall back to rules-based behavior.
220
+
221
+ ### Bi-temporal Memory
222
+ - `created` - When the system recorded the memory
223
+ - `eventTime` - When the fact actually occurred (optional)
224
+
225
+ ### Update Operations (`update.ts`)
226
+ Mem0-style updates: `add | update | delete | noop` based on content similarity and explicit retraction.
227
+
228
+ ### Export/Import
229
+ Full data export available via `exportAll()` - returns all memories, episodes, and metadata.
230
+
231
+ ## CLI Usage (`cli.ts`)
232
+
233
+ ```bash
234
+ nanomem stats # Show memory counts
235
+ nanomem search <query> # Search memories
236
+ nanomem forget <id> # Delete a memory
237
+ nanomem export # Export all as JSON
238
+ nanomem insights [--output <path>] # Generate HTML report
239
+ ```
240
+
241
+ ## Files Reference
242
+
243
+ - `index.ts` - Barrel export (public API surface)
244
+ - `engine.ts` - Main engine class (690 lines)
245
+ - `config.ts` - Configuration management
246
+ - `types.ts` - All type definitions
247
+ - `store.ts` - JSON persistence layer
248
+ - `extraction.ts` - Memory extraction (LLM + heuristic)
249
+ - `consolidation.ts` - Episode consolidation
250
+ - `scoring.ts` - Retrieval and ranking algorithms
251
+ - `privacy.ts` - PII filtering, scoping, TTL
252
+ - `linking.ts` - Memory relationship discovery
253
+ - `i18n.ts` - Internationalization (en/zh)
254
+ - `eviction.ts` - Memory eviction algorithms
255
+ - `update.ts` - Memory update operations
256
+ - `extension.ts` - NanoPencil extension adapter
257
+ - `insights-html.ts` - HTML report generation
258
+ - `cli.ts` - Standalone CLI tool
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # @nanopencil/nanomem
2
+
3
+ > Persistent memory engine for AI coding agents with consolidation, scoring, and insights.
4
+
5
+ ## Features
6
+
7
+ - **Dual-path extraction**: LLM-based or heuristic regex fallback
8
+ - **Seven memory types**: Knowledge, Lessons, Preferences, Decisions, Entities, Patterns, Struggles
9
+ - **Stanford-style scoring**: Recency, importance, and relevance weighting
10
+ - **Utility-based eviction**: Access frequency vs base impact
11
+ - **A-MEM style linking**: Automatic memory association
12
+ - **Mem0-style updates**: Add, update, delete, retract operations
13
+ - **Spaced repetition**: Ebbinghaus forgetting curve reinforcement
14
+ - **Privacy protection**: PII filtering and TTL expiration
15
+ - **Bilingual prompts**: Chinese and English support
16
+ - **Insights reports**: Pattern/struggle analysis with recommendations
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @nanopencil/nanomem
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ```typescript
27
+ import { NanoMemEngine, getConfig } from '@nanopencil/nanomem';
28
+
29
+ // Create engine with defaults
30
+ const engine = new NanoMemEngine();
31
+
32
+ // Extract memories from conversation
33
+ const items = await engine.extractAndStore(
34
+ "User: The API endpoint is /api/v1/users\nAssistant: Got it, I'll remember.",
35
+ "my-project"
36
+ );
37
+
38
+ // Get memory injection for system prompt
39
+ const injection = await engine.getMemoryInjection(
40
+ "my-project",
41
+ ["api", "rest", "typescript"]
42
+ );
43
+
44
+ console.log(injection);
45
+ // ## Memory Injection
46
+ //
47
+ // ### Knowledge
48
+ // - The API endpoint is /api/v1/users
49
+ //
50
+ // ---
51
+ // This memory injection is based on your conversation history...
52
+ ```
53
+
54
+ ## Memory Types
55
+
56
+ | Type | Purpose | Half-Life |
57
+ |------|---------|-----------|
58
+ | `knowledge` | Project facts, API info | 60 days |
59
+ | `lessons` | Errors, solutions, learnings | 90 days |
60
+ | `preferences` | User preferences, style habits | 120 days |
61
+ | `decisions` | Architectural choices | 45 days |
62
+ | `entities` | Named entities (people, projects) | 30 days |
63
+ | `patterns` | Behavioral patterns (trigger→behavior) | 180 days |
64
+ | `struggles` | Struggle experiences (problem→attempts→solution) | 120 days |
65
+ | `work` | Work summaries (goal + summary) | 45 days |
66
+
67
+ ## Configuration
68
+
69
+ ```typescript
70
+ import { NanoMemEngine, getConfig } from '@nanopencil/nanomem';
71
+
72
+ const config = getConfig({
73
+ memoryDir: './my-memory',
74
+ tokenBudget: 8000,
75
+ budget: {
76
+ lessons: 0.25,
77
+ knowledge: 0.25,
78
+ episodes: 0.15,
79
+ preferences: 0.1,
80
+ work: 0.15,
81
+ facets: 0.1
82
+ },
83
+ halfLife: {
84
+ lesson: 90,
85
+ fact: 60,
86
+ pattern: 180
87
+ },
88
+ locale: 'zh' // or 'en'
89
+ });
90
+
91
+ const engine = new NanoMemEngine(config);
92
+ ```
93
+
94
+ ## API Reference
95
+
96
+ ### Constructor
97
+
98
+ ```typescript
99
+ constructor(overrides?: Partial<NanomemConfig>, llmFn?: LlmFn)
100
+ ```
101
+
102
+ ### Methods
103
+
104
+ - `extractAndStore(conversation, project)` - Extract and store memories
105
+ - `getMemoryInjection(project, contextTags, scope?)` - Get memory for system prompt
106
+ - `saveEpisode(episode)` - Save a conversation episode
107
+ - `consolidate()` - Consolidate episodes into long-term memory
108
+ - `searchEntries(query, scope?)` - Search memories
109
+ - `forgetEntry(id)` - Delete a memory
110
+ - `getStats()` - Get memory statistics
111
+ - `generateInsights()` - Generate insights report
112
+
113
+ ### Extension Integration
114
+
115
+ For NanoPencil integration:
116
+
117
+ ```typescript
118
+ import nanomemExtension from '@nanopencil/nanomem/extension';
119
+
120
+ // In NanoPencil
121
+ pi.registerExtension(() => nanomemExtension);
122
+ ```
123
+
124
+ ## Storage Structure
125
+
126
+ ```
127
+ ~/.nanomem/memory/
128
+ ├── knowledge.json
129
+ ├── lessons.json
130
+ ├── preferences.json
131
+ ├── facets.json
132
+ ├── work.json
133
+ ├── meta.json
134
+ └── episodes/
135
+ ├── *.jsonl
136
+ ```
137
+
138
+ ## Environment Variables
139
+
140
+ - `NANOMEM_MEMORY_DIR` - Override memory directory (default: `~/.nanomem/memory`)
141
+ - `NANOMEM_TOKEN_BUDGET` - Token budget for injections (default: 6000)
142
+ - `NANOMEM_LOCALE` - Locale for prompts (`en` or `zh`, default: `en`)
143
+
144
+ ## License
145
+
146
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * [INPUT]: process.argv
4
+ * [OUTPUT]: stats | search <query> | forget <id> | export | insights — terminal output or JSON or HTML
5
+ * [POS]: Standalone CLI for NanoMem — no host dependency
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;GAIG"}
package/dist/cli.js ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * [INPUT]: process.argv
4
+ * [OUTPUT]: stats | search <query> | forget <id> | export | insights — terminal output or JSON or HTML
5
+ * [POS]: Standalone CLI for NanoMem — no host dependency
6
+ */
7
+ import { writeFileSync } from "node:fs";
8
+ import { NanoMemEngine } from "./engine.js";
9
+ import { renderFullInsightsHtml } from "./full-insights-html.js";
10
+ import { renderInsightsHtml } from "./insights-html.js";
11
+ const args = process.argv.slice(2);
12
+ const sub = args[0];
13
+ const engine = new NanoMemEngine();
14
+ async function main() {
15
+ if (!sub || sub === "help" || sub === "-h" || sub === "--help") {
16
+ console.log(`nanomem — NanoMem memory CLI
17
+
18
+ Usage:
19
+ nanomem stats Show memory counts (sessions, knowledge, lessons, preferences, work, episodes, facets)
20
+ nanomem search <query> Search memories by query text
21
+ nanomem forget <id> Remove a memory entry by ID
22
+ nanomem export Export all memories as JSON to stdout
23
+ nanomem insights [--output <path>] Generate full HTML insights report (default: ./nanomem-insights.html)
24
+ nanomem insights --simple [--output <path>] Generate simple insights report (rules-only, no LLM)
25
+ nanomem help Show this help
26
+ `);
27
+ return;
28
+ }
29
+ if (sub === "stats") {
30
+ const s = await engine.getStats();
31
+ console.log(`Sessions: ${s.totalSessions}`);
32
+ console.log(`Knowledge: ${s.knowledge}`);
33
+ console.log(`Lessons: ${s.lessons}`);
34
+ console.log(`Preferences: ${s.preferences}`);
35
+ console.log(`Work: ${s.work}`);
36
+ console.log(`Episodes: ${s.episodes}`);
37
+ return;
38
+ }
39
+ if (sub === "search") {
40
+ const query = args.slice(1).join(" ").trim() || " ";
41
+ const results = await engine.searchEntries(query);
42
+ if (!results.length) {
43
+ console.log("No matching memories.");
44
+ return;
45
+ }
46
+ for (const e of results) {
47
+ console.log(`[${e.type}] ${e.id} — ${e.content.slice(0, 100)}`);
48
+ }
49
+ return;
50
+ }
51
+ if (sub === "forget") {
52
+ const id = args[1];
53
+ if (!id) {
54
+ console.error("Usage: nanomem forget <id>");
55
+ process.exit(1);
56
+ }
57
+ const ok = await engine.forgetEntry(id);
58
+ console.log(ok ? `Removed entry ${id}` : `Entry ${id} not found`);
59
+ return;
60
+ }
61
+ if (sub === "export") {
62
+ const data = await engine.exportAll();
63
+ console.log(JSON.stringify(data, null, 2));
64
+ return;
65
+ }
66
+ if (sub === "insights") {
67
+ const simple = args.includes("--simple");
68
+ const outputIdx = args.indexOf("--output");
69
+ const outputPath = outputIdx >= 0 && args[outputIdx + 1] ? args[outputIdx + 1] : "./nanomem-insights.html";
70
+ if (simple) {
71
+ const report = await engine.generateInsights();
72
+ const html = renderInsightsHtml(report, engine.cfg.locale);
73
+ writeFileSync(outputPath, html, "utf-8");
74
+ }
75
+ else {
76
+ const report = await engine.generateFullInsights();
77
+ const html = renderFullInsightsHtml(report, engine.cfg.locale);
78
+ writeFileSync(outputPath, html, "utf-8");
79
+ }
80
+ console.log(`Insights report written to: ${outputPath}`);
81
+ return;
82
+ }
83
+ console.error(`Unknown command: ${sub}. Run 'nanomem help' for usage.`);
84
+ process.exit(1);
85
+ }
86
+ main().catch((err) => {
87
+ console.error(err);
88
+ process.exit(1);
89
+ });
90
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * [INPUT]: process.env, optional overrides
3
+ * [OUTPUT]: NanomemConfig — memory dir, token budget, scoring weights, etc.
4
+ * [POS]: Shared by engine and adapters; host products configure via this
5
+ */
6
+ import type { MemoryScope } from "./types.js";
7
+ export interface NanomemConfig {
8
+ memoryDir: string;
9
+ tokenBudget: number;
10
+ budget: {
11
+ lessons: number;
12
+ knowledge: number;
13
+ episodes: number;
14
+ preferences: number;
15
+ work: number;
16
+ facets: number;
17
+ };
18
+ halfLife: Record<string, number>;
19
+ maxEntries: {
20
+ knowledge: number;
21
+ lessons: number;
22
+ preferences: number;
23
+ work: number;
24
+ facets: number;
25
+ };
26
+ consolidationThreshold: number;
27
+ /** Stanford-style retrieval scoring weights */
28
+ scoreWeights: {
29
+ recency: number;
30
+ importance: number;
31
+ relevance: number;
32
+ };
33
+ /** Utility-weighted eviction: access frequency vs base impact */
34
+ evictionWeights: {
35
+ accessFrequency: number;
36
+ baseImpact: number;
37
+ };
38
+ /** Default scope for all operations */
39
+ defaultScope?: MemoryScope;
40
+ /** Locale for LLM prompts and injection templates */
41
+ locale: "en" | "zh";
42
+ /** Strength growth factor on each successful recall (spaced repetition) */
43
+ strengthGrowthFactor: number;
44
+ }
45
+ export declare function getConfig(overrides?: Partial<NanomemConfig>): NanomemConfig;
46
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACtG,sBAAsB,EAAE,MAAM,CAAC;IAC/B,+CAA+C;IAC/C,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACzE,iEAAiE;IACjE,eAAe,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,uCAAuC;IACvC,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,qDAAqD;IACrD,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,2EAA2E;IAC3E,oBAAoB,EAAE,MAAM,CAAC;CAC7B;AA2BD,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAiB3E"}
package/dist/config.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * [INPUT]: process.env, optional overrides
3
+ * [OUTPUT]: NanomemConfig — memory dir, token budget, scoring weights, etc.
4
+ * [POS]: Shared by engine and adapters; host products configure via this
5
+ */
6
+ import { homedir } from "node:os";
7
+ import { join } from "node:path";
8
+ const DEFAULT_BUDGET = {
9
+ lessons: 0.2,
10
+ knowledge: 0.2,
11
+ episodes: 0.18,
12
+ preferences: 0.1,
13
+ work: 0.2,
14
+ facets: 0.12,
15
+ };
16
+ const DEFAULT_HALF_LIFE = {
17
+ lesson: 90,
18
+ fact: 60,
19
+ episode: 14,
20
+ preference: 120,
21
+ decision: 45,
22
+ entity: 30,
23
+ work: 45,
24
+ pattern: 180,
25
+ struggle: 120,
26
+ };
27
+ const DEFAULT_MAX_ENTRIES = { knowledge: 200, lessons: 100, preferences: 50, work: 80, facets: 80 };
28
+ const DEFAULT_SCORE_WEIGHTS = { recency: 1, importance: 1, relevance: 1 };
29
+ const DEFAULT_EVICTION_WEIGHTS = { accessFrequency: 0.4, baseImpact: 0.6 };
30
+ export function getConfig(overrides) {
31
+ const tokenBudget = Number(process.env.NANOMEM_TOKEN_BUDGET) || 6000;
32
+ const memoryDir = process.env.NANOMEM_MEMORY_DIR || overrides?.memoryDir || join(homedir(), ".nanomem", "memory");
33
+ const locale = process.env.NANOMEM_LOCALE || overrides?.locale || "en";
34
+ return {
35
+ memoryDir,
36
+ tokenBudget: overrides?.tokenBudget ?? tokenBudget,
37
+ budget: overrides?.budget ?? { ...DEFAULT_BUDGET },
38
+ halfLife: overrides?.halfLife ?? { ...DEFAULT_HALF_LIFE },
39
+ maxEntries: overrides?.maxEntries ?? { ...DEFAULT_MAX_ENTRIES },
40
+ consolidationThreshold: overrides?.consolidationThreshold ?? 10,
41
+ scoreWeights: overrides?.scoreWeights ?? { ...DEFAULT_SCORE_WEIGHTS },
42
+ evictionWeights: overrides?.evictionWeights ?? { ...DEFAULT_EVICTION_WEIGHTS },
43
+ defaultScope: overrides?.defaultScope,
44
+ locale,
45
+ strengthGrowthFactor: overrides?.strengthGrowthFactor ?? 1.5,
46
+ };
47
+ }
48
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAsBjC,MAAM,cAAc,GAAG;IACtB,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;IACd,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,GAAG;IAChB,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,IAAI;CACH,CAAC;AAEX,MAAM,iBAAiB,GAA2B;IACjD,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,EAAE;IACX,UAAU,EAAE,GAAG;IACf,QAAQ,EAAE,EAAE;IACZ,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,GAAG;CACb,CAAC;AAEF,MAAM,mBAAmB,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACpG,MAAM,qBAAqB,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;AAC1E,MAAM,wBAAwB,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AAE3E,MAAM,UAAU,SAAS,CAAC,SAAkC;IAC3D,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC;IACrE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAClH,MAAM,MAAM,GAAI,OAAO,CAAC,GAAG,CAAC,cAA8B,IAAI,SAAS,EAAE,MAAM,IAAI,IAAI,CAAC;IACxF,OAAO;QACN,SAAS;QACT,WAAW,EAAE,SAAS,EAAE,WAAW,IAAI,WAAW;QAClD,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,EAAE,GAAG,cAAc,EAAE;QAClD,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE,GAAG,iBAAiB,EAAE;QACzD,UAAU,EAAE,SAAS,EAAE,UAAU,IAAI,EAAE,GAAG,mBAAmB,EAAE;QAC/D,sBAAsB,EAAE,SAAS,EAAE,sBAAsB,IAAI,EAAE;QAC/D,YAAY,EAAE,SAAS,EAAE,YAAY,IAAI,EAAE,GAAG,qBAAqB,EAAE;QACrE,eAAe,EAAE,SAAS,EAAE,eAAe,IAAI,EAAE,GAAG,wBAAwB,EAAE;QAC9E,YAAY,EAAE,SAAS,EAAE,YAAY;QACrC,MAAM;QACN,oBAAoB,EAAE,SAAS,EAAE,oBAAoB,IAAI,GAAG;KAC5D,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * [INPUT]: unconsolidated episodes, LlmFn (optional), config
3
+ * [OUTPUT]: newly extracted MemoryEntries (facts + lessons) promoted to long-term storage
4
+ * [POS]: Episodic→Semantic consolidation — heart of multi-store memory model
5
+ *
6
+ * Two modes:
7
+ * LLM-powered (preferred): produces high-quality semantic extraction
8
+ * Heuristic fallback: frequency-based file/error extraction
9
+ */
10
+ import type { NanomemConfig } from "./config.js";
11
+ import type { Episode, LlmFn, MemoryEntry } from "./types.js";
12
+ export declare function consolidateEpisodes(episodes: Episode[], cfg: NanomemConfig, llmFn?: LlmFn): Promise<MemoryEntry[]>;
13
+ //# sourceMappingURL=consolidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidation.d.ts","sourceRoot":"","sources":["../src/consolidation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9D,wBAAsB,mBAAmB,CACxC,QAAQ,EAAE,OAAO,EAAE,EACnB,GAAG,EAAE,aAAa,EAClB,KAAK,CAAC,EAAE,KAAK,GACX,OAAO,CAAC,WAAW,EAAE,CAAC,CAaxB"}