gnosys-mcp 1.1.1 → 1.3.0
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 +162 -55
- package/dist/cli.js +149 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.js +150 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/archive.d.ts +95 -0
- package/dist/lib/archive.d.ts.map +1 -0
- package/dist/lib/archive.js +311 -0
- package/dist/lib/archive.js.map +1 -0
- package/dist/lib/ask.d.ts +13 -1
- package/dist/lib/ask.d.ts.map +1 -1
- package/dist/lib/ask.js +86 -1
- package/dist/lib/ask.js.map +1 -1
- package/dist/lib/audit.d.ts +47 -0
- package/dist/lib/audit.d.ts.map +1 -0
- package/dist/lib/audit.js +136 -0
- package/dist/lib/audit.js.map +1 -0
- package/dist/lib/config.d.ts +31 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +38 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/dashboard.d.ts +10 -0
- package/dist/lib/dashboard.d.ts.map +1 -1
- package/dist/lib/dashboard.js +88 -1
- package/dist/lib/dashboard.js.map +1 -1
- package/dist/lib/embeddings.d.ts.map +1 -1
- package/dist/lib/embeddings.js +2 -0
- package/dist/lib/embeddings.js.map +1 -1
- package/dist/lib/hybridSearch.d.ts +11 -1
- package/dist/lib/hybridSearch.d.ts.map +1 -1
- package/dist/lib/hybridSearch.js +79 -16
- package/dist/lib/hybridSearch.js.map +1 -1
- package/dist/lib/lock.d.ts +28 -0
- package/dist/lib/lock.d.ts.map +1 -0
- package/dist/lib/lock.js +145 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/maintenance.d.ts +10 -0
- package/dist/lib/maintenance.d.ts.map +1 -1
- package/dist/lib/maintenance.js +121 -9
- package/dist/lib/maintenance.js.map +1 -1
- package/dist/lib/recall.d.ts +67 -0
- package/dist/lib/recall.d.ts.map +1 -0
- package/dist/lib/recall.js +211 -0
- package/dist/lib/recall.js.map +1 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -245,18 +245,29 @@ ANTHROPIC_API_KEY = "your-key-here"
|
|
|
245
245
|
| `gnosys_ask` | Ask a question, get a synthesized answer with citations |
|
|
246
246
|
| `gnosys_reindex` | Rebuild semantic embeddings from all memories |
|
|
247
247
|
| `gnosys_list` | List memories with optional filters |
|
|
248
|
+
| `gnosys_lens` | Filtered views — combine category, tag, status, confidence, date filters |
|
|
248
249
|
| `gnosys_add` | Add a memory (LLM-structured) |
|
|
249
250
|
| `gnosys_add_structured` | Add with explicit fields (no LLM) |
|
|
250
251
|
| `gnosys_update` | Update frontmatter or content |
|
|
251
252
|
| `gnosys_reinforce` | Signal usefulness of a memory |
|
|
252
253
|
| `gnosys_commit_context` | Extract memories from conversation context |
|
|
254
|
+
| `gnosys_bootstrap` | Batch-import existing markdown documents |
|
|
253
255
|
| `gnosys_import` | Bulk import from CSV, JSON, or JSONL |
|
|
254
256
|
| `gnosys_init` | Initialize a new store |
|
|
255
|
-
| `
|
|
256
|
-
| `
|
|
257
|
+
| `gnosys_stale` | Find memories not modified within N days |
|
|
258
|
+
| `gnosys_history` | Git-backed version history for a memory |
|
|
259
|
+
| `gnosys_rollback` | Rollback a memory to a previous commit |
|
|
260
|
+
| `gnosys_timeline` | Show when memories were created/modified over time |
|
|
261
|
+
| `gnosys_stats` | Summary statistics for the memory store |
|
|
262
|
+
| `gnosys_links` | Show wikilinks and backlinks for a memory |
|
|
263
|
+
| `gnosys_graph` | Full cross-reference graph across all memories |
|
|
264
|
+
| `gnosys_maintain` | Run vault maintenance (decay, dedup, consolidation, archiving) |
|
|
265
|
+
| `gnosys_dearchive` | Force-dearchive memories from archive back to active |
|
|
266
|
+
| `gnosys_dashboard` | System dashboard (memory count, health, archive, graph, LLM status) |
|
|
257
267
|
| `gnosys_reindex_graph` | Build/rebuild the wikilink graph |
|
|
258
268
|
| `gnosys_stores` | Show active stores |
|
|
259
269
|
| `gnosys_tags` | List tag registry |
|
|
270
|
+
| `gnosys_tags_add` | Add a new tag to the registry |
|
|
260
271
|
|
|
261
272
|
---
|
|
262
273
|
|
|
@@ -276,6 +287,7 @@ your-project/
|
|
|
276
287
|
nvd-cves/
|
|
277
288
|
cve-2024-1234.md
|
|
278
289
|
gnosys.json # configuration
|
|
290
|
+
archive.db # two-tier memory archive (SQLite)
|
|
279
291
|
.config/tags.json # tag registry
|
|
280
292
|
CHANGELOG.md
|
|
281
293
|
.git/ # auto-versioned
|
|
@@ -528,26 +540,111 @@ The `gnosys_maintain` MCP tool lets agents trigger maintenance programmatically
|
|
|
528
540
|
|
|
529
541
|
## Comparison
|
|
530
542
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
|
534
|
-
|
|
535
|
-
|
|
|
536
|
-
|
|
|
537
|
-
|
|
|
538
|
-
|
|
|
539
|
-
|
|
|
540
|
-
|
|
|
541
|
-
|
|
|
542
|
-
|
|
|
543
|
-
|
|
|
544
|
-
|
|
|
545
|
-
|
|
|
546
|
-
|
|
|
547
|
-
|
|
|
548
|
-
|
|
|
549
|
-
|
|
|
550
|
-
|
|
|
543
|
+
Agent memory is a spectrum — from a single markdown file to full knowledge graphs. Here's an honest look at the trade-offs.
|
|
544
|
+
|
|
545
|
+
| Aspect | Plain Markdown | RAG (Vector DB) | Knowledge Graph | **Gnosys** |
|
|
546
|
+
|--------|---------------|-----------------|-----------------|-----------|
|
|
547
|
+
| **Examples** | CLAUDE.md, .cursorrules | Mem0, LangChain Memory | Graphiti/Zep, Mem0 Graph | — |
|
|
548
|
+
| **Storage** | `.md` files | Embeddings in vector DB | Nodes/edges in graph DB | `.md` files + SQLite index + SQLite archive |
|
|
549
|
+
| **Transparency** | Perfect | Lossy (embeddings) | High (query nodes) | High (readable markdown) |
|
|
550
|
+
| **Version history** | Git native | None built-in | None built-in | Git native |
|
|
551
|
+
| **Keyword search** | Manual / grep | BM25 layer (some) | BM25 layer (some) | FTS5 (built-in) |
|
|
552
|
+
| **Semantic search** | None | Vector similarity | Graph + vectors | Vector + FTS5 hybrid (RRF) |
|
|
553
|
+
| **Relationship traversal** | None | None | Multi-hop graph queries | Wikilinks (manual encoding) |
|
|
554
|
+
| **Automatic extraction** | No | Yes (embeddings) | Yes (entities + edges) | No (explicit structuring) |
|
|
555
|
+
| **Conflict detection** | No | No | Yes (graph rules) | No |
|
|
556
|
+
| **Scale comfort zone** | ~5K memories | 100K+ | 100K+ | 100K+ (two-tier: active `.md` + SQLite archive) |
|
|
557
|
+
| **Setup time** | < 5 min | 30 min – 2 hours | 4 – 8 hours | 15 – 30 min |
|
|
558
|
+
| **Infrastructure** | None | Vector DB + embeddings API | Graph DB + LLM | SQLite (embedded) |
|
|
559
|
+
| **Human editability** | Excellent | Poor (re-embed) | Moderate | Excellent |
|
|
560
|
+
| **MCP integration** | Via skill files | Custom server | Mem0 ships MCP | MCP server (included) |
|
|
561
|
+
| **Obsidian compatible** | Partially | No | No | Yes (full vault) |
|
|
562
|
+
| **Cost** | Free | $0–500+/mo (cloud DB + embeddings) | $250+/mo (Mem0 Pro) or self-host | Free (MIT) |
|
|
563
|
+
| **Memory lifecycle** | Manual cleanup | Manual / TTL | Manual / TTL | Auto-archive + auto-dearchive on cite |
|
|
564
|
+
| **Offline capable** | Yes | Self-hosted only | Self-hosted only | Yes (Ollama/LM Studio) |
|
|
565
|
+
|
|
566
|
+
### Where others genuinely win
|
|
567
|
+
|
|
568
|
+
- **Knowledge graphs** (Graphiti, Mem0 Graph) excel at multi-hop reasoning ("Who does Alice report to?") and automatic conflict detection. If your domain has clear entities and relationships — org charts, dependency trees, CRM data — a graph DB is the right tool.
|
|
569
|
+
- **RAG/vector search** handles fuzzy semantic matching without requiring explicit keyword clouds. You don't need to think about relevance fields — the embeddings handle conceptual similarity automatically.
|
|
570
|
+
- **Automatic extraction** in both RAG and graph approaches means the system learns from conversations without you explicitly structuring each fact.
|
|
571
|
+
|
|
572
|
+
### Where Gnosys wins
|
|
573
|
+
|
|
574
|
+
- **Zero infrastructure**: No vector DB to deploy, no graph DB to manage. SQLite is embedded.
|
|
575
|
+
- **Full transparency**: Every memory is a readable, editable `.md` file. No opaque embeddings.
|
|
576
|
+
- **Git versioning**: Complete history, rollback, diff, blame. No other memory system versions every write.
|
|
577
|
+
- **Obsidian native**: Browse, edit, graph view, wikilinks — all with your existing Obsidian setup.
|
|
578
|
+
- **Hybrid search without a vector DB**: FTS5 keyword search is built-in. Semantic search is optional (local embeddings via Ollama, no API costs).
|
|
579
|
+
- **Bulk import**: CSV, JSON, JSONL. Turn a dataset into a searchable knowledge base in seconds.
|
|
580
|
+
- **Cost**: Genuinely free. No cloud service, no API costs if using local LLM providers.
|
|
581
|
+
- **Two-tier memory**: Active memories stay lightning-fast as markdown files. Old/low-confidence memories automatically archive to SQLite — and auto-dearchive when needed by search or ask.
|
|
582
|
+
|
|
583
|
+
### Two-Tier Memory (Active + Archive)
|
|
584
|
+
|
|
585
|
+
Gnosys uses a two-tier architecture so your current work stays fast while safely growing to 100k+ memories:
|
|
586
|
+
|
|
587
|
+
**Active layer** — `.gnosys/<category>/*.md` — fast markdown files for day-to-day work.
|
|
588
|
+
|
|
589
|
+
**Archive layer** — `.gnosys/archive.db` — SQLite database for old or low-confidence memories.
|
|
590
|
+
|
|
591
|
+
The flow is fully automatic and bidirectional:
|
|
592
|
+
1. `gnosys maintain --auto-apply` moves stale memories (>90 days unreinforced + confidence below 0.3) from active → archive
|
|
593
|
+
2. Every search and ask query checks the archive if active results are insufficient
|
|
594
|
+
3. Archived memories that get cited in an answer are automatically restored to active and reinforced
|
|
595
|
+
|
|
596
|
+
You can also force-dearchive with `gnosys dearchive "query"` or the `gnosys_dearchive` MCP tool.
|
|
597
|
+
|
|
598
|
+
Configure thresholds in `gnosys.json`:
|
|
599
|
+
```json
|
|
600
|
+
{
|
|
601
|
+
"archive": {
|
|
602
|
+
"maxActiveDays": 90,
|
|
603
|
+
"minConfidence": 0.3
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### Enterprise Reliability (v1.3.0)
|
|
609
|
+
|
|
610
|
+
Built for long-running agent orchestrators that call Gnosys hundreds of times per session.
|
|
611
|
+
|
|
612
|
+
**Always-on recall** — `gnosys_recall` tool + `gnosys://recall` resource — Sub-50ms automatic context injection. No LLM, no embeddings. Three modes: **aggressive** (default, always injects top 3+), **balanced** (relevance threshold), **conservative** (high relevance only). MCP resource with `priority: 1` for hosts that support automatic resource injection. Returns `<gnosys-recall>` blocks or a `<gnosys: no-strong-recall-needed>` heartbeat marker.
|
|
613
|
+
|
|
614
|
+
```bash
|
|
615
|
+
# CLI — aggressive mode (default)
|
|
616
|
+
gnosys recall "React state management"
|
|
617
|
+
|
|
618
|
+
# Override mode, host-friendly format
|
|
619
|
+
gnosys recall "React state management" --mode balanced --host
|
|
620
|
+
|
|
621
|
+
# MCP tool (called by orchestrator before each turn)
|
|
622
|
+
gnosys_recall { query: "React state management", mode: "aggressive" }
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
Configure in `gnosys.json`:
|
|
626
|
+
```json
|
|
627
|
+
{
|
|
628
|
+
"recall": {
|
|
629
|
+
"mode": "aggressive",
|
|
630
|
+
"minRelevanceScore": 0.65,
|
|
631
|
+
"maxMemoriesPerTurn": 8,
|
|
632
|
+
"alwaysInjectTopN": 3
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
**Concurrency safety** — Write locking with PID tracking prevents corruption when multiple agents write simultaneously. SQLite databases (archive + embeddings) use WAL mode for concurrent reads during writes. Stale lock detection auto-recovers from crashed processes.
|
|
638
|
+
|
|
639
|
+
**Audit trail** — Every memory operation (read, write, recall, ask, maintain, archive, dearchive) is logged to `.gnosys/.config/audit.jsonl` with timestamps, durations, and optional traceIds for correlation with your outer orchestrator.
|
|
640
|
+
|
|
641
|
+
```bash
|
|
642
|
+
gnosys audit --days 7 --operation recall --json
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
**Deterministic dearchive** — When an LLM-synthesized answer cites archived memories, a three-stage fallback ensures they're always restored: path match → title match → all archive results from context. No memory is left behind even if the LLM output is unpredictable.
|
|
646
|
+
|
|
647
|
+
**Performance monitoring** — `gnosys dashboard` now includes enterprise performance benchmarks: recall latency, active search latency, and archive search latency, with warnings if recall exceeds the 50ms target.
|
|
551
648
|
|
|
552
649
|
---
|
|
553
650
|
|
|
@@ -558,31 +655,47 @@ gnosys --help # List all commands
|
|
|
558
655
|
gnosys init # Initialize a new store
|
|
559
656
|
gnosys add "raw input" # Add memory via LLM
|
|
560
657
|
gnosys add-structured ... # Add memory with explicit fields
|
|
658
|
+
gnosys commit-context "..." # Extract memories from conversation
|
|
659
|
+
gnosys bootstrap <dir> # Batch-import existing markdown files
|
|
660
|
+
gnosys import <file> ... # Bulk import CSV/JSON/JSONL data
|
|
561
661
|
gnosys discover "keywords" # Find relevant memories (metadata only)
|
|
562
662
|
gnosys search "query" # Full-text search with snippets
|
|
563
663
|
gnosys hybrid-search "q" # Hybrid keyword + semantic search
|
|
564
664
|
gnosys semantic-search "q" # Semantic similarity search
|
|
565
665
|
gnosys ask "question" # Ask a question, get cited answer
|
|
566
|
-
gnosys reindex # Build/rebuild semantic embeddings
|
|
567
666
|
gnosys read <path> # Read a specific memory
|
|
568
667
|
gnosys list # List all memories
|
|
668
|
+
gnosys lens # Filtered views (category, tag, status, date...)
|
|
569
669
|
gnosys update <path> ... # Update a memory
|
|
570
670
|
gnosys reinforce <id> ... # Signal memory usefulness
|
|
571
671
|
gnosys stale # Find stale memories
|
|
572
|
-
gnosys
|
|
573
|
-
gnosys
|
|
672
|
+
gnosys history <path> # Git-backed version history
|
|
673
|
+
gnosys rollback <path> <hash> # Rollback to a previous commit
|
|
674
|
+
gnosys timeline # Knowledge evolution over time
|
|
675
|
+
gnosys stats # Summary statistics
|
|
676
|
+
gnosys links <path> # Wikilinks and backlinks for a memory
|
|
677
|
+
gnosys graph # Full cross-reference graph
|
|
678
|
+
gnosys tags # List tag registry
|
|
679
|
+
gnosys tags-add # Add a new tag
|
|
680
|
+
gnosys reindex # Build/rebuild semantic embeddings
|
|
681
|
+
gnosys reindex-graph # Build/rebuild wikilink graph
|
|
574
682
|
gnosys maintain # Run vault maintenance (dry run by default)
|
|
575
|
-
gnosys maintain --
|
|
576
|
-
gnosys
|
|
683
|
+
gnosys maintain --auto-apply # Apply all maintenance + archiving automatically
|
|
684
|
+
gnosys dearchive "query" # Force-dearchive memories from archive to active
|
|
577
685
|
gnosys dashboard # Pretty system dashboard
|
|
578
686
|
gnosys dashboard --json # Dashboard as JSON
|
|
579
|
-
gnosys reindex-graph # Build/rebuild wikilink graph
|
|
580
687
|
gnosys config show # Show SOC configuration
|
|
581
688
|
gnosys config set provider <name> # Set default provider
|
|
582
689
|
gnosys config set task <task> <provider> <model> # Route task
|
|
583
690
|
gnosys doctor # Full system health check (all providers)
|
|
584
|
-
gnosys tags # List tag registry
|
|
585
691
|
gnosys stores # Show active stores
|
|
692
|
+
gnosys recall "query" # Always-on recall (aggressive mode by default)
|
|
693
|
+
gnosys recall "q" --mode balanced # Override recall mode
|
|
694
|
+
gnosys recall "q" --host # Output in <gnosys-recall> host format
|
|
695
|
+
gnosys recall "q" --json # Recall as JSON for programmatic use
|
|
696
|
+
gnosys audit # View audit trail (last 7 days)
|
|
697
|
+
gnosys audit --days 30 # View last 30 days of operations
|
|
698
|
+
gnosys audit --operation ask # Filter by operation type
|
|
586
699
|
gnosys serve # Start MCP server (stdio)
|
|
587
700
|
gnosys serve --with-maintenance # MCP server + maintenance every 6h
|
|
588
701
|
```
|
|
@@ -612,8 +725,12 @@ src/
|
|
|
612
725
|
hybridSearch.ts # Hybrid search with RRF fusion
|
|
613
726
|
ask.ts # Freeform Q&A with LLM synthesis + citations
|
|
614
727
|
llm.ts # LLM abstraction — System of Cognition (5 providers)
|
|
615
|
-
maintenance.ts # Auto-maintenance: decay, dedup, consolidation,
|
|
616
|
-
|
|
728
|
+
maintenance.ts # Auto-maintenance: decay, dedup, consolidation, archiving
|
|
729
|
+
archive.ts # Two-tier memory: active ↔ archive (SQLite)
|
|
730
|
+
recall.ts # Ultra-fast recall hook for agent orchestrators
|
|
731
|
+
audit.ts # Structured JSONL audit logging
|
|
732
|
+
lock.ts # File-level write locking + WAL helper
|
|
733
|
+
dashboard.ts # Aggregated system dashboard + performance monitoring
|
|
617
734
|
graph.ts # Persistent wikilink graph (graph.json)
|
|
618
735
|
tags.ts # Tag registry management
|
|
619
736
|
ingest.ts # LLM-powered structuring (with retry logic)
|
|
@@ -636,22 +753,20 @@ src/
|
|
|
636
753
|
|
|
637
754
|
Real numbers from our demo vault (120 memories — 100 USDA foods + 20 NVD CVEs):
|
|
638
755
|
|
|
639
|
-
| Metric |
|
|
640
|
-
|
|
641
|
-
| Import 100 records
|
|
642
|
-
| Cold start (first load) | 0.3s |
|
|
643
|
-
| Keyword search
|
|
644
|
-
| Hybrid search (keyword + semantic) | ~50ms |
|
|
645
|
-
| Reindex 120 embeddings | ~8s (first run
|
|
646
|
-
| Maintenance dry-run (120 memories) | ~2s |
|
|
647
|
-
| Graph reindex (120 memories) | <1s |
|
|
648
|
-
| Storage per memory | ~1 KB `.md` file |
|
|
649
|
-
| Embedding storage | ~0.3 MB
|
|
650
|
-
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
All benchmarks on Apple M-series hardware, Node.js 20+. Import speed depends on mode — `structured` bypasses LLM entirely. LLM-enriched imports depend on provider latency.
|
|
756
|
+
| Metric | Result |
|
|
757
|
+
|--------|--------|
|
|
758
|
+
| Import 100 records (structured) | 0.6s |
|
|
759
|
+
| Cold start (first load) | 0.3s |
|
|
760
|
+
| Keyword search (FTS5) | <10ms |
|
|
761
|
+
| Hybrid search (keyword + semantic) | ~50ms |
|
|
762
|
+
| Reindex 120 embeddings | ~8s (first run downloads ~80 MB model) |
|
|
763
|
+
| Maintenance dry-run (120 memories) | ~2s |
|
|
764
|
+
| Graph reindex (120 memories) | <1s |
|
|
765
|
+
| Storage per memory | ~1 KB `.md` file |
|
|
766
|
+
| Embedding storage (120 memories) | ~0.3 MB |
|
|
767
|
+
| Test suite | 143 tests, 0 errors |
|
|
768
|
+
|
|
769
|
+
All benchmarks on Apple M-series hardware, Node.js 20+. Structured imports bypass LLM entirely. LLM-enriched imports depend on provider latency.
|
|
655
770
|
|
|
656
771
|
---
|
|
657
772
|
|
|
@@ -678,14 +793,6 @@ Gnosys is open source (MIT) and actively developed. Here's how to get involved:
|
|
|
678
793
|
|
|
679
794
|
---
|
|
680
795
|
|
|
681
|
-
## Roadmap
|
|
682
|
-
|
|
683
|
-
See the [6-phase roadmap](https://gnosys.ai/roadmap) for what's next.
|
|
684
|
-
|
|
685
|
-
**Have ideas?** [Join the discussion →](https://github.com/proticom/gnosys-mcp/discussions)
|
|
686
|
-
|
|
687
|
-
---
|
|
688
|
-
|
|
689
796
|
## License
|
|
690
797
|
|
|
691
798
|
MIT — [LICENSE](LICENSE)
|
package/dist/cli.js
CHANGED
|
@@ -1163,7 +1163,7 @@ program
|
|
|
1163
1163
|
}
|
|
1164
1164
|
const embeddings = new GnosysEmbeddings(storePath);
|
|
1165
1165
|
const hybridSearch = new GnosysHybridSearch(search, embeddings, resolver, storePath);
|
|
1166
|
-
const ask = new GnosysAsk(hybridSearch, cliConfig);
|
|
1166
|
+
const ask = new GnosysAsk(hybridSearch, cliConfig, resolver, storePath);
|
|
1167
1167
|
if (!ask.isLLMAvailable) {
|
|
1168
1168
|
console.error("No LLM provider available. Set ANTHROPIC_API_KEY or switch to Ollama: gnosys config set provider ollama");
|
|
1169
1169
|
process.exit(1);
|
|
@@ -1453,10 +1453,53 @@ program
|
|
|
1453
1453
|
console.log("");
|
|
1454
1454
|
console.log(formatMaintenanceReport(report));
|
|
1455
1455
|
});
|
|
1456
|
+
// ─── gnosys dearchive ───────────────────────────────────────────────────
|
|
1457
|
+
program
|
|
1458
|
+
.command("dearchive <query>")
|
|
1459
|
+
.description("Force-dearchive memories matching a query from archive.db back to active")
|
|
1460
|
+
.option("--limit <n>", "Max memories to dearchive", "5")
|
|
1461
|
+
.action(async (query, opts) => {
|
|
1462
|
+
const { GnosysArchive } = await import("./lib/archive.js");
|
|
1463
|
+
const resolver = await getResolver();
|
|
1464
|
+
const stores = resolver.getStores();
|
|
1465
|
+
if (stores.length === 0) {
|
|
1466
|
+
console.error("No Gnosys stores found. Run gnosys init first.");
|
|
1467
|
+
process.exit(1);
|
|
1468
|
+
}
|
|
1469
|
+
const writeTarget = resolver.getWriteTarget();
|
|
1470
|
+
if (!writeTarget) {
|
|
1471
|
+
console.error("No writable store found.");
|
|
1472
|
+
process.exit(1);
|
|
1473
|
+
}
|
|
1474
|
+
const archive = new GnosysArchive(writeTarget.path);
|
|
1475
|
+
if (!archive.isAvailable()) {
|
|
1476
|
+
console.error("Archive not available. Is better-sqlite3 installed?");
|
|
1477
|
+
process.exit(1);
|
|
1478
|
+
}
|
|
1479
|
+
const results = archive.searchArchive(query, parseInt(opts.limit));
|
|
1480
|
+
if (results.length === 0) {
|
|
1481
|
+
console.log(`No archived memories found matching "${query}".`);
|
|
1482
|
+
archive.close();
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
console.log(`Found ${results.length} archived memories matching "${query}":\n`);
|
|
1486
|
+
for (const r of results) {
|
|
1487
|
+
console.log(` • ${r.title} (${r.id})`);
|
|
1488
|
+
}
|
|
1489
|
+
console.log("");
|
|
1490
|
+
// Dearchive all found
|
|
1491
|
+
const ids = results.map((r) => r.id);
|
|
1492
|
+
const restored = await archive.dearchiveBatch(ids, writeTarget.store);
|
|
1493
|
+
archive.close();
|
|
1494
|
+
console.log(`Dearchived ${restored.length} memories back to active:`);
|
|
1495
|
+
for (const rp of restored) {
|
|
1496
|
+
console.log(` → ${rp}`);
|
|
1497
|
+
}
|
|
1498
|
+
});
|
|
1456
1499
|
// ─── gnosys doctor ──────────────────────────────────────────────────────
|
|
1457
1500
|
program
|
|
1458
1501
|
.command("doctor")
|
|
1459
|
-
.description("Check system health: stores, LLM connectivity, embeddings")
|
|
1502
|
+
.description("Check system health: stores, LLM connectivity, embeddings, archive")
|
|
1460
1503
|
.action(async () => {
|
|
1461
1504
|
const resolver = await getResolver();
|
|
1462
1505
|
const stores = resolver.getStores();
|
|
@@ -1474,6 +1517,31 @@ program
|
|
|
1474
1517
|
}
|
|
1475
1518
|
}
|
|
1476
1519
|
console.log("");
|
|
1520
|
+
// Check archive
|
|
1521
|
+
if (stores.length > 0) {
|
|
1522
|
+
console.log("Archive (Two-Tier Memory):");
|
|
1523
|
+
try {
|
|
1524
|
+
const { GnosysArchive } = await import("./lib/archive.js");
|
|
1525
|
+
const archive = new GnosysArchive(stores[0].path);
|
|
1526
|
+
if (archive.isAvailable()) {
|
|
1527
|
+
const stats = archive.getStats();
|
|
1528
|
+
console.log(` Archived memories: ${stats.totalArchived}`);
|
|
1529
|
+
if (stats.totalArchived > 0) {
|
|
1530
|
+
console.log(` Archive DB size: ${stats.dbSizeMB.toFixed(2)} MB`);
|
|
1531
|
+
console.log(` Oldest archived: ${stats.oldestArchived}`);
|
|
1532
|
+
console.log(` Newest archived: ${stats.newestArchived}`);
|
|
1533
|
+
}
|
|
1534
|
+
archive.close();
|
|
1535
|
+
}
|
|
1536
|
+
else {
|
|
1537
|
+
console.log(" Not available (better-sqlite3 not installed)");
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
catch {
|
|
1541
|
+
console.log(" Not initialized");
|
|
1542
|
+
}
|
|
1543
|
+
console.log("");
|
|
1544
|
+
}
|
|
1477
1545
|
// Check config — SOC routing
|
|
1478
1546
|
const cfg = stores.length > 0 ? await loadConfig(stores[0].path) : DEFAULT_CONFIG;
|
|
1479
1547
|
console.log("System of Cognition (SOC):");
|
|
@@ -1616,5 +1684,84 @@ program
|
|
|
1616
1684
|
}
|
|
1617
1685
|
await import("./index.js");
|
|
1618
1686
|
});
|
|
1687
|
+
// ─── gnosys recall ───────────────────────────────────────────────────────
|
|
1688
|
+
program
|
|
1689
|
+
.command("recall <query>")
|
|
1690
|
+
.description("Always-on memory recall — injects most relevant memories as context (sub-50ms, no LLM)")
|
|
1691
|
+
.option("--limit <n>", "Max memories to return (default from config)")
|
|
1692
|
+
.option("--mode <mode>", "Recall mode: aggressive | balanced | conservative (default from config)")
|
|
1693
|
+
.option("--trace-id <id>", "Trace ID for audit correlation")
|
|
1694
|
+
.option("--json", "Output raw JSON instead of formatted text")
|
|
1695
|
+
.option("--host", "Output in host-friendly <gnosys-recall> format (default for MCP)")
|
|
1696
|
+
.action(async (query, opts) => {
|
|
1697
|
+
const resolver = new GnosysResolver();
|
|
1698
|
+
await resolver.resolve();
|
|
1699
|
+
const stores = resolver.getStores();
|
|
1700
|
+
if (stores.length === 0) {
|
|
1701
|
+
console.error("No Gnosys stores found. Run 'gnosys init' first.");
|
|
1702
|
+
process.exit(1);
|
|
1703
|
+
}
|
|
1704
|
+
const { recall, formatRecall, formatRecallCLI } = await import("./lib/recall.js");
|
|
1705
|
+
const { initAudit, closeAudit } = await import("./lib/audit.js");
|
|
1706
|
+
const storePath = stores[0].path;
|
|
1707
|
+
initAudit(storePath);
|
|
1708
|
+
// Load config for recall settings
|
|
1709
|
+
const cfg = await loadConfig(storePath);
|
|
1710
|
+
const recallConfig = {
|
|
1711
|
+
...cfg.recall,
|
|
1712
|
+
...(opts.mode ? { mode: opts.mode } : {}),
|
|
1713
|
+
};
|
|
1714
|
+
// Build search index
|
|
1715
|
+
const search = new GnosysSearch(storePath);
|
|
1716
|
+
await search.addStoreMemories(stores[0].store);
|
|
1717
|
+
const result = await recall(query, {
|
|
1718
|
+
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
1719
|
+
search,
|
|
1720
|
+
resolver,
|
|
1721
|
+
storePath,
|
|
1722
|
+
traceId: opts.traceId,
|
|
1723
|
+
recallConfig,
|
|
1724
|
+
});
|
|
1725
|
+
if (opts.json) {
|
|
1726
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1727
|
+
}
|
|
1728
|
+
else if (opts.host) {
|
|
1729
|
+
console.log(formatRecall(result));
|
|
1730
|
+
}
|
|
1731
|
+
else {
|
|
1732
|
+
console.log(formatRecallCLI(result));
|
|
1733
|
+
}
|
|
1734
|
+
closeAudit();
|
|
1735
|
+
});
|
|
1736
|
+
// ─── gnosys audit ────────────────────────────────────────────────────────
|
|
1737
|
+
program
|
|
1738
|
+
.command("audit")
|
|
1739
|
+
.description("View the structured audit trail of memory operations")
|
|
1740
|
+
.option("--days <n>", "Show entries from the last N days", "7")
|
|
1741
|
+
.option("--operation <op>", "Filter by operation type (read, write, recall, etc.)")
|
|
1742
|
+
.option("--limit <n>", "Max entries to show")
|
|
1743
|
+
.option("--json", "Output raw JSON instead of formatted timeline")
|
|
1744
|
+
.action(async (opts) => {
|
|
1745
|
+
const resolver = new GnosysResolver();
|
|
1746
|
+
await resolver.resolve();
|
|
1747
|
+
const stores = resolver.getStores();
|
|
1748
|
+
if (stores.length === 0) {
|
|
1749
|
+
console.error("No Gnosys stores found. Run 'gnosys init' first.");
|
|
1750
|
+
process.exit(1);
|
|
1751
|
+
}
|
|
1752
|
+
const { readAuditLog, formatAuditTimeline } = await import("./lib/audit.js");
|
|
1753
|
+
const storePath = stores[0].path;
|
|
1754
|
+
const entries = readAuditLog(storePath, {
|
|
1755
|
+
days: parseInt(opts.days, 10),
|
|
1756
|
+
operation: opts.operation,
|
|
1757
|
+
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
1758
|
+
});
|
|
1759
|
+
if (opts.json) {
|
|
1760
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
1761
|
+
}
|
|
1762
|
+
else {
|
|
1763
|
+
console.log(formatAuditTimeline(entries));
|
|
1764
|
+
}
|
|
1765
|
+
});
|
|
1619
1766
|
program.parse();
|
|
1620
1767
|
//# sourceMappingURL=cli.js.map
|