@super-pocock-ai/memory-core 2.0.0 → 2.0.5
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/dist/index.js +61 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -3
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
});
|
|
44
44
|
module.exports = __toCommonJS(index_exports);
|
|
45
45
|
var import_fs7 = require("fs");
|
|
46
|
-
var
|
|
46
|
+
var import_path7 = require("path");
|
|
47
47
|
|
|
48
48
|
// src/tool.ts
|
|
49
49
|
var import_plugin = require("@opencode-ai/plugin");
|
|
@@ -297,16 +297,23 @@ function getProjectMemoryDir(projectRoot) {
|
|
|
297
297
|
function getGlobalMemoryDir(projectRoot) {
|
|
298
298
|
return (0, import_path3.join)(getMemoryRoot(projectRoot), "global");
|
|
299
299
|
}
|
|
300
|
+
function getSessionMemoryDir(projectRoot, sessionId) {
|
|
301
|
+
return (0, import_path3.join)(getMemoryRoot(projectRoot), "sessions", sessionId);
|
|
302
|
+
}
|
|
300
303
|
function getDbPath(projectRoot) {
|
|
301
304
|
return (0, import_path3.join)(getMemoryRoot(projectRoot), "memory.db");
|
|
302
305
|
}
|
|
303
306
|
|
|
304
307
|
// src/checkpoint-plugin.ts
|
|
305
308
|
var import_fs4 = require("fs");
|
|
309
|
+
var import_path4 = require("path");
|
|
306
310
|
var CheckpointPlugin = async ({ client, directory }) => {
|
|
307
311
|
const config = loadConfig(directory);
|
|
308
|
-
const
|
|
309
|
-
|
|
312
|
+
const memoryRoot = getMemoryRoot(directory);
|
|
313
|
+
const projectDir = getProjectMemoryDir(directory);
|
|
314
|
+
(0, import_fs4.mkdirSync)(memoryRoot, { recursive: true });
|
|
315
|
+
(0, import_fs4.mkdirSync)((0, import_path4.join)(memoryRoot, "sessions"), { recursive: true });
|
|
316
|
+
(0, import_fs4.mkdirSync)(projectDir, { recursive: true });
|
|
310
317
|
let lastCheckpointRatio = 0;
|
|
311
318
|
const THRESHOLDS = config.memory.checkpoint.thresholds.map((t) => parseFloat(t) / 100);
|
|
312
319
|
return {
|
|
@@ -347,6 +354,8 @@ Extract and preserve these 11 fields:
|
|
|
347
354
|
async function triggerCheckpoint(client, sessionID, directory) {
|
|
348
355
|
const messages = await client.session.messages({ path: { id: sessionID } });
|
|
349
356
|
const context = constructCheckpointContext(messages);
|
|
357
|
+
const sessionDir = getSessionMemoryDir(directory, sessionID);
|
|
358
|
+
(0, import_fs4.mkdirSync)(sessionDir, { recursive: true });
|
|
350
359
|
await client.session.prompt({
|
|
351
360
|
path: { id: sessionID },
|
|
352
361
|
body: {
|
|
@@ -354,7 +363,11 @@ async function triggerCheckpoint(client, sessionID, directory) {
|
|
|
354
363
|
parts: [{
|
|
355
364
|
type: "text",
|
|
356
365
|
text: `Extract checkpoint from this context:
|
|
357
|
-
${context}
|
|
366
|
+
${context}
|
|
367
|
+
|
|
368
|
+
Write checkpoint to:
|
|
369
|
+
- Session: .super-pocock/memory/sessions/${sessionID}/checkpoint.md
|
|
370
|
+
- Project: .super-pocock/memory/projects/<pid>/checkpoint.md`
|
|
358
371
|
}]
|
|
359
372
|
}
|
|
360
373
|
});
|
|
@@ -365,26 +378,55 @@ function constructCheckpointContext(messages) {
|
|
|
365
378
|
|
|
366
379
|
// src/injection-plugin.ts
|
|
367
380
|
var import_fs5 = require("fs");
|
|
368
|
-
var
|
|
381
|
+
var import_path5 = require("path");
|
|
369
382
|
var MemoryInjectionPlugin = async ({ directory }) => {
|
|
370
383
|
const config = loadConfig(directory);
|
|
371
384
|
const memoryCache = /* @__PURE__ */ new Map();
|
|
372
|
-
function
|
|
385
|
+
function getLatestSessionId() {
|
|
386
|
+
const sessionsDir = (0, import_path5.join)(getMemoryRoot(directory), "sessions");
|
|
387
|
+
if (!(0, import_fs5.existsSync)(sessionsDir)) return null;
|
|
388
|
+
const sessions = (0, import_fs5.readdirSync)(sessionsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
389
|
+
if (sessions.length === 0) return null;
|
|
390
|
+
let latestSession = sessions[0];
|
|
391
|
+
let latestTime = 0;
|
|
392
|
+
for (const session of sessions) {
|
|
393
|
+
const sessionPath = (0, import_path5.join)(sessionsDir, session);
|
|
394
|
+
const stat = require("fs").statSync(sessionPath);
|
|
395
|
+
if (stat.mtimeMs > latestTime) {
|
|
396
|
+
latestTime = stat.mtimeMs;
|
|
397
|
+
latestSession = session;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return latestSession;
|
|
401
|
+
}
|
|
402
|
+
function loadMemoryFiles(sessionId) {
|
|
373
403
|
const projectDir = getProjectMemoryDir(directory);
|
|
374
404
|
const globalDir = getGlobalMemoryDir(directory);
|
|
405
|
+
const memoryRoot = getMemoryRoot(directory);
|
|
375
406
|
const memories = {};
|
|
376
407
|
const files = [
|
|
377
|
-
{ key: "
|
|
378
|
-
{ key: "
|
|
379
|
-
{ key: "
|
|
380
|
-
{ key: "
|
|
381
|
-
{ key: "global_memory", path: (0, import_path4.join)(globalDir, "MEMORY.md") }
|
|
408
|
+
{ key: "memory", path: (0, import_path5.join)(projectDir, "MEMORY.md") },
|
|
409
|
+
{ key: "notes", path: (0, import_path5.join)(projectDir, "notes.md") },
|
|
410
|
+
{ key: "progress", path: (0, import_path5.join)(projectDir, "tasks", "progress.md") },
|
|
411
|
+
{ key: "global_memory", path: (0, import_path5.join)(globalDir, "MEMORY.md") }
|
|
382
412
|
];
|
|
383
413
|
for (const file of files) {
|
|
384
414
|
if ((0, import_fs5.existsSync)(file.path)) {
|
|
385
415
|
memories[file.key] = (0, import_fs5.readFileSync)(file.path, "utf-8");
|
|
386
416
|
}
|
|
387
417
|
}
|
|
418
|
+
if (sessionId) {
|
|
419
|
+
const sessionCheckpoint = (0, import_path5.join)(memoryRoot, "sessions", sessionId, "checkpoint.md");
|
|
420
|
+
if ((0, import_fs5.existsSync)(sessionCheckpoint)) {
|
|
421
|
+
memories.checkpoint = (0, import_fs5.readFileSync)(sessionCheckpoint, "utf-8");
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (!memories.checkpoint) {
|
|
425
|
+
const projectCheckpoint = (0, import_path5.join)(projectDir, "checkpoint.md");
|
|
426
|
+
if ((0, import_fs5.existsSync)(projectCheckpoint)) {
|
|
427
|
+
memories.checkpoint = (0, import_fs5.readFileSync)(projectCheckpoint, "utf-8");
|
|
428
|
+
}
|
|
429
|
+
}
|
|
388
430
|
return memories;
|
|
389
431
|
}
|
|
390
432
|
function estimateTokens(text) {
|
|
@@ -429,7 +471,8 @@ ${smartTruncate(memories.progress, budget.progress)}`);
|
|
|
429
471
|
return {
|
|
430
472
|
event: async ({ event }) => {
|
|
431
473
|
if (event.type === "session.created") {
|
|
432
|
-
const
|
|
474
|
+
const latestSessionId = getLatestSessionId();
|
|
475
|
+
const memories = loadMemoryFiles(latestSessionId);
|
|
433
476
|
memoryCache.set(event.properties.sessionID, memories);
|
|
434
477
|
}
|
|
435
478
|
},
|
|
@@ -470,13 +513,13 @@ ${criticalMemory.join("\n\n")}`);
|
|
|
470
513
|
|
|
471
514
|
// src/dream-plugin.ts
|
|
472
515
|
var import_fs6 = require("fs");
|
|
473
|
-
var
|
|
516
|
+
var import_path6 = require("path");
|
|
474
517
|
var DreamPlugin = async ({ client, directory }) => {
|
|
475
518
|
const config = loadConfig(directory);
|
|
476
519
|
const memoryDir = getProjectMemoryDir(directory);
|
|
477
520
|
(0, import_fs6.mkdirSync)(memoryDir, { recursive: true });
|
|
478
521
|
function getLastTimestamp(metaFile) {
|
|
479
|
-
const metaPath = (0,
|
|
522
|
+
const metaPath = (0, import_path6.join)(memoryDir, metaFile);
|
|
480
523
|
if ((0, import_fs6.existsSync)(metaPath)) {
|
|
481
524
|
const meta = JSON.parse((0, import_fs6.readFileSync)(metaPath, "utf-8"));
|
|
482
525
|
return meta.timestamp ?? 0;
|
|
@@ -484,7 +527,7 @@ var DreamPlugin = async ({ client, directory }) => {
|
|
|
484
527
|
return 0;
|
|
485
528
|
}
|
|
486
529
|
function setLastTimestamp(metaFile) {
|
|
487
|
-
const metaPath = (0,
|
|
530
|
+
const metaPath = (0, import_path6.join)(memoryDir, metaFile);
|
|
488
531
|
(0, import_fs6.writeFileSync)(metaPath, JSON.stringify({ timestamp: Date.now() }));
|
|
489
532
|
}
|
|
490
533
|
function shouldAutoRun(metaFile, intervalDays) {
|
|
@@ -532,9 +575,9 @@ var MemoryCorePlugin = async (ctx) => {
|
|
|
532
575
|
const memoryRoot = getMemoryRoot(ctx.directory);
|
|
533
576
|
const projectDir = getProjectMemoryDir(ctx.directory);
|
|
534
577
|
const globalDir = getGlobalMemoryDir(ctx.directory);
|
|
535
|
-
(0, import_fs7.mkdirSync)((0,
|
|
536
|
-
(0, import_fs7.mkdirSync)((0,
|
|
537
|
-
(0, import_fs7.mkdirSync)((0,
|
|
578
|
+
(0, import_fs7.mkdirSync)((0, import_path7.join)(memoryRoot, "global"), { recursive: true });
|
|
579
|
+
(0, import_fs7.mkdirSync)((0, import_path7.join)(projectDir, "sessions"), { recursive: true });
|
|
580
|
+
(0, import_fs7.mkdirSync)((0, import_path7.join)(projectDir, "tasks"), { recursive: true });
|
|
538
581
|
const memoryTool = createMemoryTool({
|
|
539
582
|
memoryDir: memoryRoot,
|
|
540
583
|
dbPath: getDbPath(ctx.directory)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/tool.ts","../src/store.ts","../src/reconcile.ts","../src/config.ts","../src/paths.ts","../src/checkpoint-plugin.ts","../src/injection-plugin.ts","../src/dream-plugin.ts"],"sourcesContent":["import type { Plugin } from \"@opencode-ai/plugin\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\nimport { createMemoryTool } from \"./tool\"\nimport { CheckpointPlugin } from \"./checkpoint-plugin\"\nimport { MemoryInjectionPlugin } from \"./injection-plugin\"\nimport { DreamPlugin } from \"./dream-plugin\"\nimport { getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir, getDbPath } from \"./paths\"\nimport { ensureConfig } from \"./config\"\n\nexport const MemoryCorePlugin: Plugin = async (ctx) => {\n // 确保配置文件存在\n ensureConfig(ctx.directory)\n\n const memoryRoot = getMemoryRoot(ctx.directory)\n const projectDir = getProjectMemoryDir(ctx.directory)\n const globalDir = getGlobalMemoryDir(ctx.directory)\n\n // 创建目录结构\n mkdirSync(join(memoryRoot, \"global\"), { recursive: true })\n mkdirSync(join(projectDir, \"sessions\"), { recursive: true })\n mkdirSync(join(projectDir, \"tasks\"), { recursive: true })\n\n // 创建 memory 工具\n const memoryTool = createMemoryTool({\n memoryDir: memoryRoot,\n dbPath: getDbPath(ctx.directory),\n })\n\n // 初始化子插件\n const checkpointPlugin = await CheckpointPlugin(ctx)\n const injectionPlugin = await MemoryInjectionPlugin(ctx)\n const dreamPlugin = await DreamPlugin(ctx)\n\n return {\n tool: {\n memory: memoryTool,\n },\n event: async (input) => {\n await checkpointPlugin.event?.(input)\n await injectionPlugin.event?.(input)\n await dreamPlugin.event?.(input)\n },\n \"experimental.chat.system.transform\": async (input, output) => {\n await injectionPlugin[\"experimental.chat.system.transform\"]?.(input, output)\n },\n \"experimental.session.compacting\": async (input, output) => {\n await checkpointPlugin[\"experimental.session.compacting\"]?.(input, output)\n await injectionPlugin[\"experimental.session.compacting\"]?.(input, output)\n },\n }\n}\n\nexport default MemoryCorePlugin\n\n// 导出子模块\nexport { MemoryStore } from \"./store\"\nexport { createMemoryTool } from \"./tool\"\nexport { resolveProjectId, getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir } from \"./paths\"\nexport { loadConfig, DEFAULT_CONFIG } from \"./config\"\nexport type { MemoryConfig } from \"./config\"\nexport type { SearchResult, SearchFilters } from \"./store\"\n","import { tool } from \"@opencode-ai/plugin\"\nimport { z } from \"zod\"\nimport { MemoryStore } from \"./store\"\nimport { reconcileMemoryDir } from \"./reconcile\"\nimport { mkdirSync } from \"fs\"\n\nexport function createMemoryTool(ctx: { memoryDir: string; dbPath: string }) {\n let store: MemoryStore | null = null\n\n function ensureStore() {\n if (!store) {\n mkdirSync(ctx.memoryDir, { recursive: true })\n store = new MemoryStore(ctx.dbPath)\n reconcileMemoryDir(store, ctx.memoryDir)\n }\n return store\n }\n\n return tool({\n description: \"Search or write to the persistent memory store. Search returns ranked results across memory files. Write saves content to a memory file.\",\n args: {\n operation: z.enum([\"search\", \"write\", \"list\", \"forget\"]),\n query: z.string().optional(),\n scope: z.string().optional(),\n scope_id: z.string().optional(),\n type: z.string().optional(),\n limit: z.number().optional(),\n path: z.string().optional(),\n content: z.string().optional(),\n memory_id: z.string().optional(),\n },\n execute(args: any) {\n const s = ensureStore()\n\n if (args.operation === \"search\") {\n if (!args.query) return \"query is required for search\"\n const results = s.search(args.query, {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit,\n })\n if (results.length === 0) return \"No results found\"\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"write\") {\n if (!args.path) return \"path is required for write\"\n if (!args.content) return \"content is required for write\"\n s.write(\n args.path,\n args.scope ?? \"unknown\",\n args.scope_id ?? \"\",\n args.type ?? \"snapshot\",\n args.content,\n )\n return `Wrote to ${args.path}`\n }\n\n if (args.operation === \"list\") {\n const results = s.search(\"*\", {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit ?? 50,\n })\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"forget\") {\n if (!args.memory_id) return \"memory_id is required for forget\"\n s.forget(args.memory_id)\n return `Forgot ${args.memory_id}`\n }\n\n return \"Invalid operation\"\n },\n })\n}\n","import Database from \"better-sqlite3\"\n\nexport interface SearchFilters {\n scope?: string\n scope_id?: string\n type?: string\n limit?: number\n}\n\nexport interface SearchResult {\n path: string\n scope: string\n scope_id: string\n type: string\n snippet: string\n score: number\n}\n\nexport class MemoryStore {\n public db: Database.Database\n\n constructor(dbPath: string) {\n this.db = new Database(dbPath)\n this.db.pragma(\"journal_mode = WAL\")\n this.init()\n }\n\n private init() {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memory_files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT NOT NULL UNIQUE,\n scope TEXT NOT NULL,\n scope_id TEXT NOT NULL DEFAULT '',\n type TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n last_indexed_at INTEGER NOT NULL\n )\n `)\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts\n USING fts5(path, body, tokenize='unicode61')\n `)\n }\n\n search(query: string, filters: SearchFilters = {}): SearchResult[] {\n const tokens = query.split(/\\s+/).filter(Boolean).map(t => `\"${t}\"`)\n if (tokens.length === 0) return []\n const ftsQuery = tokens.join(\" OR \")\n const limit = filters.limit ?? 10\n\n let sql = `\n SELECT f.path, m.scope, m.scope_id, m.type,\n snippet(memory_fts, 1, '<<', '>>', '...', 32) AS snippet,\n bm25(memory_fts) AS score\n FROM memory_fts f\n JOIN memory_files m ON m.path = f.path\n WHERE memory_fts MATCH ?\n `\n const params: any[] = [ftsQuery]\n if (filters.scope) { sql += ` AND m.scope = ?`; params.push(filters.scope) }\n if (filters.scope_id) { sql += ` AND m.scope_id = ?`; params.push(filters.scope_id) }\n if (filters.type) { sql += ` AND m.type = ?`; params.push(filters.type) }\n sql += ` ORDER BY score LIMIT ?`\n params.push(limit)\n return this.db.prepare(sql).all(...params) as SearchResult[]\n }\n\n write(path: string, scope: string, scope_id: string, type: string, content: string) {\n const fingerprint = `${content.length}-${Date.now()}`\n const now = Date.now()\n\n this.db.prepare(`\n INSERT OR REPLACE INTO memory_files (path, scope, scope_id, type, fingerprint, last_indexed_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `).run(path, scope, scope_id, type, fingerprint, now)\n\n this.db.prepare(`DELETE FROM memory_fts WHERE path = ?`).run(path)\n this.db.prepare(`INSERT INTO memory_fts (path, body) VALUES (?, ?)`).run(path, content)\n }\n\n forget(memoryId: string) {\n this.db.prepare(\"DELETE FROM memory_files WHERE path = ?\").run(memoryId)\n this.db.prepare(\"DELETE FROM memory_fts WHERE path = ?\").run(memoryId)\n }\n\n close() {\n this.db.close()\n }\n}\n","import { readdirSync, readFileSync } from \"fs\"\nimport { join, relative, sep } from \"path\"\nimport type { MemoryStore } from \"./store\"\n\nfunction parseScopeAndId(memoryRoot: string, filePath: string): { scope: string; scope_id: string } {\n const rel = relative(memoryRoot, filePath).split(sep)\n if (rel[0] === \"global\") return { scope: \"global\", scope_id: \"\" }\n if (rel[0] === \"projects\" && rel.length >= 3) return { scope: \"projects\", scope_id: rel[1] }\n if (rel[0] === \"sessions\" && rel.length >= 3) return { scope: \"sessions\", scope_id: rel[1] }\n return { scope: \"unknown\", scope_id: \"\" }\n}\n\nfunction walkMdFiles(dir: string): string[] {\n const results: string[] = []\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...walkMdFiles(full))\n } else if (entry.name.endsWith(\".md\")) {\n results.push(full)\n }\n }\n return results\n}\n\nexport function reconcileMemoryDir(store: MemoryStore, memoryRoot: string) {\n const filesOnDisk = walkMdFiles(memoryRoot)\n const diskPaths = new Set<string>()\n\n for (const file of filesOnDisk) {\n diskPaths.add(file)\n const content = readFileSync(file, \"utf-8\")\n const { scope, scope_id } = parseScopeAndId(memoryRoot, file)\n store.write(file, scope, scope_id, \"snapshot\", content)\n }\n\n const indexed = store.db.prepare(\"SELECT path FROM memory_files\").all() as { path: string }[]\n for (const row of indexed) {\n if (!diskPaths.has(row.path)) {\n store.forget(row.path)\n }\n }\n}\n","import { readFileSync, existsSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join, dirname } from \"path\"\n\nexport interface MemoryConfig {\n memory: {\n injection: {\n total_budget: number\n allocation: {\n checkpoint: number\n memory: number\n notes: number\n progress: number\n buffer: number\n }\n }\n checkpoint: {\n thresholds: string[]\n drain_timeout_ms: number\n idle_timeout_ms: number\n }\n dream: {\n auto: boolean\n interval_days: number\n }\n distill: {\n auto: boolean\n interval_days: number\n }\n }\n}\n\nexport const DEFAULT_CONFIG: MemoryConfig = {\n memory: {\n injection: {\n total_budget: 2000,\n allocation: {\n checkpoint: 0.30,\n memory: 0.25,\n notes: 0.20,\n progress: 0.15,\n buffer: 0.10\n }\n },\n checkpoint: {\n thresholds: [\"40%\", \"60%\", \"80%\"],\n drain_timeout_ms: 120000,\n idle_timeout_ms: 300000\n },\n dream: {\n auto: true,\n interval_days: 7\n },\n distill: {\n auto: true,\n interval_days: 30\n }\n }\n}\n\nexport function getConfigPath(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"config.json\")\n}\n\nexport function loadConfig(projectRoot: string): MemoryConfig {\n const configPath = getConfigPath(projectRoot)\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, \"utf-8\")\n return { ...DEFAULT_CONFIG, ...JSON.parse(content) }\n }\n return DEFAULT_CONFIG\n}\n\nexport function ensureConfig(projectRoot: string): void {\n const configPath = getConfigPath(projectRoot)\n if (!existsSync(configPath)) {\n mkdirSync(dirname(configPath), { recursive: true })\n writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2))\n }\n}\n","import { createHash } from \"crypto\"\nimport { join } from \"path\"\n\nexport type Scope = \"global\" | \"projects\" | \"sessions\"\n\nexport function resolveProjectId(absRepoPath: string): string {\n return createHash(\"sha256\").update(absRepoPath).digest(\"hex\").slice(0, 12)\n}\n\nexport function getMemoryRoot(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"memory\")\n}\n\nexport function getProjectMemoryDir(projectRoot: string): string {\n const projectId = resolveProjectId(projectRoot)\n return join(getMemoryRoot(projectRoot), \"projects\", projectId)\n}\n\nexport function getGlobalMemoryDir(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"global\")\n}\n\nexport function getSessionMemoryDir(projectRoot: string, sessionId: string): string {\n return join(getProjectMemoryDir(projectRoot), \"sessions\", sessionId)\n}\n\nexport function getDbPath(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"memory.db\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir } from \"./paths\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const CheckpointPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryDir = getProjectMemoryDir(directory)\n mkdirSync(memoryDir, { recursive: true })\n\n let lastCheckpointRatio = 0\n const THRESHOLDS = config.memory.checkpoint.thresholds.map(t => parseFloat(t) / 100)\n\n return {\n event: async ({ event }) => {\n // 触发 1: Token 比例阈值\n if (event.type === \"session.next.step.ended\") {\n const ratio = event.properties.tokens / event.properties.contextLimit\n const nextThreshold = THRESHOLDS.find(t => t > lastCheckpointRatio)\n if (nextThreshold && ratio >= nextThreshold) {\n lastCheckpointRatio = ratio\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }\n }\n\n // 触发 2: 会话结束(idle 超时)\n if (event.type === \"session.status\" && event.properties?.status?.type === \"idle\") {\n setTimeout(async () => {\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }, config.memory.checkpoint.idle_timeout_ms)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n output.context.push(`\n## Checkpoint Instructions\nExtract and preserve these 11 fields:\n1. Intent (用户的核心目标)\n2. Actions (已执行的操作)\n3. Task Tree (子任务层级)\n4. Errors & Workarounds (遇到的问题及解决)\n5. Design Decisions (关键技术选择)\n6. Constraints (限制条件)\n7. Current State (任务进度)\n8. TODOs (剩余工作)\n9. Code Changes Summary (Git diff 概要)\n10. Key File Paths (涉及的核心文件)\n11. Timestamp (检查点创建时间)\n `)\n },\n }\n}\n\nasync function triggerCheckpoint(client: any, sessionID: string, directory: string) {\n const messages = await client.session.messages({ path: { id: sessionID } })\n const context = constructCheckpointContext(messages)\n\n await client.session.prompt({\n path: { id: sessionID },\n body: {\n agent: \"checkpoint-writer\",\n parts: [{\n type: \"text\",\n text: `Extract checkpoint from this context:\\n${context}`\n }],\n },\n })\n}\n\nfunction constructCheckpointContext(messages: any[]): string {\n return messages.map(m => `[${m.role}]: ${m.content}`).join(\"\\n\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir, getGlobalMemoryDir } from \"./paths\"\nimport { existsSync, readFileSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const MemoryInjectionPlugin: Plugin = async ({ directory }) => {\n const config = loadConfig(directory)\n const memoryCache = new Map<string, Record<string, string>>()\n\n function loadMemoryFiles() {\n const projectDir = getProjectMemoryDir(directory)\n const globalDir = getGlobalMemoryDir(directory)\n\n const memories: Record<string, string> = {}\n\n const files = [\n { key: \"checkpoint\", path: join(projectDir, \"checkpoint.md\") },\n { key: \"memory\", path: join(projectDir, \"MEMORY.md\") },\n { key: \"notes\", path: join(projectDir, \"notes.md\") },\n { key: \"progress\", path: join(projectDir, \"tasks\", \"progress.md\") },\n { key: \"global_memory\", path: join(globalDir, \"MEMORY.md\") },\n ]\n\n for (const file of files) {\n if (existsSync(file.path)) {\n memories[file.key] = readFileSync(file.path, \"utf-8\")\n }\n }\n\n return memories\n }\n\n function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n }\n\n function smartTruncate(text: string, maxTokens: number): string {\n const estimatedTokens = estimateTokens(text)\n if (estimatedTokens <= maxTokens) return text\n\n const keepChars = maxTokens * 4 * 0.3\n const start = text.substring(0, keepChars)\n const end = text.substring(text.length - keepChars)\n\n return `${start}\\n\\n... [记忆已压缩,原 ${estimatedTokens} tokens] ...\\n\\n${end}`\n }\n\n function formatMemory(memories: Record<string, string>, budget: Record<string, number>): string {\n const sections = []\n\n if (memories.checkpoint && budget.checkpoint > 0) {\n sections.push(`## 检查点状态\\n${smartTruncate(memories.checkpoint, budget.checkpoint)}`)\n }\n if (memories.memory && budget.memory > 0) {\n sections.push(`## 项目记忆\\n${smartTruncate(memories.memory, budget.memory)}`)\n }\n if (memories.global_memory && budget.memory > 0) {\n sections.push(`## 全局记忆\\n${smartTruncate(memories.global_memory, budget.memory * 0.5)}`)\n }\n if (memories.notes && budget.notes > 0) {\n sections.push(`## 当前笔记\\n${smartTruncate(memories.notes, budget.notes)}`)\n }\n if (memories.progress && budget.progress > 0) {\n sections.push(`## 任务进度\\n${smartTruncate(memories.progress, budget.progress)}`)\n }\n\n return sections.join(\"\\n\\n\")\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n const memories = loadMemoryFiles()\n memoryCache.set(event.properties.sessionID, memories)\n }\n },\n\n \"experimental.chat.system.transform\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const totalBudget = config.memory.injection.total_budget\n const allocation = config.memory.injection.allocation\n\n const budget = {\n checkpoint: Math.floor(totalBudget * allocation.checkpoint),\n memory: Math.floor(totalBudget * allocation.memory),\n notes: Math.floor(totalBudget * allocation.notes),\n progress: Math.floor(totalBudget * allocation.progress),\n }\n\n const memoryContext = formatMemory(memories, budget)\n\n if (memoryContext) {\n output.system.push(`\\n\\n# Injected Memory Context\\n${memoryContext}`)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const criticalMemory = []\n if (memories.checkpoint) {\n criticalMemory.push(`当前检查点: ${memories.checkpoint.substring(0, 500)}`)\n }\n if (memories.progress) {\n criticalMemory.push(`任务进度摘要: ${memories.progress.substring(0, 300)}`)\n }\n\n output.context.push(`## 保留的关键记忆\\n${criticalMemory.join(\"\\n\\n\")}`)\n },\n }\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir } from \"./paths\"\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const DreamPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryDir = getProjectMemoryDir(directory)\n mkdirSync(memoryDir, { recursive: true })\n\n function getLastTimestamp(metaFile: string): number {\n const metaPath = join(memoryDir, metaFile)\n if (existsSync(metaPath)) {\n const meta = JSON.parse(readFileSync(metaPath, \"utf-8\"))\n return meta.timestamp ?? 0\n }\n return 0\n }\n\n function setLastTimestamp(metaFile: string) {\n const metaPath = join(memoryDir, metaFile)\n writeFileSync(metaPath, JSON.stringify({ timestamp: Date.now() }))\n }\n\n function shouldAutoRun(metaFile: string, intervalDays: number): boolean {\n const lastRun = getLastTimestamp(metaFile)\n const intervalMs = intervalDays * 24 * 60 * 60 * 1000\n return Date.now() - lastRun > intervalMs\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n // 自动触发 dream\n if (config.memory.dream.auto && shouldAutoRun(\".dream-meta.json\", config.memory.dream.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"dream\",\n parts: [{\n type: \"text\",\n text: \"Run automatic dream memory consolidation pass.\"\n }],\n },\n })\n setLastTimestamp(\".dream-meta.json\")\n }\n\n // 自动触发 distill\n if (config.memory.distill.auto && shouldAutoRun(\".distill-meta.json\", config.memory.distill.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"distill\",\n parts: [{\n type: \"text\",\n text: \"Run automatic distill pass.\"\n }],\n },\n })\n setLastTimestamp(\".distill-meta.json\")\n }\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,IAAAA,aAA0B;AAC1B,IAAAC,eAAqB;;;ACFrB,oBAAqB;AACrB,iBAAkB;;;ACDlB,4BAAqB;AAkBd,IAAM,cAAN,MAAkB;AAAA,EAChB;AAAA,EAEP,YAAY,QAAgB;AAC1B,SAAK,KAAK,IAAI,sBAAAC,QAAS,MAAM;AAC7B,SAAK,GAAG,OAAO,oBAAoB;AACnC,SAAK,KAAK;AAAA,EACZ;AAAA,EAEQ,OAAO;AACb,SAAK,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAUZ;AACD,SAAK,GAAG,KAAK;AAAA;AAAA;AAAA,KAGZ;AAAA,EACH;AAAA,EAEA,OAAO,OAAe,UAAyB,CAAC,GAAmB;AACjE,UAAM,SAAS,MAAM,MAAM,KAAK,EAAE,OAAO,OAAO,EAAE,IAAI,OAAK,IAAI,CAAC,GAAG;AACnE,QAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AACjC,UAAM,WAAW,OAAO,KAAK,MAAM;AACnC,UAAM,QAAQ,QAAQ,SAAS;AAE/B,QAAI,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQV,UAAM,SAAgB,CAAC,QAAQ;AAC/B,QAAI,QAAQ,OAAO;AAAE,aAAO;AAAoB,aAAO,KAAK,QAAQ,KAAK;AAAA,IAAE;AAC3E,QAAI,QAAQ,UAAU;AAAE,aAAO;AAAuB,aAAO,KAAK,QAAQ,QAAQ;AAAA,IAAE;AACpF,QAAI,QAAQ,MAAM;AAAE,aAAO;AAAmB,aAAO,KAAK,QAAQ,IAAI;AAAA,IAAE;AACxE,WAAO;AACP,WAAO,KAAK,KAAK;AACjB,WAAO,KAAK,GAAG,QAAQ,GAAG,EAAE,IAAI,GAAG,MAAM;AAAA,EAC3C;AAAA,EAEA,MAAM,MAAc,OAAe,UAAkB,MAAc,SAAiB;AAClF,UAAM,cAAc,GAAG,QAAQ,MAAM,IAAI,KAAK,IAAI,CAAC;AACnD,UAAM,MAAM,KAAK,IAAI;AAErB,SAAK,GAAG,QAAQ;AAAA;AAAA;AAAA,KAGf,EAAE,IAAI,MAAM,OAAO,UAAU,MAAM,aAAa,GAAG;AAEpD,SAAK,GAAG,QAAQ,uCAAuC,EAAE,IAAI,IAAI;AACjE,SAAK,GAAG,QAAQ,mDAAmD,EAAE,IAAI,MAAM,OAAO;AAAA,EACxF;AAAA,EAEA,OAAO,UAAkB;AACvB,SAAK,GAAG,QAAQ,yCAAyC,EAAE,IAAI,QAAQ;AACvE,SAAK,GAAG,QAAQ,uCAAuC,EAAE,IAAI,QAAQ;AAAA,EACvE;AAAA,EAEA,QAAQ;AACN,SAAK,GAAG,MAAM;AAAA,EAChB;AACF;;;ACzFA,gBAA0C;AAC1C,kBAAoC;AAGpC,SAAS,gBAAgB,YAAoB,UAAuD;AAClG,QAAM,UAAM,sBAAS,YAAY,QAAQ,EAAE,MAAM,eAAG;AACpD,MAAI,IAAI,CAAC,MAAM,SAAU,QAAO,EAAE,OAAO,UAAU,UAAU,GAAG;AAChE,MAAI,IAAI,CAAC,MAAM,cAAc,IAAI,UAAU,EAAG,QAAO,EAAE,OAAO,YAAY,UAAU,IAAI,CAAC,EAAE;AAC3F,MAAI,IAAI,CAAC,MAAM,cAAc,IAAI,UAAU,EAAG,QAAO,EAAE,OAAO,YAAY,UAAU,IAAI,CAAC,EAAE;AAC3F,SAAO,EAAE,OAAO,WAAW,UAAU,GAAG;AAC1C;AAEA,SAAS,YAAY,KAAuB;AAC1C,QAAM,UAAoB,CAAC;AAC3B,aAAW,aAAS,uBAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,UAAM,WAAO,kBAAK,KAAK,MAAM,IAAI;AACjC,QAAI,MAAM,YAAY,GAAG;AACvB,cAAQ,KAAK,GAAG,YAAY,IAAI,CAAC;AAAA,IACnC,WAAW,MAAM,KAAK,SAAS,KAAK,GAAG;AACrC,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,OAAoB,YAAoB;AACzE,QAAM,cAAc,YAAY,UAAU;AAC1C,QAAM,YAAY,oBAAI,IAAY;AAElC,aAAW,QAAQ,aAAa;AAC9B,cAAU,IAAI,IAAI;AAClB,UAAM,cAAU,wBAAa,MAAM,OAAO;AAC1C,UAAM,EAAE,OAAO,SAAS,IAAI,gBAAgB,YAAY,IAAI;AAC5D,UAAM,MAAM,MAAM,OAAO,UAAU,YAAY,OAAO;AAAA,EACxD;AAEA,QAAM,UAAU,MAAM,GAAG,QAAQ,+BAA+B,EAAE,IAAI;AACtE,aAAW,OAAO,SAAS;AACzB,QAAI,CAAC,UAAU,IAAI,IAAI,IAAI,GAAG;AAC5B,YAAM,OAAO,IAAI,IAAI;AAAA,IACvB;AAAA,EACF;AACF;;;AFtCA,IAAAC,aAA0B;AAEnB,SAAS,iBAAiB,KAA4C;AAC3E,MAAI,QAA4B;AAEhC,WAAS,cAAc;AACrB,QAAI,CAAC,OAAO;AACV,gCAAU,IAAI,WAAW,EAAE,WAAW,KAAK,CAAC;AAC5C,cAAQ,IAAI,YAAY,IAAI,MAAM;AAClC,yBAAmB,OAAO,IAAI,SAAS;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AAEA,aAAO,oBAAK;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,MACJ,WAAW,aAAE,KAAK,CAAC,UAAU,SAAS,QAAQ,QAAQ,CAAC;AAAA,MACvD,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,UAAU,aAAE,OAAO,EAAE,SAAS;AAAA,MAC9B,MAAM,aAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,MAAM,aAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,MAC7B,WAAW,aAAE,OAAO,EAAE,SAAS;AAAA,IACjC;AAAA,IACA,QAAQ,MAAW;AACjB,YAAM,IAAI,YAAY;AAEtB,UAAI,KAAK,cAAc,UAAU;AAC/B,YAAI,CAAC,KAAK,MAAO,QAAO;AACxB,cAAM,UAAU,EAAE,OAAO,KAAK,OAAO;AAAA,UACnC,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,QACd,CAAC;AACD,YAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,eAAO,KAAK,UAAU,SAAS,MAAM,CAAC;AAAA,MACxC;AAEA,UAAI,KAAK,cAAc,SAAS;AAC9B,YAAI,CAAC,KAAK,KAAM,QAAO;AACvB,YAAI,CAAC,KAAK,QAAS,QAAO;AAC1B,UAAE;AAAA,UACA,KAAK;AAAA,UACL,KAAK,SAAS;AAAA,UACd,KAAK,YAAY;AAAA,UACjB,KAAK,QAAQ;AAAA,UACb,KAAK;AAAA,QACP;AACA,eAAO,YAAY,KAAK,IAAI;AAAA,MAC9B;AAEA,UAAI,KAAK,cAAc,QAAQ;AAC7B,cAAM,UAAU,EAAE,OAAO,KAAK;AAAA,UAC5B,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX,OAAO,KAAK,SAAS;AAAA,QACvB,CAAC;AACD,eAAO,KAAK,UAAU,SAAS,MAAM,CAAC;AAAA,MACxC;AAEA,UAAI,KAAK,cAAc,UAAU;AAC/B,YAAI,CAAC,KAAK,UAAW,QAAO;AAC5B,UAAE,OAAO,KAAK,SAAS;AACvB,eAAO,UAAU,KAAK,SAAS;AAAA,MACjC;AAEA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;;;AG9EA,IAAAC,aAAmE;AACnE,IAAAC,eAA8B;AA8BvB,IAAM,iBAA+B;AAAA,EAC1C,QAAQ;AAAA,IACN,WAAW;AAAA,MACT,cAAc;AAAA,MACd,YAAY;AAAA,QACV,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAU;AAAA,QACV,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,YAAY,CAAC,OAAO,OAAO,KAAK;AAAA,MAChC,kBAAkB;AAAA,MAClB,iBAAiB;AAAA,IACnB;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,eAAe;AAAA,IACjB;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,eAAe;AAAA,IACjB;AAAA,EACF;AACF;AAEO,SAAS,cAAc,aAA6B;AACzD,aAAO,mBAAK,aAAa,iBAAiB,aAAa;AACzD;AAEO,SAAS,WAAW,aAAmC;AAC5D,QAAM,aAAa,cAAc,WAAW;AAC5C,UAAI,uBAAW,UAAU,GAAG;AAC1B,UAAM,cAAU,yBAAa,YAAY,OAAO;AAChD,WAAO,EAAE,GAAG,gBAAgB,GAAG,KAAK,MAAM,OAAO,EAAE;AAAA,EACrD;AACA,SAAO;AACT;AAEO,SAAS,aAAa,aAA2B;AACtD,QAAM,aAAa,cAAc,WAAW;AAC5C,MAAI,KAAC,uBAAW,UAAU,GAAG;AAC3B,kCAAU,sBAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,kCAAc,YAAY,KAAK,UAAU,gBAAgB,MAAM,CAAC,CAAC;AAAA,EACnE;AACF;;;AC9EA,oBAA2B;AAC3B,IAAAC,eAAqB;AAId,SAAS,iBAAiB,aAA6B;AAC5D,aAAO,0BAAW,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC3E;AAEO,SAAS,cAAc,aAA6B;AACzD,aAAO,mBAAK,aAAa,iBAAiB,QAAQ;AACpD;AAEO,SAAS,oBAAoB,aAA6B;AAC/D,QAAM,YAAY,iBAAiB,WAAW;AAC9C,aAAO,mBAAK,cAAc,WAAW,GAAG,YAAY,SAAS;AAC/D;AAEO,SAAS,mBAAmB,aAA6B;AAC9D,aAAO,mBAAK,cAAc,WAAW,GAAG,QAAQ;AAClD;AAMO,SAAS,UAAU,aAA6B;AACrD,aAAO,mBAAK,cAAc,WAAW,GAAG,WAAW;AACrD;;;ACzBA,IAAAC,aAA0B;AAGnB,IAAM,mBAA2B,OAAO,EAAE,QAAQ,UAAU,MAAM;AACvE,QAAM,SAAS,WAAW,SAAS;AACnC,QAAM,YAAY,oBAAoB,SAAS;AAC/C,4BAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAExC,MAAI,sBAAsB;AAC1B,QAAM,aAAa,OAAO,OAAO,WAAW,WAAW,IAAI,OAAK,WAAW,CAAC,IAAI,GAAG;AAEnF,SAAO;AAAA,IACL,OAAO,OAAO,EAAE,MAAM,MAAM;AAE1B,UAAI,MAAM,SAAS,2BAA2B;AAC5C,cAAM,QAAQ,MAAM,WAAW,SAAS,MAAM,WAAW;AACzD,cAAM,gBAAgB,WAAW,KAAK,OAAK,IAAI,mBAAmB;AAClE,YAAI,iBAAiB,SAAS,eAAe;AAC3C,gCAAsB;AACtB,gBAAM,kBAAkB,QAAQ,MAAM,WAAW,WAAW,SAAS;AAAA,QACvE;AAAA,MACF;AAGA,UAAI,MAAM,SAAS,oBAAoB,MAAM,YAAY,QAAQ,SAAS,QAAQ;AAChF,mBAAW,YAAY;AACrB,gBAAM,kBAAkB,QAAQ,MAAM,WAAW,WAAW,SAAS;AAAA,QACvE,GAAG,OAAO,OAAO,WAAW,eAAe;AAAA,MAC7C;AAAA,IACF;AAAA,IAEA,mCAAmC,OAAO,OAAO,WAAW;AAC1D,aAAO,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAcnB;AAAA,IACH;AAAA,EACF;AACF;AAEA,eAAe,kBAAkB,QAAa,WAAmB,WAAmB;AAClF,QAAM,WAAW,MAAM,OAAO,QAAQ,SAAS,EAAE,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;AAC1E,QAAM,UAAU,2BAA2B,QAAQ;AAEnD,QAAM,OAAO,QAAQ,OAAO;AAAA,IAC1B,MAAM,EAAE,IAAI,UAAU;AAAA,IACtB,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,OAAO,CAAC;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,EAA0C,OAAO;AAAA,MACzD,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAEA,SAAS,2BAA2B,UAAyB;AAC3D,SAAO,SAAS,IAAI,OAAK,IAAI,EAAE,IAAI,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACjE;;;ACrEA,IAAAC,aAAyC;AACzC,IAAAC,eAAqB;AAEd,IAAM,wBAAgC,OAAO,EAAE,UAAU,MAAM;AACpE,QAAM,SAAS,WAAW,SAAS;AACnC,QAAM,cAAc,oBAAI,IAAoC;AAE5D,WAAS,kBAAkB;AACzB,UAAM,aAAa,oBAAoB,SAAS;AAChD,UAAM,YAAY,mBAAmB,SAAS;AAE9C,UAAM,WAAmC,CAAC;AAE1C,UAAM,QAAQ;AAAA,MACZ,EAAE,KAAK,cAAc,UAAM,mBAAK,YAAY,eAAe,EAAE;AAAA,MAC7D,EAAE,KAAK,UAAU,UAAM,mBAAK,YAAY,WAAW,EAAE;AAAA,MACrD,EAAE,KAAK,SAAS,UAAM,mBAAK,YAAY,UAAU,EAAE;AAAA,MACnD,EAAE,KAAK,YAAY,UAAM,mBAAK,YAAY,SAAS,aAAa,EAAE;AAAA,MAClE,EAAE,KAAK,iBAAiB,UAAM,mBAAK,WAAW,WAAW,EAAE;AAAA,IAC7D;AAEA,eAAW,QAAQ,OAAO;AACxB,cAAI,uBAAW,KAAK,IAAI,GAAG;AACzB,iBAAS,KAAK,GAAG,QAAI,yBAAa,KAAK,MAAM,OAAO;AAAA,MACtD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,eAAe,MAAsB;AAC5C,WAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAAA,EAClC;AAEA,WAAS,cAAc,MAAc,WAA2B;AAC9D,UAAM,kBAAkB,eAAe,IAAI;AAC3C,QAAI,mBAAmB,UAAW,QAAO;AAEzC,UAAM,YAAY,YAAY,IAAI;AAClC,UAAM,QAAQ,KAAK,UAAU,GAAG,SAAS;AACzC,UAAM,MAAM,KAAK,UAAU,KAAK,SAAS,SAAS;AAElD,WAAO,GAAG,KAAK;AAAA;AAAA,kDAAoB,eAAe;AAAA;AAAA,EAAmB,GAAG;AAAA,EAC1E;AAEA,WAAS,aAAa,UAAkC,QAAwC;AAC9F,UAAM,WAAW,CAAC;AAElB,QAAI,SAAS,cAAc,OAAO,aAAa,GAAG;AAChD,eAAS,KAAK;AAAA,EAAa,cAAc,SAAS,YAAY,OAAO,UAAU,CAAC,EAAE;AAAA,IACpF;AACA,QAAI,SAAS,UAAU,OAAO,SAAS,GAAG;AACxC,eAAS,KAAK;AAAA,EAAY,cAAc,SAAS,QAAQ,OAAO,MAAM,CAAC,EAAE;AAAA,IAC3E;AACA,QAAI,SAAS,iBAAiB,OAAO,SAAS,GAAG;AAC/C,eAAS,KAAK;AAAA,EAAY,cAAc,SAAS,eAAe,OAAO,SAAS,GAAG,CAAC,EAAE;AAAA,IACxF;AACA,QAAI,SAAS,SAAS,OAAO,QAAQ,GAAG;AACtC,eAAS,KAAK;AAAA,EAAY,cAAc,SAAS,OAAO,OAAO,KAAK,CAAC,EAAE;AAAA,IACzE;AACA,QAAI,SAAS,YAAY,OAAO,WAAW,GAAG;AAC5C,eAAS,KAAK;AAAA,EAAY,cAAc,SAAS,UAAU,OAAO,QAAQ,CAAC,EAAE;AAAA,IAC/E;AAEA,WAAO,SAAS,KAAK,MAAM;AAAA,EAC7B;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,EAAE,MAAM,MAAM;AAC1B,UAAI,MAAM,SAAS,mBAAmB;AACpC,cAAM,WAAW,gBAAgB;AACjC,oBAAY,IAAI,MAAM,WAAW,WAAW,QAAQ;AAAA,MACtD;AAAA,IACF;AAAA,IAEA,sCAAsC,OAAO,OAAO,WAAW;AAC7D,YAAM,WAAW,YAAY,IAAI,MAAM,SAAS;AAChD,UAAI,CAAC,SAAU;AAEf,YAAM,cAAc,OAAO,OAAO,UAAU;AAC5C,YAAM,aAAa,OAAO,OAAO,UAAU;AAE3C,YAAM,SAAS;AAAA,QACb,YAAY,KAAK,MAAM,cAAc,WAAW,UAAU;AAAA,QAC1D,QAAQ,KAAK,MAAM,cAAc,WAAW,MAAM;AAAA,QAClD,OAAO,KAAK,MAAM,cAAc,WAAW,KAAK;AAAA,QAChD,UAAU,KAAK,MAAM,cAAc,WAAW,QAAQ;AAAA,MACxD;AAEA,YAAM,gBAAgB,aAAa,UAAU,MAAM;AAEnD,UAAI,eAAe;AACjB,eAAO,OAAO,KAAK;AAAA;AAAA;AAAA,EAAkC,aAAa,EAAE;AAAA,MACtE;AAAA,IACF;AAAA,IAEA,mCAAmC,OAAO,OAAO,WAAW;AAC1D,YAAM,WAAW,YAAY,IAAI,MAAM,SAAS;AAChD,UAAI,CAAC,SAAU;AAEf,YAAM,iBAAiB,CAAC;AACxB,UAAI,SAAS,YAAY;AACvB,uBAAe,KAAK,mCAAU,SAAS,WAAW,UAAU,GAAG,GAAG,CAAC,EAAE;AAAA,MACvE;AACA,UAAI,SAAS,UAAU;AACrB,uBAAe,KAAK,yCAAW,SAAS,SAAS,UAAU,GAAG,GAAG,CAAC,EAAE;AAAA,MACtE;AAEA,aAAO,QAAQ,KAAK;AAAA,EAAe,eAAe,KAAK,MAAM,CAAC,EAAE;AAAA,IAClE;AAAA,EACF;AACF;;;AC/GA,IAAAC,aAAmE;AACnE,IAAAC,eAAqB;AAEd,IAAM,cAAsB,OAAO,EAAE,QAAQ,UAAU,MAAM;AAClE,QAAM,SAAS,WAAW,SAAS;AACnC,QAAM,YAAY,oBAAoB,SAAS;AAC/C,4BAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAExC,WAAS,iBAAiB,UAA0B;AAClD,UAAM,eAAW,mBAAK,WAAW,QAAQ;AACzC,YAAI,uBAAW,QAAQ,GAAG;AACxB,YAAM,OAAO,KAAK,UAAM,yBAAa,UAAU,OAAO,CAAC;AACvD,aAAO,KAAK,aAAa;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAEA,WAAS,iBAAiB,UAAkB;AAC1C,UAAM,eAAW,mBAAK,WAAW,QAAQ;AACzC,kCAAc,UAAU,KAAK,UAAU,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC,CAAC;AAAA,EACnE;AAEA,WAAS,cAAc,UAAkB,cAA+B;AACtE,UAAM,UAAU,iBAAiB,QAAQ;AACzC,UAAM,aAAa,eAAe,KAAK,KAAK,KAAK;AACjD,WAAO,KAAK,IAAI,IAAI,UAAU;AAAA,EAChC;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,EAAE,MAAM,MAAM;AAC1B,UAAI,MAAM,SAAS,mBAAmB;AAEpC,YAAI,OAAO,OAAO,MAAM,QAAQ,cAAc,oBAAoB,OAAO,OAAO,MAAM,aAAa,GAAG;AACpG,gBAAM,OAAO,QAAQ,OAAO;AAAA,YAC1B,MAAM,EAAE,IAAI,MAAM,WAAW,UAAU;AAAA,YACvC,MAAM;AAAA,cACJ,OAAO;AAAA,cACP,OAAO,CAAC;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF,CAAC;AACD,2BAAiB,kBAAkB;AAAA,QACrC;AAGA,YAAI,OAAO,OAAO,QAAQ,QAAQ,cAAc,sBAAsB,OAAO,OAAO,QAAQ,aAAa,GAAG;AAC1G,gBAAM,OAAO,QAAQ,OAAO;AAAA,YAC1B,MAAM,EAAE,IAAI,MAAM,WAAW,UAAU;AAAA,YACvC,MAAM;AAAA,cACJ,OAAO;AAAA,cACP,OAAO,CAAC;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF,CAAC;AACD,2BAAiB,oBAAoB;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ARxDO,IAAM,mBAA2B,OAAO,QAAQ;AAErD,eAAa,IAAI,SAAS;AAE1B,QAAM,aAAa,cAAc,IAAI,SAAS;AAC9C,QAAM,aAAa,oBAAoB,IAAI,SAAS;AACpD,QAAM,YAAY,mBAAmB,IAAI,SAAS;AAGlD,gCAAU,mBAAK,YAAY,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,gCAAU,mBAAK,YAAY,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAC3D,gCAAU,mBAAK,YAAY,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAGxD,QAAM,aAAa,iBAAiB;AAAA,IAClC,WAAW;AAAA,IACX,QAAQ,UAAU,IAAI,SAAS;AAAA,EACjC,CAAC;AAGD,QAAM,mBAAmB,MAAM,iBAAiB,GAAG;AACnD,QAAM,kBAAkB,MAAM,sBAAsB,GAAG;AACvD,QAAM,cAAc,MAAM,YAAY,GAAG;AAEzC,SAAO;AAAA,IACL,MAAM;AAAA,MACJ,QAAQ;AAAA,IACV;AAAA,IACA,OAAO,OAAO,UAAU;AACtB,YAAM,iBAAiB,QAAQ,KAAK;AACpC,YAAM,gBAAgB,QAAQ,KAAK;AACnC,YAAM,YAAY,QAAQ,KAAK;AAAA,IACjC;AAAA,IACA,sCAAsC,OAAO,OAAO,WAAW;AAC7D,YAAM,gBAAgB,oCAAoC,IAAI,OAAO,MAAM;AAAA,IAC7E;AAAA,IACA,mCAAmC,OAAO,OAAO,WAAW;AAC1D,YAAM,iBAAiB,iCAAiC,IAAI,OAAO,MAAM;AACzE,YAAM,gBAAgB,iCAAiC,IAAI,OAAO,MAAM;AAAA,IAC1E;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;","names":["import_fs","import_path","Database","import_fs","import_fs","import_path","import_path","import_fs","import_fs","import_path","import_fs","import_path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/tool.ts","../src/store.ts","../src/reconcile.ts","../src/config.ts","../src/paths.ts","../src/checkpoint-plugin.ts","../src/injection-plugin.ts","../src/dream-plugin.ts"],"sourcesContent":["import type { Plugin } from \"@opencode-ai/plugin\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\nimport { createMemoryTool } from \"./tool\"\nimport { CheckpointPlugin } from \"./checkpoint-plugin\"\nimport { MemoryInjectionPlugin } from \"./injection-plugin\"\nimport { DreamPlugin } from \"./dream-plugin\"\nimport { getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir, getDbPath } from \"./paths\"\nimport { ensureConfig } from \"./config\"\n\nexport const MemoryCorePlugin: Plugin = async (ctx) => {\n // 确保配置文件存在\n ensureConfig(ctx.directory)\n\n const memoryRoot = getMemoryRoot(ctx.directory)\n const projectDir = getProjectMemoryDir(ctx.directory)\n const globalDir = getGlobalMemoryDir(ctx.directory)\n\n // 创建目录结构\n mkdirSync(join(memoryRoot, \"global\"), { recursive: true })\n mkdirSync(join(projectDir, \"sessions\"), { recursive: true })\n mkdirSync(join(projectDir, \"tasks\"), { recursive: true })\n\n // 创建 memory 工具\n const memoryTool = createMemoryTool({\n memoryDir: memoryRoot,\n dbPath: getDbPath(ctx.directory),\n })\n\n // 初始化子插件\n const checkpointPlugin = await CheckpointPlugin(ctx)\n const injectionPlugin = await MemoryInjectionPlugin(ctx)\n const dreamPlugin = await DreamPlugin(ctx)\n\n return {\n tool: {\n memory: memoryTool,\n },\n event: async (input) => {\n await checkpointPlugin.event?.(input)\n await injectionPlugin.event?.(input)\n await dreamPlugin.event?.(input)\n },\n \"experimental.chat.system.transform\": async (input, output) => {\n await injectionPlugin[\"experimental.chat.system.transform\"]?.(input, output)\n },\n \"experimental.session.compacting\": async (input, output) => {\n await checkpointPlugin[\"experimental.session.compacting\"]?.(input, output)\n await injectionPlugin[\"experimental.session.compacting\"]?.(input, output)\n },\n }\n}\n\nexport default MemoryCorePlugin\n\n// 导出子模块\nexport { MemoryStore } from \"./store\"\nexport { createMemoryTool } from \"./tool\"\nexport { resolveProjectId, getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir } from \"./paths\"\nexport { loadConfig, DEFAULT_CONFIG } from \"./config\"\nexport type { MemoryConfig } from \"./config\"\nexport type { SearchResult, SearchFilters } from \"./store\"\n","import { tool } from \"@opencode-ai/plugin\"\nimport { z } from \"zod\"\nimport { MemoryStore } from \"./store\"\nimport { reconcileMemoryDir } from \"./reconcile\"\nimport { mkdirSync } from \"fs\"\n\nexport function createMemoryTool(ctx: { memoryDir: string; dbPath: string }) {\n let store: MemoryStore | null = null\n\n function ensureStore() {\n if (!store) {\n mkdirSync(ctx.memoryDir, { recursive: true })\n store = new MemoryStore(ctx.dbPath)\n reconcileMemoryDir(store, ctx.memoryDir)\n }\n return store\n }\n\n return tool({\n description: \"Search or write to the persistent memory store. Search returns ranked results across memory files. Write saves content to a memory file.\",\n args: {\n operation: z.enum([\"search\", \"write\", \"list\", \"forget\"]),\n query: z.string().optional(),\n scope: z.string().optional(),\n scope_id: z.string().optional(),\n type: z.string().optional(),\n limit: z.number().optional(),\n path: z.string().optional(),\n content: z.string().optional(),\n memory_id: z.string().optional(),\n },\n execute(args: any) {\n const s = ensureStore()\n\n if (args.operation === \"search\") {\n if (!args.query) return \"query is required for search\"\n const results = s.search(args.query, {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit,\n })\n if (results.length === 0) return \"No results found\"\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"write\") {\n if (!args.path) return \"path is required for write\"\n if (!args.content) return \"content is required for write\"\n s.write(\n args.path,\n args.scope ?? \"unknown\",\n args.scope_id ?? \"\",\n args.type ?? \"snapshot\",\n args.content,\n )\n return `Wrote to ${args.path}`\n }\n\n if (args.operation === \"list\") {\n const results = s.search(\"*\", {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit ?? 50,\n })\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"forget\") {\n if (!args.memory_id) return \"memory_id is required for forget\"\n s.forget(args.memory_id)\n return `Forgot ${args.memory_id}`\n }\n\n return \"Invalid operation\"\n },\n })\n}\n","import Database from \"better-sqlite3\"\n\nexport interface SearchFilters {\n scope?: string\n scope_id?: string\n type?: string\n limit?: number\n}\n\nexport interface SearchResult {\n path: string\n scope: string\n scope_id: string\n type: string\n snippet: string\n score: number\n}\n\nexport class MemoryStore {\n public db: Database.Database\n\n constructor(dbPath: string) {\n this.db = new Database(dbPath)\n this.db.pragma(\"journal_mode = WAL\")\n this.init()\n }\n\n private init() {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memory_files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT NOT NULL UNIQUE,\n scope TEXT NOT NULL,\n scope_id TEXT NOT NULL DEFAULT '',\n type TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n last_indexed_at INTEGER NOT NULL\n )\n `)\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts\n USING fts5(path, body, tokenize='unicode61')\n `)\n }\n\n search(query: string, filters: SearchFilters = {}): SearchResult[] {\n const tokens = query.split(/\\s+/).filter(Boolean).map(t => `\"${t}\"`)\n if (tokens.length === 0) return []\n const ftsQuery = tokens.join(\" OR \")\n const limit = filters.limit ?? 10\n\n let sql = `\n SELECT f.path, m.scope, m.scope_id, m.type,\n snippet(memory_fts, 1, '<<', '>>', '...', 32) AS snippet,\n bm25(memory_fts) AS score\n FROM memory_fts f\n JOIN memory_files m ON m.path = f.path\n WHERE memory_fts MATCH ?\n `\n const params: any[] = [ftsQuery]\n if (filters.scope) { sql += ` AND m.scope = ?`; params.push(filters.scope) }\n if (filters.scope_id) { sql += ` AND m.scope_id = ?`; params.push(filters.scope_id) }\n if (filters.type) { sql += ` AND m.type = ?`; params.push(filters.type) }\n sql += ` ORDER BY score LIMIT ?`\n params.push(limit)\n return this.db.prepare(sql).all(...params) as SearchResult[]\n }\n\n write(path: string, scope: string, scope_id: string, type: string, content: string) {\n const fingerprint = `${content.length}-${Date.now()}`\n const now = Date.now()\n\n this.db.prepare(`\n INSERT OR REPLACE INTO memory_files (path, scope, scope_id, type, fingerprint, last_indexed_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `).run(path, scope, scope_id, type, fingerprint, now)\n\n this.db.prepare(`DELETE FROM memory_fts WHERE path = ?`).run(path)\n this.db.prepare(`INSERT INTO memory_fts (path, body) VALUES (?, ?)`).run(path, content)\n }\n\n forget(memoryId: string) {\n this.db.prepare(\"DELETE FROM memory_files WHERE path = ?\").run(memoryId)\n this.db.prepare(\"DELETE FROM memory_fts WHERE path = ?\").run(memoryId)\n }\n\n close() {\n this.db.close()\n }\n}\n","import { readdirSync, readFileSync } from \"fs\"\nimport { join, relative, sep } from \"path\"\nimport type { MemoryStore } from \"./store\"\n\nfunction parseScopeAndId(memoryRoot: string, filePath: string): { scope: string; scope_id: string } {\n const rel = relative(memoryRoot, filePath).split(sep)\n if (rel[0] === \"global\") return { scope: \"global\", scope_id: \"\" }\n if (rel[0] === \"projects\" && rel.length >= 3) return { scope: \"projects\", scope_id: rel[1] }\n if (rel[0] === \"sessions\" && rel.length >= 3) return { scope: \"sessions\", scope_id: rel[1] }\n return { scope: \"unknown\", scope_id: \"\" }\n}\n\nfunction walkMdFiles(dir: string): string[] {\n const results: string[] = []\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...walkMdFiles(full))\n } else if (entry.name.endsWith(\".md\")) {\n results.push(full)\n }\n }\n return results\n}\n\nexport function reconcileMemoryDir(store: MemoryStore, memoryRoot: string) {\n const filesOnDisk = walkMdFiles(memoryRoot)\n const diskPaths = new Set<string>()\n\n for (const file of filesOnDisk) {\n diskPaths.add(file)\n const content = readFileSync(file, \"utf-8\")\n const { scope, scope_id } = parseScopeAndId(memoryRoot, file)\n store.write(file, scope, scope_id, \"snapshot\", content)\n }\n\n const indexed = store.db.prepare(\"SELECT path FROM memory_files\").all() as { path: string }[]\n for (const row of indexed) {\n if (!diskPaths.has(row.path)) {\n store.forget(row.path)\n }\n }\n}\n","import { readFileSync, existsSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join, dirname } from \"path\"\n\nexport interface MemoryConfig {\n memory: {\n injection: {\n total_budget: number\n allocation: {\n checkpoint: number\n memory: number\n notes: number\n progress: number\n buffer: number\n }\n }\n checkpoint: {\n thresholds: string[]\n drain_timeout_ms: number\n idle_timeout_ms: number\n }\n dream: {\n auto: boolean\n interval_days: number\n }\n distill: {\n auto: boolean\n interval_days: number\n }\n }\n}\n\nexport const DEFAULT_CONFIG: MemoryConfig = {\n memory: {\n injection: {\n total_budget: 2000,\n allocation: {\n checkpoint: 0.30,\n memory: 0.25,\n notes: 0.20,\n progress: 0.15,\n buffer: 0.10\n }\n },\n checkpoint: {\n thresholds: [\"40%\", \"60%\", \"80%\"],\n drain_timeout_ms: 120000,\n idle_timeout_ms: 300000\n },\n dream: {\n auto: true,\n interval_days: 7\n },\n distill: {\n auto: true,\n interval_days: 30\n }\n }\n}\n\nexport function getConfigPath(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"config.json\")\n}\n\nexport function loadConfig(projectRoot: string): MemoryConfig {\n const configPath = getConfigPath(projectRoot)\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, \"utf-8\")\n return { ...DEFAULT_CONFIG, ...JSON.parse(content) }\n }\n return DEFAULT_CONFIG\n}\n\nexport function ensureConfig(projectRoot: string): void {\n const configPath = getConfigPath(projectRoot)\n if (!existsSync(configPath)) {\n mkdirSync(dirname(configPath), { recursive: true })\n writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2))\n }\n}\n","import { createHash } from \"crypto\"\nimport { join } from \"path\"\n\nexport type Scope = \"global\" | \"projects\" | \"sessions\"\n\nexport function resolveProjectId(absRepoPath: string): string {\n return createHash(\"sha256\").update(absRepoPath).digest(\"hex\").slice(0, 12)\n}\n\nexport function getMemoryRoot(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"memory\")\n}\n\nexport function getProjectMemoryDir(projectRoot: string): string {\n const projectId = resolveProjectId(projectRoot)\n return join(getMemoryRoot(projectRoot), \"projects\", projectId)\n}\n\nexport function getGlobalMemoryDir(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"global\")\n}\n\nexport function getSessionMemoryDir(projectRoot: string, sessionId: string): string {\n return join(getMemoryRoot(projectRoot), \"sessions\", sessionId)\n}\n\nexport function getDbPath(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"memory.db\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir, getSessionMemoryDir, getMemoryRoot } from \"./paths\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const CheckpointPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryRoot = getMemoryRoot(directory)\n const projectDir = getProjectMemoryDir(directory)\n \n // 创建必要的目录\n mkdirSync(memoryRoot, { recursive: true })\n mkdirSync(join(memoryRoot, \"sessions\"), { recursive: true })\n mkdirSync(projectDir, { recursive: true })\n\n let lastCheckpointRatio = 0\n const THRESHOLDS = config.memory.checkpoint.thresholds.map(t => parseFloat(t) / 100)\n\n return {\n event: async ({ event }) => {\n // 触发 1: Token 比例阈值\n if (event.type === \"session.next.step.ended\") {\n const ratio = event.properties.tokens / event.properties.contextLimit\n const nextThreshold = THRESHOLDS.find(t => t > lastCheckpointRatio)\n if (nextThreshold && ratio >= nextThreshold) {\n lastCheckpointRatio = ratio\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }\n }\n\n // 触发 2: 会话结束(idle 超时)\n if (event.type === \"session.status\" && event.properties?.status?.type === \"idle\") {\n setTimeout(async () => {\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }, config.memory.checkpoint.idle_timeout_ms)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n output.context.push(`\n## Checkpoint Instructions\nExtract and preserve these 11 fields:\n1. Intent (用户的核心目标)\n2. Actions (已执行的操作)\n3. Task Tree (子任务层级)\n4. Errors & Workarounds (遇到的问题及解决)\n5. Design Decisions (关键技术选择)\n6. Constraints (限制条件)\n7. Current State (任务进度)\n8. TODOs (剩余工作)\n9. Code Changes Summary (Git diff 概要)\n10. Key File Paths (涉及的核心文件)\n11. Timestamp (检查点创建时间)\n `)\n },\n }\n}\n\nasync function triggerCheckpoint(client: any, sessionID: string, directory: string) {\n const messages = await client.session.messages({ path: { id: sessionID } })\n const context = constructCheckpointContext(messages)\n\n // 创建会话目录\n const sessionDir = getSessionMemoryDir(directory, sessionID)\n mkdirSync(sessionDir, { recursive: true })\n\n await client.session.prompt({\n path: { id: sessionID },\n body: {\n agent: \"checkpoint-writer\",\n parts: [{\n type: \"text\",\n text: `Extract checkpoint from this context:\\n${context}\\n\\nWrite checkpoint to:\\n- Session: .super-pocock/memory/sessions/${sessionID}/checkpoint.md\\n- Project: .super-pocock/memory/projects/<pid>/checkpoint.md`\n }],\n },\n })\n}\n\nfunction constructCheckpointContext(messages: any[]): string {\n return messages.map(m => `[${m.role}]: ${m.content}`).join(\"\\n\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir, getGlobalMemoryDir, getSessionMemoryDir, getMemoryRoot } from \"./paths\"\nimport { existsSync, readFileSync, readdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const MemoryInjectionPlugin: Plugin = async ({ directory }) => {\n const config = loadConfig(directory)\n const memoryCache = new Map<string, Record<string, string>>()\n\n function getLatestSessionId(): string | null {\n const sessionsDir = join(getMemoryRoot(directory), \"sessions\")\n if (!existsSync(sessionsDir)) return null\n \n const sessions = readdirSync(sessionsDir, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => d.name)\n \n if (sessions.length === 0) return null\n \n // 返回最新的会话(按目录修改时间)\n let latestSession = sessions[0]\n let latestTime = 0\n \n for (const session of sessions) {\n const sessionPath = join(sessionsDir, session)\n const stat = require(\"fs\").statSync(sessionPath)\n if (stat.mtimeMs > latestTime) {\n latestTime = stat.mtimeMs\n latestSession = session\n }\n }\n \n return latestSession\n }\n\n function loadMemoryFiles(sessionId?: string) {\n const projectDir = getProjectMemoryDir(directory)\n const globalDir = getGlobalMemoryDir(directory)\n const memoryRoot = getMemoryRoot(directory)\n\n const memories: Record<string, string> = {}\n\n // 项目级记忆\n const files = [\n { key: \"memory\", path: join(projectDir, \"MEMORY.md\") },\n { key: \"notes\", path: join(projectDir, \"notes.md\") },\n { key: \"progress\", path: join(projectDir, \"tasks\", \"progress.md\") },\n { key: \"global_memory\", path: join(globalDir, \"MEMORY.md\") },\n ]\n\n for (const file of files) {\n if (existsSync(file.path)) {\n memories[file.key] = readFileSync(file.path, \"utf-8\")\n }\n }\n\n // 会话级 checkpoint(优先)\n if (sessionId) {\n const sessionCheckpoint = join(memoryRoot, \"sessions\", sessionId, \"checkpoint.md\")\n if (existsSync(sessionCheckpoint)) {\n memories.checkpoint = readFileSync(sessionCheckpoint, \"utf-8\")\n }\n }\n\n // 项目级 checkpoint(备选)\n if (!memories.checkpoint) {\n const projectCheckpoint = join(projectDir, \"checkpoint.md\")\n if (existsSync(projectCheckpoint)) {\n memories.checkpoint = readFileSync(projectCheckpoint, \"utf-8\")\n }\n }\n\n return memories\n }\n\n function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n }\n\n function smartTruncate(text: string, maxTokens: number): string {\n const estimatedTokens = estimateTokens(text)\n if (estimatedTokens <= maxTokens) return text\n\n const keepChars = maxTokens * 4 * 0.3\n const start = text.substring(0, keepChars)\n const end = text.substring(text.length - keepChars)\n\n return `${start}\\n\\n... [记忆已压缩,原 ${estimatedTokens} tokens] ...\\n\\n${end}`\n }\n\n function formatMemory(memories: Record<string, string>, budget: Record<string, number>): string {\n const sections = []\n\n if (memories.checkpoint && budget.checkpoint > 0) {\n sections.push(`## 检查点状态\\n${smartTruncate(memories.checkpoint, budget.checkpoint)}`)\n }\n if (memories.memory && budget.memory > 0) {\n sections.push(`## 项目记忆\\n${smartTruncate(memories.memory, budget.memory)}`)\n }\n if (memories.global_memory && budget.memory > 0) {\n sections.push(`## 全局记忆\\n${smartTruncate(memories.global_memory, budget.memory * 0.5)}`)\n }\n if (memories.notes && budget.notes > 0) {\n sections.push(`## 当前笔记\\n${smartTruncate(memories.notes, budget.notes)}`)\n }\n if (memories.progress && budget.progress > 0) {\n sections.push(`## 任务进度\\n${smartTruncate(memories.progress, budget.progress)}`)\n }\n\n return sections.join(\"\\n\\n\")\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n // 获取最新的会话 ID\n const latestSessionId = getLatestSessionId()\n const memories = loadMemoryFiles(latestSessionId)\n memoryCache.set(event.properties.sessionID, memories)\n }\n },\n\n \"experimental.chat.system.transform\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const totalBudget = config.memory.injection.total_budget\n const allocation = config.memory.injection.allocation\n\n const budget = {\n checkpoint: Math.floor(totalBudget * allocation.checkpoint),\n memory: Math.floor(totalBudget * allocation.memory),\n notes: Math.floor(totalBudget * allocation.notes),\n progress: Math.floor(totalBudget * allocation.progress),\n }\n\n const memoryContext = formatMemory(memories, budget)\n\n if (memoryContext) {\n output.system.push(`\\n\\n# Injected Memory Context\\n${memoryContext}`)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const criticalMemory = []\n if (memories.checkpoint) {\n criticalMemory.push(`当前检查点: ${memories.checkpoint.substring(0, 500)}`)\n }\n if (memories.progress) {\n criticalMemory.push(`任务进度摘要: ${memories.progress.substring(0, 300)}`)\n }\n\n output.context.push(`## 保留的关键记忆\\n${criticalMemory.join(\"\\n\\n\")}`)\n },\n }\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir } from \"./paths\"\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const DreamPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryDir = getProjectMemoryDir(directory)\n mkdirSync(memoryDir, { recursive: true })\n\n function getLastTimestamp(metaFile: string): number {\n const metaPath = join(memoryDir, metaFile)\n if (existsSync(metaPath)) {\n const meta = JSON.parse(readFileSync(metaPath, \"utf-8\"))\n return meta.timestamp ?? 0\n }\n return 0\n }\n\n function setLastTimestamp(metaFile: string) {\n const metaPath = join(memoryDir, metaFile)\n writeFileSync(metaPath, JSON.stringify({ timestamp: Date.now() }))\n }\n\n function shouldAutoRun(metaFile: string, intervalDays: number): boolean {\n const lastRun = getLastTimestamp(metaFile)\n const intervalMs = intervalDays * 24 * 60 * 60 * 1000\n return Date.now() - lastRun > intervalMs\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n // 自动触发 dream\n if (config.memory.dream.auto && shouldAutoRun(\".dream-meta.json\", config.memory.dream.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"dream\",\n parts: [{\n type: \"text\",\n text: \"Run automatic dream memory consolidation pass.\"\n }],\n },\n })\n setLastTimestamp(\".dream-meta.json\")\n }\n\n // 自动触发 distill\n if (config.memory.distill.auto && shouldAutoRun(\".distill-meta.json\", config.memory.distill.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"distill\",\n parts: [{\n type: \"text\",\n text: \"Run automatic distill pass.\"\n }],\n },\n })\n setLastTimestamp(\".distill-meta.json\")\n }\n }\n },\n }\n}\n"],"mappings":"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","names":["import_fs","import_path","Database","import_fs","import_fs","import_path","import_path","import_fs","import_path","import_fs","import_path","import_fs","import_path"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/index.ts
|
|
2
9
|
import { mkdirSync as mkdirSync5 } from "fs";
|
|
3
|
-
import { join as
|
|
10
|
+
import { join as join7 } from "path";
|
|
4
11
|
|
|
5
12
|
// src/tool.ts
|
|
6
13
|
import { tool } from "@opencode-ai/plugin";
|
|
@@ -254,16 +261,23 @@ function getProjectMemoryDir(projectRoot) {
|
|
|
254
261
|
function getGlobalMemoryDir(projectRoot) {
|
|
255
262
|
return join3(getMemoryRoot(projectRoot), "global");
|
|
256
263
|
}
|
|
264
|
+
function getSessionMemoryDir(projectRoot, sessionId) {
|
|
265
|
+
return join3(getMemoryRoot(projectRoot), "sessions", sessionId);
|
|
266
|
+
}
|
|
257
267
|
function getDbPath(projectRoot) {
|
|
258
268
|
return join3(getMemoryRoot(projectRoot), "memory.db");
|
|
259
269
|
}
|
|
260
270
|
|
|
261
271
|
// src/checkpoint-plugin.ts
|
|
262
272
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
273
|
+
import { join as join4 } from "path";
|
|
263
274
|
var CheckpointPlugin = async ({ client, directory }) => {
|
|
264
275
|
const config = loadConfig(directory);
|
|
265
|
-
const
|
|
266
|
-
|
|
276
|
+
const memoryRoot = getMemoryRoot(directory);
|
|
277
|
+
const projectDir = getProjectMemoryDir(directory);
|
|
278
|
+
mkdirSync3(memoryRoot, { recursive: true });
|
|
279
|
+
mkdirSync3(join4(memoryRoot, "sessions"), { recursive: true });
|
|
280
|
+
mkdirSync3(projectDir, { recursive: true });
|
|
267
281
|
let lastCheckpointRatio = 0;
|
|
268
282
|
const THRESHOLDS = config.memory.checkpoint.thresholds.map((t) => parseFloat(t) / 100);
|
|
269
283
|
return {
|
|
@@ -304,6 +318,8 @@ Extract and preserve these 11 fields:
|
|
|
304
318
|
async function triggerCheckpoint(client, sessionID, directory) {
|
|
305
319
|
const messages = await client.session.messages({ path: { id: sessionID } });
|
|
306
320
|
const context = constructCheckpointContext(messages);
|
|
321
|
+
const sessionDir = getSessionMemoryDir(directory, sessionID);
|
|
322
|
+
mkdirSync3(sessionDir, { recursive: true });
|
|
307
323
|
await client.session.prompt({
|
|
308
324
|
path: { id: sessionID },
|
|
309
325
|
body: {
|
|
@@ -311,7 +327,11 @@ async function triggerCheckpoint(client, sessionID, directory) {
|
|
|
311
327
|
parts: [{
|
|
312
328
|
type: "text",
|
|
313
329
|
text: `Extract checkpoint from this context:
|
|
314
|
-
${context}
|
|
330
|
+
${context}
|
|
331
|
+
|
|
332
|
+
Write checkpoint to:
|
|
333
|
+
- Session: .super-pocock/memory/sessions/${sessionID}/checkpoint.md
|
|
334
|
+
- Project: .super-pocock/memory/projects/<pid>/checkpoint.md`
|
|
315
335
|
}]
|
|
316
336
|
}
|
|
317
337
|
});
|
|
@@ -321,27 +341,56 @@ function constructCheckpointContext(messages) {
|
|
|
321
341
|
}
|
|
322
342
|
|
|
323
343
|
// src/injection-plugin.ts
|
|
324
|
-
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
|
|
325
|
-
import { join as
|
|
344
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
345
|
+
import { join as join5 } from "path";
|
|
326
346
|
var MemoryInjectionPlugin = async ({ directory }) => {
|
|
327
347
|
const config = loadConfig(directory);
|
|
328
348
|
const memoryCache = /* @__PURE__ */ new Map();
|
|
329
|
-
function
|
|
349
|
+
function getLatestSessionId() {
|
|
350
|
+
const sessionsDir = join5(getMemoryRoot(directory), "sessions");
|
|
351
|
+
if (!existsSync2(sessionsDir)) return null;
|
|
352
|
+
const sessions = readdirSync2(sessionsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
353
|
+
if (sessions.length === 0) return null;
|
|
354
|
+
let latestSession = sessions[0];
|
|
355
|
+
let latestTime = 0;
|
|
356
|
+
for (const session of sessions) {
|
|
357
|
+
const sessionPath = join5(sessionsDir, session);
|
|
358
|
+
const stat = __require("fs").statSync(sessionPath);
|
|
359
|
+
if (stat.mtimeMs > latestTime) {
|
|
360
|
+
latestTime = stat.mtimeMs;
|
|
361
|
+
latestSession = session;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return latestSession;
|
|
365
|
+
}
|
|
366
|
+
function loadMemoryFiles(sessionId) {
|
|
330
367
|
const projectDir = getProjectMemoryDir(directory);
|
|
331
368
|
const globalDir = getGlobalMemoryDir(directory);
|
|
369
|
+
const memoryRoot = getMemoryRoot(directory);
|
|
332
370
|
const memories = {};
|
|
333
371
|
const files = [
|
|
334
|
-
{ key: "
|
|
335
|
-
{ key: "
|
|
336
|
-
{ key: "
|
|
337
|
-
{ key: "
|
|
338
|
-
{ key: "global_memory", path: join4(globalDir, "MEMORY.md") }
|
|
372
|
+
{ key: "memory", path: join5(projectDir, "MEMORY.md") },
|
|
373
|
+
{ key: "notes", path: join5(projectDir, "notes.md") },
|
|
374
|
+
{ key: "progress", path: join5(projectDir, "tasks", "progress.md") },
|
|
375
|
+
{ key: "global_memory", path: join5(globalDir, "MEMORY.md") }
|
|
339
376
|
];
|
|
340
377
|
for (const file of files) {
|
|
341
378
|
if (existsSync2(file.path)) {
|
|
342
379
|
memories[file.key] = readFileSync3(file.path, "utf-8");
|
|
343
380
|
}
|
|
344
381
|
}
|
|
382
|
+
if (sessionId) {
|
|
383
|
+
const sessionCheckpoint = join5(memoryRoot, "sessions", sessionId, "checkpoint.md");
|
|
384
|
+
if (existsSync2(sessionCheckpoint)) {
|
|
385
|
+
memories.checkpoint = readFileSync3(sessionCheckpoint, "utf-8");
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (!memories.checkpoint) {
|
|
389
|
+
const projectCheckpoint = join5(projectDir, "checkpoint.md");
|
|
390
|
+
if (existsSync2(projectCheckpoint)) {
|
|
391
|
+
memories.checkpoint = readFileSync3(projectCheckpoint, "utf-8");
|
|
392
|
+
}
|
|
393
|
+
}
|
|
345
394
|
return memories;
|
|
346
395
|
}
|
|
347
396
|
function estimateTokens(text) {
|
|
@@ -386,7 +435,8 @@ ${smartTruncate(memories.progress, budget.progress)}`);
|
|
|
386
435
|
return {
|
|
387
436
|
event: async ({ event }) => {
|
|
388
437
|
if (event.type === "session.created") {
|
|
389
|
-
const
|
|
438
|
+
const latestSessionId = getLatestSessionId();
|
|
439
|
+
const memories = loadMemoryFiles(latestSessionId);
|
|
390
440
|
memoryCache.set(event.properties.sessionID, memories);
|
|
391
441
|
}
|
|
392
442
|
},
|
|
@@ -427,13 +477,13 @@ ${criticalMemory.join("\n\n")}`);
|
|
|
427
477
|
|
|
428
478
|
// src/dream-plugin.ts
|
|
429
479
|
import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync4 } from "fs";
|
|
430
|
-
import { join as
|
|
480
|
+
import { join as join6 } from "path";
|
|
431
481
|
var DreamPlugin = async ({ client, directory }) => {
|
|
432
482
|
const config = loadConfig(directory);
|
|
433
483
|
const memoryDir = getProjectMemoryDir(directory);
|
|
434
484
|
mkdirSync4(memoryDir, { recursive: true });
|
|
435
485
|
function getLastTimestamp(metaFile) {
|
|
436
|
-
const metaPath =
|
|
486
|
+
const metaPath = join6(memoryDir, metaFile);
|
|
437
487
|
if (existsSync3(metaPath)) {
|
|
438
488
|
const meta = JSON.parse(readFileSync4(metaPath, "utf-8"));
|
|
439
489
|
return meta.timestamp ?? 0;
|
|
@@ -441,7 +491,7 @@ var DreamPlugin = async ({ client, directory }) => {
|
|
|
441
491
|
return 0;
|
|
442
492
|
}
|
|
443
493
|
function setLastTimestamp(metaFile) {
|
|
444
|
-
const metaPath =
|
|
494
|
+
const metaPath = join6(memoryDir, metaFile);
|
|
445
495
|
writeFileSync2(metaPath, JSON.stringify({ timestamp: Date.now() }));
|
|
446
496
|
}
|
|
447
497
|
function shouldAutoRun(metaFile, intervalDays) {
|
|
@@ -489,9 +539,9 @@ var MemoryCorePlugin = async (ctx) => {
|
|
|
489
539
|
const memoryRoot = getMemoryRoot(ctx.directory);
|
|
490
540
|
const projectDir = getProjectMemoryDir(ctx.directory);
|
|
491
541
|
const globalDir = getGlobalMemoryDir(ctx.directory);
|
|
492
|
-
mkdirSync5(
|
|
493
|
-
mkdirSync5(
|
|
494
|
-
mkdirSync5(
|
|
542
|
+
mkdirSync5(join7(memoryRoot, "global"), { recursive: true });
|
|
543
|
+
mkdirSync5(join7(projectDir, "sessions"), { recursive: true });
|
|
544
|
+
mkdirSync5(join7(projectDir, "tasks"), { recursive: true });
|
|
495
545
|
const memoryTool = createMemoryTool({
|
|
496
546
|
memoryDir: memoryRoot,
|
|
497
547
|
dbPath: getDbPath(ctx.directory)
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/tool.ts","../src/store.ts","../src/reconcile.ts","../src/config.ts","../src/paths.ts","../src/checkpoint-plugin.ts","../src/injection-plugin.ts","../src/dream-plugin.ts"],"sourcesContent":["import type { Plugin } from \"@opencode-ai/plugin\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\nimport { createMemoryTool } from \"./tool\"\nimport { CheckpointPlugin } from \"./checkpoint-plugin\"\nimport { MemoryInjectionPlugin } from \"./injection-plugin\"\nimport { DreamPlugin } from \"./dream-plugin\"\nimport { getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir, getDbPath } from \"./paths\"\nimport { ensureConfig } from \"./config\"\n\nexport const MemoryCorePlugin: Plugin = async (ctx) => {\n // 确保配置文件存在\n ensureConfig(ctx.directory)\n\n const memoryRoot = getMemoryRoot(ctx.directory)\n const projectDir = getProjectMemoryDir(ctx.directory)\n const globalDir = getGlobalMemoryDir(ctx.directory)\n\n // 创建目录结构\n mkdirSync(join(memoryRoot, \"global\"), { recursive: true })\n mkdirSync(join(projectDir, \"sessions\"), { recursive: true })\n mkdirSync(join(projectDir, \"tasks\"), { recursive: true })\n\n // 创建 memory 工具\n const memoryTool = createMemoryTool({\n memoryDir: memoryRoot,\n dbPath: getDbPath(ctx.directory),\n })\n\n // 初始化子插件\n const checkpointPlugin = await CheckpointPlugin(ctx)\n const injectionPlugin = await MemoryInjectionPlugin(ctx)\n const dreamPlugin = await DreamPlugin(ctx)\n\n return {\n tool: {\n memory: memoryTool,\n },\n event: async (input) => {\n await checkpointPlugin.event?.(input)\n await injectionPlugin.event?.(input)\n await dreamPlugin.event?.(input)\n },\n \"experimental.chat.system.transform\": async (input, output) => {\n await injectionPlugin[\"experimental.chat.system.transform\"]?.(input, output)\n },\n \"experimental.session.compacting\": async (input, output) => {\n await checkpointPlugin[\"experimental.session.compacting\"]?.(input, output)\n await injectionPlugin[\"experimental.session.compacting\"]?.(input, output)\n },\n }\n}\n\nexport default MemoryCorePlugin\n\n// 导出子模块\nexport { MemoryStore } from \"./store\"\nexport { createMemoryTool } from \"./tool\"\nexport { resolveProjectId, getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir } from \"./paths\"\nexport { loadConfig, DEFAULT_CONFIG } from \"./config\"\nexport type { MemoryConfig } from \"./config\"\nexport type { SearchResult, SearchFilters } from \"./store\"\n","import { tool } from \"@opencode-ai/plugin\"\nimport { z } from \"zod\"\nimport { MemoryStore } from \"./store\"\nimport { reconcileMemoryDir } from \"./reconcile\"\nimport { mkdirSync } from \"fs\"\n\nexport function createMemoryTool(ctx: { memoryDir: string; dbPath: string }) {\n let store: MemoryStore | null = null\n\n function ensureStore() {\n if (!store) {\n mkdirSync(ctx.memoryDir, { recursive: true })\n store = new MemoryStore(ctx.dbPath)\n reconcileMemoryDir(store, ctx.memoryDir)\n }\n return store\n }\n\n return tool({\n description: \"Search or write to the persistent memory store. Search returns ranked results across memory files. Write saves content to a memory file.\",\n args: {\n operation: z.enum([\"search\", \"write\", \"list\", \"forget\"]),\n query: z.string().optional(),\n scope: z.string().optional(),\n scope_id: z.string().optional(),\n type: z.string().optional(),\n limit: z.number().optional(),\n path: z.string().optional(),\n content: z.string().optional(),\n memory_id: z.string().optional(),\n },\n execute(args: any) {\n const s = ensureStore()\n\n if (args.operation === \"search\") {\n if (!args.query) return \"query is required for search\"\n const results = s.search(args.query, {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit,\n })\n if (results.length === 0) return \"No results found\"\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"write\") {\n if (!args.path) return \"path is required for write\"\n if (!args.content) return \"content is required for write\"\n s.write(\n args.path,\n args.scope ?? \"unknown\",\n args.scope_id ?? \"\",\n args.type ?? \"snapshot\",\n args.content,\n )\n return `Wrote to ${args.path}`\n }\n\n if (args.operation === \"list\") {\n const results = s.search(\"*\", {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit ?? 50,\n })\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"forget\") {\n if (!args.memory_id) return \"memory_id is required for forget\"\n s.forget(args.memory_id)\n return `Forgot ${args.memory_id}`\n }\n\n return \"Invalid operation\"\n },\n })\n}\n","import Database from \"better-sqlite3\"\n\nexport interface SearchFilters {\n scope?: string\n scope_id?: string\n type?: string\n limit?: number\n}\n\nexport interface SearchResult {\n path: string\n scope: string\n scope_id: string\n type: string\n snippet: string\n score: number\n}\n\nexport class MemoryStore {\n public db: Database.Database\n\n constructor(dbPath: string) {\n this.db = new Database(dbPath)\n this.db.pragma(\"journal_mode = WAL\")\n this.init()\n }\n\n private init() {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memory_files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT NOT NULL UNIQUE,\n scope TEXT NOT NULL,\n scope_id TEXT NOT NULL DEFAULT '',\n type TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n last_indexed_at INTEGER NOT NULL\n )\n `)\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts\n USING fts5(path, body, tokenize='unicode61')\n `)\n }\n\n search(query: string, filters: SearchFilters = {}): SearchResult[] {\n const tokens = query.split(/\\s+/).filter(Boolean).map(t => `\"${t}\"`)\n if (tokens.length === 0) return []\n const ftsQuery = tokens.join(\" OR \")\n const limit = filters.limit ?? 10\n\n let sql = `\n SELECT f.path, m.scope, m.scope_id, m.type,\n snippet(memory_fts, 1, '<<', '>>', '...', 32) AS snippet,\n bm25(memory_fts) AS score\n FROM memory_fts f\n JOIN memory_files m ON m.path = f.path\n WHERE memory_fts MATCH ?\n `\n const params: any[] = [ftsQuery]\n if (filters.scope) { sql += ` AND m.scope = ?`; params.push(filters.scope) }\n if (filters.scope_id) { sql += ` AND m.scope_id = ?`; params.push(filters.scope_id) }\n if (filters.type) { sql += ` AND m.type = ?`; params.push(filters.type) }\n sql += ` ORDER BY score LIMIT ?`\n params.push(limit)\n return this.db.prepare(sql).all(...params) as SearchResult[]\n }\n\n write(path: string, scope: string, scope_id: string, type: string, content: string) {\n const fingerprint = `${content.length}-${Date.now()}`\n const now = Date.now()\n\n this.db.prepare(`\n INSERT OR REPLACE INTO memory_files (path, scope, scope_id, type, fingerprint, last_indexed_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `).run(path, scope, scope_id, type, fingerprint, now)\n\n this.db.prepare(`DELETE FROM memory_fts WHERE path = ?`).run(path)\n this.db.prepare(`INSERT INTO memory_fts (path, body) VALUES (?, ?)`).run(path, content)\n }\n\n forget(memoryId: string) {\n this.db.prepare(\"DELETE FROM memory_files WHERE path = ?\").run(memoryId)\n this.db.prepare(\"DELETE FROM memory_fts WHERE path = ?\").run(memoryId)\n }\n\n close() {\n this.db.close()\n }\n}\n","import { readdirSync, readFileSync } from \"fs\"\nimport { join, relative, sep } from \"path\"\nimport type { MemoryStore } from \"./store\"\n\nfunction parseScopeAndId(memoryRoot: string, filePath: string): { scope: string; scope_id: string } {\n const rel = relative(memoryRoot, filePath).split(sep)\n if (rel[0] === \"global\") return { scope: \"global\", scope_id: \"\" }\n if (rel[0] === \"projects\" && rel.length >= 3) return { scope: \"projects\", scope_id: rel[1] }\n if (rel[0] === \"sessions\" && rel.length >= 3) return { scope: \"sessions\", scope_id: rel[1] }\n return { scope: \"unknown\", scope_id: \"\" }\n}\n\nfunction walkMdFiles(dir: string): string[] {\n const results: string[] = []\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...walkMdFiles(full))\n } else if (entry.name.endsWith(\".md\")) {\n results.push(full)\n }\n }\n return results\n}\n\nexport function reconcileMemoryDir(store: MemoryStore, memoryRoot: string) {\n const filesOnDisk = walkMdFiles(memoryRoot)\n const diskPaths = new Set<string>()\n\n for (const file of filesOnDisk) {\n diskPaths.add(file)\n const content = readFileSync(file, \"utf-8\")\n const { scope, scope_id } = parseScopeAndId(memoryRoot, file)\n store.write(file, scope, scope_id, \"snapshot\", content)\n }\n\n const indexed = store.db.prepare(\"SELECT path FROM memory_files\").all() as { path: string }[]\n for (const row of indexed) {\n if (!diskPaths.has(row.path)) {\n store.forget(row.path)\n }\n }\n}\n","import { readFileSync, existsSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join, dirname } from \"path\"\n\nexport interface MemoryConfig {\n memory: {\n injection: {\n total_budget: number\n allocation: {\n checkpoint: number\n memory: number\n notes: number\n progress: number\n buffer: number\n }\n }\n checkpoint: {\n thresholds: string[]\n drain_timeout_ms: number\n idle_timeout_ms: number\n }\n dream: {\n auto: boolean\n interval_days: number\n }\n distill: {\n auto: boolean\n interval_days: number\n }\n }\n}\n\nexport const DEFAULT_CONFIG: MemoryConfig = {\n memory: {\n injection: {\n total_budget: 2000,\n allocation: {\n checkpoint: 0.30,\n memory: 0.25,\n notes: 0.20,\n progress: 0.15,\n buffer: 0.10\n }\n },\n checkpoint: {\n thresholds: [\"40%\", \"60%\", \"80%\"],\n drain_timeout_ms: 120000,\n idle_timeout_ms: 300000\n },\n dream: {\n auto: true,\n interval_days: 7\n },\n distill: {\n auto: true,\n interval_days: 30\n }\n }\n}\n\nexport function getConfigPath(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"config.json\")\n}\n\nexport function loadConfig(projectRoot: string): MemoryConfig {\n const configPath = getConfigPath(projectRoot)\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, \"utf-8\")\n return { ...DEFAULT_CONFIG, ...JSON.parse(content) }\n }\n return DEFAULT_CONFIG\n}\n\nexport function ensureConfig(projectRoot: string): void {\n const configPath = getConfigPath(projectRoot)\n if (!existsSync(configPath)) {\n mkdirSync(dirname(configPath), { recursive: true })\n writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2))\n }\n}\n","import { createHash } from \"crypto\"\nimport { join } from \"path\"\n\nexport type Scope = \"global\" | \"projects\" | \"sessions\"\n\nexport function resolveProjectId(absRepoPath: string): string {\n return createHash(\"sha256\").update(absRepoPath).digest(\"hex\").slice(0, 12)\n}\n\nexport function getMemoryRoot(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"memory\")\n}\n\nexport function getProjectMemoryDir(projectRoot: string): string {\n const projectId = resolveProjectId(projectRoot)\n return join(getMemoryRoot(projectRoot), \"projects\", projectId)\n}\n\nexport function getGlobalMemoryDir(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"global\")\n}\n\nexport function getSessionMemoryDir(projectRoot: string, sessionId: string): string {\n return join(getProjectMemoryDir(projectRoot), \"sessions\", sessionId)\n}\n\nexport function getDbPath(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"memory.db\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir } from \"./paths\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const CheckpointPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryDir = getProjectMemoryDir(directory)\n mkdirSync(memoryDir, { recursive: true })\n\n let lastCheckpointRatio = 0\n const THRESHOLDS = config.memory.checkpoint.thresholds.map(t => parseFloat(t) / 100)\n\n return {\n event: async ({ event }) => {\n // 触发 1: Token 比例阈值\n if (event.type === \"session.next.step.ended\") {\n const ratio = event.properties.tokens / event.properties.contextLimit\n const nextThreshold = THRESHOLDS.find(t => t > lastCheckpointRatio)\n if (nextThreshold && ratio >= nextThreshold) {\n lastCheckpointRatio = ratio\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }\n }\n\n // 触发 2: 会话结束(idle 超时)\n if (event.type === \"session.status\" && event.properties?.status?.type === \"idle\") {\n setTimeout(async () => {\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }, config.memory.checkpoint.idle_timeout_ms)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n output.context.push(`\n## Checkpoint Instructions\nExtract and preserve these 11 fields:\n1. Intent (用户的核心目标)\n2. Actions (已执行的操作)\n3. Task Tree (子任务层级)\n4. Errors & Workarounds (遇到的问题及解决)\n5. Design Decisions (关键技术选择)\n6. Constraints (限制条件)\n7. Current State (任务进度)\n8. TODOs (剩余工作)\n9. Code Changes Summary (Git diff 概要)\n10. Key File Paths (涉及的核心文件)\n11. Timestamp (检查点创建时间)\n `)\n },\n }\n}\n\nasync function triggerCheckpoint(client: any, sessionID: string, directory: string) {\n const messages = await client.session.messages({ path: { id: sessionID } })\n const context = constructCheckpointContext(messages)\n\n await client.session.prompt({\n path: { id: sessionID },\n body: {\n agent: \"checkpoint-writer\",\n parts: [{\n type: \"text\",\n text: `Extract checkpoint from this context:\\n${context}`\n }],\n },\n })\n}\n\nfunction constructCheckpointContext(messages: any[]): string {\n return messages.map(m => `[${m.role}]: ${m.content}`).join(\"\\n\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir, getGlobalMemoryDir } from \"./paths\"\nimport { existsSync, readFileSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const MemoryInjectionPlugin: Plugin = async ({ directory }) => {\n const config = loadConfig(directory)\n const memoryCache = new Map<string, Record<string, string>>()\n\n function loadMemoryFiles() {\n const projectDir = getProjectMemoryDir(directory)\n const globalDir = getGlobalMemoryDir(directory)\n\n const memories: Record<string, string> = {}\n\n const files = [\n { key: \"checkpoint\", path: join(projectDir, \"checkpoint.md\") },\n { key: \"memory\", path: join(projectDir, \"MEMORY.md\") },\n { key: \"notes\", path: join(projectDir, \"notes.md\") },\n { key: \"progress\", path: join(projectDir, \"tasks\", \"progress.md\") },\n { key: \"global_memory\", path: join(globalDir, \"MEMORY.md\") },\n ]\n\n for (const file of files) {\n if (existsSync(file.path)) {\n memories[file.key] = readFileSync(file.path, \"utf-8\")\n }\n }\n\n return memories\n }\n\n function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n }\n\n function smartTruncate(text: string, maxTokens: number): string {\n const estimatedTokens = estimateTokens(text)\n if (estimatedTokens <= maxTokens) return text\n\n const keepChars = maxTokens * 4 * 0.3\n const start = text.substring(0, keepChars)\n const end = text.substring(text.length - keepChars)\n\n return `${start}\\n\\n... [记忆已压缩,原 ${estimatedTokens} tokens] ...\\n\\n${end}`\n }\n\n function formatMemory(memories: Record<string, string>, budget: Record<string, number>): string {\n const sections = []\n\n if (memories.checkpoint && budget.checkpoint > 0) {\n sections.push(`## 检查点状态\\n${smartTruncate(memories.checkpoint, budget.checkpoint)}`)\n }\n if (memories.memory && budget.memory > 0) {\n sections.push(`## 项目记忆\\n${smartTruncate(memories.memory, budget.memory)}`)\n }\n if (memories.global_memory && budget.memory > 0) {\n sections.push(`## 全局记忆\\n${smartTruncate(memories.global_memory, budget.memory * 0.5)}`)\n }\n if (memories.notes && budget.notes > 0) {\n sections.push(`## 当前笔记\\n${smartTruncate(memories.notes, budget.notes)}`)\n }\n if (memories.progress && budget.progress > 0) {\n sections.push(`## 任务进度\\n${smartTruncate(memories.progress, budget.progress)}`)\n }\n\n return sections.join(\"\\n\\n\")\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n const memories = loadMemoryFiles()\n memoryCache.set(event.properties.sessionID, memories)\n }\n },\n\n \"experimental.chat.system.transform\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const totalBudget = config.memory.injection.total_budget\n const allocation = config.memory.injection.allocation\n\n const budget = {\n checkpoint: Math.floor(totalBudget * allocation.checkpoint),\n memory: Math.floor(totalBudget * allocation.memory),\n notes: Math.floor(totalBudget * allocation.notes),\n progress: Math.floor(totalBudget * allocation.progress),\n }\n\n const memoryContext = formatMemory(memories, budget)\n\n if (memoryContext) {\n output.system.push(`\\n\\n# Injected Memory Context\\n${memoryContext}`)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const criticalMemory = []\n if (memories.checkpoint) {\n criticalMemory.push(`当前检查点: ${memories.checkpoint.substring(0, 500)}`)\n }\n if (memories.progress) {\n criticalMemory.push(`任务进度摘要: ${memories.progress.substring(0, 300)}`)\n }\n\n output.context.push(`## 保留的关键记忆\\n${criticalMemory.join(\"\\n\\n\")}`)\n },\n }\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir } from \"./paths\"\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const DreamPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryDir = getProjectMemoryDir(directory)\n mkdirSync(memoryDir, { recursive: true })\n\n function getLastTimestamp(metaFile: string): number {\n const metaPath = join(memoryDir, metaFile)\n if (existsSync(metaPath)) {\n const meta = JSON.parse(readFileSync(metaPath, \"utf-8\"))\n return meta.timestamp ?? 0\n }\n return 0\n }\n\n function setLastTimestamp(metaFile: string) {\n const metaPath = join(memoryDir, metaFile)\n writeFileSync(metaPath, JSON.stringify({ timestamp: Date.now() }))\n }\n\n function shouldAutoRun(metaFile: string, intervalDays: number): boolean {\n const lastRun = getLastTimestamp(metaFile)\n const intervalMs = intervalDays * 24 * 60 * 60 * 1000\n return Date.now() - lastRun > intervalMs\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n // 自动触发 dream\n if (config.memory.dream.auto && shouldAutoRun(\".dream-meta.json\", config.memory.dream.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"dream\",\n parts: [{\n type: \"text\",\n text: \"Run automatic dream memory consolidation pass.\"\n }],\n },\n })\n setLastTimestamp(\".dream-meta.json\")\n }\n\n // 自动触发 distill\n if (config.memory.distill.auto && shouldAutoRun(\".distill-meta.json\", config.memory.distill.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"distill\",\n parts: [{\n type: \"text\",\n text: \"Run automatic distill pass.\"\n }],\n },\n })\n setLastTimestamp(\".distill-meta.json\")\n }\n }\n },\n }\n}\n"],"mappings":"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","names":["mkdirSync","join","readFileSync","mkdirSync","join","join","join","mkdirSync","existsSync","readFileSync","join","existsSync","readFileSync","writeFileSync","mkdirSync","join","mkdirSync","join"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/tool.ts","../src/store.ts","../src/reconcile.ts","../src/config.ts","../src/paths.ts","../src/checkpoint-plugin.ts","../src/injection-plugin.ts","../src/dream-plugin.ts"],"sourcesContent":["import type { Plugin } from \"@opencode-ai/plugin\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\nimport { createMemoryTool } from \"./tool\"\nimport { CheckpointPlugin } from \"./checkpoint-plugin\"\nimport { MemoryInjectionPlugin } from \"./injection-plugin\"\nimport { DreamPlugin } from \"./dream-plugin\"\nimport { getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir, getDbPath } from \"./paths\"\nimport { ensureConfig } from \"./config\"\n\nexport const MemoryCorePlugin: Plugin = async (ctx) => {\n // 确保配置文件存在\n ensureConfig(ctx.directory)\n\n const memoryRoot = getMemoryRoot(ctx.directory)\n const projectDir = getProjectMemoryDir(ctx.directory)\n const globalDir = getGlobalMemoryDir(ctx.directory)\n\n // 创建目录结构\n mkdirSync(join(memoryRoot, \"global\"), { recursive: true })\n mkdirSync(join(projectDir, \"sessions\"), { recursive: true })\n mkdirSync(join(projectDir, \"tasks\"), { recursive: true })\n\n // 创建 memory 工具\n const memoryTool = createMemoryTool({\n memoryDir: memoryRoot,\n dbPath: getDbPath(ctx.directory),\n })\n\n // 初始化子插件\n const checkpointPlugin = await CheckpointPlugin(ctx)\n const injectionPlugin = await MemoryInjectionPlugin(ctx)\n const dreamPlugin = await DreamPlugin(ctx)\n\n return {\n tool: {\n memory: memoryTool,\n },\n event: async (input) => {\n await checkpointPlugin.event?.(input)\n await injectionPlugin.event?.(input)\n await dreamPlugin.event?.(input)\n },\n \"experimental.chat.system.transform\": async (input, output) => {\n await injectionPlugin[\"experimental.chat.system.transform\"]?.(input, output)\n },\n \"experimental.session.compacting\": async (input, output) => {\n await checkpointPlugin[\"experimental.session.compacting\"]?.(input, output)\n await injectionPlugin[\"experimental.session.compacting\"]?.(input, output)\n },\n }\n}\n\nexport default MemoryCorePlugin\n\n// 导出子模块\nexport { MemoryStore } from \"./store\"\nexport { createMemoryTool } from \"./tool\"\nexport { resolveProjectId, getMemoryRoot, getProjectMemoryDir, getGlobalMemoryDir } from \"./paths\"\nexport { loadConfig, DEFAULT_CONFIG } from \"./config\"\nexport type { MemoryConfig } from \"./config\"\nexport type { SearchResult, SearchFilters } from \"./store\"\n","import { tool } from \"@opencode-ai/plugin\"\nimport { z } from \"zod\"\nimport { MemoryStore } from \"./store\"\nimport { reconcileMemoryDir } from \"./reconcile\"\nimport { mkdirSync } from \"fs\"\n\nexport function createMemoryTool(ctx: { memoryDir: string; dbPath: string }) {\n let store: MemoryStore | null = null\n\n function ensureStore() {\n if (!store) {\n mkdirSync(ctx.memoryDir, { recursive: true })\n store = new MemoryStore(ctx.dbPath)\n reconcileMemoryDir(store, ctx.memoryDir)\n }\n return store\n }\n\n return tool({\n description: \"Search or write to the persistent memory store. Search returns ranked results across memory files. Write saves content to a memory file.\",\n args: {\n operation: z.enum([\"search\", \"write\", \"list\", \"forget\"]),\n query: z.string().optional(),\n scope: z.string().optional(),\n scope_id: z.string().optional(),\n type: z.string().optional(),\n limit: z.number().optional(),\n path: z.string().optional(),\n content: z.string().optional(),\n memory_id: z.string().optional(),\n },\n execute(args: any) {\n const s = ensureStore()\n\n if (args.operation === \"search\") {\n if (!args.query) return \"query is required for search\"\n const results = s.search(args.query, {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit,\n })\n if (results.length === 0) return \"No results found\"\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"write\") {\n if (!args.path) return \"path is required for write\"\n if (!args.content) return \"content is required for write\"\n s.write(\n args.path,\n args.scope ?? \"unknown\",\n args.scope_id ?? \"\",\n args.type ?? \"snapshot\",\n args.content,\n )\n return `Wrote to ${args.path}`\n }\n\n if (args.operation === \"list\") {\n const results = s.search(\"*\", {\n scope: args.scope,\n scope_id: args.scope_id,\n type: args.type,\n limit: args.limit ?? 50,\n })\n return JSON.stringify(results, null, 2)\n }\n\n if (args.operation === \"forget\") {\n if (!args.memory_id) return \"memory_id is required for forget\"\n s.forget(args.memory_id)\n return `Forgot ${args.memory_id}`\n }\n\n return \"Invalid operation\"\n },\n })\n}\n","import Database from \"better-sqlite3\"\n\nexport interface SearchFilters {\n scope?: string\n scope_id?: string\n type?: string\n limit?: number\n}\n\nexport interface SearchResult {\n path: string\n scope: string\n scope_id: string\n type: string\n snippet: string\n score: number\n}\n\nexport class MemoryStore {\n public db: Database.Database\n\n constructor(dbPath: string) {\n this.db = new Database(dbPath)\n this.db.pragma(\"journal_mode = WAL\")\n this.init()\n }\n\n private init() {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memory_files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT NOT NULL UNIQUE,\n scope TEXT NOT NULL,\n scope_id TEXT NOT NULL DEFAULT '',\n type TEXT NOT NULL,\n fingerprint TEXT NOT NULL,\n last_indexed_at INTEGER NOT NULL\n )\n `)\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts\n USING fts5(path, body, tokenize='unicode61')\n `)\n }\n\n search(query: string, filters: SearchFilters = {}): SearchResult[] {\n const tokens = query.split(/\\s+/).filter(Boolean).map(t => `\"${t}\"`)\n if (tokens.length === 0) return []\n const ftsQuery = tokens.join(\" OR \")\n const limit = filters.limit ?? 10\n\n let sql = `\n SELECT f.path, m.scope, m.scope_id, m.type,\n snippet(memory_fts, 1, '<<', '>>', '...', 32) AS snippet,\n bm25(memory_fts) AS score\n FROM memory_fts f\n JOIN memory_files m ON m.path = f.path\n WHERE memory_fts MATCH ?\n `\n const params: any[] = [ftsQuery]\n if (filters.scope) { sql += ` AND m.scope = ?`; params.push(filters.scope) }\n if (filters.scope_id) { sql += ` AND m.scope_id = ?`; params.push(filters.scope_id) }\n if (filters.type) { sql += ` AND m.type = ?`; params.push(filters.type) }\n sql += ` ORDER BY score LIMIT ?`\n params.push(limit)\n return this.db.prepare(sql).all(...params) as SearchResult[]\n }\n\n write(path: string, scope: string, scope_id: string, type: string, content: string) {\n const fingerprint = `${content.length}-${Date.now()}`\n const now = Date.now()\n\n this.db.prepare(`\n INSERT OR REPLACE INTO memory_files (path, scope, scope_id, type, fingerprint, last_indexed_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `).run(path, scope, scope_id, type, fingerprint, now)\n\n this.db.prepare(`DELETE FROM memory_fts WHERE path = ?`).run(path)\n this.db.prepare(`INSERT INTO memory_fts (path, body) VALUES (?, ?)`).run(path, content)\n }\n\n forget(memoryId: string) {\n this.db.prepare(\"DELETE FROM memory_files WHERE path = ?\").run(memoryId)\n this.db.prepare(\"DELETE FROM memory_fts WHERE path = ?\").run(memoryId)\n }\n\n close() {\n this.db.close()\n }\n}\n","import { readdirSync, readFileSync } from \"fs\"\nimport { join, relative, sep } from \"path\"\nimport type { MemoryStore } from \"./store\"\n\nfunction parseScopeAndId(memoryRoot: string, filePath: string): { scope: string; scope_id: string } {\n const rel = relative(memoryRoot, filePath).split(sep)\n if (rel[0] === \"global\") return { scope: \"global\", scope_id: \"\" }\n if (rel[0] === \"projects\" && rel.length >= 3) return { scope: \"projects\", scope_id: rel[1] }\n if (rel[0] === \"sessions\" && rel.length >= 3) return { scope: \"sessions\", scope_id: rel[1] }\n return { scope: \"unknown\", scope_id: \"\" }\n}\n\nfunction walkMdFiles(dir: string): string[] {\n const results: string[] = []\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...walkMdFiles(full))\n } else if (entry.name.endsWith(\".md\")) {\n results.push(full)\n }\n }\n return results\n}\n\nexport function reconcileMemoryDir(store: MemoryStore, memoryRoot: string) {\n const filesOnDisk = walkMdFiles(memoryRoot)\n const diskPaths = new Set<string>()\n\n for (const file of filesOnDisk) {\n diskPaths.add(file)\n const content = readFileSync(file, \"utf-8\")\n const { scope, scope_id } = parseScopeAndId(memoryRoot, file)\n store.write(file, scope, scope_id, \"snapshot\", content)\n }\n\n const indexed = store.db.prepare(\"SELECT path FROM memory_files\").all() as { path: string }[]\n for (const row of indexed) {\n if (!diskPaths.has(row.path)) {\n store.forget(row.path)\n }\n }\n}\n","import { readFileSync, existsSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join, dirname } from \"path\"\n\nexport interface MemoryConfig {\n memory: {\n injection: {\n total_budget: number\n allocation: {\n checkpoint: number\n memory: number\n notes: number\n progress: number\n buffer: number\n }\n }\n checkpoint: {\n thresholds: string[]\n drain_timeout_ms: number\n idle_timeout_ms: number\n }\n dream: {\n auto: boolean\n interval_days: number\n }\n distill: {\n auto: boolean\n interval_days: number\n }\n }\n}\n\nexport const DEFAULT_CONFIG: MemoryConfig = {\n memory: {\n injection: {\n total_budget: 2000,\n allocation: {\n checkpoint: 0.30,\n memory: 0.25,\n notes: 0.20,\n progress: 0.15,\n buffer: 0.10\n }\n },\n checkpoint: {\n thresholds: [\"40%\", \"60%\", \"80%\"],\n drain_timeout_ms: 120000,\n idle_timeout_ms: 300000\n },\n dream: {\n auto: true,\n interval_days: 7\n },\n distill: {\n auto: true,\n interval_days: 30\n }\n }\n}\n\nexport function getConfigPath(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"config.json\")\n}\n\nexport function loadConfig(projectRoot: string): MemoryConfig {\n const configPath = getConfigPath(projectRoot)\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, \"utf-8\")\n return { ...DEFAULT_CONFIG, ...JSON.parse(content) }\n }\n return DEFAULT_CONFIG\n}\n\nexport function ensureConfig(projectRoot: string): void {\n const configPath = getConfigPath(projectRoot)\n if (!existsSync(configPath)) {\n mkdirSync(dirname(configPath), { recursive: true })\n writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2))\n }\n}\n","import { createHash } from \"crypto\"\nimport { join } from \"path\"\n\nexport type Scope = \"global\" | \"projects\" | \"sessions\"\n\nexport function resolveProjectId(absRepoPath: string): string {\n return createHash(\"sha256\").update(absRepoPath).digest(\"hex\").slice(0, 12)\n}\n\nexport function getMemoryRoot(projectRoot: string): string {\n return join(projectRoot, \".super-pocock\", \"memory\")\n}\n\nexport function getProjectMemoryDir(projectRoot: string): string {\n const projectId = resolveProjectId(projectRoot)\n return join(getMemoryRoot(projectRoot), \"projects\", projectId)\n}\n\nexport function getGlobalMemoryDir(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"global\")\n}\n\nexport function getSessionMemoryDir(projectRoot: string, sessionId: string): string {\n return join(getMemoryRoot(projectRoot), \"sessions\", sessionId)\n}\n\nexport function getDbPath(projectRoot: string): string {\n return join(getMemoryRoot(projectRoot), \"memory.db\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir, getSessionMemoryDir, getMemoryRoot } from \"./paths\"\nimport { mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const CheckpointPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryRoot = getMemoryRoot(directory)\n const projectDir = getProjectMemoryDir(directory)\n \n // 创建必要的目录\n mkdirSync(memoryRoot, { recursive: true })\n mkdirSync(join(memoryRoot, \"sessions\"), { recursive: true })\n mkdirSync(projectDir, { recursive: true })\n\n let lastCheckpointRatio = 0\n const THRESHOLDS = config.memory.checkpoint.thresholds.map(t => parseFloat(t) / 100)\n\n return {\n event: async ({ event }) => {\n // 触发 1: Token 比例阈值\n if (event.type === \"session.next.step.ended\") {\n const ratio = event.properties.tokens / event.properties.contextLimit\n const nextThreshold = THRESHOLDS.find(t => t > lastCheckpointRatio)\n if (nextThreshold && ratio >= nextThreshold) {\n lastCheckpointRatio = ratio\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }\n }\n\n // 触发 2: 会话结束(idle 超时)\n if (event.type === \"session.status\" && event.properties?.status?.type === \"idle\") {\n setTimeout(async () => {\n await triggerCheckpoint(client, event.properties.sessionID, directory)\n }, config.memory.checkpoint.idle_timeout_ms)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n output.context.push(`\n## Checkpoint Instructions\nExtract and preserve these 11 fields:\n1. Intent (用户的核心目标)\n2. Actions (已执行的操作)\n3. Task Tree (子任务层级)\n4. Errors & Workarounds (遇到的问题及解决)\n5. Design Decisions (关键技术选择)\n6. Constraints (限制条件)\n7. Current State (任务进度)\n8. TODOs (剩余工作)\n9. Code Changes Summary (Git diff 概要)\n10. Key File Paths (涉及的核心文件)\n11. Timestamp (检查点创建时间)\n `)\n },\n }\n}\n\nasync function triggerCheckpoint(client: any, sessionID: string, directory: string) {\n const messages = await client.session.messages({ path: { id: sessionID } })\n const context = constructCheckpointContext(messages)\n\n // 创建会话目录\n const sessionDir = getSessionMemoryDir(directory, sessionID)\n mkdirSync(sessionDir, { recursive: true })\n\n await client.session.prompt({\n path: { id: sessionID },\n body: {\n agent: \"checkpoint-writer\",\n parts: [{\n type: \"text\",\n text: `Extract checkpoint from this context:\\n${context}\\n\\nWrite checkpoint to:\\n- Session: .super-pocock/memory/sessions/${sessionID}/checkpoint.md\\n- Project: .super-pocock/memory/projects/<pid>/checkpoint.md`\n }],\n },\n })\n}\n\nfunction constructCheckpointContext(messages: any[]): string {\n return messages.map(m => `[${m.role}]: ${m.content}`).join(\"\\n\")\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir, getGlobalMemoryDir, getSessionMemoryDir, getMemoryRoot } from \"./paths\"\nimport { existsSync, readFileSync, readdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const MemoryInjectionPlugin: Plugin = async ({ directory }) => {\n const config = loadConfig(directory)\n const memoryCache = new Map<string, Record<string, string>>()\n\n function getLatestSessionId(): string | null {\n const sessionsDir = join(getMemoryRoot(directory), \"sessions\")\n if (!existsSync(sessionsDir)) return null\n \n const sessions = readdirSync(sessionsDir, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => d.name)\n \n if (sessions.length === 0) return null\n \n // 返回最新的会话(按目录修改时间)\n let latestSession = sessions[0]\n let latestTime = 0\n \n for (const session of sessions) {\n const sessionPath = join(sessionsDir, session)\n const stat = require(\"fs\").statSync(sessionPath)\n if (stat.mtimeMs > latestTime) {\n latestTime = stat.mtimeMs\n latestSession = session\n }\n }\n \n return latestSession\n }\n\n function loadMemoryFiles(sessionId?: string) {\n const projectDir = getProjectMemoryDir(directory)\n const globalDir = getGlobalMemoryDir(directory)\n const memoryRoot = getMemoryRoot(directory)\n\n const memories: Record<string, string> = {}\n\n // 项目级记忆\n const files = [\n { key: \"memory\", path: join(projectDir, \"MEMORY.md\") },\n { key: \"notes\", path: join(projectDir, \"notes.md\") },\n { key: \"progress\", path: join(projectDir, \"tasks\", \"progress.md\") },\n { key: \"global_memory\", path: join(globalDir, \"MEMORY.md\") },\n ]\n\n for (const file of files) {\n if (existsSync(file.path)) {\n memories[file.key] = readFileSync(file.path, \"utf-8\")\n }\n }\n\n // 会话级 checkpoint(优先)\n if (sessionId) {\n const sessionCheckpoint = join(memoryRoot, \"sessions\", sessionId, \"checkpoint.md\")\n if (existsSync(sessionCheckpoint)) {\n memories.checkpoint = readFileSync(sessionCheckpoint, \"utf-8\")\n }\n }\n\n // 项目级 checkpoint(备选)\n if (!memories.checkpoint) {\n const projectCheckpoint = join(projectDir, \"checkpoint.md\")\n if (existsSync(projectCheckpoint)) {\n memories.checkpoint = readFileSync(projectCheckpoint, \"utf-8\")\n }\n }\n\n return memories\n }\n\n function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n }\n\n function smartTruncate(text: string, maxTokens: number): string {\n const estimatedTokens = estimateTokens(text)\n if (estimatedTokens <= maxTokens) return text\n\n const keepChars = maxTokens * 4 * 0.3\n const start = text.substring(0, keepChars)\n const end = text.substring(text.length - keepChars)\n\n return `${start}\\n\\n... [记忆已压缩,原 ${estimatedTokens} tokens] ...\\n\\n${end}`\n }\n\n function formatMemory(memories: Record<string, string>, budget: Record<string, number>): string {\n const sections = []\n\n if (memories.checkpoint && budget.checkpoint > 0) {\n sections.push(`## 检查点状态\\n${smartTruncate(memories.checkpoint, budget.checkpoint)}`)\n }\n if (memories.memory && budget.memory > 0) {\n sections.push(`## 项目记忆\\n${smartTruncate(memories.memory, budget.memory)}`)\n }\n if (memories.global_memory && budget.memory > 0) {\n sections.push(`## 全局记忆\\n${smartTruncate(memories.global_memory, budget.memory * 0.5)}`)\n }\n if (memories.notes && budget.notes > 0) {\n sections.push(`## 当前笔记\\n${smartTruncate(memories.notes, budget.notes)}`)\n }\n if (memories.progress && budget.progress > 0) {\n sections.push(`## 任务进度\\n${smartTruncate(memories.progress, budget.progress)}`)\n }\n\n return sections.join(\"\\n\\n\")\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n // 获取最新的会话 ID\n const latestSessionId = getLatestSessionId()\n const memories = loadMemoryFiles(latestSessionId)\n memoryCache.set(event.properties.sessionID, memories)\n }\n },\n\n \"experimental.chat.system.transform\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const totalBudget = config.memory.injection.total_budget\n const allocation = config.memory.injection.allocation\n\n const budget = {\n checkpoint: Math.floor(totalBudget * allocation.checkpoint),\n memory: Math.floor(totalBudget * allocation.memory),\n notes: Math.floor(totalBudget * allocation.notes),\n progress: Math.floor(totalBudget * allocation.progress),\n }\n\n const memoryContext = formatMemory(memories, budget)\n\n if (memoryContext) {\n output.system.push(`\\n\\n# Injected Memory Context\\n${memoryContext}`)\n }\n },\n\n \"experimental.session.compacting\": async (input, output) => {\n const memories = memoryCache.get(input.sessionID)\n if (!memories) return\n\n const criticalMemory = []\n if (memories.checkpoint) {\n criticalMemory.push(`当前检查点: ${memories.checkpoint.substring(0, 500)}`)\n }\n if (memories.progress) {\n criticalMemory.push(`任务进度摘要: ${memories.progress.substring(0, 300)}`)\n }\n\n output.context.push(`## 保留的关键记忆\\n${criticalMemory.join(\"\\n\\n\")}`)\n },\n }\n}\n","import type { Plugin } from \"@opencode-ai/plugin\"\nimport { loadConfig } from \"./config\"\nimport { getProjectMemoryDir } from \"./paths\"\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"fs\"\nimport { join } from \"path\"\n\nexport const DreamPlugin: Plugin = async ({ client, directory }) => {\n const config = loadConfig(directory)\n const memoryDir = getProjectMemoryDir(directory)\n mkdirSync(memoryDir, { recursive: true })\n\n function getLastTimestamp(metaFile: string): number {\n const metaPath = join(memoryDir, metaFile)\n if (existsSync(metaPath)) {\n const meta = JSON.parse(readFileSync(metaPath, \"utf-8\"))\n return meta.timestamp ?? 0\n }\n return 0\n }\n\n function setLastTimestamp(metaFile: string) {\n const metaPath = join(memoryDir, metaFile)\n writeFileSync(metaPath, JSON.stringify({ timestamp: Date.now() }))\n }\n\n function shouldAutoRun(metaFile: string, intervalDays: number): boolean {\n const lastRun = getLastTimestamp(metaFile)\n const intervalMs = intervalDays * 24 * 60 * 60 * 1000\n return Date.now() - lastRun > intervalMs\n }\n\n return {\n event: async ({ event }) => {\n if (event.type === \"session.created\") {\n // 自动触发 dream\n if (config.memory.dream.auto && shouldAutoRun(\".dream-meta.json\", config.memory.dream.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"dream\",\n parts: [{\n type: \"text\",\n text: \"Run automatic dream memory consolidation pass.\"\n }],\n },\n })\n setLastTimestamp(\".dream-meta.json\")\n }\n\n // 自动触发 distill\n if (config.memory.distill.auto && shouldAutoRun(\".distill-meta.json\", config.memory.distill.interval_days)) {\n await client.session.prompt({\n path: { id: event.properties.sessionID },\n body: {\n agent: \"distill\",\n parts: [{\n type: \"text\",\n text: \"Run automatic distill pass.\"\n }],\n },\n })\n setLastTimestamp(\".distill-meta.json\")\n }\n }\n },\n }\n}\n"],"mappings":"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","names":["mkdirSync","join","readFileSync","mkdirSync","join","join","mkdirSync","join","existsSync","readFileSync","readdirSync","join","existsSync","readFileSync","writeFileSync","mkdirSync","join","mkdirSync","join"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@super-pocock-ai/memory-core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "持久化记忆系统,基于 SQLite FTS5 和 BM25 搜索",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
"types": "./dist/index.d.ts"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"files": [
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
16
18
|
"scripts": {
|
|
17
19
|
"build": "tsup src/index.ts --no-dts --format esm,cjs",
|
|
18
20
|
"test": "vitest run",
|
|
@@ -30,6 +32,13 @@
|
|
|
30
32
|
"tsup": "^8.0.0",
|
|
31
33
|
"vitest": "^2.0.0"
|
|
32
34
|
},
|
|
33
|
-
"keywords": [
|
|
35
|
+
"keywords": [
|
|
36
|
+
"opencode",
|
|
37
|
+
"memory",
|
|
38
|
+
"sqlite",
|
|
39
|
+
"fts5",
|
|
40
|
+
"bm25",
|
|
41
|
+
"checkpoint"
|
|
42
|
+
],
|
|
34
43
|
"license": "MIT"
|
|
35
44
|
}
|