import type { ChatProvider, ParsedCommand, ResolvedChatContext, WorkPackage, } from "./work-package-types"; const SLASH_COMMAND = /^\/(ask|plan|change|execute)\b\s*/i; export function resolveChatRequestContext(args: { parsed: ParsedCommand; detailOpen: boolean; selectedWorkPackage?: Pick; }) { const { parsed, detailOpen, selectedWorkPackage } = args; const hasExplicitCommand = Boolean(parsed.mode) || Boolean(parsed.referencedPackageName); if (hasExplicitCommand) { return { parsedCommand: parsed, shouldAutomateBoard: false, source: "explicit-command" as const, }; } const slashMatch = parsed.instruction.match(SLASH_COMMAND); if (slashMatch && selectedWorkPackage) { return { parsedCommand: { referencedPackageName: selectedWorkPackage.title, mode: slashMatch[1].toLowerCase() as "ask" | "plan" | "change" | "execute", instruction: parsed.instruction.replace(SLASH_COMMAND, "").trim(), }, shouldAutomateBoard: false, source: "slash-command" as const, }; } if (detailOpen && selectedWorkPackage && parsed.instruction.trim()) { return { parsedCommand: { referencedPackageName: selectedWorkPackage.title, mode: "ask" as const, instruction: parsed.instruction, }, shouldAutomateBoard: false, source: "selected-package-context" as const, }; } return { parsedCommand: parsed, shouldAutomateBoard: true, source: "board-automation" as const, }; } export function buildResolvedContext(args: { parsedCommand?: ParsedCommand; shouldAutomateBoard?: boolean; selectedWorkPackage?: Pick | null; provider: ChatProvider; }): ResolvedChatContext { const { parsedCommand, shouldAutomateBoard, selectedWorkPackage, provider } = args; if (shouldAutomateBoard || !parsedCommand?.mode) { return { scope: "global", workPackageId: null, workPackageTitle: null, mode: "board_automation", provider, boardMutationPolicy: "replace_all", }; } return { scope: "package", workPackageId: selectedWorkPackage?.id ?? null, workPackageTitle: selectedWorkPackage?.title ?? parsedCommand.referencedPackageName ?? null, mode: parsedCommand.mode, provider, boardMutationPolicy: parsedCommand.mode === "ask" ? "none" : "selected_package_only", }; } export function buildThinkingSummary(args: { context: ResolvedChatContext; model?: string; note?: string; }) { const { context, model, note } = args; const lines: string[] = []; if (context.scope === "package" && context.workPackageTitle) { lines.push(`Resolved scope to ${context.workPackageTitle}.`); } else { lines.push("Resolved scope to board-wide planning."); } if (context.mode === "board_automation") { lines.push("Mode: board_automation. Board hydration is allowed."); } else if (context.boardMutationPolicy === "none") { lines.push(`Mode: ${context.mode}. Board changes are disabled for this request.`); } else { lines.push( `Mode: ${context.mode}. Board changes are limited to the selected work package.`, ); } lines.push( context.provider === "live" ? `Using live model ${model ?? "configured model"}.` : "Using mock mode.", ); if (note) { lines.push(note); } return lines; }