Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
fix(memory): recursive listing so namespaced memories are visible
  • Loading branch information
savagelysubtle committed Aug 23, 2026
commit 538226b4d7db9d2f7037cbbe6991da158f927839
7 changes: 3 additions & 4 deletions packages/core/src/system-context/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ const loadMemoryIndex = Effect.fn("SystemContextBuiltIns.loadMemoryIndex")(funct
) {
const exists = yield* fs.existsSafe(dir)
if (!exists) return ""
const entries = yield* fs.readDirectoryEntries(dir).pipe(Effect.catch(() => Effect.succeed([])))
const files = entries.filter((e) => e.type === "file" && e.name.endsWith(".md"))
const files = (yield* fs.glob("**/*.md", { cwd: dir }).pipe(Effect.catch(() => Effect.succeed([])))).sort()
if (files.length === 0) return ""
const lines: string[] = []
for (const file of files.slice(0, 50)) {
const content =
(yield* fs.readFileStringSafe(path.join(dir, file.name)).pipe(Effect.catch(() => Effect.succeed(undefined))))
(yield* fs.readFileStringSafe(path.join(dir, file)).pipe(Effect.catch(() => Effect.succeed(undefined))))
?.split("\n")
.find((l) => l.trim()) ?? ""
lines.push(`- ${file.name.replace(/\.md$/, "")}${content ? ` — ${content.slice(0, 120)}` : ""}`)
lines.push(`- ${file.replace(/\.md$/, "")}${content ? ` — ${content.slice(0, 120)}` : ""}`)
}
return [
"Persistent project memories recorded by previous sessions (use the memory tool to read or update):",
Expand Down
9 changes: 4 additions & 5 deletions packages/opencode/src/tool/memory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,13 @@ export const MemoryTool = Tool.define<typeof Parameters, Metadata, FSUtil.Servic

if (params.action === "list") {
yield* fs.ensureDir(dir)
const entries = yield* fs.readDirectoryEntries(dir).pipe(Effect.catch(() => Effect.succeed([])))
const files = entries.filter((e) => e.type === "file" && e.name.endsWith(".md"))
const files = (yield* fs.glob("**/*.md", { cwd: dir })).sort()
if (files.length === 0) return { title: "memory", metadata: {}, output: "No memories stored yet." }
const lines = []
for (const file of files) {
for (const file of files.slice(0, 100)) {
const content =
(yield* fs.readFileStringSafe(path.join(dir, file.name)))?.split("\n").find((l) => l.trim()) ?? ""
lines.push(`- ${file.name.replace(/\.md$/, "")}${content ? ` — ${content.slice(0, 120)}` : ""}`)
(yield* fs.readFileStringSafe(path.join(dir, file)))?.split("\n").find((l) => l.trim()) ?? ""
lines.push(`- ${file.replace(/\.md$/, "")}${content ? ` — ${content.slice(0, 120)}` : ""}`)
}
return { title: `${files.length} memories`, metadata: { count: files.length }, output: lines.join("\n") }
}
Expand Down
6 changes: 3 additions & 3 deletions packages/opencode/test/tool/memory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@ describe("MemoryTool", () => {
metadata: () => Effect.void,
} as never

const write = yield* def.execute({ action: "write", name: "user-prefs", content: "# Prefers bun" }, ctx)
const write = yield* def.execute({ action: "write", name: "environment/user-prefs", content: "# Prefers bun" }, ctx)
expect(write.output).toContain("Stored memory")

const list = yield* def.execute({ action: "list" }, ctx)
expect(list.output).toContain("user-prefs")
expect(list.output).toContain("Prefers bun")

const read = yield* def.execute({ action: "read", name: "user-prefs" }, ctx)
const read = yield* def.execute({ action: "read", name: "environment/user-prefs" }, ctx)
expect(read.output).toBe("# Prefers bun")

const del = yield* def.execute({ action: "delete", name: "user-prefs" }, ctx)
const del = yield* def.execute({ action: "delete", name: "environment/user-prefs" }, ctx)
expect(del.output).toContain("Deleted")

const emptyList = yield* def.execute({ action: "list" }, ctx)
Expand Down
Loading