@zilliz/memsearch-opencode 0.1.2 → 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/README.md CHANGED
@@ -30,6 +30,8 @@ uv tool install 'memsearch[onnx]'
30
30
  }
31
31
  ```
32
32
 
33
+ > Windows note: the current plugin shells out to `bash` and `python3` helper scripts. Plain Windows installs are not supported yet; use WSL2 (recommended) or a POSIX-compatible shell such as Git Bash. See issue #387.
34
+
33
35
  ### Install from Source (development)
34
36
 
35
37
  ```bash
@@ -73,6 +75,17 @@ OpenCode Session
73
75
  └── memory_transcript ──→ parse-transcript.py (SQLite reader)
74
76
  ```
75
77
 
78
+ ## Verify It Works
79
+
80
+ After restarting OpenCode, chat for a few turns in a project and confirm memory capture is happening:
81
+
82
+ ```bash
83
+ ls .memsearch/memory/
84
+ cat .memsearch/memory/$(date +%Y-%m-%d).md
85
+ ```
86
+
87
+ If the plugin is active, daily markdown files should appear and grow as conversations finish.
88
+
76
89
  ## Recall Memories
77
90
 
78
91
  **Manual invocation** — explicitly invoke the skill with a query:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zilliz/memsearch-opencode",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "memsearch plugin for OpenCode — semantic memory search across sessions",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -11,6 +11,7 @@
11
11
  "index.ts",
12
12
  "scripts/",
13
13
  "skills/",
14
+ "prompts/",
14
15
  "README.md"
15
16
  ],
16
17
  "keywords": [
@@ -0,0 +1,14 @@
1
+ You are a third-person note-taker. You will receive a transcript of ONE conversation turn between a human and {{AGENT_NAME}}.
2
+
3
+ Your job is to record what happened as factual third-person notes. You are an EXTERNAL OBSERVER — you are NOT {{AGENT_NAME}}, NOT an assistant. Do NOT answer the human's question, do NOT give suggestions, do NOT offer help. ONLY record what occurred.
4
+
5
+ Output 2-6 bullet points, each starting with '- '. NOTHING else.
6
+
7
+ Rules:
8
+ - Write in third person: 'User asked...', '{{AGENT_NAME}} read file X', '{{AGENT_NAME}} ran command Y'
9
+ - First bullet: what the user asked or wanted (one sentence)
10
+ - Remaining bullets: what was done — tools called, files read/edited, commands run, key findings
11
+ - Be specific: mention file names, function names, tool names, and concrete outcomes
12
+ - Do NOT answer the human's question yourself — just note what was discussed
13
+ - Do NOT add any text before or after the bullet points
14
+ - Write in the same language as the human's message in the transcript
@@ -53,20 +53,41 @@ def ensure_isolated_config():
53
53
  return os.path.dirname(isolated) # /tmp/opencode-memsearch-summarize
54
54
 
55
55
 
56
- def summarize_with_llm(turn_text, small_model):
56
+ def _load_summarize_prompt(agent_name, memsearch_cmd=None):
57
+ """Load summarization prompt: user custom > plugin built-in > inline fallback."""
58
+ # Try user-custom prompt via config
59
+ if memsearch_cmd:
60
+ try:
61
+ result = subprocess.run(
62
+ memsearch_cmd.split() + ["config", "get", "prompts.summarize"],
63
+ capture_output=True, text=True, timeout=5,
64
+ )
65
+ custom_path = result.stdout.strip()
66
+ if custom_path and os.path.isfile(custom_path):
67
+ template = Path(custom_path).read_text(encoding="utf-8")
68
+ return template.replace("{{AGENT_NAME}}", agent_name)
69
+ except Exception:
70
+ pass
71
+
72
+ # Plugin built-in template
73
+ builtin = Path(__file__).resolve().parent.parent / "prompts" / "summarize.txt"
74
+ if builtin.is_file():
75
+ template = builtin.read_text(encoding="utf-8")
76
+ return template.replace("{{AGENT_NAME}}", agent_name)
77
+
78
+ # Inline fallback
79
+ return (
80
+ "You are a third-person note-taker. Summarize the transcript as "
81
+ "2-6 bullet points. Write in third person. Output ONLY bullet points."
82
+ )
83
+
84
+
85
+ def summarize_with_llm(turn_text, small_model, memsearch_cmd=None):
57
86
  """Summarize using opencode run in isolated env (no plugins -> no recursion)."""
58
- # Keep the instruction short and put it AFTER the transcript to avoid
59
- # the LLM treating the instruction itself as the conversation content.
60
- # Clear delimiters (===) separate the transcript from the task.
87
+ system_prompt = _load_summarize_prompt("OpenCode", memsearch_cmd)
61
88
  full_prompt = (
62
- f"===TRANSCRIPT START===\n"
63
- f"{turn_text}\n"
64
- f"===TRANSCRIPT END===\n\n"
65
- f"Summarize the transcript above as 2-6 third-person bullet points (each starting with '- '). "
66
- f"Write 'User asked/did...' and 'OpenCode replied/did...'. "
67
- f"Be specific (file names, tools, outcomes). "
68
- f"Same language as the human. "
69
- f"Output ONLY bullet points, nothing else."
89
+ f"{system_prompt}\n\n"
90
+ f"Transcript:\n{turn_text}"
70
91
  )
71
92
  isolated_dir = ensure_isolated_config()
72
93
 
@@ -279,7 +300,7 @@ def main():
279
300
  for session_id, turn_text, msg_time in new_turns:
280
301
  if turn_text and len(turn_text) > 10:
281
302
  # Summarize with LLM, fallback to raw text
282
- summary = summarize_with_llm(turn_text, small_model)
303
+ summary = summarize_with_llm(turn_text, small_model, args.memsearch_cmd)
283
304
  write_capture(memory_dir, summary if summary else turn_text, session_id, db_path)
284
305
  if msg_time > last_msg_time:
285
306
  last_msg_time = msg_time