open-mem 0.2.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/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +309 -0
- package/dist/ai/compressor.d.ts +43 -0
- package/dist/ai/compressor.d.ts.map +1 -0
- package/dist/ai/parser.d.ts +35 -0
- package/dist/ai/parser.d.ts.map +1 -0
- package/dist/ai/prompts.d.ts +15 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/summarizer.d.ts +30 -0
- package/dist/ai/summarizer.d.ts.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/context/builder.d.ts +11 -0
- package/dist/context/builder.d.ts.map +1 -0
- package/dist/context/progressive.d.ts +13 -0
- package/dist/context/progressive.d.ts.map +1 -0
- package/dist/db/database.d.ts +45 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/observations.d.ts +17 -0
- package/dist/db/observations.d.ts.map +1 -0
- package/dist/db/pending.d.ts +20 -0
- package/dist/db/pending.d.ts.map +1 -0
- package/dist/db/schema.d.ts +13 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/sessions.d.ts +17 -0
- package/dist/db/sessions.d.ts.map +1 -0
- package/dist/db/summaries.d.ts +12 -0
- package/dist/db/summaries.d.ts.map +1 -0
- package/dist/hooks/compaction.d.ts +19 -0
- package/dist/hooks/compaction.d.ts.map +1 -0
- package/dist/hooks/context-inject.d.ts +19 -0
- package/dist/hooks/context-inject.d.ts.map +1 -0
- package/dist/hooks/session-events.d.ts +18 -0
- package/dist/hooks/session-events.d.ts.map +1 -0
- package/dist/hooks/tool-capture.d.ts +25 -0
- package/dist/hooks/tool-capture.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +361 -0
- package/dist/queue/processor.d.ts +52 -0
- package/dist/queue/processor.d.ts.map +1 -0
- package/dist/tools/recall.d.ts +4 -0
- package/dist/tools/recall.d.ts.map +1 -0
- package/dist/tools/save.d.ts +5 -0
- package/dist/tools/save.d.ts.map +1 -0
- package/dist/tools/search.d.ts +5 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/timeline.d.ts +6 -0
- package/dist/tools/timeline.d.ts.map +1 -0
- package/dist/types.d.ts +177 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +60 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-02-06
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `mem-recall` tool for fetching full observation details by ID
|
|
12
|
+
- Progressive disclosure context injection with type icons, token costs, and file grouping
|
|
13
|
+
- `<private>` tag support for user-controlled content exclusion from memory
|
|
14
|
+
- Structured session summaries with request, investigated, learned, completed, and next steps fields
|
|
15
|
+
- Concept vocabulary guidance in AI compression prompts (how-it-works, gotcha, pattern, trade-off, etc.)
|
|
16
|
+
- Context injection configuration options (token cost display, observation type filters, full observation count)
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- README `OPEN_MEM_CONTEXT_INJECTION` default incorrectly documented as `false` (actual default: `true`)
|
|
20
|
+
- Missing `.open-mem/` in project .gitignore
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- License changed from AGPL-3.0 to MIT
|
|
24
|
+
|
|
25
|
+
## [0.1.0] - 2026-01-15
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- Initial release
|
|
29
|
+
- Automatic observation capture from tool executions
|
|
30
|
+
- AI-powered compression using Claude (optional — works without API key)
|
|
31
|
+
- SQLite + FTS5 full-text search for fast retrieval
|
|
32
|
+
- Context injection into new sessions via system prompt
|
|
33
|
+
- Three custom tools: `mem-search`, `mem-save`, `mem-timeline`
|
|
34
|
+
- Session summaries with AI-generated narratives
|
|
35
|
+
- Progressive disclosure with token budget management
|
|
36
|
+
- Configurable sensitive content redaction
|
|
37
|
+
- Data retention policies (default: 90 days)
|
|
38
|
+
- 162 tests with 395 assertions
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cristobal Callejon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# open-mem
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.npmjs.com/package/open-mem)
|
|
5
|
+
[](https://bun.sh)
|
|
6
|
+
|
|
7
|
+
Persistent memory for [OpenCode](https://opencode.ai) — captures, compresses, and recalls context across coding sessions.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- [OpenCode](https://opencode.ai) (the AI coding assistant)
|
|
12
|
+
- [Bun](https://bun.sh) >= 1.0
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
bun add open-mem
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Configure OpenCode
|
|
23
|
+
|
|
24
|
+
Add `open-mem` to the `plugin` array in your OpenCode config (`~/.config/opencode/opencode.json`):
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"plugin": ["open-mem"]
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
> **Note**: If you already have plugins, just append `"open-mem"` to the existing array.
|
|
33
|
+
|
|
34
|
+
That's it. open-mem starts capturing from your next OpenCode session.
|
|
35
|
+
|
|
36
|
+
### Enable AI Compression (Optional)
|
|
37
|
+
|
|
38
|
+
For intelligent compression of observations using Claude:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Without an API key, open-mem still works — it falls back to a basic metadata extractor that captures tool names, file paths, and output snippets.
|
|
45
|
+
|
|
46
|
+
## Key Features
|
|
47
|
+
|
|
48
|
+
- 🧠 **Automatic observation capture** from tool executions
|
|
49
|
+
- 🤖 **AI-powered compression** using Claude (optional — works without API key)
|
|
50
|
+
- 🔍 **SQLite + FTS5** full-text search for fast retrieval
|
|
51
|
+
- 💡 **Progressive disclosure** with token-cost-aware context injection
|
|
52
|
+
- 🔒 **Privacy controls** with `<private>` tag support
|
|
53
|
+
- 🛠️ **Four custom tools**: mem-search, mem-save, mem-timeline, mem-recall
|
|
54
|
+
- ⚡ **Zero-config setup** — works out of the box
|
|
55
|
+
- 📁 **All data stored locally** in your project directory
|
|
56
|
+
|
|
57
|
+
## How It Works
|
|
58
|
+
|
|
59
|
+
open-mem runs in the background as an OpenCode plugin. When you use tools (reading files, running commands, editing code), it captures what happened. During idle time, it compresses those captures into structured observations using AI. At the start of your next session, it injects a compact memory index into the system prompt — so your agent knows what you've been working on.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
┌─────────────────────────────────────────────────────┐
|
|
63
|
+
│ OpenCode │
|
|
64
|
+
│ │
|
|
65
|
+
│ tool.execute.after ───> [Tool Capture Hook] │
|
|
66
|
+
│ │ │
|
|
67
|
+
│ v │
|
|
68
|
+
│ [Pending Queue] │
|
|
69
|
+
│ │ │
|
|
70
|
+
│ session.idle ─────────> [Queue Processor] │
|
|
71
|
+
│ │ │
|
|
72
|
+
│ v │
|
|
73
|
+
│ [AI Compressor] ───> Anthropic │
|
|
74
|
+
│ │ │
|
|
75
|
+
│ v │
|
|
76
|
+
│ [SQLite + FTS5] │
|
|
77
|
+
│ │ │
|
|
78
|
+
│ system.transform <─── [Context Injector] │
|
|
79
|
+
│ │
|
|
80
|
+
│ mem-search ─────────> [FTS5 Search] │
|
|
81
|
+
│ mem-save ───────────> [Direct Save] │
|
|
82
|
+
│ mem-timeline ───────> [Session Query] │
|
|
83
|
+
│ mem-recall ─────────> [Full Observation Fetch] │
|
|
84
|
+
└─────────────────────────────────────────────────────┘
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Observation Capture
|
|
88
|
+
|
|
89
|
+
When you use tools in OpenCode (reading files, running commands, editing code), open-mem's `tool.execute.after` hook captures each execution as a pending observation. Sensitive content (API keys, tokens, passwords) is automatically redacted, and `<private>` blocks are stripped.
|
|
90
|
+
|
|
91
|
+
### AI Compression
|
|
92
|
+
|
|
93
|
+
On `session.idle`, the queue processor batches pending observations and sends them to Claude for semantic compression. Each raw tool output is distilled into a structured observation with:
|
|
94
|
+
|
|
95
|
+
- Type classification (decision, bugfix, feature, refactor, discovery, change)
|
|
96
|
+
- Title and narrative summary
|
|
97
|
+
- Key facts extracted
|
|
98
|
+
- Concepts/tags for search
|
|
99
|
+
- Files involved
|
|
100
|
+
|
|
101
|
+
If no Anthropic API key is set, a fallback compressor extracts basic metadata without AI.
|
|
102
|
+
|
|
103
|
+
### Progressive Disclosure
|
|
104
|
+
|
|
105
|
+
open-mem injects a compact index into the system prompt at session start. Each entry shows a type icon, title, token cost, and related files — giving the agent a map of what's in memory without consuming the full context window.
|
|
106
|
+
|
|
107
|
+
The agent sees *what* exists and decides *what to fetch* using `mem-search` and `mem-recall`. This minimizes context window usage while providing full access to all stored observations.
|
|
108
|
+
|
|
109
|
+
Example of an injected index entry:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
🔧 [refactor] Extract pricing logic (~120 tokens) — src/pricing.ts
|
|
113
|
+
💡 [discovery] FTS5 requires specific tokenizer config (~85 tokens)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Session Compaction
|
|
117
|
+
|
|
118
|
+
During session compaction (`experimental.session.compacting`), open-mem injects memory context to preserve important information across compaction boundaries.
|
|
119
|
+
|
|
120
|
+
## Custom Tools
|
|
121
|
+
|
|
122
|
+
### mem-search
|
|
123
|
+
|
|
124
|
+
Search through past observations and session summaries using FTS5 full-text search.
|
|
125
|
+
|
|
126
|
+
| Argument | Type | Required | Description |
|
|
127
|
+
|----------|------|----------|-------------|
|
|
128
|
+
| `query` | string | yes | Search query (keywords, phrases, file paths) |
|
|
129
|
+
| `type` | enum | no | Filter by type: `decision`, `bugfix`, `feature`, `refactor`, `discovery`, `change` |
|
|
130
|
+
| `limit` | number | no | Max results (1–50, default: 10) |
|
|
131
|
+
|
|
132
|
+
### mem-save
|
|
133
|
+
|
|
134
|
+
Manually save an important observation to memory.
|
|
135
|
+
|
|
136
|
+
| Argument | Type | Required | Description |
|
|
137
|
+
|----------|------|----------|-------------|
|
|
138
|
+
| `title` | string | yes | Brief title (max 80 chars) |
|
|
139
|
+
| `type` | enum | yes | Observation type: `decision`, `bugfix`, `feature`, `refactor`, `discovery`, `change` |
|
|
140
|
+
| `narrative` | string | yes | Detailed description of what to remember |
|
|
141
|
+
| `concepts` | string[] | no | Related concepts/tags |
|
|
142
|
+
| `files` | string[] | no | Related file paths |
|
|
143
|
+
|
|
144
|
+
### mem-timeline
|
|
145
|
+
|
|
146
|
+
View a timeline of past coding sessions for the current project.
|
|
147
|
+
|
|
148
|
+
| Argument | Type | Required | Description |
|
|
149
|
+
|----------|------|----------|-------------|
|
|
150
|
+
| `limit` | number | no | Number of recent sessions (1–20, default: 5) |
|
|
151
|
+
| `sessionId` | string | no | Show details for a specific session |
|
|
152
|
+
|
|
153
|
+
### mem-recall
|
|
154
|
+
|
|
155
|
+
Fetch full observation details by ID. Use after `mem-search` to get complete narratives, facts, concepts, and file lists for specific observations.
|
|
156
|
+
|
|
157
|
+
| Argument | Type | Required | Description |
|
|
158
|
+
|----------|------|----------|-------------|
|
|
159
|
+
| `ids` | string[] | yes | Observation IDs to fetch |
|
|
160
|
+
| `limit` | number | no | Maximum number of results (1–50, default: 10) |
|
|
161
|
+
|
|
162
|
+
## Configuration
|
|
163
|
+
|
|
164
|
+
open-mem works out of the box with zero configuration. All settings can be customized via environment variables:
|
|
165
|
+
|
|
166
|
+
| Variable | Default | Description |
|
|
167
|
+
|----------|---------|-------------|
|
|
168
|
+
| `ANTHROPIC_API_KEY` | — | API key for AI compression (optional) |
|
|
169
|
+
| `OPEN_MEM_DB_PATH` | `.open-mem/memory.db` | Path to SQLite database |
|
|
170
|
+
| `OPEN_MEM_MODEL` | `claude-sonnet-4-20250514` | Model for AI compression |
|
|
171
|
+
| `OPEN_MEM_MAX_CONTEXT_TOKENS` | `4000` | Token budget for injected context |
|
|
172
|
+
| `OPEN_MEM_COMPRESSION` | `true` | Set to `false` to disable AI compression |
|
|
173
|
+
| `OPEN_MEM_CONTEXT_INJECTION` | `true` | Set to `false` to disable context injection |
|
|
174
|
+
| `OPEN_MEM_IGNORED_TOOLS` | — | Comma-separated tool names to ignore (e.g. `Bash,Glob`) |
|
|
175
|
+
| `OPEN_MEM_BATCH_SIZE` | `5` | Observations per processing batch |
|
|
176
|
+
| `OPEN_MEM_RETENTION_DAYS` | `90` | Delete observations older than N days (0 = forever) |
|
|
177
|
+
| `OPEN_MEM_LOG_LEVEL` | `warn` | Log verbosity: `debug`, `info`, `warn`, `error` |
|
|
178
|
+
| `OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS` | `true` | Show token costs in context index entries |
|
|
179
|
+
| `OPEN_MEM_CONTEXT_TYPES` | all | Observation types to include in context injection |
|
|
180
|
+
| `OPEN_MEM_CONTEXT_FULL_COUNT` | `3` | Number of recent observations shown in full |
|
|
181
|
+
| `OPEN_MEM_MAX_OBSERVATIONS` | `50` | Maximum observations to consider for context |
|
|
182
|
+
|
|
183
|
+
<details>
|
|
184
|
+
<summary><strong>Programmatic Configuration Reference</strong></summary>
|
|
185
|
+
|
|
186
|
+
If you need to configure open-mem programmatically (e.g. for testing or custom integrations), these are the full config options:
|
|
187
|
+
|
|
188
|
+
| Option | Type | Default | Description |
|
|
189
|
+
|--------|------|---------|-------------|
|
|
190
|
+
| `dbPath` | string | `.open-mem/memory.db` | SQLite database file path |
|
|
191
|
+
| `apiKey` | string | `undefined` | Anthropic API key |
|
|
192
|
+
| `model` | string | `claude-sonnet-4-20250514` | Claude model for compression |
|
|
193
|
+
| `maxTokensPerCompression` | number | `1024` | Max tokens per compression response |
|
|
194
|
+
| `compressionEnabled` | boolean | `true` | Enable AI compression |
|
|
195
|
+
| `contextInjectionEnabled` | boolean | `true` | Enable context injection |
|
|
196
|
+
| `maxContextTokens` | number | `4000` | Token budget for system prompt injection |
|
|
197
|
+
| `batchSize` | number | `5` | Observations per batch |
|
|
198
|
+
| `batchIntervalMs` | number | `30000` | Batch processing interval (ms) |
|
|
199
|
+
| `ignoredTools` | string[] | `[]` | Tool names to skip |
|
|
200
|
+
| `minOutputLength` | number | `50` | Minimum output length to capture |
|
|
201
|
+
| `maxIndexEntries` | number | `20` | Max observation index entries in context |
|
|
202
|
+
| `sensitivePatterns` | string[] | `[]` | Additional regex patterns to redact |
|
|
203
|
+
| `retentionDays` | number | `90` | Data retention period (0 = forever) |
|
|
204
|
+
| `maxDatabaseSizeMb` | number | `500` | Maximum database size |
|
|
205
|
+
| `logLevel` | string | `warn` | Log level: `debug`, `info`, `warn`, `error` |
|
|
206
|
+
|
|
207
|
+
</details>
|
|
208
|
+
|
|
209
|
+
## Privacy & Security
|
|
210
|
+
|
|
211
|
+
### Local Data Storage
|
|
212
|
+
|
|
213
|
+
All data is stored locally in your project's `.open-mem/` directory. No data leaves your machine except when AI compression is enabled.
|
|
214
|
+
|
|
215
|
+
### Anthropic API
|
|
216
|
+
|
|
217
|
+
When AI compression is enabled, tool outputs are sent to Claude for compression. Disable with `OPEN_MEM_COMPRESSION=false` to keep everything fully local.
|
|
218
|
+
|
|
219
|
+
### Automatic Redaction
|
|
220
|
+
|
|
221
|
+
open-mem automatically redacts common sensitive patterns before storage:
|
|
222
|
+
|
|
223
|
+
- API keys and tokens (e.g. `sk-ant-...`, `ghp_...`, `Bearer ...`)
|
|
224
|
+
- Passwords and secrets
|
|
225
|
+
- Environment variable values matching sensitive patterns
|
|
226
|
+
- Custom patterns via the `sensitivePatterns` config option
|
|
227
|
+
|
|
228
|
+
### `<private>` Tags
|
|
229
|
+
|
|
230
|
+
Wrap any content in `<private>...</private>` tags to exclude it from memory entirely. Private blocks are stripped before observation capture — they never reach the database or the Anthropic API.
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
<private>
|
|
234
|
+
This content will not be stored in memory.
|
|
235
|
+
</private>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Gitignore
|
|
239
|
+
|
|
240
|
+
Add `.open-mem/` to your `.gitignore` to prevent committing memory data:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
echo '.open-mem/' >> .gitignore
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Troubleshooting
|
|
247
|
+
|
|
248
|
+
### "AI compression enabled but no ANTHROPIC_API_KEY found"
|
|
249
|
+
|
|
250
|
+
This is a warning, not an error. open-mem works without an API key — it falls back to a basic metadata extractor. To enable AI compression:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Database errors
|
|
257
|
+
|
|
258
|
+
If you encounter SQLite errors, try removing the database and letting it recreate:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
rm -rf .open-mem/
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Context not appearing in sessions
|
|
265
|
+
|
|
266
|
+
1. Verify the plugin is loaded: check OpenCode logs for `[open-mem]` messages
|
|
267
|
+
2. Ensure `OPEN_MEM_CONTEXT_INJECTION` is not set to `false`
|
|
268
|
+
3. Check that observations exist: use the `mem-timeline` tool
|
|
269
|
+
4. The first session won't have context — observations must be captured first
|
|
270
|
+
|
|
271
|
+
### High memory usage
|
|
272
|
+
|
|
273
|
+
If the database grows too large, adjust retention:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
export OPEN_MEM_RETENTION_DAYS=30
|
|
277
|
+
export OPEN_MEM_MAX_CONTEXT_TOKENS=2000
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Uninstalling
|
|
281
|
+
|
|
282
|
+
1. Remove `"open-mem"` from the `plugin` array in your OpenCode config (`~/.config/opencode/opencode.json`).
|
|
283
|
+
|
|
284
|
+
2. Remove the package:
|
|
285
|
+
```bash
|
|
286
|
+
bun remove open-mem
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
3. Optionally, delete stored memory data:
|
|
290
|
+
```bash
|
|
291
|
+
rm -rf .open-mem/
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Documentation
|
|
295
|
+
|
|
296
|
+
- [Getting Started](docs/getting-started.md) — installation, configuration, and first steps
|
|
297
|
+
- [Architecture](docs/architecture.md) — internal design, data flow, and source layout
|
|
298
|
+
|
|
299
|
+
## Contributing
|
|
300
|
+
|
|
301
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, code style, and submission guidelines.
|
|
302
|
+
|
|
303
|
+
## Changelog
|
|
304
|
+
|
|
305
|
+
See [CHANGELOG.md](CHANGELOG.md) for a detailed history of changes.
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ParsedObservation } from "./parser";
|
|
2
|
+
export interface CompressorConfig {
|
|
3
|
+
apiKey: string | undefined;
|
|
4
|
+
model: string;
|
|
5
|
+
maxTokensPerCompression: number;
|
|
6
|
+
compressionEnabled: boolean;
|
|
7
|
+
minOutputLength: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Compresses raw tool output into structured observations using the
|
|
11
|
+
* Anthropic Messages API. Falls back to a heuristic-based observation
|
|
12
|
+
* when the API is unavailable or disabled.
|
|
13
|
+
*/
|
|
14
|
+
export declare class ObservationCompressor {
|
|
15
|
+
private client;
|
|
16
|
+
private config;
|
|
17
|
+
constructor(config: CompressorConfig);
|
|
18
|
+
/** Maximum input characters sent to the API (~12.5K tokens) */
|
|
19
|
+
static readonly MAX_INPUT_LENGTH = 50000;
|
|
20
|
+
/**
|
|
21
|
+
* Compress a single tool output into a structured observation.
|
|
22
|
+
* Returns `null` when compression is disabled, the output is too short,
|
|
23
|
+
* or the API call fails after retries.
|
|
24
|
+
*/
|
|
25
|
+
compress(toolName: string, toolOutput: string, sessionContext?: string): Promise<ParsedObservation | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Compress multiple items sequentially (avoids rate-limit bursts).
|
|
28
|
+
* Returns a map of `callId -> ParsedObservation | null`.
|
|
29
|
+
*/
|
|
30
|
+
compressBatch(items: ReadonlyArray<{
|
|
31
|
+
toolName: string;
|
|
32
|
+
toolOutput: string;
|
|
33
|
+
callId: string;
|
|
34
|
+
sessionContext?: string;
|
|
35
|
+
}>): Promise<Map<string, ParsedObservation | null>>;
|
|
36
|
+
/**
|
|
37
|
+
* Produce a basic observation from tool metadata when AI compression
|
|
38
|
+
* is unavailable.
|
|
39
|
+
*/
|
|
40
|
+
createFallbackObservation(toolName: string, toolOutput: string): ParsedObservation;
|
|
41
|
+
isAvailable(): Promise<boolean>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=compressor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../../src/ai/compressor.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,iBAAiB,EAA4B,MAAM,UAAU,CAAC;AAO5E,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACxB;AAMD;;;;GAIG;AACH,qBAAa,qBAAqB;IACjC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAmB;gBAErB,MAAM,EAAE,gBAAgB;IAUpC,+DAA+D;IAC/D,MAAM,CAAC,QAAQ,CAAC,gBAAgB,SAAU;IAE1C;;;;OAIG;IACG,QAAQ,CACb,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAiDpC;;;OAGG;IACG,aAAa,CAClB,KAAK,EAAE,aAAa,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC,GACA,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAqBjD;;;OAGG;IACH,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,iBAAiB;IAqB5E,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAarC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ObservationType } from "../types";
|
|
2
|
+
export interface ParsedObservation {
|
|
3
|
+
type: ObservationType;
|
|
4
|
+
title: string;
|
|
5
|
+
subtitle: string;
|
|
6
|
+
facts: string[];
|
|
7
|
+
narrative: string;
|
|
8
|
+
concepts: string[];
|
|
9
|
+
filesRead: string[];
|
|
10
|
+
filesModified: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface ParsedSummary {
|
|
13
|
+
summary: string;
|
|
14
|
+
keyDecisions: string[];
|
|
15
|
+
filesModified: string[];
|
|
16
|
+
concepts: string[];
|
|
17
|
+
request?: string;
|
|
18
|
+
investigated?: string;
|
|
19
|
+
learned?: string;
|
|
20
|
+
completed?: string;
|
|
21
|
+
nextSteps?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse an AI response containing `<observation>...</observation>` XML into
|
|
25
|
+
* a structured object. Returns `null` if the response cannot be parsed at all.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseObservationResponse(response: string): ParsedObservation | null;
|
|
28
|
+
/**
|
|
29
|
+
* Parse an AI response containing `<session_summary>...</session_summary>`
|
|
30
|
+
* into a structured object. Returns `null` if unparseable.
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseSummaryResponse(response: string): ParsedSummary | null;
|
|
33
|
+
/** Rough token count (4 chars ~ 1 token for English text) */
|
|
34
|
+
export declare function estimateTokens(text: string): number;
|
|
35
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/ai/parser.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMhD,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAyCD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CA4BnF;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA0B3E;AAMD,6DAA6D;AAC7D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a prompt that instructs the AI to compress raw tool output into a
|
|
3
|
+
* structured observation (type, title, facts, narrative, concepts, files).
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildCompressionPrompt(toolName: string, toolOutput: string, sessionContext?: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Build a prompt that instructs the AI to produce a session summary from
|
|
8
|
+
* a list of observations.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildSummarizationPrompt(observations: ReadonlyArray<{
|
|
11
|
+
type: string;
|
|
12
|
+
title: string;
|
|
13
|
+
narrative: string;
|
|
14
|
+
}>, sessionId: string): string;
|
|
15
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/ai/prompts.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACrB,MAAM,CAkDR;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,YAAY,EAAE,aAAa,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CAClB,CAAC,EACF,SAAS,EAAE,MAAM,GACf,MAAM,CAwCR"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Observation } from "../types";
|
|
2
|
+
import { type ParsedSummary } from "./parser";
|
|
3
|
+
export interface SummarizerConfig {
|
|
4
|
+
apiKey: string | undefined;
|
|
5
|
+
model: string;
|
|
6
|
+
maxTokensPerCompression: number;
|
|
7
|
+
compressionEnabled: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generates a concise summary of a coding session from its observations.
|
|
11
|
+
* Falls back to a heuristic aggregation when the API is unavailable.
|
|
12
|
+
*/
|
|
13
|
+
export declare class SessionSummarizer {
|
|
14
|
+
private client;
|
|
15
|
+
private config;
|
|
16
|
+
constructor(config: SummarizerConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Summarize a session's observations via the Anthropic API.
|
|
19
|
+
* Returns `null` for empty observation lists, falls back to heuristic
|
|
20
|
+
* summary when the API is disabled or errors out.
|
|
21
|
+
*/
|
|
22
|
+
summarize(sessionId: string, observations: ReadonlyArray<Observation>): Promise<ParsedSummary | null>;
|
|
23
|
+
/**
|
|
24
|
+
* Build a summary by aggregating observation metadata — no AI required.
|
|
25
|
+
*/
|
|
26
|
+
createFallbackSummary(observations: ReadonlyArray<Observation>): ParsedSummary;
|
|
27
|
+
/** Whether a session has enough observations to warrant summarization */
|
|
28
|
+
shouldSummarize(observationCount: number): boolean;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=summarizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarizer.d.ts","sourceRoot":"","sources":["../../src/ai/summarizer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,UAAU,CAAC;AAOpE,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AAMD;;;GAGG;AACH,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAmB;gBAErB,MAAM,EAAE,gBAAgB;IAUpC;;;;OAIG;IACG,SAAS,CACd,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,aAAa,CAAC,WAAW,CAAC,GACtC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA2ChC;;OAEG;IACH,qBAAqB,CAAC,YAAY,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,aAAa;IAqC9E,yEAAyE;IACzE,eAAe,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO;CAGlD"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OpenMemConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve configuration by merging defaults, environment variables, and overrides.
|
|
4
|
+
* Priority: defaults < env vars < overrides
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveConfig(projectDir: string, overrides?: Partial<OpenMemConfig>): OpenMemConfig;
|
|
7
|
+
/**
|
|
8
|
+
* Validate a resolved configuration. Returns an array of error messages.
|
|
9
|
+
* An empty array means the configuration is valid.
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateConfig(config: OpenMemConfig): string[];
|
|
12
|
+
/** Get a copy of the default configuration */
|
|
13
|
+
export declare function getDefaultConfig(): OpenMemConfig;
|
|
14
|
+
/** Ensure the database directory exists */
|
|
15
|
+
export declare function ensureDbDirectory(config: OpenMemConfig): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,SAAS,CAAC;AAyF9D;;;GAGG;AACH,wBAAgB,aAAa,CAC5B,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAChC,aAAa,CAoBf;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAsB9D;AAMD,8CAA8C;AAC9C,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAED,2CAA2C;AAC3C,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5E"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ObservationType } from "../types";
|
|
2
|
+
import type { ProgressiveContext } from "./progressive";
|
|
3
|
+
export interface ContextBuilderConfig {
|
|
4
|
+
showTokenCosts: boolean;
|
|
5
|
+
observationTypes: ObservationType[] | "all";
|
|
6
|
+
fullObservationCount: number;
|
|
7
|
+
showLastSummary: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildContextString(context: ProgressiveContext, config?: ContextBuilderConfig): string;
|
|
10
|
+
export declare function buildCompactContext(context: ProgressiveContext): string;
|
|
11
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/context/builder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAiC,eAAe,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAMxD,MAAM,WAAW,oBAAoB;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAC5C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;CACzB;AA0BD,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,kBAAkB,EAC3B,MAAM,GAAE,oBAA6C,GACnD,MAAM,CAgFR;AA8BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAoBvE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Observation, ObservationIndex, Session, SessionSummary } from "../types";
|
|
2
|
+
export interface ProgressiveContext {
|
|
3
|
+
recentSummaries: SessionSummary[];
|
|
4
|
+
observationIndex: ObservationIndex[];
|
|
5
|
+
fullObservations: Observation[];
|
|
6
|
+
totalTokens: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Select summaries and observation-index entries that fit within the
|
|
10
|
+
* token budget. Summaries are higher priority (richer context).
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildProgressiveContext(_recentSessions: ReadonlyArray<Session>, summaries: ReadonlyArray<SessionSummary>, observationIndex: ReadonlyArray<ObservationIndex>, maxTokens: number, fullObservations?: ReadonlyArray<Observation>): ProgressiveContext;
|
|
13
|
+
//# sourceMappingURL=progressive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progressive.d.ts","sourceRoot":"","sources":["../../src/context/progressive.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAMvF,MAAM,WAAW,kBAAkB;IAClC,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IACrC,gBAAgB,EAAE,WAAW,EAAE,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;CACpB;AAMD;;;GAGG;AACH,wBAAgB,uBAAuB,CACtC,eAAe,EAAE,aAAa,CAAC,OAAO,CAAC,EACvC,SAAS,EAAE,aAAa,CAAC,cAAc,CAAC,EACxC,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,EACjD,SAAS,EAAE,MAAM,EACjB,gBAAgB,GAAE,aAAa,CAAC,WAAW,CAAM,GAC/C,kBAAkB,CA2BpB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Database as BunDatabase, type SQLQueryBindings } from "bun:sqlite";
|
|
2
|
+
/** Param array accepted by query helpers */
|
|
3
|
+
type Params = SQLQueryBindings[];
|
|
4
|
+
export interface Migration {
|
|
5
|
+
version: number;
|
|
6
|
+
name: string;
|
|
7
|
+
up: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Manages the SQLite connection lifecycle: opening, configuring (WAL mode,
|
|
11
|
+
* foreign keys, busy timeout), running migrations, and exposing typed
|
|
12
|
+
* query helpers. Wraps bun:sqlite.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Database {
|
|
15
|
+
private db;
|
|
16
|
+
constructor(dbPath: string);
|
|
17
|
+
private open;
|
|
18
|
+
private configure;
|
|
19
|
+
private ensureMigrationTable;
|
|
20
|
+
/**
|
|
21
|
+
* Run pending migrations in version order. Already-applied migrations
|
|
22
|
+
* are skipped. Each migration runs inside a transaction.
|
|
23
|
+
*/
|
|
24
|
+
migrate(migrations: Migration[]): void;
|
|
25
|
+
/** Execute a write statement (INSERT / UPDATE / DELETE) with optional params */
|
|
26
|
+
run(sql: string, params?: Params): void;
|
|
27
|
+
/** Fetch a single row, or null if not found */
|
|
28
|
+
get<T>(sql: string, params?: Params): T | null;
|
|
29
|
+
/** Fetch all matching rows */
|
|
30
|
+
all<T>(sql: string, params?: Params): T[];
|
|
31
|
+
/** Execute raw SQL (multiple statements, no params) */
|
|
32
|
+
exec(sql: string): void;
|
|
33
|
+
/** Wrap a function in a SQLite transaction — auto-commits or rolls back */
|
|
34
|
+
transaction<T>(fn: () => T): T;
|
|
35
|
+
/** Close the database connection */
|
|
36
|
+
close(): void;
|
|
37
|
+
/** Check whether the connection is still usable */
|
|
38
|
+
get isOpen(): boolean;
|
|
39
|
+
/** Access the underlying bun:sqlite instance for advanced use */
|
|
40
|
+
get raw(): BunDatabase;
|
|
41
|
+
}
|
|
42
|
+
/** Create and configure a Database instance at the given path */
|
|
43
|
+
export declare function createDatabase(dbPath: string): Database;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG5E,4CAA4C;AAC5C,KAAK,MAAM,GAAG,gBAAgB,EAAE,CAAC;AAMjC,MAAM,WAAW,SAAS;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACX;AAMD;;;;GAIG;AACH,qBAAa,QAAQ;IACpB,OAAO,CAAC,EAAE,CAAc;gBAEZ,MAAM,EAAE,MAAM;IAS1B,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,oBAAoB;IAU5B;;;OAGG;IACI,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI;IA0B7C,gFAAgF;IACzE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAS9C,+CAA+C;IACxC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAKrD,8BAA8B;IACvB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE;IAKhD,uDAAuD;IAChD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI9B,2EAA2E;IACpE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAQrC,oCAAoC;IAC7B,KAAK,IAAI,IAAI;IAIpB,mDAAmD;IACnD,IAAW,MAAM,IAAI,OAAO,CAO3B;IAED,iEAAiE;IACjE,IAAW,GAAG,IAAI,WAAW,CAE5B;CACD;AAMD,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAEvD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Observation, ObservationIndex, SearchQuery, SearchResult } from "../types";
|
|
2
|
+
import type { Database } from "./database";
|
|
3
|
+
export declare class ObservationRepository {
|
|
4
|
+
private db;
|
|
5
|
+
constructor(db: Database);
|
|
6
|
+
create(data: Omit<Observation, "id" | "createdAt">): Observation;
|
|
7
|
+
getById(id: string): Observation | null;
|
|
8
|
+
getBySession(sessionId: string): Observation[];
|
|
9
|
+
getCount(sessionId?: string): number;
|
|
10
|
+
/** Lightweight index for progressive disclosure */
|
|
11
|
+
getIndex(projectPath: string, limit?: number): ObservationIndex[];
|
|
12
|
+
search(query: SearchQuery): SearchResult[];
|
|
13
|
+
searchByConcept(concept: string, limit?: number): Observation[];
|
|
14
|
+
searchByFile(filePath: string, limit?: number): Observation[];
|
|
15
|
+
private mapRow;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=observations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../../src/db/observations.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAEhB,WAAW,EACX,YAAY,EACZ,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,qBAAa,qBAAqB;IACrB,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAMhC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,WAAW;IAiChE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAOvC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE;IAS9C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAYpC,mDAAmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,gBAAgB,EAAE;IAyB7D,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,EAAE;IA6B1C,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,WAAW,EAAE;IAc3D,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,WAAW,EAAE;IAkBzD,OAAO,CAAC,MAAM;CAkBd"}
|