Created
April 11, 2026 14:58
-
-
Save mariodian/69bca1c1a80d40d60b7833ccbc19466d to your computer and use it in GitHub Desktop.
Mempalace Auto Save Plugin for OpenCode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| - Mempalace Auto Save Plugin for OpenCode | |
| - | |
| - Installation: | |
| - Manually copy this file to ~/.config/opencode/plugins/ | |
| */ | |
| import type { Hooks, Plugin } from "@opencode-ai/plugin"; | |
| import type { Event } from "@opencode-ai/sdk"; | |
| const SAVE_INTERVAL = 5; // Save every N user messages | |
| interface TranscriptEntry { | |
| role: "user" | "assistant"; | |
| text: string; | |
| timestamp: number; | |
| } | |
| export const MempalaceSave: Plugin = async ({ | |
| $, | |
| directory, | |
| }): Promise<Hooks> => { | |
| let userMessageCount = 0; | |
| let entries: TranscriptEntry[] = []; | |
| let saving = false; | |
| const messageRoles = new Map<string, "user" | "assistant">(); | |
| const seenMessageIds = new Set<string>(); | |
| async function flush(): Promise<void> { | |
| if (entries.length === 0 || saving) return; | |
| saving = true; | |
| const transcript = entries.map((e) => `[${e.role}] ${e.text}`).join("\n\n"); | |
| const tmpFile = `${directory}/.mempalace_autosave_${Date.now()}.txt`; | |
| try { | |
| const { writeFileSync } = await import("node:fs"); | |
| writeFileSync(tmpFile, transcript, "utf-8"); | |
| await $`bash -c 'mempalace mine ${tmpFile} --mode convos >/dev/null 2>&1'`; | |
| await $`rm -f ${tmpFile}`; | |
| } catch { | |
| try { | |
| await $`rm -f ${tmpFile}`.nothrow(); | |
| } catch { | |
| // ignore cleanup errors | |
| } | |
| } | |
| entries = []; | |
| userMessageCount = 0; | |
| saving = false; | |
| } | |
| return { | |
| event: async ({ event }: { event: Event }): Promise<void> => { | |
| if (event.type === "message.updated") { | |
| const info = event.properties.info as | |
| | { id: string; role: "user" | "assistant" } | |
| | undefined; | |
| if (info?.id && info?.role) { | |
| messageRoles.set(info.id, info.role); | |
| } | |
| } | |
| if (event.type === "message.part.updated") { | |
| const part = event.properties.part as { | |
| messageID?: string; | |
| type: string; | |
| text?: string; | |
| }; | |
| const messageId = part.messageID ?? ""; | |
| if (!messageId) return; | |
| if (seenMessageIds.has(messageId)) return; | |
| if (part.type === "text" && part.text?.trim()) { | |
| const role = messageRoles.get(messageId); | |
| if (role) { | |
| seenMessageIds.add(messageId); | |
| entries.push({ role, text: part.text, timestamp: Date.now() }); | |
| if (role === "user") { | |
| userMessageCount++; | |
| if (userMessageCount >= SAVE_INTERVAL) { | |
| await flush(); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (event.type === "session.end" && entries.length > 0) { | |
| await flush(); | |
| } | |
| }, | |
| }; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment