/** * Plan step extraction and [DONE:n] progress tracking. * * The agent outputs [DONE:n] markers in its text to signal that step n * of the approved plan has been completed. The UI parses these markers * and renders a progress widget. */ export interface PlanStep { /** 1-based step number */ step: number; /** Short description extracted from the plan */ text: string; completed: boolean; } /** * Extract numbered steps from a plan markdown string. * * Steps are ONLY read from a dedicated step-section heading (`## Steps` or a * close synonym — see STEP_SECTION_HEADING). If the plan has no such section, * this returns an empty array — progress tracking is opt-in. * * The previous behaviour scanned the entire document for any top-level * numbered list when no step section was present, which scraped phantom * "steps" out of unrelated prose (design decisions, Q&A bullets, rejected * alternatives). The post-approval prompt then pushed the model to march * through those non-tasks and emit `[DONE:n]` markers for them, deadlocking * a model that correctly refused to fabricate completion. Requiring an * explicit step-section heading keeps the progress contract honest. * * Looks for lines like: * 1. Do something * 2) Do something else * 3. **Bold step** */ export declare function extractPlanSteps(planContent: string): PlanStep[]; /** * Re-base a frozen step list onto a freshly extracted one. * * The progress widget captures `extractPlanSteps` once, at plan-approval time. * But the agent can rewrite or expand the approved plan while implementing it * (e.g. a 2-step plan becomes 12 steps). When that happens the frozen snapshot * goes stale: the total is wrong and `[DONE:n]` markers for the new steps can't * be matched. Re-extracting from the live plan and re-basing onto it keeps the * total in sync. * * Completion is carried over BY STEP NUMBER (not text), so a reworded step that * was already done stays done. New steps adopt the fresh text and start * incomplete. If the fresh plan has no steps (e.g. the step section was * temporarily removed mid-edit) the previous list is returned unchanged so we * never blow away real progress. The previous array reference is returned when * nothing meaningfully changed, so React state setters can no-op. */ export declare function rebasePlanSteps(previous: PlanStep[], fresh: PlanStep[]): PlanStep[]; /** * Strip [DONE:n] markers from text for display purposes. * These markers are machine-readable signals for the progress widget, * not meant to be shown to the user. */ export declare function stripDoneMarkers(text: string): string; /** * Segment of an assistant turn's text after [DONE:N] markers are split * out for inline rendering. Used by the chat to render "✓ Step N: " * markers in the same temporal order the agent emitted them, instead of * stripping markers to invisible whitespace. */ export type DisplaySegment = { kind: "text"; text: string; } | { kind: "done"; stepNum: number; description: string; }; /** * Split text on [DONE:N] markers, returning an array of segments. Empty/ * whitespace-only text segments are dropped. Step description is looked * up in `steps` (falls back to "" so the renderer can show just the step * number when the plan is no longer in scope, e.g. after onComplete * cleared planSteps). */ export declare function segmentDisplayText(text: string, steps: PlanStep[]): DisplaySegment[]; /** * Scan text for [DONE:n] markers and return the set of completed step numbers. */ export declare function findCompletedMarkers(text: string): Set; /** * Apply completed markers to a steps array (immutable — returns new array). */ export declare function markStepsCompleted(steps: PlanStep[], completed: Set): PlanStep[]; //# sourceMappingURL=plan-steps.d.ts.map