"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.classifyAgenticMode = classifyAgenticMode;
exports.handleOperateModeRequest = handleOperateModeRequest;
exports.createOrUpdateBulletJournalService = createOrUpdateBulletJournalService;
exports.listAgenticServices = listAgenticServices;
exports.getAgenticService = getAgenticService;
exports.exportAgenticServices = exportAgenticServices;
exports.importAgenticServices = importAgenticServices;
exports.createOrUpdateGenericOperateService = createOrUpdateGenericOperateService;
const crypto = __importStar(require("crypto"));
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const jobs_1 = require("../automation/jobs");
const modeClassifier_1 = require("./modeClassifier");
const commandExtractor_1 = require("./commandExtractor");
const promiseLedger_1 = require("./promiseLedger");
const OPERATE_TRIGGERS = [
    'send me reminders',
    'send me a reminder',
    'send me telegram reminder',
    'telegram reminder',
    'remind me',
    'remind me daily',
    'check in with me',
    'keep track of',
    'let me add tasks',
    'let me update tasks',
    'update for me',
    'let me close tasks',
    'add notes',
    'manage this for me',
    'keep me honest',
    'follow up',
    'monitor this',
    'notify me',
    'ask me every morning',
    'review this each day',
    'keep a log',
];
const BULLET_JOURNAL_COMMANDS = [
    'add_task',
    'update_task',
    'close_task',
    'reopen_task',
    'add_note',
    'edit_note',
    'delete_note',
    'show_today',
    'show_open_tasks',
    'show_closed_tasks',
    'daily_review',
    'weekly_review',
    'set_reminder_time',
    'pause_reminders',
    'resume_reminders',
];
function classifyAgenticMode(message) {
    const lower = message.toLowerCase();
    if (looksLikeExternalBulletJournalTaskRequest(lower)) {
        return { mode: 'build', reason: 'Request targets an existing bullet journal rather than an operating service command.', matchedTriggers: [] };
    }
    const canonical = (0, modeClassifier_1.classifyMode)(message);
    if (canonical.mode === 'build') {
        return { mode: 'build', reason: `Canonical mode classifier selected BUILD mode: ${canonical.reason}`, matchedTriggers: canonical.matchedPatterns };
    }
    if (canonical.mode === 'operate' && !explicitlyRequestsSoftwareBuild(lower)) {
        return { mode: 'operate', reason: `Canonical mode classifier selected OPERATE mode: ${canonical.reason}`, matchedTriggers: canonical.matchedPatterns };
    }
    const matchedTriggers = OPERATE_TRIGGERS.filter((trigger) => lower.includes(trigger));
    if (matchedTriggers.length > 0 && !explicitlyRequestsSoftwareBuild(lower)) {
        return { mode: 'operate', reason: 'Request asks for ongoing service behavior.', matchedTriggers };
    }
    if (looksLikeBulletJournalServiceRequest(lower) && !explicitlyRequestsSoftwareBuild(lower)) {
        return { mode: 'operate', reason: 'Request asks for a bullet journal operating service.', matchedTriggers: ['bullet journal'] };
    }
    if (/\b(check|scan|visit|look at|watch)\b[\s\S]{0,200}\b(daily|every day|each day|every morning)\b/.test(lower) && !explicitlyRequestsSoftwareBuild(lower)) {
        return { mode: 'operate', reason: 'Request asks for a recurring check.', matchedTriggers: ['recurring check'] };
    }
    if (looksLikeAgenticSearchRequest(lower) && !explicitlyRequestsSoftwareBuild(lower)) {
        return { mode: 'operate', reason: 'Request asks for ongoing search or availability monitoring.', matchedTriggers: ['agentic search'] };
    }
    if (looksLikeBulletJournalCommand(lower)) {
        return { mode: 'operate', reason: 'Request matches a bullet journal service command.', matchedTriggers: ['bullet journal command'] };
    }
    if (looksLikeGenericOperateCommand(lower)) {
        return { mode: 'operate', reason: 'Request matches an operating service command.', matchedTriggers: ['operating service command'] };
    }
    return { mode: 'build', reason: 'No ongoing service trigger detected.', matchedTriggers: [] };
}
async function handleOperateModeRequest(projectDir, message, now = new Date(), options) {
    const classification = classifyAgenticMode(message);
    if (classification.mode !== 'operate')
        return { handled: false, response: '', classification };
    const checkCaps = options?.checkCapabilities;
    const genericCommand = parseGenericOperateCommand(message);
    if (genericCommand && !isBulletJournalRequest(message)) {
        const commandResult = await applyGenericOperateCommand(projectDir, genericCommand, now);
        return { handled: true, response: commandResult.response, classification, service: commandResult.service, state: commandResult.state, schedule: commandResult.schedule };
    }
    if (!isBulletJournalRequest(message)) {
        const result = await createOrUpdateGenericOperateService(projectDir, message, now);
        const limitations = checkCaps ? checkCaps(['scheduler', 'notifications']) : null;
        return {
            handled: true,
            response: [
                `${result.service.service_name} is set up.`,
                result.schedule ? `I will check it every day at 09:00.` : 'Operating service state can be created, but proactive reminders require a scheduler/automation capability.',
                limitations ? limitations : '',
                'You can ask for status, add notes, pause reminders, or resume reminders.',
                `Current state: ${result.state.observations.length} observation(s), ${result.state.notes.length} note(s).`,
            ].filter(Boolean).join(' '),
            classification,
            service: result.service,
            state: result.state,
            schedule: result.schedule,
            capabilityLimitations: limitations,
        };
    }
    const command = parseBulletJournalCommand(message);
    if (command) {
        const commandResult = await applyBulletJournalCommand(projectDir, command, now);
        return { handled: true, response: commandResult.response, classification, service: commandResult.service, state: commandResult.state, schedule: commandResult.schedule };
    }
    const result = await createOrUpdateBulletJournalService(projectDir, { reminderTime: parseReminderTime(message) ?? '09:00' }, now);
    const limitations = checkCaps ? checkCaps(['scheduler', 'notifications']) : null;
    const scheduleText = result.schedule
        ? `I will check in every day at ${result.state.reminder_time}.`
        : 'Operating service state can be created, but proactive reminders require a scheduler/automation capability.';
    return {
        handled: true,
        response: [
            'Your Bullet Journal agent is set up.',
            scheduleText,
            limitations ? limitations : '',
            'You can say: add task..., close task..., update task..., add note..., show today, show open tasks, show closed tasks, daily review, weekly review, pause reminders, or resume reminders.',
            `Current state: ${openTasks(result.state).length} open task(s), ${result.state.closed_tasks.length} closed task(s), ${result.state.notes.length} note(s).`,
        ].filter(Boolean).join(' '),
        classification,
        service: result.service,
        state: result.state,
        schedule: result.schedule,
        capabilityLimitations: limitations,
    };
}
async function createOrUpdateBulletJournalService(projectDir, input = {}, now = new Date()) {
    const storageDir = bulletJournalDir(projectDir);
    const state = await loadBulletJournalState(projectDir, now);
    state.reminder_time = normalizeReminderTime(input.reminderTime) ?? state.reminder_time;
    state.updated_at = now.toISOString();
    const service = await loadBulletJournalDefinition(projectDir, now);
    service.updated_at = now.toISOString();
    service.storage_location = path.relative(projectDir, storageDir).split(path.sep).join('/');
    const schedule = await ensureBulletJournalSchedule(projectDir, service, state.reminder_time, now);
    service.automation_job_id = schedule?.id;
    service.schedules = [{ id: 'daily_check_in', type: 'cron', expression: dailyCron(state.reminder_time), enabled: !state.reminders_paused && state.enabled, automation_job_id: schedule?.id ?? null }];
    await saveBulletJournalDefinition(projectDir, service);
    await saveBulletJournalState(projectDir, state);
    // Auto-create a promise for the scheduled service if one doesn't already exist.
    if (schedule) {
        const existing = await (0, promiseLedger_1.listPromises)(projectDir, { service_id: service.service_id });
        if (!existing.some((p) => p.schedule_id === schedule.id && p.status === 'pending')) {
            (0, promiseLedger_1.createPromise)(projectDir, `Daily check-in for ${service.service_name} at ${state.reminder_time}`, {
                service_id: service.service_id,
                schedule_id: schedule.id,
                capability_required: 'scheduler',
            }).catch(() => { });
        }
    }
    return { service, state, schedule };
}
async function listAgenticServices(projectDir) {
    let entries = [];
    try {
        entries = await fs.readdir(servicesDir(projectDir), { withFileTypes: true });
    }
    catch {
        return [];
    }
    const services = [];
    for (const entry of entries) {
        if (!entry.isDirectory())
            continue;
        const stored = await getAgenticService(projectDir, entry.name);
        if (stored)
            services.push(stored);
    }
    services.sort((a, b) => b.service.updated_at.localeCompare(a.service.updated_at));
    return services;
}
async function getAgenticService(projectDir, serviceId) {
    if (!/^[a-zA-Z0-9._-]+$/.test(serviceId))
        return null;
    const servicePath = path.join(servicesDir(projectDir), serviceId, 'service.json');
    const statePath = path.join(servicesDir(projectDir), serviceId, 'state.json');
    try {
        const [serviceRaw, stateRaw] = await Promise.all([fs.readFile(servicePath, 'utf-8'), fs.readFile(statePath, 'utf-8')]);
        return { service: JSON.parse(serviceRaw), state: JSON.parse(stateRaw) };
    }
    catch {
        return null;
    }
}
async function exportAgenticServices(projectDir, serviceIds, now = new Date()) {
    const requestedIds = serviceIds?.map((id) => id.trim()).filter(Boolean);
    const services = requestedIds && requestedIds.length > 0
        ? (await Promise.all(requestedIds.map((id) => getAgenticService(projectDir, id)))).filter((item) => Boolean(item))
        : await listAgenticServices(projectDir);
    return { version: 1, exported_at: now.toISOString(), source: 'ollama-agent-harness', services };
}
async function importAgenticServices(projectDir, payload, options = {}, now = new Date()) {
    const source = typeof payload === 'object' && payload !== null ? payload : {};
    if (source.version !== 1 || !Array.isArray(source.services))
        throw new Error('Invalid operating services export payload.');
    const imported = [];
    const skipped = [];
    for (const item of source.services) {
        if (!isStoredAgenticService(item))
            throw new Error('Invalid operating service entry.');
        const serviceId = item.service.service_id;
        if (!/^[a-zA-Z0-9._-]+$/.test(serviceId))
            throw new Error(`Invalid service id: ${serviceId}`);
        const existing = await getAgenticService(projectDir, serviceId);
        if (existing && !options.overwrite) {
            skipped.push(serviceId);
            continue;
        }
        const service = { ...item.service, storage_location: `.harness/services/${serviceId}` };
        delete service.automation_job_id;
        const state = typeof item.state === 'object' && item.state !== null ? { ...item.state, service_id: serviceId, mode: 'operate' } : item.state;
        const dir = path.join(servicesDir(projectDir), serviceId);
        service.schedules = (service.schedules || []).map((entry) => ({ ...entry, automation_job_id: null, enabled: serviceStateEnabled(state) }));
        await fs.mkdir(dir, { recursive: true });
        await fs.writeFile(path.join(dir, 'service.json'), JSON.stringify(service, null, 2), 'utf-8');
        await fs.writeFile(path.join(dir, 'state.json'), JSON.stringify(state, null, 2), 'utf-8');
        if (serviceStateEnabled(state)) {
            const schedule = serviceId === 'bullet_journal'
                ? await ensureBulletJournalSchedule(projectDir, service, typeof state.reminder_time === 'string' ? state.reminder_time : '09:00', now)
                : await ensureGenericOperateSchedule(projectDir, service, service.purpose, extractUrl(service.purpose), now);
            service.automation_job_id = schedule?.id;
            service.schedules = (service.schedules || []).map((entry) => ({ ...entry, automation_job_id: schedule?.id ?? null, enabled: Boolean(schedule) }));
            service.updated_at = now.toISOString();
            await fs.writeFile(path.join(dir, 'service.json'), JSON.stringify(service, null, 2), 'utf-8');
        }
        imported.push(serviceId);
    }
    return { imported, skipped };
}
function serviceStateEnabled(state) {
    const source = state;
    return source.enabled !== false && source.reminders_paused !== true;
}
function isStoredAgenticService(value) {
    if (typeof value !== 'object' || value === null)
        return false;
    const item = value;
    const service = item.service;
    return typeof service?.service_id === 'string'
        && typeof service.service_name === 'string'
        && service.mode === 'operate'
        && typeof service.purpose === 'string'
        && typeof item.state === 'object'
        && item.state !== null;
}
async function createOrUpdateGenericOperateService(projectDir, request, now = new Date()) {
    const siteUrl = extractUrl(request);
    const serviceId = siteUrl ? `site_monitor_${shortHash(siteUrl)}` : `operate_${slugify(request).slice(0, 42) || shortHash(request)}`;
    const dir = path.join(servicesDir(projectDir), serviceId);
    const storageLocation = path.relative(projectDir, dir).split(path.sep).join('/');
    const existing = await getAgenticService(projectDir, serviceId);
    const createdAt = existing?.service.created_at ?? now.toISOString();
    const state = normalizeGenericOperateState(existing?.state, serviceId, now, createdAt);
    const purpose = siteUrl
        ? `Check ${siteUrl} daily and report whether the requested condition appears true: ${request}`
        : request;
    const service = {
        service_id: serviceId,
        service_name: siteUrl ? 'Site Monitor Agent' : 'Operating Service Agent',
        mode: 'operate',
        purpose,
        persistent_state_schema: {
            observations: 'Timestamped findings from each proactive check.',
            tasks: 'Service-owned follow-up items managed by the agent.',
            notes: 'User or agent notes attached to the service.',
            reminders: 'Reminder and schedule metadata.',
            reviews: 'Periodic summaries of findings and unresolved items.',
        },
        supported_commands: ['show_status', 'add_note', 'record_observation', 'pause_reminders', 'resume_reminders', 'daily_review', 'close_item'],
        schedules: [{ id: 'daily_check', type: 'cron', expression: '0 9 * * *', enabled: state.enabled && !state.reminders_paused }],
        reminder_rules: ['Check once per day at the configured time.', 'Record an observation.', 'Notify the user with concise status and next action when the condition changes or needs attention.'],
        notification_templates: {
            daily_check: siteUrl
                ? `Daily site check for ${siteUrl}: summarize whether the requested condition appears true, cite the observed signal, and ask if I should keep monitoring or change criteria.`
                : 'Daily service check: summarize current status, observations, and any needed follow-up.',
        },
        state_transition_rules: ['record_observation appends timestamped findings.', 'add_note creates a timestamped note.', 'pause_reminders disables scheduled checks.', 'resume_reminders enables scheduled checks.', 'close_item marks service-owned follow-up items closed.'],
        review_rules: ['Daily checks append observations.', 'Weekly review summarizes changes, unresolved items, and recurring themes.'],
        close_archive_rules: ['Closed items remain in state for auditability.', 'Archive only after explicit user request.'],
        user_interaction_examples: siteUrl
            ? [`check ${siteUrl} daily to see if a room is free`, 'show status', 'pause reminders', 'resume reminders']
            : ['monitor this daily', 'show status', 'add note ...', 'pause reminders'],
        safety_confirmation_rules: ['Ask before taking external action beyond checking and reporting.', 'Do not book, purchase, submit forms, or contact third parties without explicit confirmation.'],
        storage_location: storageLocation,
        enable_disable_controls: ['pause_reminders', 'resume_reminders'],
        created_at: createdAt,
        updated_at: now.toISOString(),
    };
    const schedule = await ensureGenericOperateSchedule(projectDir, service, request, siteUrl, now);
    service.automation_job_id = schedule?.id;
    service.schedules = [{ id: 'daily_check', type: 'cron', expression: '0 9 * * *', enabled: state.enabled && !state.reminders_paused, automation_job_id: schedule?.id ?? null }];
    state.updated_at = now.toISOString();
    await fs.mkdir(dir, { recursive: true });
    await fs.writeFile(path.join(dir, 'service.json'), JSON.stringify(service, null, 2), 'utf-8');
    await fs.writeFile(path.join(dir, 'state.json'), JSON.stringify(state, null, 2), 'utf-8');
    // Auto-create a promise for the scheduled service if one doesn't already exist.
    if (schedule) {
        const existing = await (0, promiseLedger_1.listPromises)(projectDir, { service_id: serviceId });
        if (!existing.some((p) => p.schedule_id === schedule.id && p.status === 'pending')) {
            (0, promiseLedger_1.createPromise)(projectDir, `Daily check for ${service.service_name}: ${purpose.slice(0, 80)}`, {
                service_id: serviceId,
                schedule_id: schedule.id,
                capability_required: 'scheduler',
            }).catch(() => { });
        }
    }
    return { service, state, schedule };
}
async function applyBulletJournalCommand(projectDir, command, now) {
    const setup = await createOrUpdateBulletJournalService(projectDir, {}, now);
    const state = setup.state;
    const extractedCommand = bulletJournalCommandToExtracted(command);
    const validation = (0, commandExtractor_1.validateStateTransition)(extractedCommand, 'bullet_journal');
    if (!validation.valid) {
        const error = validation.errors.join(' ');
        await appendServiceTransitionEvent(projectDir, 'bullet_journal', extractedCommand, false, error);
        return { response: `I could not apply that command: ${error} Current state: ${openTasks(state).length} open task(s), ${state.closed_tasks.length} closed task(s), ${state.notes.length} note(s).`, service: setup.service, state, schedule: setup.schedule };
    }
    let response = '';
    if (command.name === 'add_task') {
        const parsedTask = parseTaskDetails(command.title);
        const task = {
            id: `task_${now.getTime().toString(36)}_${crypto.randomBytes(2).toString('hex')}`,
            title: parsedTask.title,
            description: command.description ?? '',
            status: 'open',
            priority: command.priority ?? parsedTask.priority ?? 'normal',
            due_date: command.dueDate ?? parsedTask.dueDate ?? null,
            created_at: now.toISOString(),
            updated_at: now.toISOString(),
            closed_at: null,
            tags: command.tags ?? parsedTask.tags,
            notes: [],
        };
        state.tasks.push(task);
        response = `Added task ${task.id}: ${task.title}.`;
    }
    else if (command.name === 'add_note') {
        const note = { id: `note_${now.getTime().toString(36)}_${crypto.randomBytes(2).toString('hex')}`, content: command.content, created_at: now.toISOString(), updated_at: now.toISOString(), tags: command.tags ?? [], linked_task_id: command.linkedTaskId ?? null };
        state.notes.push(note);
        if (note.linked_task_id) {
            const linked = state.tasks.find((task) => task.id === note.linked_task_id);
            if (linked)
                linked.notes.push(note.id);
        }
        response = `Added note ${note.id}.`;
    }
    else if (command.name === 'update_task') {
        const task = state.tasks.find((candidate) => candidate.id === command.selector || candidate.title.toLowerCase() === command.selector.toLowerCase());
        if (!task)
            response = `I could not find a task matching "${command.selector}".`;
        else {
            const parsedTask = command.title ? parseTaskDetails(command.title) : null;
            task.title = parsedTask?.title ?? command.title ?? task.title;
            task.description = command.description ?? task.description;
            task.priority = command.priority ?? parsedTask?.priority ?? task.priority;
            task.due_date = command.dueDate !== undefined ? command.dueDate : parsedTask?.dueDate ?? task.due_date;
            if (parsedTask?.tags.length)
                task.tags = Array.from(new Set([...task.tags, ...parsedTask.tags]));
            task.updated_at = now.toISOString();
            response = `Updated task ${task.id}: ${task.title}.`;
        }
    }
    else if (command.name === 'close_task') {
        const task = findTask(state, command.selector);
        if (!task)
            response = `I could not find an open task matching "${command.selector}".`;
        else {
            task.status = 'closed';
            task.updated_at = now.toISOString();
            task.closed_at = now.toISOString();
            if (!state.closed_tasks.some((closed) => closed.id === task.id))
                state.closed_tasks.push({ ...task });
            response = `Closed task ${task.id}: ${task.title}.`;
        }
    }
    else if (command.name === 'reopen_task') {
        const task = state.tasks.find((candidate) => candidate.id === command.selector || candidate.title.toLowerCase() === command.selector.toLowerCase());
        if (!task)
            response = `I could not find a task matching "${command.selector}".`;
        else {
            task.status = 'open';
            task.updated_at = now.toISOString();
            task.closed_at = null;
            state.closed_tasks = state.closed_tasks.filter((closed) => closed.id !== task.id);
            response = `Reopened task ${task.id}: ${task.title}.`;
        }
    }
    else if (command.name === 'show_today') {
        response = formatDailyCheckIn(state, now);
    }
    else if (command.name === 'show_open_tasks') {
        response = formatTaskList('Open tasks', openTasks(state));
    }
    else if (command.name === 'show_closed_tasks') {
        response = formatTaskList('Closed tasks', state.closed_tasks);
    }
    else if (command.name === 'daily_review') {
        const entry = { id: `daily_${now.toISOString().slice(0, 10)}`, created_at: now.toISOString(), open_tasks: openTasks(state).length, closed_tasks: state.closed_tasks.length, notes: state.notes.length };
        state.daily_logs.push(entry);
        response = `Daily review saved: ${openTasks(state).length} open task(s), ${state.closed_tasks.length} closed task(s), ${state.notes.length} note(s).`;
    }
    else if (command.name === 'weekly_review') {
        const entry = { id: `weekly_${now.getTime().toString(36)}`, created_at: now.toISOString(), completed_tasks: state.closed_tasks.length, open_tasks: openTasks(state).length, recurring_themes: summarizeTags(state) };
        state.reviews.push(entry);
        response = `Weekly review saved: ${state.closed_tasks.length} completed task(s), ${openTasks(state).length} open task(s).`;
    }
    else if (command.name === 'edit_note') {
        const note = state.notes.find((candidate) => candidate.id === command.noteId);
        if (!note)
            response = `I could not find note ${command.noteId}.`;
        else {
            note.content = command.content;
            note.updated_at = now.toISOString();
            response = `Updated note ${note.id}.`;
        }
    }
    else if (command.name === 'delete_note') {
        const before = state.notes.length;
        state.notes = state.notes.filter((note) => note.id !== command.noteId);
        response = state.notes.length === before ? `I could not find note ${command.noteId}.` : `Deleted note ${command.noteId}.`;
    }
    else if (command.name === 'set_reminder_time') {
        state.reminder_time = command.time;
        const updated = await createOrUpdateBulletJournalService(projectDir, { reminderTime: command.time }, now);
        response = `Reminder time set to ${updated.state.reminder_time}.`;
        return { response, service: updated.service, state: updated.state, schedule: updated.schedule };
    }
    else if (command.name === 'pause_reminders' || command.name === 'resume_reminders') {
        state.reminders_paused = command.name === 'pause_reminders';
        state.enabled = command.name !== 'pause_reminders';
        if (setup.schedule)
            await (0, jobs_1.updateAutomationJob)(projectDir, setup.schedule.id, { enabled: !state.reminders_paused }, now);
        response = state.reminders_paused ? 'Bullet Journal reminders are paused.' : 'Bullet Journal reminders are resumed.';
    }
    state.updated_at = now.toISOString();
    await saveBulletJournalState(projectDir, state);
    await appendServiceTransitionEvent(projectDir, 'bullet_journal', extractedCommand, true);
    return { response: `${response} Current state: ${openTasks(state).length} open task(s), ${state.closed_tasks.length} closed task(s), ${state.notes.length} note(s).`, service: setup.service, state, schedule: setup.schedule };
}
function parseBulletJournalCommand(message) {
    const trimmed = message.trim();
    const lower = trimmed.toLowerCase();
    const addTask = trimmed.match(/^add(?: a)? task[:\s]+(.+)$/i);
    if (addTask)
        return { name: 'add_task', title: addTask[1].trim() };
    const closeTask = trimmed.match(/^close(?: task)?[:\s]+(.+)$/i);
    if (closeTask)
        return { name: 'close_task', selector: closeTask[1].trim() };
    const reopenTask = trimmed.match(/^reopen(?: task)?[:\s]+(.+)$/i);
    if (reopenTask)
        return { name: 'reopen_task', selector: reopenTask[1].trim() };
    const updateTask = trimmed.match(/^update(?: task)?\s+([^:]+):\s*(.+)$/i);
    if (updateTask)
        return { name: 'update_task', selector: updateTask[1].trim(), title: updateTask[2].trim() };
    const note = trimmed.match(/^(?:add )?note[:\s]+(.+)$/i);
    if (note)
        return { name: 'add_note', content: note[1].trim() };
    const editNote = trimmed.match(/^edit note\s+(\S+)[:\s]+(.+)$/i);
    if (editNote)
        return { name: 'edit_note', noteId: editNote[1].trim(), content: editNote[2].trim() };
    const deleteNote = trimmed.match(/^delete note\s+(\S+)$/i);
    if (deleteNote)
        return { name: 'delete_note', noteId: deleteNote[1].trim() };
    const reminderTime = parseReminderTime(trimmed);
    if (/set reminder time|remind me at|check in at/i.test(trimmed) && reminderTime)
        return { name: 'set_reminder_time', time: reminderTime };
    if (lower === 'show today' || lower === 'today' || lower === 'daily check-in')
        return { name: 'show_today' };
    if (lower === 'show open tasks' || lower === 'open tasks')
        return { name: 'show_open_tasks' };
    if (lower === 'show closed tasks' || lower === 'closed tasks')
        return { name: 'show_closed_tasks' };
    if (lower === 'daily review')
        return { name: 'daily_review' };
    if (lower === 'weekly review')
        return { name: 'weekly_review' };
    if (lower === 'pause reminders')
        return { name: 'pause_reminders' };
    if (lower === 'resume reminders')
        return { name: 'resume_reminders' };
    return null;
}
async function applyGenericOperateCommand(projectDir, command, now) {
    const serviceRecord = await findGenericOperateService(projectDir, command.target);
    if (serviceRecord.status === 'missing')
        return { response: 'No generic operating service is configured yet.', schedule: null };
    if (serviceRecord.status === 'ambiguous')
        return { response: `Multiple generic operating services are configured. Target one with its service id, URL, or service name: ${serviceRecord.services.map((item) => item.service.service_id).join(', ')}.`, schedule: null };
    const service = serviceRecord.service;
    const state = normalizeGenericOperateState(serviceRecord.state, service.service_id, now, service.created_at);
    const extractedCommand = genericOperateCommandToExtracted(command);
    const validation = (0, commandExtractor_1.validateStateTransition)(extractedCommand, service.service_id);
    if (!validation.valid) {
        const error = validation.errors.join(' ');
        await appendServiceTransitionEvent(projectDir, service.service_id, extractedCommand, false, error);
        return { response: `I could not apply that command: ${error} ${formatGenericOperateCounts(state)}`, service, state, schedule: null };
    }
    let response = '';
    let schedule = null;
    if (command.name === 'show_status') {
        response = formatGenericOperateStatus(service, state);
    }
    else if (command.name === 'add_note') {
        const note = { id: `note_${now.getTime().toString(36)}_${crypto.randomBytes(2).toString('hex')}`, content: command.content, created_at: now.toISOString(), updated_at: now.toISOString() };
        state.notes.push(note);
        response = `Added note ${note.id}.`;
    }
    else if (command.name === 'record_observation') {
        const observation = { id: `obs_${now.getTime().toString(36)}_${crypto.randomBytes(2).toString('hex')}`, content: command.content, created_at: now.toISOString() };
        state.observations.push(observation);
        response = `Recorded observation ${observation.id}.`;
    }
    else if (command.name === 'pause_reminders' || command.name === 'resume_reminders') {
        state.reminders_paused = command.name === 'pause_reminders';
        state.enabled = command.name !== 'pause_reminders';
        if (service.automation_job_id)
            schedule = await (0, jobs_1.updateAutomationJob)(projectDir, service.automation_job_id, { enabled: state.enabled }, now);
        response = state.enabled ? `${service.service_name} reminders are resumed.` : `${service.service_name} reminders are paused.`;
    }
    service.updated_at = now.toISOString();
    service.schedules = (service.schedules || []).map((entry) => ({ ...entry, enabled: state.enabled && !state.reminders_paused }));
    state.updated_at = now.toISOString();
    await saveGenericOperateService(projectDir, service, state);
    await appendServiceTransitionEvent(projectDir, service.service_id, extractedCommand, true);
    return { response: `${response} ${formatGenericOperateCounts(state)}`, service, state, schedule };
}
function bulletJournalCommandToExtracted(command) {
    if (command.name === 'add_task')
        return { type: 'add_task', title: command.title, due_date: command.dueDate ?? undefined, priority: command.priority };
    if (command.name === 'add_note')
        return { type: 'add_note', content: command.content, task_id: command.linkedTaskId ?? undefined };
    if (command.name === 'update_task')
        return { type: 'update_task', task_id: command.selector, title: command.title, fields: { description: command.description, priority: command.priority, due_date: command.dueDate } };
    if (command.name === 'edit_note')
        return { type: 'edit_note', note_id: command.noteId, content: command.content };
    if (command.name === 'delete_note')
        return { type: 'delete_note', note_id: command.noteId };
    if (command.name === 'close_task')
        return { type: 'close_task', task_id: command.selector };
    if (command.name === 'reopen_task')
        return { type: 'reopen_task', task_id: command.selector };
    if (command.name === 'set_reminder_time')
        return { type: 'set_reminder_time', reminder_time: command.time };
    return { type: command.name };
}
function genericOperateCommandToExtracted(command) {
    if (command.name === 'add_note')
        return { type: 'add_note', content: command.content };
    if (command.name === 'record_observation')
        return { type: 'add_note', content: command.content, fields: { source_command: 'record_observation' } };
    if (command.name === 'pause_reminders')
        return { type: 'pause_reminders' };
    if (command.name === 'resume_reminders')
        return { type: 'resume_reminders' };
    return { type: 'show_today', fields: { source_command: command.name, target: command.target } };
}
async function appendServiceTransitionEvent(projectDir, serviceId, command, success, error) {
    const event = (0, commandExtractor_1.createTransitionEvent)(serviceId, command, success, error);
    const logPath = path.join(servicesDir(projectDir), serviceId, 'events.jsonl');
    await fs.mkdir(path.dirname(logPath), { recursive: true });
    await fs.appendFile(logPath, JSON.stringify(event) + '\n', 'utf-8');
}
function parseGenericOperateCommand(message) {
    const trimmed = message.trim();
    const lower = trimmed.toLowerCase();
    const status = trimmed.match(/^(?:show status|status)(?:\s+(?:for|of)\s+(.+))?$/i);
    if (status)
        return { name: 'show_status', target: normalizeGenericCommandTarget(status[1]) };
    const scopedNote = trimmed.match(/^(?:site monitor|operating service)(?:\s+(.+?))?\s+add note[:\s]+(.+)$/i);
    if (scopedNote)
        return { name: 'add_note', target: normalizeGenericCommandTarget(scopedNote[1]), content: scopedNote[2].trim() };
    const note = trimmed.match(/^add note(?:\s+(?:to|for)\s+(.+?))?[:\s]+(.+)$/i);
    if (note)
        return { name: 'add_note', target: normalizeGenericCommandTarget(note[1]), content: note[2].trim() };
    const observation = trimmed.match(/^(?:(?:site monitor|operating service)(?:\s+(.+?))?\s+)?(?:record observation|observed)[:\s]+(.+)$/i);
    if (observation)
        return { name: 'record_observation', target: normalizeGenericCommandTarget(observation[1]), content: observation[2].trim() };
    const reminders = trimmed.match(/^(?:(?:site monitor|operating service)(?:\s+(.+?))?\s+)?(pause|resume) reminders$/i);
    if (reminders)
        return { name: reminders[2].toLowerCase() === 'pause' ? 'pause_reminders' : 'resume_reminders', target: normalizeGenericCommandTarget(reminders[1]) };
    return null;
}
function normalizeGenericCommandTarget(value) {
    const target = value?.trim();
    if (!target)
        return undefined;
    if (/^(site monitor|operating service)$/i.test(target))
        return undefined;
    return target;
}
async function findGenericOperateService(projectDir, target) {
    const services = await listAgenticServices(projectDir);
    const genericServices = services.filter((item) => item.service.service_id !== 'bullet_journal');
    if (genericServices.length === 0)
        return { status: 'missing' };
    if (target) {
        const matches = genericServices.filter((item) => genericServiceMatchesTarget(item.service, target));
        if (matches.length === 1)
            return { status: 'found', service: matches[0].service, state: matches[0].state };
        if (matches.length > 1)
            return { status: 'ambiguous', services: matches };
        return { status: 'missing' };
    }
    if (genericServices.length === 1)
        return { status: 'found', service: genericServices[0].service, state: genericServices[0].state };
    return { status: 'ambiguous', services: genericServices };
}
function genericServiceMatchesTarget(service, target) {
    const normalizedTarget = target.trim().toLowerCase();
    const url = extractUrl(target);
    const urlServiceId = url ? `site_monitor_${shortHash(url)}` : null;
    return service.service_id.toLowerCase() === normalizedTarget
        || service.service_name.toLowerCase() === normalizedTarget
        || service.storage_location.toLowerCase().endsWith(`/${normalizedTarget}`)
        || (urlServiceId !== null && service.service_id === urlServiceId)
        || (url !== null && service.purpose.toLowerCase().includes(url.toLowerCase()))
        || service.purpose.toLowerCase().includes(normalizedTarget);
}
async function saveGenericOperateService(projectDir, service, state) {
    const dir = path.join(servicesDir(projectDir), service.service_id);
    await fs.mkdir(dir, { recursive: true });
    await fs.writeFile(path.join(dir, 'service.json'), JSON.stringify(service, null, 2), 'utf-8');
    await fs.writeFile(path.join(dir, 'state.json'), JSON.stringify(state, null, 2), 'utf-8');
}
function formatGenericOperateStatus(service, state) {
    const status = state.enabled && !state.reminders_paused ? 'enabled' : 'paused';
    return `${service.service_name} is ${status}. ${formatGenericOperateCounts(state)}`;
}
function formatGenericOperateCounts(state) {
    return `Current state: ${state.observations.length} observation(s), ${state.notes.length} note(s), ${state.tasks.length} task(s).`;
}
async function ensureGenericOperateSchedule(projectDir, service, request, siteUrl, now) {
    const prompt = [
        `service_id: ${service.service_id}`,
        'mode: operate',
        `Purpose: ${service.purpose}`,
        siteUrl ? `Check this site: ${siteUrl}` : '',
        `Original user request: ${request}`,
        `Read and update service state at ${service.storage_location}/state.json.`,
        'Act as an operational service: check, record observations, and notify with a concise status. Do not build an app, UI, markdown task file, or code project unless the user explicitly asks for software.',
    ].filter(Boolean).join('\n');
    const jobs = await (0, jobs_1.listAutomationJobs)(projectDir);
    const existing = jobs.find((job) => job.id === service.automation_job_id) ?? jobs.find((job) => job.name === `${service.service_name}: ${service.service_id}`);
    const input = { name: `${service.service_name}: ${service.service_id}`, prompt, schedule: '0 9 * * *' };
    if (existing)
        return (0, jobs_1.updateAutomationJob)(projectDir, existing.id, { ...input, enabled: true }, now);
    return (0, jobs_1.createAutomationJob)(projectDir, input, now);
}
function normalizeGenericOperateState(raw, serviceId, now, createdAt) {
    const source = typeof raw === 'object' && raw !== null ? raw : {};
    return {
        service_id: serviceId,
        mode: 'operate',
        observations: Array.isArray(source.observations) ? source.observations : [],
        tasks: Array.isArray(source.tasks) ? source.tasks : [],
        notes: Array.isArray(source.notes) ? source.notes : [],
        reminders: Array.isArray(source.reminders) ? source.reminders : [],
        reviews: Array.isArray(source.reviews) ? source.reviews : [],
        enabled: source.enabled !== false,
        reminders_paused: source.reminders_paused === true,
        created_at: typeof source.created_at === 'string' ? source.created_at : createdAt,
        updated_at: now.toISOString(),
    };
}
async function loadBulletJournalDefinition(projectDir, now) {
    try {
        const parsed = JSON.parse(await fs.readFile(bulletJournalDefinitionPath(projectDir), 'utf-8'));
        return parsed;
    }
    catch {
        const storageLocation = path.relative(projectDir, bulletJournalDir(projectDir)).split(path.sep).join('/');
        return {
            service_id: 'bullet_journal',
            service_name: 'Bullet Journal Agent',
            mode: 'operate',
            purpose: 'Maintain a persistent bullet journal with tasks, notes, reminders, daily logs, collections, and reviews.',
            persistent_state_schema: {
                tasks: ['id', 'title', 'description', 'status', 'priority', 'due_date', 'created_at', 'updated_at', 'closed_at', 'tags', 'notes'],
                notes: ['id', 'content', 'created_at', 'updated_at', 'tags', 'linked_task_id'],
                daily_logs: 'Timestamped daily review entries.',
                collections: 'Named groups of related tasks or notes.',
                closed_tasks: 'Closed task snapshots.',
                reminders: 'Reminder rules and schedule metadata.',
                reviews: 'Daily and weekly review summaries.',
            },
            supported_commands: BULLET_JOURNAL_COMMANDS,
            schedules: [],
            reminder_rules: [
                'Send/check in once per day at the configured time.',
                'Show open tasks due today.',
                'Show overdue tasks.',
                'Ask what to add, update, close, or note.',
                'Summarise yesterday unresolved tasks if relevant.',
            ],
            notification_templates: {
                daily_check_in: 'Good morning. Here\'s your bullet journal check-in:\nOpen today:\n1. ...\nOverdue:\n1. ...\nWant to add, update, close anything, or add a note?',
            },
            state_transition_rules: [
                'add_task creates an open task.',
                'update_task modifies fields.',
                'close_task sets status = closed and closed_at timestamp.',
                'reopen_task sets status = open.',
                'add_note creates a timestamped note.',
                'linked notes can attach to tasks.',
                'daily_review writes a daily_log entry.',
                'weekly_review summarises completed/open tasks and recurring themes.',
            ],
            review_rules: ['Daily review writes daily_logs.', 'Weekly review summarises completed/open tasks and recurring themes.'],
            close_archive_rules: ['Closed tasks remain in tasks with status=closed and are mirrored in closed_tasks.', 'Archived records are retained unless explicitly deleted.'],
            user_interaction_examples: ['add task pay invoice', 'close task task_abc123', 'add note Remember to call Sam', 'show today', 'weekly review'],
            safety_confirmation_rules: ['Ask for confirmation before deleting notes or clearing large sections of state.', 'Do not expose private journal state outside the local harness response unless the user asks.'],
            storage_location: storageLocation,
            enable_disable_controls: ['pause_reminders', 'resume_reminders'],
            created_at: now.toISOString(),
            updated_at: now.toISOString(),
        };
    }
}
async function loadBulletJournalState(projectDir, now) {
    try {
        const parsed = JSON.parse(await fs.readFile(bulletJournalStatePath(projectDir), 'utf-8'));
        return {
            ...emptyBulletJournalState(now),
            ...parsed,
            tasks: Array.isArray(parsed.tasks) ? parsed.tasks : [],
            notes: Array.isArray(parsed.notes) ? parsed.notes : [],
            daily_logs: Array.isArray(parsed.daily_logs) ? parsed.daily_logs : [],
            collections: Array.isArray(parsed.collections) ? parsed.collections : [],
            closed_tasks: Array.isArray(parsed.closed_tasks) ? parsed.closed_tasks : [],
            reminders: Array.isArray(parsed.reminders) ? parsed.reminders : [],
            reviews: Array.isArray(parsed.reviews) ? parsed.reviews : [],
        };
    }
    catch {
        return emptyBulletJournalState(now);
    }
}
function emptyBulletJournalState(now) {
    return {
        service_id: 'bullet_journal',
        mode: 'operate',
        tasks: [],
        notes: [],
        daily_logs: [],
        collections: [],
        closed_tasks: [],
        reminders: [],
        reviews: [],
        reminder_time: '09:00',
        reminders_paused: false,
        enabled: true,
        created_at: now.toISOString(),
        updated_at: now.toISOString(),
    };
}
async function ensureBulletJournalSchedule(projectDir, service, reminderTime, now) {
    const schedule = dailyCron(reminderTime);
    const prompt = [
        'service_id: bullet_journal',
        'mode: operate',
        'Send the daily bullet journal check-in using this exact format:',
        'Good morning. Here\'s your bullet journal check-in:',
        'Open today:',
        '1. ...',
        'Overdue:',
        '1. ...',
        'Want to add, update, close anything, or add a note?',
        `Read service state from ${service.storage_location}/state.json before composing the check-in.`,
    ].join('\n');
    const jobs = await (0, jobs_1.listAutomationJobs)(projectDir);
    const existing = jobs.find((job) => job.id === service.automation_job_id) ?? jobs.find((job) => job.name === 'Bullet Journal daily check-in');
    if (existing)
        return (0, jobs_1.updateAutomationJob)(projectDir, existing.id, { name: 'Bullet Journal daily check-in', prompt, schedule, enabled: true }, now);
    return (0, jobs_1.createAutomationJob)(projectDir, { name: 'Bullet Journal daily check-in', prompt, schedule }, now);
}
async function saveBulletJournalDefinition(projectDir, service) {
    await fs.mkdir(bulletJournalDir(projectDir), { recursive: true });
    await fs.writeFile(bulletJournalDefinitionPath(projectDir), JSON.stringify(service, null, 2), 'utf-8');
}
async function saveBulletJournalState(projectDir, state) {
    await fs.mkdir(bulletJournalDir(projectDir), { recursive: true });
    await fs.writeFile(bulletJournalStatePath(projectDir), JSON.stringify(state, null, 2), 'utf-8');
}
function isBulletJournalRequest(message) {
    const lower = message.toLowerCase();
    return lower.includes('bullet journal') || lower.includes('bullet proof journal') || looksLikeBulletJournalCommand(lower);
}
function looksLikeBulletJournalServiceRequest(lower) {
    return (lower.includes('bullet journal') || lower.includes('bullet proof journal')) && (lower.includes('service') || lower.includes('agent') || lower.includes('remind') || lower.includes('keep track') || lower.includes('manage') || lower.includes('update for me') || lower.includes('keep me honest'));
}
function looksLikeBulletJournalCommand(lower) {
    return /^(add( a)? task|update( task)?|close( task)?|reopen( task)?|note|add note|edit note|delete note|show today|today|daily check-in|show open tasks|open tasks|show closed tasks|closed tasks|daily review|weekly review|set reminder time|pause reminders|resume reminders)\b/.test(lower.trim());
}
function looksLikeExternalBulletJournalTaskRequest(lower) {
    return /^(add(?: a)? task|close(?: task)?|complete(?: task)?|update(?: task)?|reopen(?: task)?)\b/.test(lower.trim())
        && /\b(to|in|into)\s+(my|the)?\s*bullet journal\b/.test(lower);
}
function looksLikeGenericOperateCommand(lower) {
    return /^(show status|status|site monitor\b|operating service\b|add note (to|for) .+|record observation|observed)\b/.test(lower.trim());
}
function looksLikeAgenticSearchRequest(lower) {
    const text = lower.trim();
    return /\b(look for|find|search for|watch for|monitor for|check for)\b[\s\S]{0,120}\b(book|books|room|rooms|appointment|appointments|slot|slots|availability|stock|tickets?)\b/.test(text)
        && /\b(for me|daily|every day|each day|every morning|when|until|available|opens?|appears?|comes? up|in stock|free)\b/.test(text);
}
function explicitlyRequestsSoftwareBuild(lower) {
    return /\b(build|code|develop|implement|scaffold|create|make|generate|write)\b.{0,60}\b(app|application|ui|dashboard|website|site|software|codebase|project|component|page|document|template|artifact|code|script|function|class|module|api|cli|tool)\b/.test(lower);
}
function parseReminderTime(message) {
    const match = message.match(/(?:at|time\s+to)\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)?/i);
    if (!match)
        return null;
    let hour = Number(match[1]);
    const minute = match[2] ? Number(match[2]) : 0;
    const meridiem = match[3]?.toLowerCase();
    if (meridiem === 'pm' && hour < 12)
        hour += 12;
    if (meridiem === 'am' && hour === 12)
        hour = 0;
    if (hour < 0 || hour > 23 || minute < 0 || minute > 59)
        return null;
    return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
}
function parseTaskDetails(rawTitle) {
    let title = rawTitle.trim();
    let priority;
    let dueDate;
    const tags = Array.from(title.matchAll(/#([a-zA-Z0-9_-]+)/g)).map((match) => match[1]);
    title = title.replace(/\s*#[a-zA-Z0-9_-]+/g, '').trim();
    const dueMatch = title.match(/\b(?:due|by)\s+(\d{4}-\d{2}-\d{2})\b/i);
    if (dueMatch) {
        dueDate = dueMatch[1];
        title = title.replace(dueMatch[0], '').trim();
    }
    const priorityMatch = title.match(/\bpriority\s+(high|normal|low)\b/i) ?? title.match(/\b(high|normal|low)\s+priority\b/i);
    if (priorityMatch) {
        priority = priorityMatch[1].toLowerCase();
        title = title.replace(priorityMatch[0], '').trim();
    }
    return { title: title.replace(/\s{2,}/g, ' ') || rawTitle.trim(), priority, dueDate, tags };
}
function extractUrl(message) {
    const match = message.match(/https?:\/\/[^\s)]+/i);
    if (!match)
        return null;
    try {
        return new URL(match[0]).toString();
    }
    catch {
        return null;
    }
}
function slugify(value) {
    return value.toLowerCase().replace(/https?:\/\/[^\s)]+/g, '').replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');
}
function shortHash(value) {
    return crypto.createHash('sha1').update(value).digest('hex').slice(0, 8);
}
function normalizeReminderTime(value) {
    if (!value)
        return null;
    const match = value.match(/^(\d{1,2}):(\d{2})$/);
    if (!match)
        return null;
    const hour = Number(match[1]);
    const minute = Number(match[2]);
    if (hour < 0 || hour > 23 || minute < 0 || minute > 59)
        return null;
    return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
}
function dailyCron(reminderTime) {
    const normalized = normalizeReminderTime(reminderTime) ?? '09:00';
    const [hour, minute] = normalized.split(':');
    return `${Number(minute)} ${Number(hour)} * * *`;
}
function openTasks(state) {
    return state.tasks.filter((task) => task.status !== 'closed');
}
function findTask(state, selector) {
    const lower = selector.toLowerCase();
    return openTasks(state).find((task) => task.id === selector || task.title.toLowerCase() === lower || task.title.toLowerCase().includes(lower));
}
function formatDailyCheckIn(state, now) {
    const today = now.toISOString().slice(0, 10);
    const dueToday = openTasks(state).filter((task) => task.due_date === today || !task.due_date);
    const overdue = openTasks(state).filter((task) => task.due_date && task.due_date < today);
    return [
        'Good morning. Here\'s your bullet journal check-in:',
        'Open today:',
        numberedTasks(dueToday),
        'Overdue:',
        numberedTasks(overdue),
        'Want to add, update, close anything, or add a note?',
    ].join('\n');
}
function formatTaskList(title, tasks) {
    return `${title}:\n${numberedTasks(tasks)}`;
}
function numberedTasks(tasks) {
    if (tasks.length === 0)
        return 'None.';
    return tasks.map((task, index) => `${index + 1}. ${task.title} (${task.id})`).join('\n');
}
function summarizeTags(state) {
    const counts = new Map();
    for (const item of [...state.tasks, ...state.notes]) {
        for (const tag of item.tags)
            counts.set(tag, (counts.get(tag) ?? 0) + 1);
    }
    return [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([tag]) => tag);
}
function bulletJournalDir(projectDir) {
    return path.join(servicesDir(projectDir), 'bullet_journal');
}
function servicesDir(projectDir) {
    return path.join(projectDir, '.harness', 'services');
}
function bulletJournalDefinitionPath(projectDir) {
    return path.join(bulletJournalDir(projectDir), 'service.json');
}
function bulletJournalStatePath(projectDir) {
    return path.join(bulletJournalDir(projectDir), 'state.json');
}
//# sourceMappingURL=agenticServiceMode.js.map