// SF — Exec (context-mode) tool registration.
//
// Registers the `resume_agent` and `kill_agent` tools as native SF agent tools.
// Note: `run_command` and `read_output` were removed in the 2026-05-17 atomic
// tool-rename cutover (operator-direction). Use Bash for shell execution.
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { Type } from "@sinclair/typebox";

// Headless exit code for "reload with session resume".  Correlates with
// EXIT_RELOAD in src/headless-events.ts — kept in sync manually.
const EXIT_RELOAD = 12;

import { executeResume } from "../tools/resume-tool.js";
export function registerExecTools(pi) {
	pi.registerTool({
		name: "resume_agent",
		label: "Resume (Read Snapshot)",
		description:
			"Read the saved session snapshot and return a compact summary of recent commands, top memories, and active context. " +
			"Use this immediately after context compaction or session resume to re-orient before continuing work.",
		promptSnippet:
			"Read the pre-compaction snapshot to re-orient after context loss",
		promptGuidelines: [
			"Call this right after a session resumes if you feel you've lost durable context.",
			"The snapshot is a summary — use memory_search or read_output for detail.",
		],
		parameters: Type.Object({}),
		async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
			return executeResume(params, {
				baseDir: process.cwd(),
			});
		},
	});
	/**
	 * Reload the agent — snapshot state, restart, and resume the same session.
	 *
	 * In the machine surface: writes sessionId to a sentinel file and exits with EXIT_RELOAD.
	 * The supervisor detects EXIT_RELOAD, reads the sessionId, and restarts with --resume.
	 * The agent resumes the same session with fresh extension code.
	 *
	 * In interactive TUI: exits the process (no session resume possible in TUI).
	 *
	 * Use after updating extension config files (e.g. ~/.mcp.json, ~/.sf/mcp.json)
	 * that require a process restart to take effect.
	 */
	pi.registerTool({
		name: "kill_agent",
		label: "Reload Agent (Snapshot & Resume)",
		description:
			"Snapshot the current session, kill the agent, and restart it resuming the same session. " +
			"Use after updating extension config files (e.g. ~/.mcp.json) that require a process restart. " +
			"The supervisor resumes the same session — agent continues from where it left off. " +
			"In interactive TUI: exits without session resume.",
		promptSnippet:
			"Snapshot and reload the pi-agent so it resumes the same session with fresh extension code",
		promptGuidelines: [
			"Use this to reload extension code, external MCP server config, or native tools without losing the session.",
			"The machine-surface supervisor will resume the same session automatically.",
			"In interactive TUI: the process exits and you restart manually.",
		],
		parameters: Type.Object({}),
		async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
			const tmpDir = process.env.TEMP ?? "/tmp";
			const sessionIdFile = join(tmpDir, "sf-current-session");
			const sentinelFile = join(tmpDir, "sf-reload-sentinel");
			// Read sessionId and write sentinel so runHeadless can resume this session
			if (existsSync(sessionIdFile)) {
				try {
					const sessionId = readFileSync(sessionIdFile, "utf-8").trim();
					if (sessionId) {
						writeFileSync(sentinelFile, sessionId, "utf-8");
					}
				} catch {
					// Fall through — exit with EXIT_RELOAD even without sessionId
				}
			}
			// Clear the session file so stale entries don't persist across reloads
			try {
				unlinkSync(sessionIdFile);
			} catch {
				// non-fatal
			}
			// EXIT_RELOAD (12) tells runHeadless to resume the session.
			// Falls back to normal restart if sentinel was not written.
			process.exit(EXIT_RELOAD);
			// unreachable
		},
	});
}
