@ordewell/core 0.4.15 → 0.4.17
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.
- package/dist/{ITerminalRunner-DqAs12sy.d.ts → ITerminalRunner-CbLHKXT5.d.ts} +1 -1
- package/dist/{ITerminalRunner-D_RBDoHa.d.mts → ITerminalRunner-E3-6QNUS.d.mts} +1 -1
- package/dist/{ModeResolver-CzZd-i6T.d.ts → ModeResolver-Ob-ihQbI.d.ts} +1 -1
- package/dist/{ModeResolver-CCKYqdZC.d.mts → ModeResolver-mtIWrLXn.d.mts} +1 -1
- package/dist/{Task-cGrfYRXK.d.mts → Task-4rDGr8Su.d.mts} +1 -1
- package/dist/{Task-cGrfYRXK.d.ts → Task-4rDGr8Su.d.ts} +1 -1
- package/dist/{chunk-YTJ7EOV6.mjs → chunk-DV3YIKRA.mjs} +2 -2
- package/dist/{chunk-YTJ7EOV6.mjs.map → chunk-DV3YIKRA.mjs.map} +1 -1
- package/dist/{chunk-UEJ3SZQ7.mjs → chunk-QJ63PD5K.mjs} +2 -2
- package/dist/{chunk-N6HTBUKG.mjs → chunk-T4KGVP4N.mjs} +1 -1
- package/dist/chunk-T4KGVP4N.mjs.map +1 -0
- package/dist/index.d.mts +38 -20
- package/dist/index.d.ts +38 -20
- package/dist/index.js +44 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -24
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +1 -1
- package/dist/order-labels.d.ts +1 -1
- package/dist/{parsing-D87zKtTe.d.ts → parsing-BJoHbA-t.d.ts} +2 -2
- package/dist/{parsing-BT-dvFcu.d.mts → parsing-BWfpLch9.d.mts} +2 -2
- package/dist/parsing.d.mts +3 -3
- package/dist/parsing.d.ts +3 -3
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +2 -2
- package/dist/{plan-utils-BbC9KdK4.d.ts → plan-utils-DJm2a7Zp.d.ts} +4 -2
- package/dist/{plan-utils-DHBIvkiT.d.mts → plan-utils-s6VL8NDF.d.mts} +4 -2
- package/dist/plan-utils.d.mts +3 -3
- package/dist/plan-utils.d.ts +3 -3
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +2 -2
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/package.json +1 -1
- package/skills/improve-codebase-architecture/SKILL.md +59 -0
- package/dist/chunk-N6HTBUKG.mjs.map +0 -1
- /package/dist/{chunk-UEJ3SZQ7.mjs.map → chunk-QJ63PD5K.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/models/Task.ts","../src/services/JsonExtractor.ts"],"sourcesContent":["import { v4 as uuidv4 } from 'uuid';\n\nexport interface UserStep {\n order: number;\n instruction: string;\n completed: boolean;\n}\n\n/** One deterministic signal gathered while verifying a completed task. */\nexport interface VerificationCheck {\n name: 'exit_code' | 'completion_marker' | 'manual';\n passed: boolean;\n /** A check that did not apply. Skipped checks don't affect the verdict. */\n skipped: boolean;\n detail: string;\n}\n\n/** Evidence-based verdict for a completed task. Single end-to-end outcome produced by verification. */\nexport interface Verdict {\n outcome: 'pass' | 'fail';\n reason: string;\n checks: VerificationCheck[];\n decidedAt: string;\n}\n\nexport interface TaskOutputSummary {\n reviewReason: string;\n logTail: string;\n capturedAt: string;\n}\n\nexport type TaskType = 'ai' | 'user';\nexport type TaskStatus = 'pending' | 'approved' | 'in_progress' | 'completed' | 'failed' | 'blocked' | 'awaiting_user';\nexport type TaskMode = string;\n\nexport interface TaskModelAssignment {\n modelId: string;\n modelLabel: string;\n thinkingEffort?: string;\n /**\n * All variant ids the model offered when this assignment was made. Carried\n * on the assignment because runners need it at spawn time (opencode's TUI\n * only honors an assigned variant when the others are config-disabled) and\n * the discovery catalog isn't available there.\n */\n availableVariants?: string[];\n}\n\nexport type RunnerId = string;\n\nexport interface Task {\n id: string;\n order: number;\n title: string;\n description: string;\n type: TaskType;\n status: TaskStatus;\n dependencies: string[];\n prompt?: string;\n userSteps?: UserStep[];\n subtasks: Task[];\n verdict?: Verdict;\n outputSummary?: TaskOutputSummary;\n assignedModel?: TaskModelAssignment;\n assignedRunner: RunnerId;\n thinkingEffort?: string;\n taskMode?: TaskMode;\n completionMarker: string;\n autonomy?: 'AFK' | 'HITL';\n sliceType?: 'HITL' | 'AFK';\n userStoriesCovered?: string[];\n}\n\nexport interface DiscoveredMode {\n id: string;\n label: string;\n description: string;\n}\n\nexport type ResearchToolType =\n | 'read_file' | 'read_files' | 'glob' | 'grep' | 'find_symbol' | 'list_dir'\n | 'bash' | 'fetch' | 'web_search' | 'spawn_research_agent'\n /**\n * A tool belonging to a harness planner's own toolbox (ADR-0009) that has no\n * Ordewell equivalent — Edit, WebFetch, TodoWrite, whatever a coding agent\n * ships next. The real name travels in `toolLabel` rather than being\n * relabelled as a tool it is not; the union stays closed so the\n * exhaustiveness checks in every surface's icon/label switch survive.\n */\n | 'agent_tool';\n\n/**\n * What happened when a research tool call ran, for honest per-surface\n * rendering. The broadcast seam carries this on every `research_step_done` so\n * surfaces do not have to pattern-match refusal text to tell a refused `rm`\n * from a successful `rm` — the old render path flipped a `✓` for both.\n */\nexport type ResearchStepOutcome = 'success' | 'failure' | 'refused' | 'denied' | 'not_executed';\n\nexport interface ResearchStep {\n id: string;\n tool: ResearchToolType;\n /** The tool's own name when it came from a harness planner — always set for `agent_tool`. */\n toolLabel?: string;\n args: string;\n result: string;\n success: boolean;\n outcome: ResearchStepOutcome;\n /** The model's tool_call id, so a surface can match `tool_result` to the\n * pending `tool_call` it announced — robust under parallel same-tool rounds. */\n toolCallId?: string;\n timestamp: string;\n thinkingText?: string;\n}\n\nexport interface UserPromptEntry {\n id: string;\n type: 'user_prompt' | 'system';\n content: string;\n timestamp: string;\n}\n\nexport type ResearchLogEntry = ResearchStep | UserPromptEntry;\n\nexport interface ResearchProgress {\n // 'liveness' carries no content: a raw-line signal from the harness process\n // (ADR-0009) that reaches a surface even when a turn is producing nothing\n // visible — a subagent's filtered chatter, most often — so an idle watchdog\n // downstream doesn't mistake \"nothing to show\" for \"nothing happening\".\n type: 'thinking' | 'tool_call' | 'tool_result' | 'plan_token' | 'interrupted' | 'liveness';\n text?: string;\n tool?: string;\n /** Harness planners (ADR-0009): the agent's own name for a tool Ordewell has no member for. */\n toolLabel?: string;\n toolArgs?: string;\n toolResult?: string;\n planToken?: string;\n step?: ResearchStep;\n /** The model's tool_call id, threaded on tool_call and tool_result so a\n * surface can match the result to its pending call — robust under parallel\n * same-tool rounds where LIFO-by-name matching mislabels summaries. */\n toolCallId?: string;\n /** Present when this event originates from (or reports on) one spawned research subagent (issue #34). */\n subagentId?: string;\n}\n\nexport interface ThinkingBlock {\n id: string;\n text: string;\n}\n\nexport interface StreamThinkingEvent {\n type: 'thinking';\n block: ThinkingBlock;\n}\n\nexport interface StreamStepEvent {\n type: 'step';\n step: ResearchStep;\n}\n\nexport type StreamEvent = StreamThinkingEvent | StreamStepEvent;\n\nexport interface DiscoveredModel {\n modelId: string;\n modelLabel: string;\n runnerProvider?: string;\n /**\n * Human-facing provider name as the runner itself reports it (e.g.\n * \"OpenCode Zen\" for `runnerProvider: 'opencode'`). Populated from the\n * runner's own provider catalog when available; when absent the UI derives a\n * label from `runnerProvider` by title-casing.\n */\n runnerProviderLabel?: string;\n /**\n * The runner whose catalog listed this model. Stamped once, at the single\n * `ModelDiscovery.discover` choke point, so a flat cross-runner list can\n * still say where each entry came from — `runnerProvider` alone cannot:\n * OpenCode reports most of its catalog as `openrouter`, which names the\n * serving backend, not the agent Ordewell would spawn.\n */\n runnerId?: string;\n /** The runner's display name (`OpenCode`), from its manifest. */\n runnerLabel?: string;\n variants: { id: string; label: string }[];\n}\n\nexport type PlanStatus = 'draft' | 'approved' | 'rejected' | 'running' | 'completed';\n\n/**\n * One entry of the planner's persisted dialogue (ADR-0002). The single source\n * of truth for both UI redisplay and conversational context. Tool-call results\n * are NOT stored here — they live in the AI service's tool-use history;\n * `researchLog` remains the persisted tool trace for the UI.\n */\nexport interface ConversationMessage {\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n /**\n * Timeline marker: 'plan_generated' records the point in the dialogue where\n * the plan was committed (the UI anchors the plan card there on restore);\n * 'system' is a host-injected notice. Absent for ordinary chat turns, so\n * sessions saved before markers existed degrade gracefully.\n */\n kind?: 'plan_generated' | 'system';\n}\n\nexport interface QueuedMessage {\n id: string;\n text: string;\n timestamp: string;\n}\n\nexport interface PlanModificationWarnings {\n deletedCompleted: string[];\n changedCompleted: string[];\n deletedInProgress: string[];\n modifiedInProgress: string[];\n brokenDependencies: string[];\n}\n\nexport function emptyWarnings(): PlanModificationWarnings {\n return { deletedCompleted: [], changedCompleted: [], deletedInProgress: [], modifiedInProgress: [], brokenDependencies: [] };\n}\n\nexport interface LegacyPlanState {\n tasks: Task[];\n generatedAt: string;\n status: PlanStatus;\n runners: RunnerId[];\n lastUpdated: string;\n researchLog?: ResearchLogEntry[];\n /** The planner dialogue — user messages and assistant messages, in order (ADR-0002). */\n conversationHistory?: ConversationMessage[];\n /** Full markdown PRD once written by the planner (PRD mode), also saved to .scratch/<slug>/PRD.md. */\n prdMarkdown?: string;\n /** Follow-ups queued while tasks execute — applied as plan modifications between batches. */\n queuedMessages?: QueuedMessage[];\n}\n\nexport interface Message {\n id: string;\n role: 'user' | 'planner' | 'system';\n content: string;\n timestamp: number;\n}\n\nexport interface TaskSnapshot extends Task {\n completedAt: number;\n verdict?: Verdict;\n retryCount: number;\n finalized: boolean;\n}\n\nexport type PlanState =\n | {\n phase: 'planning';\n history: Message[];\n message: string;\n pendingTasks: Task[];\n }\n | {\n phase: 'executing';\n history: Message[];\n message: string;\n executionLog: TaskSnapshot[];\n pendingTasks: Task[];\n goal: string;\n runners: string[];\n status: PlanStatus;\n };\n\nfunction hasPhase(raw: unknown): raw is PlanState {\n return typeof raw === 'object' && raw !== null && 'phase' in raw;\n}\n\nfunction hasTasks(raw: unknown): raw is LegacyPlanState {\n return typeof raw === 'object' && raw !== null && 'tasks' in raw && Array.isArray((raw as Record<string, unknown>).tasks);\n}\n\nfunction migrateHistory(raw: LegacyPlanState): Message[] {\n const messages: Message[] = [];\n\n if (raw.researchLog) {\n for (const entry of raw.researchLog) {\n if ('type' in entry && entry.type === 'user_prompt') {\n messages.push({\n id: entry.id,\n role: 'user',\n content: (entry as UserPromptEntry).content,\n timestamp: new Date(entry.timestamp).getTime(),\n });\n } else {\n const step = entry as ResearchStep;\n messages.push({\n id: step.id,\n role: 'system',\n content: JSON.stringify({ tool: step.tool, args: step.args, result: step.result }),\n timestamp: new Date(step.timestamp).getTime(),\n });\n }\n }\n }\n\n if (raw.queuedMessages) {\n for (const qm of raw.queuedMessages) {\n messages.push({\n id: qm.id,\n role: 'system',\n content: qm.text,\n timestamp: new Date(qm.timestamp).getTime(),\n });\n }\n }\n\n return messages;\n}\n\nexport function migratePlanState(raw: unknown): PlanState {\n if (hasPhase(raw)) return raw;\n\n if (!hasTasks(raw)) {\n return {\n phase: 'planning',\n history: [],\n message: '',\n pendingTasks: [],\n };\n }\n\n const hasExecution = raw.tasks.some(\n (t) => t.status === 'completed' || t.status === 'failed',\n );\n\n const messages = migrateHistory(raw);\n\n if (hasExecution) {\n const executionLog: TaskSnapshot[] = raw.tasks\n .filter((t) => t.status === 'completed' || t.status === 'failed')\n .map((t) => ({\n ...t,\n completedAt: new Date(raw.lastUpdated).getTime(),\n verdict: t.verdict,\n retryCount: 0,\n finalized: true,\n }));\n\n const pendingTasks = raw.tasks.filter(\n (t) => t.status !== 'completed' && t.status !== 'failed' && t.status !== 'blocked',\n );\n\n return {\n phase: 'executing',\n history: messages,\n message: '',\n executionLog,\n pendingTasks,\n goal: '',\n runners: raw.runners,\n status: raw.status,\n };\n }\n\n return {\n phase: 'planning',\n history: messages,\n message: '',\n pendingTasks: raw.tasks,\n };\n}\n\nexport function migrateLegacyPlan(legacy: LegacyPlanState): PlanState {\n const messages: Message[] = [];\n\n if (legacy.researchLog) {\n for (const entry of legacy.researchLog) {\n if ('type' in entry && entry.type === 'user_prompt') {\n messages.push({\n id: entry.id,\n role: 'user',\n content: (entry as UserPromptEntry).content,\n timestamp: new Date(entry.timestamp).getTime(),\n });\n } else {\n const step = entry as ResearchStep;\n messages.push({\n id: step.id,\n role: 'system',\n content: JSON.stringify({ tool: step.tool, args: step.args, result: step.result }),\n timestamp: new Date(step.timestamp).getTime(),\n });\n }\n }\n }\n\n if (legacy.queuedMessages) {\n for (const qm of legacy.queuedMessages) {\n messages.push({\n id: qm.id,\n role: 'system',\n content: qm.text,\n timestamp: new Date(qm.timestamp).getTime(),\n });\n }\n }\n\n const isPlanning = legacy.status === 'draft' || legacy.status === 'approved' || legacy.status === 'rejected';\n\n if (isPlanning) {\n return {\n phase: 'planning',\n history: messages,\n message: 'Plan generation',\n pendingTasks: legacy.tasks.filter((t) => t.status === 'pending' || t.status === ('draft' as never)),\n };\n }\n\n const nonCompletedTasks = legacy.tasks.filter(\n (t) => t.status !== 'completed' && t.status !== 'failed' && t.status !== 'blocked'\n );\n\n const completedSnapshot: TaskSnapshot[] = legacy.tasks\n .filter((t) => t.status === 'completed' || t.status === 'failed')\n .map((t) => ({\n ...t,\n completedAt: new Date(legacy.lastUpdated).getTime(),\n verdict: t.verdict,\n retryCount: 0,\n finalized: true,\n }));\n\n return {\n phase: 'executing',\n history: messages,\n message: 'Plan migration',\n executionLog: completedSnapshot,\n pendingTasks: nonCompletedTasks,\n goal: 'Plan migration',\n runners: legacy.runners,\n status: legacy.status,\n };\n}\n\nexport { taskOrderLabel, resolveOrderLabel } from '../order-labels';\n\nexport function createTask(overrides: Partial<Task> = {}): Task {\n return {\n id: overrides.id ?? uuidv4(),\n order: overrides.order ?? 0,\n title: overrides.title ?? '',\n description: overrides.description ?? '',\n type: overrides.type ?? 'ai',\n status: overrides.status ?? 'pending',\n dependencies: overrides.dependencies ?? [],\n prompt: overrides.prompt,\n userSteps: overrides.userSteps,\n subtasks: overrides.subtasks ?? [],\n verdict: overrides.verdict,\n outputSummary: overrides.outputSummary,\n assignedModel: overrides.assignedModel,\n assignedRunner: overrides.assignedRunner ?? 'claude-code',\n thinkingEffort: overrides.thinkingEffort,\n taskMode: overrides.taskMode ?? 'build',\n completionMarker: overrides.completionMarker ?? uuidv4(),\n autonomy: overrides.autonomy,\n sliceType: overrides.sliceType,\n userStoriesCovered: overrides.userStoriesCovered,\n };\n}\n\nexport function createEmptyPlan(): LegacyPlanState {\n return {\n tasks: [],\n generatedAt: new Date().toISOString(),\n status: 'draft',\n runners: ['claude-code'],\n lastUpdated: new Date().toISOString(),\n };\n}\n\nexport function flattenTasks(tasks: Task[]): Task[] {\n return tasks.flatMap((t) => [t, ...flattenTasks(t.subtasks ?? [])]);\n}\n\n/** A flattened task with the parent it hangs under, null for a top-level task. */\nexport interface TaskWithParent {\n task: Task;\n parent: Task | null;\n}\n\nexport function flattenTasksWithParents(tasks: Task[]): TaskWithParent[] {\n const rows: TaskWithParent[] = [];\n const walk = (t: Task, parent: Task | null) => {\n rows.push({ task: t, parent });\n for (const sub of t.subtasks ?? []) walk(sub, t);\n };\n for (const t of tasks) walk(t, null);\n return rows;\n}\n\nexport function migrateTask(task: Record<string, unknown>): Task {\n if (!task.assignedModel) {\n task.assignedModel = undefined;\n }\n if (!task.assignedRunner) {\n task.assignedRunner = 'claude-code';\n }\n if (!task.thinkingEffort) {\n task.thinkingEffort = undefined;\n }\n if (!task.completionMarker) {\n task.completionMarker = uuidv4();\n }\n if (task.verdict && task.verification) {\n delete task.verification;\n }\n if (!task.autonomy) {\n task.autonomy = undefined;\n }\n if (!task.sliceType) {\n task.sliceType = undefined;\n }\n if (!task.userStoriesCovered) {\n task.userStoriesCovered = undefined;\n }\n return task as unknown as Task;\n}\n\nexport function addTaskToPlan(tasks: Task[], partial: Partial<Task>): Task[] {\n const maxOrder = tasks.reduce((max, t) => Math.max(max, t.order), 0);\n const newTask = createTask({\n ...partial,\n order: partial.order ?? maxOrder + 1,\n status: 'pending',\n });\n return renumberTasks([...tasks, newTask]);\n}\n\nexport function removeTaskFromPlan(tasks: Task[], taskId: string): Task[] {\n const result = tasks\n .filter((t) => t.id !== taskId)\n .map((t) => ({\n ...t,\n dependencies: t.dependencies.filter((depId) => depId !== taskId),\n subtasks: removeTaskFromPlan(t.subtasks, taskId),\n }));\n return renumberTasks(result);\n}\n\nexport function updateTaskInPlan(tasks: Task[], taskId: string, changes: Partial<Task>): Task[] {\n return renumberTasks(\n tasks.map((t) => {\n if (t.id === taskId) return { ...t, ...changes, id: t.id };\n return { ...t, subtasks: updateTaskInPlan(t.subtasks, taskId, changes) };\n })\n );\n}\n\nexport function renumberTasks(tasks: Task[]): Task[] {\n return tasks.map((t, i) => ({\n ...t,\n order: i + 1,\n subtasks: renumberTasks(t.subtasks),\n }));\n}\n\nexport function validateModifiedPlan(original: Task[], modified: Task[]): PlanModificationWarnings {\n const allOriginal = flattenTasks(original);\n const allModified = flattenTasks(modified);\n const warnings = emptyWarnings();\n const originalMap = new Map(allOriginal.map((t) => [t.id, t]));\n const modifiedIds = new Set(allModified.map((t) => t.id));\n\n for (const ot of originalMap.values()) {\n if (ot.status === 'completed' && !modifiedIds.has(ot.id)) {\n warnings.deletedCompleted.push(ot.title);\n } else if (ot.status === 'in_progress' && !modifiedIds.has(ot.id)) {\n warnings.deletedInProgress.push(ot.title);\n }\n }\n\n for (const mt of allModified) {\n const orig = originalMap.get(mt.id);\n if (orig) {\n if (orig.status === 'completed' && mt.status !== 'completed') {\n warnings.changedCompleted.push(orig.title);\n }\n if (orig.status === 'in_progress' && (mt.status !== 'in_progress' || mt.prompt !== orig.prompt)) {\n warnings.modifiedInProgress.push(orig.title);\n }\n if (orig.status === 'failed' && mt.status === 'pending') {\n for (const dt of allModified) {\n if (dt.dependencies.includes(mt.id) && dt.status === 'blocked') {\n dt.status = 'pending';\n }\n }\n }\n }\n }\n\n for (const t of allModified) {\n for (const depId of t.dependencies) {\n if (!modifiedIds.has(depId)) {\n warnings.brokenDependencies.push(`${t.title} → ${depId}`);\n }\n }\n }\n\n return warnings;\n}\n\nexport interface ActiveTaskSession {\n id: string;\n taskId: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport interface ValidationContext {\n executionLog: TaskSnapshot[];\n oldPending: Task[];\n newPending: Task[];\n activeSessions: Map<string, ActiveTaskSession>;\n}\n\nexport type ValidationCheck = (ctx: ValidationContext) => ValidationResult;\n\nexport function warningsText(w: PlanModificationWarnings): string | null {\n const lines: string[] = [];\n if (w.deletedCompleted.length) lines.push(`Completed tasks deleted: ${w.deletedCompleted.join(', ')}`);\n if (w.changedCompleted.length) lines.push(`Completed tasks modified: ${w.changedCompleted.join(', ')}`);\n if (w.deletedInProgress.length) lines.push(`In-progress tasks deleted: ${w.deletedInProgress.join(', ')}`);\n if (w.modifiedInProgress.length) lines.push(`In-progress tasks modified: ${w.modifiedInProgress.join(', ')}`);\n if (w.brokenDependencies.length) lines.push(`Broken dependencies: ${w.brokenDependencies.join(', ')}`);\n return lines.length > 0 ? lines.join('\\n') : null;\n}\n","/** The envelope key a full plan reply is keyed by: `{\"tasks\":[...]}`. */\nexport const PLAN_ENVELOPE_KEY = 'tasks';\n/** The envelope key a targeted-edits reply is keyed by: `{\"taskOps\":[...]}`. */\nexport const TASK_OPS_ENVELOPE_KEY = 'taskOps';\n/** The envelope key a read-only detail request is keyed by: `{\"taskQuery\":{...}}`. */\nexport const TASK_QUERY_ENVELOPE_KEY = 'taskQuery';\n\n/** Thrown when an LLM plan response cannot be parsed into a valid plan. Carries the raw text so callers can log it or retry. */\nexport class PlanParseError extends Error {\n readonly raw: string;\n /**\n * True when the reply was cut off mid-object (output-token limit) rather\n * than malformed — the two need different repairs: a truncated emission will\n * be cut at the same point again unless the retry frees context or asks for\n * terser output.\n */\n readonly truncated: boolean;\n /**\n * True when the JSON parsed fine and a *shape* rule rejected it. The generic\n * \"could not be parsed as JSON\" corrective is a lie for these, so the model\n * re-sends the same object; a semantic rejection must be repaired by naming\n * the rule it broke.\n */\n readonly semantic: boolean;\n constructor(message: string, raw: string, opts?: { truncated?: boolean; semantic?: boolean }) {\n super(message);\n this.name = 'PlanParseError';\n this.raw = raw;\n this.truncated = opts?.truncated ?? false;\n this.semantic = opts?.semantic ?? false;\n }\n}\n/**\n * Strip the noise reasoning models wrap around their answer: markdown code\n * fences and `<think>…</think>` chain-of-thought blocks (which routinely contain\n * stray braces that would otherwise derail brace-balancing). Reasoning captured\n * out-of-band by the service never reaches here, but a model that inlines its\n * thinking in the content channel still must not corrupt parsing.\n */\nexport function stripModelNoise(raw: string): string {\n return raw\n .replace(/<think>[\\s\\S]*?<\\/think>/gi, '')\n .replace(/```json\\s*/gi, '')\n .replace(/```\\s*/g, '')\n .trim();\n}\n\n/**\n * Scan from `start` (which must point at a `{`) for the matching balanced close,\n * ignoring braces inside strings. Returns the object substring and whether it was\n * balanced; an unbalanced result means the input was truncated mid-object.\n */\nfunction balancedObjectAt(text: string, start: number): { json: string; balanced: boolean } {\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === '{') depth++;\n else if (ch === '}') {\n depth--;\n if (depth === 0) return { json: text.slice(start, i + 1), balanced: true };\n }\n }\n return { json: text.slice(start), balanced: false };\n}\n\n/**\n * Scan an LLM response for every balanced `{…}` object carrying a `\"<key>\":`\n * entry. Strips fences and `<think>` blocks first. A matching object is\n * skipped over wholesale, so its nested braces don't produce fragment\n * candidates; non-matching objects are descended into, so a match wrapped in\n * an unrelated outer object is still found. `fallback` preserves the legacy\n * behavior for callers with no keyed match: the first balanced object, else\n * the stripped text so a JSON.parse error still surfaces.\n */\nexport function extractObjectsWithKey(raw: string, key: string): {\n matches: string[];\n fallback: { json: string; balanced: boolean };\n sawBrace: boolean;\n /** An object ran to EOF unclosed — the classic signature of truncated output. */\n sawUnbalanced: boolean;\n} {\n const stripped = stripModelNoise(raw);\n const keyRe = new RegExp(`\"${key}\"\\\\s*:`);\n\n const matches: string[] = [];\n let firstObject: string | null = null;\n let sawBrace = false;\n let sawUnbalanced = false;\n let inString = false;\n let escaped = false;\n for (let i = 0; i < stripped.length; i++) {\n const ch = stripped[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') { inString = true; continue; }\n if (ch !== '{') continue;\n\n sawBrace = true;\n const obj = balancedObjectAt(stripped, i);\n // A stray brace in a reasoning preamble produces an unbalanced candidate,\n // which we skip so it can't swallow the real object that follows.\n if (obj.balanced && keyRe.test(obj.json)) {\n matches.push(obj.json);\n i += obj.json.length - 1;\n continue;\n }\n if (!obj.balanced) sawUnbalanced = true;\n if (!firstObject && obj.balanced) firstObject = obj.json;\n }\n\n return {\n matches,\n fallback: firstObject !== null ? { json: firstObject, balanced: true } : { json: stripped, balanced: false },\n sawBrace,\n sawUnbalanced,\n };\n}\n\n/**\n * Pull the JSON object out of an LLM response and report whether it was balanced.\n * Strips fences and `<think>` blocks, then walks every top-level `{…}` and\n * returns the FIRST one that contains a `\"tasks\"` key — so a brace appearing\n * earlier in reasoning (or an unrelated preamble object) can't make us parse the\n * wrong thing. Falls back to the first balanced object and, failing that, the\n * first `{` onwards so a genuine `JSON.parse` error still surfaces.\n */\nexport function extractObjectWithBalance(raw: string): { json: string; balanced: boolean; sawBrace: boolean } {\n const { matches, fallback, sawBrace } = extractObjectsWithKey(raw, PLAN_ENVELOPE_KEY);\n if (matches.length > 0) return { json: matches[0], balanced: true, sawBrace };\n return { ...fallback, sawBrace };\n}\n\n/**\n * Pull the JSON object out of an LLM response. Strips markdown code fences and\n * `<think>` blocks, prefers the object containing a `tasks` key, and tolerates a\n * prose preamble and trailing prose. Returns the fence-stripped text unchanged\n * if no `{` is present so the caller's JSON.parse produces a clear failure.\n */\nexport function extractJsonObject(raw: string): string {\n return extractObjectWithBalance(raw).json;\n}\n\n/** Drop trailing commas before a closing `}` or `]` — a common model quirk. */\nexport function stripTrailingCommas(json: string): string {\n return json.replace(/,(\\s*[}\\]])/g, '$1');\n}\n\n/**\n * Escape raw control characters that appear INSIDE string literals — budget\n * models routinely emit multi-line `prompt` strings with literal newlines,\n * which strict JSON.parse rejects (\"bad control character\"). Characters\n * outside strings (formatting whitespace) are left untouched.\n */\nexport function escapeControlCharsInStrings(json: string): string {\n let out = '';\n let inString = false;\n let escaped = false;\n for (const ch of json) {\n if (inString) {\n if (escaped) { out += ch; escaped = false; continue; }\n if (ch === '\\\\') { out += ch; escaped = true; continue; }\n if (ch === '\"') { out += ch; inString = false; continue; }\n if (ch === '\\n') { out += '\\\\n'; continue; }\n if (ch === '\\r') { out += '\\\\r'; continue; }\n if (ch === '\\t') { out += '\\\\t'; continue; }\n out += ch;\n continue;\n }\n if (ch === '\"') inString = true;\n out += ch;\n }\n return out;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { h as RunnerId, c as PlanStatus, L as LegacyPlanState, a as DiscoveredModel, T as Task, d as ResearchProgress, R as ResearchLogEntry, C as ConversationMessage, n as TaskSnapshot, Q as QueuedMessage, A as ActiveTaskSession, g as ResearchToolType, b as PlanState, v as Verdict } from './Task-
|
|
2
|
-
export { D as DiscoveredMode, M as Message, P as PlanModificationWarnings, e as ResearchStep, f as ResearchStepOutcome, S as StreamEvent, i as StreamStepEvent, j as StreamThinkingEvent, k as TaskMode, l as TaskModelAssignment, m as TaskOutputSummary, o as TaskStatus, p as TaskType, q as TaskWithParent, r as ThinkingBlock, U as UserPromptEntry, s as UserStep, V as ValidationCheck, t as ValidationContext, u as ValidationResult, w as VerificationCheck, x as addTaskToPlan, y as createEmptyPlan, z as createTask, B as emptyWarnings, E as flattenTasks, F as flattenTasksWithParents, G as migrateLegacyPlan, H as migratePlanState, I as migrateTask, J as removeTaskFromPlan, K as renumberTasks, N as updateTaskInPlan, O as validateModifiedPlan, W as warningsText } from './Task-
|
|
3
|
-
import { f as IFileSystem, R as ReadFileOpts, T as ToolOutcome, d as GrepOptions, c as GlobOptions, b as FindSymbolOptions, I as IConfig, A as AiProvider, r as ProviderModelLists, i as ITerminalSession, h as ITerminalRunner, w as RunnerRegistry, k as OrchestratorOption, u as RunnerInvocation, g as IPluginStore, v as RunnerPluginManifest, t as ResolveContext } from './ITerminalRunner-
|
|
4
|
-
export { a as AllProviderModels, C as CatalogModel, D as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, e as GrepOutputMode, M as ModelCatalog, j as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginCloneFn, l as PluginEntry, m as PluginFeatures, n as PluginMode, o as PluginModelDiscovery, p as PluginRunnerDef, q as ProviderCredentialSource, s as ProviderModelsResult, S as SEARCH_EXCLUSIONS, x as collectProviderCredentials, y as enabledRunners, z as fetchAllProviderModels, B as isReservedRunnerName, E as knownModelId, H as resolveModelShortcut, J as resolveProvider, K as toOrchestratorOptions } from './ITerminalRunner-
|
|
1
|
+
import { h as RunnerId, c as PlanStatus, L as LegacyPlanState, a as DiscoveredModel, T as Task, d as ResearchProgress, R as ResearchLogEntry, C as ConversationMessage, n as TaskSnapshot, Q as QueuedMessage, A as ActiveTaskSession, g as ResearchToolType, b as PlanState, v as Verdict } from './Task-4rDGr8Su.mjs';
|
|
2
|
+
export { D as DiscoveredMode, M as Message, P as PlanModificationWarnings, e as ResearchStep, f as ResearchStepOutcome, S as StreamEvent, i as StreamStepEvent, j as StreamThinkingEvent, k as TaskMode, l as TaskModelAssignment, m as TaskOutputSummary, o as TaskStatus, p as TaskType, q as TaskWithParent, r as ThinkingBlock, U as UserPromptEntry, s as UserStep, V as ValidationCheck, t as ValidationContext, u as ValidationResult, w as VerificationCheck, x as addTaskToPlan, y as createEmptyPlan, z as createTask, B as emptyWarnings, E as flattenTasks, F as flattenTasksWithParents, G as migrateLegacyPlan, H as migratePlanState, I as migrateTask, J as removeTaskFromPlan, K as renumberTasks, N as updateTaskInPlan, O as validateModifiedPlan, W as warningsText } from './Task-4rDGr8Su.mjs';
|
|
3
|
+
import { f as IFileSystem, R as ReadFileOpts, T as ToolOutcome, d as GrepOptions, c as GlobOptions, b as FindSymbolOptions, I as IConfig, A as AiProvider, r as ProviderModelLists, i as ITerminalSession, h as ITerminalRunner, w as RunnerRegistry, k as OrchestratorOption, u as RunnerInvocation, g as IPluginStore, v as RunnerPluginManifest, t as ResolveContext } from './ITerminalRunner-E3-6QNUS.mjs';
|
|
4
|
+
export { a as AllProviderModels, C as CatalogModel, D as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, e as GrepOutputMode, M as ModelCatalog, j as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginCloneFn, l as PluginEntry, m as PluginFeatures, n as PluginMode, o as PluginModelDiscovery, p as PluginRunnerDef, q as ProviderCredentialSource, s as ProviderModelsResult, S as SEARCH_EXCLUSIONS, x as collectProviderCredentials, y as enabledRunners, z as fetchAllProviderModels, B as isReservedRunnerName, E as knownModelId, H as resolveModelShortcut, J as resolveProvider, K as toOrchestratorOptions } from './ITerminalRunner-E3-6QNUS.mjs';
|
|
5
5
|
import { I as IApproval, d as ApprovalRequest, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.mjs';
|
|
6
6
|
export { A as ApprovalKind, b as ApprovalPolicy, c as ApprovalPolicyOptions, e as ApprovalSource, D as DENY_ALL } from './ApprovalPolicy-BVhGdECT.mjs';
|
|
7
|
-
import { R as RunnerModeInfo } from './ModeResolver-
|
|
8
|
-
export { M as ManifestLookup, b as buildModeGuide, f as filteredBuildModes, r as resolveDefaultMode, a as resolveTaskMode, c as runnerModesFrom } from './ModeResolver-
|
|
9
|
-
import { T as TaskOp, c as SessionBroadcaster } from './plan-utils-
|
|
10
|
-
export { A as ApplyTaskOpsResult, C as CHECKPOINT_TRUNCATE_LENGTH, S as SerializedPlan, a as SerializedTask, b as SerializedTaskStatus, d as SessionMessage, e as TaskRef, f as applyTaskOps, g as canMergeTasks, h as canSetDependencies, i as canSplitTask, j as classifyOutcome, k as dependencyCandidates, l as dependentsOf, m as executionSummary, p as parseTaskOpsJson, s as serializePlan, n as serializeTask, o as serializeTaskStatus, q as summarizeToolCall, t as textHasTaskOps, r as truncateCheckpointSummary } from './plan-utils-
|
|
7
|
+
import { R as RunnerModeInfo } from './ModeResolver-mtIWrLXn.mjs';
|
|
8
|
+
export { M as ManifestLookup, b as buildModeGuide, f as filteredBuildModes, r as resolveDefaultMode, a as resolveTaskMode, c as runnerModesFrom } from './ModeResolver-mtIWrLXn.mjs';
|
|
9
|
+
import { T as TaskOp, c as SessionBroadcaster } from './plan-utils-s6VL8NDF.mjs';
|
|
10
|
+
export { A as ApplyTaskOpsResult, C as CHECKPOINT_TRUNCATE_LENGTH, S as SerializedPlan, a as SerializedTask, b as SerializedTaskStatus, d as SessionMessage, e as TaskRef, f as applyTaskOps, g as canMergeTasks, h as canSetDependencies, i as canSplitTask, j as classifyOutcome, k as dependencyCandidates, l as dependentsOf, m as executionSummary, p as parseTaskOpsJson, s as serializePlan, n as serializeTask, o as serializeTaskStatus, q as summarizeToolCall, t as textHasTaskOps, r as truncateCheckpointSummary } from './plan-utils-s6VL8NDF.mjs';
|
|
11
11
|
import { ChildProcess } from 'child_process';
|
|
12
12
|
import { EventEmitter } from 'events';
|
|
13
|
-
import { b as PlanParseError } from './parsing-
|
|
14
|
-
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as TASK_QUERY_ENVELOPE_KEY, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as looksLikePlanAttempt, p as parsePartialPlan, n as parsePlanJson, s as stripModelNoise, o as stripTrailingCommas, v as validatePlanModification } from './parsing-
|
|
13
|
+
import { b as PlanParseError } from './parsing-BWfpLch9.mjs';
|
|
14
|
+
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as TASK_QUERY_ENVELOPE_KEY, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as looksLikePlanAttempt, p as parsePartialPlan, n as parsePlanJson, s as stripModelNoise, o as stripTrailingCommas, v as validatePlanModification } from './parsing-BWfpLch9.mjs';
|
|
15
15
|
export { resolveOrderLabel, taskOrderLabel } from './order-labels.mjs';
|
|
16
16
|
|
|
17
17
|
interface SessionMeta {
|
|
@@ -1073,8 +1073,16 @@ interface AgentAdapter {
|
|
|
1073
1073
|
* Send one user message and stream the turn's events until it ends. Resolves
|
|
1074
1074
|
* when the agent yields the floor; rejects only when the transport itself
|
|
1075
1075
|
* failed in a way no `error` event could describe.
|
|
1076
|
-
|
|
1077
|
-
|
|
1076
|
+
*
|
|
1077
|
+
* `onActivity`, when given, fires on raw transport traffic — every stdio
|
|
1078
|
+
* line or stream chunk the process produces — independent of whether that
|
|
1079
|
+
* traffic becomes an `AgentEvent`. An adapter may legitimately emit nothing
|
|
1080
|
+
* for long stretches (a subagent's filtered output, most often); a caller
|
|
1081
|
+
* using presence-of-events as a liveness signal would read that silence as
|
|
1082
|
+
* a hang. `onActivity` is the seam that keeps liveness detection from being
|
|
1083
|
+
* coupled to what each adapter chooses to surface.
|
|
1084
|
+
*/
|
|
1085
|
+
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
1078
1086
|
/** The agent's native session id once it has announced one. Resumption hint only. */
|
|
1079
1087
|
nativeSessionId(): string | null;
|
|
1080
1088
|
/** Kill the process and release its resources. Idempotent. */
|
|
@@ -2099,6 +2107,8 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2099
2107
|
private exited;
|
|
2100
2108
|
/** Set for the duration of a turn. Outside one, events are buffered rather than dropped. */
|
|
2101
2109
|
private turnEmit;
|
|
2110
|
+
/** Set for the duration of a turn. Pinged on every raw line, whether or not `handleLine` turns it into an event. */
|
|
2111
|
+
private turnActivity;
|
|
2102
2112
|
/**
|
|
2103
2113
|
* Events the agent produced before its first turn — in practice the startup
|
|
2104
2114
|
* warnings that arrive during the handshake. Dropping them hid the one
|
|
@@ -2132,7 +2142,7 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2132
2142
|
/** Protocol handshake, if the agent needs one before it accepts a turn. */
|
|
2133
2143
|
protected handshake(_opts: AgentStartOptions): Promise<void>;
|
|
2134
2144
|
start(opts: AgentStartOptions): Promise<void>;
|
|
2135
|
-
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
2145
|
+
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
2136
2146
|
nativeSessionId(): string | null;
|
|
2137
2147
|
dispose(): void;
|
|
2138
2148
|
/** Write one raw protocol line to the agent. */
|
|
@@ -2247,7 +2257,7 @@ declare class OpenCodeAdapter implements AgentAdapter {
|
|
|
2247
2257
|
private turnHasText;
|
|
2248
2258
|
constructor(deps: AgentProcessDeps);
|
|
2249
2259
|
start(opts: AgentStartOptions): Promise<void>;
|
|
2250
|
-
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
2260
|
+
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
2251
2261
|
/**
|
|
2252
2262
|
* Emit one message part, once. OpenCode reports a tool part repeatedly as it
|
|
2253
2263
|
* moves through pending → running → completed, so parts are keyed by id and
|
|
@@ -2292,7 +2302,7 @@ declare function mapAgentTool(name: string): MappedTool;
|
|
|
2292
2302
|
*/
|
|
2293
2303
|
declare function normalizeAgentArgs(tool: ResearchToolType, args: Record<string, unknown>): Record<string, unknown>;
|
|
2294
2304
|
|
|
2295
|
-
declare const BUILTIN_SKILL_NAMES: readonly ["grilling", "to-spec"];
|
|
2305
|
+
declare const BUILTIN_SKILL_NAMES: readonly ["grilling", "to-spec", "improve-codebase-architecture"];
|
|
2296
2306
|
interface SkillMetadata {
|
|
2297
2307
|
name: string;
|
|
2298
2308
|
description: string;
|
|
@@ -2360,11 +2370,19 @@ interface SessionRuntimeSettings {
|
|
|
2360
2370
|
*/
|
|
2361
2371
|
declare function sessionRuntimeSettings(settings: UserSettings): SessionRuntimeSettings;
|
|
2362
2372
|
/**
|
|
2363
|
-
* Resolve
|
|
2364
|
-
* exported so surfaces and verification can drive substitution without a
|
|
2365
|
-
* Session.
|
|
2366
|
-
*
|
|
2367
|
-
*
|
|
2373
|
+
* Resolve `/skill-name` invocations to their skill's markdown content. Pure
|
|
2374
|
+
* and exported so surfaces and verification can drive substitution without a
|
|
2375
|
+
* full Session.
|
|
2376
|
+
*
|
|
2377
|
+
* A message that is *only* `/skill-name` keeps the legacy whole-message
|
|
2378
|
+
* behaviour: an unknown skill becomes a notice naming what IS available,
|
|
2379
|
+
* instead of a bare slash token a runner would mis-resolve in its own skills
|
|
2380
|
+
* directory. Anywhere else in a message, a matching token is spliced in place
|
|
2381
|
+
* (surrounding text is untouched); a token that doesn't name a real skill is
|
|
2382
|
+
* left as plain text rather than raising a notice, since embedded in a
|
|
2383
|
+
* sentence it's as likely to be incidental text (a path, an example command)
|
|
2384
|
+
* as a typo'd invocation. The same skill name repeated only expands its first
|
|
2385
|
+
* occurrence — later repeats stay literal.
|
|
2368
2386
|
*/
|
|
2369
2387
|
declare function resolveSkillInvocation(text: string, skillsService: Pick<SkillsService, 'findSkill' | 'listSkills'>): string;
|
|
2370
2388
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { h as RunnerId, c as PlanStatus, L as LegacyPlanState, a as DiscoveredModel, T as Task, d as ResearchProgress, R as ResearchLogEntry, C as ConversationMessage, n as TaskSnapshot, Q as QueuedMessage, A as ActiveTaskSession, g as ResearchToolType, b as PlanState, v as Verdict } from './Task-
|
|
2
|
-
export { D as DiscoveredMode, M as Message, P as PlanModificationWarnings, e as ResearchStep, f as ResearchStepOutcome, S as StreamEvent, i as StreamStepEvent, j as StreamThinkingEvent, k as TaskMode, l as TaskModelAssignment, m as TaskOutputSummary, o as TaskStatus, p as TaskType, q as TaskWithParent, r as ThinkingBlock, U as UserPromptEntry, s as UserStep, V as ValidationCheck, t as ValidationContext, u as ValidationResult, w as VerificationCheck, x as addTaskToPlan, y as createEmptyPlan, z as createTask, B as emptyWarnings, E as flattenTasks, F as flattenTasksWithParents, G as migrateLegacyPlan, H as migratePlanState, I as migrateTask, J as removeTaskFromPlan, K as renumberTasks, N as updateTaskInPlan, O as validateModifiedPlan, W as warningsText } from './Task-
|
|
3
|
-
import { f as IFileSystem, R as ReadFileOpts, T as ToolOutcome, d as GrepOptions, c as GlobOptions, b as FindSymbolOptions, I as IConfig, A as AiProvider, r as ProviderModelLists, i as ITerminalSession, h as ITerminalRunner, w as RunnerRegistry, k as OrchestratorOption, u as RunnerInvocation, g as IPluginStore, v as RunnerPluginManifest, t as ResolveContext } from './ITerminalRunner-
|
|
4
|
-
export { a as AllProviderModels, C as CatalogModel, D as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, e as GrepOutputMode, M as ModelCatalog, j as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginCloneFn, l as PluginEntry, m as PluginFeatures, n as PluginMode, o as PluginModelDiscovery, p as PluginRunnerDef, q as ProviderCredentialSource, s as ProviderModelsResult, S as SEARCH_EXCLUSIONS, x as collectProviderCredentials, y as enabledRunners, z as fetchAllProviderModels, B as isReservedRunnerName, E as knownModelId, H as resolveModelShortcut, J as resolveProvider, K as toOrchestratorOptions } from './ITerminalRunner-
|
|
1
|
+
import { h as RunnerId, c as PlanStatus, L as LegacyPlanState, a as DiscoveredModel, T as Task, d as ResearchProgress, R as ResearchLogEntry, C as ConversationMessage, n as TaskSnapshot, Q as QueuedMessage, A as ActiveTaskSession, g as ResearchToolType, b as PlanState, v as Verdict } from './Task-4rDGr8Su.js';
|
|
2
|
+
export { D as DiscoveredMode, M as Message, P as PlanModificationWarnings, e as ResearchStep, f as ResearchStepOutcome, S as StreamEvent, i as StreamStepEvent, j as StreamThinkingEvent, k as TaskMode, l as TaskModelAssignment, m as TaskOutputSummary, o as TaskStatus, p as TaskType, q as TaskWithParent, r as ThinkingBlock, U as UserPromptEntry, s as UserStep, V as ValidationCheck, t as ValidationContext, u as ValidationResult, w as VerificationCheck, x as addTaskToPlan, y as createEmptyPlan, z as createTask, B as emptyWarnings, E as flattenTasks, F as flattenTasksWithParents, G as migrateLegacyPlan, H as migratePlanState, I as migrateTask, J as removeTaskFromPlan, K as renumberTasks, N as updateTaskInPlan, O as validateModifiedPlan, W as warningsText } from './Task-4rDGr8Su.js';
|
|
3
|
+
import { f as IFileSystem, R as ReadFileOpts, T as ToolOutcome, d as GrepOptions, c as GlobOptions, b as FindSymbolOptions, I as IConfig, A as AiProvider, r as ProviderModelLists, i as ITerminalSession, h as ITerminalRunner, w as RunnerRegistry, k as OrchestratorOption, u as RunnerInvocation, g as IPluginStore, v as RunnerPluginManifest, t as ResolveContext } from './ITerminalRunner-CbLHKXT5.js';
|
|
4
|
+
export { a as AllProviderModels, C as CatalogModel, D as DiscoveryCommand, F as FetchAllProviderModelsOptions, G as GREP_DEFAULT_HEAD_LIMIT, e as GrepOutputMode, M as ModelCatalog, j as ModelShortcut, O as ORCHESTRATOR_SHORTCUTS, P as PluginCloneFn, l as PluginEntry, m as PluginFeatures, n as PluginMode, o as PluginModelDiscovery, p as PluginRunnerDef, q as ProviderCredentialSource, s as ProviderModelsResult, S as SEARCH_EXCLUSIONS, x as collectProviderCredentials, y as enabledRunners, z as fetchAllProviderModels, B as isReservedRunnerName, E as knownModelId, H as resolveModelShortcut, J as resolveProvider, K as toOrchestratorOptions } from './ITerminalRunner-CbLHKXT5.js';
|
|
5
5
|
import { I as IApproval, d as ApprovalRequest, a as ApprovalMode } from './ApprovalPolicy-BVhGdECT.js';
|
|
6
6
|
export { A as ApprovalKind, b as ApprovalPolicy, c as ApprovalPolicyOptions, e as ApprovalSource, D as DENY_ALL } from './ApprovalPolicy-BVhGdECT.js';
|
|
7
|
-
import { R as RunnerModeInfo } from './ModeResolver-
|
|
8
|
-
export { M as ManifestLookup, b as buildModeGuide, f as filteredBuildModes, r as resolveDefaultMode, a as resolveTaskMode, c as runnerModesFrom } from './ModeResolver-
|
|
9
|
-
import { T as TaskOp, c as SessionBroadcaster } from './plan-utils-
|
|
10
|
-
export { A as ApplyTaskOpsResult, C as CHECKPOINT_TRUNCATE_LENGTH, S as SerializedPlan, a as SerializedTask, b as SerializedTaskStatus, d as SessionMessage, e as TaskRef, f as applyTaskOps, g as canMergeTasks, h as canSetDependencies, i as canSplitTask, j as classifyOutcome, k as dependencyCandidates, l as dependentsOf, m as executionSummary, p as parseTaskOpsJson, s as serializePlan, n as serializeTask, o as serializeTaskStatus, q as summarizeToolCall, t as textHasTaskOps, r as truncateCheckpointSummary } from './plan-utils-
|
|
7
|
+
import { R as RunnerModeInfo } from './ModeResolver-Ob-ihQbI.js';
|
|
8
|
+
export { M as ManifestLookup, b as buildModeGuide, f as filteredBuildModes, r as resolveDefaultMode, a as resolveTaskMode, c as runnerModesFrom } from './ModeResolver-Ob-ihQbI.js';
|
|
9
|
+
import { T as TaskOp, c as SessionBroadcaster } from './plan-utils-DJm2a7Zp.js';
|
|
10
|
+
export { A as ApplyTaskOpsResult, C as CHECKPOINT_TRUNCATE_LENGTH, S as SerializedPlan, a as SerializedTask, b as SerializedTaskStatus, d as SessionMessage, e as TaskRef, f as applyTaskOps, g as canMergeTasks, h as canSetDependencies, i as canSplitTask, j as classifyOutcome, k as dependencyCandidates, l as dependentsOf, m as executionSummary, p as parseTaskOpsJson, s as serializePlan, n as serializeTask, o as serializeTaskStatus, q as summarizeToolCall, t as textHasTaskOps, r as truncateCheckpointSummary } from './plan-utils-DJm2a7Zp.js';
|
|
11
11
|
import { ChildProcess } from 'child_process';
|
|
12
12
|
import { EventEmitter } from 'events';
|
|
13
|
-
import { b as PlanParseError } from './parsing-
|
|
14
|
-
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as TASK_QUERY_ENVELOPE_KEY, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as looksLikePlanAttempt, p as parsePartialPlan, n as parsePlanJson, s as stripModelNoise, o as stripTrailingCommas, v as validatePlanModification } from './parsing-
|
|
13
|
+
import { b as PlanParseError } from './parsing-BJoHbA-t.js';
|
|
14
|
+
export { P as PLAN_ENVELOPE_KEY, a as PartialPlanTask, T as TASK_OPS_ENVELOPE_KEY, c as TASK_QUERY_ENVELOPE_KEY, d as checkDepsResolve, e as checkImmutableLog, f as checkInProgress, g as checkNoCycles, h as checkUniqueIds, i as escapeControlCharsInStrings, j as extractJsonObject, k as extractObjectWithBalance, l as extractObjectsWithKey, m as looksLikePlanAttempt, p as parsePartialPlan, n as parsePlanJson, s as stripModelNoise, o as stripTrailingCommas, v as validatePlanModification } from './parsing-BJoHbA-t.js';
|
|
15
15
|
export { resolveOrderLabel, taskOrderLabel } from './order-labels.js';
|
|
16
16
|
|
|
17
17
|
interface SessionMeta {
|
|
@@ -1073,8 +1073,16 @@ interface AgentAdapter {
|
|
|
1073
1073
|
* Send one user message and stream the turn's events until it ends. Resolves
|
|
1074
1074
|
* when the agent yields the floor; rejects only when the transport itself
|
|
1075
1075
|
* failed in a way no `error` event could describe.
|
|
1076
|
-
|
|
1077
|
-
|
|
1076
|
+
*
|
|
1077
|
+
* `onActivity`, when given, fires on raw transport traffic — every stdio
|
|
1078
|
+
* line or stream chunk the process produces — independent of whether that
|
|
1079
|
+
* traffic becomes an `AgentEvent`. An adapter may legitimately emit nothing
|
|
1080
|
+
* for long stretches (a subagent's filtered output, most often); a caller
|
|
1081
|
+
* using presence-of-events as a liveness signal would read that silence as
|
|
1082
|
+
* a hang. `onActivity` is the seam that keeps liveness detection from being
|
|
1083
|
+
* coupled to what each adapter chooses to surface.
|
|
1084
|
+
*/
|
|
1085
|
+
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
1078
1086
|
/** The agent's native session id once it has announced one. Resumption hint only. */
|
|
1079
1087
|
nativeSessionId(): string | null;
|
|
1080
1088
|
/** Kill the process and release its resources. Idempotent. */
|
|
@@ -2099,6 +2107,8 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2099
2107
|
private exited;
|
|
2100
2108
|
/** Set for the duration of a turn. Outside one, events are buffered rather than dropped. */
|
|
2101
2109
|
private turnEmit;
|
|
2110
|
+
/** Set for the duration of a turn. Pinged on every raw line, whether or not `handleLine` turns it into an event. */
|
|
2111
|
+
private turnActivity;
|
|
2102
2112
|
/**
|
|
2103
2113
|
* Events the agent produced before its first turn — in practice the startup
|
|
2104
2114
|
* warnings that arrive during the handshake. Dropping them hid the one
|
|
@@ -2132,7 +2142,7 @@ declare abstract class StdioAgentAdapter implements AgentAdapter {
|
|
|
2132
2142
|
/** Protocol handshake, if the agent needs one before it accepts a turn. */
|
|
2133
2143
|
protected handshake(_opts: AgentStartOptions): Promise<void>;
|
|
2134
2144
|
start(opts: AgentStartOptions): Promise<void>;
|
|
2135
|
-
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
2145
|
+
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
2136
2146
|
nativeSessionId(): string | null;
|
|
2137
2147
|
dispose(): void;
|
|
2138
2148
|
/** Write one raw protocol line to the agent. */
|
|
@@ -2247,7 +2257,7 @@ declare class OpenCodeAdapter implements AgentAdapter {
|
|
|
2247
2257
|
private turnHasText;
|
|
2248
2258
|
constructor(deps: AgentProcessDeps);
|
|
2249
2259
|
start(opts: AgentStartOptions): Promise<void>;
|
|
2250
|
-
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
2260
|
+
send(message: string, onEvent: (event: AgentEvent) => void, signal?: AbortSignal, onActivity?: () => void): Promise<void>;
|
|
2251
2261
|
/**
|
|
2252
2262
|
* Emit one message part, once. OpenCode reports a tool part repeatedly as it
|
|
2253
2263
|
* moves through pending → running → completed, so parts are keyed by id and
|
|
@@ -2292,7 +2302,7 @@ declare function mapAgentTool(name: string): MappedTool;
|
|
|
2292
2302
|
*/
|
|
2293
2303
|
declare function normalizeAgentArgs(tool: ResearchToolType, args: Record<string, unknown>): Record<string, unknown>;
|
|
2294
2304
|
|
|
2295
|
-
declare const BUILTIN_SKILL_NAMES: readonly ["grilling", "to-spec"];
|
|
2305
|
+
declare const BUILTIN_SKILL_NAMES: readonly ["grilling", "to-spec", "improve-codebase-architecture"];
|
|
2296
2306
|
interface SkillMetadata {
|
|
2297
2307
|
name: string;
|
|
2298
2308
|
description: string;
|
|
@@ -2360,11 +2370,19 @@ interface SessionRuntimeSettings {
|
|
|
2360
2370
|
*/
|
|
2361
2371
|
declare function sessionRuntimeSettings(settings: UserSettings): SessionRuntimeSettings;
|
|
2362
2372
|
/**
|
|
2363
|
-
* Resolve
|
|
2364
|
-
* exported so surfaces and verification can drive substitution without a
|
|
2365
|
-
* Session.
|
|
2366
|
-
*
|
|
2367
|
-
*
|
|
2373
|
+
* Resolve `/skill-name` invocations to their skill's markdown content. Pure
|
|
2374
|
+
* and exported so surfaces and verification can drive substitution without a
|
|
2375
|
+
* full Session.
|
|
2376
|
+
*
|
|
2377
|
+
* A message that is *only* `/skill-name` keeps the legacy whole-message
|
|
2378
|
+
* behaviour: an unknown skill becomes a notice naming what IS available,
|
|
2379
|
+
* instead of a bare slash token a runner would mis-resolve in its own skills
|
|
2380
|
+
* directory. Anywhere else in a message, a matching token is spliced in place
|
|
2381
|
+
* (surrounding text is untouched); a token that doesn't name a real skill is
|
|
2382
|
+
* left as plain text rather than raising a notice, since embedded in a
|
|
2383
|
+
* sentence it's as likely to be incidental text (a path, an example command)
|
|
2384
|
+
* as a typo'd invocation. The same skill name repeated only expands its first
|
|
2385
|
+
* occurrence — later repeats stay literal.
|
|
2368
2386
|
*/
|
|
2369
2387
|
declare function resolveSkillInvocation(text: string, skillsService: Pick<SkillsService, 'findSkill' | 'listSkills'>): string;
|
|
2370
2388
|
/**
|
package/dist/index.js
CHANGED
|
@@ -10873,6 +10873,8 @@ var StdioAgentAdapter = class {
|
|
|
10873
10873
|
exited = null;
|
|
10874
10874
|
/** Set for the duration of a turn. Outside one, events are buffered rather than dropped. */
|
|
10875
10875
|
turnEmit = null;
|
|
10876
|
+
/** Set for the duration of a turn. Pinged on every raw line, whether or not `handleLine` turns it into an event. */
|
|
10877
|
+
turnActivity = null;
|
|
10876
10878
|
/**
|
|
10877
10879
|
* Events the agent produced before its first turn — in practice the startup
|
|
10878
10880
|
* warnings that arrive during the handshake. Dropping them hid the one
|
|
@@ -10919,12 +10921,15 @@ var StdioAgentAdapter = class {
|
|
|
10919
10921
|
windowsVerbatimArguments: launch.verbatim
|
|
10920
10922
|
});
|
|
10921
10923
|
this.process.stdout?.on("data", (chunk) => {
|
|
10922
|
-
this.stdout.push(chunk.toString(), (line) =>
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
this.
|
|
10926
|
-
|
|
10927
|
-
|
|
10924
|
+
this.stdout.push(chunk.toString(), (line) => {
|
|
10925
|
+
this.turnActivity?.();
|
|
10926
|
+
this.handleLine(line, (event) => {
|
|
10927
|
+
if (this.turnEmit) this.turnEmit(event);
|
|
10928
|
+
else if (!this.hadTurn && !TURN_SCOPED_EVENTS.has(event.type) && this.betweenTurns.length < BETWEEN_TURN_EVENT_CAP) {
|
|
10929
|
+
this.betweenTurns.push(event);
|
|
10930
|
+
}
|
|
10931
|
+
});
|
|
10932
|
+
});
|
|
10928
10933
|
});
|
|
10929
10934
|
this.process.stderr?.on("data", (chunk) => {
|
|
10930
10935
|
this.stderrTail = (this.stderrTail + chunk.toString()).slice(-STDERR_TAIL_CHARS);
|
|
@@ -10941,7 +10946,7 @@ ${err.message}`).slice(-STDERR_TAIL_CHARS);
|
|
|
10941
10946
|
});
|
|
10942
10947
|
await this.handshake(opts);
|
|
10943
10948
|
}
|
|
10944
|
-
async send(message, onEvent, signal) {
|
|
10949
|
+
async send(message, onEvent, signal, onActivity) {
|
|
10945
10950
|
if (!this.process) throw new Error(`${this.agentId} planner session is not started`);
|
|
10946
10951
|
if (this.exited) {
|
|
10947
10952
|
onEvent({ type: "error", message: this.exitMessage() });
|
|
@@ -10953,6 +10958,7 @@ ${err.message}`).slice(-STDERR_TAIL_CHARS);
|
|
|
10953
10958
|
if (settled) return;
|
|
10954
10959
|
settled = true;
|
|
10955
10960
|
this.turnEmit = null;
|
|
10961
|
+
this.turnActivity = null;
|
|
10956
10962
|
this.hadTurn = true;
|
|
10957
10963
|
signal?.removeEventListener("abort", onAbort);
|
|
10958
10964
|
this.process?.removeListener("exit", onExit);
|
|
@@ -10974,6 +10980,7 @@ ${err.message}`).slice(-STDERR_TAIL_CHARS);
|
|
|
10974
10980
|
finish();
|
|
10975
10981
|
};
|
|
10976
10982
|
this.turnEmit = emit;
|
|
10983
|
+
this.turnActivity = onActivity ?? null;
|
|
10977
10984
|
this.process.once("exit", onExit);
|
|
10978
10985
|
this.process.once("error", onExit);
|
|
10979
10986
|
if (signal?.aborted) {
|
|
@@ -11608,7 +11615,7 @@ ${this.stderrTail.trim()}` : ""}`);
|
|
|
11608
11615
|
if (!created?.id) throw new Error("The OpenCode planner server did not return a session id.");
|
|
11609
11616
|
this.sessionId = created.id;
|
|
11610
11617
|
}
|
|
11611
|
-
async send(message, onEvent, signal) {
|
|
11618
|
+
async send(message, onEvent, signal, onActivity) {
|
|
11612
11619
|
if (!this.baseUrl || !this.sessionId) throw new Error("OpenCode planner session is not started");
|
|
11613
11620
|
if (this.exited) {
|
|
11614
11621
|
onEvent({ type: "error", message: this.exitMessage() });
|
|
@@ -11628,7 +11635,8 @@ ${this.stderrTail.trim()}` : ""}`);
|
|
|
11628
11635
|
if (part.type === "tool") this.emitPart(part, seen, onEvent);
|
|
11629
11636
|
},
|
|
11630
11637
|
(ask) => this.denyPermission(ask, seen, onEvent),
|
|
11631
|
-
connected
|
|
11638
|
+
connected,
|
|
11639
|
+
onActivity
|
|
11632
11640
|
);
|
|
11633
11641
|
await Promise.race([streamReady, new Promise((r) => {
|
|
11634
11642
|
const t = setTimeout(r, STREAM_CONNECT_TIMEOUT_MS);
|
|
@@ -11743,7 +11751,7 @@ ${part.text}` : part.text });
|
|
|
11743
11751
|
* the settled POST repeats it — but permission requests arrive nowhere else,
|
|
11744
11752
|
* so the stream is load-bearing for {@link denyPermission}.
|
|
11745
11753
|
*/
|
|
11746
|
-
async streamEvents(signal, onPart, onPermission, onConnected) {
|
|
11754
|
+
async streamEvents(signal, onPart, onPermission, onConnected, onActivity) {
|
|
11747
11755
|
const response = await this.deps.fetch(`${this.baseUrl}/event`, { signal }).catch(() => null);
|
|
11748
11756
|
const body = response?.body;
|
|
11749
11757
|
if (!body) {
|
|
@@ -11757,6 +11765,7 @@ ${part.text}` : part.text });
|
|
|
11757
11765
|
for (; ; ) {
|
|
11758
11766
|
const { done, value } = await reader.read().catch(() => ({ done: true, value: void 0 }));
|
|
11759
11767
|
if (done) return;
|
|
11768
|
+
onActivity?.();
|
|
11760
11769
|
buffer += decoder.decode(value, { stream: true });
|
|
11761
11770
|
let newline;
|
|
11762
11771
|
while ((newline = buffer.indexOf("\n")) >= 0) {
|
|
@@ -12151,7 +12160,7 @@ var CliAgentAiService = class {
|
|
|
12151
12160
|
case "turn_end":
|
|
12152
12161
|
return;
|
|
12153
12162
|
}
|
|
12154
|
-
}, signal);
|
|
12163
|
+
}, signal, () => onProgress({ type: "liveness" }));
|
|
12155
12164
|
for (const id of [...pendingCalls.keys()]) {
|
|
12156
12165
|
settle(id, "The agent ended the turn without reporting this call's result.", false, "not_executed");
|
|
12157
12166
|
}
|
|
@@ -12577,7 +12586,7 @@ function builtinSkillsDir() {
|
|
|
12577
12586
|
}
|
|
12578
12587
|
|
|
12579
12588
|
// src/services/SkillsService.ts
|
|
12580
|
-
var BUILTIN_SKILL_NAMES = ["grilling", "to-spec"];
|
|
12589
|
+
var BUILTIN_SKILL_NAMES = ["grilling", "to-spec", "improve-codebase-architecture"];
|
|
12581
12590
|
var RETIRED_BUILTIN_SKILL_NAMES = ["grill-me"];
|
|
12582
12591
|
function parseSkillFile(filePath, name, source) {
|
|
12583
12592
|
const raw = fs4.readFileSync(filePath, "utf8");
|
|
@@ -12984,16 +12993,27 @@ var PlanEditError = class extends Error {
|
|
|
12984
12993
|
function sessionRuntimeSettings(settings) {
|
|
12985
12994
|
return { ...plannerRuntimeToggles(settings), modelAllowlist: settings.modelAllowlist };
|
|
12986
12995
|
}
|
|
12996
|
+
var SKILL_TOKEN = /(^|\s)\/([a-z][a-z0-9_-]*)([,.!?;:]*)(?=\s|$)/gi;
|
|
12987
12997
|
function resolveSkillInvocation(text, skillsService) {
|
|
12988
|
-
const
|
|
12989
|
-
if (
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
12995
|
-
|
|
12996
|
-
|
|
12998
|
+
const bareMatch = text.trim().match(/^\/([a-z][a-z0-9_-]*)$/im);
|
|
12999
|
+
if (bareMatch) {
|
|
13000
|
+
const skillName = bareMatch[1].toLowerCase();
|
|
13001
|
+
const skill = skillsService.findSkill(skillName);
|
|
13002
|
+
if (!skill) {
|
|
13003
|
+
const available = typeof skillsService.listSkills === "function" ? skillsService.listSkills().map((s) => s.name).join(", ") : "";
|
|
13004
|
+
return `Unknown skill: ${skillName}. Available skills: ${available}`;
|
|
13005
|
+
}
|
|
13006
|
+
return skill.content;
|
|
13007
|
+
}
|
|
13008
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
13009
|
+
return text.replace(SKILL_TOKEN, (full, lead, name, punct) => {
|
|
13010
|
+
const skillName = name.toLowerCase();
|
|
13011
|
+
if (expanded.has(skillName)) return full;
|
|
13012
|
+
const skill = skillsService.findSkill(skillName);
|
|
13013
|
+
if (!skill) return full;
|
|
13014
|
+
expanded.add(skillName);
|
|
13015
|
+
return `${lead}${skill.content}${punct}`;
|
|
13016
|
+
});
|
|
12997
13017
|
}
|
|
12998
13018
|
var Session = class {
|
|
12999
13019
|
/** Injected by a test; when present it is the service, forever. */
|
|
@@ -13165,6 +13185,9 @@ var Session = class {
|
|
|
13165
13185
|
};
|
|
13166
13186
|
}
|
|
13167
13187
|
translateProgress(progress) {
|
|
13188
|
+
if (progress.type === "liveness") {
|
|
13189
|
+
this.broadcast({ type: "planner_liveness" });
|
|
13190
|
+
}
|
|
13168
13191
|
if (progress.type === "thinking" && progress.text) {
|
|
13169
13192
|
this.broadcast({ type: "plan_thinking", text: progress.text });
|
|
13170
13193
|
}
|