zidane 6.2.13 → 6.2.15

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.
Files changed (36) hide show
  1. package/dist/acp-cli.js +2 -2
  2. package/dist/{anthropic-BYsc6qWj.js → anthropic-CTAXBVsj.js} +2 -2
  3. package/dist/anthropic-CTAXBVsj.js.map +1 -0
  4. package/dist/{auth-Bb479DFB.js → auth-BCpEbzvO.js} +2 -2
  5. package/dist/{auth-Bb479DFB.js.map → auth-BCpEbzvO.js.map} +1 -1
  6. package/dist/chat/pure.d.ts +3 -3
  7. package/dist/chat/pure.js +3 -2
  8. package/dist/chat.d.ts +3 -3
  9. package/dist/chat.js +5 -4
  10. package/dist/chat.js.map +1 -1
  11. package/dist/history-search-C4bk1Wz_.js +486 -0
  12. package/dist/history-search-C4bk1Wz_.js.map +1 -0
  13. package/dist/history-search-worker.d.ts +1 -0
  14. package/dist/history-search-worker.js +86 -0
  15. package/dist/history-search-worker.js.map +1 -0
  16. package/dist/index.js +1 -1
  17. package/dist/providers/anthropic.js +1 -1
  18. package/dist/providers.js +1 -1
  19. package/dist/{tool-formatters-BSwVkSX2.d.ts → tool-formatters-DdgS-xE2.d.ts} +90 -4
  20. package/dist/tool-formatters-DdgS-xE2.d.ts.map +1 -0
  21. package/dist/transcript-anchors-DKjXpQ0h.d.ts.map +1 -1
  22. package/dist/{transcript-anchors-yogJHuBW.js → transcript-anchors-DZ-8BF4p.js} +3 -3
  23. package/dist/transcript-anchors-DZ-8BF4p.js.map +1 -0
  24. package/dist/tui.d.ts +52 -10
  25. package/dist/tui.d.ts.map +1 -1
  26. package/dist/tui.js +1340 -246
  27. package/dist/tui.js.map +1 -1
  28. package/dist/{turn-operations-CXjRaltC.js → turn-operations-CokV32wf.js} +82 -11
  29. package/dist/turn-operations-CokV32wf.js.map +1 -0
  30. package/dist/{turn-operations-CjkgQKmR.d.ts → turn-operations-sE-Sli9H.d.ts} +2 -2
  31. package/dist/{turn-operations-CjkgQKmR.d.ts.map → turn-operations-sE-Sli9H.d.ts.map} +1 -1
  32. package/package.json +1 -1
  33. package/dist/anthropic-BYsc6qWj.js.map +0 -1
  34. package/dist/tool-formatters-BSwVkSX2.d.ts.map +0 -1
  35. package/dist/transcript-anchors-yogJHuBW.js.map +0 -1
  36. package/dist/turn-operations-CXjRaltC.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-operations-CokV32wf.js","names":["DEFAULT_RESULT_LIMIT"],"sources":["../src/chat/completion-chats.ts","../src/chat/edit-approval.ts","../src/chat/edit-diff.ts","../src/chat/turn-selection.ts","../src/chat/color-gradient.ts","../src/chat/completion-files.ts","../src/chat/completion-skills.ts","../src/chat/markdown-segments.ts","../src/chat/model-catalog.ts","../src/chat/prompt-segments.ts","../src/chat/streaming-pure.ts","../src/chat/tool-formatters.ts","../src/chat/turn-operations.ts"],"sourcesContent":["/**\n * Completion provider for cross-chat references. Trigger: `#`.\n *\n * The visible row is human-friendly (session title, age, project), but the\n * inserted token is id-based (`#abc123`) so titles with spaces never enter the\n * prompt grammar. The token is the shortest normalized id prefix that is unique\n * within the reference catalog, with a six-character floor for readability.\n */\n\nimport type {\n CompletionContext,\n CompletionItem,\n CompletionProvider,\n CompletionReference,\n} from './completion-core'\nimport { Fzf } from 'fzf'\nimport { ageString, shortId } from './format'\n\nexport const CHATS_TRIGGER = '#'\n\nconst DEFAULT_RESULT_LIMIT = 50\nconst MIN_TOKEN_LENGTH = 6\n\nexport type ChatReferenceScope = 'project' | 'all'\n\nexport interface ChatReferenceEntry {\n id: string\n title: string\n turnCount: number\n userMessageCount: number\n runCount: number\n projectRoot?: string\n updatedAt: number\n}\n\nexport interface ChatReferenceData {\n entry: ChatReferenceEntry\n token: string\n}\n\nfunction normalizeId(id: string): string {\n return id.replace(/-/g, '').toLowerCase()\n}\n\nfunction projectLabel(projectRoot: string | undefined): string {\n if (!projectRoot)\n return ''\n const parts = projectRoot.split(/[\\\\/]/).filter(Boolean)\n return parts[parts.length - 1] ?? projectRoot\n}\n\nfunction tokenFor(id: string, catalog: readonly ChatReferenceEntry[]): string {\n const normalized = normalizeId(id)\n const normalizedIds = catalog.map(entry => normalizeId(entry.id))\n for (let len = Math.min(MIN_TOKEN_LENGTH, normalized.length); len <= normalized.length; len++) {\n const token = normalized.slice(0, len)\n const matches = normalizedIds.filter(candidate => candidate.startsWith(token))\n if (matches.length === 1)\n return token\n }\n return normalized || shortId(id)\n}\n\nfunction stripTrailingPunctuation(candidate: string): string {\n return candidate.replace(/[.,;:)\\]}!?]+$/, '')\n}\n\nfunction descriptionFor(entry: ChatReferenceEntry, token: string, scope: ChatReferenceScope): string {\n const bits = [\n `#${token}`,\n ageString(entry.updatedAt),\n `${entry.userMessageCount} msg${entry.userMessageCount === 1 ? '' : 's'}`,\n ]\n const project = projectLabel(entry.projectRoot)\n if (scope === 'all' && project)\n bits.push(project)\n return bits.join(' · ')\n}\n\nfunction scoreChats(\n catalog: readonly ChatReferenceEntry[],\n tokenCatalog: readonly ChatReferenceEntry[],\n query: string,\n limit: number,\n scope: ChatReferenceScope,\n): CompletionItem<ChatReferenceData>[] {\n const q = query.trim().toLowerCase()\n const rows = catalog.map(entry => ({\n entry,\n token: tokenFor(entry.id, tokenCatalog),\n project: projectLabel(entry.projectRoot),\n }))\n const fuzzyHits = q.length > 0\n ? new Set(new Fzf(rows, {\n selector: r => `${r.entry.title} ${r.token} ${r.project}`,\n casing: 'case-insensitive',\n }).find(q).map(r => r.item))\n : null\n const scored: { entry: ChatReferenceEntry, token: string, rank: number }[] = []\n for (const row of rows) {\n const title = row.entry.title.toLowerCase()\n const token = row.token.toLowerCase()\n const project = row.project.toLowerCase()\n if (q.length === 0) {\n scored.push({ entry: row.entry, token: row.token, rank: 5 })\n continue\n }\n if (token.startsWith(q)) {\n scored.push({ entry: row.entry, token: row.token, rank: 0 })\n continue\n }\n if (title.startsWith(q)) {\n scored.push({ entry: row.entry, token: row.token, rank: 1 })\n continue\n }\n if (title.includes(q)) {\n scored.push({ entry: row.entry, token: row.token, rank: 2 })\n continue\n }\n if (project.includes(q)) {\n scored.push({ entry: row.entry, token: row.token, rank: 3 })\n continue\n }\n if (fuzzyHits?.has(row)) {\n scored.push({ entry: row.entry, token: row.token, rank: 4 })\n }\n }\n scored.sort((a, b) => {\n if (a.rank !== b.rank)\n return a.rank - b.rank\n return b.entry.updatedAt - a.entry.updatedAt\n })\n return scored.slice(0, limit).map<CompletionItem<ChatReferenceData>>(({ entry, token }) => ({\n id: token,\n label: entry.title,\n description: descriptionFor(entry, token, scope),\n insertText: `${CHATS_TRIGGER}${token} `,\n data: { entry, token },\n }))\n}\n\nexport function createChatsCompletionProvider(opts: {\n getCatalog: () => readonly ChatReferenceEntry[]\n getReferenceCatalog?: () => readonly ChatReferenceEntry[]\n getScope?: () => ChatReferenceScope\n ensureCatalog?: () => Promise<readonly ChatReferenceEntry[]>\n limit?: number\n}): CompletionProvider<ChatReferenceData> {\n const limit = opts.limit ?? DEFAULT_RESULT_LIMIT\n const scope = () => opts.getScope?.() ?? 'project'\n return {\n id: 'chats',\n trigger: CHATS_TRIGGER,\n label: 'Chats',\n suggest(query) {\n const current = opts.getCatalog()\n const tokenCatalog = opts.getReferenceCatalog?.() ?? current\n const effectiveTokenCatalog = tokenCatalog.length > 0 ? tokenCatalog : current\n if (current.length > 0)\n return scoreChats(current, effectiveTokenCatalog, query, limit, scope())\n if (opts.ensureCatalog) {\n return opts.ensureCatalog().then((loaded) => {\n const refreshed = opts.getReferenceCatalog?.() ?? loaded\n const refreshedTokenCatalog = refreshed.length > 0 ? refreshed : loaded\n return scoreChats(loaded, refreshedTokenCatalog, query, limit, scope())\n })\n }\n return []\n },\n parseReferences(text, _ctx: CompletionContext) {\n const catalog = opts.getReferenceCatalog?.() ?? opts.getCatalog()\n if (catalog.length === 0)\n return []\n const byToken = new Map<string, ChatReferenceData>()\n for (const entry of catalog) {\n const token = tokenFor(entry.id, catalog)\n byToken.set(token, { entry, token })\n }\n const refs: CompletionReference<ChatReferenceData>[] = []\n const rx = /(^|\\s)#(\\S+)/g\n for (const m of text.matchAll(rx)) {\n const candidate = stripTrailingPunctuation(m[2])\n const data = byToken.get(candidate.toLowerCase())\n if (!data)\n continue\n const start = m.index + m[1].length\n refs.push({\n providerId: 'chats',\n start,\n end: start + 1 + candidate.length,\n itemId: data.entry.id,\n data,\n })\n }\n return refs\n },\n }\n}\n\nexport function uniqueChatIdsFromReferences(\n references: readonly CompletionReference<unknown>[],\n): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n for (const ref of references) {\n if (ref.providerId !== 'chats')\n continue\n if (seen.has(ref.itemId))\n continue\n seen.add(ref.itemId)\n out.push(ref.itemId)\n }\n return out\n}\n\nexport function chatReferenceTokensFromText(text: string): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const rx = /(^|\\s)#(\\S+)/g\n for (const m of text.matchAll(rx)) {\n const token = stripTrailingPunctuation(m[2]).toLowerCase()\n if (!token || seen.has(token))\n continue\n seen.add(token)\n out.push(token)\n }\n return out\n}\n","/**\n * Pure helpers for the file-edit approval gate.\n *\n * Lives in `chat/` (not `tui/`) so unit tests can exercise the decision\n * logic without mounting React. The TUI binds these helpers in\n * `app.tsx`'s `applyGate` and in the modal's submit path; replay code\n * (`eventsFromTurns`) reuses the result parser.\n */\n\nimport type { ToolResultContent } from '../types'\nimport type { ApprovalDecision } from './safe-mode-context'\nimport type { EditOutcome, EditOutcomeKind, EditPayload } from './types'\n\n/**\n * Convert a per-hunk approval mask into an `EditOutcome[]`. `true` →\n * `applied`; `false` → `denied` with the supplied reason.\n *\n * Length is `Math.max(mask.length, fallbackLength)` so callers passing a\n * shorter mask still get a fully-populated array — missing entries\n * default to applied, matching the \"no decision => keep\" convention.\n */\nexport function maskToOutcomeKinds(\n mask: readonly boolean[],\n fallbackLength: number,\n deniedReason = 'denied by user',\n): EditOutcome[] {\n const len = Math.max(mask.length, fallbackLength)\n const out: EditOutcome[] = []\n for (let i = 0; i < len; i++) {\n const keep = i < mask.length ? mask[i] : true\n out.push(keep ? { kind: 'applied' } : { kind: 'denied', reason: deniedReason })\n }\n return out\n}\n\n/**\n * Apply an `ApprovalDecision` to a payload, returning the resolved\n * per-hunk outcomes + the gate-level verdict.\n *\n * Pure — does not mutate `input` or `payload`. The TUI's `applyGate`\n * consumes the result: stashes `outcomes` in the pending-annotation map\n * (keyed by callId) so `tool:transform` can append the\n * `<edit-outcomes>` block to the tool result, rebinds `ctx.input.edits`\n * to the approved subset for `partial`, and emits the `syntheticEvent`\n * for fully-denied or fully-blocked calls.\n */\nexport interface ResolvedApproval {\n /** Final state of every hunk after the decision (1:1 with payload.hunks). */\n outcomes: EditOutcome[]\n /** True when no hunk will be applied — gate should `block` the call. */\n shouldBlock: boolean\n /**\n * Synthetic `EditPayload` to render in the transcript. Identical to the\n * incoming payload but with `outcomes` set so the renderer can badge\n * each hunk. Only meaningful when at least one hunk was denied —\n * an all-applied decision returns `null` here and the normal\n * `tool:before` event suffices.\n */\n syntheticEvent: EditPayload | null\n}\n\nexport function resolveApprovalForPayload(\n decision: ApprovalDecision,\n payload: EditPayload,\n): ResolvedApproval {\n const total = payload.hunks.length\n\n if (decision === 'deny') {\n const outcomes: EditOutcome[] = Array.from(\n { length: total },\n () => ({ kind: 'denied' as const, reason: 'denied by user' }),\n )\n return {\n outcomes,\n shouldBlock: true,\n syntheticEvent: { ...payload, outcomes },\n }\n }\n\n if (typeof decision === 'object' && decision.kind === 'partial') {\n const outcomes = maskToOutcomeKinds(decision.mask, total)\n const anyApplied = outcomes.some(o => o.kind === 'applied')\n return {\n outcomes,\n shouldBlock: !anyApplied,\n syntheticEvent: { ...payload, outcomes },\n }\n }\n\n // accept-once / accept-session / accept-safelist: every hunk applies.\n // No synthetic event — `tool:before` will paint the standard payload.\n return {\n outcomes: Array.from({ length: total }, () => ({ kind: 'applied' as const })),\n shouldBlock: false,\n syntheticEvent: null,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Result annotation — XML-like sentinel block appended to edit tool\n// results so the renderer (live + replay) can reconstruct per-hunk\n// outcomes without a host-side side-channel on `tool_call.input`.\n//\n// Shape (one block per call):\n//\n// <edit-outcomes>\n// #1 applied\n// #2 denied: denied by user\n// #3 applied\n// </edit-outcomes>\n//\n// - Opening + closing tags each on their own line.\n// - One line per hunk: `#<1-based index> <kind>[: <reason>]`.\n// - `kind` is one of `applied | denied | skipped | failed`.\n//\n// The TUI's `tool:transform` hook appends the block when at least one\n// hunk is NOT applied — an all-applied call needs no annotation since\n// the legacy summary line conveys the same information.\n// ---------------------------------------------------------------------------\n\n/** Sentinel tags used by {@link buildEditOutcomesAnnotation} / parser. */\nconst ANNOTATION_OPEN = '<edit-outcomes>'\nconst ANNOTATION_CLOSE = '</edit-outcomes>'\n\nconst OUTCOME_KIND_RE = /^applied|denied|skipped|failed$/\nconst OUTCOME_LINE_RE = /^#(\\d+) (applied|denied|skipped|failed)(?:: ?(.*))?$/\n\n/**\n * Render an `EditOutcome[]` as the wire-format annotation block. Returns\n * the body to APPEND to a tool result; callers join with a leading\n * `\\n\\n` separator. Idempotent on missing reasons — bare `applied` lines\n * stay terse.\n */\nexport function buildEditOutcomesAnnotation(outcomes: readonly EditOutcome[]): string {\n const lines: string[] = [ANNOTATION_OPEN]\n for (let i = 0; i < outcomes.length; i++) {\n const o = outcomes[i]\n if (!OUTCOME_KIND_RE.test(o.kind))\n continue\n const reason = o.reason ? `: ${o.reason}` : ''\n lines.push(`#${i + 1} ${o.kind}${reason}`)\n }\n lines.push(ANNOTATION_CLOSE)\n return lines.join('\\n')\n}\n\n/**\n * Parse an `<edit-outcomes>…</edit-outcomes>` annotation block out of a\n * tool result body. Returns the outcomes keyed by 1-based hunk index, or\n * `null` when the block is missing / malformed.\n *\n * Anchored on the explicit tag pair so the parser doesn't false-positive\n * on natural prose that happens to contain `#1 applied`.\n */\nexport function parseEditOutcomesFromResult(\n result: string | readonly ToolResultContent[],\n): EditOutcome[] | null {\n const text = typeof result === 'string'\n ? result\n : result\n .filter((b): b is Extract<ToolResultContent, { type: 'text' }> => b.type === 'text')\n .map(b => b.text)\n .join('\\n')\n\n if (!text)\n return null\n\n const openIdx = text.indexOf(`\\n${ANNOTATION_OPEN}\\n`)\n const startIdx = openIdx >= 0 ? openIdx + 1 : (text.startsWith(`${ANNOTATION_OPEN}\\n`) ? 0 : -1)\n if (startIdx < 0)\n return null\n\n const closeNeedle = `\\n${ANNOTATION_CLOSE}`\n const closeIdx = text.indexOf(closeNeedle, startIdx)\n if (closeIdx < 0)\n return null\n\n const body = text.slice(startIdx + ANNOTATION_OPEN.length + 1, closeIdx)\n const found: Array<{ idx: number, outcome: EditOutcome }> = []\n for (const line of body.split('\\n')) {\n if (line.length === 0)\n continue\n const m = OUTCOME_LINE_RE.exec(line)\n if (!m)\n return null\n const idx = Number.parseInt(m[1], 10)\n if (!Number.isFinite(idx) || idx < 1)\n return null\n const kind = m[2] as EditOutcomeKind\n const reason = m[3]?.trim()\n found.push({\n idx,\n outcome: {\n kind,\n ...(reason ? { reason } : {}),\n },\n })\n }\n\n if (found.length === 0)\n return null\n\n const maxIdx = Math.max(...found.map(f => f.idx))\n const outcomes: EditOutcome[] = Array.from({ length: maxIdx }, () => ({ kind: 'applied' }))\n for (const { idx, outcome } of found)\n outcomes[idx - 1] = outcome\n return outcomes\n}\n\n/**\n * Strip the first `<edit-outcomes>…</edit-outcomes>` block out of a tool\n * result body, returning the surrounding text. Used by the\n * `tool:transform` hook to peel a body-emitted annotation before\n * re-appending the merged (approval ∪ body) version — otherwise the\n * result would carry two annotation blocks and\n * {@link parseEditOutcomesFromResult} would only see the first.\n *\n * Anchored on the same `\\n<edit-outcomes>\\n` / start-of-string newline\n * shape the parser uses, so prose that incidentally mentions\n * `<edit-outcomes>` (e.g. a model summarizing its own format) isn't\n * mistakenly stripped. Trims a single leading `\\n\\n` separator when\n * present so successive strips don't leave dangling blank lines.\n * Idempotent on inputs that don't contain a properly-anchored block.\n */\nexport function stripEditOutcomesAnnotation(text: string): string {\n // Mirror `parseEditOutcomesFromResult`'s anchor: either preceded by\n // a newline (the common case after a `\\n\\n` separator from the body)\n // OR at the very start of the body. A bare `<edit-outcomes>` inside\n // prose without that surrounding newline shape stays untouched.\n const newlineNeedle = `\\n${ANNOTATION_OPEN}\\n`\n const newlineIdx = text.indexOf(newlineNeedle)\n let openIdx: number\n if (newlineIdx >= 0)\n openIdx = newlineIdx + 1\n else if (text.startsWith(`${ANNOTATION_OPEN}\\n`))\n openIdx = 0\n else\n return text\n\n const closeIdx = text.indexOf(ANNOTATION_CLOSE, openIdx)\n if (closeIdx < 0)\n return text\n const blockEnd = closeIdx + ANNOTATION_CLOSE.length\n // Eat one preceding `\\n\\n` separator (the shape the writer emits)\n // so the trimmed text doesn't end with an awkward double newline.\n const sepStart = openIdx >= 2 && text.slice(openIdx - 2, openIdx) === '\\n\\n'\n ? openIdx - 2\n : openIdx\n return text.slice(0, sepStart) + text.slice(blockEnd)\n}\n\n/**\n * Merge body-side outcomes (keyed against the approved subset the tool\n * actually ran on, in subset-position order) into approval-side outcomes\n * (1:1 with the model's ORIGINAL `edits` list, with `denied` entries for\n * every hunk the user dropped).\n *\n * Algorithm: walk the approval array; every `applied` placeholder\n * corresponds to one approved hunk that the body ran. Consume body's\n * outcomes in order against those placeholders. Non-`applied` approval\n * entries (`denied`, `skipped`) stay untouched — they describe gate-\n * level decisions the body never saw.\n *\n * Pure. Returns a fresh array; never mutates either input.\n *\n * Edge cases:\n * - `body` is empty / shorter than the approved count → remaining\n * approval `applied` placeholders stay as `applied` (the body ran\n * happily; absence of a body entry means nothing failed).\n * - `body` longer than approved count → trailing body entries are\n * ignored. Shouldn't happen in practice (body sees the rebound\n * subset), but the guard keeps the merge total-pure.\n */\nexport function mergeApprovalAndBodyOutcomes(\n approval: readonly EditOutcome[],\n body: readonly EditOutcome[] | null,\n): EditOutcome[] {\n if (!body || body.length === 0)\n return approval.slice()\n const out: EditOutcome[] = []\n let bi = 0\n for (const entry of approval) {\n if (entry.kind === 'applied' && bi < body.length) {\n out.push(body[bi])\n bi++\n }\n else {\n out.push(entry)\n }\n }\n return out\n}\n\n/**\n * Rewrite a `multi_edit` body header so the totals reflect the model's\n * ORIGINAL edit list (the merged outcomes count) instead of the subset\n * the body actually saw after gate rebinding. Without this, a partially\n * approved call surfaces a misleading `applied 2 of 2 edits` (subset\n * counts) on the wire even when the original was `applied 2 of 3`.\n *\n * Three body-side shapes are handled (matching `multi_edit`'s emit):\n * 1. `Edited <path>: applied N edits (R replacements).`\n * 2. `Edited <path>: applied N of M edits (R replacements).`\n * 3. `multi_edit error: no edits applied to <path> (M attempted).`\n *\n * The replacements count is preserved verbatim — it's a body-side stat\n * the chat layer can't recompute. When the first line doesn't look like\n * any of the three shapes (e.g. an unrelated error preamble bubbled up),\n * the text is returned unchanged.\n */\nexport function rewriteMultiEditHeader(\n text: string,\n merged: readonly EditOutcome[],\n path: string,\n): string {\n const newlineIdx = text.indexOf('\\n')\n const firstLine = newlineIdx < 0 ? text : text.slice(0, newlineIdx)\n const rest = newlineIdx < 0 ? '' : text.slice(newlineIdx)\n\n // Match either success shape (with or without \"of M\") and capture R.\n // The path component uses `.+` greedy so colons (Windows `C:\\…`) and\n // parens (unusual but valid filenames) don't trip the match — the\n // regex engine backtracks to find the longest path that still lets\n // `: applied N…` line up against the trailing structure.\n const successMatch = firstLine.match(\n /^Edited .+: applied \\d+(?: of \\d+)? edits? \\((\\d+) replacement/,\n )\n // Match the all-failed shape (no replacements stat, defaults to 0).\n // `startsWith` instead of regex: the prefix is unique enough and\n // sidesteps the same path-content escaping concerns.\n const isFailedShape = firstLine.startsWith('multi_edit error: no edits applied to ')\n && firstLine.endsWith(' attempted).')\n if (!successMatch && !isFailedShape)\n return text\n\n const replacements = successMatch ? Number.parseInt(successMatch[1], 10) || 0 : 0\n const counts = summarizeOutcomes(merged)\n const applied = counts.applied\n const total = merged.length\n\n let newHeader: string\n if (applied === total) {\n newHeader = `Edited ${path}: applied ${total} edit${total === 1 ? '' : 's'} (${replacements} replacement${replacements === 1 ? '' : 's'}).`\n }\n else if (applied > 0) {\n newHeader = `Edited ${path}: applied ${applied} of ${total} edits (${replacements} replacement${replacements === 1 ? '' : 's'}).`\n }\n else {\n newHeader = `multi_edit error: no edits applied to ${path} (${total} attempted).`\n }\n\n return newHeader + rest\n}\n\n/**\n * Aggregate counts for the transcript's summary badge (`3 applied · 1\n * denied · 1 skipped`). Exported so renderers don't reimplement the\n * tally. Pure / O(n).\n */\nexport function summarizeOutcomes(outcomes: readonly EditOutcome[] | undefined): {\n applied: number\n denied: number\n skipped: number\n failed: number\n pending: number\n total: number\n} {\n const counts = { applied: 0, denied: 0, skipped: 0, failed: 0, pending: 0 }\n if (!outcomes)\n return { ...counts, total: 0 }\n for (const o of outcomes)\n counts[o.kind] += 1\n return { ...counts, total: outcomes.length }\n}\n","import type { ResolvedMatch } from '../tools/edit-utils'\nimport type { EditHunk, EditPayload } from './types'\nimport { resolveOldString, styleReplacementForVia } from '../tools/edit-utils'\n\n// ---------------------------------------------------------------------------\n// extractEditPayload — pulls `EditPayload` out of a tool call's raw input.\n//\n// Used by both the live `tool:before` hook and the historical replay path\n// (`eventsFromTurns`). Returns `undefined` when the tool isn't one of the\n// supported edit tools, or when the input shape is unexpected — in either\n// case the renderer falls back to the unstructured `↳ name(args)` line.\n//\n// Outcomes are NOT pulled from input — they live on the paired tool_result\n// text via the `<edit-outcomes>` annotation block written by the TUI's\n// `tool:transform` hook. `eventsFromTurns` pairs call ↔ result by callId\n// and attaches outcomes after the fact via `parseEditOutcomesFromResult`.\n//\n// `write_file` needs the *previous* on-disk content to render a diff;\n// that's the caller's responsibility (the TUI's hook reads it before the\n// tool runs). Pass it as `priorContent`; an empty string is fine for a\n// fresh create. Historical replay has no priorContent and falls through\n// to `oldString: ''` — every line renders as an addition, matching\n// `git diff` for newly-added files.\n// ---------------------------------------------------------------------------\n\ninterface EditStepInput {\n old_string: unknown\n new_string: unknown\n replace_all?: unknown\n}\n\nexport function extractEditPayload(\n name: string,\n input: Record<string, unknown>,\n priorContent?: string,\n): EditPayload | undefined {\n const path = input.path\n if (typeof path !== 'string' || path === '')\n return undefined\n\n if (name === 'edit') {\n const oldString = input.old_string\n const newString = input.new_string\n if (typeof oldString !== 'string' || typeof newString !== 'string')\n return undefined\n const hunks: EditHunk[] = [{\n oldString,\n newString,\n ...(input.replace_all === true ? { replaceAll: true } : {}),\n }]\n return {\n tool: 'edit',\n path,\n hunks,\n ...(priorContent !== undefined ? { priorContent } : {}),\n }\n }\n\n if (name === 'multi_edit') {\n const steps = input.edits\n if (!Array.isArray(steps) || steps.length === 0)\n return undefined\n const hunks: EditHunk[] = []\n for (const raw of steps as EditStepInput[]) {\n if (typeof raw?.old_string !== 'string' || typeof raw?.new_string !== 'string')\n return undefined\n hunks.push({\n oldString: raw.old_string,\n newString: raw.new_string,\n ...(raw.replace_all === true ? { replaceAll: true } : {}),\n })\n }\n return {\n tool: 'multi_edit',\n path,\n hunks,\n ...(priorContent !== undefined ? { priorContent } : {}),\n }\n }\n\n if (name === 'write_file') {\n const content = input.content\n if (typeof content !== 'string')\n return undefined\n const hunks: EditHunk[] = [{ oldString: priorContent ?? '', newString: content }]\n return {\n tool: 'write_file',\n path,\n hunks,\n ...(priorContent !== undefined ? { priorContent } : {}),\n }\n }\n\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Line diff — LCS table walk, returns a sequence of `context | add | remove`\n// rows. Backed by the standard 2-D dynamic-programming LCS — O(n·m) time\n// and memory — but ONLY over the changed core: common prefix and suffix\n// lines are trimmed first, so a one-hunk edit to a 76k-line file costs a\n// table over the hunk, not the file. `buildContextualDiff` feeds WHOLE\n// FILES through here (the showEditDiffs / edit-approval render path);\n// without the trim, a 76k-line file demanded a 76k×76k ≈ 5.8-billion-cell\n// table — tens of GB — which OOM'd the TUI outright on real reports.\n//\n// When the trimmed core is still over {@link LCS_CELL_BUDGET} (two\n// genuinely unrelated large texts — e.g. `write_file` replacing a big\n// file wholesale), the diff degrades to a coarse replace (all removes,\n// then all adds) instead of allocating the table: a valid, just\n// non-minimal, diff — O(n+m) and bounded.\n//\n// Trailing newline policy: a string ending with `\\n` produces a trailing\n// empty `\"\"` line after split. We trim it so a single-line edit doesn't\n// emit a phantom empty `+` row below the actual content.\n// ---------------------------------------------------------------------------\n\n/**\n * LCS table cell budget shared by the line- and token-level diffs. 4M\n * cells ≈ low tens of MB of `number[]` rows — imperceptible — while\n * anything needing more (multi-thousand-line change cores) wouldn't\n * produce a human-readable minimal diff anyway.\n */\nconst LCS_CELL_BUDGET = 4_000_000\n\nexport type DiffOp = 'context' | 'add' | 'remove'\n\nexport interface DiffLine {\n op: DiffOp\n text: string\n}\n\nexport function computeLineDiff(oldString: string, newString: string): DiffLine[] {\n const oldLines = splitLines(oldString)\n const newLines = splitLines(newString)\n\n // Trim the common prefix/suffix — the LCS table only ever sees the\n // changed core. Exactness is preserved: identical flanking lines are\n // context in ANY minimal diff.\n let lo = 0\n while (lo < oldLines.length && lo < newLines.length && oldLines[lo] === newLines[lo])\n lo++\n let oldHi = oldLines.length\n let newHi = newLines.length\n while (oldHi > lo && newHi > lo && oldLines[oldHi - 1] === newLines[newHi - 1]) {\n oldHi--\n newHi--\n }\n\n const out: DiffLine[] = []\n for (let k = 0; k < lo; k++)\n out.push({ op: 'context', text: oldLines[k] })\n\n const n = oldHi - lo\n const m = newHi - lo\n if ((n + 1) * (m + 1) > LCS_CELL_BUDGET) {\n // Core too large for a minimal diff — coarse replace, same\n // remove-block-then-add-block ordering the LCS walk produces for\n // fully-changed regions.\n for (let k = lo; k < oldHi; k++)\n out.push({ op: 'remove', text: oldLines[k] })\n for (let k = lo; k < newHi; k++)\n out.push({ op: 'add', text: newLines[k] })\n }\n else if (n > 0 || m > 0) {\n appendLcsDiff(out, oldLines, newLines, lo, oldHi, newHi)\n }\n\n for (let k = oldHi; k < oldLines.length; k++)\n out.push({ op: 'context', text: oldLines[k] })\n return out\n}\n\n/**\n * The classic LCS table + reverse walk over `old[lo..oldHi) ×\n * new[lo..newHi)`, appending ops to `out` in forward order. Diagonals at\n * equal lines → context; otherwise step into the higher of (up, left)\n * and emit remove/add respectively. Ties break so adjacent remove/add\n * pairs stay grouped (the intra-line highlighter pairs them up).\n */\nfunction appendLcsDiff(\n out: DiffLine[],\n oldLines: readonly string[],\n newLines: readonly string[],\n lo: number,\n oldHi: number,\n newHi: number,\n): void {\n const n = oldHi - lo\n const m = newHi - lo\n const lcs: number[][] = Array.from({ length: n + 1 }, () => Array.from<number>({ length: m + 1 }).fill(0))\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < m; j++) {\n lcs[i + 1][j + 1] = oldLines[lo + i] === newLines[lo + j]\n ? lcs[i][j] + 1\n : Math.max(lcs[i][j + 1], lcs[i + 1][j])\n }\n }\n\n const core: DiffLine[] = []\n let i = n\n let j = m\n while (i > 0 || j > 0) {\n if (i > 0 && j > 0 && oldLines[lo + i - 1] === newLines[lo + j - 1]) {\n core.push({ op: 'context', text: oldLines[lo + i - 1] })\n i--\n j--\n continue\n }\n if (j > 0 && (i === 0 || lcs[i][j - 1] >= lcs[i - 1][j])) {\n core.push({ op: 'add', text: newLines[lo + j - 1] })\n j--\n continue\n }\n core.push({ op: 'remove', text: oldLines[lo + i - 1] })\n i--\n }\n core.reverse()\n out.push(...core)\n}\n\n/**\n * Split a string into lines preserving empty lines but dropping the\n * implicit trailing `\"\"` produced by a final `\\n`. Exported only for\n * its tests — callers should use `computeLineDiff`.\n */\nexport function splitLines(s: string): string[] {\n if (s === '')\n return []\n const parts = s.split('\\n')\n if (parts[parts.length - 1] === '')\n parts.pop()\n return parts\n}\n\n// ---------------------------------------------------------------------------\n// Inline diff — word-level segments for a paired (remove, add) row.\n//\n// Same LCS recipe over **word tokens** so the renderer can bold the\n// genuinely-different runs inside each line. Tokenization keeps runs of\n// word characters + non-word characters as separate units so a rename\n// like `oldName → newName` highlights the single token rather than the\n// whole word boundary.\n//\n// Returns parallel segment arrays for the old and new lines — same\n// segment order, `changed: true` on the diverging tokens. Renderer\n// renders unchanged tokens in the line's base fg + changed tokens in\n// a brighter accent (with the row's bg still tinted).\n// ---------------------------------------------------------------------------\n\nexport interface InlineSegment {\n text: string\n changed: boolean\n}\n\nexport interface InlineDiff {\n oldSegments: InlineSegment[]\n newSegments: InlineSegment[]\n}\n\nexport function computeInlineDiff(oldLine: string, newLine: string): InlineDiff {\n const oldTokens = tokenize(oldLine)\n const newTokens = tokenize(newLine)\n\n const n = oldTokens.length\n const m = newTokens.length\n // Same cell budget as the line diff — a paired remove/add of two\n // megabyte-scale single lines (minified bundles) would otherwise\n // allocate a token² table. Degrade to \"whole line changed\": correct,\n // just unhighlighted.\n if ((n + 1) * (m + 1) > LCS_CELL_BUDGET) {\n return {\n oldSegments: oldLine === '' ? [] : [{ text: oldLine, changed: true }],\n newSegments: newLine === '' ? [] : [{ text: newLine, changed: true }],\n }\n }\n const lcs: number[][] = Array.from({ length: n + 1 }, () => Array.from<number>({ length: m + 1 }).fill(0))\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < m; j++) {\n lcs[i + 1][j + 1] = oldTokens[i] === newTokens[j]\n ? lcs[i][j] + 1\n : Math.max(lcs[i][j + 1], lcs[i + 1][j])\n }\n }\n\n // Walk table — same as computeLineDiff but emit segments tagged\n // changed/unchanged into the side they belong to.\n const oldSegments: InlineSegment[] = []\n const newSegments: InlineSegment[] = []\n let i = n\n let j = m\n while (i > 0 || j > 0) {\n if (i > 0 && j > 0 && oldTokens[i - 1] === newTokens[j - 1]) {\n pushSegment(oldSegments, { text: oldTokens[i - 1], changed: false })\n pushSegment(newSegments, { text: newTokens[j - 1], changed: false })\n i--\n j--\n continue\n }\n if (j > 0 && (i === 0 || lcs[i][j - 1] >= lcs[i - 1][j])) {\n pushSegment(newSegments, { text: newTokens[j - 1], changed: true })\n j--\n continue\n }\n pushSegment(oldSegments, { text: oldTokens[i - 1], changed: true })\n i--\n }\n oldSegments.reverse()\n newSegments.reverse()\n return { oldSegments, newSegments }\n}\n\n/**\n * Coalesce adjacent same-state segments so the renderer emits one\n * `<span>` per run instead of one per token — keeps the React tree\n * shallow on dense lines without changing the visual output.\n *\n * Walking direction is reverse (we push during the reverse walk, then\n * the caller reverses the array), so we coalesce against the *tail*.\n */\nfunction pushSegment(buf: InlineSegment[], seg: InlineSegment): void {\n const tail = buf[buf.length - 1]\n if (tail && tail.changed === seg.changed)\n tail.text = seg.text + tail.text\n else\n buf.push(seg)\n}\n\n/**\n * Tokenize on word / non-word boundaries. Each run of `\\w+` is one\n * token; each run of `\\W+` (whitespace, punctuation) is another. This\n * gives the right granularity for renames (`oldName` → `newName`) and\n * for symbol swaps (`+ → -`) without exploding into per-char segments.\n *\n * Exported only for its tests.\n */\nexport function tokenize(s: string): string[] {\n if (s === '')\n return []\n const out: string[] = []\n // Greedy: alternating word / non-word runs. Avoids per-char tokens\n // which would inflate the LCS table on long lines.\n const re = /\\w+|\\W+/g\n for (const match of s.matchAll(re))\n out.push(match[0])\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Unified diff serialization — feeds OpenTUI's native `<diff>` renderable.\n//\n// `<diff>` parses standard unified diff syntax (`--- a/path`, `+++ b/path`,\n// `@@ -l,n +l,m @@`, then `[ +-]<line>` rows) and handles per-language\n// syntax highlighting + bg coloring + wrap. We build the string from our\n// `EditPayload` and let the renderable do the rest.\n//\n// Line numbers in the chunk header are SYNTHETIC. `edit` only carries an\n// `old_string` snippet (no file position), `multi_edit` sequential edits\n// invalidate each other's positions, and `write_file` always starts at\n// line 1. Synthetic `@@ -1,N +1,M @@` is correct enough for the visual\n// gutter; users read the path in the header for context.\n//\n// New-file convention: when `oldString === ''` we emit `--- /dev/null`\n// and `@@ -0,0 +1,n @@`, matching `git diff` for newly added files.\n// ---------------------------------------------------------------------------\n\n/**\n * Apply the payload's hunks against `priorContent` and return the\n * resulting file body. Mirrors the agent's tool-side semantics:\n * - `replaceAll === true` → `String.replaceAll`\n * - otherwise → first-occurrence `String.replace`\n *\n * Hunks are applied in order — a `multi_edit` later hunk operates on\n * the output of the earlier ones, just like the actual tool.\n */\nexport function applyEditPayload(payload: EditPayload, priorContent: string): string {\n let out = priorContent\n for (const hunk of payload.hunks) {\n out = hunk.replaceAll\n ? out.replaceAll(hunk.oldString, hunk.newString)\n : out.replace(hunk.oldString, hunk.newString)\n }\n return out\n}\n\n/**\n * Like `buildUnifiedDiff` but operating against the full file content\n * so the diff carries *real* file line numbers and configurable\n * surrounding context.\n *\n * Strategy:\n * 1. Apply the payload to `priorContent` → `newContent`.\n * 2. Run `computeLineDiff` over the whole file.\n * 3. Group non-context ops into hunks, padding each with up to\n * `contextLines` of context above and below. Adjacent hunks\n * whose context regions touch are merged so we don't emit two\n * `@@` headers separated by zero context lines.\n *\n * The output line numbers in the `@@` header are 1-based and reflect\n * the change's position in the actual file — what the user expects\n * when reading a diff alongside their editor.\n *\n * For `write_file` creating a new file (priorContent === ''), this\n * falls back to the same `--- /dev/null` convention as\n * `buildUnifiedDiff`.\n */\nexport function buildContextualDiff(\n payload: EditPayload,\n priorContent: string,\n contextLines = 3,\n): string {\n const newContent = applyEditPayload(payload, priorContent)\n const isNewFile = priorContent === ''\n const ops = computeLineDiff(priorContent, newContent)\n\n // Pre-compute 1-based file line numbers for each op. `oldLine[i]` is\n // the original-file line `ops[i]` corresponds to (for context /\n // remove ops; undefined for adds since they don't exist in the old).\n // Same for `newLine[i]`. Add-only and remove-only ops still need a\n // base anchor for the hunk header, which we read off the *next*\n // context/anchor line — captured by tracking running counters.\n const oldLineFor: number[] = []\n const newLineFor: number[] = []\n let ol = 1\n let nl = 1\n for (const op of ops) {\n oldLineFor.push(ol)\n newLineFor.push(nl)\n if (op.op !== 'add')\n ol++\n if (op.op !== 'remove')\n nl++\n }\n\n // Group indices of change ops into hunks with `contextLines` padding.\n // Each entry: `[startIdx, endIdx]` inclusive into `ops`.\n const hunks: Array<[number, number]> = []\n for (let i = 0; i < ops.length; i++) {\n if (ops[i].op === 'context')\n continue\n const start = Math.max(0, i - contextLines)\n const end = Math.min(ops.length - 1, i + contextLines)\n const last = hunks[hunks.length - 1]\n if (last && start <= last[1] + 1)\n last[1] = Math.max(last[1], end)\n else\n hunks.push([start, end])\n }\n\n // No-op edit (e.g. `edit` with old_string === new_string) → empty diff.\n if (hunks.length === 0)\n return ''\n\n const parts: string[] = []\n parts.push(isNewFile ? '--- /dev/null' : `--- a/${payload.path}`)\n parts.push(`+++ b/${payload.path}`)\n\n for (const [start, end] of hunks) {\n const slice = ops.slice(start, end + 1)\n const oldCount = slice.filter(l => l.op !== 'add').length\n const newCount = slice.filter(l => l.op !== 'remove').length\n // For hunks that contain only adds (oldCount === 0), git emits the\n // line *before* the insertion, with count 0. We replicate that by\n // using `oldLineFor[start] - 1` clamped at 0.\n const oldStart = oldCount === 0\n ? Math.max(0, oldLineFor[start] - 1)\n : oldLineFor[start]\n const newStart = newCount === 0\n ? Math.max(0, newLineFor[start] - 1)\n : newLineFor[start]\n parts.push(`@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`)\n for (const line of slice) {\n const prefix = line.op === 'add' ? '+' : line.op === 'remove' ? '-' : ' '\n parts.push(`${prefix}${line.text}`)\n }\n }\n return `${parts.join('\\n')}\\n`\n}\n\n// ---------------------------------------------------------------------------\n// summarizeEditPayload — compact-mode digest of an edit call.\n//\n// Produces per-hunk stats + a one-line preview suitable for the\n// transcript's compact diff view (`Settings.editDiffDisplay === 'compact'`).\n// Uses `priorContent` when available so each summary entry carries the\n// real file line number; falls back to per-hunk LCS over the snippet\n// pair when priorContent is absent (historical replay).\n//\n// Multi-file safety: this only summarizes the payload it's handed; the\n// caller is responsible for separating per-file payloads.\n// ---------------------------------------------------------------------------\n\nexport interface EditHunkSummary {\n /** 1-based line number in the new file where the change starts; undefined when unknown (no priorContent). */\n line?: number\n /** Number of lines added in this hunk. */\n added: number\n /** Number of lines removed in this hunk. */\n removed: number\n /** First removed line preview (trimmed, may be empty for pure additions). */\n firstOld?: string\n /** First added line preview (trimmed, may be empty for pure deletions). */\n firstNew?: string\n}\n\nexport interface EditSummary {\n totalAdded: number\n totalRemoved: number\n hunks: EditHunkSummary[]\n}\n\n/**\n * Build a per-hunk digest used by the compact diff view.\n *\n * Strategy:\n * - When `priorContent` is present and the payload describes a real\n * file transformation, compute the contextual diff once, then walk\n * the LCS ops splitting at runs of `add` / `remove` to anchor each\n * summary entry to the **real** file line. This guarantees the\n * summary's `L<n>` matches what the user sees in their editor.\n * - Otherwise, fall back to per-hunk LCS over the (oldString,\n * newString) snippet pair. Line numbers are absent because the\n * snippet has no file position.\n */\nexport function summarizeEditPayload(payload: EditPayload): EditSummary {\n const prior = payload.priorContent\n if (prior !== undefined) {\n const newContent = applyEditPayload(payload, prior)\n const ops = computeLineDiff(prior, newContent)\n return summarizeOpsByHunk(ops)\n }\n\n // No prior content — diff each (oldString, newString) snippet pair\n // in isolation. Line numbers can't be derived; we still get\n // meaningful +/− counts and a first-line preview.\n const hunks: EditHunkSummary[] = []\n let totalAdded = 0\n let totalRemoved = 0\n for (const hunk of payload.hunks) {\n const ops = computeLineDiff(hunk.oldString, hunk.newString)\n let added = 0\n let removed = 0\n let firstOld: string | undefined\n let firstNew: string | undefined\n for (const op of ops) {\n if (op.op === 'add') {\n added++\n if (firstNew === undefined)\n firstNew = op.text\n }\n else if (op.op === 'remove') {\n removed++\n if (firstOld === undefined)\n firstOld = op.text\n }\n }\n totalAdded += added\n totalRemoved += removed\n hunks.push({\n added,\n removed,\n ...(firstOld !== undefined ? { firstOld } : {}),\n ...(firstNew !== undefined ? { firstNew } : {}),\n })\n }\n return { totalAdded, totalRemoved, hunks }\n}\n\n/**\n * Walk an LCS op stream and emit one summary entry per *run* of\n * non-context ops, with the new-file line number where each run\n * starts. Adjacent add/remove ops collapse into the same entry —\n * matches git's hunk grouping at zero context.\n */\nfunction summarizeOpsByHunk(ops: readonly DiffLine[]): EditSummary {\n const hunks: EditHunkSummary[] = []\n let totalAdded = 0\n let totalRemoved = 0\n let nl = 1\n let i = 0\n while (i < ops.length) {\n const op = ops[i]\n if (op.op === 'context') {\n nl++\n i++\n continue\n }\n const runStartLine = nl\n let added = 0\n let removed = 0\n let firstOld: string | undefined\n let firstNew: string | undefined\n while (i < ops.length && ops[i].op !== 'context') {\n const cur = ops[i]\n if (cur.op === 'add') {\n added++\n if (firstNew === undefined)\n firstNew = cur.text\n nl++\n }\n else {\n removed++\n if (firstOld === undefined)\n firstOld = cur.text\n }\n i++\n }\n totalAdded += added\n totalRemoved += removed\n hunks.push({\n line: runStartLine,\n added,\n removed,\n ...(firstOld !== undefined ? { firstOld } : {}),\n ...(firstNew !== undefined ? { firstNew } : {}),\n })\n }\n return { totalAdded, totalRemoved, hunks }\n}\n\n// ---------------------------------------------------------------------------\n// previewEditPayload — model-faithful preview that mirrors the tool body's\n// lenient resolver (curly-quote recovery, line-number-prefix stripping,\n// model-side `<n>`→`<name>` desanitize). The naive `applyEditPayload`\n// only does exact `String.replace`, which renders a blank diff whenever\n// the model emits an `old_string` the tool body would still recover via\n// `resolveOldString`. The modal uses this so what the user previews\n// matches what the tool would actually apply.\n//\n// Returns per-hunk `resolution` metadata so the modal can:\n// - mark hunks the tool wouldn't find (`resolved: false`) with a\n// warning glyph in the list,\n// - render an explanatory fallback panel instead of an empty diff box.\n// ---------------------------------------------------------------------------\n\nexport interface HunkResolution {\n /**\n * True when the tool body would find this hunk's `old_string` AND apply\n * it without ambiguity. False when `resolveOldString` returned null OR\n * the match was ambiguous (multiple occurrences and `replace_all` off).\n */\n resolved: boolean\n /** Path the resolver took — `'exact'` when no recovery was needed. */\n via?: ResolvedMatch['via']\n /** Match count in the running content for the hunk. */\n occurrences?: number\n /** True when the resolver found >1 match without `replace_all`. */\n ambiguous?: boolean\n}\n\nexport interface PreviewResult {\n /** Full unified diff of the (resolvable) hunks against `priorContent`. */\n diffText: string\n /** 1:1 with `payload.hunks`. */\n resolution: HunkResolution[]\n /**\n * Per-hunk isolated diff text rendered against the cumulative content\n * after applying all earlier resolved hunks. Useful for the modal's\n * focused-hunk view so hunk #N's preview reflects the state hunks\n * 1..N-1 will leave the file in (same as the tool's order).\n */\n perHunkDiff: string[]\n /**\n * Resolved hunks with `oldString` rewritten to the haystack's actual\n * bytes and `newString` re-styled to preserve curly-quote typography\n * / line-prefix conventions. Pass this to `buildContextualDiff` to\n * paint the unified diff.\n */\n resolvedPayload: EditPayload\n}\n\nexport function previewEditPayload(\n payload: EditPayload,\n priorContent: string,\n contextLines = 3,\n): PreviewResult {\n const resolution: HunkResolution[] = []\n const resolvedHunks: EditHunk[] = []\n const perHunkDiff: string[] = []\n let running = priorContent\n\n for (const hunk of payload.hunks) {\n // `write_file` synthesizes a hunk with `oldString = priorContent`,\n // which is always a perfect match by construction.\n if (hunk.oldString === '' || hunk.oldString === running) {\n resolution.push({ resolved: true, via: 'exact', occurrences: 1 })\n resolvedHunks.push(hunk)\n perHunkDiff.push(buildContextualDiff(\n { ...payload, hunks: [hunk] },\n running,\n contextLines,\n ))\n running = hunk.newString\n continue\n }\n\n const match = resolveOldString(running, hunk.oldString)\n if (!match) {\n resolution.push({ resolved: false })\n resolvedHunks.push(hunk)\n perHunkDiff.push('')\n continue\n }\n\n const ambiguous = match.occurrences > 1 && !hunk.replaceAll\n const styledNew = styleReplacementForVia(hunk.newString, match.via, match.actual)\n const resolvedHunk: EditHunk = {\n oldString: match.actual,\n newString: styledNew,\n ...(hunk.replaceAll ? { replaceAll: true } : {}),\n }\n resolution.push({\n resolved: !ambiguous,\n via: match.via,\n occurrences: match.occurrences,\n ...(ambiguous ? { ambiguous: true } : {}),\n })\n resolvedHunks.push(resolvedHunk)\n // Ambiguous matches paint nothing — the tool would reject the call;\n // the modal renders the `UnresolvedHunkPanel` instead so the user\n // can see what went wrong rather than a misleading first-occurrence\n // preview.\n perHunkDiff.push(ambiguous\n ? ''\n : buildContextualDiff(\n { ...payload, hunks: [resolvedHunk] },\n running,\n contextLines,\n ))\n if (!ambiguous) {\n running = hunk.replaceAll\n ? running.replaceAll(match.actual, styledNew)\n : running.replace(match.actual, styledNew)\n }\n }\n\n const resolvedPayload: EditPayload = { ...payload, hunks: resolvedHunks }\n // Whole-payload diff renders only the hunks the tool would actually\n // apply. Ambiguous + unresolved hunks are surfaced via `resolution`\n // instead — letting them through here would paint misleading\n // first-occurrence diffs.\n const applicableHunks = resolvedHunks.filter((_, i) => resolution[i].resolved)\n const diffText = applicableHunks.length === 0\n ? ''\n : buildContextualDiff(\n { ...payload, hunks: applicableHunks },\n priorContent,\n contextLines,\n )\n\n return { diffText, resolution, perHunkDiff, resolvedPayload }\n}\n\n// ---------------------------------------------------------------------------\n// Render clip — bound a unified-diff string before it reaches the native\n// <diff> renderable. The renderable materializes row buffers, word-wrap\n// layout, and (when a grammar matches) tree-sitter highlight state for\n// EVERY line it is handed — a scrollbox around it only bounds the\n// VIEWPORT, not the allocation. A wholesale rewrite of a 76k-line file\n// produces a ~150k-line diff that measured >1 GB of native RSS for a\n// single transcript row, and the kernel SIGKILLs the TUI under that\n// pressure (macOS jetsam) before any JS error can surface.\n//\n// Line- AND size-capped: minified single-line files blow the size side\n// long before the line side, and a SINGLE line at or above the budget is\n// hard-truncated (not admitted whole) — otherwise a `-<20MB minified line>`\n// row would hand the renderable one line whose word-wrap layout is\n// hundreds of thousands of wrapped rows, re-creating the blowup this\n// exists to prevent. Clipping is display-only — the tool applied (or will\n// apply) the full change regardless — so callers render the returned\n// `hiddenLines` as a footer so the reader knows the tail exists.\n//\n// The size budget counts UTF-16 CODE UNITS (`String.length`), not bytes:\n// this module is re-exported through `chat/pure` (no-node contract), so\n// `Buffer.byteLength` is unavailable and per-line `TextEncoder` encoding\n// would allocate on the hot render path. Code units under-count multi-byte\n// text by at most 3× (UTF-8) / equal (UTF-16 BMP), so the real ceiling is\n// ~3× the budget — still bounded, which is all this guard needs.\n// ---------------------------------------------------------------------------\n\nexport interface ClippedDiff {\n /** The (possibly clipped) diff text. Original string identity when nothing was cut. */\n text: string\n /** Diff lines dropped from the tail. `0` = complete. */\n hiddenLines: number\n /** Total diff lines (excluding the trailing-newline phantom). */\n totalLines: number\n}\n\n/** Default line budget for transcript diff rows. */\nexport const DIFF_RENDER_MAX_LINES = 600\n/** Default size budget (UTF-16 code units) for transcript diff rows. */\nexport const DIFF_RENDER_MAX_BYTES = 512 * 1024\n/** Marker appended to a line hard-truncated mid-content by the size cap. */\nconst CLIP_LINE_MARKER = ' …⟨line clipped⟩'\n\n/**\n * Truncate `line` so it fits `budget` code units including the marker,\n * without splitting a UTF-16 surrogate pair. Returns the line unchanged\n * when it already fits.\n */\nfunction clipLine(line: string, budget: number): string {\n if (line.length <= budget)\n return line\n let end = Math.max(0, budget - CLIP_LINE_MARKER.length)\n // Don't slice between a high/low surrogate — step back off a lone high.\n const code = line.charCodeAt(end - 1)\n if (end > 0 && code >= 0xD800 && code <= 0xDBFF)\n end--\n return line.slice(0, end) + CLIP_LINE_MARKER\n}\n\nexport function clipDiffForRender(\n diff: string,\n maxLines: number = DIFF_RENDER_MAX_LINES,\n maxBytes: number = DIFF_RENDER_MAX_BYTES,\n): ClippedDiff {\n const lines = diff.split('\\n')\n // The diff builders always terminate with `\\n`, so `split` yields a\n // phantom empty final element — don't count it in the total the footer\n // reports (mirrors computeLineDiff's trailing-newline policy).\n const totalLines = lines.length > 0 && lines[lines.length - 1] === ''\n ? lines.length - 1\n : lines.length\n if (totalLines <= maxLines && diff.length <= maxBytes)\n return { text: diff, hiddenLines: 0, totalLines }\n\n const kept: string[] = []\n let used = 0\n for (let i = 0; i < totalLines; i++) {\n if (kept.length >= maxLines)\n break\n const line = lines[i]\n const cost = line.length + 1 // '\\n' rejoin\n if (used + cost > maxBytes) {\n // First line already over budget → hard-truncate it so the\n // renderable never sees an oversized single line. Any later line\n // that would overflow just ends the clip (the tail is hidden).\n if (kept.length === 0)\n kept.push(clipLine(line, maxBytes))\n break\n }\n kept.push(line)\n used += cost\n }\n return { text: kept.join('\\n'), hiddenLines: totalLines - kept.length, totalLines }\n}\n\nexport function buildUnifiedDiff(payload: EditPayload): string {\n const parts: string[] = []\n const isNewFile = payload.tool === 'write_file' && payload.hunks[0]?.oldString === ''\n // File header. Both `---` and `+++` lines are mandatory per the parser\n // (see `Missing \"--- ...\"` throw in the upstream parseDiff).\n parts.push(isNewFile ? `--- /dev/null` : `--- a/${payload.path}`)\n parts.push(`+++ b/${payload.path}`)\n\n for (const hunk of payload.hunks) {\n const lines = computeLineDiff(hunk.oldString, hunk.newString)\n const oldCount = lines.filter(l => l.op !== 'add').length\n const newCount = lines.filter(l => l.op !== 'remove').length\n const oldStart = oldCount === 0 ? 0 : 1\n const newStart = newCount === 0 ? 0 : 1\n parts.push(`@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`)\n for (const line of lines) {\n const prefix = line.op === 'add' ? '+' : line.op === 'remove' ? '-' : ' '\n parts.push(`${prefix}${line.text}`)\n }\n }\n return `${parts.join('\\n')}\\n`\n}\n\n// ---------------------------------------------------------------------------\n// File extension → tree-sitter filetype name.\n//\n// Names must match what `setupTreeSitter` registered (see\n// `src/tui/tree-sitter.ts`'s `EXTRA_PARSERS` / `LOCAL_PARSERS`) plus what\n// OpenTUI ships out of the box (`typescript`, `javascript`, `markdown`,\n// `zig`). JSX/TSX are registered as `javascriptreact`/`typescriptreact`\n// aliases of the JS/TS parsers, not `jsx`/`tsx` — passing the fence-style\n// name to the `<diff>` renderable's `filetype` prop silently misses (falls\n// back to plain text, no error). Unknown extensions return `undefined`.\n// ---------------------------------------------------------------------------\n\nconst FILETYPE_BY_EXT: Readonly<Record<string, string>> = {\n ts: 'typescript',\n mts: 'typescript',\n cts: 'typescript',\n tsx: 'typescriptreact',\n js: 'javascript',\n mjs: 'javascript',\n cjs: 'javascript',\n jsx: 'javascriptreact',\n py: 'python',\n pyi: 'python',\n rs: 'rust',\n go: 'go',\n json: 'json',\n jsonc: 'json',\n sh: 'bash',\n bash: 'bash',\n zsh: 'bash',\n yaml: 'yaml',\n yml: 'yaml',\n html: 'html',\n htm: 'html',\n css: 'css',\n md: 'markdown',\n markdown: 'markdown',\n zig: 'zig',\n lua: 'lua',\n toml: 'toml',\n sql: 'sql',\n}\n\nexport function filetypeFromPath(path: string): string | undefined {\n // Strip query / fragment so `path?ts=…` style references still match.\n const cleaned = path.split(/[?#]/, 1)[0]\n const lastDot = cleaned.lastIndexOf('.')\n if (lastDot === -1 || lastDot === cleaned.length - 1)\n return undefined\n const ext = cleaned.slice(lastDot + 1).toLowerCase()\n return FILETYPE_BY_EXT[ext]\n}\n","// ---------------------------------------------------------------------------\n// Transcript visibility + select-turn navigation — pure data rules consumed\n// by any renderer that walks a `StreamEvent[]`. They encode the user-facing\n// semantics (settings + edit-tool error prefixes) rather than any\n// presentation primitive, and import nothing node-bound — so they live in\n// their own leaf module that a browser-context renderer can import via\n// `zidane/chat/pure`. `store.ts` re-exports them for back-compat; the TUI\n// re-exports them via `zidane/tui`.\n// ---------------------------------------------------------------------------\n\nimport type { Settings, StreamEvent } from './types'\nimport { searchHighlightRanges } from './history-search'\n\n/** Tools whose `tool-result` event is suppressed when `showEditDiffs` is on. */\nexport const EDIT_TOOL_NAMES: ReadonlySet<string> = new Set(['edit', 'multi_edit', 'write_file'])\n\n/**\n * Keep turn-selection mode alive after deleting its active row. Prefer the\n * row that slides into the deleted index; at the tail, select the new last\n * row. Returns null only when no selectable rows survive.\n */\nexport function selectionAfterTurnRemoval(\n before: readonly string[],\n removedId: string,\n after: readonly string[],\n): string | null {\n if (after.includes(removedId))\n return removedId\n if (after.length === 0)\n return null\n const index = before.indexOf(removedId)\n return after[Math.min(Math.max(0, index), after.length - 1)] ?? null\n}\n\n/**\n * Recognize a tool-result body as carrying NON-success information so the\n * renderer doesn't suppress it under `showEditDiffs`. Three categories:\n *\n * - `edit` → \"Edit error: …\"\n * - `write_file` permission errors wrapped by the loop → \"Tool failed: …\"\n * - `multi_edit` → legacy single-line error `multi_edit error: …`, OR\n * a result carrying an `<edit-outcomes>…</edit-outcomes>` annotation\n * block. The TUI only appends the annotation when at least one hunk\n * was NOT applied, so its mere presence is the signal — the result\n * body needs to stay visible next to the diff so the user can read\n * denial / skip / failure reasons longer than the per-hunk badge.\n * - Fully-denied gate emit (`[fully denied] <edit-outcomes>…`) likewise\n * stays visible.\n *\n * Exported for unit-testability of the visibility matrix.\n */\nexport function isEditErrorResult(text: string): boolean {\n if (text.startsWith('Edit error:'))\n return true\n if (text.startsWith('Tool failed:'))\n return true\n if (text.startsWith('multi_edit error:'))\n return true\n if (text.startsWith('[fully denied]'))\n return true\n // The annotation block only appears when at least one hunk was NOT\n // applied (see `src/tui/app.tsx` `annotateEditResult`), so a present\n // sentinel pair signals \"denial / skip / failure attached — surface\n // the result body so reasons are readable next to the diff badges\".\n if (text.includes('\\n<edit-outcomes>\\n') || text.startsWith('<edit-outcomes>\\n'))\n return true\n return false\n}\n\n/**\n * `callId` prefix minted by the TUI's `!` bash mode (see `runBashCommand`\n * in `src/tui/app.tsx`). The prefix is the durable signal — it survives\n * persistence and replay — that a `shell` tool exchange was USER-initiated,\n * so renderers can keep it visible even when the tool-display settings\n * hide model-driven plumbing: the user typed the command and expects to\n * see it and what it printed.\n */\nexport const BASH_CALL_ID_PREFIX = 'bash_'\n\n/** Is this event a user-initiated `!` bash exchange (vs. a model-driven shell call)? */\nexport function isUserBashEvent(event: Pick<StreamEvent, 'tool' | 'callId'>): boolean {\n return event.tool === 'shell' && event.callId?.startsWith(BASH_CALL_ID_PREFIX) === true\n}\n\n/**\n * Prompt-history entries (↑/↓ cycling) from a transcript, in submit order:\n * every submitted prompt (`user-prompt` events, raw text) AND every `!` bash\n * command (its `tool` event, reconstructed as `!command` so a recalled entry\n * re-submits through the same bash path). Model-driven tool calls are\n * excluded — only what the user actually typed belongs in their history.\n * Works identically on live events and on `eventsFromTurns` replay, so bash\n * commands persist in the history across session reloads for free.\n */\nexport function promptHistoryFromEvents(events: readonly StreamEvent[]): string[] {\n const history: string[] = []\n for (const event of events) {\n // Skip synthetic echoes (command injected-prompt markers, context-note\n // `display` lines) — the user never typed them, so they must not\n // resurface via up-arrow recall.\n if (event.kind === 'user-prompt' && !event.synthetic)\n history.push(event.text)\n else if (event.kind === 'tool' && isUserBashEvent(event) && typeof event.input?.command === 'string')\n history.push(`!${event.input.command}`)\n }\n return history\n}\n\n/** Searchable text of one stream event — tool name, label, and body text. */\nexport function streamEventSearchText(event: StreamEvent): string {\n return [event.tool, event.label, event.text].filter(Boolean).join('\\n')\n}\n\nexport function isVisibleDuringSearch(event: StreamEvent, settings: Settings, query: string): boolean {\n if (isVisible(event, settings))\n return true\n // Search may reveal a matching top-level row that its normal preference\n // hides (thinking, tool results — including a subagent's final report).\n // Nested child output stays collapsed and signals through the visible\n // lifecycle parent instead.\n return (event.depth ?? 0) === 0\n && searchHighlightRanges(streamEventSearchText(event), query).length > 0\n}\n\n/**\n * Per-event visibility — filters honor user toggles and the\n * `hideSubagentOutput` setting. When subagent output is hidden:\n * - Child-agent events are filtered down to the `spawn-start` /\n * `spawn-end` markers so the user still sees \"🌱 working… 🌳 done\".\n * - The parent's `tool-result` for `spawn` is hidden too. Its body\n * duplicates `spawn-end`'s stats line *and* the parent's next\n * markdown turn; showing it again produces an extra\n * `┃ [sub-agent child-1] Completed …` block users just want gone.\n *\n * Renderer-agnostic — returns plain `boolean` so TUI / GUI consumers\n * can filter events identically.\n */\nexport function isVisible(event: StreamEvent, settings: Settings): boolean {\n if (settings.hideSubagentOutput) {\n if ((event.depth ?? 0) > 0)\n return event.kind === 'spawn-start' || event.kind === 'spawn-end'\n if (event.kind === 'tool-result' && event.tool === 'spawn')\n return false\n }\n // Suppress successful `tool-result`s for edit/multi_edit/write_file when\n // the diff renderer is on — the diff itself is the success indicator;\n // the `Edited path: N replacements.` line just adds noise. Error\n // results bypass the suppression so failures stay visible.\n if (\n settings.showEditDiffs\n && event.kind === 'tool-result'\n && event.tool\n && EDIT_TOOL_NAMES.has(event.tool)\n && !isEditErrorResult(event.text)\n ) {\n return false\n }\n switch (event.kind) {\n case 'thinking': return settings.showThinking\n // User-initiated `!` bash rows are never hidden — the user ran the\n // command to SEE it and its output; `toolCallDisplay` / `showToolResults`\n // gate model plumbing only. Without the `tool` exemption, hiding tool\n // calls would leave bash output floating with no sign of what ran.\n case 'tool': return settings.toolCallDisplay !== 'hidden' || isUserBashEvent(event)\n case 'tool-result': return settings.showToolResults || isUserBashEvent(event)\n default: return true\n }\n}\n\n/**\n * Build the `resultTurnId → owningAssistantTurnId` map used by the select-\n * turn mode to coalesce a tool-call's surrounding turns into ONE navigation\n * stop.\n *\n * Protocol shape: every `tool_call` block in an assistant turn is closed by\n * a matching `tool_result` block in the *next* user turn (the agent loop's\n * history validator depends on this). When the next user turn's only events\n * are `tool-result`s — i.e. it's pure plumbing for the prior assistant\n * turn — we map it back to that assistant turn here. The select-turn nav\n * index ({@link selectableTurnIds}) skips owned turns, and the renderer's\n * highlight gate ({@link isTurnHighlighted}) extends the selection accent\n * from the assistant turn to the events of any turn it owns. Net effect:\n *\n * - Navigation never lands the cursor on a result-only turn whose own\n * events may be hidden by `showToolResults: false` — the cursor\n * wouldn't be visible.\n * - Selecting an assistant turn highlights the call AND its result as\n * one unit, matching the user's mental model of \"one message\".\n *\n * Owner-lookup is conservative: result-only turns with no matching prior\n * assistant turn (orphaned — usually because the parent was deleted)\n * stay selectable so the user can act on them via the turn-details modal.\n *\n * Subagent (`childId` set) events are ignored — they live in a separate\n * conversation tree.\n */\nexport function turnSelectionOwnership(events: readonly StreamEvent[]): Map<string, string> {\n // Build per-turn event-kind summary in render order. We need:\n // - Whether a turn is \"result-only\" (every event is `tool-result`).\n // - The most recent previous turn that emitted a `tool` event (= the\n // candidate owner for the next result-only turn).\n const orderedTurnIds: string[] = []\n const summaryByTurn = new Map<string, { kinds: StreamEvent['kind'][], resultCallIds: string[] }>()\n const callOwner = new Map<string, string>()\n for (const e of events) {\n if (!e.turnId)\n continue\n if (e.childId)\n continue\n let summary = summaryByTurn.get(e.turnId)\n if (!summary) {\n orderedTurnIds.push(e.turnId)\n summary = { kinds: [], resultCallIds: [] }\n summaryByTurn.set(e.turnId, summary)\n }\n summary.kinds.push(e.kind)\n if (e.callId) {\n if (e.kind === 'tool')\n callOwner.set(e.callId, e.turnId)\n else if (e.kind === 'tool-result')\n summary.resultCallIds.push(e.callId)\n }\n }\n\n const ownership = new Map<string, string>()\n let lastToolEmitterTurnId: string | null = null\n for (const tid of orderedTurnIds) {\n const { kinds, resultCallIds } = summaryByTurn.get(tid)!\n const isResultOnly = kinds.length > 0 && kinds.every(k => k === 'tool-result')\n if (isResultOnly) {\n // Prefer the exact callId owner: in a FILTERED transcript (search) an\n // unrelated tool-emitting turn can sit between a result and its true\n // owner, so adjacency alone would coalesce onto the interloper.\n const exactOwner = resultCallIds\n .map(callId => callOwner.get(callId))\n .find(owner => owner !== undefined && owner !== tid)\n if (exactOwner)\n ownership.set(tid, exactOwner)\n else if (lastToolEmitterTurnId)\n ownership.set(tid, lastToolEmitterTurnId)\n // No owner found — leave the orphan selectable. Don't update\n // `lastToolEmitterTurnId` either (a result-only turn never emits\n // a `tool` event itself).\n continue\n }\n if (kinds.includes('tool'))\n lastToolEmitterTurnId = tid\n }\n return ownership\n}\n\n/**\n * Render-time check: should `event` paint with the selection accent?\n *\n * `true` when the event's own turn is selected, OR when the selected turn\n * `owns` the event's turn via {@link turnSelectionOwnership} (the call and\n * its tool-result rows highlight together). `false` when nothing is\n * selected or the relationship doesn't apply.\n *\n * Pure. Renderer-agnostic — the TUI's `<Transcript>` uses it; a GUI's\n * equivalent walks the same rule.\n */\nexport function isTurnHighlighted(\n event: Pick<StreamEvent, 'turnId'>,\n selectedTurnId: string | null,\n ownership: ReadonlyMap<string, string>,\n): boolean {\n if (selectedTurnId === null || !event.turnId)\n return false\n if (event.turnId === selectedTurnId)\n return true\n return ownership.get(event.turnId) === selectedTurnId\n || ownership.get(selectedTurnId) === event.turnId\n}\n\n/**\n * Deduplicated, in-order list of **parent-conversation** turn ids that appear\n * in a rendered transcript — the navigation index for the TUI's select-turn\n * mode. Three classes of turns are deliberately skipped:\n *\n * - **Subagent turns** (`childId` set). Nested execution detail; the\n * user's mental model of a \"message\" is the conversational exchange,\n * not each spawn turn. Also filtered out by `isVisible` under\n * `hideSubagentOutput: true` — selecting them would highlight nothing.\n * - **Result-only turns** — see {@link turnSelectionOwnership}. These get\n * coalesced into the assistant turn that emitted their tool_calls.\n * - **Settings-hidden turns** (when `settings` is supplied). A turn whose\n * every event fails {@link isVisible} would render no rows — landing\n * the cursor there hides it from the user entirely. The check is opt-\n * in so SDK callers without a Settings object keep the legacy\n * \"everything visible\" behavior.\n *\n * Synthetic events (separator, spawn-start, spawn-end) have no `turnId` and\n * are skipped naturally.\n */\nexport function selectableTurnIds(\n events: readonly StreamEvent[],\n settings?: Settings,\n visible?: (event: StreamEvent) => boolean,\n): string[] {\n const ownership = turnSelectionOwnership(events)\n\n // Per-turn visible event count (only computed when settings is supplied).\n // We need this to drop turns whose every event is filtered out by user\n // toggles — otherwise `↑/↓` could land the cursor on a row that paints\n // nothing visible.\n const visibleCount = settings ? new Map<string, number>() : null\n if (settings && visibleCount) {\n for (const e of events) {\n if (!e.turnId || e.childId)\n continue\n if (!(visible ? visible(e) : isVisible(e, settings)))\n continue\n visibleCount.set(e.turnId, (visibleCount.get(e.turnId) ?? 0) + 1)\n }\n }\n\n const seen = new Set<string>()\n const ordered: string[] = []\n for (const e of events) {\n if (!e.turnId)\n continue\n if (e.childId)\n continue\n if (seen.has(e.turnId))\n continue\n if (ownership.has(e.turnId))\n continue // result-only — owned by an earlier assistant turn\n if (visibleCount && (visibleCount.get(e.turnId) ?? 0) === 0)\n continue // every event of this turn is hidden by user settings\n seen.add(e.turnId)\n ordered.push(e.turnId)\n }\n return ordered\n}\n","// ---------------------------------------------------------------------------\n// HSL color gradient helpers — shared between the Crush throbber (cycling\n// per-frame paint) and the title overlay (static per-character paint).\n//\n// Renderer-agnostic on purpose: a future GUI shell wants the same ramp\n// math against the same hex strings the theme palette already stores, so\n// this lives in `zidane/chat` next to the theme definition rather than\n// inside the TUI's OpenTUI layer.\n//\n// We blend in HSL with shortest-path hue interpolation rather than\n// straight sRGB lerp because saturated palette pairs (e.g. Charple →\n// Dolly = purple → magenta) would muddy through grey when interpolated\n// componentwise in RGB. HSL keeps the path along the hue ring, so the\n// gradient stays vivid.\n// ---------------------------------------------------------------------------\n\n/** Parse `#rrggbb` (case-insensitive) into `[r, g, b]` 0–255 integers. */\nfunction parseHex(hex: string): [number, number, number] {\n const h = hex.replace('#', '')\n return [\n Number.parseInt(h.slice(0, 2), 16),\n Number.parseInt(h.slice(2, 4), 16),\n Number.parseInt(h.slice(4, 6), 16),\n ]\n}\n\n/** Convert sRGB 0–255 → HSL 0–1. */\nfunction rgbToHsl(r: number, g: number, b: number): [number, number, number] {\n r /= 255\n g /= 255\n b /= 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n const l = (max + min) / 2\n if (max === min)\n return [0, 0, l]\n const d = max - min\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\n let h: number\n if (max === r)\n h = (g - b) / d + (g < b ? 6 : 0)\n else if (max === g)\n h = (b - r) / d + 2\n else\n h = (r - g) / d + 4\n return [h / 6, s, l]\n}\n\n/** Convert HSL 0–1 → sRGB 0–255. Standard piecewise formula. */\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n if (s === 0)\n return [l * 255, l * 255, l * 255]\n const hue2rgb = (p: number, q: number, t: number) => {\n if (t < 0)\n t += 1\n if (t > 1)\n t -= 1\n if (t < 1 / 6)\n return p + (q - p) * 6 * t\n if (t < 1 / 2)\n return q\n if (t < 2 / 3)\n return p + (q - p) * (2 / 3 - t) * 6\n return p\n }\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s\n const p = 2 * l - q\n return [\n hue2rgb(p, q, h + 1 / 3) * 255,\n hue2rgb(p, q, h) * 255,\n hue2rgb(p, q, h - 1 / 3) * 255,\n ]\n}\n\nfunction toHex(rgb: readonly [number, number, number]): string {\n const pad = (v: number) => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, '0')\n return `#${pad(rgb[0])}${pad(rgb[1])}${pad(rgb[2])}`\n}\n\n/**\n * Blend two hex colors in HSL space with shortest-path hue interpolation.\n * `t` ∈ [0, 1]; `t=0` returns `from`, `t=1` returns `to`.\n */\nexport function blendHsl(from: string, to: string, t: number): string {\n const [r1, g1, b1] = parseHex(from)\n const [r2, g2, b2] = parseHex(to)\n const [h1, s1, l1] = rgbToHsl(r1, g1, b1)\n const [h2, s2, l2] = rgbToHsl(r2, g2, b2)\n // Shortest path around the hue wheel — purple→pink shouldn't detour\n // through cyan just because the raw subtraction is positive.\n let dh = h2 - h1\n if (dh > 0.5)\n dh -= 1\n else if (dh < -0.5)\n dh += 1\n const h = (h1 + dh * t + 1) % 1\n const s = s1 + (s2 - s1) * t\n const l = l1 + (l2 - l1) * t\n return toHex(hslToRgb(h, s, l))\n}\n\n/**\n * Static gradient ramp of length `n` going from `from` (index 0) to\n * `to` (index n-1) in HSL space. For the cycling A→B→A→B ramp the\n * throbber uses, see `buildCycleRamp` in `src/tui/crush-throbber.tsx`.\n */\nexport function buildLinearRamp(from: string, to: string, n: number): string[] {\n if (n <= 0)\n return []\n if (n === 1)\n return [blendHsl(from, to, 0.5)]\n const ramp: string[] = []\n for (let i = 0; i < n; i++)\n ramp.push(blendHsl(from, to, i / (n - 1)))\n return ramp\n}\n","/**\n * Completion provider that exposes the discovered project file catalog\n * (files AND directories — see `FileEntry.kind`) as `@`-prefixed\n * mentions. Trigger: `@`. Filtering: substring against `name + path`,\n * case-insensitive. Inserted text is `@{path} ` (`@{path}/ ` for\n * directories) so the cursor lands ready for the next token.\n *\n * Provider is pure UI — file *attachment* (reading bytes, injecting into\n * the prompt) happens at the submission boundary, where the host walks\n * `state.references` and decides what to do with each `FileEntry`.\n */\n\nimport type {\n CompletionContext,\n CompletionItem,\n CompletionProvider,\n CompletionReference,\n} from './completion-core'\nimport type { FileEntry } from './files-discovery'\nimport { Fzf } from 'fzf'\n\n/** Trigger character — `@` is the conventional file-mention prefix in chat UIs. */\nexport const FILES_TRIGGER = '@'\n\n/** Cap on returned items. Keeps the popover compact + render-cheap. */\nconst DEFAULT_RESULT_LIMIT = 50\n\n/** Identity formatter — preserves the discovery path verbatim. */\nconst IDENTITY_FORMAT = (entry: FileEntry): string => entry.path\n\n/**\n * Displayed/inserted form of a catalog entry. Directories carry a\n * trailing `/` so the emitted mention (`@src/chat/`) is visually and\n * semantically unambiguous — both to the user and to the agent's\n * path-resolving tools.\n */\nfunction displayOf(entry: FileEntry, formatPath: (entry: FileEntry) => string): string {\n const base = formatPath(entry)\n return entry.kind === 'dir' && !base.endsWith('/') ? `${base}/` : base\n}\n\n/**\n * Rank-and-slice a file catalog against a query. Hoisted to a module\n * helper so both the sync and async branches of `suggest()` share one\n * implementation (the async branch hits this once the lazy directory\n * walk resolves; sync branch hits it on every keystroke thereafter).\n *\n * `formatPath` rewrites the catalog's project-root-relative path into\n * the form the host wants emitted into the prompt (typically CWD-rel\n * or absolute when launched from a project subdir — see\n * `formatPathForCwd` in `path-display.ts`). Falls back to the raw\n * `entry.path` when omitted.\n */\nfunction scoreFiles(\n catalog: readonly FileEntry[],\n query: string,\n limit: number,\n formatPath: (entry: FileEntry) => string,\n): CompletionItem<FileEntry>[] {\n const q = query.trim().toLowerCase()\n // Pre-pass: fzf over the catalog's basenames feeds the rank-4 fuzzy\n // tier, catching small typos / omissions (`lop.ts` → `loop.ts`).\n // Scoped to basename — a path-wide fuzzy match would surface\n // near-random files on short queries. fzf enforces in-order\n // (subsequence) matching, so the fuzzy tier never degenerates into a\n // bag-of-chars filter. We keep only set membership (not fzf's score):\n // within-tier ordering stays alphabetical, and the Set keeps the loop\n // below O(1) per file.\n const fuzzyHits = q.length > 0\n ? new Set(new Fzf([...catalog], {\n selector: f => f.name,\n casing: 'case-insensitive',\n }).find(q).map(r => r.item))\n : null\n const scored: { entry: FileEntry, display: string, rank: number }[] = []\n for (const file of catalog) {\n const display = displayOf(file, formatPath)\n const name = file.name.toLowerCase()\n const path = display.toLowerCase()\n if (q.length === 0) {\n scored.push({ entry: file, display, rank: 5 })\n continue\n }\n if (name === q) {\n scored.push({ entry: file, display, rank: 0 })\n continue\n }\n if (name.startsWith(q)) {\n scored.push({ entry: file, display, rank: 1 })\n continue\n }\n if (name.includes(q)) {\n scored.push({ entry: file, display, rank: 2 })\n continue\n }\n if (path.includes(q)) {\n scored.push({ entry: file, display, rank: 3 })\n continue\n }\n if (fuzzyHits?.has(file)) {\n scored.push({ entry: file, display, rank: 4 })\n continue\n }\n }\n scored.sort((a, b) => {\n if (a.rank !== b.rank)\n return a.rank - b.rank\n return a.display.localeCompare(b.display)\n })\n return scored.slice(0, limit).map<CompletionItem<FileEntry>>(({ entry, display }) => ({\n id: display,\n // Directories carry the trailing `/` on the label too so rows are\n // distinguishable at a glance in the popover.\n label: entry.kind === 'dir' ? `${entry.name}/` : entry.name,\n // Description is the parent directory — gives the user disambiguation\n // signal when multiple files share a basename (`index.ts` × 12).\n //\n // Uses the catalog's RAW project-root-relative path, NOT the\n // cwd-formatted `display`. The cwd-formatted path flips a file's\n // visible shape based on whether it sits above or below\n // `process.cwd()` (absolute parent vs cwd-relative parent vs\n // empty for \"right here\"), which produces a popover that looks\n // half-broken when the same basename exists in multiple project\n // locations: `EDIT_THIS.md /Users/…/zidane` next to plain\n // `EDIT_THIS.md` for a sibling under the cwd. Anchoring the\n // description on `file.path` keeps the disambiguation column\n // stable + project-shaped regardless of where the user launched\n // the TUI from; the inserted text still uses `display` so the\n // tools can resolve it.\n description: parentDir(entry.path),\n insertText: `${FILES_TRIGGER}${display} `,\n data: entry,\n }))\n}\n\n/**\n * Build an `@`-prefixed files completion provider against a *live* catalog.\n *\n * The factory captures a getter so the catalog can be re-scanned (cwd\n * change, manual refresh) without re-instantiating the provider — the\n * App keeps one provider for the lifetime of the prompt block and just\n * mutates the underlying state.\n *\n * `limit` caps the result list so the popover stays bounded on huge\n * monorepos. Filtering is substring on `path` + `name`, case-insensitive,\n * with an fzf-scored basename fuzzy fallback so small typos / omissions\n * (`lop.ts` → `loop.ts`) still surface results; ranking prefers (in\n * order): exact name match, name prefix, name substring, path substring,\n * basename fuzzy match, alphabetical.\n */\nexport function createFilesCompletionProvider(opts: {\n /** Live file catalog. Re-evaluated per call so refreshes take effect immediately. */\n getCatalog: () => readonly FileEntry[]\n /**\n * Optional hook called the first time the host needs the catalog —\n * e.g. when the user opens the `@` popover. Hosts wire this to a\n * lazy directory walk so boot doesn't pay for it in monorepos\n * where the popover may never open. Idempotent contract: callers\n * may invoke it on every `suggest`; the host caches internally.\n *\n * When provided, `suggest()` returns a Promise on the very first\n * invocation if the catalog is still empty — the popover's loading\n * state surfaces while the walk completes; subsequent calls are\n * sync because `getCatalog()` then returns the populated state.\n */\n ensureCatalog?: () => Promise<readonly FileEntry[]>\n /** Max items returned to the popover. Default: 50. */\n limit?: number\n /**\n * Rewrite the catalog's project-root-relative path into the form\n * inserted into the prompt + matched by `parseReferences`. Wire this\n * to `formatPathForCwd` so paths emitted into the buffer line up\n * with the agent's CWD-resolving tools when the TUI launches from a\n * project subdirectory. Default: identity.\n *\n * Stable identity expected — `parseReferences` calls it once per\n * catalog entry per keystroke for the highlight pass; pure\n * pure-function shape keeps the popover responsive on huge repos.\n */\n formatPath?: (entry: FileEntry) => string\n}): CompletionProvider<FileEntry> {\n const limit = opts.limit ?? DEFAULT_RESULT_LIMIT\n const formatPath = opts.formatPath ?? IDENTITY_FORMAT\n return {\n id: 'files',\n trigger: FILES_TRIGGER,\n label: 'Files',\n suggest(query) {\n // Kick off lazy discovery (no-op on subsequent calls). If the\n // host wired a thunk and the catalog isn't ready yet, hand the\n // popover a Promise — it already supports `loading` and refreshes\n // `items` when the promise resolves.\n if (opts.ensureCatalog) {\n const pending = opts.ensureCatalog()\n const current = opts.getCatalog()\n if (current.length === 0) {\n return pending.then(loaded => scoreFiles(loaded, query, limit, formatPath))\n }\n }\n return scoreFiles(opts.getCatalog(), query, limit, formatPath)\n },\n parseReferences(text, _ctx: CompletionContext) {\n const catalog = opts.getCatalog()\n if (catalog.length === 0)\n return []\n // Keyed by the DISPLAYED path (what `insertText` emitted) so a\n // post-format buffer still resolves back to its `FileEntry`.\n // Directories are additionally keyed by their slash-less form so a\n // hand-typed `@src/chat` resolves like the inserted `@src/chat/`\n // (no collision risk — a file and a dir can't share a path).\n const byPath = new Map<string, FileEntry>()\n for (const file of catalog) {\n const display = displayOf(file, formatPath)\n byPath.set(display, file)\n if (file.kind === 'dir')\n byPath.set(formatPath(file), file)\n }\n const refs: CompletionReference<FileEntry>[] = []\n // Match `@<path>` at start-of-buffer or after whitespace. Paths are\n // non-whitespace sequences — files contain `/`, `.`, `-`, etc., so a\n // word-boundary rule won't do. We greedy-match `\\S+` then trim\n // trailing punctuation that's almost never part of the intended\n // reference (sentence end). The trimmed candidate must exist in the\n // catalog for the span to be highlighted — typos don't produce\n // false-positive references.\n // Capture groups: 1 = leading boundary (start-of-buffer or whitespace),\n // 2 = path body without the `@` sigil. `@` itself is matched but not\n // captured because the consumer only needs the raw path to look up\n // the catalog entry.\n const rx = /(^|\\s)@(\\S+)/g\n for (const m of text.matchAll(rx)) {\n const rawCandidate = m[2]\n // Strip trailing `.`, `,`, `;`, `:`, `)` , `]`, `}`, `!`, `?` — when\n // the exact candidate isn't in the catalog but a shorter prefix is,\n // the user almost certainly mentioned the file in regular prose.\n // Single regex replace + slice instead of a per-char loop keeps this\n // O(n) in candidate length rather than O(n²) on pathological tails.\n const stripped = byPath.has(rawCandidate)\n ? rawCandidate\n : rawCandidate.replace(/[.,;:)\\]}!?]+$/, '')\n const file = byPath.get(stripped)\n if (!file)\n continue\n const start = m.index + m[1].length\n // `trimmed` matches the visible \"@<stripped>\" span — recompute its\n // length from `stripped` so we don't over-paint on the trailing punct.\n const trimmedLen = 1 + stripped.length // `@` + path\n refs.push({\n providerId: 'files',\n start,\n end: start + trimmedLen,\n // `itemId` mirrors `suggest()`'s `id` (the displayed path)\n // so the engine's reference ↔ item correlation stays\n // consistent on either side of the formatter. `data.path`\n // still carries the raw project-root-relative path for\n // downstream consumers (`uniqueFilesFromReferences`,\n // submission attach hooks, …). Canonicalized through\n // `displayOf` so a slash-less dir mention still correlates\n // with the suggestion item's id (which carries the `/`).\n itemId: displayOf(file, formatPath),\n data: file,\n })\n }\n return refs\n },\n }\n}\n\n/** Return the parent directory of a forward-slashed path, or `''` for root entries. */\nfunction parentDir(path: string): string {\n const lastSlash = path.lastIndexOf('/')\n return lastSlash <= 0 ? '' : path.slice(0, lastSlash)\n}\n\n/**\n * Walk a reference list and return the deduplicated set of files in\n * first-mention order — input to \"attach these files to the prompt\"\n * downstream logic.\n */\nexport function uniqueFilesFromReferences(\n references: readonly CompletionReference<unknown>[],\n): FileEntry[] {\n const out: FileEntry[] = []\n const seen = new Set<string>()\n for (const ref of references) {\n if (ref.providerId !== 'files')\n continue\n if (seen.has(ref.itemId))\n continue\n seen.add(ref.itemId)\n out.push(ref.data as FileEntry)\n }\n return out\n}\n","/**\n * Completion provider that exposes the discovered skills catalog as\n * slash-commands. Trigger: `/`. Filtering: substring against `name +\n * description`, case-insensitive. Inserted text is `/{name} ` so the\n * cursor lands ready for the next token.\n *\n * Skill activation is **not** performed here — the provider is pure UI.\n * Submission flow at the host (TUI `onSubmitPrompt`) walks the prompt for\n * skill references via `parseReferences` and calls `agent.activateSkill`\n * before `agent.run`.\n */\n\nimport type { SkillConfig } from '../skills'\nimport type {\n CompletionContext,\n CompletionItem,\n CompletionProvider,\n CompletionReference,\n} from './completion-core'\nimport { Fzf } from 'fzf'\n\n/** Trigger character — slash-commands convention. */\nexport const SKILLS_TRIGGER = '/'\n\n/** Valid skill-name shape (matches the parser): lowercase alnum + dashes. */\nconst SKILL_NAME_RX = /^[a-z0-9][a-z0-9-]*$/\n\n/**\n * Filter + rank visible skills against a query. Hoisted to a module\n * helper so the sync and async branches of `suggest()` share one\n * implementation (the async branch hits this once the lazy SKILL.md\n * scan resolves; sync branch hits it on every keystroke thereafter).\n */\nfunction scoreSkills(\n catalog: readonly SkillConfig[],\n query: string,\n): CompletionItem<SkillConfig>[] {\n const q = query.trim().toLowerCase()\n const valid = catalog.filter(skill => SKILL_NAME_RX.test(skill.name))\n // fzf pre-pass over skill *names* so the rank-3 fuzzy tier catches\n // small typos (`reseach` → `research`). Scoped to name only — fuzzy\n // matching against descriptions (free-form sentences) would surface\n // near-random skills on short queries.\n const fuzzyHits = q.length > 0\n ? new Set(new Fzf(valid, {\n selector: s => s.name,\n casing: 'case-insensitive',\n }).find(q).map(r => r.item))\n : null\n const scored: { skill: SkillConfig, rank: number }[] = []\n for (const skill of valid) {\n const name = skill.name.toLowerCase()\n const desc = skill.description.toLowerCase()\n if (q.length === 0) {\n scored.push({ skill, rank: 4 })\n continue\n }\n if (name.startsWith(q)) {\n scored.push({ skill, rank: 0 })\n continue\n }\n if (name.includes(q)) {\n scored.push({ skill, rank: 1 })\n continue\n }\n if (desc.includes(q)) {\n scored.push({ skill, rank: 2 })\n continue\n }\n if (fuzzyHits?.has(skill)) {\n scored.push({ skill, rank: 3 })\n continue\n }\n }\n scored.sort((a, b) => {\n if (a.rank !== b.rank)\n return a.rank - b.rank\n return a.skill.name.localeCompare(b.skill.name)\n })\n return scored.map<CompletionItem<SkillConfig>>(({ skill }) => ({\n id: skill.name,\n label: skill.name,\n description: skill.description,\n insertText: `${SKILLS_TRIGGER}${skill.name} `,\n data: skill,\n }))\n}\n\n/**\n * Build a slash-command completion provider against a *live* skills\n * catalog. The factory captures a getter so the catalog can change across\n * renders (toggles, reload) without re-instantiating the provider.\n *\n * Pass `getEnabled` to additionally hide skills the user has toggled off\n * — when undefined, every catalog entry is offered.\n */\nexport function createSkillsCompletionProvider(opts: {\n /** Live catalog. Re-evaluated per call so toggles take effect immediately. */\n getCatalog: () => readonly SkillConfig[]\n /** Optional enable-set filter; when undefined every catalog skill is offered. */\n getEnabled?: () => readonly string[] | undefined\n /**\n * Optional hook called the first time the host needs the catalog —\n * typically when the user opens the `/` popover. Mirror of the\n * files provider's `ensureCatalog`; same idempotent contract.\n *\n * Hosts wire this to a lazy SKILL.md scan so the boot path stays\n * free of disk reads in deeply-nested skill trees. Returns a Promise\n * on the very first `suggest()` call when the catalog is still\n * empty so the popover surfaces its loading state.\n */\n ensureCatalog?: () => Promise<readonly SkillConfig[]>\n}): CompletionProvider<SkillConfig> {\n const visible = (): SkillConfig[] => {\n const all = opts.getCatalog()\n const enabled = opts.getEnabled?.()\n if (enabled === undefined)\n return [...all]\n const allow = new Set(enabled)\n return all.filter(s => allow.has(s.name))\n }\n return {\n id: 'skills',\n trigger: SKILLS_TRIGGER,\n label: 'Skills',\n suggest(query) {\n // Lazy-load on first suggest if the host wired a thunk. Same\n // pattern as the files provider — popover loading state covers\n // the gap, subsequent suggests are sync.\n if (opts.ensureCatalog) {\n const pending = opts.ensureCatalog()\n if (opts.getCatalog().length === 0) {\n return pending.then(() => scoreSkills(visible(), query))\n }\n }\n return scoreSkills(visible(), query)\n },\n parseReferences(text, _ctx: CompletionContext) {\n const catalog = visible()\n if (catalog.length === 0)\n return []\n const byName = new Map<string, SkillConfig>()\n for (const skill of catalog) byName.set(skill.name, skill)\n const refs: CompletionReference<SkillConfig>[] = []\n // Match `/name` at start-of-buffer or after whitespace. The lookbehind\n // is implemented manually (no regex `\\b` because `/` isn't a word\n // character) so we work in environments that lack lookbehind support.\n // Grammar must match `SKILL_NAME_RX` — `[a-z0-9-]` only, no `_`. Using\n // `\\w` here would parse `/foo_bar` as a candidate, only for the catalog\n // lookup to drop it; aligning the two grammars keeps the parser honest.\n const rx = /(^|\\s)(\\/([a-z0-9][a-z0-9-]*))/g\n for (const m of text.matchAll(rx)) {\n const name = m[3]\n const skill = byName.get(name)\n if (!skill)\n continue\n const start = m.index + m[1].length\n refs.push({\n providerId: 'skills',\n start,\n end: start + m[2].length,\n itemId: skill.name,\n data: skill,\n })\n }\n return refs\n },\n }\n}\n\n/**\n * Walk a parsed prompt for skill references and return the deduplicated\n * list of skill names — input to `agent.activateSkill(name)` calls on\n * submit.\n */\nexport function uniqueSkillNamesFromReferences(\n references: readonly CompletionReference<unknown>[],\n): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n for (const ref of references) {\n if (ref.providerId !== 'skills')\n continue\n if (seen.has(ref.itemId))\n continue\n seen.add(ref.itemId)\n out.push(ref.itemId)\n }\n return out\n}\n","// ---------------------------------------------------------------------------\n// Renderer-agnostic markdown text segmenter.\n//\n// `splitMarkdownCodeBlocks` walks a markdown string once and emits an\n// ordered list of prose / fenced-code segments. Useful for any consumer\n// that wants to render fenced code differently from prose (a TUI that\n// wraps fences with a copy header, a GUI that hands fenced bodies to a\n// Monaco-style editor, a renderer that pipes prose through `marked` and\n// fences through Shiki, etc).\n//\n// Lives in `zidane/chat` so future renderer shells get the same\n// segmenter — no OpenTUI dependency, no React dependency, pure\n// string-in / array-out.\n// ---------------------------------------------------------------------------\n\n/**\n * One block returned by {@link splitMarkdownCodeBlocks}. Prose segments\n * carry their original markdown (including blank lines that bracketed\n * the fence) so the surrounding paragraph spacing stays faithful to the\n * original input. Code segments carry the raw body — fence markers and\n * info-string stripped — so a \"copy code\" action lands what the user\n * actually sees, byte-for-byte.\n */\nexport interface MarkdownSegment {\n kind: 'prose' | 'code'\n content: string\n /** Info-string (e.g. `ts`, `python`). Empty when the fence had none. */\n lang?: string\n /**\n * `true` on a code segment whose closing fence hasn't arrived yet —\n * i.e. the trailing block during streaming. Consumers can render this\n * in \"streaming\" mode (no copy affordance, partial-highlight pipeline)\n * until the closer lands and it flips to a regular closed segment.\n */\n open?: boolean\n}\n\n/**\n * Split markdown text into alternating prose / fenced-code segments.\n *\n * Recognizes both ` ``` ` and `~~~` fences, with arbitrary length ≥ 3,\n * matching CommonMark's \"fence indicator must be at least as long to\n * close\" rule. Info-strings (the bit after the opening fence) are kept\n * as the `lang` hint; any trailing whitespace is trimmed. Closing\n * fences are detected on a line of their own (whitespace tolerated).\n *\n * Unclosed fences fall back to emitting the would-be-code body as a\n * trailing prose segment so no content is dropped — finalized markdown\n * isn't expected to ship one, but the fallback keeps the renderer\n * truthful when the model produces malformed output.\n *\n * Exported for unit tests.\n */\nexport function splitMarkdownCodeBlocks(text: string): MarkdownSegment[] {\n const lines = text.split('\\n')\n const segments: MarkdownSegment[] = []\n let prose: string[] = []\n let code: string[] = []\n let inFence = false\n let fenceChar = ''\n let fenceLen = 0\n let lang = ''\n\n // Drop a single trailing/leading blank line off each emitted prose\n // segment. Markdown convention puts a blank line between a paragraph\n // and the fence that follows; without trimming, that blank stacks\n // with the code panel's `marginTop: 1` (and symmetrically with\n // `marginBottom: 1` on the post-fence side), producing a double-blank\n // gap when the renderer adds its own panel margins.\n const flushProse = () => {\n if (prose.length > 0 && prose[prose.length - 1] === '')\n prose.pop()\n if (prose.length > 0) {\n segments.push({ kind: 'prose', content: prose.join('\\n') })\n prose = []\n }\n }\n\n let trimLeadingProseBlank = false\n\n for (const line of lines) {\n if (!inFence) {\n const open = line.match(/^(`{3,}|~{3,})([^\\n`~]*)$/)\n if (open) {\n flushProse()\n inFence = true\n fenceChar = open[1]![0]!\n fenceLen = open[1]!.length\n lang = open[2]!.trim()\n code = []\n continue\n }\n if (trimLeadingProseBlank) {\n trimLeadingProseBlank = false\n if (line === '' && prose.length === 0)\n continue\n }\n prose.push(line)\n }\n else {\n const close = line.match(/^(`{3,}|~{3,})\\s*$/)\n if (close && close[1]![0]! === fenceChar && close[1]!.length >= fenceLen) {\n segments.push({ kind: 'code', content: code.join('\\n'), lang })\n inFence = false\n code = []\n trimLeadingProseBlank = true\n continue\n }\n code.push(line)\n }\n }\n\n if (inFence) {\n prose.push(`${fenceChar.repeat(fenceLen)}${lang}`, ...code)\n }\n flushProse()\n return segments\n}\n\n/**\n * Remove HTML comments from markdown PROSE while leaving fenced code and\n * inline code spans untouched (`<!-- -->` inside a fence or backticks is\n * legitimate content the user must see). Comments may span lines; a line\n * reduced to whitespace by comment removal is dropped entirely so no\n * phantom paragraph gap remains.\n */\nexport function stripHtmlCommentsOutsideCode(text: string): string {\n const lines = text.split('\\n')\n const out: string[] = []\n let inFence = false\n let fenceChar = ''\n let fenceLen = 0\n let inComment = false\n\n for (const line of lines) {\n if (inFence) {\n out.push(line)\n if (isFenceClose(line, fenceChar, fenceLen))\n inFence = false\n continue\n }\n if (!inComment) {\n const open = parseFenceOpen(line)\n if (open) {\n out.push(line)\n inFence = true\n fenceChar = open.char\n fenceLen = open.length\n continue\n }\n }\n\n // Prose line: char scan tracking inline code spans (`…`) and the\n // cross-line comment state.\n let result = ''\n let i = 0\n let spanTicks = 0\n let dropped = false\n while (i < line.length) {\n if (inComment) {\n const end = line.indexOf('-->', i)\n if (end === -1) {\n i = line.length\n break\n }\n i = end + 3\n inComment = false\n continue\n }\n const ch = line[i]!\n if (ch === '`') {\n let run = 1\n while (line[i + run] === '`')\n run++\n if (spanTicks === 0)\n spanTicks = run\n else if (run === spanTicks)\n spanTicks = 0\n result += line.slice(i, i + run)\n i += run\n continue\n }\n if (spanTicks === 0 && line.startsWith('<!--', i)) {\n inComment = true\n dropped = true\n i += 4\n continue\n }\n result += ch\n i++\n }\n\n // A line that held only comment content vanishes with it.\n if (dropped && result.trim() === '' && line.trim() !== '')\n continue\n if (inComment && result.trim() === '' && line.trim() !== '')\n continue\n out.push(result)\n }\n return out.join('\\n')\n}\n\nconst LIST_ITEM_RE = /^( *)(?:[-+*]|\\d+[.)]) +/\n\n/**\n * Lift indented fenced code blocks to column 0 while preserving the code\n * body's relative indentation.\n *\n * OpenTUI's markdown renderNode hook only receives top-level code tokens.\n * A common assistant shape is:\n *\n * - Run this:\n * ```bash\n * command\n * ```\n *\n * Marked parses that as code inside a list token, so the TUI loses the\n * code-panel wrapper and copy affordance. Normalizing just the fence's list\n * indentation keeps the prose readable while routing the snippet through\n * the same top-level renderer as ordinary fences.\n */\nexport function normalizeMarkdownCodeFences(text: string): string {\n const lines = text.split('\\n')\n const out: string[] = []\n const listIndents: number[] = []\n let inFence = false\n let fenceChar = ''\n let fenceLen = 0\n let lift = 0\n\n for (const line of lines) {\n if (inFence) {\n const normalized = stripFenceIndent(line, lift)\n out.push(normalized)\n\n if (isFenceClose(normalized, fenceChar, fenceLen)) {\n inFence = false\n fenceChar = ''\n fenceLen = 0\n lift = 0\n }\n continue\n }\n\n updateListIndentStack(listIndents, line)\n\n const open = parseFenceOpen(line)\n if (!open) {\n out.push(line)\n continue\n }\n\n const activeListIndent = [...listIndents].reverse().find(i => i <= open.indent)\n lift = activeListIndent ?? (open.indent <= 3 ? open.indent : 0)\n\n const normalized = stripFenceIndent(line, lift)\n out.push(normalized)\n inFence = true\n fenceChar = open.char\n fenceLen = open.length\n }\n\n return out.join('\\n')\n}\n\n/**\n * Default per-chunk target for {@link chunkMarkdownForRender}. Chosen from\n * measurement: marked's lexer (which OpenTUI's `<markdown>` runs\n * internally) is O(n²) over paragraph-heavy input — ~500ms at 64KiB,\n * ~2s at 128KiB, ~6s at 256KiB on an M-series laptop — while staying\n * comfortably in the linear zone below ~32KiB (≤ ~200ms). Chunking a\n * large document into ≤24KiB pieces keeps the total render linear in\n * document size with a small constant.\n */\nexport const MARKDOWN_RENDER_CHUNK_TARGET_BYTES = 24_576\n\n/**\n * A blank-line split is only safe when the next block clearly STARTS a\n * new top-level construct. Lines that continue a multi-block construct —\n * list items (loose lists put blank lines between items; splitting would\n * restart ordered-list numbering), blockquote lines, table rows, and\n * indented continuations / indented code — are unsafe, so a chunk grows\n * past the target rather than splitting one of these. Worst case (one\n * giant list) degrades to a single chunk: the pre-chunking behavior.\n */\nfunction isUnsafeChunkBoundary(line: string): boolean {\n return LIST_ITEM_RE.test(line)\n || /^ *>/.test(line)\n || /^ *\\|/.test(line)\n || /^ {4,}/.test(line)\n}\n\n/**\n * Split a large markdown document into render-safe chunks at blank-line\n * boundaries outside code fences, each roughly `targetBytes` long.\n *\n * Rendering the chunks as SIBLING markdown renderables (with a one-row\n * gap standing in for the consumed blank line) is visually equivalent to\n * one renderable, but sidesteps the quadratic lexer cost documented on\n * {@link MARKDOWN_RENDER_CHUNK_TARGET_BYTES}. Chunk boundaries are\n * prefix-stable: appending text (streaming) can only ever change the\n * LAST chunk, so keyed-by-index consumers reconcile cheaply.\n *\n * Returns `[text]` untouched for anything at or under the target.\n */\nexport function chunkMarkdownForRender(text: string, targetBytes: number = MARKDOWN_RENDER_CHUNK_TARGET_BYTES): string[] {\n if (text.length <= targetBytes)\n return [text]\n\n const lines = text.split('\\n')\n const chunks: string[] = []\n let current: string[] = []\n let currentBytes = 0\n let inFence = false\n let fenceChar = ''\n let fenceLen = 0\n\n const push = (line: string): void => {\n current.push(line)\n currentBytes += line.length + 1\n }\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] as string\n\n if (inFence) {\n push(line)\n if (isFenceClose(line, fenceChar, fenceLen))\n inFence = false\n continue\n }\n\n const open = parseFenceOpen(line)\n if (open) {\n push(line)\n inFence = true\n fenceChar = open.char\n fenceLen = open.length\n continue\n }\n\n // Split point: a blank-line run outside a fence, once the current\n // chunk is big enough and the next content starts a safe new block.\n if (line.trim() === '' && currentBytes >= targetBytes && current.length > 0) {\n let next = i + 1\n while (next < lines.length && (lines[next] as string).trim() === '')\n next++\n if (next < lines.length && !isUnsafeChunkBoundary(lines[next] as string)) {\n chunks.push(current.join('\\n'))\n current = []\n currentBytes = 0\n i = next - 1 // consume the blank run; the renderer restores the gap\n continue\n }\n }\n\n push(line)\n }\n\n if (current.length > 0)\n chunks.push(current.join('\\n'))\n return chunks.length > 0 ? chunks : [text]\n}\n\nfunction parseFenceOpen(line: string): { indent: number, char: string, length: number } | null {\n const indent = leadingSpaces(line)\n const char = line[indent]\n if (char !== '`' && char !== '~')\n return null\n\n const length = countRun(line, indent, char)\n if (length < 3)\n return null\n\n const info = line.slice(indent + length)\n if (char === '`' && info.includes('`'))\n return null\n\n return { indent, char, length }\n}\n\nfunction isFenceClose(line: string, fenceChar: string, fenceLen: number): boolean {\n const indent = leadingSpaces(line)\n if (line[indent] !== fenceChar)\n return false\n\n const length = countRun(line, indent, fenceChar)\n if (length < fenceLen)\n return false\n\n return onlySpaces(line, indent + length)\n}\n\nfunction updateListIndentStack(listIndents: number[], line: string): void {\n const contentIndent = leadingSpaces(line)\n if (line.trim().length > 0) {\n while (listIndents.length > 0 && contentIndent < listIndents[listIndents.length - 1]!)\n listIndents.pop()\n }\n\n const item = line.match(LIST_ITEM_RE)\n if (!item)\n return\n\n const indent = item[0]!.length\n if (indent > (listIndents[listIndents.length - 1] ?? 0))\n listIndents.push(indent)\n}\n\nfunction leadingSpaces(line: string): number {\n let i = 0\n while (i < line.length && line[i] === ' ')\n i++\n return i\n}\n\nfunction countRun(line: string, start: number, char: string): number {\n let i = start\n while (i < line.length && line[i] === char)\n i++\n return i - start\n}\n\nfunction onlySpaces(line: string, start: number): boolean {\n for (let i = start; i < line.length; i++) {\n if (line[i] !== ' ')\n return false\n }\n return true\n}\n\nfunction stripFenceIndent(line: string, columns: number): string {\n if (columns <= 0)\n return line\n let i = 0\n while (i < columns && line[i] === ' ')\n i++\n return line.slice(i)\n}\n","/**\n * Cross-provider model catalog — assembly + fuzzy filtering.\n *\n * Renderer-agnostic helpers consumed by `ModelPickerModal` (TUI) and any\n * future UI that wants a unified \"pick a model across all available\n * providers\" experience. Pure: no React, no I/O, no provider construction.\n *\n * The catalog is the flat union of every available provider's models,\n * each entry tagged with the provider it belongs to so the picker can\n * re-issue a `Picked` tuple `{ providerKey, modelId }` on commit.\n */\n\nimport type { ProviderAuth, ProviderKey } from './auth'\nimport type { ModelInfo } from './providers'\n\n/** A model entry as displayed in the cross-provider picker. */\nexport interface CatalogEntry {\n providerKey: ProviderKey\n providerLabel: string\n model: ModelInfo\n /**\n * Pre-computed lowercase corpus for substring search across the\n * provider key, label, model id, and display name. Built once at\n * catalog-assembly time so filtering on every keystroke is\n * O(catalogSize × queryLength), not O(catalogSize × fieldCount ×\n * lowercase-overhead × queryLength).\n */\n searchCorpus: string\n}\n\n/**\n * Build the unified catalog from a list of available providers.\n *\n * Provider order is preserved (callers typically pass the picker order\n * — alphabetical, auth-detection order, etc.); model order inside each\n * provider matches whatever `modelsFor` returns. The current selection\n * (when set) is bubbled to the top of its provider's section so it\n * shows first without disturbing relative ordering elsewhere.\n *\n * `modelsFor` is injected (not imported from `./providers`) so the same\n * helper works with hosts that supply their own model resolver via\n * `ResolvedConfig.modelsFor`.\n */\nexport function buildModelCatalog(opts: {\n providers: readonly ProviderAuth[]\n modelsFor: (key: ProviderKey) => readonly ModelInfo[]\n /** Optional currently-selected pair — promoted to the top of its provider group. */\n current?: { providerKey: ProviderKey, modelId: string } | null\n}): CatalogEntry[] {\n const entries: CatalogEntry[] = []\n for (const provider of opts.providers) {\n const models = opts.modelsFor(provider.key)\n if (models.length === 0)\n continue\n // Promote the currently-selected model to position 0 inside its\n // own provider section so the picker doesn't bury the user's\n // active row at the bottom of a long provider list.\n let ordered: readonly ModelInfo[] = models\n if (opts.current?.providerKey === provider.key) {\n const idx = models.findIndex(m => m.id === opts.current?.modelId)\n if (idx > 0) {\n const next = models.slice()\n const [active] = next.splice(idx, 1)\n next.unshift(active)\n ordered = next\n }\n }\n for (const model of ordered) {\n entries.push({\n providerKey: provider.key,\n providerLabel: provider.label,\n model,\n searchCorpus: buildSearchCorpus(provider, model),\n })\n }\n }\n return entries\n}\n\n/**\n * Filter `catalog` by a user query. Empty / whitespace-only queries\n * pass everything through unchanged (`O(1)` short-circuit). Multi-term\n * queries (space-separated) require EVERY term to appear somewhere in\n * the entry's search corpus — so `\"claude opus\"` matches `claude-opus-4`\n * regardless of how the words are interleaved with provider names.\n *\n * Match is case-insensitive (the corpus is pre-lowercased; the query\n * is lowercased once per call).\n */\nexport function filterModelCatalog(\n catalog: readonly CatalogEntry[],\n query: string,\n): CatalogEntry[] {\n const trimmed = query.trim().toLowerCase()\n if (!trimmed)\n return catalog.slice()\n const terms = trimmed.split(/\\s+/)\n return catalog.filter(entry => terms.every(t => entry.searchCorpus.includes(t)))\n}\n\n/**\n * Find a catalog entry's index by its `{providerKey, modelId}` tuple.\n * Returns `-1` when not present. Useful when re-rendering the picker\n * (a query just narrowed the list, where did the selection land?).\n */\nexport function indexOfEntry(\n catalog: readonly CatalogEntry[],\n target: { providerKey: ProviderKey, modelId: string } | null | undefined,\n): number {\n if (!target)\n return -1\n return catalog.findIndex(\n e => e.providerKey === target.providerKey && e.model.id === target.modelId,\n )\n}\n\nfunction buildSearchCorpus(provider: ProviderAuth, model: ModelInfo): string {\n const parts = [\n provider.key,\n provider.label,\n model.id,\n model.name ?? '',\n model.provider ?? '',\n ]\n return parts.join(' ').toLowerCase()\n}\n","/**\n * Pure string + reference math for rendering a submitted prompt with chip\n * pills around completion references. Renderer-agnostic — the TUI walks\n * the segments into OpenTUI `<text>` nodes, a GUI walks them into JSX\n * spans + `<span class=\"chip\">` pills. No layout engine assumptions.\n */\n\n/**\n * Highlight span — half-open `[start, end)` over the source string.\n *\n * Offsets are JS string indices (UTF-16 code units) — the same convention used\n * everywhere else in the chat layer (`text[i]`, `m.index`, `String.slice`).\n * Surrogate pairs that straddle a span boundary would render malformed, but\n * realistic prompts in this surface (terminal text + ASCII triggers) keep that\n * risk theoretical; callers feeding emoji-heavy content should normalize to\n * codepoint walks upstream.\n */\nexport interface PromptSegmentRef {\n start: number\n end: number\n /** Provider id tagging this span (`'skills'`, `'files'`, …). Free-form. */\n providerId: string\n}\n\n/**\n * One atomic unit emitted by {@link splitPromptSegments}. Plain segments\n * are word-sized so wraps land cleanly between words; chip segments\n * carry the source `providerId` (`'skills'`, `'files'`, …) so renderers\n * can pick per-kind colors without re-walking the ref list.\n */\nexport type PromptSegment\n = | { kind: 'plain', text: string }\n | { kind: 'chip', text: string, providerId: string }\n\n/**\n * Split a prompt buffer into word-sized atomic segments suitable for a\n * flex-row + flex-wrap renderer (TUI) or a `display: inline` flow with\n * inline-block chips (GUI). Each chip becomes one segment (atomic —\n * never broken across rows); each plain run is split into \"word +\n * trailing space\" units so wraps land at clean word boundaries.\n *\n * Robust to:\n * - Overlapping refs — sorted by start; later refs that overlap are\n * dropped via the first-wins rule.\n * - Out-of-bounds refs — dropped entirely when `end > text.length` or\n * `start >= text.length`. Partial clipping would silently truncate\n * a chip's label; the caller is in a better position to surface the\n * mismatch (typically a stale `refs` array referencing a previous text).\n * - Whitespace-only plain runs — emitted as their own plain segment\n * so chip-adjacent-to-chip cases keep the original spacing.\n *\n * Word splitter rationale: `\\S+\\s*` keeps trailing whitespace attached\n * to its preceding word so wrap boundaries land between words (cleanly).\n * A leading-whitespace-only segment is captured by `\\s+` so we don't\n * drop it entirely when the plain run starts with a space.\n */\nexport function splitPromptSegments(\n text: string,\n refs: readonly PromptSegmentRef[],\n): PromptSegment[] {\n const sorted = [...refs]\n .filter(r => r.end > r.start && r.start < text.length && r.end <= text.length)\n .sort((a, b) => a.start - b.start)\n const out: PromptSegment[] = []\n let cursor = 0\n for (const ref of sorted) {\n if (ref.start < cursor)\n continue // overlapping with a previous ref — drop\n if (ref.start > cursor) {\n const matches = text.slice(cursor, ref.start).match(/\\S+\\s*|\\s+/g) ?? []\n for (const m of matches)\n out.push({ kind: 'plain', text: m })\n }\n out.push({ kind: 'chip', text: text.slice(ref.start, ref.end), providerId: ref.providerId })\n cursor = ref.end\n }\n if (cursor < text.length) {\n const matches = text.slice(cursor).match(/\\S+\\s*|\\s+/g) ?? []\n for (const m of matches)\n out.push({ kind: 'plain', text: m })\n }\n return out\n}\n","/**\n * Streaming finalize reducers + context-window math — pure transforms.\n *\n * No React, no node — so a browser-context renderer imports these via\n * `zidane/chat/pure`. The `useStreamBuffer` React hook + its smooth-stream\n * ticker live in `./streaming` (main barrel) and re-export these for\n * back-compat; a renderer owns its own ticker against the same reducers.\n */\n\nimport type { TurnUsage } from '../types'\nimport type { Owner, StreamEvent } from './types'\nimport { effectiveInputFromTurn } from '../stats'\n\nconst PARENT_OWNER: Owner = 'parent'\n\nexport function ownerOf(event: StreamEvent): Owner {\n return event.childId ?? PARENT_OWNER\n}\n\n/** Flip any trailing streaming markdown blocks (any owner) to finalized. */\nexport function finalizeStreamingMarkdown(events: StreamEvent[]): StreamEvent[] {\n let changed = false\n const next = events.map((e) => {\n if (e.kind === 'markdown' && e.streaming) {\n changed = true\n return { ...e, streaming: false }\n }\n return e\n })\n return changed ? next : events\n}\n\n/** Flip the trailing streaming markdown block for one specific owner. */\nexport function finalizeStreamingMarkdownForOwner(events: StreamEvent[], owner: Owner): StreamEvent[] {\n for (let i = events.length - 1; i >= 0; i--) {\n const e = events[i]\n if (e.kind !== 'markdown')\n continue\n if (!e.streaming)\n continue\n if (ownerOf(e) !== owner)\n continue\n const next = events.slice()\n next[i] = { ...e, streaming: false }\n return next\n }\n return events\n}\n\n/**\n * Effective context size for a single turn.\n *\n * `usage.input` is misleading on its own when prompt caching is active: providers\n * (Anthropic, OpenRouter→Anthropic, Gemini) report `input` as the *new uncached*\n * tokens only — the cached prefix shows up in `cacheRead`, and newly-cached\n * tokens in `cacheCreation`. The model still saw all three buckets, so the real\n * context-window utilization is their sum.\n *\n * Non-caching providers leave `cacheRead`/`cacheCreation` undefined, so this\n * collapses to plain `input` for them.\n */\nexport function turnContextSize(usage: TurnUsage | undefined): number {\n return effectiveInputFromTurn(usage)\n}\n\n// ---------------------------------------------------------------------------\n// Transcript memory cap\n// ---------------------------------------------------------------------------\n\n/**\n * Display-layer transcript bounds. Each rendered event holds live React\n * fibers + OpenTUI renderables + native text buffers even when scrolled\n * off-screen — measured at roughly 0.13 MB RSS per markdown-heavy event —\n * so an uncapped multi-thousand-event session (a normal working day with\n * tool calls) climbs into the hundreds of MB and eventually OOM/thrash.\n *\n * The cap bounds ONLY what is materialized on screen: session turns on\n * disk are complete, and switching sessions / re-activating replays the\n * most recent window again. Trimming happens at TURN boundaries so a\n * turn's rows are never orphaned, and re-caps fold into one cumulative\n * marker rather than stacking markers.\n */\nexport const MAX_TRANSCRIPT_EVENTS = 1_500\n/** Post-trim size — the hysteresis gap keeps re-trims O(rare), not per-append. */\nexport const TRANSCRIPT_TRIM_TO_EVENTS = 1_200\n\n/**\n * The cumulative count rides IN the marker's display text and is parsed\n * back out on re-cap — deliberately text-as-protocol rather than a new\n * StreamEvent kind or field: 'info' renders everywhere for free (no\n * renderer changes, no persistence shape change — markers are display\n * state and never persisted), and producer + consumer live ten lines\n * apart in this file. Same precedent as task-notification re-synthesis.\n * If markers ever need richer data, THAT is the moment for a dedicated\n * event kind.\n */\nconst HIDDEN_MARKER_RE = /^… (\\d+) earlier transcript items hidden/\n\nexport function hiddenEarlierTranscriptCount(events: readonly StreamEvent[]): number {\n const first = events[0]\n return first?.kind === 'info' ? Number(HIDDEN_MARKER_RE.exec(first.text)?.[1] ?? 0) : 0\n}\n\nfunction hiddenMarkerEvent(count: number): StreamEvent {\n // Copy stays host-neutral: this helper is shared SDK surface, and only\n // the TUI wires a scroll-to-load affordance — promising \"scroll up\" on\n // hosts without one would be a false affordance.\n return {\n kind: 'info',\n text: `… ${count} earlier transcript items hidden to bound memory — the full history stays in the session.`,\n }\n}\n\n/**\n * Reveal one older page while retaining everything currently visible.\n * The default transcript is memory-bounded; memory grows only when the user\n * deliberately scrolls into the marker. The cut expands to a turn boundary\n * so tool-call/result groups are never split.\n */\nexport function replaceTranscriptTurnEvents(\n displayed: readonly StreamEvent[],\n rebuilt: readonly StreamEvent[],\n turnId: string,\n): StreamEvent[] | null {\n const replacements = rebuilt.filter(event => event.turnId === turnId)\n let inserted = false\n const patched = displayed.flatMap((event) => {\n if (event.turnId !== turnId)\n return [event]\n if (inserted)\n return []\n inserted = true\n return replacements\n })\n return inserted ? patched : null\n}\n\nexport function revealEarlierTranscriptEvents(\n all: readonly StreamEvent[],\n displayed: readonly StreamEvent[],\n pageSize: number = 600,\n): StreamEvent[] {\n const hidden = hiddenEarlierTranscriptCount(displayed)\n if (hidden <= 0)\n return displayed as StreamEvent[]\n // Tail preserved by reference — it may include transient live rows that\n // are never persisted (task-notification banners, warn lines).\n const tail = displayed.slice(1)\n // Seam: where the visible tail begins inside the re-materialized history.\n // The marker count was minted against the LIVE display array — which\n // holds those transient rows — so it is NOT a reliable index into `all`.\n // Anchor structurally on the tail's first turn instead (the cap cuts at\n // turn boundaries and never ON a turn-less row, so the tail's head IS\n // that turn's first event); the count is only a fallback for tails\n // without any turn-tagged event.\n const anchorTurnId = tail.find(e => e.turnId !== undefined)?.turnId\n const anchorIndex = anchorTurnId !== undefined ? all.findIndex(e => e.turnId === anchorTurnId) : -1\n const seam = anchorIndex >= 0 ? anchorIndex : Math.min(hidden, all.length)\n let from = Math.max(0, seam - Math.max(1, pageSize))\n while (from > 0 && all[from]?.turnId !== undefined && all[from]?.turnId === all[from - 1]?.turnId)\n from--\n const out = [...all.slice(from, seam), ...tail]\n if (from > 0)\n out.unshift(hiddenMarkerEvent(from))\n return out\n}\n\n/**\n * Bound a transcript event array for display. Identity below the cap\n * (no re-render churn on the hot append path); above it, drops the\n * oldest events down to {@link TRANSCRIPT_TRIM_TO_EVENTS} — extended to\n * the next turn boundary — and prepends a cumulative hidden-count\n * marker. Callers: the stream buffer's drain commit and every\n * `eventsFromTurns` replay site.\n */\nexport function capTranscriptEvents(\n events: StreamEvent[],\n max: number = MAX_TRANSCRIPT_EVENTS,\n trimTo: number = TRANSCRIPT_TRIM_TO_EVENTS,\n): StreamEvent[] {\n if (events.length <= max)\n return events\n // A custom `max` below the default `trimTo` must still cap: clamp the\n // keep-size to 80% of the cap so the hysteresis gap scales with it.\n // (Without this, `maxTranscriptEvents: 500` would compute a cut point\n // before the array even starts and silently return it uncapped.)\n const keep = Math.max(1, Math.min(trimTo, Math.floor(max * 0.8)))\n\n // Fold a prior marker into the cumulative count instead of stacking.\n let previouslyHidden = 0\n let start = 0\n const first = events[0]\n if (first && first.kind === 'info') {\n const match = HIDDEN_MARKER_RE.exec(first.text)\n if (match) {\n previouslyHidden = Number(match[1]) || 0\n start = 1\n }\n }\n\n // Aim to keep the newest `trimTo` events, then extend the cut forward\n // to the next turn boundary so no turn is ever split mid-rows. Events\n // without a turnId (separators, banners) are boundaries themselves.\n let cut = events.length - keep\n if (cut <= start)\n return events\n const turnAtCut = (i: number): string | undefined => events[i]?.turnId\n while (cut < events.length) {\n const turn = turnAtCut(cut)\n if (turn === undefined || turn !== turnAtCut(cut - 1))\n break\n cut++\n }\n // Never cut ON a turn-less row (spawn markers, banners): the reveal seam\n // anchors on the tail's first turn-tagged event, so a turn-less tail head\n // would be re-included from the re-materialized history and render twice\n // (worst case an unpaired spawn-start that reads as a phantom live child).\n // Turn-less rows are boundaries themselves, so skipping them keeps the\n // no-split-turn invariant intact.\n while (cut < events.length && turnAtCut(cut) === undefined)\n cut++\n if (cut >= events.length)\n cut = events.length - 1 // pathological turn-less/single-turn flood: keep the last event\n\n const hidden = previouslyHidden + (cut - start)\n return [hiddenMarkerEvent(hidden), ...events.slice(cut)]\n}\n","/**\n * Per-tool display metadata + one-line formatters consumed by any\n * surface that renders a `tool` event in `'formatted'` mode (see\n * `Settings.toolCallDisplay`).\n *\n * Each native tool gets a curated entry — a `displayName` verb that\n * reads in sentence case (e.g. \"Read\", \"Shell\") and a `format` callback\n * that pulls the most informative bits out of the model's raw input to\n * a single scannable line. Unknown tools (MCP servers, host-added\n * tools, future zidane additions) fall back to {@link formatToolCall}\n * returning `null` — the renderer then shows a minimal `↳ <name>` line.\n *\n * Renderer-agnostic: returns plain data (`{ target, meta }`) so the\n * TUI's React/OpenTUI surface and any future GUI consumer can paint\n * the same shape in their own style. Lives in `zidane/chat` because\n * it has no rendering concerns; the TUI just consumes it.\n */\n\nimport { utf8ByteLength } from '../compact/utils'\n\nexport interface ToolFormatLine {\n /**\n * Primary target — typically a path, command, pattern, or\n * task description. Renderer paints this in the model accent color\n * so the eye lands on it first.\n */\n target?: string\n /**\n * Secondary annotations rendered after the target, joined with\n * ` · ` separators. Use for line ranges (`L10-25`), limits, flags,\n * or any short suffix that adds context without bloating the line.\n */\n meta?: readonly string[]\n}\n\nexport interface ToolDisplayMeta {\n /**\n * Title-case display verb (e.g. `Read`, `Shell`, `Edit`). When the\n * label depends on an input field (e.g. `skills_use`'s\n * `mode: 'activate' | 'deactivate'` → `Enable` / `Disable`), supply\n * a function instead and read the field defensively. The function\n * form is called whenever {@link displayNameFor} has the call's\n * input in scope; callers without input fall back to the function's\n * `input: undefined` branch, which should return a stable default.\n */\n displayName: string | ((input: Record<string, unknown> | undefined) => string)\n /**\n * Pull a {@link ToolFormatLine} out of the raw model input. Returns\n * `null` when the shape isn't what the tool expects (typed defensively\n * — we never want a malformed call to crash the transcript).\n */\n format: (input: Record<string, unknown>) => ToolFormatLine | null\n}\n\n// ---------------------------------------------------------------------------\n// Tool registry\n// ---------------------------------------------------------------------------\n\nexport const TOOL_DISPLAY: Readonly<Record<string, ToolDisplayMeta>> = {\n // ---- Pure reads ----\n read_file: {\n displayName: 'Read',\n format: (input) => {\n const path = stringField(input, 'path')\n if (!path)\n return null\n const meta: string[] = []\n const offset = numberField(input, 'offset')\n const limit = numberField(input, 'limit')\n if (offset !== undefined && limit !== undefined && limit > 0)\n meta.push(`L${offset}–${offset + limit - 1}`)\n else if (offset !== undefined)\n meta.push(`from L${offset}`)\n else if (limit !== undefined && limit > 0)\n meta.push(`${limit} lines`)\n return { target: path, meta }\n },\n },\n list_files: {\n displayName: 'List',\n format: (input) => {\n const path = stringField(input, 'path') ?? '.'\n return { target: path }\n },\n },\n glob: {\n displayName: 'Glob',\n format: (input) => {\n const pattern = stringField(input, 'pattern')\n if (!pattern)\n return null\n const meta: string[] = []\n const limit = numberField(input, 'limit')\n if (limit !== undefined)\n meta.push(`limit ${limit}`)\n return { target: pattern, meta }\n },\n },\n grep: {\n displayName: 'Grep',\n format: (input) => {\n const pattern = stringField(input, 'pattern')\n if (!pattern)\n return null\n const target = `/${pattern}/`\n const meta: string[] = []\n const path = stringField(input, 'path')\n if (path && path !== '.')\n meta.push(`in ${path}`)\n const glob = stringField(input, 'glob')\n if (glob)\n meta.push(glob)\n const type = stringField(input, 'type')\n if (type)\n meta.push(`type:${type}`)\n if (input['-i'] === true)\n meta.push('case-insensitive')\n const mode = stringField(input, 'output_mode')\n if (mode && mode !== 'files_with_matches')\n meta.push(mode)\n return { target, meta }\n },\n },\n\n // ---- Shell ----\n shell: {\n // Verb switches when the model dispatches a background task — same\n // pattern `skills_use` uses for activate/deactivate. The transcript\n // reads as `↳ Shell (background): npm run dev` so the user can spot\n // backgrounded invocations at a glance without reading the args.\n displayName: input => input?.run_in_background === true ? 'Shell (background)' : 'Shell',\n format: (input) => {\n const command = stringField(input, 'command')\n if (!command)\n return null\n // Model-provided intent string (\"why am I running this?\") — kept as\n // meta (not target) so the command itself stays the load-bearing\n // identifier in the row. Truncate aggressively: the description is\n // context, the command is the action.\n const description = stringField(input, 'description')\n const line: ToolFormatLine = { target: truncate(command, 200) }\n if (description && description.trim() !== '')\n line.meta = [truncate(description, 100)]\n return line\n },\n },\n shell_kill: {\n displayName: 'Kill task',\n format: (input) => {\n const taskId = stringField(input, 'task_id')\n if (!taskId)\n return null\n return { target: taskId }\n },\n },\n wait_task: {\n displayName: 'Wait for task',\n format: (input) => {\n const taskId = stringField(input, 'task_id')\n if (!taskId)\n return null\n const timeoutMs = input.timeout_ms\n return {\n target: taskId,\n meta: typeof timeoutMs === 'number' ? [`${Math.round(timeoutMs / 1000)}s timeout`] : [],\n }\n },\n },\n\n // ---- Edits (renderer falls through to EditDiffBlock when showEditDiffs is on) ----\n edit: {\n displayName: 'Edit',\n format: (input) => {\n const path = stringField(input, 'path')\n if (!path)\n return null\n return {\n target: path,\n meta: input.replace_all === true ? ['replace all'] : [],\n }\n },\n },\n multi_edit: {\n displayName: 'Multi-edit',\n format: (input) => {\n const path = stringField(input, 'path')\n if (!path)\n return null\n const edits = Array.isArray(input.edits) ? input.edits.length : 0\n return {\n target: path,\n meta: edits > 0 ? [`${edits} hunk${edits === 1 ? '' : 's'}`] : [],\n }\n },\n },\n write_file: {\n displayName: 'Write',\n format: (input) => {\n const path = stringField(input, 'path')\n if (!path)\n return null\n const content = stringField(input, 'content')\n const meta: string[] = []\n if (content !== undefined) {\n // Show byte count instead of line count — write_file's main\n // failure mode is \"did you mean to overwrite a 10KB file with\n // a 4-byte one?\", so bytes catch it faster than lines do.\n const bytes = utf8ByteLength(content)\n meta.push(`${formatBytes(bytes)}`)\n }\n return { target: path, meta }\n },\n },\n\n // ---- Spawn / orchestration ----\n spawn: {\n displayName: 'Agent',\n format: (input) => {\n const task = stringField(input, 'task')\n if (!task)\n return null\n return { target: truncate(task, 120) }\n },\n },\n\n // ---- Tool search (lazy-tool discovery) ----\n tool_search: {\n displayName: 'Search tools',\n format: (input) => {\n const query = stringField(input, 'query')\n const names = Array.isArray(input.names) ? input.names.length : 0\n if (query)\n return { target: `“${query}”` }\n if (names > 0)\n return { target: `${names} tool${names === 1 ? '' : 's'}` }\n return null\n },\n },\n\n // ---- Skills ----\n skills_use: {\n // `skills_use` straddles two intents — activation (default) and\n // deactivation (`mode: 'deactivate'`, the zidane extension that lets\n // the model recover from `AgentToolNotAllowedError`). Showing \"Activate\"\n // for both modes hid the deactivation from the transcript and made\n // the model's recovery flow harder to follow. We pick the verb from\n // `input.mode`; absent or unexpected values fall back to \"Enable\" to\n // match the spec's activate-only semantics.\n displayName: (input) => {\n const mode = input ? stringField(input, 'mode') : undefined\n return mode === 'deactivate' ? 'Disable skill' : 'Enable skill'\n },\n format: (input) => {\n const name = stringField(input, 'name')\n if (!name)\n return null\n return { target: name }\n },\n },\n skills_read: {\n displayName: 'Read skill',\n format: (input) => {\n const name = stringField(input, 'name')\n const path = stringField(input, 'path')\n if (!name)\n return null\n return { target: path ? `${name}/${path}` : name }\n },\n },\n skills_run_script: {\n displayName: 'Run script',\n format: (input) => {\n const name = stringField(input, 'name')\n const script = stringField(input, 'script')\n if (!name || !script)\n return null\n const meta: string[] = [`skill ${name}`]\n const args = Array.isArray(input.args) ? input.args : null\n if (args && args.length > 0)\n meta.push(truncate(args.map(String).join(' '), 80))\n return { target: script, meta }\n },\n },\n\n // ---- Todos ----\n todowrite: {\n displayName: 'Todos',\n format: (input) => {\n const todos = Array.isArray(input.todos) ? input.todos : null\n if (!todos)\n return null\n // Show item count + per-status tally — same shape the tool's\n // `tool_result` summary line uses, so the call line and result\n // line read consistently in the transcript.\n const counts = { pending: 0, in_progress: 0, completed: 0, cancelled: 0 }\n for (const t of todos) {\n if (!t || typeof t !== 'object')\n continue\n const status = (t as Record<string, unknown>).status\n if (typeof status === 'string' && status in counts)\n counts[status as keyof typeof counts] += 1\n }\n const meta: string[] = []\n if (counts.completed)\n meta.push(`${counts.completed} done`)\n if (counts.in_progress)\n meta.push(`${counts.in_progress} in progress`)\n if (counts.pending)\n meta.push(`${counts.pending} pending`)\n if (counts.cancelled)\n meta.push(`${counts.cancelled} cancelled`)\n return { target: `${todos.length} item${todos.length === 1 ? '' : 's'}`, meta }\n },\n },\n todoread: {\n displayName: 'Todos',\n format: () => ({ target: 'read' }),\n },\n\n // ---- Interactions (already surfaced as wizards, but the call line still renders) ----\n ask_user: {\n displayName: 'Ask user',\n format: (input) => {\n const questions = Array.isArray(input.questions) ? input.questions.length : 0\n if (questions === 0)\n return null\n return { target: `${questions} question${questions === 1 ? '' : 's'}` }\n },\n },\n present_plan: {\n displayName: 'Present plan',\n format: (input) => {\n const title = stringField(input, 'title')\n if (!title)\n return null\n return { target: title }\n },\n },\n}\n\n// ---------------------------------------------------------------------------\n// Public helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the display verb for a tool. Native tools use their curated\n * entry from {@link TOOL_DISPLAY}; everything else gets a sentence-case\n * version of the raw name (`my_host_tool` → `My host tool`) so an MCP /\n * host tool still reads cleanly in the transcript without shouting\n * Title Case at every word.\n *\n * MCP convention: every tool surfaced by `mcp/connectMcpServers` is\n * namespaced as `mcp_<server>_<tool>` (see `src/mcp/index.ts`). The\n * `mcp_` prefix is plumbing — strip it before casing so the label\n * reads as `Github create issue` instead of `Mcp github create issue`.\n * The server name leads, which doubles as a free visual grouping\n * affordance (\"everything starting with `Github` came from the github\n * MCP server\").\n */\nexport function displayNameFor(\n name: string,\n input?: Record<string, unknown>,\n): string {\n const entry = TOOL_DISPLAY[name]\n if (entry) {\n return typeof entry.displayName === 'function'\n ? entry.displayName(input)\n : entry.displayName\n }\n const stripped = name.startsWith('mcp_') ? name.slice(4) : name\n return sentenceCase(stripped)\n}\n\n/**\n * Run a tool's curated formatter and return the result, or `null` when\n * no formatter is registered / the input shape doesn't match. Renderer\n * decides what to do with `null` — typically: show `↳ <displayName>`\n * with no target / meta tail.\n */\nexport function formatToolCall(name: string, input: Record<string, unknown>): ToolFormatLine | null {\n const entry = TOOL_DISPLAY[name]\n if (!entry)\n return null\n try {\n return entry.format(input)\n }\n catch {\n // Defensive — a misshapen `input` should never crash the\n // transcript. Fall back to the unformatted line.\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction stringField(input: Record<string, unknown>, key: string): string | undefined {\n const v = input[key]\n return typeof v === 'string' && v.length > 0 ? v : undefined\n}\n\nfunction numberField(input: Record<string, unknown>, key: string): number | undefined {\n const v = input[key]\n return typeof v === 'number' && Number.isFinite(v) ? v : undefined\n}\n\n/** `snake_case` / `kebab-case` / lowercase → `Sentence case`. */\nfunction sentenceCase(s: string): string {\n const words = s.split(/[-_\\s]+/).filter(Boolean).map(w => w.toLowerCase())\n if (words.length === 0)\n return ''\n words[0] = (words[0][0]?.toUpperCase() ?? '') + words[0].slice(1)\n return words.join(' ')\n}\n\n/**\n * Collapse internal whitespace (including newlines) to single spaces\n * and clip to `max` columns with a trailing `…`. The whitespace\n * normalisation is the load-bearing bit — tool input strings like a\n * shell heredoc or a multi-line Python `-c` script otherwise render\n * across several rows in the transcript even though the `↳ Tool …`\n * line is meant to be a single-line scannable summary.\n */\nfunction truncate(s: string, max: number): string {\n const clean = s.replace(/\\s+/g, ' ').trim()\n return clean.length <= max ? clean : `${clean.slice(0, max - 1)}…`\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024)\n return `${bytes} B`\n if (bytes < 1024 * 1024)\n return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n","/**\n * Pure transforms on `SessionTurn[]` used by the TUI's turn-selection\n * modal actions (fork / delete / copy). Each helper is renderer- and\n * store-agnostic so it composes the same in TUI, SDK, or test code.\n *\n * Tool-call protocol invariant the helpers preserve:\n *\n * Every `tool_call` block emitted by an assistant turn MUST be matched\n * by a `tool_result` block (same `callId`) in a later turn before the\n * next assistant turn. Providers reject histories that violate this —\n * so any operation that mutates the turn list must either keep pairs\n * intact or strip both sides.\n */\n\nimport type { SessionContentBlock, SessionTurn } from '../types'\n\n/**\n * Fork — keep every turn up to and including `turnId`, then strip any\n * `tool_call` blocks left without a matching `tool_result` in the slice.\n *\n * Semantics:\n * - Include the selected turn (\"branch from HERE\" mental model — the\n * user wants the selected message to be the latest in the fork).\n * - If the selected turn is an assistant turn with unresolved\n * `tool_call` blocks (their `tool_result`s live in turns AFTER the\n * slice), strip those calls. Otherwise the fork would post an\n * assistant turn with no matching tool results, breaking the next\n * provider call.\n * - Drop turns that become empty (all blocks stripped).\n *\n * Returns `null` when `turnId` doesn't exist in `turns` — caller should\n * surface a \"turn not found\" error rather than silently no-op.\n */\nexport function truncateTurnsAt(turns: readonly SessionTurn[], turnId: string): SessionTurn[] | null {\n const idx = turns.findIndex(t => t.id === turnId)\n if (idx === -1)\n return null\n const slice = turns.slice(0, idx + 1)\n return stripOrphanToolBlocks(slice)\n}\n\n/**\n * Delete — remove the turn with `turnId` and any tool blocks left\n * orphaned by the removal. Returns `null` when `turnId` doesn't exist.\n *\n * Strategy:\n * 1. Drop the target turn.\n * 2. Scan the remaining turns for `tool_call`s without a matching\n * `tool_result` (orphaned by removing the user turn that carried\n * the result), and `tool_result`s without a matching `tool_call`\n * (orphaned by removing the assistant turn that issued the call).\n * Strip both sides.\n * 3. Drop turns whose content is now empty.\n *\n * This guarantees the resulting history is protocol-clean — a follow-up\n * `agent.run()` against the modified session can post turns without the\n * provider rejecting the history.\n */\nexport function deleteTurnSafely(turns: readonly SessionTurn[], turnId: string): SessionTurn[] | null {\n const idx = turns.findIndex(t => t.id === turnId)\n if (idx === -1)\n return null\n const without = [...turns.slice(0, idx), ...turns.slice(idx + 1)]\n return stripOrphanToolBlocks(without)\n}\n\n/**\n * Walk a turn list and remove any tool blocks whose counterpart is\n * missing. Drops turns left empty. Used by `truncateTurnsAt` (which can\n * leave `tool_call`s orphaned when their results are past the cut) and\n * `deleteTurnSafely` (which can orphan either side of a pair).\n *\n * Pure / total: returns a new array; never throws.\n */\nfunction stripOrphanToolBlocks(turns: readonly SessionTurn[]): SessionTurn[] {\n const callIds = new Set<string>()\n const resultIds = new Set<string>()\n for (const turn of turns) {\n for (const block of turn.content) {\n if (block.type === 'tool_call')\n callIds.add(block.id)\n else if (block.type === 'tool_result')\n resultIds.add(block.callId)\n }\n }\n const result: SessionTurn[] = []\n for (const turn of turns) {\n const filtered: SessionContentBlock[] = []\n for (const block of turn.content) {\n if (block.type === 'tool_call') {\n if (!resultIds.has(block.id))\n continue // call lost its result\n }\n else if (block.type === 'tool_result') {\n if (!callIds.has(block.callId))\n continue // result lost its call\n }\n filtered.push(block)\n }\n if (filtered.length === 0)\n continue // turn is now empty — drop it\n result.push(filtered.length === turn.content.length ? turn : { ...turn, content: filtered })\n }\n return result\n}\n\n/**\n * Serialize a turn's content to a clean text representation suited for\n * the clipboard. Joins text + thinking blocks verbatim; tool calls and\n * tool results get bracketed labels so the user can paste a readable\n * record of what happened without losing structure.\n *\n * Empty turns return `''`.\n */\nexport function turnAsText(turn: SessionTurn): string {\n const parts: string[] = []\n for (const block of turn.content) {\n if (block.type === 'text' && block.text.trim())\n parts.push(block.text)\n else if (block.type === 'thinking' && block.text.trim())\n parts.push(`[thinking]\\n${block.text}`)\n else if (block.type === 'tool_call')\n parts.push(`[tool call · ${block.name}]\\n${stringifyArgs(block.input)}`)\n else if (block.type === 'tool_result')\n parts.push(`[tool result]\\n${typeof block.output === 'string' ? block.output : JSON.stringify(block.output, null, 2)}`)\n else if (block.type === 'compact-summary')\n parts.push(`[compaction summary · ${block.replacesTurnIds.length} turn${block.replacesTurnIds.length === 1 ? '' : 's'}]\\n${block.summary}`)\n }\n return parts.join('\\n\\n')\n}\n\nfunction stringifyArgs(input: Record<string, unknown>): string {\n try {\n return JSON.stringify(input, null, 2)\n }\n catch {\n return String(input)\n }\n}\n\n/**\n * Count turns before / after the one identified by `turnId` in the\n * given list. Returns `null` when the id is missing. Used to label the\n * turn-details modal with `N before · M after`.\n */\nexport function countNeighbors(\n turnIds: readonly string[],\n turnId: string,\n): { before: number, after: number } | null {\n const idx = turnIds.indexOf(turnId)\n if (idx === -1)\n return null\n return { before: idx, after: turnIds.length - 1 - idx }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { $c as CompletionProvider, Bu as StreamEvent, Fu as Owner, Hf as TurnUsage, Mu as EditOutcome, Nf as ToolResultContent, Pu as EditPayload, Tf as SessionTurn, ap as SkillConfig, el as CompletionReference } from "./index-l0wehkWU.js";
2
- import { v as ApprovalDecision } from "./tool-formatters-BSwVkSX2.js";
2
+ import { B as ApprovalDecision } from "./tool-formatters-DdgS-xE2.js";
3
3
 
4
4
  //#region src/chat/color-gradient.d.ts
5
5
  /**
@@ -672,4 +672,4 @@ declare function countNeighbors(turnIds: readonly string[], turnId: string): {
672
672
  } | null;
673
673
  //#endregion
674
674
  export { uniqueFilesFromReferences as $, buildUnifiedDiff as A, buildEditOutcomesAnnotation as B, EditSummary as C, PreviewResult as D, InlineSegment as E, previewEditPayload as F, rewriteMultiEditHeader as G, mergeApprovalAndBodyOutcomes as H, splitLines as I, SKILLS_TRIGGER as J, stripEditOutcomesAnnotation as K, summarizeEditPayload as L, computeLineDiff as M, extractEditPayload as N, applyEditPayload as O, filetypeFromPath as P, createFilesCompletionProvider as Q, tokenize as R, EditHunkSummary as S, InlineDiff as T, parseEditOutcomesFromResult as U, maskToOutcomeKinds as V, resolveApprovalForPayload as W, uniqueSkillNamesFromReferences as X, createSkillsCompletionProvider as Y, FILES_TRIGGER as Z, formatTaskSummary as _, MAX_TRANSCRIPT_EVENTS as a, ChatReferenceEntry as at, DiffLine as b, finalizeStreamingMarkdown as c, createChatsCompletionProvider as ct, ageString as d, buildLinearRamp as dt, FileEntry as et, compactPath as f, formatTaskStatus as g, formatDuration as h, turnAsText as i, ChatReferenceData as it, computeInlineDiff as j, buildContextualDiff as k, finalizeStreamingMarkdownForOwner as l, uniqueChatIdsFromReferences as lt, fmtTokens as m, deleteTurnSafely as n, listProjectFiles as nt, TRANSCRIPT_TRIM_TO_EVENTS as o, ChatReferenceScope as ot, fmtCost as p, summarizeOutcomes as q, truncateTurnsAt as r, CHATS_TRIGGER as rt, capTranscriptEvents as s, chatReferenceTokensFromText as st, countNeighbors as t, ListProjectFilesOptions as tt, turnContextSize as u, blendHsl as ut, previewLine as v, HunkResolution as w, DiffOp as x, shortId as y, ResolvedApproval as z };
675
- //# sourceMappingURL=turn-operations-CjkgQKmR.d.ts.map
675
+ //# sourceMappingURL=turn-operations-sE-Sli9H.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"turn-operations-CjkgQKmR.d.ts","names":[],"sources":["../src/chat/color-gradient.ts","../src/chat/completion-chats.ts","../src/chat/files-discovery.ts","../src/chat/completion-files.ts","../src/chat/completion-skills.ts","../src/chat/edit-approval.ts","../src/tools/edit-utils.ts","../src/chat/edit-diff.ts","../src/chat/format.ts","../src/chat/streaming-pure.ts","../src/chat/turn-operations.ts"],"mappings":"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"}
1
+ {"version":3,"file":"turn-operations-sE-Sli9H.d.ts","names":[],"sources":["../src/chat/color-gradient.ts","../src/chat/completion-chats.ts","../src/chat/files-discovery.ts","../src/chat/completion-files.ts","../src/chat/completion-skills.ts","../src/chat/edit-approval.ts","../src/tools/edit-utils.ts","../src/chat/edit-diff.ts","../src/chat/format.ts","../src/chat/streaming-pure.ts","../src/chat/turn-operations.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zidane",
3
- "version": "6.2.13",
3
+ "version": "6.2.15",
4
4
  "description": "an agent that goes straight to the goal",
5
5
  "type": "module",
6
6
  "private": false,