opencode-claude-memory 1.6.4 → 1.6.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.
Files changed (2) hide show
  1. package/dist/index.js +69 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -98,9 +98,67 @@ function extractRecentTools(messages) {
98
98
  }
99
99
  return tools;
100
100
  }
101
+ // Tracks how many memory entries a memory_list call saw so tool.execute.after
102
+ // can render a meaningful title without re-reading the filesystem. Keyed by
103
+ // callID, which uniquely identifies a single tool invocation.
104
+ const memoryListCountByCallID = new Map();
105
+ const memorySearchCountByCallID = new Map();
106
+ function buildMemoryToolTitle(toolID, args, callID) {
107
+ switch (toolID) {
108
+ case "memory_save": {
109
+ const type = typeof args?.type === "string" ? args.type : "";
110
+ const name = typeof args?.name === "string" ? args.name : "";
111
+ if (type && name)
112
+ return `${type}: ${name}`;
113
+ if (name)
114
+ return name;
115
+ return undefined;
116
+ }
117
+ case "memory_delete":
118
+ case "memory_read": {
119
+ const fileName = typeof args?.file_name === "string" ? args.file_name : "";
120
+ return fileName || undefined;
121
+ }
122
+ case "memory_list": {
123
+ const count = callID ? memoryListCountByCallID.get(callID) : undefined;
124
+ if (callID)
125
+ memoryListCountByCallID.delete(callID);
126
+ if (count === undefined)
127
+ return "list memories";
128
+ return `${count} ${count === 1 ? "memory" : "memories"}`;
129
+ }
130
+ case "memory_search": {
131
+ const query = typeof args?.query === "string" ? args.query : "";
132
+ const count = callID ? memorySearchCountByCallID.get(callID) : undefined;
133
+ if (callID)
134
+ memorySearchCountByCallID.delete(callID);
135
+ if (query && count !== undefined) {
136
+ return `"${query}" · ${count} ${count === 1 ? "match" : "matches"}`;
137
+ }
138
+ if (query)
139
+ return `"${query}"`;
140
+ return undefined;
141
+ }
142
+ default:
143
+ return undefined;
144
+ }
145
+ }
146
+ function getCallID(ctx) {
147
+ if (!ctx || typeof ctx !== "object")
148
+ return undefined;
149
+ const v = ctx.callID;
150
+ return typeof v === "string" ? v : undefined;
151
+ }
101
152
  export const MemoryPlugin = async ({ worktree }) => {
102
153
  getMemoryDir(worktree);
103
154
  return {
155
+ "tool.execute.after": async (input, output) => {
156
+ if (!input.tool.startsWith("memory_"))
157
+ return;
158
+ const title = buildMemoryToolTitle(input.tool, input.args, input.callID);
159
+ if (title)
160
+ output.title = title;
161
+ },
104
162
  "experimental.chat.messages.transform": async (_input, output) => {
105
163
  const { query, sessionID } = getLastUserQuery(output.messages);
106
164
  if (sessionID) {
@@ -177,7 +235,7 @@ export const MemoryPlugin = async ({ worktree }) => {
177
235
  .string()
178
236
  .describe("Memory content. For feedback/project types, structure as: rule/fact, then **Why:** and **How to apply:** lines"),
179
237
  },
180
- async execute(args) {
238
+ async execute(args, _ctx) {
181
239
  const filePath = saveMemory(worktree, args.file_name, args.name, args.description, args.type, args.content);
182
240
  return `Memory saved to ${filePath}`;
183
241
  },
@@ -187,7 +245,7 @@ export const MemoryPlugin = async ({ worktree }) => {
187
245
  args: {
188
246
  file_name: tool.schema.string().describe("File name of the memory to delete (with or without .md extension)"),
189
247
  },
190
- async execute(args) {
248
+ async execute(args, _ctx) {
191
249
  const deleted = deleteMemory(worktree, args.file_name);
192
250
  return deleted ? `Memory "${args.file_name}" deleted.` : `Memory "${args.file_name}" not found.`;
193
251
  },
@@ -197,8 +255,11 @@ export const MemoryPlugin = async ({ worktree }) => {
197
255
  "Use this to check what memories exist before saving a new one (to avoid duplicates) " +
198
256
  "or when you need to recall what's been stored.",
199
257
  args: {},
200
- async execute() {
258
+ async execute(_args, ctx) {
201
259
  const entries = listMemories(worktree);
260
+ const callID = getCallID(ctx);
261
+ if (callID)
262
+ memoryListCountByCallID.set(callID, entries.length);
202
263
  if (entries.length === 0) {
203
264
  return "No memories saved yet.";
204
265
  }
@@ -212,8 +273,11 @@ export const MemoryPlugin = async ({ worktree }) => {
212
273
  args: {
213
274
  query: tool.schema.string().describe("Search query — searches across name, description, and content"),
214
275
  },
215
- async execute(args) {
276
+ async execute(args, ctx) {
216
277
  const results = searchMemories(worktree, args.query);
278
+ const callID = getCallID(ctx);
279
+ if (callID)
280
+ memorySearchCountByCallID.set(callID, results.length);
217
281
  if (results.length === 0) {
218
282
  return `No memories matching "${args.query}".`;
219
283
  }
@@ -226,7 +290,7 @@ export const MemoryPlugin = async ({ worktree }) => {
226
290
  args: {
227
291
  file_name: tool.schema.string().describe("File name of the memory to read (with or without .md extension)"),
228
292
  },
229
- async execute(args) {
293
+ async execute(args, _ctx) {
230
294
  const entry = readMemory(worktree, args.file_name);
231
295
  if (!entry) {
232
296
  return `Memory "${args.file_name}" not found.`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-claude-memory",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "type": "module",
5
5
  "description": "Claude Code-compatible memory compatibility layer for OpenCode — zero config, local-first, no migration",
6
6
  "main": "dist/index.js",