// SF Bootstrap — session_todo tool registration.
//
// Purpose: expose manage_todos as a native agent tool so the agent can
// maintain a durable per-session task checklist that survives context
// compaction (items persist in .sf/session_todo.json).
//
// Consumer: register-extension.js, which calls registerSessionTodoTool(pi).
import { Type } from "@sinclair/typebox";
import {
	executeSessionTodoAdd,
	executeSessionTodoCheck,
	executeSessionTodoList,
} from "../tools/session-todo-tool.js";

/**
 * Register the manage_todos tool with the pi extension API.
 *
 * Purpose: give the agent a file-backed checklist tool so in-session tasks
 * survive context compaction without relying on context-window memory.
 * Consumer: register-extension.js non-critical registration loop.
 */
export function registerSessionTodoTool(pi) {
	pi.registerTool({
		name: "manage_todos",
		label: "Session Todo",
		description:
			"Manage a per-session task checklist backed by .sf/session_todo.json. " +
			"Items survive context compaction and are included in the pre-compaction " +
			"snapshot. Use this instead of relying on context-window memory for " +
			"multi-step checklists within a single session.",
		promptSnippet:
			"Add, check off, or list session-scoped tasks that survive compaction",
		promptGuidelines: [
			"Add todos at the start of complex multi-step work so you don't lose track after compaction.",
			"Check items off as you complete them — the list is visible in resume_agent after compaction.",
			"Use list before starting a new sub-task to see what remains.",
		],
		parameters: Type.Object({
			op: Type.Union(
				[Type.Literal("add"), Type.Literal("check"), Type.Literal("list")],
				{
					description:
						'Operation: "add" appends a new item, "check" marks one done, "list" shows all.',
				},
			),
			text: Type.Optional(
				Type.String({
					description: 'Text of the new todo item. Required for op="add".',
				}),
			),
			id: Type.Optional(
				Type.String({
					description: 'Id of the todo to check off. Required for op="check".',
				}),
			),
		}),
		async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
			const baseDir = process.cwd();
			switch (params.op) {
				case "add": {
					if (!params.text || params.text.trim() === "") {
						return {
							content: [
								{
									type: "text",
									text: 'Error: op="add" requires a non-empty "text" parameter.',
								},
							],
							details: { operation: "add", error: "missing_text" },
							isError: true,
						};
					}
					return executeSessionTodoAdd({ text: params.text }, baseDir);
				}
				case "check": {
					if (!params.id || params.id.trim() === "") {
						return {
							content: [
								{
									type: "text",
									text: 'Error: op="check" requires an "id" parameter.',
								},
							],
							details: { operation: "check", error: "missing_id" },
							isError: true,
						};
					}
					return executeSessionTodoCheck({ id: params.id }, baseDir);
				}
				case "list":
					return executeSessionTodoList(baseDir);
				default:
					return {
						content: [
							{
								type: "text",
								text: `Error: unknown op "${params.op}". Use "add", "check", or "list".`,
							},
						],
						details: { operation: params.op, error: "unknown_op" },
						isError: true,
					};
			}
		},
	});
}
