opencode-memoir 2.0.2 → 2.0.4

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,7 +21,7 @@ OpenCode downloads and resolves the package from npm automatically; no manual in
21
21
  ## Quick start
22
22
 
23
23
  1. Install the plugin (see above)
24
- 2. Start coding — the agent can use `memoir_recall`, `memoir_remember`, `memoir_get` MCP tools automatically
24
+ 2. Start coding — the agent can use `memoir_memoir_recall`, `memoir_memoir_remember`, `memoir_memoir_get` MCP tools automatically
25
25
 
26
26
  ## Store configuration
27
27
 
@@ -58,7 +58,7 @@ All optional:
58
58
 
59
59
  ## How it works
60
60
 
61
- Instead of wrapping the `memoir` CLI and re-implementing tools in TypeScript, this plugin registers `memoir-mcp` as a dynamic MCP server. OpenCode starts the server via `uvx --from memoir-ai[mcp] memoir-mcp`, and all memoir tools (`memoir_recall`, `memoir_remember`, `memoir_get`, etc.) are available natively to the LLM.
61
+ Instead of wrapping the `memoir` CLI and re-implementing tools in TypeScript, this plugin registers `memoir-mcp` as a dynamic MCP server. OpenCode starts the server via `uvx --from memoir-ai[mcp] memoir-mcp`, and all memoir tools (`memoir_memoir_recall`, `memoir_memoir_remember`, `memoir_memoir_get`, etc.) are available natively to the LLM.
62
62
 
63
63
  ## Development
64
64
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA4IxE,QAAA,MAAM,MAAM,EAAE,YAGb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA6IxE,QAAA,MAAM,MAAM,EAAE,YAGb,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ import { execFile, execFileSync } from "node:child_process";
26
26
  import { homedir } from "node:os";
27
27
  import { join, resolve } from "node:path";
28
28
  import { promisify } from "node:util";
29
+ var UVX_PYTHON = "3.13";
29
30
  var execFileAsync = promisify(execFile);
