@cogmem/engram 0.2.1 → 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 CHANGED
@@ -19,6 +19,22 @@ bun install -g @cogmem/engram
19
19
  engram --help
20
20
  ```
21
21
 
22
+ ### Quick Setup for AI Editors
23
+
24
+ The `install` command sets up the skill file and MCP server config for your editor:
25
+
26
+ ```bash
27
+ engram install # interactive — prompts for provider + scope
28
+ engram install --provider claude --global # skill → ~/.claude/skills/, MCP → ~/.claude.json
29
+ engram install --provider claude --project # skill → .claude/skills/, MCP → .mcp.json
30
+ engram install --provider claude --global --dry-run # preview without writing files
31
+ ```
32
+
33
+ This installs two things:
34
+
35
+ 1. **SKILL.md** — a cognitive protocol that teaches agents how to use engram effectively
36
+ 2. **MCP config** — adds the engram server to your editor's MCP settings
37
+
22
38
  ## The Science
23
39
 
24
40
  engram is built on memory research. Every design decision traces back to how the brain operates.
@@ -27,12 +43,12 @@ engram is built on memory research. Every design decision traces back to how the
27
43
 
28
44
  The brain has distinct memory systems with different properties:
29
45
 
30
- | System | Brain Region | Duration | engram Mapping |
31
- |---|---|---|---|
32
- | **Working Memory** | Prefrontal Cortex | Seconds | `engram focus` — capacity-limited buffer (Miller's Law: 7 ± 2 items) |
33
- | **Episodic Memory** | Hippocampus → Neocortex | Minutes to lifetime | Contextual experiences — the *what, when, where, how it felt* |
34
- | **Semantic Memory** | Neocortex | Very long-term | Facts and concepts, detached from when you learned them |
35
- | **Procedural Memory** | Basal Ganglia | Lifetime | Skills and habits — immune to decay, expressed through action |
46
+ | System | Brain Region | Duration | engram Mapping |
47
+ | --------------------- | ----------------------- | ------------------- | -------------------------------------------------------------------- |
48
+ | **Working Memory** | Prefrontal Cortex | Seconds | `engram focus` — capacity-limited buffer (Miller's Law: 7 ± 2 items) |
49
+ | **Episodic Memory** | Hippocampus → Neocortex | Minutes to lifetime | Contextual experiences — the _what, when, where, how it felt_ |
50
+ | **Semantic Memory** | Neocortex | Very long-term | Facts and concepts, detached from when you learned them |
51
+ | **Procedural Memory** | Basal Ganglia | Lifetime | Skills and habits — immune to decay, expressed through action |
36
52
 
37
53
  ### ACT-R Activation Model
38
54
 
@@ -78,7 +94,7 @@ When one memory is activated, activation spreads along associative links to rela
78
94
  S_ji = S - ln(fan_j)
79
95
  ```
80
96
 
81
- Memories with many connections receive *less* boost from each (diffusion). Specific cues work better than generic ones.
97
+ Memories with many connections receive _less_ boost from each (diffusion). Specific cues work better than generic ones.
82
98
 
83
99
  ### Consolidation (Sleep)
84
100
 
@@ -158,7 +174,7 @@ engram exposes its cognitive model as an MCP (Model Context Protocol) server, so
158
174
 
159
175
  ### Setup
160
176
 
161
- Add to your MCP client configuration (e.g., Claude Code `settings.json`):
177
+ The easiest way is `engram install` (see above). To configure manually, add to your MCP client configuration:
162
178
 
