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.
89 lines
3.2 KiB
TypeScript
89 lines
3.2 KiB
TypeScript
import type { AgentTool, AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
import { logger, untilAborted } from "@oh-my-pi/pi-utils";
|
|
import { type } from "arktype";
|
|
import { ensureBankExists } from "../hindsight/bank";
|
|
import reflectDescription from "../prompts/tools/reflect.md" with { type: "text" };
|
|
import type { ToolSession } from ".";
|
|
|
|
const memoryReflectSchema = type({
|
|
query: type("string").describe("question to answer"),
|
|
"context?": type("string").describe("optional context"),
|
|
});
|
|
|
|
export type MemoryReflectParams = typeof memoryReflectSchema.infer;
|
|
|
|
export class MemoryReflectTool implements AgentTool<typeof memoryReflectSchema> {
|
|
readonly name = "reflect";
|
|
readonly approval = "read" as const;
|
|
readonly label = "Reflect";
|
|
readonly description = reflectDescription;
|
|
readonly parameters = memoryReflectSchema;
|
|
readonly strict = true;
|
|
readonly loadMode = "discoverable";
|
|
readonly summary = "Synthesize an answer from long-term memory";
|
|
|
|
constructor(private readonly session: ToolSession) {}
|
|
|
|
static createIf(session: ToolSession): MemoryReflectTool | null {
|
|
const backend = session.settings.get("memory.backend");
|
|
if (backend !== "hindsight" && backend !== "mnemopi") return null;
|
|
return new MemoryReflectTool(session);
|
|
}
|
|
|
|
async execute(_id: string, params: MemoryReflectParams, signal?: AbortSignal): Promise<AgentToolResult> {
|
|
return untilAborted(signal, async () => {
|
|
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.");
|
|
}
|
|
|
|
try {
|
|
const query = params.context?.trim()
|
|
? `${params.query.trim()}\n\nAdditional context:\n${params.context.trim()}`
|
|
: params.query;
|
|
const results = await state.recallResultsScoped(query);
|
|
if (results.length === 0) {
|
|
return {
|
|
content: [{ type: "text", text: "No relevant information found to reflect on." }],
|
|
details: {},
|
|
};
|
|
}
|
|
const summary = state.formatContextScoped(results);
|
|
return {
|
|
content: [{ type: "text", text: `Based on recalled memories:\n\n${summary}` }],
|
|
details: {},
|
|
};
|
|
} catch (err) {
|
|
logger.warn("reflect failed", { backend: "mnemopi", bank: state.config.bank, error: String(err) });
|
|
throw err instanceof Error ? err : new Error(String(err));
|
|
}
|
|
}
|
|
|
|
const state = this.session.getHindsightSessionState?.();
|
|
if (!state) {
|
|
throw new Error("Hindsight backend is not initialised for this session.");
|
|
}
|
|
|
|
try {
|
|
await ensureBankExists(state.client, state.bankId, state.config, state.banksSet);
|
|
const response = await state.client.reflect(state.bankId, params.query, {
|
|
context: params.context,
|
|
budget: state.config.recallBudget,
|
|
tags: state.recallTags,
|
|
tagsMatch: state.recallTagsMatch,
|
|
});
|
|
const text = response.text?.trim() || "No relevant information found to reflect on.";
|
|
return {
|
|
content: [{ type: "text", text }],
|
|
details: {},
|
|
};
|
|
} catch (err) {
|
|
logger.warn("reflect failed", { bankId: state.bankId, error: String(err) });
|
|
throw err instanceof Error ? err : new Error(String(err));
|
|
}
|
|
});
|
|
}
|
|
}
|