"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTodoReadTool = exports.createTodoWriteTool = void 0;
exports.setTodosForTempDir = setTodosForTempDir;
exports.getTodosForTempDir = getTodosForTempDir;
exports.clearTodosForTempDir = clearTodosForTempDir;
const ai_1 = require("ai");
const path = __importStar(require("path"));
const toolDefinitions_1 = require("../../utils/tools/toolDefinitions");
const toolLimits_1 = require("../../constants/toolLimits");
const helpers_1 = require("../../utils/runtime/helpers");
/**
 * Get path to todos.json file in the stream's temporary directory
 */
function getTodoFilePath(tempDir) {
    return path.join(tempDir, "todos.json");
}
/**
 * Read todos from filesystem using runtime abstraction
 */
async function readTodos(runtime, tempDir) {
    const todoFile = getTodoFilePath(tempDir);
    try {
        const content = await (0, helpers_1.readFileString)(runtime, todoFile);
        return JSON.parse(content);
    }
    catch {
        // File doesn't exist yet or is invalid
        return [];
    }
}
/**
 * Validate todo sequencing rules before persisting.
 * Enforces order: completed → in_progress → pending (top to bottom)
 * Enforces maximum count to encourage summarization.
 */
function validateTodos(todos) {
    if (!Array.isArray(todos)) {
        throw new Error("Invalid todos payload: expected an array");
    }
    if (todos.length === 0) {
        return;
    }
    // Enforce maximum TODO count
    if (todos.length > toolLimits_1.MAX_TODOS) {
        throw new Error(`Too many TODOs (${todos.length}/${toolLimits_1.MAX_TODOS}). ` +
            `Keep high precision at the center: ` +
            `summarize old completed work (e.g., 'Setup phase (3 tasks)'), ` +
            `keep recent completions detailed (1-2), ` +
            `one in_progress, ` +
            `immediate pending detailed (2-3), ` +
            `and summarize far future work (e.g., 'Testing phase (4 items)').`);
    }
    let phase = "completed";
    let inProgressCount = 0;
    todos.forEach((todo, index) => {
        const status = todo.status;
        switch (status) {
            case "completed": {
                if (phase !== "completed") {
                    throw new Error(`Invalid todo order at index ${index}: completed tasks must appear before in-progress or pending tasks`);
                }
                // Stay in completed phase
                break;
            }
            case "in_progress": {
                if (phase === "pending") {
                    throw new Error(`Invalid todo order at index ${index}: in-progress tasks must appear before pending tasks`);
                }
                inProgressCount += 1;
                if (inProgressCount > 1) {
                    throw new Error("Invalid todo list: only one task can be marked as in_progress at a time");
                }
                // Transition to in_progress phase (from completed or stay in in_progress)
                phase = "in_progress";
                break;
            }
            case "pending": {
                // Transition to pending phase (from completed, in_progress, or stay in pending)
                phase = "pending";
                break;
            }
            default: {
                throw new Error(`Invalid todo status at index ${index}: ${String(status)}`);
            }
        }
    });
}
/**
 * Write todos to filesystem using runtime abstraction
 */
async function writeTodos(runtime, tempDir, todos) {
    validateTodos(todos);
    const todoFile = getTodoFilePath(tempDir);
    // Ensure directory exists before writing (SSH runtime might not have created it yet)
    await (0, helpers_1.execBuffered)(runtime, `mkdir -p "${tempDir}"`, { cwd: "/", timeout: 10 });
    await (0, helpers_1.writeFileString)(runtime, todoFile, JSON.stringify(todos, null, 2));
}
/**
 * Todo write tool factory
 * Creates a tool that allows the AI to create/update the todo list
 */
const createTodoWriteTool = (config) => {
    return (0, ai_1.tool)({
        description: toolDefinitions_1.TOOL_DEFINITIONS.todo_write.description,
        inputSchema: toolDefinitions_1.TOOL_DEFINITIONS.todo_write.schema,
        execute: async ({ todos }) => {
            await writeTodos(config.runtime, config.runtimeTempDir, todos);
            return {
                success: true,
                count: todos.length,
            };
        },
    });
};
exports.createTodoWriteTool = createTodoWriteTool;
/**
 * Todo read tool factory
 * Creates a tool that allows the AI to read the current todo list
 */
const createTodoReadTool = (config) => {
    return (0, ai_1.tool)({
        description: toolDefinitions_1.TOOL_DEFINITIONS.todo_read.description,
        inputSchema: toolDefinitions_1.TOOL_DEFINITIONS.todo_read.schema,
        execute: async () => {
            const todos = await readTodos(config.runtime, config.runtimeTempDir);
            return {
                todos,
            };
        },
    });
};
exports.createTodoReadTool = createTodoReadTool;
/**
 * Set todos for a temp directory (useful for testing)
 */
async function setTodosForTempDir(runtime, tempDir, todos) {
    await writeTodos(runtime, tempDir, todos);
}
/**
 * Get todos for a temp directory (useful for testing)
 */
async function getTodosForTempDir(runtime, tempDir) {
    return readTodos(runtime, tempDir);
}
/**
 * Clear todos for a temp directory (useful for testing and cleanup)
 */
async function clearTodosForTempDir(runtime, tempDir) {
    const todoFile = getTodoFilePath(tempDir);
    try {
        await (0, helpers_1.execBuffered)(runtime, `rm -f "${todoFile}"`, { cwd: "/", timeout: 10 });
    }
    catch {
        // File doesn't exist, nothing to clear
    }
}
//# sourceMappingURL=todo.js.map