import z from "zod";
import { createToolFactory, PermissionLevel, ToolCategory } from "../types.js";
const rememberKnowledgeCandidateSchema = z.object({
    name: z
        .string()
        .describe('A short, unique, human-readable name for this knowledge entry (e.g. "No Emojis in UI")'),
    description: z
        .string()
        .describe("A one-sentence summary that acts as a retrieval trigger for when this knowledge entry should be applied"),
    content: z
        .string()
        .describe("The full content of the knowledge entry — a clear, actionable rule or preference"),
    targetFactName: z
        .string()
        .optional()
        .describe("For action=update or action=delete: the name of an existing knowledge entry to modify"),
    action: z
        .enum(["create", "update", "delete"])
        .optional()
        .default("create")
        .describe("Whether to create a new knowledge entry, update an existing one, or delete one"),
    reason: z
        .string()
        .optional()
        .describe("Optional explanation of why this knowledge entry is being remembered"),
});
/**
 * The rememberKnowledge tool is a *signal* tool — it does not persist anything itself.
 *
 * When Clark calls it, it:
 * 1. Sets `clark.context.rememberKnowledgeCandidatesForTurn` with the candidates
 * 2. Triggers the approval flow for those candidates
 *
 * The actual persistence is handled in the llm-generating handler after the user confirms.
 *
 * This tool should be available from normal chat flow whenever Clark detects
 * the user wants to remember something.
 */
export const rememberKnowledgeToolFactory = createToolFactory("rememberKnowledge", ({ clark }) => {
    return {
        category: ToolCategory.MEMORY,
        readOnly: true,
        defaultPermission: PermissionLevel.ALLOW,
        description: `Use this tool when the user wants you to remember, save, or keep track of a preference, rule, or instruction specific to this application.

Call this tool when the user:
- Explicitly says "/remember" or "remember this"
- Says things like "always use X", "make sure you never Y", "I want you to know that Z"
- Indicates a persistent preference or rule they want applied to this app going forward

You should draft one or more knowledge-entry candidates based on what the user wants to remember.
Each candidate should have:
- A short, unique name
- A clear one-sentence description that works as a retrieval trigger: include what the knowledge entry governs and the kinds of user requests/phrases that should activate it
- The full rule/preference as content — **use Markdown** to structure the content: use headings, bullet lists, bold, and code blocks where appropriate so the knowledge entry is easy to read and follow

After calling this tool, continue with the rest of the user's request. The knowledge entry is NOT saved yet — it will be shown to the user for approval. Do not tell the user that it's saved or remembered; say you've drafted it for their review.
Do NOT call this tool for one-off instructions that only apply to the current task.

Read existing knowledge before drafting new entries, and avoid duplicates unless you intend to update.`,
        inputSchema: z.object({
            candidates: z
                .array(rememberKnowledgeCandidateSchema)
                .min(1)
                .describe("One or more knowledge entries to remember. Typically just one per call."),
        }),
        execute: async ({ candidates, }) => {
            // Validate: reject placeholder content
            const PLACEHOLDER_PATTERNS = [
                /^update this knowledge/i,
                /^placeholder/i,
                /\[(?:insert|fill|replace|your|add|placeholder|todo|knowledge|content|description|name)\b.*\]/i,
                /^TODO/i,
            ];
            const validCandidates = candidates.filter((c) => {
                const isPlaceholder = PLACEHOLDER_PATTERNS.some((p) => p.test(c.content) || p.test(c.name));
                return (!isPlaceholder &&
                    c.content.trim().length > 0 &&
                    c.name.trim().length > 0);
            });
            if (validCandidates.length === 0) {
                return {
                    success: false,
                    message: "No valid knowledge-entry candidates provided. Please provide specific, non-placeholder content.",
                };
            }
            const normalizedCandidates = validCandidates;
            // Store candidates in Clark context for approval message handling
            clark.updateContext((ctx) => ({
                ...ctx,
                rememberKnowledgeCandidatesForTurn: normalizedCandidates,
                explicitRememberKnowledgeIntentForTurn: true,
            }));
            const recentOutcomes = clark.context.recentKnowledgeSaveOutcomes ?? [];
            const recentNames = new Set(recentOutcomes
                .filter((outcome) => outcome.status !== "failed")
                .map((outcome) => outcome.factName.trim().toLowerCase()));
            const recentlySavedMatches = normalizedCandidates
                .filter((candidate) => recentNames.has(candidate.name.trim().toLowerCase()))
                .map((candidate) => candidate.name);
            return {
                success: true,
                message: `Drafted ${normalizedCandidates.length} knowledge entr${normalizedCandidates.length === 1 ? "y" : "ies"} for user approval. Not saved yet — continue with the user's request.`,
                candidates: normalizedCandidates,
                recentlySavedMatches,
            };
        },
    };
});
//# sourceMappingURL=remember-knowledge.js.map