30
31
  function errorMessage(e) {
31
32
  return e instanceof Error ? e.message : String(e);
@@ -74,7 +75,7 @@ async function callMemoir(args, store) {
74
75
  try {
75
76
  const { stdout } = await execFileAsync(
76
77
  "uvx",
77
- ["--from", "memoir-ai", "memoir", "-s", store, ...args],
78
+ ["--python", UVX_PYTHON, "--from", "memoir-ai", "memoir", "--store", store, ...args],
78
79
  {
79
80
  encoding: "utf8",
80
81
  timeout: 15e3,
@@ -119,7 +120,7 @@ var MemoirOpenCode = async (_input, rawOptions) => {
119
120
  const opts = rawOptions ?? {};
120
121
  if (opts.store) setPluginStoreOverride(opts.store);
121
122
  const storePath = deriveStorePath();
122
- const mcpCommand = ["uvx", "--from", "memoir-ai[mcp]", "memoir-mcp"];
123
+ const mcpCommand = ["uvx", "--python", UVX_PYTHON, "--from", "memoir-ai[mcp]", "memoir-mcp"];
123
124
  if (storePath) {
124
125
  mcpCommand.push("--store", storePath);
125
126
  }
@@ -142,7 +143,7 @@ Memory rules:
142
143
  - Do not use preferences.* paths unless the user explicitly stated a preference.
143
144
  - If a fact is your interpretation, do not save it; report it as uncertain instead.
144
145
 
145
- Then call memoir_remember with replace=true for durable onboarding facts. Use namespace codebase:onboard in git repositories and project:onboard outside git.`
146
+ Then call memoir_memoir_remember with replace=true for durable onboarding facts. Use namespace codebase:onboard in git repositories and project:onboard outside git.`
146
147
  };
147
148
  const mcp = config.mcp ?? {};
148
149
  mcp.memoir = {
@@ -176,13 +177,13 @@ Then call memoir_remember with replace=true for durable onboarding facts. Use na
176
177
  if (input.sessionID && !sessionsWithStartupHint.has(sid)) {
177
178
  sessionsWithStartupHint.add(sid);
178
179
  output.system?.unshift(
179
- '[memoir] You have Memoir MCP tools (memoir_recall, memoir_remember, memoir_get, memoir_summarize, memoir_status, memoir_branches, memoir_checkout).\nSAVE (memoir_remember) after: task completion, user stating preferences/constraints, discovering project facts. RECALL (memoir_recall \u2192 memoir_get) at session start for prior context, when user asks about prior work.\nNamespaces: "default" (user context), "codebase:onboard" (project facts in git repos). Taxonomy paths: preferences.*, project.*, codebase.*, decisions.*, learning.*.'
180
+ '[memoir] You have Memoir MCP tools (memoir_memoir_recall, memoir_memoir_remember, memoir_memoir_get, memoir_memoir_summarize, memoir_memoir_status, memoir_memoir_branches, memoir_memoir_checkout).\nSAVE (memoir_memoir_remember) after: task completion, user stating preferences/constraints, discovering project facts. RECALL (memoir_memoir_recall \u2192 memoir_memoir_get) at session start for prior context, when user asks about prior work.\nNamespaces: "default" (user context), "codebase:onboard" (project facts in git repos). Taxonomy paths: preferences.*, project.*, codebase.*, decisions.*, learning.*.'
180
181
  );
181
182
  }
182
183
  const count = sessionMsgCount.get(sid) ?? 0;
183
184
  if (shouldRemind(count)) {
184
185
  output.system?.push(
185
- "\n[memoir] Reminder: Use memoir_remember to save context, memoir_recall to retrieve prior context."
186
+ "\n[memoir] Reminder: Use memoir_memoir_remember to save context, memoir_memoir_recall to retrieve prior context."
186
187
  );
187
188
  }
188
189
  } catch (e) {
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/debug.ts", "../src/memory-saver.ts", "../src/store.ts", "../src/index.ts"],
4
- "sourcesContent": ["/**\n * Debug logger writing to stderr. Prefixes with [memoir] for easy filtering.\n * Only writes when MEMOIR_DEBUG=1 is set.\n */\nexport function debugLog(...args: unknown[]): void {\n if (process.env.MEMOIR_DEBUG !== \"1\") return;\n const ts = new Date().toISOString();\n process.stderr.write(`[memoir ${ts}] ${args.map((a) => String(a)).join(\" \")}\\n`);\n}\n", "/** Per-session message count for periodic reminders. */\nexport const sessionMsgCount = new Map<string, number>();\n\nconst REMINDER_INTERVAL = Math.max(0, parseInt(process.env.MEMOIR_REMINDER_INTERVAL ?? \"5\", 10));\n\nexport function incrementMsgCount(sessionID: string): number {\n const count = (sessionMsgCount.get(sessionID) ?? 0) + 1;\n sessionMsgCount.set(sessionID, count);\n return count;\n}\n\nexport function shouldRemind(count: number): boolean {\n return REMINDER_INTERVAL > 0 && count > 1 && count % REMINDER_INTERVAL === 0;\n}\n\nexport function pruneAll(): void {\n sessionMsgCount.clear();\n}\n", "import { execFile, execFileSync } from \"node:child_process\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { debugLog } from \"./debug.js\";\n\nconst execFileAsync = promisify(execFile);\n\nfunction errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/** Resolve memoir store path.\n * 1. Plugin `store` option override\n * 2. MEMOIR_STORE env var\n * 3. Git root \u2192 `~/.memoir/<slug>` (all worktrees share one store)\n * 4. Resolved cwd \u2192 `~/.memoir/<slug>` for non-git dirs\n */\nexport function deriveStorePath(cwd = process.cwd()): string {\n if (pluginStoreOverride) return pluginStoreOverride;\n const envStore = process.env.MEMOIR_STORE;\n if (envStore) return envStore;\n\n let projectDir: string;\n try {\n const gitRoot = execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n encoding: \"utf8\",\n timeout: 3_000,\n }).trim();\n projectDir = gitRoot;\n } catch {\n projectDir = resolve(cwd);\n }\n\n const slug = projectDir.replace(/[/.]/g, \"-\");\n return join(homedir(), \".memoir\", slug);\n}\n\nexport let pluginStoreOverride: string | undefined;\n\nexport function setPluginStoreOverride(store: string | undefined): void {\n pluginStoreOverride = store;\n}\n\n/** Get current git branch (empty string if not in a git repo). */\nexport function currentGitBranch(cwd = process.cwd()): string {\n try {\n return execFileSync(\"git\", [\"branch\", \"--show-current\"], {\n cwd,\n encoding: \"utf8\",\n timeout: 3_000,\n }).trim();\n } catch {\n return \"\";\n }\n}\n\nconst branchCache = new Map<string, string>();\n\nexport function getCachedBranch(sessionID: string): string {\n return branchCache.get(sessionID) ?? \"\";\n}\n\nexport function setCachedBranch(sessionID: string, branch: string): void {\n branchCache.set(sessionID, branch);\n}\n\n/** Call the memoir CLI via uvx. */\nexport async function callMemoir(args: string[], store: string): Promise<string | null> {\n try {\n const { stdout } = (await execFileAsync(\n \"uvx\",\n [\"--from\", \"memoir-ai\", \"memoir\", \"-s\", store, ...args],\n {\n encoding: \"utf8\",\n timeout: 15_000,\n maxBuffer: 1_024 * 1_024,\n },\n )) as { stdout: string };\n return stdout.trim();\n } catch (e) {\n debugLog(\"callMemoir failed:\", errorMessage(e));\n return null;\n }\n}\n\nexport async function autoMatchMemoirBranch(store: string, sessionID: string): Promise<void> {\n const codeBranch = currentGitBranch();\n if (!codeBranch) return;\n\n const cached = getCachedBranch(sessionID);\n if (cached === codeBranch) return;\n\n // Check if branch exists in memoir\n const branchResult = await callMemoir([\"--json\", \"branch\"], store);\n if (branchResult === null) return;\n\n try {\n const data = JSON.parse(branchResult);\n const branches: string[] = data?.branches ?? [];\n if (!branches.includes(codeBranch)) {\n await callMemoir([\"branch\", codeBranch], store);\n }\n await callMemoir([\"checkout\", codeBranch], store);\n setCachedBranch(sessionID, codeBranch);\n } catch (e) {\n debugLog(\"autoMatchMemoirBranch: parsing failed:\", errorMessage(e));\n }\n}\n\nexport function pruneBranchCache(): void {\n branchCache.clear();\n}\n", "import type { Config, Plugin, PluginModule } from \"@opencode-ai/plugin\";\nimport { debugLog } from \"./debug.js\";\nimport { incrementMsgCount, pruneAll, sessionMsgCount, shouldRemind } from \"./memory-saver.js\";\nimport {\n autoMatchMemoirBranch,\n callMemoir,\n deriveStorePath,\n pruneBranchCache,\n setPluginStoreOverride,\n} from \"./store.js\";\n\nconst sessionsWithStartupHint = new Set<string>();\n\nfunction errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\nconst MemoirOpenCode: Plugin = async (_input, rawOptions) => {\n const opts = (rawOptions ?? {}) as { store?: string };\n if (opts.store) setPluginStoreOverride(opts.store);\n\n const storePath = deriveStorePath();\n\n const mcpCommand = [\"uvx\", \"--from\", \"memoir-ai[mcp]\", \"memoir-mcp\"];\n if (storePath) {\n mcpCommand.push(\"--store\", storePath);\n }\n\n const hooks: Record<string, unknown> = {\n name: \"memoir\",\n\n config: async (config: Config): Promise<void> => {\n config.command = config.command ?? {};\n config.command[\"memoir:onboard\"] = {\n description: \"Populate or refresh Memoir onboarding for this project\",\n template: `Populate or refresh Memoir onboarding for the current project.\n\nWorkflow:\n- First obtain a project file tree to understand structure.\n- Start studying from project documentation.\n- Continue only based on what the tree and documentation show.\n\nMemory rules:\n- Record only verified facts from files/docs/code or explicit user statements.\n- Do not write inferred user thoughts, intentions, preferences, or opinions.\n- Do not use preferences.* paths unless the user explicitly stated a preference.\n- If a fact is your interpretation, do not save it; report it as uncertain instead.\n\nThen call memoir_remember with replace=true for durable onboarding facts. Use namespace codebase:onboard in git repositories and project:onboard outside git.`,\n };\n\n // Register memoir MCP server\n const mcp = config.mcp ?? {};\n mcp.memoir = {\n type: \"local\" as const,\n command: mcpCommand,\n environment: storePath ? { MEMOIR_STORE: storePath } : undefined,\n };\n config.mcp = mcp;\n },\n\n \"shell.env\": async (\n _input: unknown,\n output: { env: Record<string, string> },\n ): Promise<void> => {\n try {\n if (storePath) {\n output.env.MEMOIR_STORE = storePath;\n }\n } catch (e) {\n debugLog(\"shell.env: failed:\", errorMessage(e));\n }\n },\n\n \"chat.message\": async (\n input: { sessionID?: string },\n _output: { parts?: Array<{ type: string; text: string }> },\n ): Promise<void> => {\n try {\n const sid = input.sessionID ?? \"default\";\n incrementMsgCount(sid);\n\n await autoMatchMemoirBranch(storePath, sid);\n } catch (e) {\n debugLog(\"chat.message: failed:\", errorMessage(e));\n }\n },\n\n \"experimental.chat.system.transform\": async (\n input: { sessionID?: string },\n output: { system?: string[] },\n ): Promise<void> => {\n try {\n const sid = input.sessionID ?? \"default\";\n\n if (input.sessionID && !sessionsWithStartupHint.has(sid)) {\n sessionsWithStartupHint.add(sid);\n output.system?.unshift(\n '[memoir] You have Memoir MCP tools (memoir_recall, memoir_remember, memoir_get, memoir_summarize, memoir_status, memoir_branches, memoir_checkout).\\nSAVE (memoir_remember) after: task completion, user stating preferences/constraints, discovering project facts. RECALL (memoir_recall \\u2192 memoir_get) at session start for prior context, when user asks about prior work.\\nNamespaces: \"default\" (user context), \"codebase:onboard\" (project facts in git repos). Taxonomy paths: preferences.*, project.*, codebase.*, decisions.*, learning.*.',\n );\n }\n\n const count = sessionMsgCount.get(sid) ?? 0;\n if (shouldRemind(count)) {\n output.system?.push(\n \"\\n[memoir] Reminder: Use memoir_remember to save context, memoir_recall to retrieve prior context.\",\n );\n }\n } catch (e) {\n debugLog(\"system.transform: failed:\", errorMessage(e));\n }\n },\n\n dispose: async (): Promise<void> => {\n try {\n if (process.env.MEMOIR_AUTO_SAVE === \"1\") {\n for (const [sid, count] of sessionMsgCount) {\n await callMemoir(\n [\n \"remember\",\n `session.${sid}`,\n \"--message\",\n `Session ended \u2014 ${count} user messages exchanged`,\n ],\n storePath,\n );\n }\n }\n } catch (e) {\n debugLog(\"dispose: save failed:\", errorMessage(e));\n }\n sessionsWithStartupHint.clear();\n pruneBranchCache();\n pruneAll();\n },\n };\n\n return hooks;\n};\n\nconst plugin: PluginModule = {\n id: \"opencode-memoir\",\n server: MemoirOpenCode,\n};\n\nexport default plugin;\n"],
5
- "mappings": ";AAIO,SAAS,YAAY,MAAuB;AACjD,MAAI,QAAQ,IAAI,iBAAiB,IAAK;AACtC,QAAM,MAAK,oBAAI,KAAK,GAAE,YAAY;AAClC,UAAQ,OAAO,MAAM,WAAW,EAAE,KAAK,KAAK,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC;AAAA,CAAI;AACjF;;;ACPO,IAAM,kBAAkB,oBAAI,IAAoB;AAEvD,IAAM,oBAAoB,KAAK,IAAI,GAAG,SAAS,QAAQ,IAAI,4BAA4B,KAAK,EAAE,CAAC;AAExF,SAAS,kBAAkB,WAA2B;AAC3D,QAAM,SAAS,gBAAgB,IAAI,SAAS,KAAK,KAAK;AACtD,kBAAgB,IAAI,WAAW,KAAK;AACpC,SAAO;AACT;AAEO,SAAS,aAAa,OAAwB;AACnD,SAAO,oBAAoB,KAAK,QAAQ,KAAK,QAAQ,sBAAsB;AAC7E;AAEO,SAAS,WAAiB;AAC/B,kBAAgB,MAAM;AACxB;;;ACjBA,SAAS,UAAU,oBAAoB;AACvC,SAAS,eAAe;AACxB,SAAS,MAAM,eAAe;AAC9B,SAAS,iBAAiB;AAG1B,IAAM,gBAAgB,UAAU,QAAQ;AAExC,SAAS,aAAa,GAAoB;AACxC,SAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAClD;AAQO,SAAS,gBAAgB,MAAM,QAAQ,IAAI,GAAW;AAC3D,MAAI,oBAAqB,QAAO;AAChC,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,SAAU,QAAO;AAErB,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,aAAa,OAAO,CAAC,aAAa,iBAAiB,GAAG;AAAA,MACpE;AAAA,MACA,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC,EAAE,KAAK;AACR,iBAAa;AAAA,EACf,QAAQ;AACN,iBAAa,QAAQ,GAAG;AAAA,EAC1B;AAEA,QAAM,OAAO,WAAW,QAAQ,SAAS,GAAG;AAC5C,SAAO,KAAK,QAAQ,GAAG,WAAW,IAAI;AACxC;AAEO,IAAI;AAEJ,SAAS,uBAAuB,OAAiC;AACtE,wBAAsB;AACxB;AAGO,SAAS,iBAAiB,MAAM,QAAQ,IAAI,GAAW;AAC5D,MAAI;AACF,WAAO,aAAa,OAAO,CAAC,UAAU,gBAAgB,GAAG;AAAA,MACvD;AAAA,MACA,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC,EAAE,KAAK;AAAA,EACV,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAM,cAAc,oBAAI,IAAoB;AAErC,SAAS,gBAAgB,WAA2B;AACzD,SAAO,YAAY,IAAI,SAAS,KAAK;AACvC;AAEO,SAAS,gBAAgB,WAAmB,QAAsB;AACvE,cAAY,IAAI,WAAW,MAAM;AACnC;AAGA,eAAsB,WAAW,MAAgB,OAAuC;AACtF,MAAI;AACF,UAAM,EAAE,OAAO,IAAK,MAAM;AAAA,MACxB;AAAA,MACA,CAAC,UAAU,aAAa,UAAU,MAAM,OAAO,GAAG,IAAI;AAAA,MACtD;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,WAAW,OAAQ;AAAA,MACrB;AAAA,IACF;AACA,WAAO,OAAO,KAAK;AAAA,EACrB,SAAS,GAAG;AACV,aAAS,sBAAsB,aAAa,CAAC,CAAC;AAC9C,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,sBAAsB,OAAe,WAAkC;AAC3F,QAAM,aAAa,iBAAiB;AACpC,MAAI,CAAC,WAAY;AAEjB,QAAM,SAAS,gBAAgB,SAAS;AACxC,MAAI,WAAW,WAAY;AAG3B,QAAM,eAAe,MAAM,WAAW,CAAC,UAAU,QAAQ,GAAG,KAAK;AACjE,MAAI,iBAAiB,KAAM;AAE3B,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,YAAY;AACpC,UAAM,WAAqB,MAAM,YAAY,CAAC;AAC9C,QAAI,CAAC,SAAS,SAAS,UAAU,GAAG;AAClC,YAAM,WAAW,CAAC,UAAU,UAAU,GAAG,KAAK;AAAA,IAChD;AACA,UAAM,WAAW,CAAC,YAAY,UAAU,GAAG,KAAK;AAChD,oBAAgB,WAAW,UAAU;AAAA,EACvC,SAAS,GAAG;AACV,aAAS,0CAA0C,aAAa,CAAC,CAAC;AAAA,EACpE;AACF;AAEO,SAAS,mBAAyB;AACvC,cAAY,MAAM;AACpB;;;ACtGA,IAAM,0BAA0B,oBAAI,IAAY;AAEhD,SAASA,cAAa,GAAoB;AACxC,SAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAClD;AAEA,IAAM,iBAAyB,OAAO,QAAQ,eAAe;AAC3D,QAAM,OAAQ,cAAc,CAAC;AAC7B,MAAI,KAAK,MAAO,wBAAuB,KAAK,KAAK;AAEjD,QAAM,YAAY,gBAAgB;AAElC,QAAM,aAAa,CAAC,OAAO,UAAU,kBAAkB,YAAY;AACnE,MAAI,WAAW;AACb,eAAW,KAAK,WAAW,SAAS;AAAA,EACtC;AAEA,QAAM,QAAiC;AAAA,IACrC,MAAM;AAAA,IAEN,QAAQ,OAAO,WAAkC;AAC/C,aAAO,UAAU,OAAO,WAAW,CAAC;AACpC,aAAO,QAAQ,gBAAgB,IAAI;AAAA,QACjC,aAAa;AAAA,QACb,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcZ;AAGA,YAAM,MAAM,OAAO,OAAO,CAAC;AAC3B,UAAI,SAAS;AAAA,QACX,MAAM;AAAA,QACN,SAAS;AAAA,QACT,aAAa,YAAY,EAAE,cAAc,UAAU,IAAI;AAAA,MACzD;AACA,aAAO,MAAM;AAAA,IACf;AAAA,IAEA,aAAa,OACXC,SACA,WACkB;AAClB,UAAI;AACF,YAAI,WAAW;AACb,iBAAO,IAAI,eAAe;AAAA,QAC5B;AAAA,MACF,SAAS,GAAG;AACV,iBAAS,sBAAsBD,cAAa,CAAC,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,IAEA,gBAAgB,OACd,OACA,YACkB;AAClB,UAAI;AACF,cAAM,MAAM,MAAM,aAAa;AAC/B,0BAAkB,GAAG;AAErB,cAAM,sBAAsB,WAAW,GAAG;AAAA,MAC5C,SAAS,GAAG;AACV,iBAAS,yBAAyBA,cAAa,CAAC,CAAC;AAAA,MACnD;AAAA,IACF;AAAA,IAEA,sCAAsC,OACpC,OACA,WACkB;AAClB,UAAI;AACF,cAAM,MAAM,MAAM,aAAa;AAE/B,YAAI,MAAM,aAAa,CAAC,wBAAwB,IAAI,GAAG,GAAG;AACxD,kCAAwB,IAAI,GAAG;AAC/B,iBAAO,QAAQ;AAAA,YACb;AAAA,UACF;AAAA,QACF;AAEA,cAAM,QAAQ,gBAAgB,IAAI,GAAG,KAAK;AAC1C,YAAI,aAAa,KAAK,GAAG;AACvB,iBAAO,QAAQ;AAAA,YACb;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,iBAAS,6BAA6BA,cAAa,CAAC,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,IAEA,SAAS,YAA2B;AAClC,UAAI;AACF,YAAI,QAAQ,IAAI,qBAAqB,KAAK;AACxC,qBAAW,CAAC,KAAK,KAAK,KAAK,iBAAiB;AAC1C,kBAAM;AAAA,cACJ;AAAA,gBACE;AAAA,gBACA,WAAW,GAAG;AAAA,gBACd;AAAA,gBACA,wBAAmB,KAAK;AAAA,cAC1B;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,iBAAS,yBAAyBA,cAAa,CAAC,CAAC;AAAA,MACnD;AACA,8BAAwB,MAAM;AAC9B,uBAAiB;AACjB,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,SAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,QAAQ;AACV;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["/**\n * Debug logger writing to stderr. Prefixes with [memoir] for easy filtering.\n * Only writes when MEMOIR_DEBUG=1 is set.\n */\nexport function debugLog(...args: unknown[]): void {\n if (process.env.MEMOIR_DEBUG !== \"1\") return;\n const ts = new Date().toISOString();\n process.stderr.write(`[memoir ${ts}] ${args.map((a) => String(a)).join(\" \")}\\n`);\n}\n", "/** Per-session message count for periodic reminders. */\nexport const sessionMsgCount = new Map<string, number>();\n\nconst REMINDER_INTERVAL = Math.max(0, parseInt(process.env.MEMOIR_REMINDER_INTERVAL ?? \"5\", 10));\n\nexport function incrementMsgCount(sessionID: string): number {\n const count = (sessionMsgCount.get(sessionID) ?? 0) + 1;\n sessionMsgCount.set(sessionID, count);\n return count;\n}\n\nexport function shouldRemind(count: number): boolean {\n return REMINDER_INTERVAL > 0 && count > 1 && count % REMINDER_INTERVAL === 0;\n}\n\nexport function pruneAll(): void {\n sessionMsgCount.clear();\n}\n", "import { execFile, execFileSync } from \"node:child_process\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { debugLog } from \"./debug.js\";\n\n/** Python version pinned for uvx to avoid litellm build failure on 3.14+. */\nexport const UVX_PYTHON = \"3.13\" as const;\n\nconst execFileAsync = promisify(execFile);\n\nfunction errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/** Resolve memoir store path.\n * 1. Plugin `store` option override\n * 2. MEMOIR_STORE env var\n * 3. Git root \u2192 `~/.memoir/<slug>` (all worktrees share one store)\n * 4. Resolved cwd \u2192 `~/.memoir/<slug>` for non-git dirs\n */\nexport function deriveStorePath(cwd = process.cwd()): string {\n if (pluginStoreOverride) return pluginStoreOverride;\n const envStore = process.env.MEMOIR_STORE;\n if (envStore) return envStore;\n\n let projectDir: string;\n try {\n const gitRoot = execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n encoding: \"utf8\",\n timeout: 3_000,\n }).trim();\n projectDir = gitRoot;\n } catch {\n projectDir = resolve(cwd);\n }\n\n const slug = projectDir.replace(/[/.]/g, \"-\");\n return join(homedir(), \".memoir\", slug);\n}\n\nexport let pluginStoreOverride: string | undefined;\n\nexport function setPluginStoreOverride(store: string | undefined): void {\n pluginStoreOverride = store;\n}\n\n/** Get current git branch (empty string if not in a git repo). */\nexport function currentGitBranch(cwd = process.cwd()): string {\n try {\n return execFileSync(\"git\", [\"branch\", \"--show-current\"], {\n cwd,\n encoding: \"utf8\",\n timeout: 3_000,\n }).trim();\n } catch {\n return \"\";\n }\n}\n\nconst branchCache = new Map<string, string>();\n\nexport function getCachedBranch(sessionID: string): string {\n return branchCache.get(sessionID) ?? \"\";\n}\n\nexport function setCachedBranch(sessionID: string, branch: string): void {\n branchCache.set(sessionID, branch);\n}\n\n/** Call the memoir CLI via uvx. */\nexport async function callMemoir(args: string[], store: string): Promise<string | null> {\n try {\n const { stdout } = (await execFileAsync(\n \"uvx\",\n [\"--python\", UVX_PYTHON, \"--from\", \"memoir-ai\", \"memoir\", \"--store\", store, ...args],\n {\n encoding: \"utf8\",\n timeout: 15_000,\n maxBuffer: 1_024 * 1_024,\n },\n )) as { stdout: string };\n return stdout.trim();\n } catch (e) {\n debugLog(\"callMemoir failed:\", errorMessage(e));\n return null;\n }\n}\n\nexport async function autoMatchMemoirBranch(store: string, sessionID: string): Promise<void> {\n const codeBranch = currentGitBranch();\n if (!codeBranch) return;\n\n const cached = getCachedBranch(sessionID);\n if (cached === codeBranch) return;\n\n // Check if branch exists in memoir\n const branchResult = await callMemoir([\"--json\", \"branch\"], store);\n if (branchResult === null) return;\n\n try {\n const data = JSON.parse(branchResult);\n const branches: string[] = data?.branches ?? [];\n if (!branches.includes(codeBranch)) {\n await callMemoir([\"branch\", codeBranch], store);\n }\n await callMemoir([\"checkout\", codeBranch], store);\n setCachedBranch(sessionID, codeBranch);\n } catch (e) {\n debugLog(\"autoMatchMemoirBranch: parsing failed:\", errorMessage(e));\n }\n}\n\nexport function pruneBranchCache(): void {\n branchCache.clear();\n}\n", "import type { Config, Plugin, PluginModule } from \"@opencode-ai/plugin\";\nimport { debugLog } from \"./debug.js\";\nimport { incrementMsgCount, pruneAll, sessionMsgCount, shouldRemind } from \"./memory-saver.js\";\nimport {\n autoMatchMemoirBranch,\n callMemoir,\n deriveStorePath,\n pruneBranchCache,\n setPluginStoreOverride,\n UVX_PYTHON,\n} from \"./store.js\";\n\nconst sessionsWithStartupHint = new Set<string>();\n\nfunction errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\nconst MemoirOpenCode: Plugin = async (_input, rawOptions) => {\n const opts = (rawOptions ?? {}) as { store?: string };\n if (opts.store) setPluginStoreOverride(opts.store);\n\n const storePath = deriveStorePath();\n\n const mcpCommand = [\"uvx\", \"--python\", UVX_PYTHON, \"--from\", \"memoir-ai[mcp]\", \"memoir-mcp\"];\n if (storePath) {\n mcpCommand.push(\"--store\", storePath);\n }\n\n const hooks: Record<string, unknown> = {\n name: \"memoir\",\n\n config: async (config: Config): Promise<void> => {\n config.command = config.command ?? {};\n config.command[\"memoir:onboard\"] = {\n description: \"Populate or refresh Memoir onboarding for this project\",\n template: `Populate or refresh Memoir onboarding for the current project.\n\nWorkflow:\n- First obtain a project file tree to understand structure.\n- Start studying from project documentation.\n- Continue only based on what the tree and documentation show.\n\nMemory rules:\n- Record only verified facts from files/docs/code or explicit user statements.\n- Do not write inferred user thoughts, intentions, preferences, or opinions.\n- Do not use preferences.* paths unless the user explicitly stated a preference.\n- If a fact is your interpretation, do not save it; report it as uncertain instead.\n\nThen call memoir_memoir_remember with replace=true for durable onboarding facts. Use namespace codebase:onboard in git repositories and project:onboard outside git.`,\n };\n\n // Register memoir MCP server\n const mcp = config.mcp ?? {};\n mcp.memoir = {\n type: \"local\" as const,\n command: mcpCommand,\n environment: storePath ? { MEMOIR_STORE: storePath } : undefined,\n };\n config.mcp = mcp;\n },\n\n \"shell.env\": async (\n _input: unknown,\n output: { env: Record<string, string> },\n ): Promise<void> => {\n try {\n if (storePath) {\n output.env.MEMOIR_STORE = storePath;\n }\n } catch (e) {\n debugLog(\"shell.env: failed:\", errorMessage(e));\n }\n },\n\n \"chat.message\": async (\n input: { sessionID?: string },\n _output: { parts?: Array<{ type: string; text: string }> },\n ): Promise<void> => {\n try {\n const sid = input.sessionID ?? \"default\";\n incrementMsgCount(sid);\n\n await autoMatchMemoirBranch(storePath, sid);\n } catch (e) {\n debugLog(\"chat.message: failed:\", errorMessage(e));\n }\n },\n\n \"experimental.chat.system.transform\": async (\n input: { sessionID?: string },\n output: { system?: string[] },\n ): Promise<void> => {\n try {\n const sid = input.sessionID ?? \"default\";\n\n if (input.sessionID && !sessionsWithStartupHint.has(sid)) {\n sessionsWithStartupHint.add(sid);\n output.system?.unshift(\n '[memoir] You have Memoir MCP tools (memoir_memoir_recall, memoir_memoir_remember, memoir_memoir_get, memoir_memoir_summarize, memoir_memoir_status, memoir_memoir_branches, memoir_memoir_checkout).\\nSAVE (memoir_memoir_remember) after: task completion, user stating preferences/constraints, discovering project facts. RECALL (memoir_memoir_recall \\u2192 memoir_memoir_get) at session start for prior context, when user asks about prior work.\\nNamespaces: \"default\" (user context), \"codebase:onboard\" (project facts in git repos). Taxonomy paths: preferences.*, project.*, codebase.*, decisions.*, learning.*.',\n );\n }\n\n const count = sessionMsgCount.get(sid) ?? 0;\n if (shouldRemind(count)) {\n output.system?.push(\n \"\\n[memoir] Reminder: Use memoir_memoir_remember to save context, memoir_memoir_recall to retrieve prior context.\",\n );\n }\n } catch (e) {\n debugLog(\"system.transform: failed:\", errorMessage(e));\n }\n },\n\n dispose: async (): Promise<void> => {\n try {\n if (process.env.MEMOIR_AUTO_SAVE === \"1\") {\n for (const [sid, count] of sessionMsgCount) {\n await callMemoir(\n [\n \"remember\",\n `session.${sid}`,\n \"--message\",\n `Session ended \u2014 ${count} user messages exchanged`,\n ],\n storePath,\n );\n }\n }\n } catch (e) {\n debugLog(\"dispose: save failed:\", errorMessage(e));\n }\n sessionsWithStartupHint.clear();\n pruneBranchCache();\n pruneAll();\n },\n };\n\n return hooks;\n};\n\nconst plugin: PluginModule = {\n id: \"opencode-memoir\",\n server: MemoirOpenCode,\n};\n\nexport default plugin;\n"],
5
+ "mappings": "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",
6
6
  "names": ["errorMessage", "_input"]
7
7
  }
package/dist/store.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /** Python version pinned for uvx to avoid litellm build failure on 3.14+. */
2
+ export declare const UVX_PYTHON: "3.13";
1
3
  /** Resolve memoir store path.
2
4
  * 1. Plugin `store` option override
3
5
  * 2. MEMOIR_STORE env var
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,SAAgB,GAAG,MAAM,CAmB3D;AAED,eAAO,IAAI,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;AAEnD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEtE;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,GAAG,SAAgB,GAAG,MAAM,CAU5D;AAID,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAEvE;AAED,mCAAmC;AACnC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBtF;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB3F;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAMA,6EAA6E;AAC7E,eAAO,MAAM,UAAU,EAAG,MAAe,CAAC;AAQ1C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,SAAgB,GAAG,MAAM,CAmB3D;AAED,eAAO,IAAI,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;AAEnD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEtE;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,GAAG,SAAgB,GAAG,MAAM,CAU5D;AAID,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAEvE;AAED,mCAAmC;AACnC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBtF;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB3F;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-memoir",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Memoir memory plugin for OpenCode — Git-versioned, taxonomy-structured AI memory.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",