e92db73ec6
- Added explicit ArkType schema descriptions across all coding agent tool definitions. - Updated schema definitions in autoresearch and commit tools with descriptive wrappers. - Documented tool schema enhancements in the packages/coding-agent CHANGELOG.
90 lines
2.9 KiB
TypeScript
90 lines
2.9 KiB
TypeScript
import type { AgentTool, AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
import { type } from "arktype";
|
|
import retainDescription from "../prompts/tools/retain.md" with { type: "text" };
|
|
import type { ToolSession } from ".";
|
|
|
|
const memoryRetainSchema = type({
|
|
items: type({
|
|
content: type("string").describe("information to remember"),
|
|
"context?": type("string").describe("source context"),
|
|
})
|
|
.array()
|
|
.atLeastLength(1)
|
|
.describe("memories to retain"),
|
|
});
|
|
|
|
export type MemoryRetainParams = typeof memoryRetainSchema.infer;
|
|
export class MemoryRetainTool implements AgentTool<typeof memoryRetainSchema> {
|
|
readonly name = "retain";
|
|
readonly approval = "read" as const;
|
|
readonly label = "Retain";
|
|
readonly description = retainDescription;
|
|
readonly parameters = memoryRetainSchema;
|
|
readonly strict = true;
|
|
readonly loadMode = "discoverable";
|
|
readonly summary = "Store important facts in long-term memory";
|
|
|
|
constructor(private readonly session: ToolSession) {}
|
|
|
|
static createIf(session: ToolSession): MemoryRetainTool | null {
|
|
const backend = session.settings.get("memory.backend");
|
|
if (backend !== "hindsight" && backend !== "mnemopi") return null;
|
|
return new MemoryRetainTool(session);
|
|
}
|
|
|
|
async execute(_id: string, params: MemoryRetainParams): Promise<AgentToolResult> {
|
|
const backend = this.session.settings.get("memory.backend");
|
|
if (backend === "mnemopi") {
|
|
const state = this.session.getMnemopiSessionState?.();
|
|
if (!state) {
|
|
throw new Error("Mnemopi backend is not initialised for this session.");
|
|
}
|
|
|
|
for (const item of params.items) {
|
|
state.rememberScoped(item.content, {
|
|
source: "coding-agent-retain",
|
|
importance: 0.75,
|
|
metadata: {
|
|
session_id: state.sessionId,
|
|
cwd: state.session.sessionManager.getCwd(),
|
|
context: item.context ?? null,
|
|
tool: "retain",
|
|
},
|
|
scope: "bank",
|
|
extract: true,
|
|
extractEntities: true,
|
|
veracity: "tool",
|
|
memoryType: "fact",
|
|
});
|
|
}
|
|
|
|
const count = params.items.length;
|
|
const noun = count === 1 ? "memory" : "memories";
|
|
return {
|
|
content: [{ type: "text", text: `${count} ${noun} stored.` }],
|
|
details: { count },
|
|
};
|
|
}
|
|
|
|
const state = this.session.getHindsightSessionState?.();
|
|
if (!state) {
|
|
throw new Error("Hindsight backend is not initialised for this session.");
|
|
}
|
|
|
|
// Push every item onto the session-owned queue and return immediately.
|
|
// The queue flushes either when it reaches its batch threshold or when
|
|
// its debounce timer fires. If the eventual batch fails, the queue
|
|
// surfaces a UI-only warning notice — the LLM is not informed.
|
|
for (const item of params.items) {
|
|
state.enqueueRetain(item.content, item.context);
|
|
}
|
|
|
|
const count = params.items.length;
|
|
const noun = count === 1 ? "memory" : "memories";
|
|
return {
|
|
content: [{ type: "text", text: `${count} ${noun} queued.` }],
|
|
details: { count },
|
|
};
|
|
}
|
|
}
|