@scitrera/memorylayer-opencode-plugin 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -0
- package/dist/src/hooks/event.d.ts +15 -0
- package/dist/src/hooks/event.d.ts.map +1 -0
- package/dist/src/hooks/event.js +53 -0
- package/dist/src/hooks/event.js.map +1 -0
- package/dist/src/hooks/message.d.ts +20 -0
- package/dist/src/hooks/message.d.ts.map +1 -0
- package/dist/src/hooks/message.js +128 -0
- package/dist/src/hooks/message.js.map +1 -0
- package/dist/src/hooks/session.d.ts +20 -0
- package/dist/src/hooks/session.d.ts.map +1 -0
- package/dist/src/hooks/session.js +121 -0
- package/dist/src/hooks/session.js.map +1 -0
- package/dist/src/hooks/tool.d.ts +23 -0
- package/dist/src/hooks/tool.d.ts.map +1 -0
- package/dist/src/hooks/tool.js +168 -0
- package/dist/src/hooks/tool.js.map +1 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +176 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/shared/client.d.ts +27 -0
- package/dist/src/shared/client.d.ts.map +1 -0
- package/dist/src/shared/client.js +69 -0
- package/dist/src/shared/client.js.map +1 -0
- package/dist/src/shared/formatters.d.ts +33 -0
- package/dist/src/shared/formatters.d.ts.map +1 -0
- package/dist/src/shared/formatters.js +187 -0
- package/dist/src/shared/formatters.js.map +1 -0
- package/dist/src/shared/observation.d.ts +59 -0
- package/dist/src/shared/observation.d.ts.map +1 -0
- package/dist/src/shared/observation.js +406 -0
- package/dist/src/shared/observation.js.map +1 -0
- package/dist/src/shared/state.d.ts +66 -0
- package/dist/src/shared/state.d.ts.map +1 -0
- package/dist/src/shared/state.js +144 -0
- package/dist/src/shared/state.js.map +1 -0
- package/dist/src/shared/types.d.ts +141 -0
- package/dist/src/shared/types.d.ts.map +1 -0
- package/dist/src/shared/types.js +9 -0
- package/dist/src/shared/types.js.map +1 -0
- package/opencode.example.json +15 -0
- package/package.json +52 -0
- package/src/commands/recall.md +55 -0
- package/src/commands/remember.md +37 -0
- package/src/commands/setup.md +47 -0
- package/src/commands/status.md +59 -0
- package/src/hooks/event.ts +63 -0
- package/src/hooks/message.ts +147 -0
- package/src/hooks/session.ts +127 -0
- package/src/hooks/tool.ts +207 -0
- package/src/index.ts +197 -0
- package/src/shared/client.ts +73 -0
- package/src/shared/formatters.ts +237 -0
- package/src/shared/observation.ts +447 -0
- package/src/shared/state.ts +159 -0
- package/src/shared/types.ts +144 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool execution hooks for MemoryLayer OpenCode plugin.
|
|
3
|
+
*
|
|
4
|
+
* Before-tool: Injects relevant memory context for write/delegation tools.
|
|
5
|
+
* After-tool: Silently captures tool observations as working memory.
|
|
6
|
+
*/
|
|
7
|
+
import { getClient, checkHealth } from "../shared/client.js";
|
|
8
|
+
import { formatRecallResult, formatStorageGuidance } from "../shared/formatters.js";
|
|
9
|
+
import { shouldSkipTool, buildObservation, } from "../shared/observation.js";
|
|
10
|
+
import { wasQueryRecalledThisTurn, markRecallDone, getCurrentTopic, getCurrentPrompt, } from "../shared/state.js";
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Before-tool hook
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Handle pre-tool execution for task/delegation tools.
|
|
16
|
+
* Returns context text to prepend to tool description, or null.
|
|
17
|
+
*/
|
|
18
|
+
async function handleTaskTool(toolArgs) {
|
|
19
|
+
const taskPrompt = (toolArgs.prompt || toolArgs.description || "");
|
|
20
|
+
if (!taskPrompt) {
|
|
21
|
+
return "RECALL-FIRST RULE: Consider using `memory_recall` before delegating to subagent. Subagents cannot access MemoryLayer.";
|
|
22
|
+
}
|
|
23
|
+
const query = taskPrompt.substring(0, 100);
|
|
24
|
+
if (wasQueryRecalledThisTurn(query)) {
|
|
25
|
+
return "Recall already done for this topic. Include relevant memories in subagent prompt.";
|
|
26
|
+
}
|
|
27
|
+
const healthy = await checkHealth();
|
|
28
|
+
if (!healthy)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
const client = getClient();
|
|
32
|
+
const result = await client.recall({ query, limit: 5 });
|
|
33
|
+
markRecallDone(query);
|
|
34
|
+
if (result.memories.length === 0) {
|
|
35
|
+
return "No relevant memories found for this task. Proceeding with delegation.";
|
|
36
|
+
}
|
|
37
|
+
const recallOutput = formatRecallResult(result, query);
|
|
38
|
+
return `INCLUDE IN SUBAGENT PROMPT - Relevant context from memory:\n\n${recallOutput}`;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return "Memory recall failed. Consider manual recall before delegation.";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Handle pre-tool execution for edit/write tools.
|
|
46
|
+
* Returns context text, or null.
|
|
47
|
+
*/
|
|
48
|
+
async function handleEditWriteTool(toolArgs) {
|
|
49
|
+
const filePath = (toolArgs.file_path || toolArgs.path || toolArgs.file || "");
|
|
50
|
+
if (!filePath)
|
|
51
|
+
return null;
|
|
52
|
+
const filename = filePath.split("/").pop() || filePath;
|
|
53
|
+
const topic = getCurrentTopic();
|
|
54
|
+
const query = topic ? `${filename} ${topic}` : `${filename} patterns solutions`;
|
|
55
|
+
if (wasQueryRecalledThisTurn(query))
|
|
56
|
+
return null;
|
|
57
|
+
const healthy = await checkHealth();
|
|
58
|
+
if (!healthy)
|
|
59
|
+
return null;
|
|
60
|
+
try {
|
|
61
|
+
const client = getClient();
|
|
62
|
+
const result = await client.recall({ query, limit: 3 });
|
|
63
|
+
if (result.memories.length === 0)
|
|
64
|
+
return null;
|
|
65
|
+
markRecallDone(query);
|
|
66
|
+
return `Relevant context for ${filename}:\n\n${formatRecallResult(result, filename)}`;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Handle before-tool execution.
|
|
74
|
+
*
|
|
75
|
+
* In OpenCode's hook system, this is called via "tool.execute.before" with
|
|
76
|
+
* (input, output) where we can mutate output.args. We use the return value
|
|
77
|
+
* pattern here and let the entry point handle injection.
|
|
78
|
+
*
|
|
79
|
+
* Returns additional context text, or null.
|
|
80
|
+
*/
|
|
81
|
+
export async function handleToolBefore(toolName, toolArgs) {
|
|
82
|
+
switch (toolName) {
|
|
83
|
+
case "task":
|
|
84
|
+
return handleTaskTool(toolArgs);
|
|
85
|
+
case "edit":
|
|
86
|
+
case "write":
|
|
87
|
+
case "multiedit":
|
|
88
|
+
case "apply_patch":
|
|
89
|
+
return handleEditWriteTool(toolArgs);
|
|
90
|
+
default:
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// After-tool hook
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
/**
|
|
98
|
+
* Store observation asynchronously (fire-and-forget)
|
|
99
|
+
*/
|
|
100
|
+
async function storeObservationAsync(obs) {
|
|
101
|
+
const client = getClient();
|
|
102
|
+
const sessionId = client.getSessionId();
|
|
103
|
+
if (!sessionId)
|
|
104
|
+
return;
|
|
105
|
+
const controller = new AbortController();
|
|
106
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
107
|
+
try {
|
|
108
|
+
await client.setWorkingMemory(sessionId, `obs_${obs.contentHash}`, {
|
|
109
|
+
type: obs.type,
|
|
110
|
+
title: obs.title,
|
|
111
|
+
tool: obs.toolName,
|
|
112
|
+
files_read: obs.filesRead,
|
|
113
|
+
files_modified: obs.filesModified,
|
|
114
|
+
facts: obs.facts,
|
|
115
|
+
concepts: obs.concepts,
|
|
116
|
+
intent: obs.intent,
|
|
117
|
+
summary: obs.summary,
|
|
118
|
+
captured_at: new Date().toISOString(),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Silent failure — never block tool execution
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
clearTimeout(timeout);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if bash output indicates a significant action
|
|
130
|
+
*/
|
|
131
|
+
function isSignificantBashOutput(toolArgs, toolOutput) {
|
|
132
|
+
const command = (toolArgs.command || "");
|
|
133
|
+
// Git commits
|
|
134
|
+
if (/git\s+commit/i.test(command))
|
|
135
|
+
return true;
|
|
136
|
+
// Build commands with errors
|
|
137
|
+
if (/npm\s+run\s+build|cargo\s+build|make\b|tsc\b|bun\s+build/i.test(command)) {
|
|
138
|
+
return /error|fail/i.test(toolOutput);
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Handle after-tool execution — capture observations as working memory.
|
|
144
|
+
*
|
|
145
|
+
* Returns additional context guidance for significant events, or null.
|
|
146
|
+
*/
|
|
147
|
+
export async function handleToolAfter(toolName, toolArgs, toolOutput) {
|
|
148
|
+
if (shouldSkipTool(toolName))
|
|
149
|
+
return null;
|
|
150
|
+
const currentPrompt = getCurrentPrompt();
|
|
151
|
+
const obs = buildObservation(toolName, toolArgs, toolOutput, currentPrompt);
|
|
152
|
+
if (!obs)
|
|
153
|
+
return null;
|
|
154
|
+
// Fire-and-forget storage
|
|
155
|
+
storeObservationAsync(obs).catch(() => { });
|
|
156
|
+
// Return guidance for significant events
|
|
157
|
+
if (toolName === "bash" && isSignificantBashOutput(toolArgs, toolOutput)) {
|
|
158
|
+
const command = (toolArgs.command || "");
|
|
159
|
+
if (/git\s+commit/i.test(command)) {
|
|
160
|
+
return formatStorageGuidance("bash", true);
|
|
161
|
+
}
|
|
162
|
+
if (/build|tsc|make|bun\s+build/i.test(command)) {
|
|
163
|
+
return "Build had errors. Consider storing the issue with `memory_remember` (subtype: error) for future reference.";
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/hooks/tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryLayer OpenCode Plugin
|
|
3
|
+
*
|
|
4
|
+
* Provides persistent memory for OpenCode sessions via hooks that:
|
|
5
|
+
* - Inject workspace briefing and directives at session start
|
|
6
|
+
* - Recall relevant memories when users ask questions
|
|
7
|
+
* - Capture tool observations as working memory
|
|
8
|
+
* - Commit working memory before context compaction
|
|
9
|
+
* - Clean up sessions on exit
|
|
10
|
+
*
|
|
11
|
+
* The plugin works alongside the MemoryLayer MCP server which provides
|
|
12
|
+
* the full suite of 21+ memory tools to the LLM.
|
|
13
|
+
*
|
|
14
|
+
* @module @scitrera/memorylayer-opencode-plugin
|
|
15
|
+
*/
|
|
16
|
+
import type { MemoryLayerHooks, PluginInput, PluginOptions } from "./shared/types.js";
|
|
17
|
+
export type { MemoryLayerHooks, PluginInput, PluginOptions, Part, Model, HookState } from "./shared/types.js";
|
|
18
|
+
/**
|
|
19
|
+
* MemoryLayer plugin for OpenCode.
|
|
20
|
+
*
|
|
21
|
+
* Usage in opencode.json:
|
|
22
|
+
* ```json
|
|
23
|
+
* {
|
|
24
|
+
* "plugin": ["@scitrera/memorylayer-opencode-plugin"]
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export default function memorylayerPlugin(ctx: PluginInput, _options?: PluginOptions): Promise<MemoryLayerHooks>;
|
|
29
|
+
export declare const id = "memorylayer";
|
|
30
|
+
export declare const server: typeof memorylayerPlugin;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAQtF,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAK9G;;;;;;;;;GASG;AACH,wBAA8B,iBAAiB,CAC7C,GAAG,EAAE,WAAW,EAChB,QAAQ,CAAC,EAAE,aAAa,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAsJ3B;AAGD,eAAO,MAAM,EAAE,gBAAgB,CAAC;AAChC,eAAO,MAAM,MAAM,0BAAoB,CAAC"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryLayer OpenCode Plugin
|
|
3
|
+
*
|
|
4
|
+
* Provides persistent memory for OpenCode sessions via hooks that:
|
|
5
|
+
* - Inject workspace briefing and directives at session start
|
|
6
|
+
* - Recall relevant memories when users ask questions
|
|
7
|
+
* - Capture tool observations as working memory
|
|
8
|
+
* - Commit working memory before context compaction
|
|
9
|
+
* - Clean up sessions on exit
|
|
10
|
+
*
|
|
11
|
+
* The plugin works alongside the MemoryLayer MCP server which provides
|
|
12
|
+
* the full suite of 21+ memory tools to the LLM.
|
|
13
|
+
*
|
|
14
|
+
* @module @scitrera/memorylayer-opencode-plugin
|
|
15
|
+
*/
|
|
16
|
+
import { setPluginDirectory } from "./shared/client.js";
|
|
17
|
+
import { initializeSession, finalizeSession } from "./hooks/session.js";
|
|
18
|
+
import { handleUserMessage, extractMessageText } from "./hooks/message.js";
|
|
19
|
+
import { handleToolBefore, handleToolAfter } from "./hooks/tool.js";
|
|
20
|
+
import { handleCompacting } from "./hooks/event.js";
|
|
21
|
+
/** Track whether session has been initialized */
|
|
22
|
+
let sessionInitialized = false;
|
|
23
|
+
/**
|
|
24
|
+
* MemoryLayer plugin for OpenCode.
|
|
25
|
+
*
|
|
26
|
+
* Usage in opencode.json:
|
|
27
|
+
* ```json
|
|
28
|
+
* {
|
|
29
|
+
* "plugin": ["@scitrera/memorylayer-opencode-plugin"]
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export default async function memorylayerPlugin(ctx, _options) {
|
|
34
|
+
// Initialize client with workspace detection from plugin context
|
|
35
|
+
setPluginDirectory(ctx.worktree || ctx.directory);
|
|
36
|
+
const hooks = {
|
|
37
|
+
/**
|
|
38
|
+
* System prompt transform — inject MemoryLayer context on first interaction.
|
|
39
|
+
*
|
|
40
|
+
* This hook modifies the system prompt to include workspace briefing,
|
|
41
|
+
* directives, and session guidance. It runs once per session (on first call)
|
|
42
|
+
* and injects the formatted context into the system prompt array.
|
|
43
|
+
*/
|
|
44
|
+
"experimental.chat.system.transform": async (_input, output) => {
|
|
45
|
+
if (!sessionInitialized) {
|
|
46
|
+
sessionInitialized = true;
|
|
47
|
+
const context = await initializeSession();
|
|
48
|
+
if (context) {
|
|
49
|
+
output.system.push(context);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* User message hook — detect patterns and recall relevant memories.
|
|
55
|
+
*
|
|
56
|
+
* When a user sends a message matching known patterns (preference questions,
|
|
57
|
+
* recall requests, implementation tasks, error reports), this hook performs
|
|
58
|
+
* a targeted recall and injects the results as additional message parts.
|
|
59
|
+
*/
|
|
60
|
+
"chat.message": async (_input, output) => {
|
|
61
|
+
const messageText = extractMessageText(output.parts);
|
|
62
|
+
if (!messageText)
|
|
63
|
+
return;
|
|
64
|
+
const context = await handleUserMessage(messageText);
|
|
65
|
+
if (context) {
|
|
66
|
+
output.parts.push({
|
|
67
|
+
type: "text",
|
|
68
|
+
text: `\n\n<memory-context>\n${context}\n</memory-context>`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Pre-tool hook — inject relevant context before tool execution.
|
|
74
|
+
*
|
|
75
|
+
* For write/edit tools: recalls context relevant to the file being modified.
|
|
76
|
+
* For task/delegation tools: recalls and suggests including context in subagent prompts.
|
|
77
|
+
*/
|
|
78
|
+
"tool.execute.before": async (input, output) => {
|
|
79
|
+
const context = await handleToolBefore(input.tool, output.args);
|
|
80
|
+
if (context) {
|
|
81
|
+
// Inject context as metadata that the LLM can see
|
|
82
|
+
// OpenCode passes args to the tool — we add a _memorylayer_context field
|
|
83
|
+
// that tools can optionally use, and it appears in the tool call metadata
|
|
84
|
+
output.args._memorylayer_context = context;
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* Post-tool hook — capture tool observations as working memory.
|
|
89
|
+
*
|
|
90
|
+
* Silently captures structured observations (files read/modified, facts,
|
|
91
|
+
* concepts, intent) and stores them as working memory. Fire-and-forget
|
|
92
|
+
* to avoid blocking tool execution.
|
|
93
|
+
*
|
|
94
|
+
* For significant events (git commits, build errors), injects guidance
|
|
95
|
+
* suggesting the user store important information.
|
|
96
|
+
*/
|
|
97
|
+
"tool.execute.after": async (input, output) => {
|
|
98
|
+
const guidance = await handleToolAfter(input.tool, input.args, output.output);
|
|
99
|
+
if (guidance) {
|
|
100
|
+
// Append guidance to tool output so the LLM sees it
|
|
101
|
+
output.output = output.output + `\n\n${guidance}`;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
/**
|
|
105
|
+
* Compaction hook — preserve memory state before context window is trimmed.
|
|
106
|
+
*
|
|
107
|
+
* Commits working memory to long-term storage and checkpoints the
|
|
108
|
+
* server-side sandbox so state survives context compaction.
|
|
109
|
+
*/
|
|
110
|
+
"experimental.session.compacting": async (input, output) => {
|
|
111
|
+
const context = await handleCompacting(input.sessionID);
|
|
112
|
+
output.context.push(...context);
|
|
113
|
+
},
|
|
114
|
+
/**
|
|
115
|
+
* Shell environment hook — inject MemoryLayer env vars into shell commands.
|
|
116
|
+
*/
|
|
117
|
+
"shell.env": async (_input, output) => {
|
|
118
|
+
if (process.env.MEMORYLAYER_URL) {
|
|
119
|
+
output.env.MEMORYLAYER_URL = process.env.MEMORYLAYER_URL;
|
|
120
|
+
}
|
|
121
|
+
if (process.env.MEMORYLAYER_API_KEY) {
|
|
122
|
+
output.env.MEMORYLAYER_API_KEY = process.env.MEMORYLAYER_API_KEY;
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
/**
|
|
126
|
+
* Command hook — handle memorylayer slash commands.
|
|
127
|
+
*/
|
|
128
|
+
"command.execute.before": async (input, output) => {
|
|
129
|
+
const cmd = input.command;
|
|
130
|
+
if (cmd === "memorylayer-remember") {
|
|
131
|
+
output.parts.push({
|
|
132
|
+
type: "text",
|
|
133
|
+
text: `Use the \`memory_remember\` tool to store the following: ${input.arguments}\n\nAuto-detect appropriate type, subtype, importance, and tags from the content.`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else if (cmd === "memorylayer-recall") {
|
|
137
|
+
output.parts.push({
|
|
138
|
+
type: "text",
|
|
139
|
+
text: `Use the \`memory_recall\` tool to search for: ${input.arguments}\n\nDisplay results with relevance scores and key metadata.`,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else if (cmd === "memorylayer-status") {
|
|
143
|
+
output.parts.push({
|
|
144
|
+
type: "text",
|
|
145
|
+
text: "Check MemoryLayer connection status: use `memory_briefing` to verify the MCP server is connected, then report server URL, workspace, memory statistics, and active session info.",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
else if (cmd === "memorylayer-setup") {
|
|
149
|
+
output.parts.push({
|
|
150
|
+
type: "text",
|
|
151
|
+
text: [
|
|
152
|
+
"Run MemoryLayer setup verification:",
|
|
153
|
+
"1. Check server health (curl http://localhost:61001/health)",
|
|
154
|
+
"2. Verify MCP tools are connected (call memory_briefing)",
|
|
155
|
+
"3. Smoke test: store a test memory, recall it, then forget it",
|
|
156
|
+
"4. Report: server URL, workspace, tool count, connection status",
|
|
157
|
+
"",
|
|
158
|
+
"If server is not running, suggest: pip install memorylayer-server && memorylayer serve",
|
|
159
|
+
].join("\n"),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
// Register cleanup on process exit
|
|
165
|
+
const cleanup = () => {
|
|
166
|
+
finalizeSession().catch(() => { });
|
|
167
|
+
};
|
|
168
|
+
process.on("beforeExit", cleanup);
|
|
169
|
+
process.on("SIGTERM", cleanup);
|
|
170
|
+
process.on("SIGINT", cleanup);
|
|
171
|
+
return hooks;
|
|
172
|
+
}
|
|
173
|
+
// Also export the plugin as a PluginModule shape
|
|
174
|
+
export const id = "memorylayer";
|
|
175
|
+
export const server = memorylayerPlugin;
|
|
176
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAKpD,iDAAiD;AACjD,IAAI,kBAAkB,GAAG,KAAK,CAAC;AAE/B;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,iBAAiB,CAC7C,GAAgB,EAChB,QAAwB;IAExB,iEAAiE;IACjE,kBAAkB,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IAElD,MAAM,KAAK,GAAqB;QAC9B;;;;;;WAMG;QACH,oCAAoC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC7D,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACxB,kBAAkB,GAAG,IAAI,CAAC;gBAC1B,MAAM,OAAO,GAAG,MAAM,iBAAiB,EAAE,CAAC;gBAC1C,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;QAED;;;;;;WAMG;QACH,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACvC,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACrD,IAAI,CAAC,WAAW;gBAAE,OAAO;YAEzB,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACrD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,yBAAyB,OAAO,qBAAqB;iBAC5D,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED;;;;;WAKG;QACH,qBAAqB,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC7C,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YAChE,IAAI,OAAO,EAAE,CAAC;gBACZ,kDAAkD;gBAClD,yEAAyE;gBACzE,0EAA0E;gBACzE,MAAM,CAAC,IAAgC,CAAC,oBAAoB,GAAG,OAAO,CAAC;YAC1E,CAAC;QACH,CAAC;QAED;;;;;;;;;WASG;QACH,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC5C,MAAM,QAAQ,GAAG,MAAM,eAAe,CACpC,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,IAAI,EACV,MAAM,CAAC,MAAM,CACd,CAAC;YACF,IAAI,QAAQ,EAAE,CAAC;gBACb,oDAAoD;gBACpD,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,OAAO,QAAQ,EAAE,CAAC;YACpD,CAAC;QACH,CAAC;QAED;;;;;WAKG;QACH,iCAAiC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACzD,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACxD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QAClC,CAAC;QAED;;WAEG;QACH,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACpC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;gBAChC,MAAM,CAAC,GAAG,CAAC,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;YAC3D,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;gBACpC,MAAM,CAAC,GAAG,CAAC,mBAAmB,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;YACnE,CAAC;QACH,CAAC;QAED;;WAEG;QACH,wBAAwB,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAChD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;YAE1B,IAAI,GAAG,KAAK,sBAAsB,EAAE,CAAC;gBACnC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,4DAA4D,KAAK,CAAC,SAAS,mFAAmF;iBACrK,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,KAAK,oBAAoB,EAAE,CAAC;gBACxC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,iDAAiD,KAAK,CAAC,SAAS,6DAA6D;iBACpI,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,KAAK,oBAAoB,EAAE,CAAC;gBACxC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,kLAAkL;iBACzL,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,GAAG,KAAK,mBAAmB,EAAE,CAAC;gBACvC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;oBAChB,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;wBACJ,qCAAqC;wBACrC,6DAA6D;wBAC7D,0DAA0D;wBAC1D,+DAA+D;wBAC/D,iEAAiE;wBACjE,EAAE;wBACF,wFAAwF;qBACzF,CAAC,IAAI,CAAC,IAAI,CAAC;iBACb,CAAC,CAAC;YACL,CAAC;QACH,CAAC;KACF,CAAC;IAEF,mCAAmC;IACnC,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,eAAe,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE9B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iDAAiD;AACjD,MAAM,CAAC,MAAM,EAAE,GAAG,aAAa,CAAC;AAChC,MAAM,CAAC,MAAM,MAAM,GAAG,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook client - provides access to the MemoryLayerClient for hook operations.
|
|
3
|
+
*
|
|
4
|
+
* Hooks use the exact same MemoryLayerClient as MCP tools, just with a shorter
|
|
5
|
+
* timeout since hooks need to respond quickly.
|
|
6
|
+
*/
|
|
7
|
+
import { MemoryLayerClient } from "@scitrera/memorylayer-mcp-server";
|
|
8
|
+
/**
|
|
9
|
+
* Set the plugin directory for workspace auto-detection.
|
|
10
|
+
* Called once during plugin initialization. Sets CWD so that
|
|
11
|
+
* detectWorkspaceId() (which reads git config) resolves correctly.
|
|
12
|
+
*/
|
|
13
|
+
export declare function setPluginDirectory(directory: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Get or create the singleton MemoryLayerClient instance.
|
|
16
|
+
* This is the same client class used by MCP tools.
|
|
17
|
+
*
|
|
18
|
+
* On each call, syncs the session ID via resolveSessionId() so that
|
|
19
|
+
* hooks running after session start send the X-Session-ID header for
|
|
20
|
+
* correct workspace resolution on the server.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getClient(): MemoryLayerClient;
|
|
23
|
+
/**
|
|
24
|
+
* Check if the MemoryLayer server is reachable
|
|
25
|
+
*/
|
|
26
|
+
export declare function checkHealth(): Promise<boolean>;
|
|
27
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/shared/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAqB,MAAM,kCAAkC,CAAC;AAMxF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAM1D;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI,iBAAiB,CA0B7C;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAOpD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook client - provides access to the MemoryLayerClient for hook operations.
|
|
3
|
+
*
|
|
4
|
+
* Hooks use the exact same MemoryLayerClient as MCP tools, just with a shorter
|
|
5
|
+
* timeout since hooks need to respond quickly.
|
|
6
|
+
*/
|
|
7
|
+
import { MemoryLayerClient, detectWorkspaceId } from "@scitrera/memorylayer-mcp-server";
|
|
8
|
+
import { resolveSessionId } from "./state.js";
|
|
9
|
+
/** Singleton client instance for hooks */
|
|
10
|
+
let clientInstance = null;
|
|
11
|
+
/**
|
|
12
|
+
* Set the plugin directory for workspace auto-detection.
|
|
13
|
+
* Called once during plugin initialization. Sets CWD so that
|
|
14
|
+
* detectWorkspaceId() (which reads git config) resolves correctly.
|
|
15
|
+
*/
|
|
16
|
+
export function setPluginDirectory(directory) {
|
|
17
|
+
try {
|
|
18
|
+
process.chdir(directory);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Ignore if directory doesn't exist
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get or create the singleton MemoryLayerClient instance.
|
|
26
|
+
* This is the same client class used by MCP tools.
|
|
27
|
+
*
|
|
28
|
+
* On each call, syncs the session ID via resolveSessionId() so that
|
|
29
|
+
* hooks running after session start send the X-Session-ID header for
|
|
30
|
+
* correct workspace resolution on the server.
|
|
31
|
+
*/
|
|
32
|
+
export function getClient() {
|
|
33
|
+
if (!clientInstance) {
|
|
34
|
+
let workspaceId = process.env.MEMORYLAYER_WORKSPACE_ID;
|
|
35
|
+
if (!workspaceId) {
|
|
36
|
+
try {
|
|
37
|
+
workspaceId = detectWorkspaceId();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
workspaceId = "_default";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
clientInstance = new MemoryLayerClient({
|
|
44
|
+
baseUrl: process.env.MEMORYLAYER_URL,
|
|
45
|
+
apiKey: process.env.MEMORYLAYER_API_KEY,
|
|
46
|
+
workspaceId,
|
|
47
|
+
timeout: 5000, // Shorter timeout for hooks
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// Sync session ID on every call
|
|
51
|
+
const sessionId = resolveSessionId("client");
|
|
52
|
+
if (sessionId && clientInstance.getSessionId() !== sessionId) {
|
|
53
|
+
clientInstance.setSessionId(sessionId);
|
|
54
|
+
}
|
|
55
|
+
return clientInstance;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if the MemoryLayer server is reachable
|
|
59
|
+
*/
|
|
60
|
+
export async function checkHealth() {
|
|
61
|
+
try {
|
|
62
|
+
await getClient().getBriefing({ limit: 1, includeMemories: false });
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/shared/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,0CAA0C;AAC1C,IAAI,cAAc,GAA6B,IAAI,CAAC;AAEpD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,IAAI,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;QACvD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,WAAW,GAAG,iBAAiB,EAAE,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,WAAW,GAAG,UAAU,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,cAAc,GAAG,IAAI,iBAAiB,CAAC;YACrC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;YACpC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;YACvC,WAAW;YACX,OAAO,EAAE,IAAI,EAAE,4BAA4B;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,SAAS,IAAI,cAAc,CAAC,YAAY,EAAE,KAAK,SAAS,EAAE,CAAC;QAC7D,cAAc,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format API responses for injection into OpenCode's context.
|
|
3
|
+
*
|
|
4
|
+
* Uses the same types returned by MemoryLayerClient (the MCP adapter),
|
|
5
|
+
* so hooks and MCP tools share the same data contracts.
|
|
6
|
+
*/
|
|
7
|
+
import type { Memory, RecallResult, ToolResponse } from "@scitrera/memorylayer-mcp-server";
|
|
8
|
+
/**
|
|
9
|
+
* Format recall results for context injection
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatRecallResult(result: RecallResult, query: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Format briefing for context injection.
|
|
14
|
+
* Accepts the ToolResponse from MemoryLayerClient.getBriefing().
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatBriefing(briefing: ToolResponse): string;
|
|
17
|
+
/**
|
|
18
|
+
* Format directive memories specially (high importance user instructions)
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatDirectives(memories: Memory[]): string;
|
|
21
|
+
/**
|
|
22
|
+
* Format sandbox state for context injection (post-compaction recovery)
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatSandboxState(inspectResult: Record<string, unknown>): string;
|
|
25
|
+
/**
|
|
26
|
+
* Format combined session start output
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatSessionStart(briefing: ToolResponse | null, directives: Memory[], topicRecall: RecallResult | null, topic?: string, sandboxState?: Record<string, unknown> | null): string;
|
|
29
|
+
/**
|
|
30
|
+
* Format guidance for storing memories after tool use
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatStorageGuidance(toolName: string, isSignificant: boolean): string;
|
|
33
|
+
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../../src/shared/formatters.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AA0B3F;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAmB9E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CA6C7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAmB3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAoBjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,YAAY,GAAG,IAAI,EAC7B,UAAU,EAAE,MAAM,EAAE,EACpB,WAAW,EAAE,YAAY,GAAG,IAAI,EAChC,KAAK,CAAC,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAC5C,MAAM,CAoDR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,MAAM,CAatF"}
|