@crewx/memory 0.1.23-rc.191 → 0.1.23-rc.192

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
@@ -3,5 +3,5 @@
3
3
  Memory engine for CrewX - markdown + frontmatter based long-term memory.
4
4
 
5
5
  ```bash
6
- npx memory index <agent_id>
6
+ crewx memory index <agent_id>
7
7
  ```
package/SKILL.md CHANGED
@@ -12,7 +12,7 @@ A long-term memory management skill based on markdown + frontmatter.
12
12
 
13
13
  ## Installation
14
14
 
15
- Included in `packages/built-in/memory`, used via the `npx memory` command.
15
+ Included in `packages/built-in/memory`, used via the `crewx memory` command.
16
16
 
17
17
  ## Features
18
18
 
@@ -34,11 +34,11 @@ Shorthand aliases for frequently used commands. They work identically to the ori
34
34
 
35
35
  ```bash
36
36
  # The following two commands are identical
37
- npx memory get agent_id ABC123
38
- npx memory read agent_id ABC123
37
+ crewx memory get agent_id ABC123
38
+ crewx memory read agent_id ABC123
39
39
 
40
- npx memory index agent_id
41
- npx memory list agent_id
40
+ crewx memory index agent_id
41
+ crewx memory list agent_id
42
42
  ```
43
43
 
44
44
  ## Directory Structure
@@ -59,7 +59,7 @@ memory/
59
59
  ### Save
60
60
 
61
61
  ```bash
62
- npx memory save <agent_id> "<summary>" [category] [--topic=xxx] [--tags=a,b,c] [--body="detailed content"]
62
+ crewx memory save <agent_id> "<summary>" [category] [--topic=xxx] [--tags=a,b,c] [--body="detailed content"]
63
63
  ```
64
64
 
65
65
  **Options:**
