opencode-planpilot 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/models.ts","../src/lib/errors.ts","../src/lib/util.ts","../src/lib/format.ts","../src/lib/app.ts","../src/lib/config.ts","../src/lib/db.ts","../src/studio/bridge.ts"],"sourcesContent":["export type PlanStatus = \"todo\" | \"done\"\nexport type StepStatus = \"todo\" | \"done\"\nexport type GoalStatus = \"todo\" | \"done\"\nexport type StepExecutor = \"ai\" | \"human\"\n\nexport interface PlanRow {\n id: number\n title: string\n content: string\n status: PlanStatus\n comment: string | null\n last_session_id: string | null\n last_cwd: string | null\n created_at: number\n updated_at: number\n}\n\nexport interface StepRow {\n id: number\n plan_id: number\n content: string\n status: StepStatus\n executor: StepExecutor\n sort_order: number\n comment: string | null\n created_at: number\n updated_at: number\n}\n\nexport interface GoalRow {\n id: number\n step_id: number\n content: string\n status: GoalStatus\n comment: string | null\n created_at: number\n updated_at: number\n}\n\nexport interface ActivePlanRow {\n id: number\n session_id: string\n plan_id: number\n updated_at: number\n}\n\nexport interface PlanDetail {\n plan: PlanRow\n steps: StepRow[]\n goals: Map<number, GoalRow[]>\n}\n\nexport interface StepDetail {\n step: StepRow\n goals: GoalRow[]\n}\n\nexport interface GoalDetail {\n goal: GoalRow\n step: StepRow\n}\n\nexport interface StepInput {\n content: string\n executor: StepExecutor\n goals: string[]\n}\n\nexport interface StepStatusChange {\n step_id: number\n from: string\n to: string\n reason: string\n}\n\nexport interface PlanStatusChange {\n plan_id: number\n from: string\n to: string\n reason: string\n}\n\nexport interface ActivePlanCleared {\n plan_id: number\n reason: string\n}\n\nexport interface StatusChanges {\n steps: StepStatusChange[]\n plans: PlanStatusChange[]\n active_plans_cleared: ActivePlanCleared[]\n}\n\nexport interface PlanChanges {\n title?: string\n content?: string\n status?: PlanStatus\n comment?: string\n}\n\nexport interface StepChanges {\n content?: string\n status?: StepStatus\n executor?: StepExecutor\n comment?: string\n}\n\nexport interface GoalChanges {\n content?: string\n status?: GoalStatus\n comment?: string\n}\n\nexport type PlanOrder = \"id\" | \"title\" | \"created\" | \"updated\"\nexport type StepOrder = \"order\" | \"id\" | \"created\" | \"updated\"\n\nexport interface StepQuery {\n status?: StepStatus | null\n executor?: StepExecutor | null\n limit?: number\n offset?: number\n order?: StepOrder\n desc?: boolean\n}\n\nexport interface GoalQuery {\n status?: GoalStatus | null\n limit?: number\n offset?: number\n}\n\nexport function createEmptyStatusChanges(): StatusChanges {\n return { steps: [], plans: [], active_plans_cleared: [] }\n}\n\nexport function mergeStatusChanges(target: StatusChanges, other: StatusChanges) {\n target.steps.push(...other.steps)\n target.plans.push(...other.plans)\n target.active_plans_cleared.push(...other.active_plans_cleared)\n}\n\nexport function statusChangesEmpty(changes: StatusChanges) {\n return !changes.steps.length && !changes.plans.length && !changes.active_plans_cleared.length\n}\n","export type AppErrorKind = \"InvalidInput\" | \"NotFound\" | \"Db\" | \"Io\" | \"Json\"\n\nexport class AppError extends Error {\n public readonly kind: AppErrorKind\n public readonly detail: string\n\n constructor(kind: AppErrorKind, detail: string) {\n super(detail)\n this.kind = kind\n this.detail = detail\n }\n\n toDisplayString(): string {\n const label = this.kind === \"InvalidInput\" ? \"Invalid input\" : this.kind === \"NotFound\" ? \"Not found\" : null\n if (!label) {\n return this.detail\n }\n if (this.detail.includes(\"\\n\")) {\n return `${label}:\\n${this.detail}`\n }\n return `${label}: ${this.detail}`\n }\n}\n\nexport function invalidInput(message: string): AppError {\n return new AppError(\"InvalidInput\", message)\n}\n\nexport function notFound(message: string): AppError {\n return new AppError(\"NotFound\", message)\n}\n\nexport function wrapDbError(message: string, err: unknown): AppError {\n const detail = err instanceof Error ? `${message}: ${err.message}` : message\n return new AppError(\"Db\", detail)\n}\n","import fs from \"fs\"\nimport path from \"path\"\nimport { invalidInput } from \"./errors\"\n\nexport function ensureNonEmpty(label: string, value: string) {\n if (value.trim().length === 0) {\n throw invalidInput(`${label} cannot be empty`)\n }\n}\n\nexport function formatDateTimeUTC(timestamp: number): string {\n const date = new Date(timestamp)\n const yyyy = date.getUTCFullYear()\n const mm = String(date.getUTCMonth() + 1).padStart(2, \"0\")\n const dd = String(date.getUTCDate()).padStart(2, \"0\")\n const hh = String(date.getUTCHours()).padStart(2, \"0\")\n const min = String(date.getUTCMinutes()).padStart(2, \"0\")\n return `${yyyy}-${mm}-${dd} ${hh}:${min}`\n}\n\nexport function uniqueIds(ids: number[]): number[] {\n const seen = new Set<number>()\n const unique: number[] = []\n for (const id of ids) {\n if (!seen.has(id)) {\n seen.add(id)\n unique.push(id)\n }\n }\n return unique\n}\n\nexport function joinIds(ids: number[]): string {\n return ids.map((id) => String(id)).join(\", \")\n}\n\nexport function normalizeCommentEntries(entries: Array<[number, string]>): Array<[number, string]> {\n const seen = new Map<number, number>()\n const ordered: Array<[number, string]> = []\n for (const [id, comment] of entries) {\n const idx = seen.get(id)\n if (idx !== undefined) {\n ordered[idx][1] = comment\n } else {\n seen.set(id, ordered.length)\n ordered.push([id, comment])\n }\n }\n return ordered\n}\n\nconst WAIT_UNTIL_PREFIX = \"@wait-until=\"\nconst WAIT_REASON_PREFIX = \"@wait-reason=\"\n\nexport type WaitComment = {\n until: number\n reason?: string\n}\n\nexport function parseWaitFromComment(comment?: string | null): WaitComment | null {\n if (!comment) return null\n let until: number | null = null\n let reason: string | undefined\n for (const line of comment.split(/\\r?\\n/)) {\n const trimmed = line.trim()\n if (trimmed.startsWith(WAIT_UNTIL_PREFIX)) {\n const raw = trimmed.slice(WAIT_UNTIL_PREFIX.length).trim()\n const value = Number(raw)\n if (Number.isFinite(value)) {\n until = value\n }\n continue\n }\n if (trimmed.startsWith(WAIT_REASON_PREFIX)) {\n const raw = trimmed.slice(WAIT_REASON_PREFIX.length).trim()\n if (raw) reason = raw\n }\n }\n if (until === null) return null\n return { until, reason }\n}\n\nfunction isWaitLine(line: string): boolean {\n const trimmed = line.trim()\n return trimmed.startsWith(WAIT_UNTIL_PREFIX) || trimmed.startsWith(WAIT_REASON_PREFIX)\n}\n\nexport function upsertWaitInComment(comment: string | null, until: number, reason?: string): string {\n const lines = comment ? comment.split(/\\r?\\n/) : []\n const filtered = lines.filter((line) => !isWaitLine(line))\n const waitLines = [`${WAIT_UNTIL_PREFIX}${Math.trunc(until)}`]\n const reasonValue = reason?.trim()\n if (reasonValue) {\n waitLines.push(`${WAIT_REASON_PREFIX}${reasonValue}`)\n }\n return [...waitLines, ...filtered].join(\"\\n\").trimEnd()\n}\n\nexport function removeWaitFromComment(comment?: string | null): string | null {\n if (!comment) return null\n const lines = comment.split(/\\r?\\n/).filter((line) => !isWaitLine(line))\n const cleaned = lines.join(\"\\n\").trimEnd()\n return cleaned.length ? cleaned : null\n}\n\nexport function resolveMaybeRealpath(value: string): string {\n try {\n return fs.realpathSync.native(value)\n } catch {\n return value\n }\n}\n\nexport function normalizePath(value: string): string {\n let resolved = resolveMaybeRealpath(value)\n resolved = path.resolve(resolved)\n if (process.platform === \"win32\") {\n resolved = resolved.toLowerCase()\n }\n return resolved.replace(/[\\\\/]+$/, \"\")\n}\n\nexport function projectMatchesPath(project: string, current: string): boolean {\n const projectNorm = normalizePath(project)\n const currentNorm = normalizePath(current)\n if (projectNorm === currentNorm) return true\n if (currentNorm.startsWith(projectNorm + path.sep)) return true\n if (projectNorm.startsWith(currentNorm + path.sep)) return true\n return false\n}\n","import type { GoalRow, PlanRow, StepRow, PlanDetail } from \"./models\"\nimport { formatDateTimeUTC } from \"./util\"\n\nfunction hasText(value?: string | null) {\n return value !== undefined && value !== null && value.trim().length > 0\n}\n\nexport function formatStepDetail(step: StepRow, goals: GoalRow[]): string {\n let output = \"\"\n output += `Step ID: ${step.id}\\n`\n output += `Plan ID: ${step.plan_id}\\n`\n output += `Status: ${step.status}\\n`\n output += `Executor: ${step.executor}\\n`\n output += `Content: ${step.content}\\n`\n if (hasText(step.comment)) {\n output += `Comment: ${step.comment ?? \"\"}\\n`\n }\n output += `Created: ${formatDateTimeUTC(step.created_at)}\\n`\n output += `Updated: ${formatDateTimeUTC(step.updated_at)}\\n`\n output += \"\\n\"\n if (!goals.length) {\n output += \"Goals: (none)\"\n return output.trimEnd()\n }\n output += \"Goals:\\n\"\n for (const goal of goals) {\n output += `- [${goal.status}] ${goal.content} (goal id ${goal.id})\\n`\n if (hasText(goal.comment)) {\n output += ` Comment: ${goal.comment ?? \"\"}\\n`\n }\n }\n return output.trimEnd()\n}\n\nexport function formatGoalDetail(goal: GoalRow, step: StepRow): string {\n let output = \"\"\n output += `Goal ID: ${goal.id}\\n`\n output += `Step ID: ${goal.step_id}\\n`\n output += `Plan ID: ${step.plan_id}\\n`\n output += `Status: ${goal.status}\\n`\n output += `Content: ${goal.content}\\n`\n if (hasText(goal.comment)) {\n output += `Comment: ${goal.comment ?? \"\"}\\n`\n }\n output += `Created: ${formatDateTimeUTC(goal.created_at)}\\n`\n output += `Updated: ${formatDateTimeUTC(goal.updated_at)}\\n`\n output += \"\\n\"\n output += `Step Status: ${step.status}\\n`\n output += `Step Executor: ${step.executor}\\n`\n output += `Step Content: ${step.content}\\n`\n if (hasText(step.comment)) {\n output += `Step Comment: ${step.comment ?? \"\"}\\n`\n }\n return output.trimEnd()\n}\n\nexport function formatPlanDetail(plan: PlanRow, steps: StepRow[], goals: Map<number, GoalRow[]>): string {\n let output = \"\"\n output += `Plan ID: ${plan.id}\\n`\n output += `Title: ${plan.title}\\n`\n output += `Status: ${plan.status}\\n`\n output += `Content: ${plan.content}\\n`\n if (hasText(plan.comment)) {\n output += `Comment: ${plan.comment ?? \"\"}\\n`\n }\n output += `Created: ${formatDateTimeUTC(plan.created_at)}\\n`\n output += `Updated: ${formatDateTimeUTC(plan.updated_at)}\\n`\n output += \"\\n\"\n if (!steps.length) {\n output += \"Steps: (none)\"\n return output.trimEnd()\n }\n output += \"Steps:\\n\"\n for (const step of steps) {\n const stepGoals = goals.get(step.id) ?? []\n if (stepGoals.length) {\n const done = stepGoals.filter((goal) => goal.status === \"done\").length\n output += `- [${step.status}] ${step.content} (step id ${step.id}, exec ${step.executor}, goals ${done}/${stepGoals.length})\\n`\n } else {\n output += `- [${step.status}] ${step.content} (step id ${step.id}, exec ${step.executor})\\n`\n }\n if (hasText(step.comment)) {\n output += ` Comment: ${step.comment ?? \"\"}\\n`\n }\n if (stepGoals.length) {\n for (const goal of stepGoals) {\n output += ` - [${goal.status}] ${goal.content} (goal id ${goal.id})\\n`\n if (hasText(goal.comment)) {\n output += ` Comment: ${goal.comment ?? \"\"}\\n`\n }\n }\n }\n }\n return output.trimEnd()\n}\n\nexport function formatPlanMarkdown(\n active: boolean,\n activeUpdated: number | null,\n plan: PlanRow,\n steps: StepRow[],\n goals: Map<number, GoalRow[]>,\n): string {\n const lines: string[] = []\n\n const checkbox = (status: string) => (status === \"done\" ? \"x\" : \" \")\n\n const collapseHeading = (text: string) => {\n const normalized = text.replace(/\\r\\n/g, \"\\n\")\n const parts = normalized\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n if (!parts.length) return \"(untitled)\"\n return parts.join(\" / \")\n }\n\n const splitTaskText = (text: string): [string, string[]] => {\n const normalized = text.replace(/\\r\\n/g, \"\\n\")\n const rawLines = normalized.split(\"\\n\")\n if (!rawLines.length) return [\"(empty)\", []]\n let firstIdx = -1\n for (let i = 0; i < rawLines.length; i += 1) {\n if (rawLines[i].trim()) {\n firstIdx = i\n break\n }\n }\n if (firstIdx === -1) return [\"(empty)\", []]\n return [rawLines[firstIdx], rawLines.slice(firstIdx + 1)]\n }\n\n const pushLine = (indent: number, text: string) => {\n lines.push(`${\" \".repeat(indent)}${text}`)\n }\n const pushBlank = (indent: number) => {\n lines.push(indent === 0 ? \"\" : \" \".repeat(indent))\n }\n\n pushLine(0, \"# Plan\")\n pushBlank(0)\n pushLine(0, `## Plan: ${collapseHeading(plan.title)}`)\n pushBlank(0)\n pushLine(0, `- **Active:** \\`${active ? \"true\" : \"false\"}\\``)\n pushLine(0, `- **Plan ID:** \\`${plan.id}\\``)\n pushLine(0, `- **Status:** \\`${plan.status}\\``)\n if (hasText(plan.comment)) {\n pushLine(0, `- **Comment:** ${plan.comment ?? \"\"}`)\n }\n if (activeUpdated) {\n pushLine(0, `- **Activated:** ${formatDateTimeUTC(activeUpdated)}`)\n }\n pushLine(0, `- **Created:** ${formatDateTimeUTC(plan.created_at)}`)\n pushLine(0, `- **Updated:** ${formatDateTimeUTC(plan.updated_at)}`)\n const stepsDone = steps.filter((step) => step.status === \"done\").length\n pushLine(0, `- **Steps:** ${stepsDone}/${steps.length}`)\n pushBlank(0)\n\n pushLine(0, \"### Plan Content\")\n pushBlank(0)\n if (!plan.content.trim()) {\n pushLine(0, \"*No content*\")\n } else {\n const normalized = plan.content.replace(/\\r\\n/g, \"\\n\")\n for (const line of normalized.split(\"\\n\")) {\n if (!line.length) {\n pushLine(0, \">\")\n } else {\n pushLine(0, `> ${line}`)\n }\n }\n }\n pushBlank(0)\n\n pushLine(0, \"### Steps\")\n pushBlank(0)\n if (!steps.length) {\n pushLine(0, \"*No steps*\")\n return lines.join(\"\\n\").trimEnd()\n }\n\n steps.forEach((step, idx) => {\n const [firstLine, restLines] = splitTaskText(step.content)\n pushLine(0, `- [${checkbox(step.status)}] **${firstLine}** *(id: ${step.id}, exec: ${step.executor}, order: ${step.sort_order})*`)\n\n let hasRest = false\n for (const line of restLines) {\n if (!line.trim()) continue\n if (!hasRest) {\n pushBlank(2)\n hasRest = true\n } else {\n pushBlank(2)\n }\n pushLine(2, line)\n }\n\n pushBlank(2)\n pushLine(2, `- Created: ${formatDateTimeUTC(step.created_at)}`)\n pushLine(2, `- Updated: ${formatDateTimeUTC(step.updated_at)}`)\n if (hasText(step.comment)) {\n pushLine(2, `- Comment: ${step.comment ?? \"\"}`)\n }\n\n const stepGoals = goals.get(step.id)\n if (stepGoals && stepGoals.length) {\n const done = stepGoals.filter((goal) => goal.status === \"done\").length\n pushLine(2, `- Goals: ${done}/${stepGoals.length}`)\n for (const goal of stepGoals) {\n const [goalFirst, goalRest] = splitTaskText(goal.content)\n pushBlank(2)\n pushLine(2, `- [${checkbox(goal.status)}] ${goalFirst} *(id: ${goal.id})*`)\n for (const line of goalRest) {\n if (!line.trim()) continue\n pushBlank(4)\n pushLine(4, line)\n }\n if (hasText(goal.comment)) {\n pushBlank(4)\n pushLine(4, `Comment: ${goal.comment ?? \"\"}`)\n }\n }\n } else {\n pushLine(2, \"- Goals: 0/0\")\n pushBlank(2)\n pushLine(2, \"- (none)\")\n }\n\n if (idx + 1 < steps.length) {\n pushBlank(0)\n }\n })\n\n return lines.join(\"\\n\").trimEnd()\n}\n\nexport function planDetailToMarkdown(detail: PlanDetail, active: boolean, activeUpdated: number | null): string {\n return formatPlanMarkdown(active, activeUpdated, detail.plan, detail.steps, detail.goals)\n}\n","import type { DatabaseConnection } from \"./db\"\nimport {\n createEmptyStatusChanges,\n mergeStatusChanges,\n type ActivePlanRow,\n type GoalChanges,\n type GoalDetail,\n type GoalQuery,\n type GoalRow,\n type GoalStatus,\n type PlanChanges,\n type PlanDetail,\n type PlanOrder,\n type PlanRow,\n type PlanStatus,\n type StatusChanges,\n type StepChanges,\n type StepDetail,\n type StepExecutor,\n type StepInput,\n type StepQuery,\n type StepRow,\n type StepStatus,\n} from \"./models\"\nimport {\n ensureNonEmpty,\n joinIds,\n normalizeCommentEntries,\n parseWaitFromComment,\n removeWaitFromComment,\n uniqueIds,\n upsertWaitInComment,\n} from \"./util\"\nimport { invalidInput, notFound } from \"./errors\"\nimport { formatStepDetail } from \"./format\"\n\nexport class PlanpilotApp {\n private db: DatabaseConnection\n private sessionId: string\n private cwd?: string\n\n constructor(db: DatabaseConnection, sessionId: string, cwd?: string) {\n this.db = db\n this.sessionId = sessionId\n this.cwd = cwd\n }\n\n addPlan(input: { title: string; content: string }): PlanRow {\n ensureNonEmpty(\"plan title\", input.title)\n ensureNonEmpty(\"plan content\", input.content)\n const now = Date.now()\n const result = this.db\n .prepare(\n `INSERT INTO plans (title, content, status, comment, last_session_id, last_cwd, created_at, updated_at)\n VALUES (?, ?, ?, NULL, ?, ?, ?, ?)`\n )\n .run(input.title, input.content, \"todo\", this.sessionId, this.cwd ?? null, now, now)\n const plan = this.getPlan(result.lastInsertRowid as number)\n return plan\n }\n\n addPlanTree(input: { title: string; content: string }, steps: StepInput[]): { plan: PlanRow; stepCount: number; goalCount: number } {\n ensureNonEmpty(\"plan title\", input.title)\n ensureNonEmpty(\"plan content\", input.content)\n steps.forEach((step) => {\n ensureNonEmpty(\"step content\", step.content)\n step.goals.forEach((goal) => ensureNonEmpty(\"goal content\", goal))\n })\n\n const tx = this.db.transaction(() => {\n const now = Date.now()\n const planResult = this.db\n .prepare(\n `INSERT INTO plans (title, content, status, comment, last_session_id, last_cwd, created_at, updated_at)\n VALUES (?, ?, ?, NULL, ?, ?, ?, ?)`\n )\n .run(input.title, input.content, \"todo\", this.sessionId, this.cwd ?? null, now, now)\n const plan = this.getPlan(planResult.lastInsertRowid as number)\n\n let stepCount = 0\n let goalCount = 0\n steps.forEach((step, idx) => {\n const stepResult = this.db\n .prepare(\n `INSERT INTO steps (plan_id, content, status, executor, sort_order, comment, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, NULL, ?, ?)`\n )\n .run(plan.id, step.content, \"todo\", step.executor, idx + 1, now, now)\n const stepId = stepResult.lastInsertRowid as number\n stepCount += 1\n step.goals.forEach((goal) => {\n this.db\n .prepare(\n `INSERT INTO goals (step_id, content, status, comment, created_at, updated_at)\n VALUES (?, ?, ?, NULL, ?, ?)`\n )\n .run(stepId, goal, \"todo\", now, now)\n goalCount += 1\n })\n })\n\n return { plan, stepCount, goalCount }\n })\n\n return tx()\n }\n\n listPlans(order?: PlanOrder | null, desc?: boolean): PlanRow[] {\n const orderBy = order ?? \"updated\"\n const direction = desc ? \"DESC\" : \"ASC\"\n const orderColumn =\n orderBy === \"id\" ? \"id\" : orderBy === \"title\" ? \"title\" : orderBy === \"created\" ? \"created_at\" : \"updated_at\"\n\n return this.db\n .prepare(`SELECT * FROM plans ORDER BY ${orderColumn} ${direction}, id ASC`)\n .all() as PlanRow[]\n }\n\n getPlan(id: number): PlanRow {\n const row = this.db.prepare(\"SELECT * FROM plans WHERE id = ?\").get(id) as PlanRow | undefined\n if (!row) throw notFound(`plan id ${id}`)\n return row\n }\n\n getStep(id: number): StepRow {\n const row = this.db.prepare(\"SELECT * FROM steps WHERE id = ?\").get(id) as StepRow | undefined\n if (!row) throw notFound(`step id ${id}`)\n return row\n }\n\n getGoal(id: number): GoalRow {\n const row = this.db.prepare(\"SELECT * FROM goals WHERE id = ?\").get(id) as GoalRow | undefined\n if (!row) throw notFound(`goal id ${id}`)\n return row\n }\n\n planWithSteps(id: number): { plan: PlanRow; steps: StepRow[] } {\n const plan = this.getPlan(id)\n const steps = this.db\n .prepare(\"SELECT * FROM steps WHERE plan_id = ? ORDER BY sort_order ASC, id ASC\")\n .all(id) as StepRow[]\n return { plan, steps }\n }\n\n getPlanDetail(id: number): PlanDetail {\n const plan = this.getPlan(id)\n const steps = this.db\n .prepare(\"SELECT * FROM steps WHERE plan_id = ? ORDER BY sort_order ASC, id ASC\")\n .all(id) as StepRow[]\n const stepIds = steps.map((step) => step.id)\n const goals = this.goalsForSteps(stepIds)\n const goalsMap = new Map<number, GoalRow[]>()\n for (const step of steps) {\n goalsMap.set(step.id, goals.get(step.id) ?? [])\n }\n return { plan, steps, goals: goalsMap }\n }\n\n getStepDetail(id: number): StepDetail {\n const step = this.getStep(id)\n const goals = this.goalsForStep(step.id)\n return { step, goals }\n }\n\n getGoalDetail(id: number): GoalDetail {\n const goal = this.getGoal(id)\n const step = this.getStep(goal.step_id)\n return { goal, step }\n }\n\n getPlanDetails(plans: PlanRow[]): PlanDetail[] {\n if (!plans.length) return []\n const planIds = plans.map((plan) => plan.id)\n const steps = this.db\n .prepare(`SELECT * FROM steps WHERE plan_id IN (${planIds.map(() => \"?\").join(\",\")}) ORDER BY plan_id ASC, sort_order ASC, id ASC`)\n .all(...planIds) as StepRow[]\n const stepIds = steps.map((step) => step.id)\n const goalsByStep = this.goalsForSteps(stepIds)\n\n const stepsByPlan = new Map<number, StepRow[]>()\n for (const step of steps) {\n const list = stepsByPlan.get(step.plan_id)\n if (list) list.push(step)\n else stepsByPlan.set(step.plan_id, [step])\n }\n\n return plans.map((plan) => {\n const planSteps = stepsByPlan.get(plan.id) ?? []\n const goalsMap = new Map<number, GoalRow[]>()\n for (const step of planSteps) {\n goalsMap.set(step.id, goalsByStep.get(step.id) ?? [])\n }\n return { plan, steps: planSteps, goals: goalsMap }\n })\n }\n\n getStepsDetail(steps: StepRow[]): StepDetail[] {\n if (!steps.length) return []\n const stepIds = steps.map((step) => step.id)\n const goalsMap = this.goalsForSteps(stepIds)\n return steps.map((step) => ({\n step,\n goals: goalsMap.get(step.id) ?? [],\n }))\n }\n\n getActivePlan(): ActivePlanRow | null {\n const row = this.db\n .prepare(\"SELECT * FROM active_plan WHERE session_id = ?\")\n .get(this.sessionId) as ActivePlanRow | undefined\n return row ?? null\n }\n\n setActivePlan(planId: number, takeover: boolean): ActivePlanRow {\n this.getPlan(planId)\n const tx = this.db.transaction(() => {\n const existing = this.db\n .prepare(\"SELECT * FROM active_plan WHERE plan_id = ?\")\n .get(planId) as ActivePlanRow | undefined\n if (existing && existing.session_id !== this.sessionId && !takeover) {\n throw invalidInput(\n `plan id ${planId} is already active in session ${existing.session_id} (use --force to take over)`\n )\n }\n\n this.db.prepare(\"DELETE FROM active_plan WHERE session_id = ?\").run(this.sessionId)\n this.db.prepare(\"DELETE FROM active_plan WHERE plan_id = ?\").run(planId)\n\n const now = Date.now()\n this.db\n .prepare(\"INSERT INTO active_plan (session_id, plan_id, updated_at) VALUES (?, ?, ?)\")\n .run(this.sessionId, planId, now)\n\n this.touchPlan(planId)\n\n const created = this.db\n .prepare(\"SELECT * FROM active_plan WHERE session_id = ?\")\n .get(this.sessionId) as ActivePlanRow | undefined\n if (!created) throw notFound(\"active plan not found after insert\")\n return created\n })\n\n return tx()\n }\n\n clearActivePlan() {\n this.db.prepare(\"DELETE FROM active_plan WHERE session_id = ?\").run(this.sessionId)\n }\n\n updatePlanWithActiveClear(id: number, changes: PlanChanges): { plan: PlanRow; cleared: boolean } {\n const tx = this.db.transaction(() => {\n const plan = this.updatePlanWithConn(id, changes)\n let cleared = false\n if (plan.status === \"done\") {\n cleared = this.clearActivePlansForPlanWithConn(plan.id)\n }\n return { plan, cleared }\n })\n\n return tx()\n }\n\n deletePlan(id: number) {\n const tx = this.db.transaction(() => {\n this.db.prepare(\"DELETE FROM active_plan WHERE plan_id = ?\").run(id)\n const stepIds = this.db\n .prepare(\"SELECT id FROM steps WHERE plan_id = ?\")\n .all(id)\n .map((row: any) => row.id as number)\n if (stepIds.length) {\n this.db\n .prepare(`DELETE FROM goals WHERE step_id IN (${stepIds.map(() => \"?\").join(\",\")})`)\n .run(...stepIds)\n this.db.prepare(\"DELETE FROM steps WHERE plan_id = ?\").run(id)\n }\n const result = this.db.prepare(\"DELETE FROM plans WHERE id = ?\").run(id)\n if (result.changes === 0) {\n throw notFound(`plan id ${id}`)\n }\n })\n\n tx()\n }\n\n addStepsBatch(\n planId: number,\n contents: string[],\n status: StepStatus,\n executor: StepExecutor,\n at?: number | null,\n ): { steps: StepRow[]; changes: StatusChanges } {\n if (!this.db.prepare(\"SELECT 1 FROM plans WHERE id = ?\").get(planId)) {\n throw notFound(`plan id ${planId}`)\n }\n if (!contents.length) {\n return { steps: [], changes: createEmptyStatusChanges() }\n }\n contents.forEach((content) => ensureNonEmpty(\"step content\", content))\n\n const tx = this.db.transaction(() => {\n const existing = this.db\n .prepare(\"SELECT * FROM steps WHERE plan_id = ? ORDER BY sort_order ASC, id ASC\")\n .all(planId) as StepRow[]\n this.normalizeStepsInPlace(existing)\n\n const total = existing.length\n const insertPos = at !== undefined && at !== null ? (at > 0 ? Math.min(at, total + 1) : 1) : total + 1\n const now = Date.now()\n const shiftBy = contents.length\n if (shiftBy > 0) {\n for (let idx = existing.length - 1; idx >= 0; idx -= 1) {\n const step = existing[idx]\n if (step.sort_order >= insertPos) {\n const newOrder = step.sort_order + shiftBy\n this.db\n .prepare(\"UPDATE steps SET sort_order = ?, updated_at = ? WHERE id = ?\")\n .run(newOrder, now, step.id)\n step.sort_order = newOrder\n step.updated_at = now\n }\n }\n }\n\n const created: StepRow[] = []\n contents.forEach((content, idx) => {\n const sortOrder = insertPos + idx\n const result = this.db\n .prepare(\n `INSERT INTO steps (plan_id, content, status, executor, sort_order, comment, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, NULL, ?, ?)`\n )\n .run(planId, content, status, executor, sortOrder, now, now)\n const step = this.getStep(result.lastInsertRowid as number)\n created.push(step)\n })\n\n const changes = this.refreshPlanStatus(planId)\n this.touchPlan(planId)\n return { steps: created, changes }\n })\n\n return tx()\n }\n\n addStepTree(planId: number, content: string, executor: StepExecutor, goals: string[]): { step: StepRow; goals: GoalRow[]; changes: StatusChanges } {\n ensureNonEmpty(\"step content\", content)\n goals.forEach((goal) => ensureNonEmpty(\"goal content\", goal))\n\n const tx = this.db.transaction(() => {\n if (!this.db.prepare(\"SELECT 1 FROM plans WHERE id = ?\").get(planId)) {\n throw notFound(`plan id ${planId}`)\n }\n const existing = this.db\n .prepare(\"SELECT * FROM steps WHERE plan_id = ? ORDER BY sort_order ASC, id ASC\")\n .all(planId) as StepRow[]\n this.normalizeStepsInPlace(existing)\n\n const sortOrder = existing.length + 1\n const now = Date.now()\n const stepResult = this.db\n .prepare(\n `INSERT INTO steps (plan_id, content, status, executor, sort_order, comment, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, NULL, ?, ?)`\n )\n .run(planId, content, \"todo\", executor, sortOrder, now, now)\n const step = this.getStep(stepResult.lastInsertRowid as number)\n\n const createdGoals: GoalRow[] = []\n for (const goalContent of goals) {\n const goalResult = this.db\n .prepare(\n `INSERT INTO goals (step_id, content, status, comment, created_at, updated_at)\n VALUES (?, ?, ?, NULL, ?, ?)`\n )\n .run(step.id, goalContent, \"todo\", now, now)\n createdGoals.push(this.getGoal(goalResult.lastInsertRowid as number))\n }\n\n const changes = this.refreshPlanStatus(planId)\n this.touchPlan(planId)\n return { step, goals: createdGoals, changes }\n })\n\n return tx()\n }\n\n listStepsFiltered(planId: number, query: StepQuery): StepRow[] {\n this.getPlan(planId)\n const conditions: string[] = [\"plan_id = ?\"]\n const params: any[] = [planId]\n if (query.status) {\n conditions.push(\"status = ?\")\n params.push(query.status)\n }\n if (query.executor) {\n conditions.push(\"executor = ?\")\n params.push(query.executor)\n }\n const order = query.order ?? \"order\"\n const direction = query.desc ? \"DESC\" : \"ASC\"\n const orderColumn =\n order === \"id\"\n ? \"id\"\n : order === \"created\"\n ? \"created_at\"\n : order === \"updated\"\n ? \"updated_at\"\n : \"sort_order\"\n\n let sql = `SELECT * FROM steps WHERE ${conditions.join(\" AND \")} ORDER BY ${orderColumn} ${direction}, id ASC`\n if (query.limit !== undefined) {\n sql += \" LIMIT ?\"\n params.push(query.limit)\n }\n if (query.offset !== undefined) {\n sql += \" OFFSET ?\"\n params.push(query.offset)\n }\n return this.db.prepare(sql).all(...params) as StepRow[]\n }\n\n countSteps(planId: number, query: StepQuery): number {\n this.getPlan(planId)\n const conditions: string[] = [\"plan_id = ?\"]\n const params: any[] = [planId]\n if (query.status) {\n conditions.push(\"status = ?\")\n params.push(query.status)\n }\n if (query.executor) {\n conditions.push(\"executor = ?\")\n params.push(query.executor)\n }\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM steps WHERE ${conditions.join(\" AND \")}`)\n .get(...params) as { count: number }\n return row.count\n }\n\n nextStep(planId: number): StepRow | null {\n const row = this.db\n .prepare(\"SELECT * FROM steps WHERE plan_id = ? AND status = ? ORDER BY sort_order ASC, id ASC LIMIT 1\")\n .get(planId, \"todo\") as StepRow | undefined\n return row ?? null\n }\n\n updateStep(id: number, changes: StepChanges): { step: StepRow; changes: StatusChanges } {\n const tx = this.db.transaction(() => {\n if (changes.content !== undefined) {\n ensureNonEmpty(\"step content\", changes.content)\n }\n if (changes.status === \"done\") {\n const pending = this.nextGoalForStep(id)\n if (pending) {\n throw invalidInput(`cannot mark step done; next pending goal: ${pending.content} (id ${pending.id})`)\n }\n }\n const existing = this.getStep(id)\n const now = Date.now()\n\n const updated = {\n content: changes.content ?? existing.content,\n status: changes.status ?? existing.status,\n executor: changes.executor ?? existing.executor,\n comment: changes.comment !== undefined ? changes.comment : existing.comment,\n }\n this.db\n .prepare(\n `UPDATE steps SET content = ?, status = ?, executor = ?, comment = ?, updated_at = ? WHERE id = ?`\n )\n .run(updated.content, updated.status, updated.executor, updated.comment, now, id)\n\n const step = this.getStep(id)\n const statusChanges = createEmptyStatusChanges()\n if (changes.status !== undefined) {\n mergeStatusChanges(statusChanges, this.refreshPlanStatus(step.plan_id))\n }\n this.touchPlan(step.plan_id)\n return { step, changes: statusChanges }\n })\n\n return tx()\n }\n\n setStepDoneWithGoals(id: number, allGoals: boolean): { step: StepRow; changes: StatusChanges } {\n const tx = this.db.transaction(() => {\n let changes = createEmptyStatusChanges()\n if (allGoals) {\n const goalChanges = this.setAllGoalsDoneForStep(id)\n mergeStatusChanges(changes, goalChanges)\n } else {\n const pending = this.nextGoalForStep(id)\n if (pending) {\n throw invalidInput(`cannot mark step done; next pending goal: ${pending.content} (id ${pending.id})`)\n }\n }\n\n const existing = this.getStep(id)\n if (existing.status !== \"done\") {\n const now = Date.now()\n this.db.prepare(\"UPDATE steps SET status = ?, updated_at = ? WHERE id = ?\").run(\"done\", now, id)\n }\n const step = this.getStep(id)\n mergeStatusChanges(changes, this.refreshPlanStatus(step.plan_id))\n this.touchPlan(step.plan_id)\n return { step, changes }\n })\n\n return tx()\n }\n\n moveStep(id: number, to: number): StepRow[] {\n const tx = this.db.transaction(() => {\n const target = this.getStep(id)\n const planId = target.plan_id\n const steps = this.db\n .prepare(\"SELECT * FROM steps WHERE plan_id = ? ORDER BY sort_order ASC, id ASC\")\n .all(planId) as StepRow[]\n const currentIndex = steps.findIndex((step) => step.id === id)\n if (currentIndex === -1) throw notFound(`step id ${id}`)\n let desiredIndex = Math.max(to - 1, 0)\n if (desiredIndex >= steps.length) desiredIndex = steps.length - 1\n\n const [moving] = steps.splice(currentIndex, 1)\n if (desiredIndex >= steps.length) steps.push(moving)\n else steps.splice(desiredIndex, 0, moving)\n\n const now = Date.now()\n steps.forEach((step, idx) => {\n const desiredOrder = idx + 1\n if (step.sort_order !== desiredOrder) {\n this.db\n .prepare(\"UPDATE steps SET sort_order = ?, updated_at = ? WHERE id = ?\")\n .run(desiredOrder, now, step.id)\n step.sort_order = desiredOrder\n step.updated_at = now\n }\n })\n return steps\n })\n\n return tx()\n }\n\n deleteSteps(ids: number[]): { deleted: number; changes: StatusChanges } {\n const tx = this.db.transaction(() => {\n if (!ids.length) return { deleted: 0, changes: createEmptyStatusChanges() }\n const unique = uniqueIds(ids)\n const steps = this.db\n .prepare(`SELECT * FROM steps WHERE id IN (${unique.map(() => \"?\").join(\",\")})`)\n .all(...unique) as StepRow[]\n const existing = new Set(steps.map((step) => step.id))\n const missing = unique.filter((id) => !existing.has(id))\n if (missing.length) {\n throw notFound(`step id(s) not found: ${joinIds(missing)}`)\n }\n\n const planIds = Array.from(new Set(steps.map((step) => step.plan_id)))\n if (unique.length) {\n this.db\n .prepare(`DELETE FROM goals WHERE step_id IN (${unique.map(() => \"?\").join(\",\")})`)\n .run(...unique)\n }\n const result = this.db\n .prepare(`DELETE FROM steps WHERE id IN (${unique.map(() => \"?\").join(\",\")})`)\n .run(...unique)\n\n planIds.forEach((planId) => this.normalizeStepsForPlan(planId))\n\n const changes = createEmptyStatusChanges()\n planIds.forEach((planId) => mergeStatusChanges(changes, this.refreshPlanStatus(planId)))\n if (planIds.length) {\n this.touchPlans(planIds)\n }\n return { deleted: result.changes, changes }\n })\n\n return tx()\n }\n\n addGoalsBatch(stepId: number, contents: string[], status: GoalStatus): { goals: GoalRow[]; changes: StatusChanges } {\n if (!contents.length) return { goals: [], changes: createEmptyStatusChanges() }\n contents.forEach((content) => ensureNonEmpty(\"goal content\", content))\n\n const tx = this.db.transaction(() => {\n const step = this.getStep(stepId)\n const now = Date.now()\n const created: GoalRow[] = []\n contents.forEach((content) => {\n const result = this.db\n .prepare(\n `INSERT INTO goals (step_id, content, status, comment, created_at, updated_at)\n VALUES (?, ?, ?, NULL, ?, ?)`\n )\n .run(stepId, content, status, now, now)\n created.push(this.getGoal(result.lastInsertRowid as number))\n })\n const changes = this.refreshStepStatus(stepId)\n this.touchPlan(step.plan_id)\n return { goals: created, changes }\n })\n\n return tx()\n }\n\n listGoalsFiltered(stepId: number, query: GoalQuery): GoalRow[] {\n this.getStep(stepId)\n const conditions: string[] = [\"step_id = ?\"]\n const params: any[] = [stepId]\n if (query.status) {\n conditions.push(\"status = ?\")\n params.push(query.status)\n }\n let sql = `SELECT * FROM goals WHERE ${conditions.join(\" AND \")} ORDER BY updated_at DESC, id DESC`\n if (query.limit !== undefined) {\n sql += \" LIMIT ?\"\n params.push(query.limit)\n }\n if (query.offset !== undefined) {\n sql += \" OFFSET ?\"\n params.push(query.offset)\n }\n return this.db.prepare(sql).all(...params) as GoalRow[]\n }\n\n countGoals(stepId: number, query: GoalQuery): number {\n this.getStep(stepId)\n const conditions: string[] = [\"step_id = ?\"]\n const params: any[] = [stepId]\n if (query.status) {\n conditions.push(\"status = ?\")\n params.push(query.status)\n }\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM goals WHERE ${conditions.join(\" AND \")}`)\n .get(...params) as { count: number }\n return row.count\n }\n\n updateGoal(id: number, changes: GoalChanges): { goal: GoalRow; changes: StatusChanges } {\n const tx = this.db.transaction(() => {\n if (changes.content !== undefined) {\n ensureNonEmpty(\"goal content\", changes.content)\n }\n const existing = this.getGoal(id)\n const now = Date.now()\n const updated = {\n content: changes.content ?? existing.content,\n status: changes.status ?? existing.status,\n comment: changes.comment !== undefined ? changes.comment : existing.comment,\n }\n this.db\n .prepare(\"UPDATE goals SET content = ?, status = ?, comment = ?, updated_at = ? WHERE id = ?\")\n .run(updated.content, updated.status, updated.comment, now, id)\n\n const goal = this.getGoal(id)\n const statusChanges = createEmptyStatusChanges()\n if (changes.status !== undefined) {\n mergeStatusChanges(statusChanges, this.refreshStepStatus(goal.step_id))\n }\n const step = this.getStep(goal.step_id)\n this.touchPlan(step.plan_id)\n return { goal, changes: statusChanges }\n })\n\n return tx()\n }\n\n setGoalStatus(id: number, status: GoalStatus): { goal: GoalRow; changes: StatusChanges } {\n const tx = this.db.transaction(() => {\n this.getGoal(id)\n const now = Date.now()\n this.db.prepare(\"UPDATE goals SET status = ?, updated_at = ? WHERE id = ?\").run(status, now, id)\n const goal = this.getGoal(id)\n const changes = this.refreshStepStatus(goal.step_id)\n const step = this.getStep(goal.step_id)\n this.touchPlan(step.plan_id)\n return { goal, changes }\n })\n\n return tx()\n }\n\n setGoalsStatus(ids: number[], status: GoalStatus): { updated: number; changes: StatusChanges } {\n if (!ids.length) return { updated: 0, changes: createEmptyStatusChanges() }\n const tx = this.db.transaction(() => {\n const unique = uniqueIds(ids)\n const goals = this.db\n .prepare(`SELECT * FROM goals WHERE id IN (${unique.map(() => \"?\").join(\",\")})`)\n .all(...unique) as GoalRow[]\n const existing = new Set(goals.map((goal) => goal.id))\n const missing = unique.filter((id) => !existing.has(id))\n if (missing.length) {\n throw notFound(`goal id(s) not found: ${joinIds(missing)}`)\n }\n const now = Date.now()\n const stepIds: number[] = []\n const stepSeen = new Set<number>()\n goals.forEach((goal) => {\n if (!stepSeen.has(goal.step_id)) {\n stepSeen.add(goal.step_id)\n stepIds.push(goal.step_id)\n }\n this.db.prepare(\"UPDATE goals SET status = ?, updated_at = ? WHERE id = ?\").run(status, now, goal.id)\n })\n\n const changes = createEmptyStatusChanges()\n stepIds.forEach((stepId) => mergeStatusChanges(changes, this.refreshStepStatus(stepId)))\n\n const planIds: number[] = []\n if (stepIds.length) {\n const steps = this.db\n .prepare(`SELECT plan_id FROM steps WHERE id IN (${stepIds.map(() => \"?\").join(\",\")})`)\n .all(...stepIds) as Array<{ plan_id: number }>\n const seen = new Set<number>()\n steps.forEach((row) => {\n if (!seen.has(row.plan_id)) {\n seen.add(row.plan_id)\n planIds.push(row.plan_id)\n }\n })\n }\n if (planIds.length) this.touchPlans(planIds)\n\n return { updated: unique.length, changes }\n })\n\n return tx()\n }\n\n deleteGoals(ids: number[]): { deleted: number; changes: StatusChanges } {\n const tx = this.db.transaction(() => {\n if (!ids.length) return { deleted: 0, changes: createEmptyStatusChanges() }\n const unique = uniqueIds(ids)\n const goals = this.db\n .prepare(`SELECT * FROM goals WHERE id IN (${unique.map(() => \"?\").join(\",\")})`)\n .all(...unique) as GoalRow[]\n const existing = new Set(goals.map((goal) => goal.id))\n const missing = unique.filter((id) => !existing.has(id))\n if (missing.length) {\n throw notFound(`goal id(s) not found: ${joinIds(missing)}`)\n }\n\n const stepIds = Array.from(new Set(goals.map((goal) => goal.step_id)))\n const result = this.db\n .prepare(`DELETE FROM goals WHERE id IN (${unique.map(() => \"?\").join(\",\")})`)\n .run(...unique)\n\n const changes = createEmptyStatusChanges()\n stepIds.forEach((stepId) => mergeStatusChanges(changes, this.refreshStepStatus(stepId)))\n\n if (stepIds.length) {\n const planIds: number[] = []\n const steps = this.db\n .prepare(`SELECT plan_id FROM steps WHERE id IN (${stepIds.map(() => \"?\").join(\",\")})`)\n .all(...stepIds) as Array<{ plan_id: number }>\n const seen = new Set<number>()\n steps.forEach((row) => {\n if (!seen.has(row.plan_id)) {\n seen.add(row.plan_id)\n planIds.push(row.plan_id)\n }\n })\n if (planIds.length) this.touchPlans(planIds)\n }\n\n return { deleted: result.changes, changes }\n })\n\n return tx()\n }\n\n commentPlans(entries: Array<[number, string]>): number[] {\n const normalized = normalizeCommentEntries(entries)\n if (!normalized.length) return []\n const ids = normalized.map(([id]) => id)\n const tx = this.db.transaction(() => {\n const existing = this.db\n .prepare(`SELECT id FROM plans WHERE id IN (${ids.map(() => \"?\").join(\",\")})`)\n .all(...ids)\n .map((row: any) => row.id as number)\n const existingSet = new Set(existing)\n const missing = ids.filter((id) => !existingSet.has(id))\n if (missing.length) {\n throw notFound(`plan id(s) not found: ${joinIds(missing)}`)\n }\n const now = Date.now()\n normalized.forEach(([planId, comment]) => {\n if (this.cwd) {\n this.db\n .prepare(\"UPDATE plans SET comment = ?, last_session_id = ?, last_cwd = ?, updated_at = ? WHERE id = ?\")\n .run(comment, this.sessionId, this.cwd, now, planId)\n } else {\n this.db\n .prepare(\"UPDATE plans SET comment = ?, last_session_id = ?, updated_at = ? WHERE id = ?\")\n .run(comment, this.sessionId, now, planId)\n }\n })\n return ids\n })\n\n return tx()\n }\n\n commentSteps(entries: Array<[number, string]>): number[] {\n const normalized = normalizeCommentEntries(entries)\n if (!normalized.length) return []\n const ids = normalized.map(([id]) => id)\n const tx = this.db.transaction(() => {\n const steps = this.db\n .prepare(`SELECT * FROM steps WHERE id IN (${ids.map(() => \"?\").join(\",\")})`)\n .all(...ids) as StepRow[]\n const existing = new Set(steps.map((step) => step.id))\n const missing = ids.filter((id) => !existing.has(id))\n if (missing.length) {\n throw notFound(`step id(s) not found: ${joinIds(missing)}`)\n }\n\n const planIds = Array.from(new Set(steps.map((step) => step.plan_id)))\n const now = Date.now()\n normalized.forEach(([stepId, comment]) => {\n this.db.prepare(\"UPDATE steps SET comment = ?, updated_at = ? WHERE id = ?\").run(comment, now, stepId)\n })\n if (planIds.length) this.touchPlans(planIds)\n return planIds\n })\n\n return tx()\n }\n\n setStepWait(stepId: number, delayMs: number, reason?: string): { step: StepRow; until: number } {\n if (!Number.isFinite(delayMs) || delayMs < 0) {\n throw invalidInput(\"delay must be a non-negative number\")\n }\n const tx = this.db.transaction(() => {\n const step = this.getStep(stepId)\n const now = Date.now()\n const until = now + Math.trunc(delayMs)\n const comment = upsertWaitInComment(step.comment, until, reason)\n this.db.prepare(\"UPDATE steps SET comment = ?, updated_at = ? WHERE id = ?\").run(comment, now, stepId)\n const updated = this.getStep(stepId)\n this.touchPlan(updated.plan_id)\n return { step: updated, until }\n })\n\n return tx()\n }\n\n clearStepWait(stepId: number): { step: StepRow } {\n const tx = this.db.transaction(() => {\n const step = this.getStep(stepId)\n const comment = step.comment ? removeWaitFromComment(step.comment) : null\n const now = Date.now()\n this.db.prepare(\"UPDATE steps SET comment = ?, updated_at = ? WHERE id = ?\").run(comment, now, stepId)\n const updated = this.getStep(stepId)\n this.touchPlan(updated.plan_id)\n return { step: updated }\n })\n\n return tx()\n }\n\n getStepWait(stepId: number): { step: StepRow; wait: { until: number; reason?: string } | null } {\n const step = this.getStep(stepId)\n const wait = parseWaitFromComment(step.comment)\n return { step, wait }\n }\n\n commentGoals(entries: Array<[number, string]>): number[] {\n const normalized = normalizeCommentEntries(entries)\n if (!normalized.length) return []\n const ids = normalized.map(([id]) => id)\n const tx = this.db.transaction(() => {\n const goals = this.db\n .prepare(`SELECT * FROM goals WHERE id IN (${ids.map(() => \"?\").join(\",\")})`)\n .all(...ids) as GoalRow[]\n const existing = new Set(goals.map((goal) => goal.id))\n const missing = ids.filter((id) => !existing.has(id))\n if (missing.length) {\n throw notFound(`goal id(s) not found: ${joinIds(missing)}`)\n }\n\n const stepIds = Array.from(new Set(goals.map((goal) => goal.step_id)))\n const now = Date.now()\n normalized.forEach(([goalId, comment]) => {\n this.db.prepare(\"UPDATE goals SET comment = ?, updated_at = ? WHERE id = ?\").run(comment, now, goalId)\n })\n\n if (stepIds.length) {\n const planIds: number[] = []\n const steps = this.db\n .prepare(`SELECT plan_id FROM steps WHERE id IN (${stepIds.map(() => \"?\").join(\",\")})`)\n .all(...stepIds) as Array<{ plan_id: number }>\n const seen = new Set<number>()\n steps.forEach((row) => {\n if (!seen.has(row.plan_id)) {\n seen.add(row.plan_id)\n planIds.push(row.plan_id)\n }\n })\n if (planIds.length) this.touchPlans(planIds)\n return planIds\n }\n\n return []\n })\n\n return tx()\n }\n\n goalsForStep(stepId: number): GoalRow[] {\n return this.db.prepare(\"SELECT * FROM goals WHERE step_id = ? ORDER BY id ASC\").all(stepId) as GoalRow[]\n }\n\n goalsForSteps(stepIds: number[]): Map<number, GoalRow[]> {\n const grouped = new Map<number, GoalRow[]>()\n if (!stepIds.length) return grouped\n const rows = this.db\n .prepare(`SELECT * FROM goals WHERE step_id IN (${stepIds.map(() => \"?\").join(\",\")}) ORDER BY step_id ASC, id ASC`)\n .all(...stepIds) as GoalRow[]\n rows.forEach((goal) => {\n const list = grouped.get(goal.step_id)\n if (list) list.push(goal)\n else grouped.set(goal.step_id, [goal])\n })\n return grouped\n }\n\n planIdsForSteps(ids: number[]): number[] {\n if (!ids.length) return []\n const unique = uniqueIds(ids)\n const rows = this.db\n .prepare(`SELECT plan_id FROM steps WHERE id IN (${unique.map(() => \"?\").join(\",\")})`)\n .all(...unique) as Array<{ plan_id: number }>\n const seen = new Set<number>()\n const planIds: number[] = []\n rows.forEach((row) => {\n if (!seen.has(row.plan_id)) {\n seen.add(row.plan_id)\n planIds.push(row.plan_id)\n }\n })\n return planIds\n }\n\n planIdsForGoals(ids: number[]): number[] {\n if (!ids.length) return []\n const unique = uniqueIds(ids)\n const goals = this.db\n .prepare(`SELECT step_id FROM goals WHERE id IN (${unique.map(() => \"?\").join(\",\")})`)\n .all(...unique) as Array<{ step_id: number }>\n const stepIds = Array.from(new Set(goals.map((row) => row.step_id)))\n if (!stepIds.length) return []\n const steps = this.db\n .prepare(`SELECT plan_id FROM steps WHERE id IN (${stepIds.map(() => \"?\").join(\",\")})`)\n .all(...stepIds) as Array<{ plan_id: number }>\n const seen = new Set<number>()\n const planIds: number[] = []\n steps.forEach((row) => {\n if (!seen.has(row.plan_id)) {\n seen.add(row.plan_id)\n planIds.push(row.plan_id)\n }\n })\n return planIds\n }\n\n private updatePlanWithConn(id: number, changes: PlanChanges): PlanRow {\n if (changes.title !== undefined) ensureNonEmpty(\"plan title\", changes.title)\n if (changes.content !== undefined) ensureNonEmpty(\"plan content\", changes.content)\n if (changes.status === \"done\") {\n const total = this.db.prepare(\"SELECT COUNT(*) as count FROM steps WHERE plan_id = ?\").get(id) as { count: number }\n if (total.count > 0) {\n const next = this.nextStep(id)\n if (next) {\n const goals = this.goalsForStep(next.id)\n const detail = formatStepDetail(next, goals)\n throw invalidInput(`cannot mark plan done; next pending step:\\n${detail}`)\n }\n }\n }\n\n const existing = this.getPlan(id)\n const now = Date.now()\n const updated = {\n title: changes.title ?? existing.title,\n content: changes.content ?? existing.content,\n status: changes.status ?? existing.status,\n comment: changes.comment !== undefined ? changes.comment : existing.comment,\n }\n\n if (this.cwd) {\n this.db\n .prepare(\n `UPDATE plans SET title = ?, content = ?, status = ?, comment = ?, last_session_id = ?, last_cwd = ?, updated_at = ? WHERE id = ?`\n )\n .run(updated.title, updated.content, updated.status, updated.comment, this.sessionId, this.cwd, now, id)\n } else {\n this.db\n .prepare(\n `UPDATE plans SET title = ?, content = ?, status = ?, comment = ?, last_session_id = ?, updated_at = ? WHERE id = ?`\n )\n .run(updated.title, updated.content, updated.status, updated.comment, this.sessionId, now, id)\n }\n\n return this.getPlan(id)\n }\n\n private refreshPlanStatus(planId: number): StatusChanges {\n const total = this.db.prepare(\"SELECT COUNT(*) as count FROM steps WHERE plan_id = ?\").get(planId) as { count: number }\n if (total.count === 0) return createEmptyStatusChanges()\n const done = this.db\n .prepare(\"SELECT COUNT(*) as count FROM steps WHERE plan_id = ? AND status = ?\")\n .get(planId, \"done\") as { count: number }\n const status: PlanStatus = done.count === total.count ? \"done\" : \"todo\"\n\n const plan = this.getPlan(planId)\n const changes = createEmptyStatusChanges()\n if (plan.status !== status) {\n const now = Date.now()\n const reason = done.count === total.count ? `all steps are done (${done.count}/${total.count})` : `steps done ${done.count}/${total.count}`\n this.db.prepare(\"UPDATE plans SET status = ?, updated_at = ? WHERE id = ?\").run(status, now, planId)\n changes.plans.push({ plan_id: planId, from: plan.status, to: status, reason })\n if (status === \"done\") {\n const clearedCurrent = this.clearActivePlansForPlanWithConn(planId)\n if (clearedCurrent) {\n changes.active_plans_cleared.push({ plan_id: planId, reason: \"plan marked done\" })\n }\n }\n }\n return changes\n }\n\n private refreshStepStatus(stepId: number): StatusChanges {\n const goals = this.db.prepare(\"SELECT * FROM goals WHERE step_id = ? ORDER BY id ASC\").all(stepId) as GoalRow[]\n if (!goals.length) return createEmptyStatusChanges()\n const doneCount = goals.filter((goal) => goal.status === \"done\").length\n const total = goals.length\n const status: StepStatus = doneCount === total ? \"done\" : \"todo\"\n\n const step = this.getStep(stepId)\n const changes = createEmptyStatusChanges()\n if (step.status !== status) {\n const now = Date.now()\n const reason = doneCount === total ? `all goals are done (${doneCount}/${total})` : `goals done ${doneCount}/${total}`\n this.db.prepare(\"UPDATE steps SET status = ?, updated_at = ? WHERE id = ?\").run(status, now, stepId)\n changes.steps.push({ step_id: stepId, from: step.status, to: status, reason })\n }\n mergeStatusChanges(changes, this.refreshPlanStatus(step.plan_id))\n return changes\n }\n\n private nextGoalForStep(stepId: number): GoalRow | null {\n const row = this.db\n .prepare(\"SELECT * FROM goals WHERE step_id = ? AND status = ? ORDER BY id ASC LIMIT 1\")\n .get(stepId, \"todo\") as GoalRow | undefined\n return row ?? null\n }\n\n private setAllGoalsDoneForStep(stepId: number): StatusChanges {\n this.getStep(stepId)\n const goals = this.goalsForStep(stepId)\n if (!goals.length) return createEmptyStatusChanges()\n const ids = goals.map((goal) => goal.id)\n return this.setGoalsStatus(ids, \"done\").changes\n }\n\n private touchPlan(planId: number) {\n const now = Date.now()\n if (this.cwd) {\n const result = this.db\n .prepare(\"UPDATE plans SET last_session_id = ?, last_cwd = ?, updated_at = ? WHERE id = ?\")\n .run(this.sessionId, this.cwd, now, planId)\n if (result.changes === 0) {\n throw notFound(`plan id ${planId}`)\n }\n } else {\n const result = this.db\n .prepare(\"UPDATE plans SET last_session_id = ?, updated_at = ? WHERE id = ?\")\n .run(this.sessionId, now, planId)\n if (result.changes === 0) {\n throw notFound(`plan id ${planId}`)\n }\n }\n }\n\n private touchPlans(planIds: number[]) {\n planIds.forEach((planId) => this.touchPlan(planId))\n }\n\n private normalizeStepsForPlan(planId: number) {\n const steps = this.db\n .prepare(\"SELECT * FROM steps WHERE plan_id = ? ORDER BY sort_order ASC, id ASC\")\n .all(planId) as StepRow[]\n this.normalizeStepsInPlace(steps)\n }\n\n private normalizeStepsInPlace(steps: StepRow[]) {\n const now = Date.now()\n steps.forEach((step, idx) => {\n const desired = idx + 1\n if (step.sort_order !== desired) {\n this.db.prepare(\"UPDATE steps SET sort_order = ?, updated_at = ? WHERE id = ?\").run(desired, now, step.id)\n step.sort_order = desired\n step.updated_at = now\n }\n })\n }\n\n private clearActivePlansForPlanWithConn(planId: number): boolean {\n const existing = this.db\n .prepare(\"SELECT * FROM active_plan WHERE plan_id = ?\")\n .all(planId) as ActivePlanRow[]\n const clearedCurrent = existing.some((row) => row.session_id === this.sessionId)\n this.db.prepare(\"DELETE FROM active_plan WHERE plan_id = ?\").run(planId)\n return clearedCurrent\n }\n}\n","import fs from \"fs\"\nimport path from \"path\"\nimport { resolvePlanpilotDir } from \"./db\"\n\nexport type KeywordRule = {\n any: string[]\n all: string[]\n none: string[]\n matchCase: boolean\n}\n\nexport type EventRule = {\n enabled: boolean\n force: boolean\n keywords: KeywordRule\n}\n\nexport type SessionErrorRule = EventRule & {\n errorNames: string[]\n statusCodes: number[]\n retryableOnly: boolean\n}\n\nexport type SessionRetryRule = EventRule & {\n attemptAtLeast: number\n}\n\nexport type SendRetryConfig = {\n enabled: boolean\n maxAttempts: number\n delaysMs: number[]\n}\n\nexport type AutoContinueConfig = {\n sendRetry: SendRetryConfig\n onSessionError: SessionErrorRule\n onSessionRetry: SessionRetryRule\n onPermissionAsked: EventRule\n onPermissionRejected: EventRule\n onQuestionAsked: EventRule\n onQuestionRejected: EventRule\n}\n\nexport type RuntimeConfig = {\n paused: boolean\n}\n\nexport type PlanpilotConfig = {\n autoContinue: AutoContinueConfig\n runtime: RuntimeConfig\n}\n\nexport type LoadedPlanpilotConfig = {\n path: string\n loadedFromFile: boolean\n config: PlanpilotConfig\n loadError?: string\n}\n\nconst DEFAULT_KEYWORDS: KeywordRule = {\n any: [],\n all: [],\n none: [],\n matchCase: false,\n}\n\nconst DEFAULT_EVENT_RULE: EventRule = {\n enabled: false,\n force: false,\n keywords: DEFAULT_KEYWORDS,\n}\n\nconst DEFAULT_SESSION_ERROR_RULE: SessionErrorRule = {\n enabled: false,\n force: true,\n keywords: DEFAULT_KEYWORDS,\n errorNames: [],\n statusCodes: [],\n retryableOnly: false,\n}\n\nconst DEFAULT_SESSION_RETRY_RULE: SessionRetryRule = {\n enabled: false,\n force: false,\n keywords: DEFAULT_KEYWORDS,\n attemptAtLeast: 1,\n}\n\nconst DEFAULT_SEND_RETRY: SendRetryConfig = {\n enabled: true,\n maxAttempts: 3,\n delaysMs: [1500, 5000, 15000],\n}\n\nexport const DEFAULT_PLANPILOT_CONFIG: PlanpilotConfig = {\n autoContinue: {\n sendRetry: DEFAULT_SEND_RETRY,\n onSessionError: DEFAULT_SESSION_ERROR_RULE,\n onSessionRetry: DEFAULT_SESSION_RETRY_RULE,\n onPermissionAsked: DEFAULT_EVENT_RULE,\n onPermissionRejected: {\n ...DEFAULT_EVENT_RULE,\n force: true,\n },\n onQuestionAsked: DEFAULT_EVENT_RULE,\n onQuestionRejected: {\n ...DEFAULT_EVENT_RULE,\n force: true,\n },\n },\n runtime: {\n paused: false,\n },\n}\n\nexport function resolvePlanpilotConfigPath(): string {\n const override = process.env.OPENCODE_PLANPILOT_CONFIG\n if (override && override.trim()) {\n const value = override.trim()\n return path.isAbsolute(value) ? value : path.resolve(value)\n }\n return path.join(resolvePlanpilotDir(), \"config.json\")\n}\n\ntype RawKeywordRule = {\n any?: unknown\n all?: unknown\n none?: unknown\n matchCase?: unknown\n}\n\ntype RawEventRule = {\n enabled?: unknown\n force?: unknown\n keywords?: RawKeywordRule\n}\n\ntype RawSessionErrorRule = RawEventRule & {\n errorNames?: unknown\n statusCodes?: unknown\n retryableOnly?: unknown\n}\n\ntype RawSessionRetryRule = RawEventRule & {\n attemptAtLeast?: unknown\n}\n\ntype RawSendRetryConfig = {\n enabled?: unknown\n maxAttempts?: unknown\n delaysMs?: unknown\n}\n\ntype RawAutoContinueConfig = {\n sendRetry?: RawSendRetryConfig\n onSessionError?: RawSessionErrorRule\n onSessionRetry?: RawSessionRetryRule\n onPermissionAsked?: RawEventRule\n onPermissionRejected?: RawEventRule\n onQuestionAsked?: RawEventRule\n onQuestionRejected?: RawEventRule\n}\n\ntype RawRuntimeConfig = {\n paused?: unknown\n}\n\ntype RawPlanpilotConfig = {\n autoContinue?: RawAutoContinueConfig\n runtime?: RawRuntimeConfig\n}\n\nfunction cloneDefaultConfig(): PlanpilotConfig {\n return {\n autoContinue: {\n sendRetry: {\n enabled: DEFAULT_PLANPILOT_CONFIG.autoContinue.sendRetry.enabled,\n maxAttempts: DEFAULT_PLANPILOT_CONFIG.autoContinue.sendRetry.maxAttempts,\n delaysMs: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.sendRetry.delaysMs],\n },\n onSessionError: {\n enabled: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.enabled,\n force: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.force,\n keywords: {\n any: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.keywords.any],\n all: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.keywords.all],\n none: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.keywords.none],\n matchCase: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.keywords.matchCase,\n },\n errorNames: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.errorNames],\n statusCodes: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.statusCodes],\n retryableOnly: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError.retryableOnly,\n },\n onSessionRetry: {\n enabled: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry.enabled,\n force: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry.force,\n keywords: {\n any: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry.keywords.any],\n all: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry.keywords.all],\n none: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry.keywords.none],\n matchCase: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry.keywords.matchCase,\n },\n attemptAtLeast: DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry.attemptAtLeast,\n },\n onPermissionAsked: {\n enabled: DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionAsked.enabled,\n force: DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionAsked.force,\n keywords: {\n any: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionAsked.keywords.any],\n all: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionAsked.keywords.all],\n none: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionAsked.keywords.none],\n matchCase: DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionAsked.keywords.matchCase,\n },\n },\n onPermissionRejected: {\n enabled: DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionRejected.enabled,\n force: DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionRejected.force,\n keywords: {\n any: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionRejected.keywords.any],\n all: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionRejected.keywords.all],\n none: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionRejected.keywords.none],\n matchCase: DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionRejected.keywords.matchCase,\n },\n },\n onQuestionAsked: {\n enabled: DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionAsked.enabled,\n force: DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionAsked.force,\n keywords: {\n any: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionAsked.keywords.any],\n all: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionAsked.keywords.all],\n none: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionAsked.keywords.none],\n matchCase: DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionAsked.keywords.matchCase,\n },\n },\n onQuestionRejected: {\n enabled: DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionRejected.enabled,\n force: DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionRejected.force,\n keywords: {\n any: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionRejected.keywords.any],\n all: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionRejected.keywords.all],\n none: [...DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionRejected.keywords.none],\n matchCase: DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionRejected.keywords.matchCase,\n },\n },\n },\n runtime: {\n paused: DEFAULT_PLANPILOT_CONFIG.runtime.paused,\n },\n }\n}\n\nfunction parseBoolean(value: unknown, fallback: boolean): boolean {\n if (typeof value === \"boolean\") return value\n return fallback\n}\n\nfunction parseStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n const parsed = value\n .filter((item): item is string => typeof item === \"string\")\n .map((item) => item.trim())\n .filter((item) => item.length > 0)\n return Array.from(new Set(parsed))\n}\n\nfunction parseNumberArray(value: unknown): number[] {\n if (!Array.isArray(value)) return []\n const parsed = value\n .map((item) => (typeof item === \"number\" ? item : Number.NaN))\n .filter((item) => Number.isFinite(item))\n .map((item) => Math.trunc(item))\n return Array.from(new Set(parsed))\n}\n\nfunction parsePositiveInt(value: unknown, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback\n const parsed = Math.trunc(value)\n return parsed > 0 ? parsed : fallback\n}\n\nfunction parsePositiveNumberArray(value: unknown, fallback: number[]): number[] {\n if (!Array.isArray(value)) return fallback\n const parsed = value\n .map((item) => (typeof item === \"number\" ? item : Number.NaN))\n .filter((item) => Number.isFinite(item))\n .map((item) => Math.trunc(item))\n .filter((item) => item > 0)\n if (!parsed.length) return fallback\n return Array.from(new Set(parsed))\n}\n\nfunction parseKeywordRule(value: RawKeywordRule | undefined, fallback: KeywordRule): KeywordRule {\n return {\n any: parseStringArray(value?.any),\n all: parseStringArray(value?.all),\n none: parseStringArray(value?.none),\n matchCase: parseBoolean(value?.matchCase, fallback.matchCase),\n }\n}\n\nfunction parseEventRule(value: RawEventRule | undefined, fallback: EventRule): EventRule {\n return {\n enabled: parseBoolean(value?.enabled, fallback.enabled),\n force: parseBoolean(value?.force, fallback.force),\n keywords: parseKeywordRule(value?.keywords, fallback.keywords),\n }\n}\n\nfunction parseSessionErrorRule(value: RawSessionErrorRule | undefined, fallback: SessionErrorRule): SessionErrorRule {\n const base = parseEventRule(value, fallback)\n return {\n ...base,\n errorNames: parseStringArray(value?.errorNames),\n statusCodes: parseNumberArray(value?.statusCodes),\n retryableOnly: parseBoolean(value?.retryableOnly, fallback.retryableOnly),\n }\n}\n\nfunction parseSessionRetryRule(value: RawSessionRetryRule | undefined, fallback: SessionRetryRule): SessionRetryRule {\n const base = parseEventRule(value, fallback)\n const rawAttempt = typeof value?.attemptAtLeast === \"number\" ? Math.trunc(value.attemptAtLeast) : fallback.attemptAtLeast\n return {\n ...base,\n attemptAtLeast: rawAttempt > 0 ? rawAttempt : fallback.attemptAtLeast,\n }\n}\n\nfunction parseSendRetryConfig(value: RawSendRetryConfig | undefined, fallback: SendRetryConfig): SendRetryConfig {\n return {\n enabled: parseBoolean(value?.enabled, fallback.enabled),\n maxAttempts: parsePositiveInt(value?.maxAttempts, fallback.maxAttempts),\n delaysMs: parsePositiveNumberArray(value?.delaysMs, fallback.delaysMs),\n }\n}\n\nfunction parseConfig(raw: RawPlanpilotConfig): PlanpilotConfig {\n return {\n autoContinue: {\n sendRetry: parseSendRetryConfig(raw.autoContinue?.sendRetry, DEFAULT_PLANPILOT_CONFIG.autoContinue.sendRetry),\n onSessionError: parseSessionErrorRule(\n raw.autoContinue?.onSessionError,\n DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionError,\n ),\n onSessionRetry: parseSessionRetryRule(\n raw.autoContinue?.onSessionRetry,\n DEFAULT_PLANPILOT_CONFIG.autoContinue.onSessionRetry,\n ),\n onPermissionAsked: parseEventRule(\n raw.autoContinue?.onPermissionAsked,\n DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionAsked,\n ),\n onPermissionRejected: parseEventRule(\n raw.autoContinue?.onPermissionRejected,\n DEFAULT_PLANPILOT_CONFIG.autoContinue.onPermissionRejected,\n ),\n onQuestionAsked: parseEventRule(\n raw.autoContinue?.onQuestionAsked,\n DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionAsked,\n ),\n onQuestionRejected: parseEventRule(\n raw.autoContinue?.onQuestionRejected,\n DEFAULT_PLANPILOT_CONFIG.autoContinue.onQuestionRejected,\n ),\n },\n runtime: {\n paused: parseBoolean(raw.runtime?.paused, DEFAULT_PLANPILOT_CONFIG.runtime.paused),\n },\n }\n}\n\nexport function normalizePlanpilotConfig(raw: unknown): PlanpilotConfig {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n return cloneDefaultConfig()\n }\n return parseConfig(raw as RawPlanpilotConfig)\n}\n\nexport function savePlanpilotConfig(config: PlanpilotConfig): LoadedPlanpilotConfig {\n const filePath = resolvePlanpilotConfigPath()\n const normalized = normalizePlanpilotConfig(config)\n const parentDir = path.dirname(filePath)\n fs.mkdirSync(parentDir, { recursive: true })\n fs.writeFileSync(filePath, `${JSON.stringify(normalized, null, 2)}\\n`, \"utf8\")\n return {\n path: filePath,\n loadedFromFile: true,\n config: normalized,\n }\n}\n\nexport function loadPlanpilotConfig(): LoadedPlanpilotConfig {\n const filePath = resolvePlanpilotConfigPath()\n try {\n if (!fs.existsSync(filePath)) {\n return {\n path: filePath,\n loadedFromFile: false,\n config: cloneDefaultConfig(),\n }\n }\n const text = fs.readFileSync(filePath, \"utf8\")\n const parsed = JSON.parse(text) as unknown\n return {\n path: filePath,\n loadedFromFile: true,\n config: normalizePlanpilotConfig(parsed),\n }\n } catch (error) {\n const loadError = error instanceof Error ? error.message : String(error)\n return {\n path: filePath,\n loadedFromFile: false,\n config: cloneDefaultConfig(),\n loadError,\n }\n }\n}\n\nexport function matchesKeywords(text: string, rule: KeywordRule): boolean {\n const source = rule.matchCase ? text : text.toLowerCase()\n const normalize = (value: string) => (rule.matchCase ? value : value.toLowerCase())\n const any = rule.any.map(normalize)\n const all = rule.all.map(normalize)\n const none = rule.none.map(normalize)\n\n if (any.length > 0 && !any.some((term) => source.includes(term))) {\n return false\n }\n if (!all.every((term) => source.includes(term))) {\n return false\n }\n if (none.some((term) => source.includes(term))) {\n return false\n }\n return true\n}\n","import fs from \"fs\"\nimport path from \"path\"\nimport os from \"os\"\nimport { Database } from \"bun:sqlite\"\nimport { xdgConfig } from \"xdg-basedir\"\n\nexport type DatabaseConnection = Database\n\nlet cachedDb: Database | null = null\n\nexport function resolveConfigRoot(): string {\n if (process.env.OPENCODE_CONFIG_DIR) {\n return process.env.OPENCODE_CONFIG_DIR\n }\n const base = xdgConfig ?? path.join(os.homedir(), \".config\")\n return path.join(base, \"opencode\")\n}\n\nexport function resolvePlanpilotDir(): string {\n const override = process.env.OPENCODE_PLANPILOT_DIR || process.env.OPENCODE_PLANPILOT_HOME\n if (override && override.trim()) return override\n return path.join(resolveConfigRoot(), \".planpilot\")\n}\n\nexport function resolveDbPath(): string {\n return path.join(resolvePlanpilotDir(), \"planpilot.db\")\n}\n\nexport function resolvePlanMarkdownDir(): string {\n return path.join(resolvePlanpilotDir(), \"plans\")\n}\n\nexport function resolvePlanMarkdownPath(planId: number): string {\n return path.join(resolvePlanMarkdownDir(), `plan_${planId}.md`)\n}\n\nexport function ensureParentDir(filePath: string) {\n const dir = path.dirname(filePath)\n fs.mkdirSync(dir, { recursive: true })\n}\n\nexport function openDatabase(): Database {\n if (cachedDb) return cachedDb\n const dbPath = resolveDbPath()\n ensureParentDir(dbPath)\n const db = new Database(dbPath)\n db.exec(\"PRAGMA foreign_keys = ON;\")\n ensureSchema(db)\n cachedDb = db\n return db\n}\n\nexport function ensureSchema(db: Database) {\n db.exec(`\n CREATE TABLE IF NOT EXISTS plans (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n title TEXT NOT NULL,\n content TEXT NOT NULL,\n status TEXT NOT NULL,\n comment TEXT,\n last_session_id TEXT,\n last_cwd TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS steps (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n plan_id INTEGER NOT NULL,\n content TEXT NOT NULL,\n status TEXT NOT NULL,\n executor TEXT NOT NULL,\n sort_order INTEGER NOT NULL,\n comment TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n FOREIGN KEY(plan_id) REFERENCES plans(id) ON DELETE CASCADE\n );\n CREATE TABLE IF NOT EXISTS goals (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n step_id INTEGER NOT NULL,\n content TEXT NOT NULL,\n status TEXT NOT NULL,\n comment TEXT,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n FOREIGN KEY(step_id) REFERENCES steps(id) ON DELETE CASCADE\n );\n CREATE TABLE IF NOT EXISTS active_plan (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n plan_id INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n UNIQUE(session_id),\n UNIQUE(plan_id),\n FOREIGN KEY(plan_id) REFERENCES plans(id) ON DELETE CASCADE\n );\n CREATE INDEX IF NOT EXISTS idx_steps_plan_order ON steps(plan_id, sort_order);\n CREATE INDEX IF NOT EXISTS idx_goals_step ON goals(step_id);\n `)\n\n const columns = db\n .prepare(\"PRAGMA table_info(plans)\")\n .all()\n .map((row: any) => row.name as string)\n if (!columns.includes(\"last_cwd\")) {\n db.exec(\"ALTER TABLE plans ADD COLUMN last_cwd TEXT\")\n }\n}\n","import { PlanpilotApp } from \"../lib/app\"\nimport { AppError, invalidInput } from \"../lib/errors\"\nimport {\n loadPlanpilotConfig,\n normalizePlanpilotConfig,\n savePlanpilotConfig,\n type PlanpilotConfig,\n} from \"../lib/config\"\nimport { openDatabase } from \"../lib/db\"\nimport { parseWaitFromComment } from \"../lib/util\"\nimport type {\n GoalQuery,\n GoalStatus,\n PlanDetail,\n PlanOrder,\n PlanStatus,\n StepDetail,\n StepExecutor,\n StepOrder,\n StepQuery,\n StepStatus,\n} from \"../lib/models\"\n\ntype JsonPrimitive = string | number | boolean | null\ntype JsonObject = object\ntype JsonValue = JsonPrimitive | JsonObject | JsonValue[]\n\ntype BridgeRequest = {\n action: string\n payload?: unknown\n context?: unknown\n plugin?: unknown\n}\n\ntype BridgeSuccess = {\n ok: true\n data: JsonValue\n}\n\ntype BridgeFailure = {\n ok: false\n error: {\n code: string\n message: string\n details: JsonValue | null\n }\n}\n\ntype BridgeResponse = BridgeSuccess | BridgeFailure\n\ntype BridgeRequestContext = {\n sessionId: string\n cwd?: string\n}\n\ntype ActionHandler = (payload: unknown, context: BridgeRequestContext) => JsonValue\n\nconst DEFAULT_SESSION_ID = \"studio\"\n\nconst PLAN_UPDATE_ALLOWED = new Set([\"title\", \"content\", \"status\", \"comment\"])\nconst STEP_UPDATE_ALLOWED = new Set([\"content\", \"status\", \"executor\", \"comment\"])\nconst GOAL_UPDATE_ALLOWED = new Set([\"content\", \"status\", \"comment\"])\n\nasync function main() {\n const response = await runBridge()\n process.stdout.write(JSON.stringify(response))\n}\n\nasync function runBridge(): Promise<BridgeResponse> {\n try {\n const raw = await readStdinOnce()\n const request = parseRequest(raw)\n const context = resolveRequestContext(request)\n const data = dispatch(request.action, request.payload, context)\n return ok(data)\n } catch (error) {\n return fail(error)\n }\n}\n\nfunction parseRequest(raw: string): BridgeRequest {\n if (!raw.trim()) {\n throw invalidInput(\"bridge request is empty\")\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw invalidInput(`bridge request is not valid JSON: ${message}`)\n }\n\n const root = asObject(parsed, \"bridge request\")\n const action = expectString(root.action, \"action\")\n return {\n action,\n payload: root.payload,\n context: root.context,\n plugin: root.plugin,\n }\n}\n\nfunction resolveRequestContext(request: BridgeRequest): BridgeRequestContext {\n const context = asObjectOptional(request.context)\n const plugin = asObjectOptional(request.plugin)\n const sessionId =\n readNonEmptyString(context?.sessionId) ?? readNonEmptyString(context?.sessionID) ?? DEFAULT_SESSION_ID\n const cwd =\n readNonEmptyString(context?.cwd) ??\n readNonEmptyString(context?.directory) ??\n readNonEmptyString(plugin?.rootPath) ??\n undefined\n return { sessionId, cwd }\n}\n\nfunction createApp(context: BridgeRequestContext): PlanpilotApp {\n return new PlanpilotApp(openDatabase(), context.sessionId, context.cwd)\n}\n\nfunction dispatch(action: string, payload: unknown, context: BridgeRequestContext): JsonValue {\n const handler = ACTIONS[action]\n if (!handler) {\n throw invalidInput(`unknown action: ${action}`)\n }\n return handler(payload, context)\n}\n\nconst ACTIONS: Record<string, ActionHandler> = {\n \"runtime.snapshot\": actionRuntimeSnapshot,\n \"runtime.next\": actionRuntimeNext,\n \"runtime.pause\": actionRuntimePause,\n \"runtime.resume\": actionRuntimeResume,\n \"events.poll\": actionEventsPoll,\n \"config.get\": actionConfigGet,\n \"config.set\": actionConfigSet,\n \"plan.list\": actionPlanList,\n \"plan.get\": actionPlanGet,\n \"plan.createTree\": actionPlanAddTree,\n \"plan.addTree\": actionPlanAddTree,\n \"plan.update\": actionPlanUpdate,\n \"plan.done\": actionPlanDone,\n \"plan.remove\": actionPlanRemove,\n \"plan.activate\": actionPlanActivate,\n \"plan.deactivate\": actionPlanDeactivate,\n \"plan.active\": actionPlanActive,\n \"step.list\": actionStepList,\n \"step.get\": actionStepGet,\n \"step.add\": actionStepAdd,\n \"step.addTree\": actionStepAddTree,\n \"step.update\": actionStepUpdate,\n \"step.done\": actionStepDone,\n \"step.remove\": actionStepRemove,\n \"step.move\": actionStepMove,\n \"step.wait\": actionStepWait,\n \"goal.list\": actionGoalList,\n \"goal.get\": actionGoalGet,\n \"goal.add\": actionGoalAdd,\n \"goal.update\": actionGoalUpdate,\n \"goal.done\": actionGoalDone,\n \"goal.remove\": actionGoalRemove,\n}\n\nfunction actionRuntimeSnapshot(_payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n return buildRuntimeSnapshot(app, loadPlanpilotConfig().config)\n}\n\nfunction actionRuntimeNext(_payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const active = app.getActivePlan()\n if (!active) {\n return {\n activePlan: null,\n nextStep: null,\n cursor: buildRuntimeCursor(app, loadPlanpilotConfig().config),\n }\n }\n\n const nextStep = app.nextStep(active.plan_id)\n return {\n activePlan: active,\n nextStep: nextStep ? serializeStepDetail(app.getStepDetail(nextStep.id)) : null,\n cursor: buildRuntimeCursor(app, loadPlanpilotConfig().config),\n }\n}\n\nfunction actionRuntimePause(_payload: unknown, context: BridgeRequestContext): JsonValue {\n const loaded = loadPlanpilotConfig()\n const config = normalizePlanpilotConfig(loaded.config)\n config.runtime.paused = true\n savePlanpilotConfig(config)\n const app = createApp(context)\n return buildRuntimeSnapshot(app, config)\n}\n\nfunction actionRuntimeResume(_payload: unknown, context: BridgeRequestContext): JsonValue {\n const loaded = loadPlanpilotConfig()\n const config = normalizePlanpilotConfig(loaded.config)\n config.runtime.paused = false\n savePlanpilotConfig(config)\n const app = createApp(context)\n return buildRuntimeSnapshot(app, config)\n}\n\nfunction actionEventsPoll(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const config = loadPlanpilotConfig().config\n const currentCursor = buildRuntimeCursor(app, config)\n\n const input = asObjectOptional(payload)\n const previousCursor = readNonEmptyString(input?.cursor) ?? \"\"\n if (previousCursor === currentCursor) {\n return {\n cursor: currentCursor,\n events: [],\n }\n }\n\n return {\n cursor: currentCursor,\n events: [\n {\n event: \"planpilot.runtime.changed\",\n id: currentCursor,\n data: buildRuntimeSnapshot(app, config),\n },\n ],\n }\n}\n\nfunction actionConfigGet(_payload: unknown, _context: BridgeRequestContext): JsonValue {\n const loaded = loadPlanpilotConfig()\n return loaded.config as unknown as JsonValue\n}\n\nfunction actionConfigSet(payload: unknown, _context: BridgeRequestContext): JsonValue {\n const root = asObject(payload, \"config.set payload\")\n const raw = \"config\" in root ? root.config : payload\n const normalized = normalizePlanpilotConfig(raw)\n const saved = savePlanpilotConfig(normalized)\n return {\n path: saved.path,\n config: saved.config as unknown as JsonValue,\n }\n}\n\nfunction actionPlanList(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObjectOptional(payload)\n const order = parsePlanOrderOptional(input?.order)\n const desc = readBoolean(input?.desc) ?? true\n const plans = app.listPlans(order, desc)\n return plans as unknown as JsonValue\n}\n\nfunction actionPlanGet(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"plan.get payload\")\n const id = expectInt(input.id, \"id\")\n return serializePlanDetail(app.getPlanDetail(id))\n}\n\nfunction actionPlanAddTree(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"plan.createTree payload\")\n const title = expectString(input.title, \"title\")\n const content = expectString(input.content, \"content\")\n const stepsInput = expectArray(input.steps, \"steps\")\n const steps = stepsInput.map((item, index) => {\n const step = asObject(item, `steps[${index}]`)\n return {\n content: expectString(step.content, `steps[${index}].content`),\n executor: parseExecutorOptional(step.executor) ?? \"ai\",\n goals: readStringArray(step.goals),\n }\n })\n\n const result = app.addPlanTree({ title, content }, steps)\n return {\n plan: result.plan,\n stepCount: result.stepCount,\n goalCount: result.goalCount,\n detail: serializePlanDetail(app.getPlanDetail(result.plan.id)),\n }\n}\n\nfunction actionPlanUpdate(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"plan.update payload\")\n const id = expectInt(input.id, \"id\")\n assertAllowedKeys(input, PLAN_UPDATE_ALLOWED, \"plan.update\")\n const result = app.updatePlanWithActiveClear(id, {\n title: readString(input.title),\n content: readString(input.content),\n status: parsePlanStatusOptional(input.status),\n comment: readNullableString(input.comment),\n })\n return {\n plan: result.plan,\n cleared: result.cleared,\n }\n}\n\nfunction actionPlanDone(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"plan.done payload\")\n const id = expectInt(input.id, \"id\")\n return app.updatePlanWithActiveClear(id, { status: \"done\" }) as unknown as JsonValue\n}\n\nfunction actionPlanRemove(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"plan.remove payload\")\n const id = expectInt(input.id, \"id\")\n app.deletePlan(id)\n return { removed: id }\n}\n\nfunction actionPlanActivate(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"plan.activate payload\")\n const id = expectInt(input.id, \"id\")\n const force = readBoolean(input.force) ?? false\n const plan = app.getPlan(id)\n if (plan.status === \"done\") {\n throw invalidInput(\"cannot activate plan; plan is done\")\n }\n return app.setActivePlan(id, force) as unknown as JsonValue\n}\n\nfunction actionPlanDeactivate(_payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const active = app.getActivePlan()\n app.clearActivePlan()\n return {\n activePlan: active,\n deactivated: true,\n }\n}\n\nfunction actionPlanActive(_payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const active = app.getActivePlan()\n if (!active) {\n return { activePlan: null, detail: null }\n }\n return {\n activePlan: active,\n detail: serializePlanDetail(app.getPlanDetail(active.plan_id)),\n }\n}\n\nfunction actionStepList(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.list payload\")\n const planId = expectInt(input.planId, \"planId\")\n const query: StepQuery = {\n status: parseStepStatusOptional(input.status),\n executor: parseExecutorOptional(input.executor),\n limit: parseIntOptional(input.limit),\n offset: parseIntOptional(input.offset),\n order: parseStepOrderOptional(input.order),\n desc: readBoolean(input.desc),\n }\n const steps = app.listStepsFiltered(planId, query)\n return steps as unknown as JsonValue\n}\n\nfunction actionStepGet(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.get payload\")\n const id = expectInt(input.id, \"id\")\n return serializeStepDetail(app.getStepDetail(id))\n}\n\nfunction actionStepAdd(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.add payload\")\n const planId = expectInt(input.planId, \"planId\")\n const contents = resolveContents(input, \"content\", \"contents\")\n const executor = parseExecutorOptional(input.executor) ?? \"ai\"\n const at = parseIntOptional(input.at)\n const result = app.addStepsBatch(planId, contents, \"todo\", executor, at)\n return {\n steps: result.steps,\n changes: result.changes,\n }\n}\n\nfunction actionStepAddTree(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.addTree payload\")\n const planId = expectInt(input.planId, \"planId\")\n const content = expectString(input.content, \"content\")\n const executor = parseExecutorOptional(input.executor) ?? \"ai\"\n const goals = readStringArray(input.goals)\n return app.addStepTree(planId, content, executor, goals) as unknown as JsonValue\n}\n\nfunction actionStepUpdate(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.update payload\")\n const id = expectInt(input.id, \"id\")\n assertAllowedKeys(input, STEP_UPDATE_ALLOWED, \"step.update\")\n return app.updateStep(id, {\n content: readString(input.content),\n status: parseStepStatusOptional(input.status),\n executor: parseExecutorOptional(input.executor),\n comment: readNullableString(input.comment),\n }) as unknown as JsonValue\n}\n\nfunction actionStepDone(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.done payload\")\n const id = expectInt(input.id, \"id\")\n const allGoals = readBoolean(input.allGoals) ?? false\n return app.setStepDoneWithGoals(id, allGoals) as unknown as JsonValue\n}\n\nfunction actionStepRemove(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.remove payload\")\n const ids = resolveIds(input)\n return app.deleteSteps(ids) as unknown as JsonValue\n}\n\nfunction actionStepMove(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.move payload\")\n const id = expectInt(input.id, \"id\")\n const to = expectInt(input.to, \"to\")\n return app.moveStep(id, to) as unknown as JsonValue\n}\n\nfunction actionStepWait(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"step.wait payload\")\n const id = expectInt(input.id, \"id\")\n const clear = readBoolean(input.clear) ?? false\n if (clear) {\n return app.clearStepWait(id) as unknown as JsonValue\n }\n\n const delayMs = expectInt(input.delayMs, \"delayMs\")\n const reason = readString(input.reason)\n return app.setStepWait(id, delayMs, reason) as unknown as JsonValue\n}\n\nfunction actionGoalList(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"goal.list payload\")\n const stepId = expectInt(input.stepId, \"stepId\")\n const query: GoalQuery = {\n status: parseGoalStatusOptional(input.status),\n limit: parseIntOptional(input.limit),\n offset: parseIntOptional(input.offset),\n }\n return app.listGoalsFiltered(stepId, query) as unknown as JsonValue\n}\n\nfunction actionGoalGet(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"goal.get payload\")\n const id = expectInt(input.id, \"id\")\n return app.getGoalDetail(id) as unknown as JsonValue\n}\n\nfunction actionGoalAdd(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"goal.add payload\")\n const stepId = expectInt(input.stepId, \"stepId\")\n const contents = resolveContents(input, \"content\", \"contents\")\n return app.addGoalsBatch(stepId, contents, \"todo\") as unknown as JsonValue\n}\n\nfunction actionGoalUpdate(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"goal.update payload\")\n const id = expectInt(input.id, \"id\")\n assertAllowedKeys(input, GOAL_UPDATE_ALLOWED, \"goal.update\")\n return app.updateGoal(id, {\n content: readString(input.content),\n status: parseGoalStatusOptional(input.status),\n comment: readNullableString(input.comment),\n }) as unknown as JsonValue\n}\n\nfunction actionGoalDone(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"goal.done payload\")\n const ids = resolveIds(input)\n if (ids.length === 1) {\n return app.setGoalStatus(ids[0], \"done\") as unknown as JsonValue\n }\n return app.setGoalsStatus(ids, \"done\") as unknown as JsonValue\n}\n\nfunction actionGoalRemove(payload: unknown, context: BridgeRequestContext): JsonValue {\n const app = createApp(context)\n const input = asObject(payload, \"goal.remove payload\")\n const ids = resolveIds(input)\n return app.deleteGoals(ids) as unknown as JsonValue\n}\n\nfunction resolveContents(input: Record<string, unknown>, contentKey: string, contentsKey: string): string[] {\n const content = readString(input[contentKey])\n const contents = readStringArray(input[contentsKey])\n const out = content ? [content, ...contents] : contents\n if (!out.length) {\n throw invalidInput(`expected ${contentKey} or ${contentsKey}`)\n }\n return out\n}\n\nfunction resolveIds(input: Record<string, unknown>): number[] {\n const fromSingle = parseIntOptional(input.id)\n const fromMany = readIntArray(input.ids)\n const ids = fromSingle !== undefined ? [fromSingle, ...fromMany] : fromMany\n if (!ids.length) {\n throw invalidInput(\"expected id or ids\")\n }\n return Array.from(new Set(ids))\n}\n\nfunction parsePlanOrderOptional(value: unknown): PlanOrder | undefined {\n const raw = readString(value)\n if (!raw) return undefined\n if (raw === \"id\" || raw === \"title\" || raw === \"created\" || raw === \"updated\") return raw\n throw invalidInput(`invalid plan order '${raw}', expected id|title|created|updated`)\n}\n\nfunction parseStepOrderOptional(value: unknown): StepOrder | undefined {\n const raw = readString(value)\n if (!raw) return undefined\n if (raw === \"order\" || raw === \"id\" || raw === \"created\" || raw === \"updated\") return raw\n throw invalidInput(`invalid step order '${raw}', expected order|id|created|updated`)\n}\n\nfunction parsePlanStatusOptional(value: unknown): PlanStatus | undefined {\n const raw = readString(value)\n if (!raw) return undefined\n if (raw === \"todo\" || raw === \"done\") return raw\n throw invalidInput(`invalid plan status '${raw}', expected todo|done`)\n}\n\nfunction parseStepStatusOptional(value: unknown): StepStatus | undefined {\n const raw = parsePlanStatusOptional(value)\n return raw as StepStatus | undefined\n}\n\nfunction parseGoalStatusOptional(value: unknown): GoalStatus | undefined {\n const raw = parsePlanStatusOptional(value)\n return raw as GoalStatus | undefined\n}\n\nfunction parseExecutorOptional(value: unknown): StepExecutor | undefined {\n const raw = readString(value)\n if (!raw) return undefined\n if (raw === \"ai\" || raw === \"human\") return raw\n throw invalidInput(`invalid executor '${raw}', expected ai|human`)\n}\n\nfunction assertAllowedKeys(input: Record<string, unknown>, allowed: Set<string>, action: string) {\n for (const key of Object.keys(input)) {\n if (key === \"id\") continue\n if (!allowed.has(key)) {\n throw invalidInput(`${action} does not support '${key}'`)\n }\n }\n}\n\nfunction buildRuntimeSnapshot(app: PlanpilotApp, config: PlanpilotConfig): JsonValue {\n const active = app.getActivePlan()\n const next = active ? app.nextStep(active.plan_id) : null\n return {\n paused: config.runtime.paused,\n activePlan: active,\n nextStep: next ? serializeStepDetail(app.getStepDetail(next.id)) : null,\n cursor: buildRuntimeCursor(app, config),\n }\n}\n\nfunction buildRuntimeCursor(app: PlanpilotApp, config: PlanpilotConfig): string {\n const plans = app.listPlans(\"updated\", true)\n const latestPlanUpdated = plans.length ? plans[0].updated_at : 0\n const active = app.getActivePlan()\n const activeUpdated = active?.updated_at ?? 0\n const activePlanId = active?.plan_id ?? 0\n const next = active ? app.nextStep(active.plan_id) : null\n const nextStepId = next?.id ?? 0\n const paused = config.runtime.paused ? 1 : 0\n return [paused, latestPlanUpdated, activeUpdated, activePlanId, nextStepId].join(\":\")\n}\n\nfunction serializePlanDetail(detail: PlanDetail): JsonValue {\n const goals = detail.steps.map((step) => ({\n stepId: step.id,\n goals: detail.goals.get(step.id) ?? [],\n }))\n return {\n plan: detail.plan,\n steps: detail.steps,\n goals,\n }\n}\n\nfunction serializeStepDetail(detail: StepDetail): JsonValue {\n const wait = parseWaitFromComment(detail.step.comment)\n return {\n step: detail.step,\n goals: detail.goals,\n wait,\n }\n}\n\nfunction ok(data: JsonValue): BridgeSuccess {\n return { ok: true, data }\n}\n\nfunction fail(error: unknown): BridgeFailure {\n if (error instanceof AppError) {\n const code =\n error.kind === \"InvalidInput\"\n ? \"invalid_input\"\n : error.kind === \"NotFound\"\n ? \"not_found\"\n : error.kind === \"Db\"\n ? \"db_error\"\n : error.kind === \"Io\"\n ? \"io_error\"\n : \"json_error\"\n return {\n ok: false,\n error: {\n code,\n message: error.toDisplayString(),\n details: null,\n },\n }\n }\n\n const message = error instanceof Error ? error.message : String(error)\n return {\n ok: false,\n error: {\n code: \"internal_error\",\n message,\n details: null,\n },\n }\n}\n\nfunction asObject(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw invalidInput(`${label} must be an object`)\n }\n return value as Record<string, unknown>\n}\n\nfunction asObjectOptional(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined\n }\n return value as Record<string, unknown>\n}\n\nfunction expectString(value: unknown, label: string): string {\n const parsed = readString(value)\n if (!parsed) {\n throw invalidInput(`${label} is required`)\n }\n return parsed\n}\n\nfunction readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined\n const trimmed = value.trim()\n return trimmed.length ? trimmed : undefined\n}\n\nfunction readNullableString(value: unknown): string | undefined {\n if (value === null || value === undefined) return undefined\n return readString(value)\n}\n\nfunction readNonEmptyString(value: unknown): string | undefined {\n return readString(value)\n}\n\nfunction readBoolean(value: unknown): boolean | undefined {\n return typeof value === \"boolean\" ? value : undefined\n}\n\nfunction expectInt(value: unknown, label: string): number {\n const parsed = parseIntOptional(value)\n if (parsed === undefined) {\n throw invalidInput(`${label} must be an integer`)\n }\n return parsed\n}\n\nfunction parseIntOptional(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value) || !Number.isInteger(value)) {\n return undefined\n }\n return value\n}\n\nfunction readStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n const out: string[] = []\n for (const item of value) {\n const text = readString(item)\n if (text) out.push(text)\n }\n return out\n}\n\nfunction readIntArray(value: unknown): number[] {\n if (!Array.isArray(value)) return []\n const out: number[] = []\n for (const item of value) {\n const id = parseIntOptional(item)\n if (id !== undefined) out.push(id)\n }\n return out\n}\n\nfunction expectArray(value: unknown, label: string): unknown[] {\n if (!Array.isArray(value)) {\n throw invalidInput(`${label} must be an array`)\n }\n return value\n}\n\nasync function readStdinOnce(): Promise<string> {\n const chunks: Buffer[] = []\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n }\n return Buffer.concat(chunks).toString(\"utf8\")\n}\n\nvoid main()\n"],"mappings":"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","names":["fs","path","path","fs"]}
@@ -0,0 +1,33 @@
1
+ type JsonPrimitive = string | number | boolean | null;
2
+ type JsonObject = {
3
+ [k: string]: JsonValue;
4
+ };
5
+ type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
6
+ type HostApi = {
7
+ invokeAction: (action: string, payload?: JsonValue, context?: JsonValue) => Promise<JsonValue>;
8
+ subscribeEvents: (handlers: {
9
+ onEvent?: (evt: {
10
+ type: string;
11
+ data: JsonValue;
12
+ lastEventId?: string;
13
+ }) => void;
14
+ onError?: (err: Event) => void;
15
+ }) => () => void;
16
+ };
17
+ type LayoutApi = {
18
+ setReservePx: (px: number) => void;
19
+ };
20
+ type StudioMountOptions = {
21
+ pluginId: string;
22
+ surface: string;
23
+ title?: string;
24
+ context: Record<string, string>;
25
+ host: HostApi;
26
+ layout?: LayoutApi;
27
+ close?: () => void;
28
+ };
29
+ declare function mount(el: HTMLElement, opts: StudioMountOptions): {
30
+ unmount(): void;
31
+ };
32
+
33
+ export { type StudioMountOptions, mount };