@zilliz/memsearch-opencode 0.1.0 → 0.1.2

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
@@ -21,11 +21,20 @@ uv tool install 'memsearch[onnx]'
21
21
  # or: pip install 'memsearch[onnx]'
22
22
  ```
23
23
 
24
- ### Install
24
+ ### Install from npm (recommended)
25
+
26
+ ```json
27
+ // In ~/.config/opencode/opencode.json
28
+ {
29
+ "plugin": ["@zilliz/memsearch-opencode"]
30
+ }
31
+ ```
32
+
33
+ ### Install from Source (development)
25
34
 
26
35
  ```bash
27
- # Clone the repo (if you haven't already)
28
- git clone https://github.com/zc277584121/memsearch.git
36
+ # Clone the repo
37
+ git clone https://github.com/zilliztech/memsearch.git
29
38
  cd memsearch
30
39
 
31
40
  # Run the installer
@@ -44,15 +53,6 @@ mkdir -p ~/.agents/skills
44
53
  ln -sf /path/to/memsearch/plugins/opencode/skills/memory-recall ~/.agents/skills/memory-recall
45
54
  ```
46
55
 
47
- ### npm Install (coming soon)
48
-
49
- ```json
50
- // In ~/.config/opencode/opencode.json
51
- {
52
- "plugin": ["memsearch-opencode"]
53
- }
54
- ```
55
-
56
56
  ## Architecture
57
57
 
58
58
  ```
@@ -73,6 +73,20 @@ OpenCode Session
73
73
  └── memory_transcript ──→ parse-transcript.py (SQLite reader)
74
74
  ```
75
75
 
76
+ ## Recall Memories
77
+
78
+ **Manual invocation** — explicitly invoke the skill with a query:
79
+
80
+ ```
81
+ /memory-recall what was the auth approach we discussed?
82
+ ```
83
+
84
+ **Auto invocation** — just ask naturally, the LLM auto-invokes memory tools when it senses the question needs history:
85
+
86
+ ```
87
+ We discussed the authentication flow before, what was the approach?
88
+ ```
89
+
76
90
  ## Tools
77
91
 
78
92
  | Tool | Description |
@@ -100,7 +114,7 @@ Each file contains timestamped entries with bullet-point summaries:
100
114
  ## Session 14:30
101
115
 
102
116
  ### 14:30
103
- <!-- session:ses_abc123 source:opencode-sqlite -->
117
+ <!-- session:ses_abc123 db:~/.local/share/opencode/opencode.db -->
104
118
  - User asked about the authentication flow.
105
119
  - Assistant explained the OAuth2 implementation in auth.ts.
106
120
  - Assistant modified the token refresh logic in refresh.ts.
package/index.ts CHANGED
@@ -68,12 +68,15 @@ function deriveCollectionName(projectDir: string): string {
68
68
  }
69
69
 
70
70
  /**
71
- * Read the tail of the N most recent daily .md files for cold-start context.
71
+ * Summarize the N most recent daily .md files for cold-start context.
72
+ * Extracts headings (## Session, ### turns) and bullet content from each
73
+ * file so the agent sees the structure of past days (what sessions existed,
74
+ * what topics came up), not just the tail of whichever file is newest.
72
75
  */
73
76
  function getRecentMemories(
74
77
  memDir: string,
75
78
  count = 2,
76
- tailLines = 15
79
+ maxLinesPerFile = 30
77
80
  ): string {
78
81
  if (!existsSync(memDir)) return "";
79
82
 
@@ -84,23 +87,24 @@ function getRecentMemories(
84
87
 
85
88
  if (files.length === 0) return "";
86
89
 
87
- const bullets: string[] = [];
90
+ const summary: string[] = [];
88
91
  for (const file of files) {
89
92
  try {
90
93
  const content = readFileSync(join(memDir, file), "utf-8");
91
- const lines = content.split("\n").slice(-tailLines);
92
- const fileBullets = lines.filter((l) => l.startsWith("- ") || l.startsWith("[Human]") || l.startsWith("[Assistant]"));
93
- if (fileBullets.length > 0) {
94
- bullets.push(`[${file}]`, ...fileBullets);
94
+ const lines = content.split("\n")
95
+ .filter((l) => /^#{2,4}\s/.test(l) || l.startsWith("- ") || l.startsWith("[Human]") || l.startsWith("[Assistant]"))
96
+ .slice(0, maxLinesPerFile);
97
+ if (lines.length > 0) {
98
+ summary.push(`[${file}]`, ...lines);
95
99
  }
96
100
  } catch { /* skip */ }
97
101
  }
98
102
 
99
- if (bullets.length === 0) {
103
+ if (summary.length === 0) {
100
104
  return `You have ${files.length} past memory file(s). Use the memory_search tool when the user's question could benefit from historical context.`;
101
105
  }
102
106
 
103
- return `Recent memories (use memory_search for full search):\n${bullets.join("\n")}`;
107
+ return `Recent memories (use memory_search for full search):\n${summary.join("\n")}`;
104
108
  }
105
109
 
106
110
  /** Shell-escape a string for safe use inside single quotes. */
