opencode-metis 0.1.5 → 0.1.6

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
@@ -1,20 +1,28 @@
1
1
  # opencode-metis
2
2
 
3
- Persistent memory system for [OpenCode](https://opencode.ai) sessions. Captures observations, enables semantic search, and preserves context across compaction.
3
+ Persistent memory system for [OpenCode](https://opencode.ai) sessions. Captures observations, compresses them with AI, enables semantic search, and preserves context across compaction.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Observation capture** — Automatically records tool executions, decisions, and session summaries
8
- - **Semantic search** — Find relevant memories by meaning, not just keywords
7
+ - **AI-compressed observations** — Tool outputs are distilled into structured knowledge by Gemini, OpenRouter, or Anthropic
8
+ - **Semantic search** — Find relevant memories by meaning via ChromaDB vector embeddings, not just keywords
9
+ - **Context injection** — Relevant past observations are automatically injected at session start
9
10
  - **Compaction survival** — Saves and restores context when OpenCode compacts messages
11
+ - **Privacy protection** — `<private>` tag stripping and automatic secret detection (API keys, tokens, PEM keys) before storage
12
+ - **Crash recovery** — Pending message queue with at-least-once delivery ensures no observations are lost
10
13
  - **Quality checks** — TDD enforcement and file-length warnings on every edit
11
14
  - **Tool redirection** — Block or redirect specific tools via configuration
12
- - **Local-only** — All data stays on your machine at `~/.config/opencode/memory/`
15
+ - **Local-only** — All data stays on your machine at `~/.config/opencode/memory/`; only AI compression calls leave the machine
13
16
 
14
17
  ## Prerequisites
15
18
 
16
- - **Bun** >= 1.0.0
17
- - **ChromaDB** (optional) — for semantic vector search. Install via `pip install chromadb` or Docker.
19
+ | Tool | Version | Required | Purpose |
20
+ |------|---------|----------|---------|
21
+ | [Bun](https://bun.sh) | >= 1.0.0 | Yes | Runtime for the worker daemon, plugin, and build system |
22
+ | [uv](https://github.com/astral-sh/uv) | latest | No | Runs `chroma-mcp` for semantic vector search (installed automatically by `init`) |
23
+ | API key | — | No | One of `GEMINI_API_KEY`, `OPENROUTER_API_KEY`, or `ANTHROPIC_API_KEY` for AI observation compression |
24
+
25
+ ChromaDB is managed automatically via `chroma-mcp` (a Model Context Protocol server launched with `uvx`). If `uv` is not installed, the system falls back to SQLite FTS5 keyword search — no semantic search, but everything else works.
18
26
 
19
27
  ## Installation
20
28
 
@@ -32,67 +40,144 @@ Persistent memory system for [OpenCode](https://opencode.ai) sessions. Captures
32
40
 
33
41
  This merges the required `plugin` and `mcp` entries into `~/.config/opencode/opencode.json`, copies framework files (agents, commands, skills) into `~/.config/opencode/`, and checks for ChromaDB availability. Existing config is backed up before modification.
34
42
 
43
+ 3. (Optional) Set an AI provider for observation compression:
44
+
45
+ ```bash
46
+ # Pick one:
47
+ export GEMINI_API_KEY="your-key"
48
+ export OPENROUTER_API_KEY="your-key"
49
+ export ANTHROPIC_API_KEY="your-key"
50
+ ```
51
+
52
+ Without an API key, observations are stored with basic string truncation instead of AI compression.
53
+
35
54
  ## CLI
36
55
 
37
- | Command | Description |
38
- | -------------------------- | ------------------------------------------------------------------ |
39
- | `opencode-metis init` | Configure `opencode.json` and copy framework files |
40
- | `opencode-metis start` | Start the memory worker and launch opencode |
41
- | `opencode-metis stop` | Stop the memory worker |
56
+ | Command | Description |
57
+ |---------|-------------|
58
+ | `opencode-metis init` | Configure `opencode.json` and copy framework files |
59
+ | `opencode-metis start` | Start the memory worker and launch opencode |
60
+ | `opencode-metis stop` | Stop the memory worker |
42
61
  | `opencode-metis start-mcp` | Start the MCP server (used by opencode via `opencode.json` config) |
43
62
 
44
63
  ## Configuration
45
64
 
46
65
  The memory system has its own optional config file at `~/.config/opencode/memory/settings.json` (separate from OpenCode's config). All fields have sensible defaults:
47
66
 
48
- | Key | Type | Default | Description |
49
- | -------------------- | -------- | ------------------------------------------------------ | ---------------------------------------- |
50
- | `workerPort` | number | `41777` | HTTP port for the worker daemon |
51
- | `workerBind` | string | `"127.0.0.1"` | Bind address for the worker |
52
- | `chromaDbUrl` | string | `"http://localhost:8000"` | ChromaDB server URL |
53
- | `recencyWindowDays` | number | `90` | Days to boost recent results |
54
- | `retentionDays` | number | `365` | Days before observations expire |
55
- | `tddEnabled` | boolean | `true` | Enforce test-file checks on edit |
56
- | `fileLengthWarn` | number | `300` | Line count warning threshold |
57
- | `fileLengthCritical` | number | `500` | Line count critical threshold |
58
- | `testFilePatterns` | string[] | `["*.test.ts", "*.spec.ts", "*_test.go", "test_*.py"]` | Glob patterns for test files |
59
- | `toolRedirectRules` | array | `[]` | Rules to deny or redirect specific tools |
67
+ ### Worker
68
+
69
+ | Key | Type | Default | Description |
70
+ |-----|------|---------|-------------|
71
+ | `workerPort` | number | `41777` | HTTP port for the worker daemon |
72
+ | `workerBind` | string | `"127.0.0.1"` | Bind address for the worker |
73
+
74
+ ### Storage
75
+
76
+ | Key | Type | Default | Description |
77
+ |-----|------|---------|-------------|
78
+ | `chromaDbUrl` | string | `"http://localhost:8000"` | ChromaDB server URL |
79
+ | `chromaDbEnabled` | boolean | `true` | Enable ChromaDB vector store |
80
+
81
+ ### AI Compression
82
+
83
+ | Key | Type | Default | Description |
84
+ |-----|------|---------|-------------|
85
+ | `aiProvider` | string \| null | `null` | AI provider: `"gemini"`, `"openrouter"`, `"anthropic"`, or `null` (auto-detect from env) |
86
+ | `aiModel` | string \| null | `null` | Override the default model for the selected provider |
87
+ | `aiCompressionTimeoutMs` | number | `15000` | Timeout per AI compression call |
88
+ | `aiCompressionMaxRetries` | number | `3` | Max retries for failed compressions |
89
+ | `aiSkipTools` | string[] | `[]` | Tool names to skip during observation capture |
90
+
91
+ ### Privacy
92
+
93
+ | Key | Type | Default | Description |
94
+ |-----|------|---------|-------------|
95
+ | `secretDetectionEnabled` | boolean | `true` | Detect and redact secrets before storage |
96
+ | `secretPatterns` | array | `[]` | Additional custom secret patterns `{ name, pattern }` |
97
+
98
+ ### Retention & Context
99
+
100
+ | Key | Type | Default | Description |
101
+ |-----|------|---------|-------------|
102
+ | `recencyWindowDays` | number | `90` | Days to boost recent results |
103
+ | `retentionDays` | number | `365` | Days before observations expire |
104
+ | `contextTokenBudget` | number | `2000` | Max tokens for context injection at session start |
105
+
106
+ ### Quality Checks
107
+
108
+ | Key | Type | Default | Description |
109
+ |-----|------|---------|-------------|
110
+ | `tddEnabled` | boolean | `true` | Enforce test-file checks on edit |
111
+ | `fileLengthWarn` | number | `300` | Line count warning threshold |
112
+ | `fileLengthCritical` | number | `500` | Line count critical threshold |
113
+ | `testFilePatterns` | string[] | `["*.test.ts", "*.spec.ts", "*_test.go", "test_*.py"]` | Glob patterns for test files |
114
+ | `toolRedirectRules` | array | `[]` | Rules to deny or redirect specific tools |
115
+
116
+ ### Notifications
117
+
118
+ | Key | Type | Default | Description |
119
+ |-----|------|---------|-------------|
120
+ | `notificationsEnabled` | boolean | `false` | Enable macOS desktop notifications for session events |
60
121
 
61
122
  ## Architecture
62
123
 
63
124
  The system has four components, each built as a separate bundle under `dist/`:
64
125
 
65
126
  - **CLI** (`dist/cli.cjs`) — Orchestrates init, start, and stop commands
66
- - **Plugin** (`dist/plugin.cjs`) — Hooks into OpenCode's lifecycle events to capture observations and enforce quality checks
67
- - **Worker** (`dist/worker.cjs`) — HTTP daemon that stores observations in SQLite, manages ChromaDB embeddings, and serves search queries
127
+ - **Plugin** (`dist/plugin.cjs`) — Hooks into OpenCode's lifecycle events to capture observations, enforce quality checks, and inject context
128
+ - **Worker** (`dist/worker.cjs`) — Bun HTTP daemon with bearer token auth that stores observations in SQLite (WAL mode), manages ChromaDB via chroma-mcp, runs AI compression, and serves search queries
68
129
  - **MCP Server** (`dist/mcp-server.cjs`) — Exposes memory tools to the AI via the Model Context Protocol
69
130
 
131
+ ### Data Flow
132
+
133
+ ```
134
+ OpenCode Session
135
+
136
+ ├─ session.created ──────► Worker /api/context/inject ──► SQLite + ChromaDB query ──► context injected
137
+
138
+ ├─ tool.execute.after ───► Worker /api/memory/save ────► privacy strip ──► SQLite write
139
+ │ │
140
+ │ └──► AI compression queue ──► Gemini/OpenRouter/Anthropic
141
+ │ │
142
+ │ └──► update observation with structured data
143
+
144
+ ├─ session.idle ─────────► Worker /api/memory/save ────► session summary stored
145
+
146
+ └─ session.compacted ───► Worker /api/context/inject ──► context restored after compaction
147
+ ```
148
+
149
+ ### Security
150
+
151
+ - **Bearer token auth** — A cryptographically random token is generated per worker instance and stored in the PID file. All non-health endpoints require `Authorization: Bearer <token>`.
152
+ - **Privacy stripping** — `<private>` tags are removed at the hook layer before data leaves the plugin process. Secrets (AWS keys, GitHub tokens, API keys, PEM keys, JWTs) are detected via regex and redacted with `[REDACTED]`.
153
+ - **Localhost binding** — The worker binds to `127.0.0.1` by default.
154
+
70
155
  ## MCP Tools
71
156
 
72
157
  Tools available to the AI through the MCP server:
73
158
 
74
- | Tool | Description |
75
- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
76
- | `search` | Semantic or keyword search across observations. Accepts `query`, optional `limit`, `type`, and `project` filters. |
77
- | `timeline` | Chronological context around an observation. Accepts `anchor` (ID, session ID, timestamp, or query) with `depth_before`/`depth_after`. |
78
- | `get_observations` | Fetch full details for specific observation IDs. |
79
- | `save_memory` | Save a new observation with `text`, optional `title` and `project`. |
80
- | `decisions` | Search decision-type observations. Optional `query` and `project` filters. |
81
- | `changes` | Get recent change-type observations. Optional `project` and `limit`. |
159
+ | Tool | Description |
160
+ |------|-------------|
161
+ | `search` | Semantic or keyword search across observations. Accepts `query`, optional `limit`, `type`, and `project` filters. |
162
+ | `timeline` | Chronological context around an observation. Accepts `anchor` (ID, session ID, timestamp, or query) with `depth_before`/`depth_after`. |
163
+ | `get_observations` | Fetch full details for specific observation IDs. |
164
+ | `save_memory` | Save a new observation with `text`, optional `title` and `project`. |
165
+ | `decisions` | Search decision-type observations. Optional `query` and `project` filters. |
166
+ | `changes` | Get recent change-type observations. Optional `project` and `limit`. |
82
167
 
83
168
  The plugin also registers `memory_search` and `memory_save` as custom tools directly in OpenCode.
84
169
 
85
170
  ## Plugin Hooks
86
171
 
87
- | Hook | Purpose |
88
- | --------------------------------- | ------------------------------------------------------------- |
89
- | `session.created` | Injects relevant memory context at session start |
90
- | `tool.execute.before` | Enforces tool redirect rules (deny/redirect) before execution |
91
- | `tool.execute.after` | Captures tool executions as observations |
92
- | `session.idle` | Saves session summaries when the session goes idle |
93
- | `experimental.session.compacting` | Saves active plan and task state before compaction |
94
- | `session.compacted` | Restores memory context after compaction |
95
- | `file.edited` | Checks for missing test files and warns on file length |
172
+ | Hook | Purpose |
173
+ |------|---------|
174
+ | `session.created` | Injects relevant memory context at session start |
175
+ | `tool.execute.before` | Enforces tool redirect rules (deny/redirect) before execution |
176
+ | `tool.execute.after` | Captures tool executions as observations (with AI compression) |
177
+ | `session.idle` | Saves session summaries when the session goes idle |
178
+ | `experimental.session.compacting` | Saves active plan and task state before compaction |
179
+ | `session.compacted` | Restores memory context after compaction |
180
+ | `file.edited` | Checks for missing test files and warns on file length |
96
181
 
97
182
  ## Local Development
98
183
 
@@ -132,11 +217,31 @@ bun run unlink # unstow
132
217
  ```bash
133
218
  bun test # Run tests
134
219
  bun run build # Build all four bundles
135
- bun run lint # ESLint + Prettier
220
+ bun run lint # Lint and format with Biome
136
221
  bun run typecheck # TypeScript type checking
137
222
  bun run dev # Watch mode for worker
138
223
  ```
139
224
 
225
+ ### Project Structure
226
+
227
+ ```
228
+ src/
229
+ cli/ CLI commands (init, start, stop, start-mcp) and worker lifecycle
230
+ mcp/ MCP server and worker proxy
231
+ plugin/ OpenCode plugin hooks, privacy filters, and custom tools
232
+ hooks/ Hook handlers (session-start, tool-after, session-idle, etc.)
233
+ privacy/ Secret detection, <private> tag stripping, privacy filter
234
+ tools/ Custom MCP tools registered in OpenCode
235
+ services/ Business logic layer
236
+ ai-compression/ Multi-provider AI agents (Gemini, OpenRouter, Anthropic), queue processor
237
+ shared/ Configuration, types, constants
238
+ storage/
239
+ sqlite/ Database, migrations, FTS5 indexing
240
+ vector/ ChromaDB connection, chroma-mcp manager, vector sync
241
+ worker/ HTTP server, router, routes, SSE broadcaster, auth middleware
242
+ test/ Integration and E2E tests
243
+ ```
244
+
140
245
  ## License
141
246
 
142
247
  MIT