163
179
  ```json
164
180
  {
@@ -173,11 +189,11 @@ Add to your MCP client configuration (e.g., Claude Code `settings.json`):
173
189
 
174
190
  ### Available Tools
175
191
 
176
- | Tool | Description |
177
- |---|---|
178
- | `memory_store` | Encode new memories or reconsolidate existing ones |
192
+ | Tool | Description |
193
+ | --------------- | ------------------------------------------------------- |
194
+ | `memory_store` | Encode new memories or reconsolidate existing ones |
179
195
  | `memory_recall` | Cue-based retrieval, memory inspection, or system stats |
180
- | `memory_manage` | Run consolidation or manage working memory |
196
+ | `memory_manage` | Run consolidation or manage working memory |
181
197
 
182
198
  ## Programmatic API
183
199
 
@@ -187,11 +203,15 @@ import { EngramEngine, encode, recall, consolidate } from "engram";
187
203
  const engine = EngramEngine.inMemory();
188
204
 
189
205
  // Encode
190
- const memory = encode(engine.storage, {
191
- content: "important fact",
192
- type: "semantic",
193
- emotion: "curiosity",
194
- }, engine.config);
206
+ const memory = encode(
207
+ engine.storage,
208
+ {
209
+ content: "important fact",
210
+ type: "semantic",
211
+ emotion: "curiosity",
212
+ },
213
+ engine.config,
214
+ );
195
215
 
196
216
  // Recall
197
217
  const results = recall(engine.storage, "important", engine.config);
@@ -206,12 +226,12 @@ engine.close();
206
226
 
207
227
  Cognitive parameters can be tuned via environment variables or the `loadConfig()` function:
208
228
 
209
- | Parameter | Default | Env Variable | Description |
210
- |---|---|---|---|
211
- | `decayRate` | 0.5 | `ENGRAM_DECAY_RATE` | ACT-R power law decay parameter |
212
- | `retrievalThreshold` | -1.0 | `ENGRAM_RETRIEVAL_THRESHOLD` | Minimum activation for recall |
213
- | `workingMemoryCapacity` | 7 | `ENGRAM_WM_CAPACITY` | Miller's Law capacity limit |
214
- | `dbPath` | `~/.engram/memory.db` | `ENGRAM_DB_PATH` | SQLite database location |
229
+ | Parameter | Default | Env Variable | Description |
230
+ | ----------------------- | --------------------- | ---------------------------- | ------------------------------- |
231
+ | `decayRate` | 0.5 | `ENGRAM_DECAY_RATE` | ACT-R power law decay parameter |
232
+ | `retrievalThreshold` | -1.0 | `ENGRAM_RETRIEVAL_THRESHOLD` | Minimum activation for recall |
233
+ | `workingMemoryCapacity` | 7 | `ENGRAM_WM_CAPACITY` | Miller's Law capacity limit |
234
+ | `dbPath` | `~/.engram/memory.db` | `ENGRAM_DB_PATH` | SQLite database location |
215
235
 
216
236
  All parameters are also configurable programmatically:
217
237
 
@@ -227,8 +247,8 @@ const engine = new EngramEngine({
227
247
 
228
248
  ## References
229
249
 
230
- - Anderson, J.R. (1993). *Rules of the Mind*. ACT-R Cognitive Architecture.
231
- - Ebbinghaus, H. (1885). *Uber das Gedachtnis*. Memory and forgetting curves.
250
+ - Anderson, J.R. (1993). _Rules of the Mind_. ACT-R Cognitive Architecture.
251
+ - Ebbinghaus, H. (1885). _Uber das Gedachtnis_. Memory and forgetting curves.
232
252
  - Collins, A.M. & Loftus, E.F. (1975). A spreading-activation theory of semantic processing.
233
253
  - Nader, K., Schafe, G.E. & Le Doux, J.E. (2000). Fear memories require protein synthesis in the amygdala for reconsolidation after retrieval.
234
254
  - Miller, G.A. (1956). The magical number seven, plus or minus two.
package/SKILL.md ADDED
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: engram
3
+ description: Cognitive memory for AI agents — use when encoding, recalling, or managing persistent memories across sessions
4
+ ---
5
+
6
+ # Engram — Cognitive Memory Protocol
7
+
8
+ You have a biologically-inspired memory system. Use it like a brain, not a database.
9
+
10
+ ## Session Lifecycle
11
+
12
+ **Start:** Recall what you know about the current context.
13
+
14
+ ```
15
+ memory_recall → { action: "recall", cue: "<project or topic>" }
16
+ memory_manage → { action: "focus_get" }
17
+ ```
18
+
19
+ **During:** Encode insights as they emerge. Don't batch everything at the end.
20
+
21
+ ```
22
+ memory_store → { action: "encode", content: "...", type: "...", emotion: "..." }
23
+ ```
24
+
25
+ **End:** Consolidate to strengthen and link memories.
26
+
27
+ ```
28
+ memory_manage → { action: "consolidate" }
29
+ ```
30
+
31
+ ## Memory Types
32
+
33
+ | Type | Use when | Examples |
34
+ | ------------ | --------------------------------------------------------------- | ---------------------------------------------------------------------------- |
35
+ | `episodic` | Something _happened_ — events, interactions, debugging sessions | "User reported login failing on Safari", "Deployed v2.3 with new caching" |
36
+ | `semantic` | A _fact_ or _concept_ — knowledge, definitions, relationships | "Auth uses JWT with 24h expiry", "The payments module depends on Stripe SDK" |
37
+ | `procedural` | A _skill_ or _process_ — how to do things, patterns, workflows | "To deploy: run tests → build → push to staging → verify → promote" |
38
+
39
+ **Default to `semantic`** when unsure. Procedural memories never decay — use them for durable skills.
40
+
41
+ ## Emotion Tags
42
+
43
+ Tag memories with emotional context. This affects recall priority — emotional memories surface faster.
44
+
45
+ | Emotion | When to use |
46
+ | -------------- | ----------------------------------------------------- |
47
+ | `joy` | Something worked well, positive outcome, breakthrough |
48
+ | `satisfaction` | Task completed successfully, clean solution |
49
+ | `curiosity` | Interesting finding, worth exploring further |
50
+ | `surprise` | Unexpected behavior, counter-intuitive result |
51
+ | `anxiety` | Risk identified, potential failure, fragile code |
52
+ | `frustration` | Recurring problem, friction, workaround needed |
53
+ | `neutral` | Routine fact, no emotional significance |
54
+
55
+ Omit emotion for routine facts. Tag frustration on pain points — it helps surface them when they recur.
56
+
57
+ ## MCP Tools Reference
58
+
59
+ ### memory_store
60
+
61
+ | Action | Required | Optional |
62
+ | --------------- | ------------------- | ------------------------------------------------------ |
63
+ | `encode` | `content` | `type`, `emotion`, `emotionWeight` (0-1), `context` |
64
+ | `encode_batch` | `memories[]` (1-50) | each: `type`, `emotion`, `emotionWeight`, `context` |
65
+ | `reconsolidate` | `id` | `newContext`, `currentEmotion`, `currentEmotionWeight` |
66
+
67
+ ### memory_recall
68
+
69
+ | Action | Required | Optional |
70
+ | --------- | -------- | ---------------------------------------------------------- |
71
+ | `recall` | `cue` | `limit`, `type`, `context`, `associative` (bool), `format` |
72
+ | `list` | — | `type`, `context`, `limit`, `offset`, `format` |
73
+ | `inspect` | `id` | — |
74
+ | `stats` | — | — |
75
+
76
+ ### memory_manage
77
+
78
+ | Action | Required | Optional |
79
+ | ----------------- | --------- | -------------------------- |
80
+ | `consolidate` | — | — |
81
+ | `focus_push` | `content` | `memoryRef` |
82
+ | `focus_pop` | — | — |
83
+ | `focus_get` | — | — |
84
+ | `focus_clear` | — | — |
85
+ | `recall_to_focus` | `cue` | `limit`, `type`, `context` |
86
+
87
+ ## Working Memory (Focus Buffer)
88
+
89
+ 7 slots. Use it to hold active context during complex tasks.
90
+
91
+ - **Push** key facts you'll reference repeatedly during a task
92
+ - **Recall to focus** loads top recall results into the buffer
93
+ - **Pop/clear** when switching contexts
94
+ - The buffer is LIFO — newest items pop first
95
+
96
+ **Priming pattern:** At session start, recall + focus to seed your working context:
97
+
98
+ ```
99
+ memory_manage → { action: "recall_to_focus", cue: "<current task>" }
100
+ ```
101
+
102
+ ## Key Behaviors
103
+
104
+ - **Recall strengthens memories** — each recall boosts activation (use-it-or-lose-it)
105
+ - **List does NOT strengthen** — use list for browsing without side effects
106
+ - **Procedural memories never decay** — once encoded, they persist permanently
107
+ - **Consolidation discovers associations** — run it to link related memories
108
+ - **Emotional memories resist decay** — tagged memories survive longer
109
+ - **Context scopes memories** — use `context: "project:name"` to partition
110
+
111
+ ## What to Encode
112
+
113
+ **Encode:** decisions and their rationale, architectural insights, debugging breakthroughs, user preferences, recurring patterns, project-specific knowledge, lessons learned
114
+
115
+ **Don't encode:** transient task state, information already in code/docs, obvious facts, raw data without interpretation
116
+
117
+ ## Context Convention
118
+
119
+ Use hierarchical context tags: `project:engram`, `project:acme/auth`, `topic:deployment`.
120
+ This lets you recall scoped to a project or topic without noise from other domains.
@@ -39,16 +39,12 @@
39
39
  "indexes": {
40
40
  "idx_access_log_memory_id": {
41
41
  "name": "idx_access_log_memory_id",
42
- "columns": [
43
- "memory_id"
44
- ],
42
+ "columns": ["memory_id"],
45
43
  "isUnique": false
46
44
  },
47
45
  "idx_access_log_accessed_at": {
48
46
  "name": "idx_access_log_accessed_at",
49
- "columns": [
50
- "accessed_at"
51
- ],
47
+ "columns": ["accessed_at"],
52
48
  "isUnique": false
53
49
  }
54
50
  },
@@ -57,12 +53,8 @@
57
53
  "name": "access_log_memory_id_memories_id_fk",
58
54
  "tableFrom": "access_log",
59
55
  "tableTo": "memories",
60
- "columnsFrom": [
61
- "memory_id"
62
- ],
63
- "columnsTo": [
64
- "id"
65
- ],
56
+ "columnsFrom": ["memory_id"],
57
+ "columnsTo": ["id"],
66
58
  "onDelete": "cascade",
67
59
  "onUpdate": "no action"
68
60
  }
@@ -121,24 +113,17 @@
121
113
  "indexes": {
122
114
  "idx_associations_source": {
123
115
  "name": "idx_associations_source",
124
- "columns": [
125
- "source_id"
126
- ],
116
+ "columns": ["source_id"],
127
117
  "isUnique": false
128
118
  },
129
119
  "idx_associations_target": {
130
120
  "name": "idx_associations_target",
131
- "columns": [
132
- "target_id"
133
- ],
121
+ "columns": ["target_id"],
134
122
  "isUnique": false
135
123
  },
136
124
  "unique_source_target": {
137
125
  "name": "unique_source_target",
138
- "columns": [
139
- "source_id",
140
- "target_id"
141
- ],
126
+ "columns": ["source_id", "target_id"],
142
127
  "isUnique": true
143
128
  }
144
129
  },
@@ -147,12 +132,8 @@
147
132
  "name": "associations_source_id_memories_id_fk",
148
133
  "tableFrom": "associations",
149
134
  "tableTo": "memories",
150
- "columnsFrom": [
151
- "source_id"
152
- ],
153
- "columnsTo": [
154
- "id"
155
- ],
135
+ "columnsFrom": ["source_id"],
136
+ "columnsTo": ["id"],
156
137
  "onDelete": "cascade",
157
138
  "onUpdate": "no action"
158
139
  },
@@ -160,12 +141,8 @@
160
141
  "name": "associations_target_id_memories_id_fk",
161
142
  "tableFrom": "associations",
162
143
  "tableTo": "memories",
163
- "columnsFrom": [
164
- "target_id"
165
- ],
166
- "columnsTo": [
167
- "id"
168
- ],
144
+ "columnsFrom": ["target_id"],
145
+ "columnsTo": ["id"],
169
146
  "onDelete": "cascade",
170
147
  "onUpdate": "no action"
171
148
  }
@@ -326,37 +303,27 @@
326
303
  "indexes": {
327
304
  "idx_memories_type": {
328
305
  "name": "idx_memories_type",
329
- "columns": [
330
- "type"
331
- ],
306
+ "columns": ["type"],
332
307
  "isUnique": false
333
308
  },
334
309
  "idx_memories_activation": {
335
310
  "name": "idx_memories_activation",
336
- "columns": [
337
- "activation"
338
- ],
311
+ "columns": ["activation"],
339
312
  "isUnique": false
340
313
  },
341
314
  "idx_memories_encoded_at": {
342
315
  "name": "idx_memories_encoded_at",
343
- "columns": [
344
- "encoded_at"
345
- ],
316
+ "columns": ["encoded_at"],
346
317
  "isUnique": false
347
318
  },
348
319
  "idx_memories_context": {
349
320
  "name": "idx_memories_context",
350
- "columns": [
351
- "context"
352
- ],
321
+ "columns": ["context"],
353
322
  "isUnique": false
354
323
  },
355
324
  "idx_memories_chunk_id": {
356
325
  "name": "idx_memories_chunk_id",
357
- "columns": [
358
- "chunk_id"
359
- ],
326
+ "columns": ["chunk_id"],
360
327
  "isUnique": false
361
328
  }
362
329
  },
@@ -414,4 +381,4 @@
414
381
  "internal": {
415
382
  "indexes": {}
416
383
  }
417
- }
384
+ }
@@ -10,4 +10,4 @@
10
10
  "breakpoints": true
11
11
  }
12
12
  ]
13
- }
13
+ }
package/package.json CHANGED
@@ -1,25 +1,43 @@
1
1
  {
2
2
  "name": "@cogmem/engram",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Human memory for artificial minds — a cognitive memory system modeled on neuroscience",
5
- "type": "module",
6
- "exports": {
7
- ".": {
8
- "bun": "./src/index.ts",
9
- "types": "./src/index.ts",
10
- "default": "./src/index.ts"
11
- }
5
+ "keywords": [
6
+ "agents",
7
+ "ai",
8
+ "bun",
9
+ "cognitive",
10
+ "mcp",
11
+ "memory",
12
+ "neuroscience"
13
+ ],
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/faltawy/engram.git"
12
18
  },
13
- "main": "./src/index.ts",
14
- "types": "./src/index.ts",
15
19
  "bin": {
16
20
  "engram": "src/cli/index.ts",
17
21
  "engram-mcp": "src/mcp/server.ts"
18
22
  },
19
23
  "files": [
20
24
  "src/",
21
- "drizzle/"
25
+ "drizzle/",
26
+ "SKILL.md"
22
27
  ],
28
+ "type": "module",
29
+ "main": "./src/index.ts",
30
+ "types": "./src/index.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./src/index.ts",
34
+ "bun": "./src/index.ts",
35
+ "default": "./src/index.ts"
36
+ }
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
23
41
  "scripts": {
24
42
  "start": "bun run src/cli/index.ts",
25
43
  "test": "bun test",
@@ -34,6 +52,7 @@
34
52
  "@modelcontextprotocol/sdk": "^1.27.1",
35
53
  "citty": "^0.2.1",
36
54
  "cli-table3": "^0.6.5",
55
+ "consola": "^3.4.2",
37
56
  "dayjs": "^1.11.19",
38
57
  "drizzle-orm": "^0.45.1",
39
58
  "kleur": "^4.1.5",
@@ -49,23 +68,6 @@
49
68
  "peerDependencies": {
50
69
  "typescript": "^5"
51
70
  },
52
- "repository": {
53
- "type": "git",
54
- "url": "git+https://github.com/faltawy/engram.git"
55
- },
56
- "keywords": [
57
- "memory",
58
- "ai",
59
- "agents",
60
- "cognitive",
61
- "mcp",
62
- "bun",
63
- "neuroscience"
64
- ],
65
- "publishConfig": {
66
- "access": "public"
67
- },
68
- "license": "MIT",
69
71
  "engines": {
70
72
  "bun": ">=1.0.0"
71
73
  }
@@ -1,7 +1,8 @@
1
1
  import { defineCommand } from "citty";
2
- import { EngramEngine } from "../../core/engine.ts";
3
- import { encode } from "../../core/encoder.ts";
2
+
4
3
  import { isValidEmotion } from "../../core/emotional-tag.ts";
4
+ import { encode } from "../../core/encoder.ts";
5
+ import { EngramEngine } from "../../core/engine.ts";
5
6
  import { isValidMemoryType, Emotion } from "../../core/memory.ts";
6
7
  import { formatMemoryEncoded } from "../format.ts";
7
8
 
@@ -39,13 +40,19 @@ export const encodeCommand = defineCommand({
39
40
  run({ args }) {
40
41
  const typeStr = args.type ?? "semantic";
41
42
  if (!isValidMemoryType(typeStr)) {
42
- console.error(`Invalid type: ${typeStr}. Valid: episodic, semantic, procedural`);
43
+ console.error(
44
+ `Invalid type: ${typeStr}. Valid: episodic, semantic, procedural`
45
+ );
43
46
  process.exit(1);
44
47
  }
45
48
 
46
49
  const emotionStr = args.emotion ?? "neutral";
47
50
  if (!isValidEmotion(emotionStr)) {
48
- console.error(`Invalid emotion: ${emotionStr}. Valid: ${Object.values(Emotion).join(", ")}`);
51
+ console.error(
52
+ `Invalid emotion: ${emotionStr}. Valid: ${Object.values(Emotion).join(
53
+ ", "
54
+ )}`
55
+ );
49
56
  process.exit(1);
50
57
  }
51
58
 
@@ -57,10 +64,12 @@ export const encodeCommand = defineCommand({
57
64
  content: args.content,
58
65
  type: typeStr,
59
66
  emotion: emotionStr,
60
- emotionWeight: args.emotionWeight ? Number(args.emotionWeight) : undefined,
67
+ emotionWeight: args.emotionWeight
68
+ ? Number(args.emotionWeight)
69
+ : undefined,
61
70
  context: args.context ?? engine.projectContext ?? undefined,
62
71
  },
63
- engine.config,
72
+ engine.config
64
73
  );
65
74
 
66
75
  console.log(formatMemoryEncoded(memory));
@@ -1,4 +1,5 @@
1
1
  import { defineCommand } from "citty";
2
+
2
3
  import { EngramEngine } from "../../core/engine.ts";
3
4
  import {
4
5
  pushFocus,
@@ -17,7 +18,8 @@ export const focusCommand = defineCommand({
17
18
  args: {
18
19
  content: {
19
20
  type: "positional",
20
- description: "Content to push into working memory (omit to view current focus)",
21
+ description:
22
+ "Content to push into working memory (omit to view current focus)",
21
23
  },
22
24
  clear: {
23
25
  type: "boolean",
@@ -47,7 +49,9 @@ export const focusCommand = defineCommand({
47
49
  const popped = popFocus(engine.storage);
48
50
  if (!isInteractive()) {
49
51
  console.log(
50
- JSON.stringify(popped ? { slot: popped.slot, content: popped.content } : null),
52
+ JSON.stringify(
53
+ popped ? { slot: popped.slot, content: popped.content } : null
54
+ )
51
55
  );
52
56
  } else if (popped) {
53
57
  console.log(dim(" Removed: ") + bold(popped.content));
@@ -58,34 +62,55 @@ export const focusCommand = defineCommand({
58
62
  }
59
63
 
60
64
  if (args.content) {
61
- const { slot, evicted } = pushFocus(engine.storage, args.content, engine.config);
65
+ const { slot, evicted } = pushFocus(
66
+ engine.storage,
67
+ args.content,
68
+ engine.config
69
+ );
62
70
  if (!isInteractive()) {
63
71
  console.log(
64
72
  JSON.stringify({
65
73
  slot: slot.slot,
66
74
  content: slot.content,
67
- evicted: evicted ? { slot: evicted.slot, content: evicted.content } : null,
68
- }),
75
+ evicted: evicted
76
+ ? { slot: evicted.slot, content: evicted.content }
77
+ : null,
78
+ })
69
79
  );
70
80
  } else {
71
- console.log(cyan(" Focused on: ") + bold(slot.content) + dim(` [slot ${slot.slot}]`));
81
+ console.log(
82
+ cyan(" Focused on: ") +
83
+ bold(slot.content) +
84
+ dim(` [slot ${slot.slot}]`)
85
+ );
72
86
  if (evicted) {
73
- console.log(dim(` Evicted: "${evicted.content}" (oldest item, capacity reached)`));
87
+ console.log(
88
+ dim(
89
+ ` Evicted: "${evicted.content}" (oldest item, capacity reached)`
90
+ )
91
+ );
74
92
  }
75
93
  }
76
94
  return;
77
95
  }
78
96
 
79
97
  const slots = getFocus(engine.storage);
80
- const { used, capacity } = focusUtilization(engine.storage, engine.config);
98
+ const { used, capacity } = focusUtilization(
99
+ engine.storage,
100
+ engine.config
101
+ );
81
102
 
82
103
  if (!isInteractive()) {
83
104
  console.log(
84
105
  JSON.stringify({
85
106
  used,
86
107
  capacity,
87
- slots: slots.map((s) => ({ slot: s.slot, content: s.content, memoryRef: s.memoryRef })),
88
- }),
108
+ slots: slots.map((s) => ({
109
+ slot: s.slot,
110
+ content: s.content,
111
+ memoryRef: s.memoryRef,
112
+ })),
113
+ })
89
114
  );
90
115
  return;
91
116
  }
@@ -97,7 +122,9 @@ export const focusCommand = defineCommand({
97
122
 
98
123
  console.log(bold(` Working Memory`) + dim(` [${used}/${capacity}]`));
99
124
  for (const slot of slots) {
100
- console.log(` ${cyan(">")} ${slot.content}` + dim(` [slot ${slot.slot}]`));
125
+ console.log(
126
+ ` ${cyan(">")} ${slot.content}` + dim(` [slot ${slot.slot}]`)
127
+ );
101
128
  }
102
129
  } finally {
103
130
  engine.close();