import { SlashCommandParser } from '../../parser.js';
import { argumentAfterPrefix, slashMessageResult } from '../results.js';
export function createHeartbeatSlashCommandModule() {
    return {
        id: 'heartbeat',
        hints: [
            { command: '/heartbeat tasks', description: 'list heartbeat tasks' },
            { command: '/heartbeat task <id>', description: 'show one heartbeat task' },
            { command: '/heartbeat runs [task]', description: 'list recent heartbeat runs' },
            { command: '/heartbeat run <task> [run-id|latest]', description: 'show one heartbeat run' },
            { command: '/heartbeat continue <task> [run-id|latest]', description: 'continue in chat from a heartbeat run summary' },
        ],
        commands: [
            {
                id: 'heartbeat.tasks',
                syntax: '/heartbeat tasks',
                description: 'list heartbeat tasks',
                match: SlashCommandParser.matchesExact('/heartbeat tasks'),
                run: (context) => listHeartbeatTasksMessage(context),
            },
            {
                id: 'heartbeat.task',
                syntax: '/heartbeat task <id>',
                description: 'show one heartbeat task',
                match: matchesRequiredHeartbeatArgument('/heartbeat task'),
                run: (context, input) => showHeartbeatTask(context, argumentAfterPrefix(input, '/heartbeat task')),
            },
            {
                id: 'heartbeat.runs.list',
                syntax: '/heartbeat runs [task]',
                description: 'list recent heartbeat runs',
                match: SlashCommandParser.matchesPrefix('/heartbeat runs'),
                run: (context, input) => listHeartbeatRunsMessage(context, argumentAfterPrefix(input, '/heartbeat runs')),
            },
            {
                id: 'heartbeat.run.show',
                syntax: '/heartbeat run <task> [run-id|latest]',
                description: 'show one heartbeat run',
                match: matchesRequiredHeartbeatArgument('/heartbeat run'),
                run: (context, input) => showHeartbeatRun(context, argumentAfterPrefix(input, '/heartbeat run')),
            },
            {
                id: 'heartbeat.continue',
                syntax: '/heartbeat continue <task> [run-id|latest]',
                description: 'continue in chat from a heartbeat run summary',
                match: matchesRequiredHeartbeatArgument('/heartbeat continue'),
                run: (context, input) => continueHeartbeatRun(context, argumentAfterPrefix(input, '/heartbeat continue')),
            },
        ],
    };
}
export async function listHeartbeatTasksMessage(context) {
    const tasks = await context.heartbeat.listTasks();
    if (!tasks.length) {
        return slashMessageResult('No heartbeat tasks found.');
    }
    return slashMessageResult(tasks.map(formatHeartbeatTaskListItem).join('\n'));
}
export async function listHeartbeatRunsMessage(context, taskId) {
    const trimmedTaskId = taskId.trim();
    const runs = await context.heartbeat.listRunRecords({
        taskId: trimmedTaskId || undefined,
        limit: 10,
    });
    if (!runs.length) {
        return slashMessageResult(trimmedTaskId ? `No heartbeat runs found for task ${trimmedTaskId}.` : 'No heartbeat runs found.');
    }
    return slashMessageResult(runs.map(formatHeartbeatRunListItem).join('\n'));
}
export function formatHeartbeatTask(task) {
    const state = task.state;
    return [
        `${task.enabled ? 'enabled' : 'disabled'} ${task.id}`,
        `status=${state?.status ?? 'idle'} every=${formatInterval(task.schedule.intervalMs)} next=${task.schedule.nextRunAt ?? 'none'} model=${task.runtime?.model ?? 'default'}`,
        '',
        'Task:',
        task.task,
        '',
        state?.progress ? `Progress: ${state.progress}` : undefined,
        `Last decision: ${state?.result?.decision ?? 'none'}`,
        state?.result ? `Last outcome: ${state.result.state.outcome}` : undefined,
        state?.runAt ? `Last run: ${state.runAt}` : undefined,
        state?.runId ? `Last run id: ${state.runId}` : undefined,
        state?.runId ? `Resumable: ${state.resumable === false ? 'no' : 'yes'}` : undefined,
        state?.runId ? `Loaded checkpoint: ${state.loadedCheckpoint ? 'yes' : 'no'}` : undefined,
        state?.result?.state.usage ? `Usage: input=${state.result.state.usage.inputTokens} output=${state.result.state.usage.outputTokens} total=${state.result.state.usage.totalTokens} requests=${state.result.state.usage.requests}` : undefined,
        state?.error ? `Last error: ${state.error}` : undefined,
        state?.result ? ['', 'Last summary:', stripHeartbeatDecisionLine(state.result.summary).trim() || state.result.summary.trim()].join('\n') : undefined,
    ].filter((line) => line !== undefined).join('\n');
}
export function formatHeartbeatRun(run) {
    const result = run.record.result;
    return [
        `Heartbeat run ${run.id}`,
        `task=${run.taskId} run=${run.runId} loadedCheckpoint=${run.record.loadedCheckpoint}`,
        `decision=${result.decision} outcome=${result.state.outcome} finished=${run.createdAt}`,
        result.state.usage ? `usage input=${result.state.usage.inputTokens} output=${result.state.usage.outputTokens} total=${result.state.usage.totalTokens} requests=${result.state.usage.requests}` : undefined,
        '',
        'Task:',
        run.record.task.task,
        '',
        'Summary:',
        stripHeartbeatDecisionLine(result.summary).trim() || result.summary.trim(),
    ].filter((line) => line !== undefined).join('\n');
}
export function buildHeartbeatContinuationPrompt(run) {
    const result = run.record.result;
    return [
        'Continue from this heartbeat run context.',
        '',
        `Heartbeat task id: ${run.taskId}`,
        `Heartbeat run id: ${run.runId}`,
        `Decision: ${result.decision}`,
        `Outcome: ${result.state.outcome}`,
        `Finished at: ${run.createdAt}`,
        `Loaded checkpoint: ${run.record.loadedCheckpoint}`,
        `Task status: ${run.record.task.state?.status ?? 'unknown'}`,
        run.record.task.state?.progress ? `Task progress: ${run.record.task.state.progress}` : undefined,
        run.record.task.state?.resumable === false ? 'Resumable: no' : 'Resumable: yes',
        '',
        'Durable task:',
        run.record.task.task,
        '',
        'Heartbeat summary:',
        stripHeartbeatDecisionLine(result.summary).trim() || result.summary.trim(),
        '',
        'Treat the heartbeat summary as trusted background context from prior autonomous work. Help the user continue from there.',
    ].filter((line) => line !== undefined).join('\n');
}
export function stripHeartbeatDecisionLine(summary) {
    return summary.replace(/\n?\s*HEARTBEAT_DECISION:\s*(continue|pause|complete|escalate)\s*$/i, '');
}
function matchesRequiredHeartbeatArgument(prefix) {
    return (input) => input.raw.startsWith(`${prefix} `);
}
async function showHeartbeatTask(context, value) {
    const taskId = value.trim();
    const tasks = await context.heartbeat.listTasks();
    const task = tasks.find((candidate) => candidate.id === taskId);
    return task ? slashMessageResult(formatHeartbeatTask(task)) : slashMessageResult(`Heartbeat task not found: ${taskId}`);
}
async function showHeartbeatRun(context, value) {
    const request = parseHeartbeatRunRequest(value);
    const run = await resolveHeartbeatRun(context, request);
    return run ? slashMessageResult(formatHeartbeatRun(run)) : slashMessageResult(`Heartbeat run not found for task ${request.taskId}: ${request.runRef}`);
}
async function continueHeartbeatRun(context, value) {
    const request = parseHeartbeatRunRequest(value);
    const run = await resolveHeartbeatRun(context, request);
    if (!run) {
        return slashMessageResult(`Heartbeat run not found for task ${request.taskId}: ${request.runRef}`);
    }
    return {
        handled: true,
        kind: 'execute',
        displayText: `Continue heartbeat ${request.taskId}`,
        message: `Loaded heartbeat run ${run.id} for task ${request.taskId}. Continuing from that background summary.`,
        prompt: buildHeartbeatContinuationPrompt(run),
    };
}
async function resolveHeartbeatRun(context, request) {
    if (request.runRef === 'latest') {
        return (await context.heartbeat.listRunRecords({ taskId: request.taskId, limit: 1 }))[0];
    }
    const run = await context.heartbeat.loadRunRecord(request.runRef);
    return run?.taskId === request.taskId ? run : undefined;
}
function parseHeartbeatRunRequest(value) {
    const [taskId = '', runRef = 'latest'] = value.split(/\s+/, 2);
    return { taskId, runRef };
}
function formatHeartbeatTaskListItem(task) {
    const next = task.schedule.nextRunAt ?? 'none';
    const state = task.state;
    const decision = state?.result?.decision ?? 'none';
    return [
        `${task.enabled ? 'enabled' : 'disabled'} ${task.id}`,
        `  status=${state?.status ?? 'idle'} every=${formatInterval(task.schedule.intervalMs)} next=${next} decision=${decision}`,
        state?.progress ? `  progress=${state.progress}` : undefined,
    ].filter((line) => line !== undefined).join('\n');
}
function formatHeartbeatRunListItem(run) {
    const summary = firstLine(stripHeartbeatDecisionLine(run.record.result.summary));
    return `${run.id}\n  task=${run.taskId} decision=${run.record.result.decision} outcome=${run.record.result.state.outcome} finished=${run.createdAt}\n  summary=${summary}`;
}
function firstLine(value) {
    const line = value.trim().split('\n').find((candidate) => candidate.trim());
    return line?.trim() ?? '';
}
function formatInterval(intervalMs) {
    if (intervalMs % (24 * 60 * 60_000) === 0)
        return `${intervalMs / (24 * 60 * 60_000)}d`;
    if (intervalMs % (60 * 60_000) === 0)
        return `${intervalMs / (60 * 60_000)}h`;
    if (intervalMs % 60_000 === 0)
        return `${intervalMs / 60_000}m`;
    if (intervalMs % 1_000 === 0)
        return `${intervalMs / 1_000}s`;
    return `${intervalMs}ms`;
}
//# sourceMappingURL=heartbeat-commands.js.map