@zilliz/memsearch-opencode 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -3
- package/index.ts +25 -8
- package/package.json +3 -2
- package/scripts/capture-daemon.py +344 -155
- package/scripts/opencode_turns.py +449 -0
- package/scripts/parse-transcript.py +61 -148
- package/skills/memory-recall/SKILL.md +2 -1
- package/scripts/__pycache__/capture-daemon.cpython-313.pyc +0 -0
package/README.md
CHANGED
|
@@ -62,6 +62,7 @@ OpenCode Session
|
|
|
62
62
|
├── chat.message hook ──→ Detect turn completion
|
|
63
63
|
│ │
|
|
64
64
|
│ ├── Extract last turn from SQLite
|
|
65
|
+
│ ├── Persist turn metadata to .memsearch/opencode-turns.db
|
|
65
66
|
│ ├── Summarize via LLM (third-person notes)
|
|
66
67
|
│ └── Append to .memsearch/memory/YYYY-MM-DD.md
|
|
67
68
|
│ │
|
|
@@ -106,7 +107,11 @@ We discussed the authentication flow before, what was the approach?
|
|
|
106
107
|
|------|-------------|
|
|
107
108
|
| `memory_search` | Semantic search over past memories. Returns ranked chunks. |
|
|
108
109
|
| `memory_get` | Expand a chunk hash to see the full markdown section. |
|
|
109
|
-
| `memory_transcript` | Read original conversation from OpenCode SQLite DB. |
|
|
110
|
+
| `memory_transcript` | Read original conversation from OpenCode SQLite DB, optionally centered on a turn cursor. |
|
|
111
|
+
|
|
112
|
+
`<project>/.memsearch/opencode-turns.db` stores derived capture checkpoints and
|
|
113
|
+
turn ordering only. It is rebuildable state, not the source of truth for
|
|
114
|
+
transcript recall.
|
|
110
115
|
|
|
111
116
|
## Memory Files
|
|
112
117
|
|
|
@@ -127,7 +132,7 @@ Each file contains timestamped entries with bullet-point summaries:
|
|
|
127
132
|
## Session 14:30
|
|
128
133
|
|
|
129
134
|
### 14:30
|
|
130
|
-
<!-- session:ses_abc123 db:~/.local/share/opencode/opencode.db -->
|
|
135
|
+
<!-- session:ses_abc123 turn:msg_123abc db:~/.local/share/opencode/opencode.db -->
|
|
131
136
|
- User asked about the authentication flow.
|
|
132
137
|
- Assistant explained the OAuth2 implementation in auth.ts.
|
|
133
138
|
- Assistant modified the token refresh logic in refresh.ts.
|
|
@@ -143,13 +148,21 @@ memsearch config set embedding.provider openai
|
|
|
143
148
|
export OPENAI_API_KEY=sk-...
|
|
144
149
|
```
|
|
145
150
|
|
|
151
|
+
To override only the OpenCode capture summarization model:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
memsearch config set plugins.opencode.summarize.model anthropic/claude-haiku
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Leave it empty or unset to keep the current `small_model` / plugin default behavior. This setting does not fall back to `llm.model`.
|
|
158
|
+
|
|
146
159
|
## How It Works
|
|
147
160
|
|
|
148
161
|
1. **Capture**: After each conversation turn, the plugin extracts the user+assistant exchange, summarizes it via LLM, and appends to a daily markdown file.
|
|
149
162
|
|
|
150
163
|
2. **Index**: The markdown files are indexed by memsearch into a Milvus collection (Milvus Lite by default, runs in-process).
|
|
151
164
|
|
|
152
|
-
3. **Recall**: When the assistant needs historical context, it calls `memory_search` to find relevant chunks. Results can be expanded with `memory_get` or drilled into with `memory_transcript
|
|
165
|
+
3. **Recall**: When the assistant needs historical context, it calls `memory_search` to find relevant chunks. Results can be expanded with `memory_get` or drilled into with `memory_transcript`, which reads the original transcript from OpenCode SQLite.
|
|
153
166
|
|
|
154
167
|
4. **Cold-start**: At session start, recent memory bullets are injected into the system prompt so the assistant has immediate context.
|
|
155
168
|
|
package/index.ts
CHANGED
|
@@ -285,11 +285,14 @@ const MemsearchPlugin: Plugin = async ({ project, directory, worktree }) => {
|
|
|
285
285
|
description:
|
|
286
286
|
"Retrieve the original conversation from a past OpenCode session. " +
|
|
287
287
|
"Use after memory_get when the expanded result contains a session anchor " +
|
|
288
|
-
"(<!-- session:ID db:PATH -->). Returns the formatted " +
|
|
289
|
-
"dialogue with [Human] and [Assistant] labels."
|
|
288
|
+
"(<!-- session:ID turn:ID db:PATH -->). Returns the formatted " +
|
|
289
|
+
"dialogue with [Human] and [Assistant] labels. When turn_id is present, " +
|
|
290
|
+
"the tool returns the target turn plus surrounding context.",
|
|
290
291
|
args: {
|
|
291
292
|
session_id: tool.schema.string().describe("The session ID from the anchor comment"),
|
|
292
|
-
|
|
293
|
+
turn_id: tool.schema.string().optional().describe("Optional turn ID from the anchor comment"),
|
|
294
|
+
context: tool.schema.number().optional().describe("Turns before/after the target turn (default: 3)"),
|
|
295
|
+
limit: tool.schema.number().optional().describe("Max number of turns to return when no turn_id is provided (default: 20)"),
|
|
293
296
|
},
|
|
294
297
|
async execute(args, context) {
|
|
295
298
|
const dir = context?.directory || projectDir;
|
|
@@ -297,11 +300,25 @@ const MemsearchPlugin: Plugin = async ({ project, directory, worktree }) => {
|
|
|
297
300
|
if (autoCapture) startCaptureDaemon(dir, col, memsearchCmd);
|
|
298
301
|
try {
|
|
299
302
|
const scriptPath = join(PLUGIN_DIR, "scripts", "parse-transcript.py");
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
const scriptArgs = [
|
|
304
|
+
scriptPath,
|
|
305
|
+
args.session_id,
|
|
306
|
+
"--project-dir",
|
|
307
|
+
dir,
|
|
308
|
+
];
|
|
309
|
+
if (args.turn_id) {
|
|
310
|
+
scriptArgs.push("--turn", args.turn_id);
|
|
311
|
+
}
|
|
312
|
+
if (typeof args.context === "number") {
|
|
313
|
+
scriptArgs.push("--context", String(args.context));
|
|
314
|
+
}
|
|
315
|
+
if (typeof args.limit === "number") {
|
|
316
|
+
scriptArgs.push("--limit", String(args.limit));
|
|
317
|
+
}
|
|
318
|
+
const result = spawnSync("python3", scriptArgs, {
|
|
319
|
+
encoding: "utf-8",
|
|
320
|
+
timeout: 15000,
|
|
321
|
+
});
|
|
305
322
|
return result.stdout?.trim() || result.stderr || "No transcript content found.";
|
|
306
323
|
} catch (e: any) {
|
|
307
324
|
return `Transcript parse failed: ${e.message}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zilliz/memsearch-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "memsearch plugin for OpenCode — semantic memory search across sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"index.ts",
|
|
12
|
-
"scripts
|
|
12
|
+
"scripts/*.py",
|
|
13
|
+
"scripts/*.sh",
|
|
13
14
|
"skills/",
|
|
14
15
|
"prompts/",
|
|
15
16
|
"README.md"
|