@@ -281,7 +285,7 @@ const MemsearchPlugin: Plugin = async ({ project, directory, worktree }) => {
281
285
  description:
282
286
  "Retrieve the original conversation from a past OpenCode session. " +
283
287
  "Use after memory_get when the expanded result contains a session anchor " +
284
- "(<!-- session:ID source:opencode-sqlite -->). Returns the formatted " +
288
+ "(<!-- session:ID db:PATH -->). Returns the formatted " +
285
289
  "dialogue with [Human] and [Assistant] labels.",
286
290
  args: {
287
291
  session_id: tool.schema.string().describe("The session ID from the anchor comment"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zilliz/memsearch-opencode",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "memsearch plugin for OpenCode — semantic memory search across sessions",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -208,7 +208,7 @@ def _extract_msg_text(conn, msg_id, msg_json):
208
208
  return "\n".join(text_parts)
209
209
 
210
210
 
211
- def write_capture(memory_dir, turn_text, session_id):
211
+ def write_capture(memory_dir, turn_text, session_id, db_path=""):
212
212
  """Write a captured turn to the daily memory file."""
213
213
  os.makedirs(memory_dir, exist_ok=True)
214
214
 
@@ -220,7 +220,7 @@ def write_capture(memory_dir, turn_text, session_id):
220
220
  with open(memory_file, "w") as f:
221
221
  f.write(f"# {today}\n\n## Session {now}\n\n")
222
222
 
223
- anchor = f"<!-- session:{session_id} source:opencode-sqlite -->\n" if session_id else ""
223
+ anchor = f"<!-- session:{session_id} db:{db_path} -->\n" if session_id else ""
224
224
  entry = f"### {now}\n{anchor}{turn_text}\n\n"
225
225
 
226
226
  with open(memory_file, "a") as f:
@@ -280,7 +280,7 @@ def main():
280
280
  if turn_text and len(turn_text) > 10:
281
281
  # Summarize with LLM, fallback to raw text
282
282
  summary = summarize_with_llm(turn_text, small_model)
283
- write_capture(memory_dir, summary if summary else turn_text, session_id)
283
+ write_capture(memory_dir, summary if summary else turn_text, session_id, db_path)
284
284
  if msg_time > last_msg_time:
285
285
  last_msg_time = msg_time
286
286
  try:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: memory-recall
3
- description: "Search and recall relevant memories from past sessions. Use when the user's question could benefit from historical context, past decisions, debugging notes, previous conversations, or project knowledge."
3
+ description: "Search and recall relevant memories from past sessions via memsearch. Use when the user's question could benefit from historical context, past decisions, debugging notes, previous conversations, or project knowledge -- especially questions like 'what did I decide about X', 'why did we do Y', or 'have I seen this before'. Also use when you see `[memsearch] Memory available` hints injected via SessionStart or UserPromptSubmit. Typical flow: search for 3-5 chunks, expand the most relevant, optionally deep-drill into original transcripts via the anchor format. Skip when the question is purely about current code state (use Read/Grep), ephemeral (today's task only), or the user has explicitly asked to ignore memory."
4
4
  allowed-tools: Bash
5
5
  ---
6
6
 
@@ -8,7 +8,7 @@ You are a memory retrieval agent for memsearch. Your job is to search past memor
8
8
 
9
9
  ## Project Collection
10
10
 
11
- Collection: !`bash __INSTALL_DIR__/scripts/derive-collection.sh`
11
+ Collection: !`bash -c 'root=$(git rev-parse --show-toplevel 2>/dev/null || true); if [ -n "$root" ]; then bash __INSTALL_DIR__/scripts/derive-collection.sh "$root"; else bash __INSTALL_DIR__/scripts/derive-collection.sh; fi'`
12
12
 
13
13
  ## Your Task
14
14
 
@@ -24,14 +24,22 @@ Search for memories relevant to: $ARGUMENTS
24
24
 
25
25
  3. **Expand**: For each relevant result, run `memsearch expand <chunk_hash> --collection <collection name above>` to get the full markdown section with surrounding context.
26
26
 
27
- 4. **Deep drill (optional)**: If an expanded chunk contains a session anchor (`<!-- session:ID source:opencode-sqlite -->`), and the original conversation seems critical, run:
28
- ```
29
- python3 __INSTALL_DIR__/scripts/parse-transcript.py <session_id> --limit 10
30
- ```
31
- to retrieve the original conversation turns from the OpenCode SQLite database.
27
+ 4. **Deep drill (optional)**: If an expanded chunk contains transcript anchors (HTML comments with session info), and the original conversation seems critical:
28
+ - If the anchor contains `db:`, run `python3 __INSTALL_DIR__/scripts/parse-transcript.py <session_id> --limit 10` to retrieve the original conversation turns from the SQLite database.
29
+ - If the anchor format is unfamiliar (e.g. `transcript:`, `rollout:` instead of `db:`), try reading the referenced file directly to explore its structure and locate the relevant conversation by the session or turn identifiers in the anchor.
32
30
 
33
31
  5. **Return results**: Output a curated summary of the most relevant memories. Be concise — only include information that is genuinely useful for the user's current question.
34
32
 
33
+ ## When unsure what to search
34
+
35
+ If the user's question is vague or you can't form a concrete search query, explore the raw markdown first — it is the source of truth for memory:
36
+
37
+ - `ls -t .memsearch/memory/ | head -10` — recent daily logs
38
+ - `grep -h "^## " .memsearch/memory/*.md | sort -u | tail -40` — session headings across all days
39
+ - `cat .memsearch/memory/<YYYY-MM-DD>.md` — read a specific day
40
+
41
+ Once a concrete topic jumps out, go back to `memsearch search` with a specific query.
42
+
35
43
  ## Output Format
36
44
 
37
45
  Organize by relevance. For each memory include: