/**
 * Kanban Bridge spectral extension.
 *
 * Registers kanban management tools that allow the coding agent to read,
 * create, update, and move Kanban tasks on the Aexol Studio board. This
 * enables task-driven execution — the agent can pick up TODO tasks, work
 * on them, and move them to DONE.
 *
 * Auth is read from ~/.spectral/config.json (same as aexol-mcp).
 * The Studio project ID comes from the local binding (.aexol/aexol.jsonc),
 * falling back to an explicit kanban_project_id flag.
 *
 * Registered tools:
 *   - kanban_list          — List all Kanban tasks for the project
 *   - kanban_get           — Get a single task by ID
 *   - kanban_create        — Create a new Kanban task
 *   - kanban_update        — Update a task (title, description, priority, tags)
 *   - kanban_move          — Move a task between columns (BACKLOG → TODO → IN_PROGRESS → DONE)
 *   - kanban_next          — Pick the next TODO task and mark it IN_PROGRESS
 *   - kanban_delete        — Delete a task
 */
/**
 * Send a GraphQL query/mutation to the Aexol backend.
 * Uses the same auth and endpoint as the Studio frontend.
 */
async function graphqlRequest(opts, query, variables) {
    const body = JSON.stringify({ query, variables });
    const res = await fetch(`${opts.backendUrl}/graphql`, {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            Accept: "application/json",
            Authorization: `Bearer ${opts.token}`,
        },
        body,
        signal: AbortSignal.timeout(opts.timeoutMs ?? 15_000),
    });
    if (!res.ok) {
        let detail = "";
        try {
            detail = (await res.text()).slice(0, 300);
        }
        catch { /* ignore */ }
        throw new GraphQLError(`HTTP ${res.status} from GraphQL${detail ? `: ${detail}` : ""}`, res.status);
    }
    const json = (await res.json());
    if (json.errors && json.errors.length > 0) {
        throw new GraphQLError(json.errors.map((e) => e.message).join("; "));
    }
    if (!json.data) {
        throw new GraphQLError("GraphQL response missing data");
    }
    return json.data;
}
class GraphQLError extends Error {
    status;
    constructor(message, status) {
        super(message);
        this.name = "GraphQLError";
        this.status = status;
    }
}
// ---------------------------------------------------------------------------
// GraphQL fragments (minimal inline selectors — no codegen dependency)
// ---------------------------------------------------------------------------
const KANBAN_TASK_FRAGMENT = `
  id
  projectId
  column
  title
  description
  priority
  sortOrder
  tags
  createdAt
  updatedAt
  completedAt
  assignee { id username email }
`;
const KANBAN_TASK_FRAGMENT_LIGHT = `
  id
  column
  title
  priority
  tags
`;
// ---------------------------------------------------------------------------
// GraphQL operations
// ---------------------------------------------------------------------------
async function listKanbanTasks(opts) {
    const data = await graphqlRequest(opts, `query($projectId: ID!) {
      kanbanTasks(projectId: $projectId, limit: 500) {
        ${KANBAN_TASK_FRAGMENT_LIGHT}
      }
    }`, { projectId: opts.projectId });
    return data.kanbanTasks;
}
async function getKanbanTask(opts, taskId) {
    // There's no single-task query, so fetch all and filter
    const data = await graphqlRequest(opts, `query($projectId: ID!) {
      kanbanTasks(projectId: $projectId, limit: 500) {
        ${KANBAN_TASK_FRAGMENT}
      }
    }`, { projectId: opts.projectId });
    const task = data.kanbanTasks.find((t) => t.id === taskId);
    if (!task)
        throw new GraphQLError(`Task not found: ${taskId}`);
    return task;
}
async function createKanbanTask(opts, input) {
    const data = await graphqlRequest(opts, `mutation($input: CreateKanbanTaskInput!) {
      createKanbanTask(input: $input) {
        ${KANBAN_TASK_FRAGMENT}
      }
    }`, {
        input: {
            projectId: opts.projectId,
            title: input.title,
            description: input.description ?? null,
            column: input.column ?? "BACKLOG",
            priority: input.priority ?? 0,
            tags: input.tags ?? null,
        },
    });
    return data.createKanbanTask;
}
async function updateKanbanTask(opts, taskId, input) {
    const data = await graphqlRequest(opts, `mutation($id: ID!, $input: UpdateKanbanTaskInput!) {
      updateKanbanTask(id: $id, input: $input) {
        ${KANBAN_TASK_FRAGMENT}
      }
    }`, {
        id: taskId,
        input: {
            title: input.title ?? undefined,
            description: input.description ?? undefined,
            column: input.column ?? undefined,
            priority: input.priority ?? undefined,
            tags: input.tags ?? undefined,
        },
    });
    return data.updateKanbanTask;
}
async function moveKanbanTask(opts, taskId, targetColumn, targetSortOrder) {
    const data = await graphqlRequest(opts, `mutation($input: MoveKanbanTaskInput!) {
      moveKanbanTask(input: $input) {
        ${KANBAN_TASK_FRAGMENT}
      }
    }`, {
        input: {
            taskId,
            targetColumn,
            targetSortOrder,
        },
    });
    return data.moveKanbanTask;
}
async function deleteKanbanTask(opts, taskId) {
    await graphqlRequest(opts, `mutation($id: ID!) {
      deleteKanbanTask(id: $id)
    }`, { id: taskId });
    return true;
}
// ---------------------------------------------------------------------------
// Config resolution
// ---------------------------------------------------------------------------
import { readConfig } from "../config.js";
import { readStudioBinding } from "../studio-binding.js";
import { getConfigFile } from "../config.js";
import { ensureAuthenticated } from "../auth-helper.js";
// Track whether we've already attempted reauth in this session to avoid loops
let _reauthAttempted = false;
async function resolveKanbanConfig(explicitProjectId) {
    const cfg = await readConfig();
    if (!cfg) {
        if (!_reauthAttempted) {
            _reauthAttempted = true;
            process.stderr.write(`[kanban-bridge] No config found at ${getConfigFile()}. Attempting OAuth login...\n`);
            const result = await ensureAuthenticated();
            if (result.ok && result.config) {
                return resolveKanbanConfig(explicitProjectId); // Retry with fresh config
            }
        }
        process.stderr.write(`[kanban-bridge] No config found at ${getConfigFile()}. Run \`spectral login\`.\n`);
        return null;
    }
    const token = cfg.teamApiKey || cfg.userJwt || "";
    if (!token) {
        if (!_reauthAttempted) {
            _reauthAttempted = true;
            process.stderr.write(`[kanban-bridge] No auth token in config. Attempting OAuth login...\n`);
            const result = await ensureAuthenticated();
            if (result.ok && result.config) {
                return resolveKanbanConfig(explicitProjectId);
            }
        }
        process.stderr.write(`[kanban-bridge] No auth token in config. Run \`spectral login\`.\n`);
        return null;
    }
    // Resolve backend URL — the config stores the MCP URL, we need the base
    const backendUrl = cfg.apiUrl.replace(/\/mcp$/, "");
    // Resolve projectId: explicit param > studio binding
    let projectId = explicitProjectId || null;
    if (!projectId) {
        try {
            const binding = await readStudioBinding();
            if (binding?.projectId) {
                projectId = binding.projectId;
            }
        }
        catch {
            // ignore
        }
    }
    if (!projectId) {
        process.stderr.write(`[kanban-bridge] No projectId available. Bind a project via \`spectral bind <project-id>\` or pass projectId explicitly.\n`);
        return null;
    }
    return { token, backendUrl, projectId };
}
// ---------------------------------------------------------------------------
// Tool: kanban_list
// ---------------------------------------------------------------------------
const kanbanListTool = {
    name: "kanban_list",
    label: "List Kanban Tasks",
    description: [
        "List all Kanban tasks for the bound Studio project.",
        "Returns tasks grouped by column: BACKLOG, TODO, IN_PROGRESS, DONE.",
        "Use this to see what work is planned and what's currently in progress.",
    ].join(" "),
    parameters: {
        type: "object",
        properties: {
            column: {
                type: "string",
                description: "Optional: filter by column (BACKLOG, TODO, IN_PROGRESS, DONE). If omitted, returns all tasks.",
            },
        },
    },
    async execute(_toolCallId, params) {
        const p = params;
        const cfg = await resolveKanbanConfig(p.projectId);
        if (!cfg) {
            return {
                content: [{ type: "text", text: "Error: Kanban bridge not configured. Run `spectral login` and `spectral bind <project-id>`." }],
                details: { isError: true },
            };
        }
        try {
            const allTasks = await listKanbanTasks(cfg);
            // Group by column
            const groups = {
                BACKLOG: [],
                TODO: [],
                IN_PROGRESS: [],
                DONE: [],
            };
            for (const task of allTasks) {
                (groups[task.column] ??= []).push(task);
            }
            if (p.column && groups[p.column]) {
                const col = groups[p.column];
                const lines = [`## ${p.column} (${col.length} tasks)`, ""];
                for (const t of col) {
                    lines.push(`- **[${t.id}]** ${t.title} (priority: ${t.priority}${t.tags ? `, tags: ${t.tags}` : ""})`);
                }
                return {
                    content: [{ type: "text", text: lines.join("\n") }],
                    details: {},
                };
            }
            const lines = [`## Kanban Board — Project ${cfg.projectId}`, `Total: ${allTasks.length} tasks`, ""];
            for (const [col, tasks] of Object.entries(groups)) {
                if (tasks.length === 0) {
                    lines.push(`### ${col} — empty`);
                }
                else {
                    lines.push(`### ${col} (${tasks.length})`);
                    for (const t of tasks) {
                        lines.push(`- **[${t.id}]** ${t.title} (priority: ${t.priority}${t.tags ? `, tags: ${t.tags}` : ""})`);
                    }
                }
                lines.push("");
            }
            return {
                content: [{ type: "text", text: lines.join("\n") }],
                details: {},
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return {
                content: [{ type: "text", text: `Error listing tasks: ${msg}` }],
                details: { isError: true },
            };
        }
    },
};
// ---------------------------------------------------------------------------
// Tool: kanban_get
// ---------------------------------------------------------------------------
const kanbanGetTool = {
    name: "kanban_get",
    label: "Get Kanban Task",
    description: "Get full details for a specific Kanban task by ID.",
    parameters: {
        type: "object",
        properties: {
            taskId: {
                type: "string",
                description: "The Kanban task ID (from kanban_list output)",
            },
            projectId: {
                type: "string",
                description: "Optional: override the default project ID",
            },
        },
        required: ["taskId"],
    },
    async execute(_toolCallId, params) {
        const p = params;
        const cfg = await resolveKanbanConfig(p.projectId);
        if (!cfg) {
            return { content: [{ type: "text", text: "Error: Kanban bridge not configured." }], details: { isError: true } };
        }
        try {
            const task = await getKanbanTask(cfg, p.taskId);
            const lines = [
                `## Task: ${task.title}`,
                `ID: ${task.id}`,
                `Column: ${task.column}`,
                `Priority: ${task.priority}`,
                `Tags: ${task.tags ?? "(none)"}`,
                `Created: ${task.createdAt}`,
                `Updated: ${task.updatedAt}`,
                task.completedAt ? `Completed: ${task.completedAt}` : null,
                task.assignee ? `Assignee: ${task.assignee.username} (${task.assignee.email})` : "Assignee: unassigned",
                "",
                "### Description",
                task.description ?? "(no description)",
            ];
            return {
                content: [{ type: "text", text: lines.filter(Boolean).join("\n") }],
                details: {},
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return { content: [{ type: "text", text: `Error: ${msg}` }], details: { isError: true } };
        }
    },
};
// ---------------------------------------------------------------------------
// Tool: kanban_create
// ---------------------------------------------------------------------------
const kanbanCreateTool = {
    name: "kanban_create",
    label: "Create Kanban Task",
    description: "Create a new Kanban task on the board.",
    parameters: {
        type: "object",
        properties: {
            title: { type: "string", description: "Task title" },
            description: { type: "string", description: "Detailed task description including acceptance criteria" },
            column: { type: "string", description: "Column: BACKLOG (default), TODO, IN_PROGRESS, DONE" },
            priority: { type: "number", description: "Priority 0-100. Higher = more urgent." },
            tags: { type: "string", description: "Comma-separated tags: auth,api,frontend,backend,testing" },
            projectId: { type: "string", description: "Optional: override the default project ID" },
        },
        required: ["title", "description"],
    },
    async execute(_toolCallId, params) {
        const p = params;
        const cfg = await resolveKanbanConfig(p.projectId);
        if (!cfg) {
            return { content: [{ type: "text", text: "Error: Kanban bridge not configured." }], details: { isError: true } };
        }
        try {
            const task = await createKanbanTask(cfg, {
                title: p.title,
                description: p.description,
                column: p.column ?? "BACKLOG",
                priority: p.priority ?? 0,
                tags: p.tags,
            });
            return {
                content: [{
                        type: "text",
                        text: `✓ Created task "${task.title}" (${task.id}) in ${task.column}`,
                    }],
                details: {},
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return { content: [{ type: "text", text: `Error creating task: ${msg}` }], details: { isError: true } };
        }
    },
};
// ---------------------------------------------------------------------------
// Tool: kanban_update
// ---------------------------------------------------------------------------
const kanbanUpdateTool = {
    name: "kanban_update",
    label: "Update Kanban Task",
    description: "Update a Kanban task's metadata (title, description, priority, tags). To move between columns, use kanban_move.",
    parameters: {
        type: "object",
        properties: {
            taskId: { type: "string", description: "The Kanban task ID" },
            title: { type: "string", description: "New title" },
            description: { type: "string", description: "Updated description with results/progress" },
            priority: { type: "number", description: "Updated priority 0-100" },
            tags: { type: "string", description: "Updated comma-separated tags" },
            projectId: { type: "string", description: "Optional: override the default project ID" },
        },
        required: ["taskId"],
    },
    async execute(_toolCallId, params) {
        const p = params;
        const cfg = await resolveKanbanConfig(p.projectId);
        if (!cfg) {
            return { content: [{ type: "text", text: "Error: Kanban bridge not configured." }], details: { isError: true } };
        }
        try {
            const input = {};
            if (p.title !== undefined)
                input.title = p.title;
            if (p.description !== undefined)
                input.description = p.description;
            if (p.priority !== undefined)
                input.priority = p.priority;
            if (p.tags !== undefined)
                input.tags = p.tags;
            if (Object.keys(input).length === 0) {
                return { content: [{ type: "text", text: "No changes provided. Specify at least one field to update." }], details: { isError: true } };
            }
            const task = await updateKanbanTask(cfg, p.taskId, input);
            return {
                content: [{ type: "text", text: `✓ Updated task "${task.title}" (${task.id})` }],
                details: {},
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return { content: [{ type: "text", text: `Error updating task: ${msg}` }], details: { isError: true } };
        }
    },
};
// ---------------------------------------------------------------------------
// Tool: kanban_move
// ---------------------------------------------------------------------------
const kanbanMoveTool = {
    name: "kanban_move",
    label: "Move Kanban Task",
    description: [
        "Move a Kanban task between columns.",
        "BACKLOG → TODO → IN_PROGRESS → DONE.",
        "Moving to DONE automatically sets the completedAt timestamp.",
        "Use this to reflect actual progress on the board.",
    ].join(" "),
    parameters: {
        type: "object",
        properties: {
            taskId: { type: "string", description: "The Kanban task ID" },
            targetColumn: { type: "string", description: "Target column: BACKLOG, TODO, IN_PROGRESS, DONE" },
            sortOrder: { type: "number", description: "Position within the target column (0 = top). Defaults to 0 (top of column)." },
            projectId: { type: "string", description: "Optional: override the default project ID" },
        },
        required: ["taskId", "targetColumn"],
    },
    async execute(_toolCallId, params) {
        const p = params;
        const validColumns = ["BACKLOG", "TODO", "IN_PROGRESS", "DONE"];
        if (!validColumns.includes(p.targetColumn)) {
            return {
                content: [{ type: "text", text: `Invalid column "${p.targetColumn}". Must be one of: ${validColumns.join(", ")}` }],
                details: { isError: true },
            };
        }
        const cfg = await resolveKanbanConfig(p.projectId);
        if (!cfg) {
            return { content: [{ type: "text", text: "Error: Kanban bridge not configured." }], details: { isError: true } };
        }
        try {
            const task = await moveKanbanTask(cfg, p.taskId, p.targetColumn, p.sortOrder ?? 0);
            return {
                content: [{
                        type: "text",
                        text: `✓ Moved "${task.title}" from ${task.column !== p.targetColumn ? "to " : "within "}${p.targetColumn}`,
                    }],
                details: {},
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return { content: [{ type: "text", text: `Error moving task: ${msg}` }], details: { isError: true } };
        }
    },
};
// ---------------------------------------------------------------------------
// Tool: kanban_next — pick next TODO, mark IN_PROGRESS
// ---------------------------------------------------------------------------
const kanbanNextTool = {
    name: "kanban_next",
    label: "Start Next Kanban Task",
    description: [
        "Pick the next-highest-priority TODO task, mark it IN_PROGRESS, and return its details.",
        "This is the primary task-driven execution tool: call it when you're ready to start working on the next planned task.",
        "The agent should call this, work on the task, then call kanban_move to DONE when finished.",
    ].join(" "),
    parameters: {
        type: "object",
        properties: {
            taskId: { type: "string", description: "Optional: start a specific task by ID instead of auto-selecting the next one." },
            projectId: { type: "string", description: "Optional: override the default project ID" },
        },
    },
    async execute(_toolCallId, params) {
        const p = params;
        const cfg = await resolveKanbanConfig(p.projectId);
        if (!cfg) {
            return { content: [{ type: "text", text: "Error: Kanban bridge not configured." }], details: { isError: true } };
        }
        try {
            const allTasks = await listKanbanTasks(cfg);
            // If a specific task ID is given, start that one
            if (p.taskId) {
                const task = allTasks.find((t) => t.id === p.taskId);
                if (!task) {
                    return { content: [{ type: "text", text: `Task not found: ${p.taskId}` }], details: { isError: true } };
                }
                if (task.column !== "TODO" && task.column !== "BACKLOG") {
                    return {
                        content: [{ type: "text", text: `Task "${task.title}" is already in ${task.column}. Only TODO or BACKLOG tasks can be started.` }],
                        details: { isError: true },
                    };
                }
                const moved = await moveKanbanTask(cfg, p.taskId, "IN_PROGRESS", 0);
                const fullTask = await getKanbanTask(cfg, p.taskId);
                const lines = [
                    `## Started: ${fullTask.title}`,
                    `ID: ${fullTask.id}`,
                    `Priority: ${fullTask.priority}`,
                    `Tags: ${fullTask.tags ?? "(none)"}`,
                    "",
                    "### Description",
                    fullTask.description ?? "(no description)",
                    "",
                    "### Instructions",
                    "1. Read and understand the task description above",
                    "2. Implement the required changes using your tools (read, write, edit, bash)",
                    "3. Test your changes when applicable",
                    `4. When done, call kanban_move to mark this task as DONE`,
                    "5. Then call kanban_next to start the next task (if any)",
                ];
                return { content: [{ type: "text", text: lines.join("\n") }], details: {} };
            }
            // Auto-select: pick the highest-priority TODO task
            const todoTasks = allTasks
                .filter((t) => t.column === "TODO")
                .sort((a, b) => b.priority - a.priority);
            if (todoTasks.length === 0) {
                // Check BACKLOG as fallback
                const backlogTasks = allTasks
                    .filter((t) => t.column === "BACKLOG")
                    .sort((a, b) => b.priority - a.priority);
                if (backlogTasks.length === 0) {
                    return {
                        content: [{ type: "text", text: "No TODO or BACKLOG tasks available. All tasks may be IN_PROGRESS or DONE. Use kanban_list to check the board." }],
                        details: {},
                    };
                }
                // Move the first BACKLOG task to TODO, then start it
                const next = backlogTasks[0];
                await moveKanbanTask(cfg, next.id, "TODO", 0);
                await moveKanbanTask(cfg, next.id, "IN_PROGRESS", 0);
                const fullTask = await getKanbanTask(cfg, next.id);
                const lines = [
                    `## Started (from BACKLOG): ${fullTask.title}`,
                    `ID: ${fullTask.id}`,
                    `Priority: ${fullTask.priority}`,
                    `Tags: ${fullTask.tags ?? "(none)"}`,
                    "",
                    "### Description",
                    fullTask.description ?? "(no description)",
                    "",
                    `Remaining TODO tasks: ${todoTasks.length}. Backlog: ${backlogTasks.length - 1}.`,
                ];
                return { content: [{ type: "text", text: lines.join("\n") }], details: {} };
            }
            // Start the highest-priority TODO
            const next = todoTasks[0];
            const moved = await moveKanbanTask(cfg, next.id, "IN_PROGRESS", 0);
            const fullTask = await getKanbanTask(cfg, next.id);
            const lines = [
                `## Started: ${fullTask.title}`,
                `ID: ${fullTask.id}`,
                `Priority: ${fullTask.priority}`,
                `Tags: ${fullTask.tags ?? "(none)"}`,
                "",
                "### Description",
                fullTask.description ?? "(no description)",
                "",
                "### Instructions",
                "1. Read and understand the task description above",
                "2. Implement the required changes using your tools (read, write, edit, bash)",
                "3. Test your changes when applicable",
                `4. When done, call kanban_move to mark this task as DONE`,
                "5. Then call kanban_next to start the next task (if any)",
                "",
                `Remaining TODO tasks: ${todoTasks.length - 1}`,
            ];
            return { content: [{ type: "text", text: lines.join("\n") }], details: {} };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return { content: [{ type: "text", text: `Error: ${msg}` }], details: { isError: true } };
        }
    },
};
// ---------------------------------------------------------------------------
// Tool: kanban_delete
// ---------------------------------------------------------------------------
const kanbanDeleteTool = {
    name: "kanban_delete",
    label: "Delete Kanban Task",
    description: "Delete a Kanban task from the board.",
    parameters: {
        type: "object",
        properties: {
            taskId: { type: "string", description: "The Kanban task ID to delete" },
            projectId: { type: "string", description: "Optional: override the default project ID" },
        },
        required: ["taskId"],
    },
    async execute(_toolCallId, params) {
        const p = params;
        const cfg = await resolveKanbanConfig(p.projectId);
        if (!cfg) {
            return { content: [{ type: "text", text: "Error: Kanban bridge not configured." }], details: { isError: true } };
        }
        try {
            await deleteKanbanTask(cfg, p.taskId);
            return {
                content: [{ type: "text", text: `✓ Deleted task ${p.taskId}` }],
                details: {},
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return { content: [{ type: "text", text: `Error deleting task: ${msg}` }], details: { isError: true } };
        }
    },
};
// ---------------------------------------------------------------------------
// Auth retry wrapper — handles 401/403 during tool execution
// ---------------------------------------------------------------------------
/**
 * Wrap a tool's execute function so that GraphQL 401/403 errors trigger
 * OAuth re-authentication and a single retry with the fresh token.
 */
function withReauthRetry(toolName, execute) {
    return async (toolCallId, params, signal, onUpdate, ctx) => {
        try {
            return await execute(toolCallId, params, signal, onUpdate, ctx);
        }
        catch (err) {
            if (err instanceof GraphQLError && (err.status === 401 || err.status === 403)) {
                if (_reauthAttempted) {
                    return {
                        content: [{ type: "text", text: `Authentication failed (HTTP ${err.status}). Please run \`spectral login\` to re-authenticate.` }],
                        details: { isError: true },
                    };
                }
                _reauthAttempted = true;
                process.stderr.write(`[kanban-bridge] Auth error (${err.status}) on ${toolName}. Attempting OAuth re-login...\n`);
                const result = await ensureAuthenticated();
                if (result.ok && result.config) {
                    process.stderr.write(`[kanban-bridge] Re-authenticated — retrying ${toolName}...\n`);
                    try {
                        return await execute(toolCallId, params, signal, onUpdate, ctx);
                    }
                    catch (retryErr) {
                        const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
                        return {
                            content: [{ type: "text", text: `Retry after re-auth also failed: ${retryMsg}` }],
                            details: { isError: true },
                        };
                    }
                }
                return {
                    content: [{ type: "text", text: `Re-authentication failed: ${result.reason ?? "unknown"}. Please run \`spectral login\` manually.` }],
                    details: { isError: true },
                };
            }
            throw err;
        }
    };
}
// ---------------------------------------------------------------------------
// Extension entry point
// ---------------------------------------------------------------------------
export default async function kanbanBridgeExtension(ext) {
    const tools = [
        kanbanListTool,
        kanbanGetTool,
        kanbanCreateTool,
        kanbanUpdateTool,
        kanbanMoveTool,
        kanbanNextTool,
        kanbanDeleteTool,
    ];
    let registered = 0;
    for (const tool of tools) {
        try {
            const wrappedTool = { ...tool, execute: withReauthRetry(tool.name, tool.execute) };
            ext.registerTool(wrappedTool);
            registered++;
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            process.stderr.write(`[kanban-bridge] Failed to register tool "${tool.name}": ${msg}\n`);
        }
    }
    // Verify config is resolvable on startup (non-fatal — tools work lazily too)
    const cfg = await resolveKanbanConfig();
    if (cfg) {
        process.stderr.write(`[kanban-bridge] Registered ${registered} Kanban tool(s). Connected to project ${cfg.projectId}.\n`);
    }
    else {
        process.stderr.write(`[kanban-bridge] Registered ${registered} Kanban tool(s). No project bound yet — tools will work once kanban_project_id or studio binding is available.\n`);
    }
}
