opencode-mem 2.3.4 → 2.3.5
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 +31 -123
- package/dist/services/embedding.d.ts.map +1 -1
- package/dist/services/embedding.js +2 -1
- package/dist/services/sqlite/connection-manager.d.ts.map +1 -1
- package/dist/services/sqlite/connection-manager.js +2 -1
- package/dist/services/tags.d.ts.map +1 -1
- package/dist/services/tags.js +4 -1
- package/dist/web/app.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,202 +8,110 @@
|
|
|
8
8
|
|
|
9
9
|
A persistent memory system for AI coding agents that enables long-term context retention across sessions using local vector database technology.
|
|
10
10
|
|
|
11
|
-
## Overview
|
|
11
|
+
## Visual Overview
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
## Key Features
|
|
16
|
-
|
|
17
|
-
- **Local Vector Database**: SQLite-based storage with sqlite-vec extension
|
|
18
|
-
- **Project Memory System**: Persistent storage for project-specific knowledge
|
|
19
|
-
- **User Profile System**: Automatic learning of preferences, patterns, and workflows
|
|
20
|
-
- **Unified Timeline**: Browse memories and prompts together with linking support
|
|
21
|
-
- **Web Interface**: Full-featured UI for memory management and search
|
|
22
|
-
- **Auto-Capture System**: Intelligent prompt-based memory extraction
|
|
23
|
-
- **Multi-Provider AI**: Support for OpenAI, Anthropic, and OpenAI-compatible APIs
|
|
24
|
-
- **Flexible Embedding Models**: 12+ local models or OpenAI-compatible APIs
|
|
25
|
-
- **Smart Deduplication**: Prevents redundant memories using similarity detection
|
|
26
|
-
- **Privacy Protection**: Built-in content filtering for sensitive information
|
|
27
|
-
|
|
28
|
-
## Installation
|
|
29
|
-
|
|
30
|
-
Add the plugin to your OpenCode configuration:
|
|
31
|
-
|
|
32
|
-
**Location**: `~/.config/opencode/opencode.json` or `opencode.jsonc`
|
|
33
|
-
|
|
34
|
-
```jsonc
|
|
35
|
-
{
|
|
36
|
-
"plugins": [
|
|
37
|
-
"opencode-mem"
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
```
|
|
13
|
+
**Project Memory Timeline:**
|
|
41
14
|
|
|
42
|
-
|
|
15
|
+

|
|
43
16
|
|
|
44
|
-
|
|
17
|
+
**User Profile Viewer:**
|
|
45
18
|
|
|
46
|
-
|
|
19
|
+

|
|
47
20
|
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
brew install sqlite
|
|
51
|
-
```
|
|
21
|
+
## Core Features
|
|
52
22
|
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
brew --prefix sqlite
|
|
56
|
-
```
|
|
23
|
+
Local vector database with SQLite, persistent project memories, automatic user profile learning, unified memory-prompt timeline, full-featured web UI, intelligent prompt-based memory extraction, multi-provider AI support (OpenAI, Anthropic), 12+ local embedding models, smart deduplication, and built-in privacy protection.
|
|
57
24
|
|
|
58
|
-
|
|
25
|
+
## Getting Started
|
|
59
26
|
|
|
60
|
-
|
|
27
|
+
Add to your OpenCode configuration at `~/.config/opencode/opencode.json`:
|
|
61
28
|
|
|
62
29
|
```jsonc
|
|
63
30
|
{
|
|
64
|
-
"
|
|
31
|
+
"plugins": ["opencode-mem"]
|
|
65
32
|
}
|
|
66
33
|
```
|
|
67
34
|
|
|
68
|
-
|
|
69
|
-
- **Apple Silicon (M1/M2/M3)**: `/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib`
|
|
70
|
-
- **Intel Mac**: `/usr/local/opt/sqlite/lib/libsqlite3.dylib`
|
|
71
|
-
|
|
72
|
-
The plugin will auto-detect these paths if not configured, but manual configuration is recommended for reliability.
|
|
73
|
-
|
|
74
|
-
### Install from Source
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
git clone https://github.com/tickernelz/opencode-mem.git
|
|
78
|
-
cd opencode-mem
|
|
79
|
-
bun install
|
|
80
|
-
bun run build
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Quick Start
|
|
35
|
+
The plugin downloads automatically on next startup. macOS users with Apple Silicon must install Homebrew SQLite and configure the custom path - see our Wiki for details.
|
|
84
36
|
|
|
85
|
-
|
|
37
|
+
## Usage Examples
|
|
86
38
|
|
|
87
39
|
```typescript
|
|
88
|
-
// Add project memory
|
|
89
40
|
memory({ mode: "add", content: "Project uses microservices architecture" })
|
|
90
|
-
|
|
91
|
-
// Search memories
|
|
92
41
|
memory({ mode: "search", query: "architecture decisions" })
|
|
93
|
-
|
|
94
|
-
// View user profile
|
|
95
42
|
memory({ mode: "profile" })
|
|
96
|
-
|
|
97
|
-
// List recent memories
|
|
98
43
|
memory({ mode: "list", limit: 10 })
|
|
99
44
|
```
|
|
100
45
|
|
|
101
|
-
|
|
46
|
+
Access the web interface at `http://127.0.0.1:4747` for visual memory browsing and management.
|
|
102
47
|
|
|
103
|
-
|
|
48
|
+
## Configuration Essentials
|
|
104
49
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-

|
|
108
|
-
|
|
109
|
-
**User Profile Viewer:**
|
|
110
|
-
|
|
111
|
-

|
|
112
|
-
|
|
113
|
-
## Configuration
|
|
114
|
-
|
|
115
|
-
Configuration file: `~/.config/opencode/opencode-mem.jsonc`
|
|
50
|
+
Configure at `~/.config/opencode/opencode-mem.jsonc`:
|
|
116
51
|
|
|
117
52
|
```jsonc
|
|
118
53
|
{
|
|
119
54
|
"storagePath": "~/.opencode-mem/data",
|
|
120
|
-
"customSqlitePath": "/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib",
|
|
121
55
|
"embeddingModel": "Xenova/nomic-embed-text-v1",
|
|
122
56
|
"webServerEnabled": true,
|
|
123
57
|
"webServerPort": 4747,
|
|
124
58
|
"autoCaptureEnabled": true,
|
|
125
59
|
"memoryProvider": "openai-chat",
|
|
126
60
|
"memoryModel": "gpt-4",
|
|
127
|
-
"memoryApiUrl": "https://api.openai.com/v1",
|
|
128
|
-
"memoryApiKey": "sk-...",
|
|
129
61
|
"userProfileAnalysisInterval": 10,
|
|
130
62
|
"maxMemories": 10
|
|
131
63
|
}
|
|
132
64
|
```
|
|
133
65
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
## Breaking Changes (v2.3)
|
|
66
|
+
Full documentation available in our [Configuration Guide](https://github.com/tickernelz/opencode-mem/wiki/Configuration-Guide).
|
|
137
67
|
|
|
138
|
-
|
|
68
|
+
## Important: v2.3 Breaking Changes
|
|
139
69
|
|
|
140
|
-
-
|
|
141
|
-
- **Removed**: `maxProjectMemories` config (use `maxMemories` instead)
|
|
142
|
-
- **Renamed**: `userMemoryAnalysisInterval` → `userProfileAnalysisInterval`
|
|
143
|
-
- **Renamed**: `performUserMemoryLearning()` → `performUserProfileLearning()`
|
|
144
|
-
- **Changed**: All memories are now project-scoped by default
|
|
145
|
-
- **Changed**: User preferences managed exclusively through automatic profile system
|
|
70
|
+
User-scoped memories removed. All memories now project-scoped. Update configuration:
|
|
146
71
|
|
|
147
|
-
**Migration required:**
|
|
148
72
|
```jsonc
|
|
149
|
-
// OLD
|
|
73
|
+
// OLD: Remove these
|
|
150
74
|
{
|
|
151
75
|
"userMemoryAnalysisInterval": 10,
|
|
152
|
-
"maxMemories": 5,
|
|
153
76
|
"maxProjectMemories": 10
|
|
154
77
|
}
|
|
155
78
|
|
|
156
|
-
// NEW
|
|
79
|
+
// NEW: Use only
|
|
157
80
|
{
|
|
158
81
|
"userProfileAnalysisInterval": 10,
|
|
159
82
|
"maxMemories": 10
|
|
160
83
|
}
|
|
161
84
|
```
|
|
162
85
|
|
|
163
|
-
Remove `scope` parameter from all `memory()` calls
|
|
164
|
-
```typescript
|
|
165
|
-
// OLD
|
|
166
|
-
memory({ mode: "add", content: "...", scope: "project" })
|
|
167
|
-
|
|
168
|
-
// NEW
|
|
169
|
-
memory({ mode: "add", content: "..." })
|
|
170
|
-
```
|
|
86
|
+
Remove `scope` parameter from all `memory()` calls. See [Migration Guide](https://github.com/tickernelz/opencode-mem/wiki/Migration-v2-3) for details.
|
|
171
87
|
|
|
172
88
|
## Documentation
|
|
173
89
|
|
|
174
|
-
For detailed documentation, see the [Wiki](https://github.com/tickernelz/opencode-mem/wiki):
|
|
175
|
-
|
|
176
90
|
- [Installation Guide](https://github.com/tickernelz/opencode-mem/wiki/Installation-Guide)
|
|
177
|
-
- [Quick Start](https://github.com/tickernelz/opencode-mem/wiki/Quick-Start)
|
|
178
|
-
- [Configuration Guide](https://github.com/tickernelz/opencode-mem/wiki/Configuration-Guide)
|
|
179
|
-
- [User Profile System](https://github.com/tickernelz/opencode-mem/wiki/User-Profile-System)
|
|
180
|
-
- [Memory Operations](https://github.com/tickernelz/opencode-mem/wiki/Memory-Operations)
|
|
181
|
-
- [Auto-Capture System](https://github.com/tickernelz/opencode-mem/wiki/Auto-Capture-System)
|
|
182
|
-
- [Web Interface](https://github.com/tickernelz/opencode-mem/wiki/Web-Interface)
|
|
183
91
|
- [API Reference](https://github.com/tickernelz/opencode-mem/wiki/API-Reference)
|
|
184
92
|
- [Troubleshooting](https://github.com/tickernelz/opencode-mem/wiki/Troubleshooting)
|
|
93
|
+
- [Complete Wiki](https://github.com/tickernelz/opencode-mem/wiki)
|
|
94
|
+
|
|
95
|
+
## Development & Contribution
|
|
185
96
|
|
|
186
|
-
|
|
97
|
+
Build and test locally:
|
|
187
98
|
|
|
188
99
|
```bash
|
|
189
100
|
bun install
|
|
190
|
-
bun run dev
|
|
191
101
|
bun run build
|
|
192
|
-
bun run format
|
|
193
102
|
bun run typecheck
|
|
103
|
+
bun run format
|
|
194
104
|
```
|
|
195
105
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
MIT License - see LICENSE file for details
|
|
199
|
-
|
|
200
|
-
## Acknowledgments
|
|
106
|
+
This project is actively seeking contributions to become the definitive memory plugin for AI coding agents. Whether you are fixing bugs, adding features, improving documentation, or expanding embedding model support, your contributions are critical. The codebase is well-structured and ready for enhancement. If you hit a blocker or have improvement ideas, submit a pull request - we review and merge contributions quickly.
|
|
201
107
|
|
|
202
|
-
|
|
108
|
+
## License & Links
|
|
203
109
|
|
|
204
|
-
|
|
110
|
+
MIT License - see LICENSE file
|
|
205
111
|
|
|
206
112
|
- **Repository**: https://github.com/tickernelz/opencode-mem
|
|
207
113
|
- **Wiki**: https://github.com/tickernelz/opencode-mem/wiki
|
|
208
114
|
- **Issues**: https://github.com/tickernelz/opencode-mem/issues
|
|
209
115
|
- **OpenCode Platform**: https://opencode.ai
|
|
116
|
+
|
|
117
|
+
Inspired by [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../src/services/embedding.ts"],"names":[],"mappings":"AAmBA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,WAAW,CAA8B;IAC1C,UAAU,EAAE,OAAO,CAAS;IAEnC,MAAM,CAAC,WAAW,IAAI,gBAAgB;IAOhC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAQzD,eAAe;IAuBvB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAkC1C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAG5D;AAED,eAAO,MAAM,gBAAgB,kBAAiC,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { pipeline, env } from "@xenova/transformers";
|
|
2
2
|
import { CONFIG } from "../config.js";
|
|
3
3
|
import { log } from "./logger.js";
|
|
4
|
+
import { join } from "node:path";
|
|
4
5
|
env.allowLocalModels = true;
|
|
5
6
|
env.allowRemoteModels = true;
|
|
6
|
-
env.cacheDir = CONFIG.storagePath
|
|
7
|
+
env.cacheDir = join(CONFIG.storagePath, ".cache");
|
|
7
8
|
const TIMEOUT_MS = 30000;
|
|
8
9
|
const GLOBAL_EMBEDDING_KEY = Symbol.for("opencode-mem.embedding.instance");
|
|
9
10
|
function withTimeout(promise, ms) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../src/services/sqlite/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,eAAe;IAqEzB,OAAO,CAAC,YAAY;IAqBlB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAmBvC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IASrC,QAAQ,IAAI,IAAI;CAWjB;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Database } from "bun:sqlite";
|
|
2
2
|
import * as sqliteVec from "sqlite-vec";
|
|
3
3
|
import { existsSync, mkdirSync } from "node:fs";
|
|
4
|
+
import { dirname } from "node:path";
|
|
4
5
|
import { log } from "../logger.js";
|
|
5
6
|
import { CONFIG } from "../../config.js";
|
|
6
7
|
export class ConnectionManager {
|
|
@@ -90,7 +91,7 @@ export class ConnectionManager {
|
|
|
90
91
|
return this.connections.get(dbPath);
|
|
91
92
|
}
|
|
92
93
|
this.configureSqlite();
|
|
93
|
-
const dir =
|
|
94
|
+
const dir = dirname(dbPath);
|
|
94
95
|
if (!existsSync(dir)) {
|
|
95
96
|
mkdirSync(dir, { recursive: true });
|
|
96
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/services/tags.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/services/tags.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAO3C;AAED,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAO1C;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU9D;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,cAAc,IAAI,OAAO,CAoBxC;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAW5D;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG;IAC1C,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB,CAKA"}
|
package/dist/services/tags.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { execSync } from "node:child_process";
|
|
3
3
|
import { CONFIG } from "../config.js";
|
|
4
|
+
import { sep, normalize } from "node:path";
|
|
4
5
|
function sha256(input) {
|
|
5
6
|
return createHash("sha256").update(input).digest("hex").slice(0, 16);
|
|
6
7
|
}
|
|
@@ -35,7 +36,9 @@ export function getGitRepoUrl(directory) {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
export function getProjectName(directory) {
|
|
38
|
-
|
|
39
|
+
// Normalize path to handle both Unix and Windows separators
|
|
40
|
+
const normalized = normalize(directory);
|
|
41
|
+
const parts = normalized.split(sep).filter((p) => p);
|
|
39
42
|
return parts[parts.length - 1] || directory;
|
|
40
43
|
}
|
|
41
44
|
export function getUserTagInfo() {
|
package/dist/web/app.js
CHANGED
|
@@ -166,14 +166,14 @@ function renderMemoryCard(memory) {
|
|
|
166
166
|
const isSelected = state.selectedMemories.has(memory.id);
|
|
167
167
|
const isPinned = memory.isPinned || false;
|
|
168
168
|
const isLinked = !!memory.linkedPromptId;
|
|
169
|
-
|
|
169
|
+
const similarityHtml =
|
|
170
170
|
memory.similarity !== undefined
|
|
171
171
|
? `<span class="similarity-score">${memory.similarity}%</span>`
|
|
172
172
|
: "";
|
|
173
173
|
|
|
174
174
|
let displayInfo = memory.displayName || memory.id;
|
|
175
175
|
if (memory.projectPath) {
|
|
176
|
-
const pathParts = memory.projectPath.split("/");
|
|
176
|
+
const pathParts = memory.projectPath.replace(/\\/g, "/").split("/").filter((p) => p);
|
|
177
177
|
displayInfo = pathParts[pathParts.length - 1] || memory.projectPath;
|
|
178
178
|
}
|
|
179
179
|
|