@@ -78,18 +78,18 @@ npx memory save <agent_id> "<summary>" [category] [--topic=xxx] [--tags=a,b,c] [
78
78
  **Examples:**
79
79
  ```bash
80
80
  # [BAD] Bad example - no details
81
- npx memory save cto "Gemini 3.0 Flash moment" decision --topic=crewx-strategy
81
+ crewx memory save cto "Gemini 3.0 Flash moment" decision --topic=crewx-strategy
82
82
 
83
83
  # [GOOD] Good example - details included
84
- npx memory save cto "Gemini 3.0 Flash moment - strategic turning point" decision --topic=crewx-strategy --tags=gemini,pricing --body="SWE-bench 78% dominates Claude 3.5 Sonnet (49%). Price is 1/6. CrewX strategy validated -- orchestration is the key moat."
84
+ crewx memory save cto "Gemini 3.0 Flash moment - strategic turning point" decision --topic=crewx-strategy --tags=gemini,pricing --body="SWE-bench 78% dominates Claude 3.5 Sonnet (49%). Price is 1/6. CrewX strategy validated -- orchestration is the key moat."
85
85
  ```
86
86
 
87
87
  ### Index Query
88
88
 
89
89
  ```bash
90
- npx memory index <agent_id> # Medium-term memory (topic summaries only)
91
- npx memory index <agent_id> --recent # Recent entry list
92
- npx memory index <agent_id> --full # Full view
90
+ crewx memory index <agent_id> # Medium-term memory (topic summaries only)
91
+ crewx memory index <agent_id> --recent # Recent entry list
92
+ crewx memory index <agent_id> --full # Full view
93
93
  ```
94
94
 
95
95
  **Drill-down pattern:** `index` -> drill into needed topic with `topic` -> drill into needed entry with `get`
@@ -97,19 +97,19 @@ npx memory index <agent_id> --full # Full view
97
97
  ### Topic Drill-down
98
98
 
99
99
  ```bash
100
- npx memory topic <agent_id> <topic_name>
100
+ crewx memory topic <agent_id> <topic_name>
101
101
  ```
102
102
 
103
103
  ### Recent Memories
104
104
 
105
105
  ```bash
106
- npx memory recent <agent_id> [days=30]
106
+ crewx memory recent <agent_id> [days=30]
107
107
  ```
108
108
 
109
109
  ### Keyword Search (Fast)
110
110
 
111
111
  ```bash
112
- npx memory find <agent_id> "<keyword>"
112
+ crewx memory find <agent_id> "<keyword>"
113
113
  ```
114
114
 
115
115
  Grep-based string matching. Fast and free.
@@ -117,7 +117,7 @@ Grep-based string matching. Fast and free.
117
117
  ### Semantic Search (AI)
118
118
 
119
119
  ```bash
120
- npx memory search <agent_id> "<query>"
120
+ crewx memory search <agent_id> "<query>"
121
121
  ```
122
122
 
123
123
  Semantic search powered by **Gemini 2.0 Flash**. Understands synonyms and context.
@@ -128,22 +128,22 @@ Semantic search powered by **Gemini 2.0 Flash**. Understands synonyms and contex
128
128
  **Examples:**
129
129
  ```bash
130
130
  # Keyword search (fast)
131
- npx memory find crewx_dev_lead "agent"
131
+ crewx memory find crewx_dev_lead "agent"
132
132
 
133
133
  # Semantic search (AI)
134
- npx memory search crewx_dev_lead "things to watch out for when assigning tasks"
134
+ crewx memory search crewx_dev_lead "things to watch out for when assigning tasks"
135
135
  ```
136
136
 
137
137
  ### Detail View (Drill-down)
138
138
 
139
139
  ```bash
140
- npx memory get <agent_id> <memory_id>
140
+ crewx memory get <agent_id> <memory_id>
141
141
  ```
142
142
 
143
143
  ### Update Memory
144
144
 
145
145
  ```bash
146
- npx memory update <agent_id> <memory_id> [options]
146
+ crewx memory update <agent_id> <memory_id> [options]
147
147
  ```
148
148
 
149
149
  **Options:**
@@ -158,16 +158,16 @@ npx memory update <agent_id> <memory_id> [options]
158
158
  **Examples:**
159
159
  ```bash
160
160
  # Update summary and detailed content
161
- npx memory update cto VkY9X6 --summary="Updated summary" --body="Updated detailed content"
161
+ crewx memory update cto VkY9X6 --summary="Updated summary" --body="Updated detailed content"
162
162
 
163
163
  # Change topic only
164
- npx memory update cto VkY9X6 --topic=new-topic
164
+ crewx memory update cto VkY9X6 --topic=new-topic
165
165
  ```
166
166
 
167
167
  ### Delete Memory
168
168
 
169
169
  ```bash
170
- npx memory delete <agent_id> <memory_id> [--force]
170
+ crewx memory delete <agent_id> <memory_id> [--force]
171
171
  ```
172
172
 
173
173
  - Without `--force`, only a confirmation message is displayed
@@ -176,16 +176,16 @@ npx memory delete <agent_id> <memory_id> [--force]
176
176
  **Examples:**
177
177
  ```bash
178
178
  # Deletion confirmation
179
- npx memory delete cto VkY9X6
179
+ crewx memory delete cto VkY9X6
180
180
 
181
181
  # Actual deletion
182
- npx memory delete cto VkY9X6 --force
182
+ crewx memory delete cto VkY9X6 --force
183
183
  ```
184
184
 
185
185
  ### Merge Memories
186
186
 
187
187
  ```bash
188
- npx memory merge <agent_id> <memory_id1> <memory_id2> [--summary="merge summary"]
188
+ crewx memory merge <agent_id> <memory_id1> <memory_id2> [--summary="merge summary"]
189
189
  ```
190
190
 
191
191
  - Merges two memories into one
@@ -196,16 +196,16 @@ npx memory merge <agent_id> <memory_id1> <memory_id2> [--summary="merge summary"
196
196
  **Examples:**
197
197
  ```bash
198
198
  # Merge two memories
199
- npx memory merge cto abc123 def456
199
+ crewx memory merge cto abc123 def456
200
200
 
201
201
  # Merge with custom summary
202
- npx memory merge cto abc123 def456 --summary="VLM fine-tuning comprehensive summary"
202
+ crewx memory merge cto abc123 def456 --summary="VLM fine-tuning comprehensive summary"
203
203
  ```
204
204
 
205
205
  ### Generate Summary (summarize)
206
206
 
207
207
  ```bash
208
- npx memory summarize <agent_id> [--force]
208
+ crewx memory summarize <agent_id> [--force]
209
209
  ```
210
210
 
211
211
  Memory summarization using the MemGAS incremental summarization approach.
@@ -229,10 +229,10 @@ Memory summarization using the MemGAS incremental summarization approach.
229
229
  **Examples:**
230
230
  ```bash
231
231
  # Incremental summary (reflects new entries only)
232
- npx memory summarize ui_devlead
232
+ crewx memory summarize ui_devlead
233
233
 
234
234
  # Force full regeneration
235
- npx memory summarize ui_devlead --force
235
+ crewx memory summarize ui_devlead --force
236
236
  ```
237
237
 
238
238
  ### Generate Summary (summarize-dirty)
@@ -241,12 +241,12 @@ npx memory summarize ui_devlead --force
241
241
  Cron checks and executes every 1 minute.
242
242
 
243
243
  ```bash
244
- npx memory summarize-dirty
244
+ crewx memory summarize-dirty
245
245
  ```
246
246
 
247
247
  **Cron registration example:**
248
248
  ```bash
249
- npx cron add "*/1 * * * *" "npx memory summarize-dirty" --mode command --name "memory-debounce"
249
+ crewx cron add "*/1 * * * *" "crewx memory summarize-dirty" --mode command --name "memory-debounce"
250
250
  ```
251
251
 
252
252
  **summary.md format:**
@@ -271,7 +271,7 @@ CLI shell environment detection performance improvement...
271
271
  ### Filename Migration (migrate)
272
272
 
273
273
  ```bash
274
- npx memory migrate <agent_id>
274
+ crewx memory migrate <agent_id>
275
275
  ```
276
276
 
277
277
  Batch converts existing slug filenames (`2026-02-16-slug-name.md`) to ID-based filenames (`QOSIOs.md`).
@@ -282,7 +282,7 @@ Batch converts existing slug filenames (`2026-02-16-slug-name.md`) to ID-based f
282
282
 
283
283
  **Example:**
284
284
  ```bash
285
- npx memory migrate ui_devlead
285
+ crewx memory migrate ui_devlead
286
286
  ```
287
287
 
288
288
  ## Frontmatter Schema
@@ -307,12 +307,12 @@ summary: "One-line summary"
307
307
  ## At Conversation Start (Required!)
308
308
  ```bash
309
309
  # Load medium-term memory (topic summaries + drill-down guide)
310
- npx memory index {{agent_id}}
310
+ crewx memory index {{agent_id}}
311
311
 
312
312
  # Drill down as needed
313
- npx memory index {{agent_id}} --recent # Recent list
314
- npx memory topic {{agent_id}} <topic> # Topic details
315
- npx memory get {{agent_id}} <id> # Individual memory
313
+ crewx memory index {{agent_id}} --recent # Recent list
314
+ crewx memory topic {{agent_id}} <topic> # Topic details
315
+ crewx memory get {{agent_id}} <id> # Individual memory
316
316
  ```
317
317
 
318
318
  ## Memory Save Triggers
@@ -336,16 +336,16 @@ npx memory get {{agent_id}} <id> # Individual memory
336
336
  **Examples:**
337
337
  ```bash
338
338
  # Add to existing topic
339
- npx memory save {{agent_id}} "VLM learning rate adjustment" decision --topic=vlm-finetuning
339
+ crewx memory save {{agent_id}} "VLM learning rate adjustment" decision --topic=vlm-finetuning
340
340
 
341
341
  # Create new topic
342
- npx memory save {{agent_id}} "New feature planning" decision --topic=new-feature-x
342
+ crewx memory save {{agent_id}} "New feature planning" decision --topic=new-feature-x
343
343
  ```
344
344
 
345
345
  ## Save Command (--body required!)
346
346
  ```bash
347
347
  # WARNING: Always save with --body included!
348
- npx memory save {{agent_id}} "<summary>" <category> --topic=<topic> --body="<detailed content>"
348
+ crewx memory save {{agent_id}} "<summary>" <category> --topic=<topic> --body="<detailed content>"
349
349
  ```
350
350
 
351
351
  **--body writing guide:**
@@ -383,7 +383,7 @@ Manages associations between memories as a graph.
383
383
  ### Build Graph
384
384
 
385
385
  ```bash
386
- npx memory mindmap build <agent_id>
386
+ crewx memory mindmap build <agent_id>
387
387
  ```
388
388
 
389
389
  Rule-based connection generation:
@@ -408,13 +408,13 @@ Rule-based connection generation:
408
408
  **[BAD] Bad example (no connections)**
409
409
  ```bash
410
410
  # topic=general, category=general -> 0 connections
411
- npx memory save agent "Discord settings removal" general
411
+ crewx memory save agent "Discord settings removal" general
412
412
  ```
413
413
 
414
414
  **[GOOD] Good example (strong connections)**
415
415
  ```bash
416
416
  # topic + category + tags -> maximum connections
417
- npx memory save agent "Discord settings removal decision" decision \
417
+ crewx memory save agent "Discord settings removal decision" decision \
418
418
  --topic=discord \
419
419
  --tags=settings,cpo-decision,oauth \
420
420
  --body="CPO meeting result..."
@@ -428,7 +428,7 @@ npx memory save agent "Discord settings removal decision" decision \
428
428
  ### View Graph Summary
429
429
 
430
430
  ```bash
431
- npx memory mindmap show <agent_id>
431
+ crewx memory mindmap show <agent_id>
432
432
  ```
433
433
 
434
434
  Displays topic-based clusters, hub nodes (memories with many connections), etc.
@@ -437,9 +437,9 @@ Default output is in **Mermaid format**, which can be visualized as a graph in V
437
437
 
438
438
  **Period filter options:**
439
439
  ```bash
440
- npx memory mindmap show <agent_id> --period=stm # 24h
441
- npx memory mindmap show <agent_id> --period=mtm # 7d
442
- npx memory mindmap show <agent_id> --period=ltm # 30d
440
+ crewx memory mindmap show <agent_id> --period=stm # 24h
441
+ crewx memory mindmap show <agent_id> --period=mtm # 7d
442
+ crewx memory mindmap show <agent_id> --period=ltm # 30d
443
443
  ```
444
444
 
445
445
  ### Export as PNG Image
@@ -448,13 +448,13 @@ Convert Mermaid output to PNG images for visual inspection.
448
448
 
449
449
  ```bash
450
450
  # 1. Save mermaid code to file
451
- npx memory mindmap show <agent_id> | sed 's/^```mermaid$//' | sed 's/^```$//' > /tmp/graph.mmd
451
+ crewx memory mindmap show <agent_id> | sed 's/^```mermaid$//' | sed 's/^```$//' > /tmp/graph.mmd
452
452
 
453
453
  # 2. Convert to PNG (runs without installation via npx)
454
454
  npx @mermaid-js/mermaid-cli -i /tmp/graph.mmd -o graph.png -w 2400 -H 1600 -b white
455
455
 
456
456
  # Period filter + PNG (e.g., last 24 hours only)
457
- npx memory mindmap show <agent_id> --period=stm | sed 's/^```mermaid$//' | sed 's/^```$//' | grep -v '^(' > /tmp/graph-stm.mmd
457
+ crewx memory mindmap show <agent_id> --period=stm | sed 's/^```mermaid$//' | sed 's/^```$//' | grep -v '^(' > /tmp/graph-stm.mmd
458
458
  npx @mermaid-js/mermaid-cli -i /tmp/graph-stm.mmd -o graph-stm.png -w 1600 -H 900 -b white
459
459
  ```
460
460
 
@@ -463,7 +463,7 @@ npx @mermaid-js/mermaid-cli -i /tmp/graph-stm.mmd -o graph-stm.png -w 1600 -H 90
463
463
  ### Query Related Memories
464
464
 
465
465
  ```bash
466
- npx memory mindmap related <agent_id> <memory_id>
466
+ crewx memory mindmap related <agent_id> <memory_id>
467
467
  ```
468
468
 
469
469
  Displays memories connected to a specific memory, sorted by weight.
@@ -472,16 +472,16 @@ Displays memories connected to a specific memory, sorted by weight.
472
472
 
473
473
  ```bash
474
474
  # Add connection
475
- npx memory mindmap add <agent_id> <from_id> <to_id> [type]
475
+ crewx memory mindmap add <agent_id> <from_id> <to_id> [type]
476
476
 
477
477
  # Remove connection
478
- npx memory mindmap remove <agent_id> <from_id> <to_id>
478
+ crewx memory mindmap remove <agent_id> <from_id> <to_id>
479
479
  ```
480
480
 
481
481
  ### Visualization (HTML) - Shared Graph
482
482
 
483
483
  ```bash
484
- npx memory mindmap html
484
+ crewx memory mindmap html
485
485
  ```
486
486
 
487
487
  Generates a **shared visualization combining connection graphs of all agents** in one place.
@@ -499,22 +499,22 @@ Generates a **shared visualization combining connection graphs of all agents** i
499
499
  **Usage:**
500
500
  ```bash
501
501
  # 1. Generate shared HTML (no agent_id needed)
502
- npx memory mindmap html
502
+ crewx memory mindmap html
503
503
 
504
504
  # 2. Open in browser
505
- npx memory mindmap open
505
+ crewx memory mindmap open
506
506
  ```
507
507
 
508
508
  **Example:**
509
509
  ```bash
510
510
  # Generate integrated visualization of all agent graphs
511
- npx memory mindmap html
511
+ crewx memory mindmap html
512
512
  ```
513
513
 
514
514
  ### Open in Browser
515
515
 
516
516
  ```bash
517
- npx memory mindmap open [agent_id]
517
+ crewx memory mindmap open [agent_id]
518
518
  ```
519
519
 
520
520
  Opens a specific agent's graph directly in the browser.
@@ -522,17 +522,17 @@ Opens a specific agent's graph directly in the browser.
522
522
  **Examples:**
523
523
  ```bash
524
524
  # Open CTO graph
525
- npx memory mindmap open cto
525
+ crewx memory mindmap open cto
526
526
 
527
527
  # Open default (all agents)
528
- npx memory mindmap open
528
+ crewx memory mindmap open
529
529
  ```
530
530
 
531
531
  ### Storage Location
532
532
 
533
533
  ```
534
534
  memory/{agent_id}/graph.json # Graph data
535
- memory/mindmap.html # Shared visualization HTML (generated by npx memory mindmap html)
535
+ memory/mindmap.html # Shared visualization HTML (generated by crewx memory mindmap html)
536
536
  ```
537
537
 
538
538
  ---
@@ -585,7 +585,7 @@ settings:
585
585
  By default, `crewx.yaml` is read from the project root. To use a different path, set the `CREWX_CONFIG` environment variable:
586
586
 
587
587
  ```bash
588
- CREWX_CONFIG=/path/to/custom-crewx.yaml npx memory index my_agent
588
+ CREWX_CONFIG=/path/to/custom-crewx.yaml crewx memory index my_agent
589
589
  ```
590
590
 
591
591
  ### Error handling
@@ -608,7 +608,7 @@ settings:
608
608
  Or override via environment variable (e.g., in CI/CD):
609
609
 
610
610
  ```bash
611
- MEMORY_SUMMARY_DAYS=14 npx memory summarize my_agent
611
+ MEMORY_SUMMARY_DAYS=14 crewx memory summarize my_agent
612
612
  ```
613
613
 
614
614
  ---
@@ -616,5 +616,5 @@ MEMORY_SUMMARY_DAYS=14 npx memory summarize my_agent
616
616
  ## v1 -> v2 Migration
617
617
 
618
618
  ```bash
619
- npx memory migrate <agent_id>
619
+ crewx memory migrate <agent_id>
620
620
  ```
package/dist/cli.js CHANGED
@@ -33,4 +33,4 @@ Examples:
33
33
  memory get myagent PWN3qt
34
34
 
35
35
  For detailed usage guide: memory usage
36
- `)}const j={read:"get",rm:"delete",ls:"recent"};const A=new Set(["help","force","verbose","full","important","no-important","json","all","version"]);function M(s){const r={positional:[],options:{}};for(let i=0;i<s.length;i++){const e=s[i];if(e==="-h"){r.options["help"]=true}else if(e.startsWith("--")){const t=e.indexOf("=");if(t!==-1){const n=e.slice(2,t);const o=e.slice(t+1);r.options[n]=o}else{const n=e.slice(2);if(!A.has(n)){const o=s[i+1];if(o!==void 0&&!o.startsWith("--")&&o!=="-h"){r.options[n]=o;i++}else{r.options[n]=true}}else{r.options[n]=true}}}else{r.positional.push(e)}}return r}async function b(s){const r=s??process.argv.slice(2);const{positional:i,options:e}=M(r);const[t,n,...o]=i;if(e.version){console.log(_);return}if(e.help){h();return}if(t==="usage"){O();return}if(t==="help"){h();return}if(!t){h();return}const g=j[t]??t;if(g==="mindmap"){const l=process.env["MEMORY_DATA_DIR"]??f.resolve(process.cwd(),"memory");const m=new S.MindmapEngine(l);const u=n;const c=o[0];const d=o.slice(1);if(!u){console.log("Usage: npx memory mindmap <subcommand> [agent_id] [args]");console.log("");console.log("Subcommands:");console.log(" build <agent_id> - Build graph");console.log(" show <agent_id> [--period=stm|mtm|ltm] [--format=mermaid|text] - Graph summary");console.log(" related <agent_id> <memory_id> - View related memories");console.log(" add <agent_id> <from_id> <to_id> [type] - Add manual relation");console.log(" remove <agent_id> <from_id> <to_id> - Remove relation");console.log(" html - Generate shared HTML");console.log(" open [agent_id] - Open in browser");process.exit(1)}switch(u){case"build":if(!c){console.log("Error: agent_id is required");process.exit(1)}m.build(c,e);break;case"show":if(!c){console.log("Error: agent_id is required");process.exit(1)}m.show(c,{period:e.period,format:e.format});break;case"related":if(!c||!d?.[0]){console.log("Error: agent_id and memory_id are required");process.exit(1)}m.related(c,d[0]);break;case"add":if(!c||!d?.[0]||!d?.[1]){console.log("Error: agent_id, from_id and to_id are required");process.exit(1)}m.add(c,d[0],d[1],d[2]);break;case"remove":if(!c||!d?.[0]||!d?.[1]){console.log("Error: agent_id, from_id and to_id are required");process.exit(1)}m.remove(c,d[0],d[1]);break;case"html":m.html();break;case"open":m.open(c);break;default:console.log(`Unknown mindmap subcommand: ${u}`);process.exit(1)}return}const a=new k.MemoryEngine;if(g==="summarize-dirty"){a.summarizeDirty();return}if(!n){console.log("Error: agent_id is required");process.exit(1)}switch(g){case"save":{const l=o[0];if(!l){console.log("Error: summary is required");process.exit(1)}let m;if(o[1]&&x.CATEGORIES.includes(o[1])){m=o[1]}else{m="general";if(o[1]&&!e.tags){e.tags=o[1]}}if(o[2]&&!e.body){e.body=o[2]}if(!e.body&&!process.stdin.isTTY){const u=q();let c;try{c=await Promise.race([u.body,new Promise(d=>setTimeout(()=>d(""),100))])}finally{u.release()}if(c){e.body=c}}a.save(n,l,m,e);break}case"index":a.index(n,e);break;case"list":a.list(n,e);break;case"stats":a.stats(n);break;case"tags":if(o[0]){a.topic(n,o[0])}else{a.tags(n)}break;case"recent":a.recent(n,parseInt(o[0]??"",10)||30);break;case"find":if(!o[0]){console.log("Error: keyword is required");process.exit(1)}a.find(n,o[0]);break;case"get":if(!o[0]){console.log("Error: memory_id is required");process.exit(1)}a.get(n,o[0]);break;case"search":if(!o[0]){console.log("Error: query is required");process.exit(1)}a.search(n,o.join(" "));break;case"update":if(!o[0]){console.log("Error: memory_id is required");process.exit(1)}a.update(n,o[0],e);break;case"delete":if(!o[0]){console.log("Error: memory_id is required");process.exit(1)}a.delete(n,o[0],e);break;case"merge":if(!o[0]||!o[1]){console.log("Error: two memory_ids are required");console.log('Usage: node cli.ts merge <agent_id> <id1> <id2> [--summary="merge summary"]');process.exit(1)}a.merge(n,o[0],o[1],e);break;case"summarize":a.summarize(n,e);break;default:console.log(`Unknown command: ${t}`);process.exit(1)}}if(require.main===module){E().then(s=>{const r=s?{skillVersion:s.getOwnSkillVersion(__dirname)}:{};return s?s.run("crewx/memory",()=>b(),r):b()}).catch(s=>{console.error(s.message);process.exit(1)})}
36
+ `)}const j={read:"get",rm:"delete",ls:"recent"};const A=new Set(["help","force","verbose","full","important","no-important","json","all","version"]);function M(s){const r={positional:[],options:{}};for(let i=0;i<s.length;i++){const e=s[i];if(e==="-h"){r.options["help"]=true}else if(e.startsWith("--")){const t=e.indexOf("=");if(t!==-1){const n=e.slice(2,t);const o=e.slice(t+1);r.options[n]=o}else{const n=e.slice(2);if(!A.has(n)){const o=s[i+1];if(o!==void 0&&!o.startsWith("--")&&o!=="-h"){r.options[n]=o;i++}else{r.options[n]=true}}else{r.options[n]=true}}}else{r.positional.push(e)}}return r}async function b(s){const r=s??process.argv.slice(2);const{positional:i,options:e}=M(r);const[t,n,...o]=i;if(e.version){console.log(_);return}if(e.help){h();return}if(t==="usage"){O();return}if(t==="help"){h();return}if(!t){h();return}const g=j[t]??t;if(g==="mindmap"){const l=process.env["MEMORY_DATA_DIR"]??f.resolve(process.cwd(),"memory");const m=new S.MindmapEngine(l);const u=n;const c=o[0];const d=o.slice(1);if(!u){console.log("Usage: crewx memory mindmap <subcommand> [agent_id] [args]");console.log("");console.log("Subcommands:");console.log(" build <agent_id> - Build graph");console.log(" show <agent_id> [--period=stm|mtm|ltm] [--format=mermaid|text] - Graph summary");console.log(" related <agent_id> <memory_id> - View related memories");console.log(" add <agent_id> <from_id> <to_id> [type] - Add manual relation");console.log(" remove <agent_id> <from_id> <to_id> - Remove relation");console.log(" html - Generate shared HTML");console.log(" open [agent_id] - Open in browser");process.exit(1)}switch(u){case"build":if(!c){console.log("Error: agent_id is required");process.exit(1)}m.build(c,e);break;case"show":if(!c){console.log("Error: agent_id is required");process.exit(1)}m.show(c,{period:e.period,format:e.format});break;case"related":if(!c||!d?.[0]){console.log("Error: agent_id and memory_id are required");process.exit(1)}m.related(c,d[0]);break;case"add":if(!c||!d?.[0]||!d?.[1]){console.log("Error: agent_id, from_id and to_id are required");process.exit(1)}m.add(c,d[0],d[1],d[2]);break;case"remove":if(!c||!d?.[0]||!d?.[1]){console.log("Error: agent_id, from_id and to_id are required");process.exit(1)}m.remove(c,d[0],d[1]);break;case"html":m.html();break;case"open":m.open(c);break;default:console.log(`Unknown mindmap subcommand: ${u}`);process.exit(1)}return}const a=new k.MemoryEngine;if(g==="summarize-dirty"){a.summarizeDirty();return}if(!n){console.log("Error: agent_id is required");process.exit(1)}switch(g){case"save":{const l=o[0];if(!l){console.log("Error: summary is required");process.exit(1)}let m;if(o[1]&&x.CATEGORIES.includes(o[1])){m=o[1]}else{m="general";if(o[1]&&!e.tags){e.tags=o[1]}}if(o[2]&&!e.body){e.body=o[2]}if(!e.body&&!process.stdin.isTTY){const u=q();let c;try{c=await Promise.race([u.body,new Promise(d=>setTimeout(()=>d(""),100))])}finally{u.release()}if(c){e.body=c}}a.save(n,l,m,e);break}case"index":a.index(n,e);break;case"list":a.list(n,e);break;case"stats":a.stats(n);break;case"tags":if(o[0]){a.topic(n,o[0])}else{a.tags(n)}break;case"recent":a.recent(n,parseInt(o[0]??"",10)||30);break;case"find":if(!o[0]){console.log("Error: keyword is required");process.exit(1)}a.find(n,o[0]);break;case"get":if(!o[0]){console.log("Error: memory_id is required");process.exit(1)}a.get(n,o[0]);break;case"search":if(!o[0]){console.log("Error: query is required");process.exit(1)}a.search(n,o.join(" "));break;case"update":if(!o[0]){console.log("Error: memory_id is required");process.exit(1)}a.update(n,o[0],e);break;case"delete":if(!o[0]){console.log("Error: memory_id is required");process.exit(1)}a.delete(n,o[0],e);break;case"merge":if(!o[0]||!o[1]){console.log("Error: two memory_ids are required");console.log('Usage: node cli.ts merge <agent_id> <id1> <id2> [--summary="merge summary"]');process.exit(1)}a.merge(n,o[0],o[1],e);break;case"summarize":a.summarize(n,e);break;default:console.log(`Unknown command: ${t}`);process.exit(1)}}if(require.main===module){E().then(s=>{const r=s?{skillVersion:s.getOwnSkillVersion(__dirname)}:{};return s?s.run("crewx/memory",()=>b(),r):b()}).catch(s=>{console.error(s.message);process.exit(1)})}
@@ -1,4 +1,4 @@
1
- "use strict";var v=exports&&exports.__importDefault||function($){return $&&$.__esModule?$:{"default":$}};Object.defineProperty(exports,"__esModule",{value:true});exports.CATEGORIES=exports.MemoryEngine=exports.SUMMARIZE_LOCK_STALE_MS=exports.SUMMARIZER_FAILURE_THRESHOLD=void 0;exports.getMemoryConfig=I;exports.createMemoryEngine=W;const l=v(require("fs"));const D=v(require("path"));const N=require("child_process");const R=require("nanoid");const B=v(require("js-yaml"));const T=require("./parser");const _=require("@crewx/knowledge-core");const M=require("@crewx/sdk");exports.SUMMARIZER_FAILURE_THRESHOLD=3;const H=".summarizer-health.json";const z=50;function U(){const $=(0,M.resolveCrewxExecutable)({env:process.env,cwd:process.cwd()});if(!$.ok){const n=new Error((0,M.formatCrewxExecutableFailure)($));Object.assign(n,{code:"CLI_UNRESOLVABLE"});throw n}const e=(0,M.createCrewxChildInvocation)($,{baseEnv:process.env});const t=(0,M.resolveWindowsSpawnProgram)({command:e.command,env:e.env,cwd:process.cwd(),packageName:"crewx",allowShellFallback:true});const r=(0,M.materializeWindowsSpawnProgram)(t,e.args);return{command:r.command,args:r.argv,env:e.env,shell:r.shell,windowsHide:r.windowsHide}}function k($,e){const t=U();return(0,N.execFileSync)(t.command,[...t.args,...$],{...e,env:t.env,...t.shell===void 0?{}:{shell:t.shell},...t.windowsHide===void 0?{}:{windowsHide:t.windowsHide}})}exports.SUMMARIZE_LOCK_STALE_MS=10*60*1e3;function j($){const e=$.match(/📄 Response:\s*─+\s*([\s\S]*?)(?=📁 Working Directory|$)/);if(e?.[1]){const t=e[1].trim();const r=t.split("\n")[0]?.trim()??"";if(!r.startsWith("{")){return t}return O(t)}return O($)}function O($){const e=$.split("\n").filter(o=>o.trim().startsWith("{"));let t="";let r=false;for(const o of e){try{const i=JSON.parse(o);if(i.type==="message"&&i.role==="assistant"){r=true;if(i.content)t+=i.content}}catch(i){}}if(r)return t.trim()||null;const n=$.trim();if(n.length===0)return null;const s=n.split("\n")[0]?.trim()??"";if(s.startsWith("{"))return null;return n}function q(){try{return(0,N.execSync)("git rev-parse --show-toplevel",{encoding:"utf8"}).trim()}catch{return process.cwd()}}function I(){try{const $=process.env.CREWX_CONFIG??D.default.join(q(),"crewx.yaml");const e=l.default.readFileSync($,"utf8");const t=B.default.load(e);const r=t?.settings;return r?.memory??{}}catch{return{}}}class P{constructor(e={}){this.searchIndexCache=new Map;const t=I();this.dataDir=e.dataDir??process.env["MEMORY_DATA_DIR"]??D.default.resolve(process.cwd(),"memory");this.summaryDays=e.summaryDays??(t.summary_days!=null?Number(t.summary_days):void 0)??(parseInt(process.env["MEMORY_SUMMARY_DAYS"]??"",10)||7);this.recentDays=e.recentDays??(t.recent_days!=null?Number(t.recent_days):void 0)??(parseInt(process.env["MEMORY_RECENT_DAYS"]??"",10)||30);this.shortTermHours=e.shortTermHours??(t.short_term_hours!=null?Number(t.short_term_hours):void 0)??24;this.summarizerAgent=e.summarizerAgent??t.summarizer_agent??"@memory_summarizer";this.searcherAgent=e.searcherAgent??t.searcher_agent??"@memory_searcher";this.summarizerTimeout=e.summarizerTimeout??(t.summarizer_timeout!=null?Number(t.summarizer_timeout):void 0)??48e4;this.searcherTimeout=e.searcherTimeout??(t.searcher_timeout!=null?Number(t.searcher_timeout):void 0)??3e5}getAgentDir(e){return D.default.join(this.dataDir,e)}getEntriesDir(e){return D.default.join(this.getAgentDir(e),"entries")}getEntryFilesFingerprint(e){const t=this.getEntriesDir(e);if(!l.default.existsSync(t))return{files:[],fingerprint:""};const r=l.default.readdirSync(t).filter(s=>s.endsWith(".md")).sort();const n=r.map(s=>{const o=l.default.statSync(D.default.join(t,s));return`${s}\0${o.size}\0${o.mtimeMs}`}).join("");return{files:r,fingerprint:n}}buildSearchIndex(e,t){const r=this.getEntriesDir(e);const n=t.map(s=>{const o=l.default.readFileSync(D.default.join(r,s),"utf-8");const{data:i,content:d}=(0,T.parseFrontmatter)(o);return{...i,file:s,body:d}});return(0,_.createSearchIndex)(n,{summary:3,tags:2,body:1})}getSearchIndex(e){const t=this.getEntryFilesFingerprint(e);const r=this.searchIndexCache.get(e);if(r?.fingerprint===t.fingerprint){return{files:t.files,index:r.index}}const n=this.buildSearchIndex(e,t.files);this.searchIndexCache.set(e,{fingerprint:t.fingerprint,index:n});return{files:t.files,index:n}}invalidateSearchIndex(e){this.searchIndexCache.delete(e)}createFindActionContext(e,t,r){return{commandId:"memory.find",params:{agentId:e,query:t},resultTags:[...new Set(r.flatMap(n=>n.tags??[]))].slice(0,3),resultIds:r.slice(0,3).map(n=>n.id),resultCount:r.length}}getSummaryPath(e){return D.default.join(this.getAgentDir(e),"summary.md")}getDirtySummaryPath(e){return D.default.join(this.getAgentDir(e),".dirty-summary")}getSummarizeLockPath(){return D.default.join(this.dataDir,".summarize.lock")}ensureDir(e){if(!l.default.existsSync(e)){l.default.mkdirSync(e,{recursive:true})}}generateId(){return(0,R.nanoid)(6)}getToday(){return new Date().toISOString().slice(0,10)}getLocalISO8601(){const e=new Date;const t=-e.getTimezoneOffset();const r=t>=0?"+":"-";const n=String(Math.floor(Math.abs(t)/60)).padStart(2,"0");const s=String(Math.abs(t)%60).padStart(2,"0");const o=e.getFullYear();const i=String(e.getMonth()+1).padStart(2,"0");const d=String(e.getDate()).padStart(2,"0");const f=String(e.getHours()).padStart(2,"0");const a=String(e.getMinutes()).padStart(2,"0");const c=String(e.getSeconds()).padStart(2,"0");return`${o}-${i}-${d}T${f}:${a}:${c}${r}${n}:${s}`}getPrimaryTag(e){return e.tags?.[0]??"general"}toEntryTimestamp(e){if(e["created_at"])return String(e["created_at"]);const t=e["date"];const r=t&&typeof t==="object"&&typeof t.toISOString==="function"?t.toISOString().slice(0,10):String(t??"");if(r.includes("T"))return r;return r+"T09:00:00+09:00"}markSummaryDirty(e){this.ensureDir(this.getAgentDir(e));l.default.writeFileSync(this.getDirtySummaryPath(e),String(Date.now()),"utf-8")}getSummarizerHealthPath(){return D.default.join(this.dataDir,H)}readSummarizerHealth(){try{const e=l.default.readFileSync(this.getSummarizerHealthPath(),"utf-8");const t=JSON.parse(e);return{consecutiveFailures:typeof t.consecutiveFailures==="number"?t.consecutiveFailures:0,notified:Boolean(t.notified)}}catch{return{consecutiveFailures:0,notified:false}}}writeSummarizerHealth(e){this.ensureDir(this.dataDir);l.default.writeFileSync(this.getSummarizerHealthPath(),JSON.stringify(e),"utf-8")}recordSummarizerFailure(){const e=this.readSummarizerHealth();e.consecutiveFailures+=1;if(e.consecutiveFailures>=exports.SUMMARIZER_FAILURE_THRESHOLD&&!e.notified){this.notifySummarizerDegraded(e.consecutiveFailures);e.notified=true}this.writeSummarizerHealth(e)}recordSummarizerSuccess(){const e=this.readSummarizerHealth();if(e.consecutiveFailures===0&&!e.notified)return;this.writeSummarizerHealth({consecutiveFailures:0,notified:false})}notifySummarizerDegraded(e){try{k(["notify","AI memory summarization keeps failing \u2014 falling back to mechanical summaries","--level=warning","--body=callSummarizer(agent="+this.summarizerAgent+") failed "+e+" times in a row, so summarization switched to the fallback (mechanical) path."],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:15e3})}catch(t){const r=t;console.error(`[memory] failed to send summarizer-health notify: ${r.message}`)}}loadAllEntries(e){const t=this.getEntriesDir(e);if(!l.default.existsSync(t))return[];const r=l.default.readdirSync(t).filter(s=>s.endsWith(".md"));const n=[];for(const s of r){const o=l.default.readFileSync(D.default.join(t,s),"utf-8");const{data:i,content:d}=(0,T.parseFrontmatter)(o);const f=d.replace(/^#[^\n]*\n*/m,"").trim();const a=Boolean(f)&&f!=="(Add details here)";const c=i;n.push({...c,file:s,hasBody:a})}n.sort((s,o)=>this.toEntryTimestamp(o).localeCompare(this.toEntryTimestamp(s)));return n}findEntryById(e,t){const r=this.getEntriesDir(e);if(!l.default.existsSync(r))return null;const n=l.default.readdirSync(r).filter(s=>s.endsWith(".md"));for(const s of n){const o=D.default.join(r,s);const i=l.default.readFileSync(o,"utf-8");const{data:d,content:f}=(0,T.parseFrontmatter)(i);if(d.id===t){return{file:s,filePath:o,data:d,content:f}}}return null}save(e,t,r="general",n={}){this.ensureDir(this.getEntriesDir(e));const s=this.generateId();const o=this.getLocalISO8601();const i=Array.isArray(n.tags)?n.tags:n.tags?n.tags.split(",").map(h=>h.trim()):[];const d=(0,T.stringifyFrontmatter)({id:s,type:"memory",date:o,category:r,tags:i,summary:t,...n.important?{important:true}:{}});const f=`${s}.md`;const a=D.default.join(this.getEntriesDir(e),f);const c=n.body??"(Add details here)";const m=`${d}
1
+ "use strict";var v=exports&&exports.__importDefault||function($){return $&&$.__esModule?$:{"default":$}};Object.defineProperty(exports,"__esModule",{value:true});exports.CATEGORIES=exports.MemoryEngine=exports.SUMMARIZE_LOCK_STALE_MS=exports.SUMMARIZER_FAILURE_THRESHOLD=void 0;exports.getMemoryConfig=P;exports.createMemoryEngine=Z;const l=v(require("fs"));const D=v(require("path"));const N=require("child_process");const B=require("nanoid");const H=v(require("js-yaml"));const T=require("./parser");const j=require("./summarizer-failure");const _=require("@crewx/knowledge-core");const z=require("@crewx/sdk");exports.SUMMARIZER_FAILURE_THRESHOLD=3;const U=".summarizer-health.json";const M=50;function q(){const $=(0,z.resolveCrewxExecutable)({env:process.env,cwd:process.cwd()});if(!$.ok){const n=new Error((0,z.formatCrewxExecutableFailure)($));Object.assign(n,{code:"CLI_UNRESOLVABLE"});throw n}const e=(0,z.createCrewxChildInvocation)($,{baseEnv:process.env});const t=(0,z.resolveWindowsSpawnProgram)({command:e.command,env:e.env,cwd:process.cwd(),packageName:"crewx",allowShellFallback:true});const r=(0,z.materializeWindowsSpawnProgram)(t,e.args);return{command:r.command,args:r.argv,env:e.env,shell:r.shell,windowsHide:r.windowsHide}}function k($,e){const t=q();return(0,N.execFileSync)(t.command,[...t.args,...$],{...e,env:t.env,...t.shell===void 0?{}:{shell:t.shell},...t.windowsHide===void 0?{}:{windowsHide:t.windowsHide}})}exports.SUMMARIZE_LOCK_STALE_MS=10*60*1e3;function O($){const e=$.match(/📄 Response:\s*─+\s*([\s\S]*?)(?=📁 Working Directory|$)/);if(e?.[1]){const t=e[1].trim();const r=t.split("\n")[0]?.trim()??"";if(!r.startsWith("{")){return t}return I(t)}return I($)}function I($){const e=$.split("\n").filter(o=>o.trim().startsWith("{"));let t="";let r=false;for(const o of e){try{const i=JSON.parse(o);if(i.type==="message"&&i.role==="assistant"){r=true;if(i.content)t+=i.content}}catch(i){}}if(r)return t.trim()||null;const n=$.trim();if(n.length===0)return null;const s=n.split("\n")[0]?.trim()??"";if(s.startsWith("{"))return null;return n}function W(){try{return(0,N.execSync)("git rev-parse --show-toplevel",{encoding:"utf8"}).trim()}catch{return process.cwd()}}function P(){try{const $=process.env.CREWX_CONFIG??D.default.join(W(),"crewx.yaml");const e=l.default.readFileSync($,"utf8");const t=H.default.load(e);const r=t?.settings;return r?.memory??{}}catch{return{}}}class L{constructor(e={}){this.searchIndexCache=new Map;const t=P();this.dataDir=e.dataDir??process.env["MEMORY_DATA_DIR"]??D.default.resolve(process.cwd(),"memory");this.summaryDays=e.summaryDays??(t.summary_days!=null?Number(t.summary_days):void 0)??(parseInt(process.env["MEMORY_SUMMARY_DAYS"]??"",10)||7);this.recentDays=e.recentDays??(t.recent_days!=null?Number(t.recent_days):void 0)??(parseInt(process.env["MEMORY_RECENT_DAYS"]??"",10)||30);this.shortTermHours=e.shortTermHours??(t.short_term_hours!=null?Number(t.short_term_hours):void 0)??24;this.summarizerAgent=e.summarizerAgent??t.summarizer_agent??"@memory_summarizer";this.searcherAgent=e.searcherAgent??t.searcher_agent??"@memory_searcher";this.summarizerTimeout=e.summarizerTimeout??(t.summarizer_timeout!=null?Number(t.summarizer_timeout):void 0)??48e4;this.searcherTimeout=e.searcherTimeout??(t.searcher_timeout!=null?Number(t.searcher_timeout):void 0)??3e5}getAgentDir(e){return D.default.join(this.dataDir,e)}getEntriesDir(e){return D.default.join(this.getAgentDir(e),"entries")}getEntryFilesFingerprint(e){const t=this.getEntriesDir(e);if(!l.default.existsSync(t))return{files:[],fingerprint:""};const r=l.default.readdirSync(t).filter(s=>s.endsWith(".md")).sort();const n=r.map(s=>{const o=l.default.statSync(D.default.join(t,s));return`${s}\0${o.size}\0${o.mtimeMs}`}).join("");return{files:r,fingerprint:n}}buildSearchIndex(e,t){const r=this.getEntriesDir(e);const n=t.map(s=>{const o=l.default.readFileSync(D.default.join(r,s),"utf-8");const{data:i,content:d}=(0,T.parseFrontmatter)(o);return{...i,file:s,body:d}});return(0,_.createSearchIndex)(n,{summary:3,tags:2,body:1})}getSearchIndex(e){const t=this.getEntryFilesFingerprint(e);const r=this.searchIndexCache.get(e);if(r?.fingerprint===t.fingerprint){return{files:t.files,index:r.index}}const n=this.buildSearchIndex(e,t.files);this.searchIndexCache.set(e,{fingerprint:t.fingerprint,index:n});return{files:t.files,index:n}}invalidateSearchIndex(e){this.searchIndexCache.delete(e)}createFindActionContext(e,t,r){return{commandId:"memory.find",params:{agentId:e,query:t},resultTags:[...new Set(r.flatMap(n=>n.tags??[]))].slice(0,3),resultIds:r.slice(0,3).map(n=>n.id),resultCount:r.length}}getSummaryPath(e){return D.default.join(this.getAgentDir(e),"summary.md")}getDirtySummaryPath(e){return D.default.join(this.getAgentDir(e),".dirty-summary")}getSummarizeLockPath(){return D.default.join(this.dataDir,".summarize.lock")}ensureDir(e){if(!l.default.existsSync(e)){l.default.mkdirSync(e,{recursive:true})}}generateId(){return(0,B.nanoid)(6)}getToday(){return new Date().toISOString().slice(0,10)}getLocalISO8601(){const e=new Date;const t=-e.getTimezoneOffset();const r=t>=0?"+":"-";const n=String(Math.floor(Math.abs(t)/60)).padStart(2,"0");const s=String(Math.abs(t)%60).padStart(2,"0");const o=e.getFullYear();const i=String(e.getMonth()+1).padStart(2,"0");const d=String(e.getDate()).padStart(2,"0");const f=String(e.getHours()).padStart(2,"0");const a=String(e.getMinutes()).padStart(2,"0");const c=String(e.getSeconds()).padStart(2,"0");return`${o}-${i}-${d}T${f}:${a}:${c}${r}${n}:${s}`}getPrimaryTag(e){return e.tags?.[0]??"general"}toEntryTimestamp(e){if(e["created_at"])return String(e["created_at"]);const t=e["date"];const r=t&&typeof t==="object"&&typeof t.toISOString==="function"?t.toISOString().slice(0,10):String(t??"");if(r.includes("T"))return r;return r+"T09:00:00+09:00"}markSummaryDirty(e){this.ensureDir(this.getAgentDir(e));l.default.writeFileSync(this.getDirtySummaryPath(e),String(Date.now()),"utf-8")}getSummarizerHealthPath(){return D.default.join(this.dataDir,U)}readSummarizerHealth(){try{const e=l.default.readFileSync(this.getSummarizerHealthPath(),"utf-8");const t=JSON.parse(e);return{consecutiveFailures:typeof t.consecutiveFailures==="number"?t.consecutiveFailures:0,notified:Boolean(t.notified),lastError:t.lastError}}catch{return{consecutiveFailures:0,notified:false}}}writeSummarizerHealth(e){this.ensureDir(this.dataDir);l.default.writeFileSync(this.getSummarizerHealthPath(),JSON.stringify(e),"utf-8")}recordSummarizerFailure(e){const t=this.readSummarizerHealth();t.consecutiveFailures+=1;t.lastError=e.code||e.message?e:void 0;if(t.consecutiveFailures>=exports.SUMMARIZER_FAILURE_THRESHOLD&&!t.notified){this.notifySummarizerDegraded(t.consecutiveFailures,t.lastError);t.notified=true}this.writeSummarizerHealth(t)}recordSummarizerSuccess(){const e=this.readSummarizerHealth();if(e.consecutiveFailures===0&&!e.notified)return;this.writeSummarizerHealth({consecutiveFailures:0,notified:false})}notifySummarizerDegraded(e,t){try{k(["notify","AI memory summarization keeps failing \u2014 falling back to mechanical summaries","--level=warning","--body=callSummarizer(agent="+this.summarizerAgent+") failed "+e+" times in a row (last error: "+(0,j.formatSummarizerLastError)(t)+"), so summarization switched to the fallback (mechanical) path."],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:15e3})}catch(r){const n=r;console.error(`[memory] failed to send summarizer-health notify: ${n.message}`)}}loadAllEntries(e){const t=this.getEntriesDir(e);if(!l.default.existsSync(t))return[];const r=l.default.readdirSync(t).filter(s=>s.endsWith(".md"));const n=[];for(const s of r){const o=l.default.readFileSync(D.default.join(t,s),"utf-8");const{data:i,content:d}=(0,T.parseFrontmatter)(o);const f=d.replace(/^#[^\n]*\n*/m,"").trim();const a=Boolean(f)&&f!=="(Add details here)";const c=i;n.push({...c,file:s,hasBody:a})}n.sort((s,o)=>this.toEntryTimestamp(o).localeCompare(this.toEntryTimestamp(s)));return n}findEntryById(e,t){const r=this.getEntriesDir(e);if(!l.default.existsSync(r))return null;const n=l.default.readdirSync(r).filter(s=>s.endsWith(".md"));for(const s of n){const o=D.default.join(r,s);const i=l.default.readFileSync(o,"utf-8");const{data:d,content:f}=(0,T.parseFrontmatter)(i);if(d.id===t){return{file:s,filePath:o,data:d,content:f}}}return null}save(e,t,r="general",n={}){this.ensureDir(this.getEntriesDir(e));const s=this.generateId();const o=this.getLocalISO8601();const i=Array.isArray(n.tags)?n.tags:n.tags?n.tags.split(",").map(h=>h.trim()):[];const d=(0,T.stringifyFrontmatter)({id:s,type:"memory",date:o,category:r,tags:i,summary:t,...n.important?{important:true}:{}});const f=`${s}.md`;const a=D.default.join(this.getEntriesDir(e),f);const c=n.body??"(Add details here)";const m=`${d}
2
2
 
3
3
  # ${t}
4
4
 
@@ -30,7 +30,7 @@ ${c}
30
30
  `;if(d>0)i+=`- Older than ${this.recentDays} days: ${d} items
31
31
  `;return i}topic(e,t){const r=this.loadAllEntries(e);const n=r.filter(s=>this.getPrimaryTag(s)===t);if(n.length===0){console.log(`No memories found for topic '${t}'.`);return}console.log(`## \u{1F4C2} Topic: ${t} (${n.length} items)
32
32
  `);for(const s of n){console.log(`### [${s.date}] ${s.summary}`);console.log(`- File: data/${e}/entries/${s.file}`);console.log(`- Category: ${s.category??"-"}`);console.log(`- Tags: ${(s.tags??[]).join(", ")||"-"}`);console.log("")}}recent(e,t=30){const r=this.getRecentEntries(e,t);if(r.length===0){console.log(`No memories found in the last ${t} days.`);return}console.log(`## \u{1F525} Last ${t} days (${r.length} items)
33
- `);for(const n of r){const s=n.hasBody?" \u{1F4C4}":"";const o=String(n.date).includes("T")?String(n.date).slice(0,16).replace("T"," "):n.date;console.log(`[${n.id}] [${o}] [${n.category??"-"}] ${n.summary}${s}`)}}getRecentEntries(e,t=30,r={}){const n=this.loadAllEntries(e);const s=new Date(Date.now()-t*24*60*60*1e3).toISOString().slice(0,10);const o=n.filter(i=>this.resolveRecentDate(e,i).slice(0,10)>=s);if(!r.includeBody)return o;return o.map(i=>({...i,body:this.readEntryBody(e,i.file)}))}resolveRecentDate(e,t){const r=this.toDateString(t.updated);if(r)return r;const n=this.toDateString(t["created_at"]);if(n)return n;const s=this.toDateString(t.date);if(s)return s;try{const o=D.default.join(this.getEntriesDir(e),t.file);return l.default.statSync(o).mtime.toISOString()}catch{return""}}toDateString(e){if(e&&typeof e==="object"&&typeof e.toISOString==="function"){return e.toISOString()}return typeof e==="string"?e:""}readEntryBody(e,t){try{const r=l.default.readFileSync(D.default.join(this.getEntriesDir(e),t),"utf-8");const{content:n}=(0,T.parseFrontmatter)(r);return n.replace(/^#[^\n]*\n*/m,"").trim()}catch{return""}}find(e,t){const{files:r,index:n}=this.getSearchIndex(e);if(r.length===0){console.log("No memories found.");return}const s=n.search(t,z+1);const o=s.length>z;const i=s.slice(0,z);if(i.length===0){console.log(`No related memories found for '${t}'.`);return}const d=o?`, top ${z}`:"";console.log(`## \u{1F50D} Search results: "${t}" (${i.length} items${d}, sorted by BM25 score)
33
+ `);for(const n of r){const s=n.hasBody?" \u{1F4C4}":"";const o=String(n.date).includes("T")?String(n.date).slice(0,16).replace("T"," "):n.date;console.log(`[${n.id}] [${o}] [${n.category??"-"}] ${n.summary}${s}`)}}getRecentEntries(e,t=30,r={}){const n=this.loadAllEntries(e);const s=new Date(Date.now()-t*24*60*60*1e3).toISOString().slice(0,10);const o=n.filter(i=>this.resolveRecentDate(e,i).slice(0,10)>=s);if(!r.includeBody)return o;return o.map(i=>({...i,body:this.readEntryBody(e,i.file)}))}resolveRecentDate(e,t){const r=this.toDateString(t.updated);if(r)return r;const n=this.toDateString(t["created_at"]);if(n)return n;const s=this.toDateString(t.date);if(s)return s;try{const o=D.default.join(this.getEntriesDir(e),t.file);return l.default.statSync(o).mtime.toISOString()}catch{return""}}toDateString(e){if(e&&typeof e==="object"&&typeof e.toISOString==="function"){return e.toISOString()}return typeof e==="string"?e:""}readEntryBody(e,t){try{const r=l.default.readFileSync(D.default.join(this.getEntriesDir(e),t),"utf-8");const{content:n}=(0,T.parseFrontmatter)(r);return n.replace(/^#[^\n]*\n*/m,"").trim()}catch{return""}}find(e,t){const{files:r,index:n}=this.getSearchIndex(e);if(r.length===0){console.log("No memories found.");return}const s=n.search(t,M+1);const o=s.length>M;const i=s.slice(0,M);if(i.length===0){console.log(`No related memories found for '${t}'.`);return}const d=o?`, top ${M}`:"";console.log(`## \u{1F50D} Search results: "${t}" (${i.length} items${d}, sorted by BM25 score)
34
34
  `);for(const m of i){const u=m._score!=null?` [${m._score}pts]`:"";console.log(`[${m.id}] [${m.date}] [${this.getPrimaryTag(m)}]${u} ${m.summary}`)}const f=this.createFindActionContext(e,t,i);const a=(0,_.generateNextActions)(f);const c=(0,_.formatActions)(a);if(c)console.log(c)}list(e,t={}){const r=this.loadAllEntries(e);let n=r;if(t.category){n=n.filter(a=>a.category===t.category)}if(t.tag){const a=t.tag.split(",").map(c=>c.trim());n=n.filter(c=>a.every(m=>(c.tags??[]).includes(m)))}if(t.json){const a=this.getEntriesDir(e);const c=n.map(m=>{let u="";if(m.file){try{const y=l.default.readFileSync(D.default.join(a,m.file),"utf-8");const{content:g}=(0,T.parseFrontmatter)(y);const h=g.replace(/^#[^\n]*\n*/m,"").trim();if(h!=="(Add details here)")u=h}catch(y){}}return{id:m.id,title:m.summary??"",category:m.category??"general",tags:m.tags??[],created_at:m.date??"",content:u}});console.log(JSON.stringify(c,null,2));return}if(n.length===0){const a=[];if(t.category)a.push(`category=${t.category}`);if(t.tag)a.push(`tag=${t.tag}`);console.log(`No memories match the filters. (${a.join(", ")||"all"})`);return}console.log(`## \u{1F4CB} List: ${e} (${n.length} items)
35
35
  `);for(const a of n){console.log(`[${a.id}] [${a.date}] [${this.getPrimaryTag(a)}] ${a.summary}`)}const s=[...new Set(n.flatMap(a=>a.tags??[]))].slice(0,3);const o=n.slice(0,3).map(a=>a.id);const i={commandId:"memory.list",params:{agentId:e,...t.category?{category:t.category}:{}},resultTags:s,resultIds:o,resultCount:n.length};const d=(0,_.generateNextActions)(i);const f=(0,_.formatActions)(d);if(f)console.log(f)}stats(e){const t=this.loadAllEntries(e);if(t.length===0){console.log("No memories found.");return}const r={};for(const a of t){const c=a.category??"general";r[c]=(r[c]??0)+1}const n={};for(const a of t){for(const c of a.tags??[]){n[c]=(n[c]??0)+1}}console.log(`# ${e} Stats (${t.length} items)
36
36
  `);console.log(`## By category`);for(const[a,c]of Object.entries(r).sort((m,u)=>u[1]-m[1])){console.log(` ${a}: ${c} items`)}console.log(`
@@ -66,7 +66,7 @@ ${a}
66
66
  `;for(const c of o)n+=`- [${c.date}] ${c.summary}
67
67
  `;for(const c of o)n+=`\u2192 [entries/${c.file}](entries/${c.file})
68
68
  `;n+=`
69
- `}return n}callSummarizer(e){try{const t=k(["q",this.summarizerAgent],{encoding:"utf-8",timeout:this.summarizerTimeout,stdio:["pipe","pipe","pipe"],input:e});const r=j(t);this.recordSummarizerSuccess();return r}catch(t){const r=t;const n=r.code==="ETIMEDOUT"||r.killed?`timed out after ${this.summarizerTimeout}ms`:r.message;console.error(`[memory] callSummarizer failed (agent=${this.summarizerAgent}), falling back to raw entry list: ${n}`);this.recordSummarizerFailure();return null}}generateSummary(e,t={}){const r=this.loadAllEntries(e);if(r.length===0)return{status:"empty"};const n=new Date(Date.now()-this.summaryDays*24*60*60*1e3).toISOString().slice(0,10);const s=t.force?r:r.filter(S=>S.date>=n);if(s.length===0)return{status:"empty",entryCount:r.length};const o=this.getSummaryPath(e);const i=l.default.existsSync(o)?(0,T.parseFrontmatter)(l.default.readFileSync(o,"utf-8")):null;const d=i?.data?.last_entry_id??null;const f=i?.content.trim()??null;const a=(S,A)=>{if(!A)return S;const x=S.findIndex(p=>p.id===A);if(x===-1)return S;return S.slice(0,x)};const c=a(s,d);if(c.length===0&&!t.force){return{status:"up-to-date",entryCount:r.length}}const m=t.force?s:c;const u=[...m].reverse().map(S=>{if(S.file){try{const A=l.default.readFileSync(D.default.join(this.getEntriesDir(e),S.file),"utf-8");const{content:x}=(0,T.parseFrontmatter)(A);const p=x.replace(/^#[^\n]*\n*/m,"").trim();return{...S,body:p}}catch(A){}}return S});const y=[...new Set(s.map(S=>this.getPrimaryTag(S)))].sort();const g=(S,A,x)=>{let p=`You are a memory summarizer for an AI agent.
69
+ `}return n}callSummarizer(e){try{const t=k(["q",this.summarizerAgent],{encoding:"utf-8",timeout:this.summarizerTimeout,stdio:["pipe","pipe","pipe"],input:e});const r=O(t);this.recordSummarizerSuccess();return r}catch(t){const r=t;const n=r.code==="ETIMEDOUT"||r.killed?`timed out after ${this.summarizerTimeout}ms`:r.message;console.error(`[memory] callSummarizer failed (agent=${this.summarizerAgent}), falling back to raw entry list: ${n}`);this.recordSummarizerFailure((0,j.describeSummarizerFailure)(r,this.summarizerTimeout));return null}}generateSummary(e,t={}){const r=this.loadAllEntries(e);if(r.length===0)return{status:"empty"};const n=new Date(Date.now()-this.summaryDays*24*60*60*1e3).toISOString().slice(0,10);const s=t.force?r:r.filter(S=>S.date>=n);if(s.length===0)return{status:"empty",entryCount:r.length};const o=this.getSummaryPath(e);const i=l.default.existsSync(o)?(0,T.parseFrontmatter)(l.default.readFileSync(o,"utf-8")):null;const d=i?.data?.last_entry_id??null;const f=i?.content.trim()??null;const a=(S,A)=>{if(!A)return S;const x=S.findIndex(p=>p.id===A);if(x===-1)return S;return S.slice(0,x)};const c=a(s,d);if(c.length===0&&!t.force){return{status:"up-to-date",entryCount:r.length}}const m=t.force?s:c;const u=[...m].reverse().map(S=>{if(S.file){try{const A=l.default.readFileSync(D.default.join(this.getEntriesDir(e),S.file),"utf-8");const{content:x}=(0,T.parseFrontmatter)(A);const p=x.replace(/^#[^\n]*\n*/m,"").trim();return{...S,body:p}}catch(A){}}return S});const y=[...new Set(s.map(S=>this.getPrimaryTag(S)))].sort();const g=(S,A,x)=>{let p=`You are a memory summarizer for an AI agent.
70
70
 
71
71
  `;if(S){p+=`## Existing summary:
72
72
  ${S}
@@ -83,7 +83,7 @@ ${S}
83
83
  `;p+=`- If there's an existing summary, merge new information into it
84
84
  `;p+=`- Topics to cover: ${x.join(", ")}
85
85
  `;p+=`- Output ONLY the markdown body (topic sections), no frontmatter or top-level heading
86
- `;return p};const h=g(t.force?null:f,u,y);const w=this.callSummarizer(h);const E=s[0]?.id;if(!w){const S=s.map(p=>{if(p.file){try{const b=l.default.readFileSync(D.default.join(this.getEntriesDir(e),p.file),"utf-8");const{content:C}=(0,T.parseFrontmatter)(b);const L=C.replace(/^#[^\n]*\n*/m,"").trim();return{...p,body:L}}catch(b){}}return p});const A=this.buildFallbackSummary(S);const x=(0,T.stringifyFrontmatter)({last_entry_id:E,last_updated:this.getToday(),entry_count:r.length,summary_days:this.summaryDays,summarizer:"fallback"});l.default.writeFileSync(o,`${x}
86
+ `;return p};const h=g(t.force?null:f,u,y);const w=this.callSummarizer(h);const E=s[0]?.id;if(!w){const S=s.map(p=>{if(p.file){try{const b=l.default.readFileSync(D.default.join(this.getEntriesDir(e),p.file),"utf-8");const{content:C}=(0,T.parseFrontmatter)(b);const R=C.replace(/^#[^\n]*\n*/m,"").trim();return{...p,body:R}}catch(b){}}return p});const A=this.buildFallbackSummary(S);const x=(0,T.stringifyFrontmatter)({last_entry_id:E,last_updated:this.getToday(),entry_count:r.length,summary_days:this.summaryDays,summarizer:"fallback"});l.default.writeFileSync(o,`${x}
87
87
 
88
88
  ${A}`,"utf-8");return{status:"fallback",entryCount:r.length,newEntries:m.length}}const F=(0,T.stringifyFrontmatter)({last_entry_id:E,last_updated:this.getToday(),entry_count:r.length,summary_days:this.summaryDays,summarizer:"memory_summarizer"});l.default.writeFileSync(o,`${F}
89
89
 
@@ -91,9 +91,9 @@ ${w}
91
91
  `,"utf-8");return{status:"updated",entryCount:r.length,newEntries:m.length}}summarize(e,t={}){const r=this.loadAllEntries(e);if(r.length===0){console.log("No memories found.");return}console.log(`\u{1F4DD} Starting summary generation (${r.length} items entries)
92
92
  `);const n=this.generateSummary(e,{force:t.force});if(n.status==="up-to-date"){console.log("\u2705 summary.md is up to date.")}else if(n.status==="fallback"){console.log(`\u{1F4CB} Fallback summary generated (AI call failed)`)}else if(n.status==="updated"){console.log(`\u{1F916} Summary complete (${n.newEntries} items applied)`)}console.log(` File: data/${e}/summary.md`);console.log(` entries: ${n.entryCount} items`)}isSummarizeLockStale(e){let t;try{t=l.default.readFileSync(e,"utf-8")}catch{return true}const r=t.match(/^pid=(\d+)/m);const n=r?Number(r[1]):NaN;if(Number.isFinite(n)){try{process.kill(n,0);return false}catch(s){const o=s;if(o.code==="ESRCH")return true}}try{const s=l.default.statSync(e);return Date.now()-s.mtimeMs>exports.SUMMARIZE_LOCK_STALE_MS}catch{return true}}acquireSummarizeLock(){const e=this.getSummarizeLockPath();const t=`pid=${process.pid}
93
93
  mtime=${new Date().toISOString()}
94
- `;try{const r=l.default.openSync(e,"wx");l.default.writeSync(r,t);l.default.closeSync(r);return true}catch(r){const n=r;if(n.code!=="EEXIST")throw n}if(!this.isSummarizeLockStale(e)){return false}l.default.writeFileSync(e,t,"utf-8");return true}releaseSummarizeLock(){try{l.default.unlinkSync(this.getSummarizeLockPath())}catch{}}summarizeDirty(){if(!l.default.existsSync(this.dataDir)){console.log(`\u{1F4A1} Register debounce cron:`);console.log(`npx cron add "*/1 * * * *" "npx memory summarize-dirty" --mode command --name "memory-debounce"`);return}if(!this.acquireSummarizeLock()){console.log(`\u23ED\uFE0F summarize-dirty is already running (lock held) \u2014 skipping this run.`);return}try{const e=l.default.readdirSync(this.dataDir,{withFileTypes:true}).filter(t=>t.isDirectory()).map(t=>t.name);for(const t of e){const r=this.getDirtySummaryPath(t);if(!l.default.existsSync(r))continue;try{const n=this.generateSummary(t);if(n.status==="updated"){console.log(`\u{1F916} ${t} summary.md updated (${n.newEntries} items applied)`)}else if(n.status==="fallback"){console.log(`\u{1F4CB} ${t} Fallback summary generated (AI call failed)`)}else if(n.status==="up-to-date"){console.log(`\u2705 ${t} summary.md is up to date.`)}else if(n.status==="empty"){console.log(`\u2139\uFE0F ${t} has no memories to summarize.`)}l.default.unlinkSync(r)}catch(n){console.error(`\u274C ${t} summary.md update failed: ${n.message}`)}}}finally{this.releaseSummarizeLock()}console.log(`\u{1F4A1} Register debounce cron:`);console.log(`npx cron add "*/1 * * * *" "npx memory summarize-dirty" --mode command --name "memory-debounce"`)}search(e,t){const r=this.loadAllEntries(e);if(r.length===0){console.log("No memories found.");return}const n=r.map(o=>`[${o.id}] [${o.date}] [${this.getPrimaryTag(o)}] ${o.summary}`).join("\n");const s=`Memory list:
94
+ `;try{const r=l.default.openSync(e,"wx");l.default.writeSync(r,t);l.default.closeSync(r);return true}catch(r){const n=r;if(n.code!=="EEXIST")throw n}if(!this.isSummarizeLockStale(e)){return false}l.default.writeFileSync(e,t,"utf-8");return true}releaseSummarizeLock(){try{l.default.unlinkSync(this.getSummarizeLockPath())}catch{}}summarizeDirty(){if(!l.default.existsSync(this.dataDir)){console.log(`\u{1F4A1} Register debounce cron:`);console.log(`crewx cron add "*/1 * * * *" "crewx memory summarize-dirty" --mode command --name "memory-debounce"`);return}if(!this.acquireSummarizeLock()){console.log(`\u23ED\uFE0F summarize-dirty is already running (lock held) \u2014 skipping this run.`);return}try{const e=l.default.readdirSync(this.dataDir,{withFileTypes:true}).filter(t=>t.isDirectory()).map(t=>t.name);for(const t of e){const r=this.getDirtySummaryPath(t);if(!l.default.existsSync(r))continue;try{const n=this.generateSummary(t);if(n.status==="updated"){console.log(`\u{1F916} ${t} summary.md updated (${n.newEntries} items applied)`)}else if(n.status==="fallback"){console.log(`\u{1F4CB} ${t} Fallback summary generated (AI call failed)`)}else if(n.status==="up-to-date"){console.log(`\u2705 ${t} summary.md is up to date.`)}else if(n.status==="empty"){console.log(`\u2139\uFE0F ${t} has no memories to summarize.`)}l.default.unlinkSync(r)}catch(n){console.error(`\u274C ${t} summary.md update failed: ${n.message}`)}}}finally{this.releaseSummarizeLock()}console.log(`\u{1F4A1} Register debounce cron:`);console.log(`crewx cron add "*/1 * * * *" "crewx memory summarize-dirty" --mode command --name "memory-debounce"`)}search(e,t){const r=this.loadAllEntries(e);if(r.length===0){console.log("No memories found.");return}const n=r.map(o=>`[${o.id}] [${o.date}] [${this.getPrimaryTag(o)}] ${o.summary}`).join("\n");const s=`Memory list:
95
95
  ${n}
96
96
 
97
97
  Question: "${t}"`;try{console.log(`\u{1F50D} "${t}" searching... (${this.searcherAgent})
98
- `);const o=k(["q",`${this.searcherAgent} ${s}`],{encoding:"utf-8",timeout:this.searcherTimeout,stdio:["pipe","pipe","pipe"]});const i=j(o);if(i){console.log(`## \u{1F9E0} Semantic search results
99
- `);console.log(i)}else{console.log(o.trim())}}catch(o){const i=o;if(i.code==="ETIMEDOUT"||i.killed){console.log("Search failed: timed out (max 5 minutes)")}else{console.log("Search failed:",i.message)}console.log("\n\u{1F4A1} Tip: try keyword search with the find command.")}}}exports.MemoryEngine=P;function W($){return new P($)}var Z=require("./types");Object.defineProperty(exports,"CATEGORIES",{enumerable:true,get:function(){return Z.CATEGORIES}});
98
+ `);const o=k(["q",`${this.searcherAgent} ${s}`],{encoding:"utf-8",timeout:this.searcherTimeout,stdio:["pipe","pipe","pipe"]});const i=O(o);if(i){console.log(`## \u{1F9E0} Semantic search results
99
+ `);console.log(i)}else{console.log(o.trim())}}catch(o){const i=o;if(i.code==="ETIMEDOUT"||i.killed){console.log("Search failed: timed out (max 5 minutes)")}else{console.log("Search failed:",i.message)}console.log("\n\u{1F4A1} Tip: try keyword search with the find command.")}}}exports.MemoryEngine=L;function Z($){return new L($)}var Y=require("./types");Object.defineProperty(exports,"CATEGORIES",{enumerable:true,get:function(){return Y.CATEGORIES}});
@@ -0,0 +1,8 @@
1
+ export declare const SUMMARIZER_CAUSE_MESSAGE_MAX_CHARS = 200;
2
+ export interface SummarizerFailureCause {
3
+ code?: string;
4
+ message?: string;
5
+ }
6
+ export declare function describeSummarizerFailure(error: unknown, timeoutMs: number): SummarizerFailureCause;
7
+ export declare function formatSummarizerLastError(cause: SummarizerFailureCause | undefined): string;
8
+
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SUMMARIZER_CAUSE_MESSAGE_MAX_CHARS=void 0;exports.describeSummarizerFailure=a;exports.formatSummarizerLastError=u;const c=require("@crewx/sdk");exports.SUMMARIZER_CAUSE_MESSAGE_MAX_CHARS=200;function a(e,t){const n=typeof e==="object"&&e!==null?e:{};const r=m(n,t);if(!r)return{};const s={};const i=(0,c.classifyTaskError)({status:"failed",error:r}).errorCode;if(i)s.code=i;const o=d((0,c.redactTechnicalMessage)(r)??"");if(o)s.message=o;return s}function u(e){if(e?.code&&e.message)return`${e.code} \u2014 ${e.message}`;return e?.code??e?.message??"unknown"}function m(e,t){if(e.code==="ETIMEDOUT"||e.killed===true)return`timed out after ${t}ms`;const n=String(e.stderr??"").split(/\r?\n/).map(r=>r.trim()).filter(r=>r.length>0&&!r.startsWith("[crewx] "));if(n.length>0)return n[n.length-1];return typeof e.code==="string"?String(e.message??""):void 0}function d(e){const t=e.replace(/\s+/g," ").trim();return Array.from(t).slice(0,exports.SUMMARIZER_CAUSE_MESSAGE_MAX_CHARS).join("")}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/memory",
3
- "version": "0.1.23-rc.191",
3
+ "version": "0.1.23-rc.192",
4
4
  "description": "Memory engine for CrewX - markdown + frontmatter based long-term memory",
5
5
  "type": "commonjs",
6
6
  "main": "dist/src/engine.js",
@@ -36,9 +36,9 @@
36
36
  "gray-matter": "^4.0.3",
37
37
  "js-yaml": "^4.1.0",
38
38
  "nanoid": "^3.3.11",
39
- "@crewx/sdk": "0.9.0-rc.174",
40
- "@crewx/shared": "0.0.6-rc.89",
41
- "@crewx/knowledge-core": "0.1.17-rc.184"
39
+ "@crewx/sdk": "0.9.0-rc.175",
40
+ "@crewx/shared": "0.0.6-rc.90",
41
+ "@crewx/knowledge-core": "0.1.17-rc.185"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/js-yaml": "^4.0.9",