neotoma 0.3.9 → 0.4.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 +149 -317
- package/dist/actions.d.ts +5 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +859 -523
- package/dist/actions.js.map +1 -1
- package/dist/cli/bootstrap.js +0 -0
- package/dist/cli/discovery.d.ts +36 -0
- package/dist/cli/discovery.d.ts.map +1 -0
- package/dist/cli/discovery.js +368 -0
- package/dist/cli/discovery.js.map +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +713 -248
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/transcript_parser.d.ts +39 -0
- package/dist/cli/transcript_parser.d.ts.map +1 -0
- package/dist/cli/transcript_parser.js +395 -0
- package/dist/cli/transcript_parser.js.map +1 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -2
- package/dist/config.js.map +1 -1
- package/dist/reducers/observation_reducer.d.ts.map +1 -1
- package/dist/reducers/observation_reducer.js +9 -2
- package/dist/reducers/observation_reducer.js.map +1 -1
- package/dist/repositories/sqlite/local_db_adapter.d.ts.map +1 -1
- package/dist/repositories/sqlite/local_db_adapter.js +192 -165
- package/dist/repositories/sqlite/local_db_adapter.js.map +1 -1
- package/dist/server.d.ts +20 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +551 -1003
- package/dist/server.js.map +1 -1
- package/dist/services/entity_queries.d.ts +6 -0
- package/dist/services/entity_queries.d.ts.map +1 -1
- package/dist/services/entity_queries.js +200 -68
- package/dist/services/entity_queries.js.map +1 -1
- package/dist/services/entity_resolution.d.ts +13 -1
- package/dist/services/entity_resolution.d.ts.map +1 -1
- package/dist/services/entity_resolution.js +56 -6
- package/dist/services/entity_resolution.js.map +1 -1
- package/dist/services/entity_semantic_search.js +2 -2
- package/dist/services/entity_semantic_search.js.map +1 -1
- package/dist/services/interpretation.d.ts +0 -2
- package/dist/services/interpretation.d.ts.map +1 -1
- package/dist/services/interpretation.js +11 -6
- package/dist/services/interpretation.js.map +1 -1
- package/dist/services/local_entity_embedding.d.ts +4 -1
- package/dist/services/local_entity_embedding.d.ts.map +1 -1
- package/dist/services/local_entity_embedding.js +3 -3
- package/dist/services/local_entity_embedding.js.map +1 -1
- package/dist/services/mcp_oauth.d.ts +12 -2
- package/dist/services/mcp_oauth.d.ts.map +1 -1
- package/dist/services/mcp_oauth.js +50 -10
- package/dist/services/mcp_oauth.js.map +1 -1
- package/dist/services/oauth_key_gate.d.ts +1 -0
- package/dist/services/oauth_key_gate.d.ts.map +1 -1
- package/dist/services/oauth_key_gate.js +16 -0
- package/dist/services/oauth_key_gate.js.map +1 -1
- package/dist/services/observation_source_label.d.ts +19 -0
- package/dist/services/observation_source_label.d.ts.map +1 -0
- package/dist/services/observation_source_label.js +98 -0
- package/dist/services/observation_source_label.js.map +1 -0
- package/dist/services/schema_registry.d.ts +1 -0
- package/dist/services/schema_registry.d.ts.map +1 -1
- package/dist/services/schema_registry.js +18 -0
- package/dist/services/schema_registry.js.map +1 -1
- package/dist/services/snapshot_computation.d.ts.map +1 -1
- package/dist/services/snapshot_computation.js +13 -0
- package/dist/services/snapshot_computation.js.map +1 -1
- package/dist/services/timeline_events.d.ts +23 -6
- package/dist/services/timeline_events.d.ts.map +1 -1
- package/dist/services/timeline_events.js +81 -18
- package/dist/services/timeline_events.js.map +1 -1
- package/dist/shared/action_handlers/entity_handlers.d.ts +8 -0
- package/dist/shared/action_handlers/entity_handlers.d.ts.map +1 -1
- package/dist/shared/action_handlers/entity_handlers.js +194 -9
- package/dist/shared/action_handlers/entity_handlers.js.map +1 -1
- package/dist/shared/action_handlers/entity_identifier_handler.d.ts +19 -0
- package/dist/shared/action_handlers/entity_identifier_handler.d.ts.map +1 -0
- package/dist/shared/action_handlers/entity_identifier_handler.js +82 -0
- package/dist/shared/action_handlers/entity_identifier_handler.js.map +1 -0
- package/dist/shared/action_schemas.d.ts +226 -134
- package/dist/shared/action_schemas.d.ts.map +1 -1
- package/dist/shared/action_schemas.js +80 -24
- package/dist/shared/action_schemas.js.map +1 -1
- package/dist/shared/contract_mappings.d.ts.map +1 -1
- package/dist/shared/contract_mappings.js +0 -20
- package/dist/shared/contract_mappings.js.map +1 -1
- package/dist/shared/openapi_file.d.ts +2 -0
- package/dist/shared/openapi_file.d.ts.map +1 -1
- package/dist/shared/openapi_file.js +12 -0
- package/dist/shared/openapi_file.js.map +1 -1
- package/dist/shared/openapi_types.d.ts +2 -120
- package/dist/shared/openapi_types.d.ts.map +1 -1
- package/openapi.yaml +33 -70
- package/package.json +26 -7
package/README.md
CHANGED
|
@@ -1,327 +1,184 @@
|
|
|
1
|
-
# Neotoma
|
|
1
|
+
# Neotoma
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Your agents forget. Neotoma makes them remember.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Versioned records — contacts, tasks, decisions, finances — that persist across Claude, Cursor, ChatGPT, OpenClaw, and every agent you run. Open-source. Local-first. Deterministic. MIT licensed.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**[neotoma.io](https://neotoma.io)** · **[Evaluate](https://neotoma.io/evaluate)** · **[Install](https://neotoma.io/install)** · **[Documentation](https://neotoma.io/docs)**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Why this exists
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
You run AI agents across tools and sessions. Without a state layer, you become the human sync layer:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- Every session starts from zero — nothing your agent learns carries over
|
|
14
|
+
- Facts conflict across tools — two agents store different versions of the same person
|
|
15
|
+
- Decisions execute without a reproducible trail — you can't trace why your agent acted
|
|
16
|
+
- Corrections don't stick — you fix something in Claude and it's wrong again in Cursor
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
These are not hypothetical. They happen every day in production agent systems. You compensate by re-prompting context, patching state gaps, and maintaining manual workarounds. Neotoma removes that tax.
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
## What Neotoma does
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
Neotoma is a deterministic state layer for AI agents. It stores structured records — contacts, tasks, transactions, decisions, events, contracts — with versioned history and full provenance. Every change creates a new version. Nothing is overwritten. Every state can be replayed from the observation log.
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
Not retrieval memory (RAG, vector search, semantic lookup). Neotoma enforces deterministic state evolution: same observations always produce the same entity state, regardless of when or in what order they are processed.
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
It's not a note-taking app or "second brain." Not provider-controlled ChatGPT Memory or Claude Projects (those are conversation-only and platform-locked; Neotoma is structured personal data memory with entity resolution and timelines, cross-platform via MCP). Not a vector store or RAG layer. Not an autonomous agent. It is the memory layer agents read and write; you control what goes in and what stays.
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Three Foundations
|
|
30
|
-
|
|
31
|
-
Neotoma is built on three architectural choices that provider memory cannot offer:
|
|
32
|
-
|
|
33
|
-
| Foundation | What it means |
|
|
34
|
-
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
35
|
-
| **Privacy-first** | User-controlled memory, end-to-end encryption and row-level security, never used for training. Your data remains yours. |
|
|
36
|
-
| **Deterministic** | Same input always produces same output. Schema-first extraction, hash-based entity IDs, full provenance. No hallucinations or probabilistic behavior. |
|
|
37
|
-
| **Cross-platform** | Works with ChatGPT, Claude, Cursor, and Claude Code via MCP. One memory system across tools; no platform lock-in. Localhost-agent friendly. |
|
|
38
|
-
|
|
39
|
-
**These enable:** Immutable audit trail and time-travel queries, cryptographic integrity, event-sourced history, entity resolution across documents and agent data, timeline generation, dual-path storing (files + agent interactions), and persistent memory without context-window limits.
|
|
40
|
-
|
|
41
|
-
**System architecture:**
|
|
26
|
+
## Architecture
|
|
42
27
|
|
|
43
28
|
```mermaid
|
|
44
29
|
graph LR
|
|
45
|
-
Sources[
|
|
46
|
-
Ingest --> Obs[Observations]
|
|
30
|
+
Sources["Sources (files, messages, APIs)"] --> Obs[Observations]
|
|
47
31
|
Obs --> Entities[Entity Resolution]
|
|
48
|
-
Entities --> Snapshots[Entity Snapshots]
|
|
32
|
+
Entities --> Snapshots["Entity Snapshots (versioned)"]
|
|
49
33
|
Snapshots --> Graph[Memory Graph]
|
|
50
34
|
Graph <--> MCP[MCP Protocol]
|
|
51
|
-
MCP --> ChatGPT
|
|
52
35
|
MCP --> Claude
|
|
36
|
+
MCP --> ChatGPT
|
|
53
37
|
MCP --> Cursor
|
|
38
|
+
MCP --> OpenClaw
|
|
54
39
|
```
|
|
55
40
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
| Problem | How Neotoma addresses it |
|
|
61
|
-
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
62
|
-
| Personal data is fragmented | Dual-path storing from file uploads and agent interactions into one source of truth. |
|
|
63
|
-
| Provider memory is conversation-only | Structured personal data memory with entity resolution and timelines across documents and agent-created data. |
|
|
64
|
-
| No trust when agents act | Explicit, named operations; visible inputs; reconstructable history. Replay and audit trail. |
|
|
65
|
-
| No cross-data reasoning | One graph: sources, entities, events, typed relationships. |
|
|
66
|
-
| Entity fragmentation | Hash-based canonical IDs unify "Acme Corp" across all personal data. |
|
|
67
|
-
| No temporal reasoning | Automatic timeline generation from date fields. |
|
|
68
|
-
| Platform lock-in | MCP-based access; works with any compatible AI tool. |
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## Core Terminology
|
|
73
|
-
|
|
74
|
-
| Term | Definition |
|
|
75
|
-
| --------------- | --------------------------------------------------------------------------------------------- |
|
|
76
|
-
| Truth Layer | Deterministic, immutable structured memory substrate that tools and agents read and write. |
|
|
77
|
-
| Source | Raw data (file, text, URL, or structured JSON) stored with content-addressed deduplication. |
|
|
78
|
-
| Observation | Granular fact extracted from a source; reducers merge observations into entity snapshots. |
|
|
79
|
-
| Entity | Canonical representation of a person, company, task, or other object with a deterministic ID. |
|
|
80
|
-
| Entity snapshot | Current truth for an entity computed from all related observations. |
|
|
81
|
-
| Provenance | Origin tracking (source, timestamp, operation) so each value is traceable. |
|
|
82
|
-
| Memory graph | Graph of sources, observations, entities, events, and typed relationships. |
|
|
83
|
-
|
|
84
|
-
For the full glossary, see [Core terminology](https://neotoma.io/#terminology).
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## Who It's For
|
|
89
|
-
|
|
90
|
-
| Who | What they need | Example data to remember |
|
|
91
|
-
| ------------------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
|
|
92
|
-
| AI-native individual operators | Memory that follows across daily tools and sessions | Tasks, preferences, notes, recurring reminders, contacts, deadlines |
|
|
93
|
-
| Knowledge workers with scattered data | Durable context across documents and sessions, with evidence and lineage | Source documents, extracted entities, citations, key quotes, timelines |
|
|
94
|
-
| Builders of agentic systems | Structured memory agents can read and write with provenance | Session histories, accumulated facts, decisions, runbooks, tool configs |
|
|
95
|
-
|
|
96
|
-
**Why Neotoma:** One memory graph across documents and agent-created data; agents remember context without re-explanation; full provenance and audit trail; works with any MCP-compatible tool; privacy-first and user-controlled. The same substrate serves both human-in-the-loop use and agent frameworks or toolchains that need deterministic memory and provenance.
|
|
97
|
-
|
|
98
|
-
**Suggested GitHub topics:** `ai-agents` `ai-memory` `memory-system` `entity-resolution` `event-sourcing` `truth-layer` `mcp` `provenance` `privacy-first`
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## Security Defaults
|
|
103
|
-
|
|
104
|
-
Neotoma stores personal data and requires secure configuration.
|
|
105
|
-
|
|
106
|
-
**Authentication:** Local auth is the active mode (dev stub or key-based when encryption is enabled). Session tokens are deprecated. See [OAuth implementation](docs/developer/mcp_oauth_implementation.md) for current local flow details.
|
|
107
|
-
|
|
108
|
-
**Authorization:** Local data isolation and explicit operation-level access controls are enforced in local-only mode.
|
|
109
|
-
|
|
110
|
-
**Data protection:** User-controlled data with full export and deletion control; never used for training or provider access. Local backend supports optional encryption at rest (key file or mnemonic). End-to-end encryption planned (v2.0.0).
|
|
111
|
-
|
|
112
|
-
**Verify your setup:** Run `npm run doctor` for environment, database, RLS, and security checks. See [Health check](docs/operations/health_check.md), [Auth](docs/subsystems/auth.md), [Privacy](docs/subsystems/privacy.md), and [Compliance](docs/legal/compliance.md).
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
## Current Status
|
|
117
|
-
|
|
118
|
-
**Version:** v0.3.0
|
|
119
|
-
**Status:** Completed (reconciliation release establishing current baseline)
|
|
120
|
-
|
|
121
|
-
**Developer preview:** Planned during dogfooding once core invariants are stable.
|
|
122
|
-
|
|
123
|
-
**What's implemented:** Sources-first architecture with content-addressed storage, dual-path storing (file uploads + agent interactions), observations architecture, entity resolution with hash-based IDs, schema registry system, auto-enhancement, timeline generation, optional entity semantic search for `retrieve_entities` and `retrieve_entity_by_identifier` (local embeddings), MCP integration (ChatGPT, Claude, Cursor), full provenance and audit trail, React frontend, CLI. See [Release roadmap](#release-roadmap) and [docs/releases/](docs/releases/) for details.
|
|
124
|
-
|
|
125
|
-
**Next steps:** Review current uncommitted changes, apply pending migrations, audit the test suite, and plan v0.4.0 realistically based on the current baseline.
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## Developer preview
|
|
130
|
-
|
|
131
|
-
The developer preview exposes the **core contract only**: CLI for humans, MCP for agents, OpenAPI as the single source of truth. There is no web app in scope for the preview; the frontend in this repo exists for development and future use.
|
|
132
|
-
|
|
133
|
-
### What is guaranteed (even in preview)
|
|
134
|
-
|
|
135
|
-
- **No silent data loss** – Operations either succeed and are recorded or fail with explicit errors.
|
|
136
|
-
- **Explicit, inspectable state mutations** – Every change is a named operation with visible inputs; state is reconstructable from the audit trail.
|
|
137
|
-
- **Auditable operations** – Full provenance; CLI and MCP map to the same underlying contract. If it cannot be expressed via the contract, it is not real.
|
|
138
|
-
- **Same contract for CLI and MCP** – Both use the same OpenAPI-backed operations; MCP tool calls log the equivalent CLI invocation (redaction-aware).
|
|
139
|
-
|
|
140
|
-
### What is not guaranteed yet
|
|
141
|
-
|
|
142
|
-
- Stable schemas
|
|
143
|
-
- Deterministic extraction across versions
|
|
144
|
-
- Long-term replay compatibility
|
|
145
|
-
- Backward compatibility
|
|
146
|
-
|
|
147
|
-
Breaking changes should be expected.
|
|
148
|
-
|
|
149
|
-
### Who this is for
|
|
150
|
-
|
|
151
|
-
- Developers comfortable with CLI-first workflows
|
|
152
|
-
- People building or operating agentic systems
|
|
153
|
-
- Anyone who treats personal data like production infrastructure
|
|
154
|
-
|
|
155
|
-
### Who this is not for (yet)
|
|
156
|
-
|
|
157
|
-
- UI-first users
|
|
158
|
-
- Casual note-taking
|
|
159
|
-
- Anyone expecting reliability guarantees today
|
|
160
|
-
|
|
161
|
-
**Storage:** The developer preview supports **local storage only** (SQLite + local file storage). See [Developer preview storage](docs/developer/developer_preview_storage.md) and [Getting started](docs/developer/getting_started.md) for setup.
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## Release Roadmap
|
|
166
|
-
|
|
167
|
-
### Completed Releases
|
|
168
|
-
|
|
169
|
-
- **v0.2.0** – Minimal ingestion + correction loop (`in_testing`). [docs/releases/v0.2.0/](docs/releases/v0.2.0/)
|
|
170
|
-
- **v0.2.1** – Documentation generation system (`in_progress`). [docs/releases/v0.2.1/](docs/releases/v0.2.1/)
|
|
171
|
-
- **v0.2.2** – `list_capabilities` MCP action (`planning`). [docs/releases/v0.2.2/](docs/releases/v0.2.2/)
|
|
172
|
-
- **v0.2.15** – Complete architecture migration (`implemented`, pending migrations). [docs/releases/v0.2.15/](docs/releases/v0.2.15/)
|
|
173
|
-
- **v0.3.0** – Reconciliation release (`completed`). [docs/releases/v0.3.0/](docs/releases/v0.3.0/)
|
|
41
|
+
- **Deterministic.** Same observations always produce the same versioned entity snapshots. No ordering sensitivity.
|
|
42
|
+
- **Immutable.** Append-only observations. Corrections add new data, never erase.
|
|
43
|
+
- **Replayable.** Inspect any entity at any point in time. Diff versions. Reconstruct history from the observation log.
|
|
44
|
+
- **Structure-first.** Schema-first extraction with deterministic retrieval. Optional similarity search when embeddings are configured.
|
|
174
45
|
|
|
175
|
-
###
|
|
46
|
+
### Three foundations
|
|
176
47
|
|
|
177
|
-
|
|
48
|
+
| Foundation | What it means |
|
|
49
|
+
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| **Privacy-first** | Your data stays local. Never used for training. User-controlled storage, optional encryption at rest. Full export and deletion control. |
|
|
51
|
+
| **Deterministic** | Same input always produces same output. Schema-first extraction, hash-based entity IDs, full provenance. No silent mutation. |
|
|
52
|
+
| **Cross-platform** | One memory graph across Claude, ChatGPT, Cursor, OpenClaw, Codex, and CLI. MCP-based access. No platform lock-in. Works alongside native memory. |
|
|
178
53
|
|
|
179
|
-
|
|
54
|
+
## State guarantees
|
|
180
55
|
|
|
181
|
-
|
|
56
|
+
Most AI memory systems optimize storage or retrieval. Neotoma enforces state integrity. [Full comparison with explanations →](https://neotoma.io/memory-guarantees)
|
|
182
57
|
|
|
183
|
-
|
|
58
|
+
| Property | Platform | Retrieval / RAG | Files | Database | Neotoma |
|
|
59
|
+
| ------------------------------------ | --------- | --------------- | ---------- | ------------- | ------------- |
|
|
60
|
+
| Deterministic state evolution | ✗ | ✗ | ✗ | ✗ | ✓ |
|
|
61
|
+
| Versioned history | ✗ | ✗ | ⚠ manual | ✗ | ✓ |
|
|
62
|
+
| Replayable timeline | ✗ | ✗ | ✗ | ✗ | ✓ |
|
|
63
|
+
| Auditable change log | ✗ | ✗ | ⚠ partial | ✗ | ✓ |
|
|
64
|
+
| Schema constraints | ✗ | ✗ | ✗ | ⚠ partial | ✓ |
|
|
65
|
+
| Silent mutation risk | ⚠ common | ⚠ common | ⚠ common | ⚠ common | prevented |
|
|
66
|
+
| Conflicting facts risk | ⚠ common | ⚠ common | ⚠ possible | ⚠ common | prevented |
|
|
67
|
+
| Reproducible state reconstruction | ✗ | ✗ | ✗ | ✗ | ✓ |
|
|
68
|
+
| Human inspectability (diffs/lineage) | ⚠ partial | ⚠ partial | ⚠ partial | ⚠ partial | ✓ |
|
|
69
|
+
| Zero-setup onboarding | ✓ | ✗ | ✗ | ✗ | ✗ |
|
|
70
|
+
| Semantic similarity search | ✗ | ✓ | ✗ | ✗ | ✓ |
|
|
71
|
+
| Direct human editability | ✗ | ✗ | ✓ | ✗ | ✗ |
|
|
184
72
|
|
|
185
|
-
|
|
73
|
+
**Platform:** Claude, ChatGPT, Gemini, Copilot. **Retrieval:** Mem0, Zep, LangChain Memory. **Files:** Markdown files, JSON stores, CRDT docs. **Database:** SQLite, Postgres, MySQL. **Neotoma:** Deterministic state layer (reference implementation).
|
|
186
74
|
|
|
187
|
-
|
|
75
|
+
## Quick start
|
|
188
76
|
|
|
189
|
-
|
|
77
|
+
### Evaluate first (recommended)
|
|
190
78
|
|
|
191
|
-
|
|
192
|
-
- [Philosophy](docs/foundation/philosophy.md) – Principles and invariants
|
|
193
|
-
- [Problem statement](docs/foundation/problem_statement.md) – Why Neotoma exists
|
|
194
|
-
- [Layered architecture](docs/foundation/layered_architecture.md) – Truth / Strategy / Execution layers
|
|
79
|
+
Ask your AI agent whether Neotoma fits your workflow. Paste this into Claude, Cursor, ChatGPT, or any MCP-capable tool:
|
|
195
80
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
- [Architecture](docs/architecture/architecture.md) – System design
|
|
200
|
-
- [MCP spec](docs/specs/MCP_SPEC.md) – MCP action catalog
|
|
201
|
-
- [Schema](docs/subsystems/schema.md) – Database schema and JSONB structures
|
|
202
|
-
|
|
203
|
-
**Developer:**
|
|
204
|
-
|
|
205
|
-
- [Getting started](docs/developer/getting_started.md) – Setup, local-only storage, first run
|
|
206
|
-
- [Developer preview storage](docs/developer/developer_preview_storage.md) – Local-only stance for the preview
|
|
207
|
-
- [CLI overview](docs/developer/cli_overview.md) – CLI workflows
|
|
208
|
-
- [CLI reference](docs/developer/cli_reference.md) – Commands and scripts
|
|
209
|
-
- [MCP overview](docs/developer/mcp_overview.md) – MCP entry points and setup links
|
|
210
|
-
- [Development workflow](docs/developer/development_workflow.md) – Git, branches, PRs
|
|
211
|
-
- [MCP developer docs](docs/developer/mcp/) – Instructions, tool descriptions, unauthenticated use
|
|
81
|
+
```
|
|
82
|
+
Read https://neotoma.io/evaluate. Before you answer, inspect any broader tool, workspace, and configuration context you can access so you assess my real workflow rather than just this chat. Then tell me whether Neotoma is a real fit for my workflow, what data would be highest value to persist first, and what I should do next.
|
|
83
|
+
```
|
|
212
84
|
|
|
213
|
-
|
|
85
|
+
The agent reads the evaluation page, checks your context, and gives you an honest assessment. If it's a fit, the agent carries you through install and activation.
|
|
214
86
|
|
|
215
|
-
-
|
|
216
|
-
- [Subsystems](docs/subsystems/) – Ingestion, observation architecture, reducer, relationships, auth, events, errors, privacy
|
|
217
|
-
- [Feature units](docs/feature_units/) – Standards, manifests, execution instructions
|
|
218
|
-
- [Testing](docs/testing/) – [Automated test catalog](docs/testing/automated_test_catalog.md), [testing standard](docs/testing/testing_standard.md)
|
|
219
|
-
- [Operations](docs/operations/) – [Runbook](docs/operations/runbook.md) (startup, health, shutdown), [Health check](docs/operations/health_check.md) (`npm run doctor`), [Troubleshooting](docs/operations/troubleshooting.md)
|
|
220
|
-
- [API](docs/api/rest_api.md), [Error codes](docs/reference/error_codes.md), [Vocabulary](docs/vocabulary/canonical_terms.md)
|
|
87
|
+
### Agent-driven install
|
|
221
88
|
|
|
222
|
-
|
|
89
|
+
Agents install Neotoma themselves. Paste this prompt into Claude, Cursor, ChatGPT, or Codex:
|
|
223
90
|
|
|
224
|
-
|
|
91
|
+
```
|
|
92
|
+
Read https://neotoma.io/install and carry me through the install-first Neotoma flow. Install, activate it with my data, and configure my current tool for robust ongoing use.
|
|
93
|
+
```
|
|
225
94
|
|
|
226
|
-
|
|
95
|
+
The agent handles npm install, initialization, and MCP configuration. **Manual install:**
|
|
227
96
|
|
|
228
97
|
```bash
|
|
229
|
-
# Global install (recommended for MCP server use)
|
|
230
98
|
npm install -g neotoma
|
|
231
|
-
|
|
232
|
-
# Initialize (creates data directories, database; init can prompt for encryption)
|
|
233
99
|
neotoma init
|
|
234
|
-
|
|
235
|
-
# Start the API server
|
|
236
|
-
neotoma api start
|
|
100
|
+
neotoma mcp config
|
|
237
101
|
```
|
|
238
102
|
|
|
239
|
-
|
|
103
|
+
More options: [Docker](docs/developer/docker.md) | [CLI reference](docs/developer/cli_reference.md) | [Getting started](docs/developer/getting_started.md)
|
|
240
104
|
|
|
241
|
-
|
|
105
|
+
## Example
|
|
242
106
|
|
|
243
107
|
```bash
|
|
244
|
-
|
|
108
|
+
neotoma store --json='[{"entity_type":"task","title":"Submit expense report","status":"open"}]'
|
|
245
109
|
neotoma entities list --type task
|
|
246
|
-
|
|
247
|
-
# Explicit remote API mode (fail if API is unreachable)
|
|
248
|
-
neotoma --api-only entities list --type task
|
|
110
|
+
neotoma upload ./invoice.pdf
|
|
249
111
|
```
|
|
250
112
|
|
|
251
|
-
|
|
113
|
+
Results reflect versioned entity state with full provenance. Agents perform the same operations through MCP tool calls (`store`, `retrieve_entities`, `retrieve_entity_by_identifier`).
|
|
252
114
|
|
|
253
|
-
|
|
254
|
-
neotoma mcp config
|
|
255
|
-
```
|
|
115
|
+
## Interfaces
|
|
256
116
|
|
|
257
|
-
|
|
117
|
+
Three interfaces. One state invariant. Every interface provides the same deterministic behavior regardless of how you access the state layer.
|
|
258
118
|
|
|
259
|
-
|
|
119
|
+
| Interface | Description |
|
|
120
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
121
|
+
| **REST API** | Full HTTP interface for application integration. Entities, relationships, observations, schema, timeline, and version history. |
|
|
122
|
+
| **MCP Server** | Model Context Protocol for Claude, ChatGPT, Cursor, OpenClaw, Codex, and more. Agents store and retrieve state through structured tool calls. |
|
|
123
|
+
| **CLI** | Command-line for scripting and direct access. Inspect entities, replay timelines, and manage state from the terminal. |
|
|
260
124
|
|
|
261
|
-
|
|
125
|
+
All three map to the same OpenAPI-backed operations. MCP tool calls log the equivalent CLI invocation.
|
|
262
126
|
|
|
263
|
-
|
|
264
|
-
git clone https://github.com/markmhendrickson/neotoma.git
|
|
265
|
-
cd neotoma
|
|
266
|
-
npm install
|
|
267
|
-
npm test
|
|
268
|
-
```
|
|
127
|
+
## Who this is for
|
|
269
128
|
|
|
270
|
-
|
|
129
|
+
People building a personal operating system with AI agents across their life — wiring together tools like Claude, Cursor, ChatGPT, OpenClaw, and custom scripts to manage contacts, tasks, finances, code, content, and other domains. The same person operates their agents, builds new pipelines, and debugs state drift. These are three operational modes, not separate personas:
|
|
271
130
|
|
|
272
|
-
|
|
131
|
+
| Mode | What you're doing | The tax you pay without Neotoma | What you get back |
|
|
132
|
+
| ---- | ----------------- | ------------------------------- | ----------------- |
|
|
133
|
+
| **Operating** | Running AI tools across sessions and contexts | Re-prompting, context re-establishment, manual cross-tool sync | Attention, continuity, trust in your tools |
|
|
134
|
+
| **Building** | Shipping agents and pipelines | Prompt workarounds, dedup hacks, memory regression fixes | Product velocity, shipping confidence |
|
|
135
|
+
| **Debugging** | Tracing state drift and reproducing failures | Writing glue (checkpoint logic, custom diffing, state serialization) | Debugging speed, platform design time |
|
|
273
136
|
|
|
274
|
-
|
|
275
|
-
git clone https://github.com/markmhendrickson/neotoma.git
|
|
276
|
-
cd neotoma
|
|
277
|
-
docker build -t neotoma .
|
|
137
|
+
**Not for:** Casual note-taking. PKM/Obsidian-style users. Thought-partner usage where the human drives every turn. Platform builders who build state management as their core product. Users who need zero-install onboarding (Neotoma requires npm and CLI today).
|
|
278
138
|
|
|
279
|
-
|
|
280
|
-
--name neotoma \
|
|
281
|
-
-p 3080:3080 \
|
|
282
|
-
-v neotoma-data:/app/data \
|
|
283
|
-
neotoma
|
|
139
|
+
## Record types
|
|
284
140
|
|
|
285
|
-
|
|
286
|
-
```
|
|
141
|
+
Neotoma stores typed entities with versioned history and provenance. Each type has a dedicated guide on [neotoma.io](https://neotoma.io):
|
|
287
142
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
```
|
|
143
|
+
| Type | What it stores | Examples |
|
|
144
|
+
| ---- | -------------- | -------- |
|
|
145
|
+
| **[Contacts](https://neotoma.io/types/contacts)** | People, companies, roles, relationships | `contact`, `company`, `account` |
|
|
146
|
+
| **[Tasks](https://neotoma.io/types/tasks)** | Obligations, deadlines, habits, goals | `task`, `habit`, `goal` |
|
|
147
|
+
| **[Transactions](https://neotoma.io/types/transactions)** | Payments, receipts, invoices, ledger entries | `transaction`, `invoice`, `receipt` |
|
|
148
|
+
| **[Contracts](https://neotoma.io/types/contracts)** | Agreements, clauses, amendments | `contract`, `clause`, `amendment` |
|
|
149
|
+
| **[Decisions](https://neotoma.io/types/decisions)** | Choices, rationale, audit trails | `decision`, `assessment`, `review` |
|
|
150
|
+
| **[Events](https://neotoma.io/types/events)** | Meetings, milestones, outcomes | `event`, `meeting`, `milestone` |
|
|
300
151
|
|
|
301
|
-
|
|
152
|
+
Schema is flexible — store any entity type with whatever fields the message implies. The system infers and evolves schemas automatically.
|
|
302
153
|
|
|
303
|
-
|
|
304
|
-
docker exec neotoma neotoma store \
|
|
305
|
-
--json='[{"entity_type":"task","title":"Submit expense report","status":"open"}]'
|
|
154
|
+
## Current status
|
|
306
155
|
|
|
307
|
-
|
|
308
|
-
|
|
156
|
+
**Version:** v0.4.0 · **Releases:** 12 · **License:** MIT
|
|
157
|
+
|
|
158
|
+
### What is guaranteed (even in preview)
|
|
309
159
|
|
|
310
|
-
|
|
160
|
+
- **No silent data loss.** Operations either succeed and are recorded or fail with explicit errors.
|
|
161
|
+
- **Explicit, inspectable state mutations.** Every change is a named operation with visible inputs. State is reconstructable from the audit trail.
|
|
162
|
+
- **Auditable operations.** Full provenance. CLI and MCP map to the same underlying contract.
|
|
163
|
+
- **Same contract for CLI and MCP.** Both use the same OpenAPI-backed operations.
|
|
311
164
|
|
|
312
|
-
|
|
165
|
+
### What is not guaranteed yet
|
|
313
166
|
|
|
314
|
-
|
|
167
|
+
- Stable schemas
|
|
168
|
+
- Deterministic extraction across versions
|
|
169
|
+
- Long-term replay compatibility
|
|
170
|
+
- Backward compatibility
|
|
315
171
|
|
|
316
|
-
|
|
317
|
-
2. In a conversation, tell your assistant: "Remind me to review my subscription Friday."
|
|
318
|
-
3. In the same conversation, ask it to list your open tasks.
|
|
172
|
+
Breaking changes should be expected. **Storage:** Local-only (SQLite + local file storage). See [Developer preview storage](docs/developer/developer_preview_storage.md).
|
|
319
173
|
|
|
320
|
-
|
|
174
|
+
## Security defaults
|
|
321
175
|
|
|
322
|
-
|
|
176
|
+
Neotoma stores user data and requires secure configuration.
|
|
323
177
|
|
|
324
|
-
|
|
178
|
+
- **Authentication:** Local auth (dev stub or key-based when encryption is enabled).
|
|
179
|
+
- **Authorization:** Local data isolation and explicit operation-level access controls.
|
|
180
|
+
- **Data protection:** User-controlled data with full export and deletion control. Never used for training. Optional encryption at rest.
|
|
181
|
+
- **Verify your setup:** Run `npm run doctor` for environment, database, and security checks. See [Auth](docs/subsystems/auth.md), [Privacy](docs/subsystems/privacy.md), [Compliance](docs/legal/compliance.md).
|
|
325
182
|
|
|
326
183
|
## Development
|
|
327
184
|
|
|
@@ -332,100 +189,75 @@ npm run dev # MCP server (stdio)
|
|
|
332
189
|
npm run dev:ui # Frontend
|
|
333
190
|
npm run dev:server # API only (MCP at /mcp)
|
|
334
191
|
npm run dev:full # API + UI + build watch
|
|
335
|
-
npm run dev:ws # WebSocket MCP bridge
|
|
336
|
-
npm run watch:prod:tunnel # Production mode + HTTPS tunnel (local storage, remote access)
|
|
337
192
|
```
|
|
338
193
|
|
|
339
|
-
For `watch:prod:tunnel`, no `.env` is required - server auto-discovers tunnel URL. Tunnel prefers Cloudflare when `cloudflared` is installed; else ngrok. Optional: `NEOTOMA_HOST_URL` (for fixed domain), `NEOTOMA_BEARER_TOKEN`. Full tunnel and env: [Tunnels](docs/developer/tunnels.md), [Getting started – Production with tunnel](docs/developer/getting_started.md#start-development-server).
|
|
340
|
-
|
|
341
194
|
**CLI:**
|
|
342
195
|
|
|
343
196
|
```bash
|
|
344
197
|
npm run cli # Run via npm (no global install)
|
|
345
198
|
npm run cli:dev # Dev mode (tsx; picks up source changes)
|
|
346
199
|
npm run setup:cli # Build and link so `neotoma` is available globally
|
|
347
|
-
# Or manually: npm run build:server && npm install -g . (or npm link)
|
|
348
200
|
```
|
|
349
201
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
Interactive `neotoma` startup is connect-only. It discovers healthy local API instances, applies `--env` as a preference, and prompts when multiple instances are available.
|
|
353
|
-
|
|
354
|
-
**Testing:** `npm test` | `npm run test:integration` | `npm run test:e2e` | `npm run test:agent-mcp` | `npm run type-check` | `npm run lint`
|
|
355
|
-
|
|
356
|
-
**IDE instructions:** Neotoma supports both Cursor and Claude Code with project-specific instructions. Instructions in `.cursor/` and `.claude/` are generated from sources in `foundation/` and `docs/`. To sync: `npm run setup:cursor` | `npm run setup:claude` (auto-syncs on commit).
|
|
357
|
-
|
|
358
|
-
See [Getting started](docs/developer/getting_started.md) for full setup and storage options.
|
|
359
|
-
|
|
360
|
-
---
|
|
361
|
-
|
|
362
|
-
## Using with AI Tools (MCP)
|
|
363
|
-
|
|
364
|
-
Neotoma exposes memory via MCP. **Developer preview:** Local storage only; local auth. **Auth:** local built-in auth with OAuth-style flow support where applicable. Dev stub: `neotoma auth login --dev-stub`.
|
|
202
|
+
**Testing:** `npm test` | `npm run test:integration` | `npm run test:e2e` | `npm run test:agent-mcp` | `npm run type-check` | `npm run lint` · **Source checkout:**
|
|
365
203
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
**Representative actions:** `store`, `reinterpret`, `correct`, `retrieve_entities`, `retrieve_entity_snapshot`, `merge_entities`, `list_observations`, `create_relationship`, `list_relationships`, `list_timeline_events`, `retrieve_graph_neighborhood`, `retrieve_file_url`, schema tools (`analyze_schema_candidates`, `get_schema_recommendations`, `update_schema_incremental`, `register_schema`). Full list: [MCP spec](docs/specs/MCP_SPEC.md).
|
|
374
|
-
|
|
375
|
-
To use the Neotoma MCP server from another workspace, see [Cursor MCP setup](docs/developer/mcp_cursor_setup.md).
|
|
204
|
+
```bash
|
|
205
|
+
git clone https://github.com/markmhendrickson/neotoma.git
|
|
206
|
+
cd neotoma
|
|
207
|
+
npm install
|
|
208
|
+
npm test
|
|
209
|
+
```
|
|
376
210
|
|
|
377
|
-
|
|
211
|
+
**Prerequisites:** Node.js v18.x or v20.x (LTS), npm v9+. No `.env` required for local storage. See [Getting started](docs/developer/getting_started.md).
|
|
378
212
|
|
|
379
|
-
##
|
|
213
|
+
## Using with AI tools (MCP)
|
|
380
214
|
|
|
381
|
-
Neotoma
|
|
215
|
+
Neotoma exposes state via MCP. Local storage only in preview. Local built-in auth.
|
|
382
216
|
|
|
383
|
-
|
|
384
|
-
- **Bounded retrieval:** Retrieve likely related entities before storing new ones.
|
|
385
|
-
- **Entity extraction:** Extract and store relevant people, tasks, events, places, and relationships from user input.
|
|
386
|
-
- **Task creation:** Create tasks when users express intent, obligations, deadlines, or reminders.
|
|
387
|
-
- **External data safety:** Store relevant entities from external tool results before responding.
|
|
217
|
+
**Setup guides:** [Cursor](https://neotoma.io/neotoma-with-cursor) · [Claude Code](https://neotoma.io/neotoma-with-claude-code) · [Claude](https://neotoma.io/neotoma-with-claude) · [ChatGPT](https://neotoma.io/neotoma-with-chatgpt) · [Codex](https://neotoma.io/neotoma-with-codex) · [OpenClaw](https://neotoma.io/neotoma-with-openclaw)
|
|
388
218
|
|
|
389
|
-
Full instructions: [MCP instructions](docs/developer/mcp/instructions.md) and [CLI agent instructions](docs/developer/cli_agent_instructions.md).
|
|
219
|
+
**Agent behavior contract:** Store first, retrieve before storing, extract entities from user input, create tasks for commitments. Full instructions: [MCP instructions](docs/developer/mcp/instructions.md) and [CLI agent instructions](docs/developer/cli_agent_instructions.md).
|
|
390
220
|
|
|
391
|
-
|
|
221
|
+
**Representative actions:** `store`, `retrieve_entities`, `retrieve_entity_snapshot`, `merge_entities`, `list_observations`, `create_relationship`, `list_relationships`, `list_timeline_events`, `retrieve_graph_neighborhood`. Full list: [MCP spec](docs/specs/MCP_SPEC.md).
|
|
392
222
|
|
|
393
|
-
##
|
|
223
|
+
## Common questions
|
|
394
224
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
3. **Explainable** – Every field traces to source (document or agent interaction).
|
|
398
|
-
4. **Entity-unified** – Canonical IDs across all personal data.
|
|
399
|
-
5. **Timeline-aware** – Chronological ordering from date fields.
|
|
400
|
-
6. **Cross-platform** – MCP for any compatible AI tool.
|
|
401
|
-
7. **Privacy-first** – User-controlled memory, encryption, RLS.
|
|
402
|
-
8. **Immutable** – Truth does not change after storage; corrections create new observations.
|
|
403
|
-
9. **Provenance** – Full audit trail; event-sourced, replayable history.
|
|
404
|
-
10. **Explicit control** – Ingestion only of what you explicitly provide; no background scanning.
|
|
405
|
-
11. **Four-layer model** – Source → Observation → Entity → Entity Snapshot.
|
|
225
|
+
**Platform memory (Claude, ChatGPT) is good enough — why add another tool?**
|
|
226
|
+
Platform memory stores what one vendor decides to remember, in a format you can't inspect or export. It doesn't version, doesn't detect conflicts, and vanishes if you switch tools. Neotoma gives you structured, cross-tool state you control.
|
|
406
227
|
|
|
407
|
-
|
|
228
|
+
**Can't I just build this with SQLite or a JSON file?**
|
|
229
|
+
You can start there — many teams do. But you'll eventually need versioning, conflict detection, schema evolution, and cross-tool sync. That's months of infrastructure work. Neotoma ships those guarantees on day one.
|
|
408
230
|
|
|
409
|
-
|
|
231
|
+
**What's the difference between RAG memory and deterministic memory?**
|
|
232
|
+
RAG stores text chunks and retrieves them by similarity. Neotoma stores structured observations and composes entity state with reducers; the same observations always yield the same snapshot. RAG optimizes relevance; deterministic memory optimizes integrity, versioning, and auditability.
|
|
410
233
|
|
|
411
|
-
|
|
412
|
-
|
|
234
|
+
**Is this production-ready?**
|
|
235
|
+
Neotoma is in developer preview — used daily by real agent workflows. The core guarantees (deterministic state, versioned history, append-only log) are stable. Install in 5 minutes and let your agent evaluate the fit.
|
|
413
236
|
|
|
414
|
-
|
|
237
|
+
More questions: [FAQ](https://neotoma.io/faq)
|
|
415
238
|
|
|
416
239
|
## Related posts
|
|
417
240
|
|
|
418
241
|
- [Neotoma developer release](https://markmhendrickson.com/posts/neotoma-developer-release)
|
|
242
|
+
- [Your AI remembers your vibe but not your work](https://markmhendrickson.com/posts/your-ai-remembers-your-vibe-but-not-your-work)
|
|
419
243
|
- [Building a truth layer for persistent agent memory](https://markmhendrickson.com/posts/truth-layer-agent-memory)
|
|
420
244
|
- [Agent memory has a truth problem](https://markmhendrickson.com/posts/agent-memory-truth-problem)
|
|
245
|
+
- [Six agentic trends I'm betting on (and how I might be wrong)](https://markmhendrickson.com/posts/six-agentic-trends-betting-on)
|
|
421
246
|
- [Why agent memory needs more than RAG](https://markmhendrickson.com/posts/why-agent-memory-needs-more-than-rag)
|
|
247
|
+
- [Agent command centers need one source of truth](https://markmhendrickson.com/posts/agent-command-centers-source-of-truth)
|
|
422
248
|
|
|
423
|
-
|
|
249
|
+
## Documentation
|
|
424
250
|
|
|
425
|
-
|
|
251
|
+
Full documentation is organized at [neotoma.io/docs](https://neotoma.io/docs) and in the `docs/` directory.
|
|
252
|
+
|
|
253
|
+
**Getting started:** [Evaluate](https://neotoma.io/evaluate), [Install](https://neotoma.io/install), [Walkthrough](https://neotoma.io/developer-walkthrough)
|
|
426
254
|
|
|
427
|
-
|
|
255
|
+
**Reference:** [REST API](https://neotoma.io/api), [MCP server](https://neotoma.io/mcp), [CLI](https://neotoma.io/cli), [Memory guarantees](https://neotoma.io/memory-guarantees), [Architecture](https://neotoma.io/architecture), [Terminology](https://neotoma.io/terminology)
|
|
428
256
|
|
|
429
|
-
|
|
257
|
+
**Foundational:** [Core identity](docs/foundation/core_identity.md), [Philosophy](docs/foundation/philosophy.md), [Problem statement](docs/foundation/problem_statement.md)
|
|
258
|
+
|
|
259
|
+
**Operations:** [Runbook](docs/operations/runbook.md), [Health check](docs/operations/health_check.md) (`npm run doctor`), [Troubleshooting](https://neotoma.io/troubleshooting)
|
|
260
|
+
|
|
261
|
+
## Contributing
|
|
430
262
|
|
|
431
|
-
MIT
|
|
263
|
+
Neotoma is in active development. For questions or collaboration, open an issue or discussion. See [CONTRIBUTING.md](CONTRIBUTING.md) and [SECURITY.md](SECURITY.md). **License:** MIT
|
package/dist/actions.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import express from "express";
|
|
2
|
+
export declare const app: any;
|
|
3
|
+
/** True when request is to localhost/127.0.0.1 (local access). Tunnel requests have a non-local Host. */
|
|
4
|
+
export declare function isLocalRequest(req: express.Request): boolean;
|
|
2
5
|
export declare function startHTTPServer(): Promise<{
|
|
3
|
-
server:
|
|
6
|
+
server: any;
|
|
4
7
|
port: number;
|
|
5
8
|
} | undefined>;
|
|
6
9
|
//# sourceMappingURL=actions.d.ts.map
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AA8E9B,eAAO,MAAM,GAAG,KAAY,CAAC;AAwL7B,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAK5D;AAk5ID,wBAAsB,eAAe;;;eAgCpC"}
|