UNPKG

open-memex

Version:

Local-first memory layer and protocol for AI coding agents. Markdown source of truth, SQLite FTS5 index, zero cloud.

44 lines (43 loc) • 2.07 kB
import { PLUGIN_ID, bootstrapPlugin, captureFromText, captureHandoff, injectOnce, } from "./plugin-core.js"; import { pickScopeRoot } from "./scope.js"; import { makeTools } from "./tools/memory.js"; import { v2Plugin } from "./opencode-v2.js"; /** * One entrypoint, both opencode generations (D60): * - OpenCode 2 structurally decodes the default export as `{ id, setup }` * and ignores `server` (see src/opencode-v2.ts). * - OpenCode 1 (≥1.18.29) reads `server` off the same default export and * ignores `setup` — the function below is the v1 plugin exactly as it * behaved before dual support. * Neither host runtime-imports an SDK package from this file: v1's SDK is * type-only (D58), and v2's decode is structural. */ const server = async ({ worktree, directory }) => { // v1's `worktree` is the filesystem root for non-git folders — never seed a // scope on it (D71). `pickScopeRoot` falls back to the opened `directory`. const state = bootstrapPlugin(pickScopeRoot(worktree, directory)); const tools = makeTools(() => state.scope, state.cfg); return { tool: tools, async "chat.message"(input, output) { const parts = (output.parts ?? []); const text = parts .map((p) => (p?.type === "text" ? p.text ?? "" : "")) .filter(Boolean) .join("\n"); captureFromText(text, state, input.sessionID ?? ""); }, async "experimental.chat.system.transform"(input, output) { const sessionID = input.sessionID ?? ""; injectOnce(sessionID, state, (block) => { output.system.push(block); }); // D73: runs on every request, so the note lands on the very turn whose // message the hook just captured. Delivered once per capture. const handoff = captureHandoff(sessionID, state); if (handoff) output.system.push(handoff); }, }; }; export default { id: PLUGIN_ID, setup: v2Plugin.setup, server };