spb/khaelor Public
KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.
TypeScript 82.9%
HTML 14.9%
CSS 1.1%
JavaScript 0.7%
1/**2 * KHAELOR3 * File: src/tools/remember.ts4 * Description: The remember tool — persist a durable project fact into .khaelor/MEMORY.md with provenance (v2 design §5).5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import * as path from "node:path";11import type { ToolDefinition } from "./registry.js";12import type { ToolContext, ToolResult } from "./types.js";1314export interface RememberInput {15 fact: string;16 section: string;17 confidence?: string;18}1920const DESCRIPTION =21 "Persist a durable fact about this project into its memory (.khaelor/MEMORY.md) — a convention, a " +22 "build command, a pitfall, an architectural constraint. Use it when you discover something future " +23 "sessions must know. Do NOT store transient task state. section: conventions | commands | pitfalls " +24 "| architecture | notes. confidence defaults to medium.";2526const MEMORY_RELATIVE = ".khaelor/MEMORY.md";2728// Local re-implementation seam: the memory module's append logic is imported29// lazily to keep the tools layer free of static cross-module dependencies.30async function appendToMemory(31 existing: string | null,32 entry: {33 section: string;34 text: string;35 provenance: { session: string; tool: string; confidence: "high" | "medium" | "low"; date: string };36 },37): Promise<string> {38 const { appendMemoryEntry } = await import("../memory/store.js");39 return appendMemoryEntry(existing, entry);40}4142async function executeRemember(input: RememberInput, ctx: ToolContext): Promise<ToolResult> {43 const startedAt = Date.now();44 const fact = input.fact.trim();45 if (fact.length === 0) {46 return {47 content: 'Parameter "fact" must be a non-empty durable fact about the project.',48 isError: true,49 metadata: { title: "remember · empty fact", durationMs: Date.now() - startedAt },50 };51 }52 const confidence =53 input.confidence === "high" || input.confidence === "low" ? input.confidence : "medium";54 const filePath = path.join(ctx.workspace.cwd(), MEMORY_RELATIVE);5556 let existing: string | null = null;57 try {58 existing = await ctx.workspace.readFile(filePath);59 } catch {60 existing = null; // first memory — the file is created below61 }6263 const updated = await appendToMemory(existing, {64 section: input.section,65 text: fact,66 provenance: {67 session: ctx.sessionId,68 tool: ctx.callId,69 confidence,70 date: new Date().toISOString().slice(0, 10),71 },72 });73 await ctx.workspace.writeFile(filePath, updated);7475 ctx.emit({76 type: "memory.written",77 payload: { section: input.section, entry: fact, confidence, toolUseId: ctx.callId },78 });7980 return {81 content: `Remembered under "${input.section}" (confidence: ${confidence}).`,82 metadata: {83 title: `Remember · ${input.section}`,84 durationMs: Date.now() - startedAt,85 extra: { confidence },86 },87 };88}8990/** Build the remember tool (project memory, v2 §5). */91export function createRememberTool(): ToolDefinition<RememberInput> {92 return {93 name: "remember",94 description: DESCRIPTION,95 inputSchema: {96 type: "object",97 properties: {98 fact: { type: "string", description: "The durable fact, one or two sentences." },99 section: {100 type: "string",101 description: "Where it belongs: conventions, commands, pitfalls, architecture, or notes.",102 enum: ["conventions", "commands", "pitfalls", "architecture", "notes"],103 },104 confidence: {105 type: "string",106 description: "How certain you are: high, medium (default), or low.",107 enum: ["high", "medium", "low"],108 },109 },110 required: ["fact", "section"],111 },112 capability: "file.write",113 execute: executeRemember,114 };115}116