ci / check (push) Canceled after 0s
The first public release of LLeMbas CLI: a terminal coding agent and project manager for any LLM API, with permission modes, git snapshots, memory and skills, knowledge bases, MCP, voice, and a link to a LLeMbas instance whose web UI can work its sessions too. Signed Linux binaries for x64 and arm64. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
42 lines
2.4 KiB
TypeScript
42 lines
2.4 KiB
TypeScript
// The memory tool, after Hermes Agent's (tools/memory_tool.py, MIT, © Nous Research): one tool,
|
||
// a single change or a batch applied together, checked against the size limit as a whole.
|
||
import { z } from "zod"
|
||
import { MemoryStore, type Op } from "../memory/store.ts"
|
||
import { defineTool, ToolError } from "./tool.ts"
|
||
import { described } from "../harness.ts"
|
||
|
||
const OpSchema = z.object({
|
||
action: z.enum(["add", "replace", "remove"]),
|
||
content: z.string().optional(),
|
||
new_text: z.string().optional(),
|
||
old_text: z.string().optional(),
|
||
})
|
||
|
||
export const memoryTool = defineTool({
|
||
...described("memory"),
|
||
access: "memory",
|
||
schema: z.object({
|
||
target: z.enum(["memory", "user", "project"]),
|
||
action: z.enum(["add", "replace", "remove"]).optional(),
|
||
content: z.string().optional(),
|
||
new_text: z.string().optional(),
|
||
old_text: z.string().optional(),
|
||
operations: z.array(OpSchema).optional(),
|
||
}),
|
||
permission: (a) => ({ permission: "memory", class: "interact", patterns: [a.target] }),
|
||
async run(a, ctx) {
|
||
if (a.target === "project" && !ctx.projectMemory) throw new ToolError("This project has no project memory: it is not trusted, or has no .agent directory. Use 'memory' for facts that hold everywhere.")
|
||
const store = a.target === "project" ? ctx.projectMemory! : (ctx.memory ?? new MemoryStore())
|
||
const norm = (o: z.infer<typeof OpSchema>): Op => ({ action: o.action, content: o.content ?? o.new_text, old_text: o.old_text })
|
||
const ops: Op[] = a.operations?.length ? a.operations.map(norm) : a.action ? [norm({ action: a.action, content: a.content, new_text: a.new_text, old_text: a.old_text })] : []
|
||
if (!ops.length) throw new ToolError("Nothing to do: give action (with content and/or old_text), or operations.")
|
||
const r = store.apply(a.target === "project" ? "memory" : a.target, ops)
|
||
const label = a.target === "user" ? "user profile" : a.target === "project" ? "project memory" : "memory"
|
||
if (!r.ok) {
|
||
const list = r.entries ? `\n\nCurrent entries (${r.usage}):\n${r.entries.map((e, i) => `${i + 1}. ${e}`).join("\n") || "(none)"}` : `\n\n${label}: ${r.usage}`
|
||
return { output: r.message + list, title: `${label}: refused`, isError: true }
|
||
}
|
||
return { output: `${r.message} ${label}: ${r.usage}. Saved — this update is complete; do not repeat it.`, title: `${label} ${ops.map((o) => (o.action === "add" ? "+" : o.action === "remove" ? "−" : "~")).join("")} · ${r.usage.split(" — ")[0]}` }
|
||
},
|
||
})
|