markform 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
- import { t as runCli } from "./cli-C8F9yDsv.mjs";
2
+ import { t as runCli } from "./cli-ZcOC47KK.mjs";
3
3
 
4
4
  export { runCli };
@@ -167,10 +167,7 @@ function renderViewContent(form) {
167
167
  html += `<div class="view-field-label">${escapeHtml(field.label)}`;
168
168
  html += ` <span class="type-badge">${field.kind}</span>`;
169
169
  if (field.required) html += " <span class=\"required\">*</span>";
170
- if (isSkipped) {
171
- const reasonText = skipReason ? `Skipped: ${escapeHtml(skipReason)}` : "Skipped";
172
- html += ` <span class="skipped-badge">${reasonText}</span>`;
173
- }
170
+ if (isSkipped) html += ` <span class="skipped-badge">Skipped</span>`;
174
171
  html += "</div>";
175
172
  html += renderViewFieldValue(field, value, isSkipped, skipReason);
176
173
  html += "</div>";
@@ -1253,4 +1250,4 @@ function renderFillRecordContent(record) {
1253
1250
 
1254
1251
  //#endregion
1255
1252
  export { renderJsonContent as a, renderViewContent as c, formatDuration as d, formatTokens as f, highlightYamlValue as i, renderYamlContent as l, FILL_RECORD_STYLES as n, renderMarkdownContent as o, renderFillRecordContent as r, renderSourceContent as s, FILL_RECORD_SCRIPTS as t, escapeHtml as u };
1256
- //# sourceMappingURL=fillRecordRenderer-CruJrLkj.mjs.map
1253
+ //# sourceMappingURL=fillRecordRenderer-VBQ2vwPV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fillRecordRenderer-VBQ2vwPV.mjs","names":[],"sources":["../src/render/renderUtils.ts","../src/render/contentRenderers.ts","../src/render/fillRecordRenderer.ts"],"sourcesContent":["/**\n * Rendering utility functions for HTML generation.\n *\n * Pure utility functions used across all renderers. No CLI or server dependencies.\n */\n\n/**\n * Escape HTML special characters.\n */\nexport function escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\n/**\n * Format milliseconds as human-readable duration.\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms.toFixed(0)}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n const minutes = Math.floor(ms / 60000);\n const seconds = ((ms % 60000) / 1000).toFixed(0);\n return `${minutes}m ${seconds}s`;\n}\n\n/**\n * Format token count with K suffix for large numbers.\n */\nexport function formatTokens(count: number): string {\n if (count >= 10000) return `${(count / 1000).toFixed(1)}k`;\n if (count >= 1000) return `${(count / 1000).toFixed(1)}k`;\n return count.toLocaleString();\n}\n","/**\n * Content-only HTML renderers for form views and syntax-highlighted content.\n *\n * These produce HTML fragments (no page shell) suitable for embedding.\n * No CLI or server dependencies.\n */\n\nimport type { Field, FieldValue, ParsedForm } from '../engine/coreTypes.js';\nimport { friendlyUrlAbbrev, formatBareUrlsAsHtmlLinks } from '../utils/urlFormat.js';\nimport { escapeHtml } from './renderUtils.js';\n\n// =============================================================================\n// View Content Renderer\n// =============================================================================\n\n/**\n * Format a checkbox state for display.\n */\nfunction formatCheckboxState(state: string): string {\n switch (state) {\n case 'done':\n return '<span class=\"checkbox checked\">☑</span>';\n case 'todo':\n return '<span class=\"checkbox unchecked\">☐</span>';\n case 'active':\n return '<span class=\"state-badge state-active\">●</span>';\n case 'incomplete':\n return '<span class=\"state-badge state-incomplete\">○</span>';\n case 'na':\n return '<span class=\"state-badge state-na\">—</span>';\n case 'yes':\n return '<span class=\"checkbox checked\">☑</span>';\n case 'no':\n return '<span class=\"checkbox unchecked\">☐</span>';\n case 'unfilled':\n return '<span class=\"state-badge state-unfilled\">?</span>';\n default:\n return `<span class=\"state-badge\">${escapeHtml(state)}</span>`;\n }\n}\n\n/**\n * Render a field value for the View tab.\n */\nfunction renderViewFieldValue(\n field: Field,\n value: FieldValue | undefined,\n isSkipped: boolean,\n skipReason?: string,\n): string {\n if (isSkipped) {\n const reasonText = skipReason ? `(skipped: ${escapeHtml(skipReason)})` : '(skipped)';\n return `<div class=\"view-field-empty\">${reasonText}</div>`;\n }\n\n if (value === undefined) {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n\n switch (field.kind) {\n case 'string': {\n const v = value.kind === 'string' ? value.value : null;\n if (v === null || v === '') {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n // Auto-link bare URLs in string content for consistency with URL fields\n const formatted = formatBareUrlsAsHtmlLinks(v, escapeHtml);\n return `<div class=\"view-field-value\">${formatted}</div>`;\n }\n case 'number': {\n const v = value.kind === 'number' ? value.value : null;\n if (v === null) {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n return `<div class=\"view-field-value\">${v}</div>`;\n }\n case 'string_list': {\n const items = value.kind === 'string_list' ? value.items : [];\n if (items.length === 0) {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n // Auto-link bare URLs in string list items\n return `<div class=\"view-field-value\"><ul>${items.map((i) => `<li>${formatBareUrlsAsHtmlLinks(i, escapeHtml)}</li>`).join('')}</ul></div>`;\n }\n case 'single_select': {\n const selected = value.kind === 'single_select' ? value.selected : null;\n if (selected === null) {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n const opt = field.options.find((o) => o.id === selected);\n return `<div class=\"view-field-value\">${escapeHtml(opt?.label ?? selected)}</div>`;\n }\n case 'multi_select': {\n const selected = value.kind === 'multi_select' ? value.selected : [];\n // Show all options with selection state\n const items = field.options.map((opt) => {\n const isSelected = selected.includes(opt.id);\n const checkbox = isSelected\n ? '<span class=\"checkbox checked\">☑</span>'\n : '<span class=\"checkbox unchecked\">☐</span>';\n return `<li class=\"checkbox-item\">${checkbox} ${escapeHtml(opt.label)}</li>`;\n });\n return `<div class=\"view-field-value\"><ul class=\"checkbox-list\">${items.join('')}</ul></div>`;\n }\n case 'checkboxes': {\n const values = value.kind === 'checkboxes' ? value.values : {};\n const mode = field.checkboxMode ?? 'multi';\n // Show all options with their state\n const items = field.options.map((opt) => {\n const state = values[opt.id] ?? (mode === 'explicit' ? 'unfilled' : 'todo');\n // For simple mode, use checkbox symbols\n if (mode === 'simple') {\n const checkbox =\n state === 'done'\n ? '<span class=\"checkbox checked\">☑</span>'\n : '<span class=\"checkbox unchecked\">☐</span>';\n return `<li class=\"checkbox-item\">${checkbox} ${escapeHtml(opt.label)}</li>`;\n }\n // For multi/explicit modes, show state text since there are multiple states\n const stateDisplay = formatCheckboxState(state);\n return `<li class=\"checkbox-item\">${stateDisplay} ${escapeHtml(opt.label)}</li>`;\n });\n return `<div class=\"view-field-value\"><ul class=\"checkbox-list\">${items.join('')}</ul></div>`;\n }\n case 'url': {\n const v = value.kind === 'url' ? value.value : null;\n if (v === null || v === '') {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n const domain = friendlyUrlAbbrev(v);\n return `<div class=\"view-field-value\"><a href=\"${escapeHtml(v)}\" target=\"_blank\" class=\"url-link\" data-url=\"${escapeHtml(v)}\">${escapeHtml(domain)}</a></div>`;\n }\n case 'url_list': {\n const items = value.kind === 'url_list' ? value.items : [];\n if (items.length === 0) {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n return `<div class=\"view-field-value\"><ul>${items\n .map((u) => {\n const domain = friendlyUrlAbbrev(u);\n return `<li><a href=\"${escapeHtml(u)}\" target=\"_blank\" class=\"url-link\" data-url=\"${escapeHtml(u)}\">${escapeHtml(domain)}</a></li>`;\n })\n .join('')}</ul></div>`;\n }\n case 'date': {\n const v = value.kind === 'date' ? value.value : null;\n if (v === null || v === '') {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n return `<div class=\"view-field-value\">${escapeHtml(v)}</div>`;\n }\n case 'year': {\n const v = value.kind === 'year' ? value.value : null;\n if (v === null) {\n return '<div class=\"view-field-empty\">(not filled)</div>';\n }\n return `<div class=\"view-field-value\">${v}</div>`;\n }\n case 'table': {\n const rows = value.kind === 'table' ? value.rows : [];\n if (rows.length === 0) {\n return '<div class=\"view-field-empty\">(no data)</div>';\n }\n let tableHtml = '<div class=\"table-container\"><table class=\"data-table\">';\n tableHtml += '<thead><tr>';\n for (const col of field.columns) {\n tableHtml += `<th>${escapeHtml(col.label)}</th>`;\n }\n tableHtml += '</tr></thead><tbody>';\n for (const row of rows) {\n tableHtml += '<tr>';\n for (const col of field.columns) {\n const cell = row[col.id];\n let cellValue = '';\n let cellHtml = '';\n if (cell?.state === 'answered' && cell.value !== undefined && cell.value !== null) {\n cellValue = String(cell.value);\n // Format URL columns as domain links\n if (col.type === 'url' && cellValue) {\n const domain = friendlyUrlAbbrev(cellValue);\n cellHtml = `<a href=\"${escapeHtml(cellValue)}\" target=\"_blank\" class=\"url-link\" data-url=\"${escapeHtml(cellValue)}\">${escapeHtml(domain)}</a>`;\n } else {\n // Auto-link bare URLs in non-URL columns for consistency\n cellHtml = formatBareUrlsAsHtmlLinks(cellValue, escapeHtml);\n }\n }\n tableHtml += `<td>${cellHtml}</td>`;\n }\n tableHtml += '</tr>';\n }\n tableHtml += '</tbody></table></div>';\n return tableHtml;\n }\n default: {\n const _exhaustive: never = field;\n throw new Error(`Unhandled field kind: ${(_exhaustive as { kind: string }).kind}`);\n }\n }\n}\n\n/**\n * Render form view content (read-only display of form fields).\n * Used for View tab content.\n */\nexport function renderViewContent(form: ParsedForm): string {\n const { schema, responsesByFieldId } = form;\n let html = '<div class=\"view-content\">';\n\n for (const group of schema.groups) {\n const groupTitle = group.title ?? group.id;\n html += `<div class=\"view-group\"><h2>${escapeHtml(groupTitle)}</h2>`;\n\n for (const field of group.children) {\n const response = responsesByFieldId[field.id];\n const value = response?.state === 'answered' ? response.value : undefined;\n const isSkipped = response?.state === 'skipped';\n const skipReason = isSkipped ? response?.reason : undefined;\n\n html += '<div class=\"view-field\">';\n html += `<div class=\"view-field-label\">${escapeHtml(field.label)}`;\n html += ` <span class=\"type-badge\">${field.kind}</span>`;\n if (field.required) {\n html += ' <span class=\"required\">*</span>';\n }\n if (isSkipped) {\n html += ` <span class=\"skipped-badge\">Skipped</span>`;\n }\n html += '</div>';\n\n // Render value based on field type\n html += renderViewFieldValue(field, value, isSkipped, skipReason);\n html += '</div>';\n }\n\n html += '</div>';\n }\n\n html += '</div>';\n return html;\n}\n\n// =============================================================================\n// Source Content Renderer\n// =============================================================================\n\n/**\n * Highlight a single line of source code (Markdown + Jinja).\n */\nfunction highlightSourceLine(line: string): string {\n // First escape HTML\n let result = escapeHtml(line);\n\n // Highlight Jinja tags: {% tag %}, {% /tag %}, {# comment #}\n // Match {% ... %} patterns\n result = result.replace(\n /(\\{%\\s*)([a-zA-Z_/]+)(\\s+[^%]*)?(%\\})/g,\n (_: string, open: string, keyword: string, attrs: string | undefined, close: string) => {\n let attrHtml = '';\n if (attrs) {\n // Highlight attributes within the tag\n attrHtml = attrs.replace(\n /([a-zA-Z_]+)(=)(\"[^\"]*\"|&#039;[^&#]*&#039;|[^\\s%]+)?/g,\n (_m: string, attrName: string, eq: string, attrValue: string) => {\n const valueHtml = attrValue ? `<span class=\"syn-jinja-value\">${attrValue}</span>` : '';\n return `<span class=\"syn-jinja-attr\">${attrName}</span>${eq}${valueHtml}`;\n },\n );\n }\n return `<span class=\"syn-jinja-tag\">${open}</span><span class=\"syn-jinja-keyword\">${keyword}</span>${attrHtml}<span class=\"syn-jinja-tag\">${close}</span>`;\n },\n );\n\n // Highlight Jinja comments: {# ... #}\n result = result.replace(/(\\{#)(.*?)(#\\})/g, `<span class=\"syn-comment\">$1$2$3</span>`);\n\n // Highlight Markdown headers\n result = result.replace(/^(#{1,6}\\s.*)$/gm, '<span class=\"syn-md-header\">$1</span>');\n\n // Highlight YAML frontmatter markers\n if (result === '---') {\n result = '<span class=\"syn-comment\">---</span>';\n }\n\n return result;\n}\n\n/**\n * Render source content with Markdown and Jinja syntax highlighting.\n * Used for Source tab content.\n */\nexport function renderSourceContent(content: string): string {\n const lines = content.split('\\n');\n const highlighted = lines.map((line) => highlightSourceLine(line)).join('\\n');\n return `<pre>${highlighted}</pre>`;\n}\n\n// =============================================================================\n// Markdown Content Renderer\n// =============================================================================\n\n/**\n * Format inline markdown (bold, italic, code, links, checkboxes).\n * Also auto-links bare URLs for consistency.\n */\nfunction formatInlineMarkdown(text: string): string {\n let result = escapeHtml(text);\n // Checkboxes - render before other formatting to avoid conflicts\n // Checked checkbox [x] or [X]\n result = result.replace(/\\[x\\]/gi, '<span class=\"checkbox checked\">☑</span>');\n // Unchecked checkbox [ ]\n result = result.replace(/\\[ \\]/g, '<span class=\"checkbox unchecked\">☐</span>');\n // Inline code\n result = result.replace(/`([^`]+)`/g, '<code>$1</code>');\n // Bold\n result = result.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');\n // Italic\n result = result.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');\n // Links - need to unescape the URL first\n // Add url-link class and data-url for copy tooltip support\n result = result.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_: string, linkText: string, url: string) => {\n const cleanUrl = url.replace(/&amp;/g, '&');\n return `<a href=\"${cleanUrl}\" target=\"_blank\" class=\"url-link\" data-url=\"${cleanUrl}\">${linkText}</a>`;\n },\n );\n // Auto-link bare URLs (not already in <a> tags or markdown links)\n // Uses negative lookbehind to skip URLs that are:\n // - Inside href=\"\" or data-url=\"\" attributes\n // - Inside anchor tag content (preceded by \">)\n // - Part of markdown link syntax ](\n result = result.replace(\n /(?<!href=\"|data-url=\"|\">|\\]\\()(?:https?:\\/\\/|www\\.)[^\\s<>\"]+(?<![.,;:!?'\")])/g,\n (url: string) => {\n // Unescape &amp; back to & for the URL\n const cleanUrl = url.replace(/&amp;/g, '&');\n const fullUrl = cleanUrl.startsWith('www.') ? `https://${cleanUrl}` : cleanUrl;\n const display = friendlyUrlAbbrev(fullUrl);\n return `<a href=\"${escapeHtml(fullUrl)}\" target=\"_blank\" class=\"url-link\" data-url=\"${escapeHtml(fullUrl)}\">${escapeHtml(display)}</a>`;\n },\n );\n return result;\n}\n\n/**\n * Render markdown content (content only, no page wrapper).\n * Used for tab content.\n */\nexport function renderMarkdownContent(content: string): string {\n const lines = content.split('\\n');\n let html = '<div class=\"markdown-content\">';\n let inParagraph = false;\n let inCodeBlock = false;\n let codeBlockContent = '';\n let inUnorderedList = false;\n let inOrderedList = false;\n let inTable = false;\n let tableHeaderDone = false;\n\n // Helper to close any open list\n const closeList = () => {\n if (inUnorderedList) {\n html += '</ul>';\n inUnorderedList = false;\n }\n if (inOrderedList) {\n html += '</ol>';\n inOrderedList = false;\n }\n };\n\n // Helper to close table\n const closeTable = () => {\n if (inTable) {\n html += '</tbody></table></div>';\n inTable = false;\n tableHeaderDone = false;\n }\n };\n\n // Helper to detect if a line is a table row\n const isTableRow = (line: string): boolean => {\n const trimmed = line.trim();\n return trimmed.startsWith('|') && trimmed.endsWith('|') && trimmed.includes('|');\n };\n\n // Helper to detect table separator line (| --- | --- |)\n const isTableSeparator = (line: string): boolean => {\n const trimmed = line.trim();\n return /^\\|[\\s-:|]+\\|$/.test(trimmed);\n };\n\n // Helper to parse table cells\n const parseTableCells = (line: string): string[] => {\n const trimmed = line.trim();\n // Remove leading and trailing pipes, then split by pipes\n const cellContent = trimmed.slice(1, -1);\n return cellContent.split('|').map((cell) => cell.trim());\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Handle fenced code blocks\n if (trimmed.startsWith('```')) {\n if (inCodeBlock) {\n // End code block\n html += `<pre><code>${escapeHtml(codeBlockContent.trim())}</code></pre>`;\n codeBlockContent = '';\n inCodeBlock = false;\n } else {\n // Start code block\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n closeList();\n closeTable();\n inCodeBlock = true;\n }\n continue;\n }\n\n if (inCodeBlock) {\n codeBlockContent += line + '\\n';\n continue;\n }\n\n // Handle table rows\n if (isTableRow(trimmed)) {\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n closeList();\n\n // Skip separator line but mark header as done\n if (isTableSeparator(trimmed)) {\n tableHeaderDone = true;\n continue;\n }\n\n const cells = parseTableCells(trimmed);\n\n if (!inTable) {\n // Start new table with header\n html += '<div class=\"table-container\"><table class=\"data-table\"><thead><tr>';\n for (const cell of cells) {\n html += `<th>${formatInlineMarkdown(cell)}</th>`;\n }\n html += '</tr></thead><tbody>';\n inTable = true;\n } else if (tableHeaderDone) {\n // Regular table row\n html += '<tr>';\n for (const cell of cells) {\n html += `<td>${formatInlineMarkdown(cell)}</td>`;\n }\n html += '</tr>';\n }\n continue;\n }\n\n // Close table if we hit a non-table line\n if (inTable && !isTableRow(trimmed)) {\n closeTable();\n }\n\n // Handle headers\n if (trimmed.startsWith('# ')) {\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n closeList();\n html += `<h2>${formatInlineMarkdown(trimmed.slice(2))}</h2>`;\n } else if (trimmed.startsWith('## ')) {\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n closeList();\n html += `<h3>${formatInlineMarkdown(trimmed.slice(3))}</h3>`;\n } else if (trimmed.startsWith('### ')) {\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n closeList();\n html += `<h4>${formatInlineMarkdown(trimmed.slice(4))}</h4>`;\n } else if (trimmed.startsWith('#### ')) {\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n closeList();\n html += `<h5>${formatInlineMarkdown(trimmed.slice(5))}</h5>`;\n } else if (trimmed.startsWith('- ') || trimmed.startsWith('* ')) {\n // Unordered list item\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n if (inOrderedList) {\n html += '</ol>';\n inOrderedList = false;\n }\n if (!inUnorderedList) {\n html += '<ul>';\n inUnorderedList = true;\n }\n const itemContent = trimmed.slice(2);\n // If item starts with checkbox, use no-bullet class\n const hasCheckbox = /^\\[[ xX]\\]/.test(itemContent);\n const liClass = hasCheckbox ? ' class=\"checkbox-item\"' : '';\n html += `<li${liClass}>${formatInlineMarkdown(itemContent)}</li>`;\n } else if (/^\\d+\\.\\s/.test(trimmed)) {\n // Ordered list item\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n if (inUnorderedList) {\n html += '</ul>';\n inUnorderedList = false;\n }\n if (!inOrderedList) {\n html += '<ol>';\n inOrderedList = true;\n }\n const text = trimmed.replace(/^\\d+\\.\\s/, '');\n html += `<li>${formatInlineMarkdown(text)}</li>`;\n } else if (trimmed === '') {\n if (inParagraph) {\n html += '</p>';\n inParagraph = false;\n }\n closeList();\n } else {\n closeList();\n if (!inParagraph) {\n html += '<p>';\n inParagraph = true;\n } else {\n html += '<br>';\n }\n html += formatInlineMarkdown(trimmed);\n }\n }\n\n if (inParagraph) {\n html += '</p>';\n }\n closeList();\n closeTable();\n\n html += '</div>';\n return html;\n}\n\n// =============================================================================\n// Syntax-Highlighted Content Renderers\n// =============================================================================\n\n/**\n * Highlight a YAML value with appropriate syntax class.\n */\nexport function highlightYamlValue(value: string): string {\n const trimmed = value.trim();\n // Booleans\n if (trimmed === 'true' || trimmed === 'false') {\n return `<span class=\"syn-bool\">${escapeHtml(value)}</span>`;\n }\n // Null\n if (trimmed === 'null' || trimmed === '~') {\n return `<span class=\"syn-null\">${escapeHtml(value)}</span>`;\n }\n // Numbers\n if (/^-?\\d+\\.?\\d*$/.test(trimmed)) {\n return `<span class=\"syn-number\">${escapeHtml(value)}</span>`;\n }\n // Quoted strings\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return `<span class=\"syn-string\">${escapeHtml(value)}</span>`;\n }\n // Unquoted strings (treat as string)\n return `<span class=\"syn-string\">${escapeHtml(value)}</span>`;\n}\n\n/**\n * Render YAML content with syntax highlighting (content only, no page wrapper).\n * Used for tab content.\n */\nexport function renderYamlContent(content: string): string {\n const highlighted = content\n .split('\\n')\n .map((line) => {\n if (line.trim().startsWith('#')) {\n return `<span class=\"syn-comment\">${escapeHtml(line)}</span>`;\n }\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0 && !line.trim().startsWith('-')) {\n const key = escapeHtml(line.slice(0, colonIndex));\n const afterColon = line.slice(colonIndex + 1).trim();\n const colonAndSpace = escapeHtml(line.slice(colonIndex, colonIndex + 1));\n if (afterColon === '') {\n return `<span class=\"syn-key\">${key}</span>${colonAndSpace}`;\n }\n const valueStart = line.indexOf(afterColon, colonIndex);\n const beforeValue = escapeHtml(line.slice(colonIndex, valueStart));\n const value = highlightYamlValue(afterColon);\n return `<span class=\"syn-key\">${key}</span>${beforeValue}${value}`;\n }\n if (line.trim().startsWith('-')) {\n const dashIndex = line.indexOf('-');\n const beforeDash = escapeHtml(line.slice(0, dashIndex));\n const afterDash = line.slice(dashIndex + 1).trim();\n if (afterDash === '') {\n return `${beforeDash}-`;\n }\n return `${beforeDash}- ${highlightYamlValue(afterDash)}`;\n }\n return escapeHtml(line);\n })\n .join('\\n');\n\n return `<pre>${highlighted}</pre>`;\n}\n\n/**\n * Render JSON content with syntax highlighting (content only, no page wrapper).\n * Used for tab content.\n */\nexport function renderJsonContent(content: string): string {\n let formatted: string;\n try {\n const parsed = JSON.parse(content) as unknown;\n formatted = JSON.stringify(parsed, null, 2);\n } catch {\n formatted = content;\n }\n\n const highlighted = formatted\n .replace(/\"([^\"]+)\":/g, '<span class=\"syn-key\">\"$1\"</span>:')\n .replace(/: \"([^\"]*)\"/g, ': <span class=\"syn-string\">\"$1\"</span>')\n .replace(/: (-?\\d+\\.?\\d*)/g, ': <span class=\"syn-number\">$1</span>')\n .replace(/: (true|false)/g, ': <span class=\"syn-bool\">$1</span>')\n .replace(/: (null)/g, ': <span class=\"syn-null\">$1</span>');\n\n return `<pre>${highlighted}</pre>`;\n}\n","/**\n * Fill record HTML renderer and associated styles/scripts.\n *\n * Renders FillRecord data as an interactive dashboard with Gantt timeline,\n * progress bars, tool summaries, and turn details. No CLI or server dependencies.\n */\n\nimport YAML from 'yaml';\n\nimport type { FillRecord } from '../harness/fillRecord.js';\nimport { escapeHtml, formatDuration, formatTokens } from './renderUtils.js';\nimport { renderYamlContent } from './contentRenderers.js';\n\n// =============================================================================\n// Fill Record Interactive Scripts\n// =============================================================================\n\n/**\n * JavaScript for fill record interactive features.\n * Consumers should include this in a <script> tag on their page.\n * Provides: frShowTip(el), frHideTip(), frCopyYaml(btn)\n */\nexport const FILL_RECORD_SCRIPTS = `\n// Copy YAML content handler for Fill Record tab (must be global for dynamically loaded content)\nfunction frCopyYaml(btn) {\n const pre = btn.parentElement.querySelector('pre');\n navigator.clipboard.writeText(pre.textContent).then(() => {\n const orig = btn.textContent;\n btn.textContent = 'Copied!';\n setTimeout(() => btn.textContent = orig, 1500);\n });\n}\n\n// Tooltip handlers for Fill Record visualizations (must be global for dynamically loaded content)\nfunction frShowTip(el) {\n var tip = document.getElementById('fr-tooltip');\n if (tip && el.dataset.tooltip) {\n tip.textContent = el.dataset.tooltip;\n // Position tooltip centered above the element\n var rect = el.getBoundingClientRect();\n tip.style.left = (rect.left + rect.width / 2) + 'px';\n tip.style.top = (rect.top - 8) + 'px';\n tip.style.transform = 'translate(-50%, -100%)';\n tip.classList.add('visible');\n }\n}\nfunction frHideTip() {\n var tip = document.getElementById('fr-tooltip');\n if (tip) tip.classList.remove('visible');\n}\n`;\n\n// =============================================================================\n// Private Helpers\n// =============================================================================\n\n/**\n * Format a patch value for display.\n * Shows full content - the container has max-height with scroll for long values.\n */\nfunction formatPatchValue(value: unknown): string {\n if (value === null || value === undefined) {\n return '<em class=\"fr-turn__patch-value--clear\">(cleared)</em>';\n }\n if (typeof value === 'string') {\n return escapeHtml(value);\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n // Arrays and objects - show full JSON\n return escapeHtml(JSON.stringify(value, null, 2));\n}\n\n/**\n * Render patches from a fill_form tool call input.\n * Returns HTML for the patch details section.\n */\nfunction renderPatchDetails(input: Record<string, unknown>): string {\n const patches = input.patches;\n if (!Array.isArray(patches) || patches.length === 0) {\n return '';\n }\n\n const patchHtml = patches\n .map((patch: unknown) => {\n if (!patch || typeof patch !== 'object') return '';\n const p = patch as Record<string, unknown>;\n const op = typeof p.op === 'string' ? p.op : 'unknown';\n const fieldId =\n typeof p.fieldId === 'string' ? p.fieldId : typeof p.noteId === 'string' ? p.noteId : '';\n\n // Determine the display based on operation type\n const opLabel = op.replace(/_/g, ' ');\n let valueHtml = '';\n\n if (op === 'skip_field') {\n valueHtml = '<em class=\"fr-turn__patch-value--skip\">(skipped)</em>';\n } else if (op === 'abort_field') {\n valueHtml = '<em class=\"fr-turn__patch-value--skip\">(aborted)</em>';\n } else if (op === 'clear_field') {\n valueHtml = '<em class=\"fr-turn__patch-value--clear\">(cleared)</em>';\n } else if ('value' in p) {\n valueHtml = formatPatchValue(p.value);\n } else if ('values' in p) {\n valueHtml = formatPatchValue(p.values);\n } else if ('rows' in p) {\n valueHtml = formatPatchValue(p.rows);\n }\n\n return `\n <div class=\"fr-turn__patch\">\n <span class=\"fr-turn__patch-field\">${escapeHtml(fieldId)}</span>\n <span class=\"fr-turn__patch-op\">${escapeHtml(opLabel)}</span>\n <span class=\"fr-turn__patch-value\">${valueHtml}</span>\n </div>\n `;\n })\n .filter(Boolean)\n .join('');\n\n return `<div class=\"fr-turn__patches\">${patchHtml}</div>`;\n}\n\n/**\n * Render a single tool call with enhanced details.\n * Shows query for web_search, patch details for fill_form.\n */\nfunction renderToolCall(tc: {\n tool: string;\n success: boolean;\n durationMs: number;\n input: Record<string, unknown>;\n result?: { error?: string; resultCount?: number };\n}): string {\n const hasError = !!tc.result?.error;\n const icon = tc.success ? '✓' : '✕';\n const errorClass = hasError ? ' fr-turn__tool--error' : '';\n\n // Build result summary\n let resultSummary = '';\n if (hasError) {\n resultSummary = `Error: ${escapeHtml(tc.result?.error ?? '')}`;\n } else if (tc.result?.resultCount !== undefined) {\n resultSummary = `${tc.result.resultCount} results`;\n } else {\n resultSummary = 'OK';\n }\n\n // Build tool-specific details\n let detailHtml = '';\n if (tc.tool === 'web_search' && typeof tc.input.query === 'string') {\n const query = escapeHtml(tc.input.query);\n detailHtml = ` <span class=\"fr-turn__query\">\"${query}\"</span>`;\n }\n\n // Base tool call line\n const toolLine = `<li class=\"fr-turn__tool${errorClass}\">${icon} <strong>${escapeHtml(tc.tool)}</strong>${detailHtml}: ${resultSummary} (${formatDuration(tc.durationMs)})</li>`;\n\n // For fill_form, add patch details\n if (tc.tool === 'fill_form' && tc.input.patches) {\n const patchDetails = renderPatchDetails(tc.input);\n if (patchDetails) {\n return toolLine + patchDetails;\n }\n }\n\n return toolLine;\n}\n\n/**\n * CSS styles for fill record visualization.\n * Uses CSS custom properties for theming (supports dark mode via prefers-color-scheme).\n * Designed to be lightweight, reusable, and embeddable.\n */\nexport const FILL_RECORD_STYLES = `\n<style>\n .fr-dashboard {\n --fr-bg: #ffffff;\n --fr-bg-muted: #f9fafb;\n --fr-bg-subtle: #f3f4f6;\n --fr-border: #e5e7eb;\n --fr-text: #111827;\n --fr-text-muted: #6b7280;\n --fr-primary: #3b82f6;\n --fr-success: #22c55e;\n --fr-warning: #f59e0b;\n --fr-error: #ef4444;\n --fr-info: #6b7280;\n\n /* Typography - consolidated to fewer sizes */\n --fr-font-sm: 13px;\n --fr-font-base: 14px;\n --fr-font-lg: 20px;\n\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n padding: 20px;\n max-width: 900px;\n margin: 0 auto;\n color: var(--fr-text);\n line-height: 1.5;\n }\n\n @media (prefers-color-scheme: dark) {\n .fr-dashboard {\n --fr-bg: #1f2937;\n --fr-bg-muted: #374151;\n --fr-bg-subtle: #4b5563;\n --fr-border: #4b5563;\n --fr-text: #f9fafb;\n --fr-text-muted: #9ca3af;\n }\n }\n\n .fr-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 12px;\n border-bottom: 1px solid var(--fr-border);\n }\n .fr-header__model {\n font-weight: 600;\n font-size: var(--fr-font-base);\n color: var(--fr-text);\n }\n .fr-header__time {\n font-weight: 600;\n font-size: var(--fr-font-base);\n color: var(--fr-text);\n }\n\n .fr-banner {\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n font-size: var(--fr-font-base);\n }\n .fr-banner--error {\n background: color-mix(in srgb, var(--fr-error) 10%, var(--fr-bg));\n border: 1px solid var(--fr-error);\n }\n .fr-banner--warning {\n background: color-mix(in srgb, var(--fr-warning) 10%, var(--fr-bg));\n border: 1px solid var(--fr-warning);\n }\n\n .fr-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));\n gap: 16px;\n margin-bottom: 24px;\n }\n\n .fr-card {\n padding: 16px;\n background: var(--fr-bg-muted);\n border-radius: 8px;\n text-align: center;\n }\n .fr-card__label {\n font-size: var(--fr-font-sm);\n color: var(--fr-text-muted);\n margin-bottom: 4px;\n }\n .fr-card__value {\n font-size: var(--fr-font-lg);\n font-weight: 600;\n }\n .fr-card__sub {\n font-size: var(--fr-font-sm);\n color: var(--fr-text-muted);\n margin-top: 2px;\n }\n\n .fr-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border-radius: 4px;\n font-weight: 600;\n font-size: var(--fr-font-sm);\n }\n .fr-badge--completed { background: color-mix(in srgb, var(--fr-success) 15%, transparent); color: var(--fr-success); }\n .fr-badge--partial { background: color-mix(in srgb, var(--fr-warning) 15%, transparent); color: var(--fr-warning); }\n .fr-badge--cancelled { background: color-mix(in srgb, var(--fr-info) 15%, transparent); color: var(--fr-info); }\n .fr-badge--failed { background: color-mix(in srgb, var(--fr-error) 15%, transparent); color: var(--fr-error); }\n\n .fr-section {\n margin-bottom: 24px;\n }\n .fr-section__title {\n font-size: var(--fr-font-base);\n font-weight: 500;\n color: var(--fr-text);\n margin-bottom: 8px;\n }\n\n .fr-progress {\n background: var(--fr-border);\n border-radius: 4px;\n height: 20px;\n overflow: hidden;\n }\n .fr-progress__bar {\n background: var(--fr-primary);\n height: 100%;\n transition: width 0.3s ease;\n }\n .fr-progress__text {\n font-size: var(--fr-font-sm);\n color: var(--fr-text-muted);\n margin-top: 4px;\n }\n\n .fr-progress__segments {\n display: flex;\n height: 100%;\n width: 100%;\n }\n .fr-progress-segment {\n height: 100%;\n min-width: 2px;\n border-right: 2px solid var(--fr-bg);\n cursor: pointer;\n }\n .fr-progress-segment:last-child {\n border-right: none;\n }\n .fr-progress-segment--filled {\n background: var(--fr-primary);\n }\n .fr-progress-segment--filled:hover {\n background: color-mix(in srgb, var(--fr-primary) 70%, white);\n }\n .fr-progress-segment--prefilled {\n background: #8b5cf6;\n }\n .fr-progress-segment--prefilled:hover {\n background: color-mix(in srgb, #8b5cf6 70%, white);\n }\n .fr-progress-segment--skipped {\n background: var(--fr-warning);\n }\n .fr-progress-segment--skipped:hover {\n background: color-mix(in srgb, var(--fr-warning) 70%, white);\n }\n .fr-progress-segment--empty {\n background: var(--fr-border);\n }\n\n /* Gantt chart - each call on its own row */\n .fr-gantt {\n margin-bottom: 8px;\n }\n .fr-gantt__row {\n display: flex;\n align-items: center;\n height: 20px;\n margin-bottom: 3px;\n }\n .fr-gantt__label {\n width: 90px;\n flex-shrink: 0;\n font-size: 11px;\n color: var(--fr-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding-right: 8px;\n text-align: right;\n }\n .fr-gantt__track {\n flex: 1;\n background: var(--fr-bg-subtle);\n border-radius: 3px;\n height: 14px;\n position: relative;\n }\n .fr-gantt__bar {\n position: absolute;\n top: 2px;\n height: calc(100% - 4px);\n min-width: 6px;\n border-radius: 2px;\n cursor: pointer;\n }\n .fr-gantt__bar:hover {\n filter: brightness(1.15);\n }\n .fr-gantt__bar--llm {\n background: var(--fr-primary);\n }\n .fr-gantt__bar--tool {\n background: var(--fr-success);\n }\n .fr-gantt__legend {\n display: flex;\n gap: 16px;\n font-size: var(--fr-font-sm);\n color: var(--fr-text-muted);\n margin-top: 12px;\n padding-top: 8px;\n border-top: 1px solid var(--fr-border);\n }\n .fr-gantt__legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .fr-gantt__legend-dot {\n width: 10px;\n height: 10px;\n border-radius: 2px;\n }\n .fr-gantt__legend-dot--llm { background: var(--fr-primary); }\n .fr-gantt__legend-dot--tool { background: var(--fr-success); }\n\n /* Tooltip container */\n .fr-tooltip {\n position: fixed;\n background: #1f2937;\n color: #f9fafb;\n padding: 8px 12px;\n border-radius: 4px;\n font-size: var(--fr-font-sm);\n white-space: pre-line;\n pointer-events: none;\n z-index: 1000;\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.05s ease-out, visibility 0.05s ease-out;\n }\n .fr-tooltip.visible {\n opacity: 1;\n visibility: visible;\n transition: opacity 0.2s ease-in, visibility 0.2s ease-in;\n }\n\n .fr-table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--fr-font-sm);\n }\n .fr-table th {\n padding: 8px 12px;\n text-align: left;\n font-weight: 600;\n background: var(--fr-bg-subtle);\n }\n .fr-table th:not(:first-child) { text-align: center; }\n .fr-table td {\n padding: 8px 12px;\n border-bottom: 1px solid var(--fr-border);\n }\n .fr-table td:not(:first-child) { text-align: center; }\n\n .fr-details {\n border: none;\n background: none;\n }\n .fr-details > summary {\n cursor: pointer;\n font-size: var(--fr-font-base);\n font-weight: 500;\n color: var(--fr-text);\n padding: 8px 0;\n list-style: none;\n }\n .fr-details > summary::-webkit-details-marker { display: none; }\n .fr-details > summary::before {\n content: '▶';\n display: inline-block;\n margin-right: 8px;\n transition: transform 0.2s;\n font-size: 11px;\n }\n .fr-details[open] > summary::before {\n transform: rotate(90deg);\n }\n .fr-details__content {\n background: var(--fr-bg-muted);\n border-radius: 8px;\n padding: 16px;\n margin-top: 8px;\n }\n\n .fr-turn {\n margin-bottom: 8px;\n background: var(--fr-bg-muted);\n border-radius: 4px;\n }\n .fr-turn summary {\n cursor: pointer;\n padding: 12px;\n font-size: var(--fr-font-sm);\n list-style: none;\n }\n .fr-turn summary::-webkit-details-marker { display: none; }\n .fr-turn summary::before {\n content: '▶';\n display: inline-block;\n margin-right: 8px;\n transition: transform 0.2s;\n font-size: 11px;\n }\n .fr-turn[open] summary::before {\n transform: rotate(90deg);\n }\n .fr-turn__content {\n padding: 0 12px 12px;\n }\n .fr-turn__tools {\n margin: 0;\n padding-left: 20px;\n list-style: none;\n }\n .fr-turn__tool {\n margin: 4px 0;\n font-size: var(--fr-font-sm);\n color: var(--fr-text-muted);\n }\n .fr-turn__tool--error { color: var(--fr-error); }\n\n .fr-turn__query {\n color: var(--fr-primary);\n font-style: italic;\n }\n\n .fr-turn__patches {\n margin: 4px 0 8px 20px;\n padding: 8px 12px;\n background: var(--fr-bg-subtle);\n border-radius: 4px;\n font-size: var(--fr-font-sm);\n }\n .fr-turn__patch {\n margin: 4px 0;\n padding: 4px 0;\n border-bottom: 1px solid var(--fr-border);\n }\n .fr-turn__patch:last-child {\n border-bottom: none;\n margin-bottom: 0;\n padding-bottom: 0;\n }\n .fr-turn__patch-field {\n font-weight: 600;\n color: var(--fr-text);\n }\n .fr-turn__patch-op {\n font-size: 11px;\n padding: 1px 4px;\n border-radius: 2px;\n background: var(--fr-bg-muted);\n color: var(--fr-text-muted);\n margin-left: 6px;\n }\n .fr-turn__patch-value {\n display: block;\n margin-top: 2px;\n color: var(--fr-text-muted);\n font-family: ui-monospace, 'SF Mono', Menlo, monospace;\n word-break: break-word;\n white-space: pre-wrap;\n max-height: 200px;\n overflow: auto;\n }\n .fr-turn__patch-value--skip {\n color: var(--fr-warning);\n font-style: italic;\n }\n .fr-turn__patch-value--clear {\n color: var(--fr-info);\n font-style: italic;\n }\n\n .fr-raw {\n position: relative;\n }\n .fr-copy-btn {\n position: absolute;\n top: 8px;\n right: 8px;\n padding: 4px 8px;\n font-size: var(--fr-font-sm);\n background: var(--fr-bg-subtle);\n border: 1px solid var(--fr-border);\n border-radius: 4px;\n cursor: pointer;\n color: var(--fr-text-muted);\n transition: all 0.15s;\n }\n .fr-copy-btn:hover {\n background: var(--fr-border);\n color: var(--fr-text);\n }\n .fr-copy-btn:active {\n transform: scale(0.95);\n }\n\n /* Scoped pre styles to override parent .tab-content pre */\n .fr-dashboard pre {\n background: var(--fr-bg-muted);\n color: var(--fr-text);\n padding: 1rem;\n border-radius: 6px;\n border: 1px solid var(--fr-border);\n overflow-x: auto;\n font-family: ui-monospace, 'SF Mono', Menlo, monospace;\n font-size: 0.85rem;\n line-height: 1.5;\n margin: 0;\n }\n\n /* Override syntax highlighting colors for dark mode compatibility */\n .fr-dashboard .syn-key { color: var(--fr-primary); }\n .fr-dashboard .syn-string { color: var(--fr-success); }\n .fr-dashboard .syn-number { color: var(--fr-primary); }\n .fr-dashboard .syn-bool { color: var(--fr-warning); }\n .fr-dashboard .syn-null { color: var(--fr-error); }\n\n @media (max-width: 600px) {\n .fr-dashboard { padding: 12px; }\n .fr-cards { grid-template-columns: repeat(2, 1fr); gap: 12px; }\n .fr-card { padding: 12px; }\n .fr-card__value { font-size: 18px; }\n .fr-table { font-size: var(--fr-font-sm); }\n .fr-table th, .fr-table td { padding: 6px 8px; }\n }\n</style>\n`;\n\n/**\n * Render fill record content (dashboard-style visualization).\n * Uses CSS custom properties for theming with automatic dark mode support.\n * Mobile responsive with grid-based layout.\n *\n * @public Exported for testing and reuse.\n */\nexport function renderFillRecordContent(record: FillRecord): string {\n const { status, statusDetail, startedAt, durationMs, llm, formProgress, toolSummary, timeline } =\n record;\n\n // Format start time for display\n const startDate = new Date(startedAt);\n const formattedDate = startDate.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n const formattedTime = startDate.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n\n // Header with model and timestamp\n const headerInfo = `\n <div class=\"fr-header\">\n <div class=\"fr-header__model\">${escapeHtml(llm.model)}</div>\n <div class=\"fr-header__time\">${formattedDate} at ${formattedTime}</div>\n </div>\n `;\n\n // Status banner for non-completed fills\n let statusBanner = '';\n if (status !== 'completed') {\n const bannerClass = status === 'failed' ? 'fr-banner--error' : 'fr-banner--warning';\n const icon = status === 'failed' ? '✕' : '⚠';\n const title = status === 'failed' ? 'FAILED' : status === 'cancelled' ? 'CANCELLED' : 'PARTIAL';\n const msg = statusDetail ?? (status === 'partial' ? 'Did not complete all fields' : '');\n statusBanner = `<div class=\"fr-banner ${bannerClass}\"><strong>${icon} ${title}${msg ? ':' : ''}</strong>${msg ? ` ${escapeHtml(msg)}` : ''}</div>`;\n }\n\n // Summary cards\n const totalTokens = llm.inputTokens + llm.outputTokens;\n const badgeClass = `fr-badge fr-badge--${status}`;\n const badgeIcon = { completed: '✓', partial: '⚠', cancelled: '⊘', failed: '✕' }[status] ?? '?';\n const badgeLabel = status.charAt(0).toUpperCase() + status.slice(1);\n\n const summaryCards = `\n <div class=\"fr-cards\">\n <div class=\"fr-card\">\n <div class=\"fr-card__label\">Status</div>\n <div><span class=\"${badgeClass}\">${badgeIcon} ${badgeLabel}</span></div>\n </div>\n <div class=\"fr-card\">\n <div class=\"fr-card__label\">Duration</div>\n <div class=\"fr-card__value\">${formatDuration(durationMs)}</div>\n </div>\n <div class=\"fr-card\">\n <div class=\"fr-card__label\">Turns</div>\n <div class=\"fr-card__value\">${timeline.length}</div>\n </div>\n <div class=\"fr-card\">\n <div class=\"fr-card__label\">Tokens</div>\n <div class=\"fr-card__value\">${formatTokens(totalTokens)}</div>\n <div class=\"fr-card__sub\">${formatTokens(llm.inputTokens)} in / ${formatTokens(llm.outputTokens)} out</div>\n </div>\n </div>\n `;\n\n // Progress bar\n // Extract filled fields from timeline to show individual segments\n // Use Map to deduplicate by fieldId, keeping only the last (final) state for each field\n const fieldsMap = new Map<string, { fieldId: string; op: string; turnNumber: number }>();\n for (const turn of timeline) {\n for (const tc of turn.toolCalls) {\n if (tc.tool === 'fill_form' && tc.input.patches) {\n const patches = tc.input.patches as { op?: string; fieldId?: string }[];\n for (const patch of patches) {\n if (patch.fieldId && patch.op) {\n fieldsMap.set(patch.fieldId, {\n fieldId: patch.fieldId,\n op: patch.op,\n turnNumber: turn.turnNumber,\n });\n }\n }\n }\n }\n }\n const fieldsFilled = Array.from(fieldsMap.values());\n\n const totalFields = formProgress.totalFields;\n const filledFields = formProgress.filledFields;\n const skippedFields = formProgress.skippedFields;\n const abortedFields = formProgress.abortedFields ?? 0;\n const progressPercent = totalFields > 0 ? Math.round((filledFields / totalFields) * 100) : 0;\n\n // Build progress segments\n const segmentWidth = totalFields > 0 ? 100 / totalFields : 0;\n\n // AI-filled fields (from timeline patches, excluding skip/abort)\n const aiFilledFields = fieldsFilled.filter(\n (f) => f.op !== 'skip_field' && f.op !== 'abort_field',\n );\n const aiFilledSegmentsHtml = aiFilledFields\n .map((f) => {\n const opLabel = f.op.replace(/_/g, ' ');\n const tooltip = `${f.fieldId}\\n${opLabel}\\nTurn ${f.turnNumber}`;\n return `<div class=\"fr-progress-segment fr-progress-segment--filled\" style=\"width: ${segmentWidth}%\" data-tooltip=\"${escapeHtml(tooltip)}\" onmouseenter=\"frShowTip(this)\" onmouseleave=\"frHideTip()\"></div>`;\n })\n .join('');\n\n // Pre-filled fields (filled before AI started, not in timeline)\n const prefilledCount = Math.max(0, filledFields - aiFilledFields.length);\n const prefilledSegmentsHtml =\n prefilledCount > 0\n ? `<div class=\"fr-progress-segment fr-progress-segment--prefilled\" style=\"width: ${segmentWidth * prefilledCount}%\" data-tooltip=\"Pre-filled (${prefilledCount} field${prefilledCount !== 1 ? 's' : ''})\" onmouseenter=\"frShowTip(this)\" onmouseleave=\"frHideTip()\"></div>`\n : '';\n\n // Skipped/aborted fields\n const skippedSegmentsHtml = fieldsFilled\n .filter((f) => f.op === 'skip_field' || f.op === 'abort_field')\n .map((f) => {\n const opLabel = f.op === 'skip_field' ? 'skipped' : 'aborted';\n const tooltip = `${f.fieldId}\\n${opLabel}\\nTurn ${f.turnNumber}`;\n return `<div class=\"fr-progress-segment fr-progress-segment--skipped\" style=\"width: ${segmentWidth}%\" data-tooltip=\"${escapeHtml(tooltip)}\" onmouseenter=\"frShowTip(this)\" onmouseleave=\"frHideTip()\"></div>`;\n })\n .join('');\n\n // Empty segments for unfilled fields\n const unfilledCount = totalFields - filledFields - skippedFields - abortedFields;\n const unfilledSegmentsHtml =\n unfilledCount > 0\n ? `<div class=\"fr-progress-segment fr-progress-segment--empty\" style=\"width: ${segmentWidth * unfilledCount}%\"></div>`\n : '';\n\n // Build progress text with details\n const progressDetails: string[] = [];\n if (prefilledCount > 0) progressDetails.push(`${prefilledCount} pre-filled`);\n if (skippedFields > 0) progressDetails.push(`${skippedFields} skipped`);\n const progressDetailsText = progressDetails.length > 0 ? ` • ${progressDetails.join(' • ')}` : '';\n\n const progressBar = `\n <div class=\"fr-section\">\n <div class=\"fr-section__title\">Progress</div>\n <div class=\"fr-progress\">\n <div class=\"fr-progress__segments\">\n ${prefilledSegmentsHtml}${aiFilledSegmentsHtml}${skippedSegmentsHtml}${unfilledSegmentsHtml}\n </div>\n </div>\n <div class=\"fr-progress__text\">\n ${filledFields}/${totalFields} fields filled (${progressPercent}%)${progressDetailsText}\n </div>\n </div>\n `;\n\n // Gantt-style timeline visualization\n // Calculate actual start/end times for each call\n const totalMs = durationMs;\n const llmCallCount = llm.totalCalls;\n const toolCallCount = toolSummary.totalCalls;\n\n // Build timeline events with actual positions\n // For each turn: LLM call happens first, then tool calls sequentially\n interface TimelineEvent {\n type: 'llm' | 'tool';\n startMs: number;\n durationMs: number;\n turnNumber: number;\n label: string;\n tokens?: { input: number; output: number; total: number };\n }\n\n const timelineEvents: TimelineEvent[] = [];\n\n for (const turn of timeline) {\n const toolTimeInTurn = turn.toolCalls.reduce((sum, tc) => sum + tc.durationMs, 0);\n const llmTimeInTurn = Math.max(0, turn.durationMs - toolTimeInTurn);\n\n // LLM call for this turn - starts at turn.startMs\n if (llmTimeInTurn > 0) {\n timelineEvents.push({\n type: 'llm',\n startMs: turn.startMs,\n durationMs: llmTimeInTurn,\n turnNumber: turn.turnNumber,\n label: `Turn ${turn.turnNumber}`,\n tokens: {\n input: turn.tokens.input,\n output: turn.tokens.output,\n total: turn.tokens.input + turn.tokens.output,\n },\n });\n }\n\n // Tool calls for this turn - use pre-computed startMs\n for (const tc of turn.toolCalls) {\n timelineEvents.push({\n type: 'tool',\n startMs: tc.startMs,\n durationMs: tc.durationMs,\n turnNumber: turn.turnNumber,\n label: tc.tool,\n });\n }\n }\n\n // Render Gantt chart rows - each event gets its own row\n const ganttRowsHtml = timelineEvents\n .map((e) => {\n const leftPct = totalMs > 0 ? (e.startMs / totalMs) * 100 : 0;\n const widthPct = totalMs > 0 ? (e.durationMs / totalMs) * 100 : 0;\n const barClass = e.type === 'llm' ? 'fr-gantt__bar--llm' : 'fr-gantt__bar--tool';\n const startTime = `Start: ${formatDuration(e.startMs)}`;\n const tooltip =\n e.type === 'llm'\n ? `${e.label}&#10;${startTime}&#10;Duration: ${formatDuration(e.durationMs)}&#10;${formatTokens(e.tokens?.total ?? 0)} tokens (${formatTokens(e.tokens?.input ?? 0)} in / ${formatTokens(e.tokens?.output ?? 0)} out)`\n : `${e.label}&#10;${startTime}&#10;Duration: ${formatDuration(e.durationMs)}&#10;Turn ${e.turnNumber}`;\n\n return `\n <div class=\"fr-gantt__row\">\n <div class=\"fr-gantt__label\">${escapeHtml(e.label)}</div>\n <div class=\"fr-gantt__track\">\n <div class=\"fr-gantt__bar ${barClass}\" style=\"left: ${leftPct}%; width: ${widthPct}%\" data-tooltip=\"${tooltip}\" onmouseenter=\"frShowTip(this)\" onmouseleave=\"frHideTip()\"></div>\n </div>\n </div>`;\n })\n .join('');\n\n const llmTotalMs = timelineEvents\n .filter((e) => e.type === 'llm')\n .reduce((sum, e) => sum + e.durationMs, 0);\n const toolTotalMs = timelineEvents\n .filter((e) => e.type === 'tool')\n .reduce((sum, e) => sum + e.durationMs, 0);\n\n const timingSection = `\n <details class=\"fr-details fr-section\" open>\n <summary>Timeline (${formatDuration(totalMs)} total)</summary>\n <div class=\"fr-details__content\">\n <div class=\"fr-gantt\">\n ${ganttRowsHtml}\n <div class=\"fr-gantt__legend\">\n <div class=\"fr-gantt__legend-item\">\n <div class=\"fr-gantt__legend-dot fr-gantt__legend-dot--llm\"></div>\n <span>LLM (${llmCallCount} call${llmCallCount !== 1 ? 's' : ''}, ${formatDuration(llmTotalMs)})</span>\n </div>\n <div class=\"fr-gantt__legend-item\">\n <div class=\"fr-gantt__legend-dot fr-gantt__legend-dot--tool\"></div>\n <span>Tools (${toolCallCount} call${toolCallCount !== 1 ? 's' : ''}, ${formatDuration(toolTotalMs)})</span>\n </div>\n </div>\n </div>\n </div>\n </details>\n `;\n\n // Tool summary table\n let toolSection = '';\n if (toolSummary.byTool.length > 0) {\n const toolRows = toolSummary.byTool\n .map(\n (t) => `\n <tr>\n <td>${escapeHtml(t.toolName)}</td>\n <td>${t.callCount}</td>\n <td>${t.successCount === t.callCount ? '100%' : `${Math.round((t.successCount / t.callCount) * 100)}%`}</td>\n <td>${formatDuration(t.timing.avgMs)}</td>\n <td>${formatDuration(t.timing.p95Ms)}</td>\n </tr>\n `,\n )\n .join('');\n\n toolSection = `\n <details class=\"fr-details fr-section\" open>\n <summary>Tool Summary</summary>\n <div style=\"overflow-x: auto; margin-top: 8px;\">\n <table class=\"fr-table\">\n <thead><tr><th>Tool</th><th>Calls</th><th>Success</th><th>Avg</th><th>p95</th></tr></thead>\n <tbody>${toolRows}</tbody>\n </table>\n </div>\n </details>\n `;\n }\n\n // Turn Details accordion\n let timelineSection = '';\n if (timeline.length > 0) {\n const timelineItems = timeline\n .map((turn) => {\n const turnTokens = turn.tokens.input + turn.tokens.output;\n const toolCallsList = turn.toolCalls.map((tc) => renderToolCall(tc)).join('');\n\n const patchInfo = turn.patchesApplied > 0 ? ` • ${turn.patchesApplied} patches` : '';\n const rejectedInfo =\n turn.patchesRejected > 0\n ? ` <span style=\"color: var(--fr-error)\">(${turn.patchesRejected} rejected)</span>`\n : '';\n\n return `\n <details class=\"fr-turn\">\n <summary><strong>Turn ${turn.turnNumber}</strong> • Order ${turn.order} • ${formatDuration(turn.durationMs)} • ${formatTokens(turnTokens)} tokens${patchInfo}${rejectedInfo}</summary>\n <div class=\"fr-turn__content\">\n ${turn.toolCalls.length > 0 ? `<ul class=\"fr-turn__tools\">${toolCallsList}</ul>` : '<span class=\"fr-turn__tool\">No tool calls</span>'}\n </div>\n </details>\n `;\n })\n .join('');\n\n timelineSection = `\n <details class=\"fr-details fr-section\">\n <summary>Turn Details (${timeline.length} turns)</summary>\n <div style=\"margin-top: 8px;\">${timelineItems}</div>\n </details>\n `;\n }\n\n // Raw YAML section with copy functionality (handler defined in main page script)\n const yamlContent = YAML.stringify(record, { lineWidth: 0 });\n\n const rawSection = `\n <details class=\"fr-details fr-section\">\n <summary>Raw YAML</summary>\n <div class=\"fr-raw\" style=\"margin-top: 8px;\">\n <button class=\"fr-copy-btn\" onclick=\"frCopyYaml(this)\">Copy</button>\n ${renderYamlContent(yamlContent)}\n </div>\n </details>\n `;\n\n // Tooltip element - functions are defined in main page script\n const tooltipHtml = `<div id=\"fr-tooltip\" class=\"fr-tooltip\"></div>`;\n\n return `\n ${FILL_RECORD_STYLES}\n ${tooltipHtml}\n <div class=\"fr-dashboard\">\n ${headerInfo}\n ${statusBanner}\n ${summaryCards}\n ${progressBar}\n ${timingSection}\n ${toolSection}\n ${timelineSection}\n ${rawSection}\n </div>\n `;\n}\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -923,6 +923,39 @@ interface Agent {
923
923
  */
924
924
  fillFormTool(issues: InspectIssue[], form: ParsedForm, maxPatches: number, previousRejections?: PatchRejection[]): Promise<AgentResponse>;
925
925
  }
926
+ /**
927
+ * Built-in provider names corresponding to the @ai-sdk/* packages from Vercel AI SDK.
928
+ */
929
+ type BuiltInProviderName = 'anthropic' | 'openai' | 'google' | 'xai' | 'deepseek';
930
+ /**
931
+ * Any provider name — built-in or custom. Provides autocomplete for built-in names.
932
+ */
933
+ type ProviderName = BuiltInProviderName | (string & {});
934
+ /**
935
+ * Adapter for an AI provider. Clients import their own @ai-sdk/* package,
936
+ * configure it, and pass the adapter to markform.
937
+ *
938
+ * The interface matches the AI SDK provider shape so providers can often
939
+ * be passed directly without wrapping.
940
+ */
941
+ interface ProviderAdapter {
942
+ /** Resolve a model name to a LanguageModel instance. */
943
+ model(modelId: string): LanguageModel;
944
+ /** Optional provider-specific tools (e.g., web search). */
945
+ tools?: Record<string, Tool>;
946
+ }
947
+ /**
948
+ * AI SDK providers are callable: provider(modelId) => LanguageModel.
949
+ * They may also have a .tools property with tool factories.
950
+ */
951
+ type AiSdkProviderCallable = ((modelId: string) => LanguageModel) & {
952
+ tools?: Record<string, (...args: unknown[]) => Tool>;
953
+ };
954
+ /**
955
+ * A ProviderInput is either a ProviderAdapter (with `.model()` method)
956
+ * or an AI SDK provider callable (auto-normalized via `normalizeProvider()`).
957
+ */
958
+ type ProviderInput = ProviderAdapter | AiSdkProviderCallable;
926
959
  /**
927
960
  * Callbacks for observing form-filling execution in real-time.
928
961
  *
@@ -1102,6 +1135,13 @@ interface FillOptions {
1102
1135
  * If a custom tool has the same name as a built-in tool, the custom tool wins.
1103
1136
  */
1104
1137
  additionalTools?: Record<string, Tool>;
1138
+ /**
1139
+ * Additional providers for string-based model resolution.
1140
+ * Keys are provider names (the part before the `/` in model IDs).
1141
+ * Values are ProviderAdapter objects or AI SDK provider callables.
1142
+ * These take priority over built-in providers.
1143
+ */
1144
+ providers?: Record<string, ProviderInput>;
1105
1145
  /**
1106
1146
  * TEST ONLY: Override agent for testing with MockAgent.
1107
1147
  * When provided, model is ignored and this agent is used instead.
@@ -1401,6 +1441,13 @@ declare class ParallelHarness {
1401
1441
  */
1402
1442
  declare function createParallelHarness(form: ParsedForm, config?: ParallelHarnessConfig): ParallelHarness;
1403
1443
  //#endregion
1444
+ //#region src/harness/modelResolver.d.ts
1445
+ /**
1446
+ * Built-in providers available by default.
1447
+ * Exported so callers can inspect which providers are built-in.
1448
+ */
1449
+ declare const BUILT_IN_PROVIDERS: Readonly<Record<BuiltInProviderName, BuiltInProviderName>>;
1450
+ //#endregion
1404
1451
  //#region src/harness/fillRecordCollector.d.ts
1405
1452
  interface FillRecordCollectorOptions {
1406
1453
  /** Form metadata */
@@ -1615,5 +1662,5 @@ declare function validateResearchForm(form: ParsedForm): {
1615
1662
  /** Markform version (injected at build time). */
1616
1663
  declare const VERSION: string;
1617
1664
  //#endregion
1618
- export { type AgentResponse, type AnswerState, AnswerStateSchema, type ApplyResult, ApplyResultSchema, type CellResponse, CellResponseSchema, type CellScopeRef, type CheckboxInfo, type CheckboxMode, CheckboxModeSchema, type CheckboxProgressCounts, CheckboxProgressCountsSchema, type CheckboxValue, CheckboxValueSchema, type CheckboxesField, CheckboxesFieldSchema, type CheckboxesValue, CheckboxesValueSchema, type ClearFieldPatch, ClearFieldPatchSchema, type CoerceInputContextResult, type CoercionResult, type ColumnTypeName, ColumnTypeNameSchema, type ComputedSummaries, type DateField, DateFieldSchema, type DateValue, DateValueSchema, type DocumentationBlock, DocumentationBlockSchema, type DocumentationTag, DocumentationTagSchema, type ExecutionMetadata, ExecutionMetadataSchema, type ExplicitCheckboxValue, ExplicitCheckboxValueSchema, type Field, type FieldBase, type FieldGroup, FieldGroupSchema, type FieldKind, FieldKindSchema, type FieldProgress, FieldProgressSchema, type FieldResponse, FieldResponseSchema, FieldSchema, type FieldScopeRef, type FieldValue, FieldValueSchema, type FillCallbacks, type FillOptions, type FillRecord, FillRecordCollector, type FillRecordCollectorOptions, FillRecordSchema, type FillRecordStatus, FillRecordStatusSchema, type FillResult, type FillStatus, FormHarness, type FormSchema, FormSchemaSchema, type FormatFillRecordSummaryOptions, type FrontmatterHarnessConfig, type HarnessConfig, HarnessConfigSchema, type HeadingInfo, type Id, type IdIndexEntry, IdSchema, type InjectCheckboxIdsOptions, type InjectHeaderIdsOptions, type InjectIdsResult, type InputContext, type InspectIssue, InspectIssueSchema, type InspectOptions, type InspectResult, InspectResultSchema, type IssueReason, IssueReasonSchema, type IssueScope, IssueScopeSchema, type JsonSchemaDraft, type JsonSchemaOptions, type JsonSchemaResult, MarkformAbortError, MarkformConfigError, MarkformError, type MarkformFieldExtension, type MarkformFrontmatter, MarkformFrontmatterSchema, MarkformLlmError, MarkformParseError, MarkformPatchError, type MarkformSchemaExtension, MarkformSectionInputSchema, MarkformValidationError, MockAgent, type MultiCheckboxState, MultiCheckboxStateSchema, type MultiSelectField, MultiSelectFieldSchema, type MultiSelectValue, MultiSelectValueSchema, type NodeType, type NumberField, NumberFieldSchema, type NumberValue, NumberValueSchema, type Option, type OptionId, OptionIdSchema, OptionSchema, ParallelHarness, type ParallelHarnessConfig, type ParallelRunResult, type ParallelStepResult, ParseError, type ParseScopeRefResult, type ParseTableResult, type ParsedForm, type ParsedRawTable, type ParsedScopeRef, type Patch, type PatchRejection, PatchSchema, type ProgressCounts, ProgressCountsSchema, type ProgressState, ProgressStateSchema, type ProgressSummary, ProgressSummarySchema, type QualifiedColumnRef, type QualifiedOptionRef, type QualifiedScopeRef, type RawFieldValue, type ResearchOptions, type ResearchResult, type ResearchStatus, type RunMode, RunModeSchema, type ScopedFillRequest, type SerializeOptions, type SessionFinal, SessionFinalSchema, type SessionTranscript, SessionTranscriptSchema, type SessionTurn, SessionTurnSchema, type SessionTurnStats, type SetCheckboxesPatch, SetCheckboxesPatchSchema, type SetDatePatch, SetDatePatchSchema, type SetMultiSelectPatch, SetMultiSelectPatchSchema, type SetNumberPatch, SetNumberPatchSchema, type SetSingleSelectPatch, SetSingleSelectPatchSchema, type SetStringListPatch, SetStringListPatchSchema, type SetStringPatch, SetStringPatchSchema, type SetTablePatch, SetTablePatchSchema, type SetUrlListPatch, SetUrlListPatchSchema, type SetUrlPatch, SetUrlPatchSchema, type SetYearPatch, SetYearPatchSchema, type Severity, SeveritySchema, type SimpleCheckboxState, SimpleCheckboxStateSchema, type SingleSelectField, SingleSelectFieldSchema, type SingleSelectValue, SingleSelectValueSchema, type SourcePosition, SourcePositionSchema, type SourceRange, SourceRangeSchema, type StepResult, StepResultSchema, type StringField, StringFieldSchema, type StringListField, StringListFieldSchema, type StringListValue, StringListValueSchema, type StringValue, StringValueSchema, type StructureSummary, StructureSummarySchema, type TableColumn, TableColumnSchema, type TableField, TableFieldSchema, type TableRowPatch, TableRowPatchSchema, type TableRowResponse, TableRowResponseSchema, type TableValue, TableValueSchema, type TimelineEntry, TimelineEntrySchema, type TimingBreakdown, type TimingBreakdownItem, TimingBreakdownItemSchema, TimingBreakdownSchema, type ToolCallRecord, ToolCallRecordSchema, type ToolStats, ToolStatsSchema, type ToolSummary, ToolSummarySchema, type TurnProgress, type TurnStats, type UrlField, UrlFieldSchema, type UrlListField, UrlListFieldSchema, type UrlListValue, UrlListValueSchema, type UrlValue, UrlValueSchema, VERSION, type ValidateOptions, type ValidateResult, type ValidationIssue, ValidationIssueSchema, type ValidatorContext, type ValidatorFn, type ValidatorRef, ValidatorRefSchema, type ValidatorRegistry, type WireFormat, WireFormatSchema, type WireRequestFormat, WireRequestFormatSchema, type WireResponseFormat, WireResponseFormatSchema, type WireResponseStep, WireResponseStepSchema, type WireToolCall, WireToolCallSchema, type WireToolResult, WireToolResultSchema, type YearField, YearFieldSchema, type YearValue, YearValueSchema, applyPatches, coerceInputContext, coerceToFieldPatch, computeAllSummaries, computeFormState, computeProgressSummary, computeStructureSummary, createHarness, createMockAgent, createParallelHarness, fieldToJsonSchema, fillForm, findAllCheckboxes, findAllHeadings, findEnclosingHeadings, findFieldById, formToJsonSchema, formatFillRecordSummary, getFieldId, injectCheckboxIds, injectHeaderIds, inspect, isAbortError, isCellRef, isConfigError, isFieldRef, isFormComplete, isLlmError, isMarkformError, isParseError, isPatchError, isQualifiedRef, isResearchForm, isRetryableError, isValidationError, parseCellValue, parseForm, parseMarkdownTable, parseRawTable, parseScopeRef, parseSession, resolveHarnessConfig, runResearch, scopeIssuesForItem, serializeForm, serializeReport, serializeScopeRef, serializeSession, validate, validateResearchForm };
1665
+ export { type AgentResponse, type AnswerState, AnswerStateSchema, type ApplyResult, ApplyResultSchema, BUILT_IN_PROVIDERS, type BuiltInProviderName, type CellResponse, CellResponseSchema, type CellScopeRef, type CheckboxInfo, type CheckboxMode, CheckboxModeSchema, type CheckboxProgressCounts, CheckboxProgressCountsSchema, type CheckboxValue, CheckboxValueSchema, type CheckboxesField, CheckboxesFieldSchema, type CheckboxesValue, CheckboxesValueSchema, type ClearFieldPatch, ClearFieldPatchSchema, type CoerceInputContextResult, type CoercionResult, type ColumnTypeName, ColumnTypeNameSchema, type ComputedSummaries, type DateField, DateFieldSchema, type DateValue, DateValueSchema, type DocumentationBlock, DocumentationBlockSchema, type DocumentationTag, DocumentationTagSchema, type ExecutionMetadata, ExecutionMetadataSchema, type ExplicitCheckboxValue, ExplicitCheckboxValueSchema, type Field, type FieldBase, type FieldGroup, FieldGroupSchema, type FieldKind, FieldKindSchema, type FieldProgress, FieldProgressSchema, type FieldResponse, FieldResponseSchema, FieldSchema, type FieldScopeRef, type FieldValue, FieldValueSchema, type FillCallbacks, type FillOptions, type FillRecord, FillRecordCollector, type FillRecordCollectorOptions, FillRecordSchema, type FillRecordStatus, FillRecordStatusSchema, type FillResult, type FillStatus, FormHarness, type FormSchema, FormSchemaSchema, type FormatFillRecordSummaryOptions, type FrontmatterHarnessConfig, type HarnessConfig, HarnessConfigSchema, type HeadingInfo, type Id, type IdIndexEntry, IdSchema, type InjectCheckboxIdsOptions, type InjectHeaderIdsOptions, type InjectIdsResult, type InputContext, type InspectIssue, InspectIssueSchema, type InspectOptions, type InspectResult, InspectResultSchema, type IssueReason, IssueReasonSchema, type IssueScope, IssueScopeSchema, type JsonSchemaDraft, type JsonSchemaOptions, type JsonSchemaResult, MarkformAbortError, MarkformConfigError, MarkformError, type MarkformFieldExtension, type MarkformFrontmatter, MarkformFrontmatterSchema, MarkformLlmError, MarkformParseError, MarkformPatchError, type MarkformSchemaExtension, MarkformSectionInputSchema, MarkformValidationError, MockAgent, type MultiCheckboxState, MultiCheckboxStateSchema, type MultiSelectField, MultiSelectFieldSchema, type MultiSelectValue, MultiSelectValueSchema, type NodeType, type NumberField, NumberFieldSchema, type NumberValue, NumberValueSchema, type Option, type OptionId, OptionIdSchema, OptionSchema, ParallelHarness, type ParallelHarnessConfig, type ParallelRunResult, type ParallelStepResult, ParseError, type ParseScopeRefResult, type ParseTableResult, type ParsedForm, type ParsedRawTable, type ParsedScopeRef, type Patch, type PatchRejection, PatchSchema, type ProgressCounts, ProgressCountsSchema, type ProgressState, ProgressStateSchema, type ProgressSummary, ProgressSummarySchema, type ProviderAdapter, type ProviderInput, type ProviderName, type QualifiedColumnRef, type QualifiedOptionRef, type QualifiedScopeRef, type RawFieldValue, type ResearchOptions, type ResearchResult, type ResearchStatus, type RunMode, RunModeSchema, type ScopedFillRequest, type SerializeOptions, type SessionFinal, SessionFinalSchema, type SessionTranscript, SessionTranscriptSchema, type SessionTurn, SessionTurnSchema, type SessionTurnStats, type SetCheckboxesPatch, SetCheckboxesPatchSchema, type SetDatePatch, SetDatePatchSchema, type SetMultiSelectPatch, SetMultiSelectPatchSchema, type SetNumberPatch, SetNumberPatchSchema, type SetSingleSelectPatch, SetSingleSelectPatchSchema, type SetStringListPatch, SetStringListPatchSchema, type SetStringPatch, SetStringPatchSchema, type SetTablePatch, SetTablePatchSchema, type SetUrlListPatch, SetUrlListPatchSchema, type SetUrlPatch, SetUrlPatchSchema, type SetYearPatch, SetYearPatchSchema, type Severity, SeveritySchema, type SimpleCheckboxState, SimpleCheckboxStateSchema, type SingleSelectField, SingleSelectFieldSchema, type SingleSelectValue, SingleSelectValueSchema, type SourcePosition, SourcePositionSchema, type SourceRange, SourceRangeSchema, type StepResult, StepResultSchema, type StringField, StringFieldSchema, type StringListField, StringListFieldSchema, type StringListValue, StringListValueSchema, type StringValue, StringValueSchema, type StructureSummary, StructureSummarySchema, type TableColumn, TableColumnSchema, type TableField, TableFieldSchema, type TableRowPatch, TableRowPatchSchema, type TableRowResponse, TableRowResponseSchema, type TableValue, TableValueSchema, type TimelineEntry, TimelineEntrySchema, type TimingBreakdown, type TimingBreakdownItem, TimingBreakdownItemSchema, TimingBreakdownSchema, type ToolCallRecord, ToolCallRecordSchema, type ToolStats, ToolStatsSchema, type ToolSummary, ToolSummarySchema, type TurnProgress, type TurnStats, type UrlField, UrlFieldSchema, type UrlListField, UrlListFieldSchema, type UrlListValue, UrlListValueSchema, type UrlValue, UrlValueSchema, VERSION, type ValidateOptions, type ValidateResult, type ValidationIssue, ValidationIssueSchema, type ValidatorContext, type ValidatorFn, type ValidatorRef, ValidatorRefSchema, type ValidatorRegistry, type WireFormat, WireFormatSchema, type WireRequestFormat, WireRequestFormatSchema, type WireResponseFormat, WireResponseFormatSchema, type WireResponseStep, WireResponseStepSchema, type WireToolCall, WireToolCallSchema, type WireToolResult, WireToolResultSchema, type YearField, YearFieldSchema, type YearValue, YearValueSchema, applyPatches, coerceInputContext, coerceToFieldPatch, computeAllSummaries, computeFormState, computeProgressSummary, computeStructureSummary, createHarness, createMockAgent, createParallelHarness, fieldToJsonSchema, fillForm, findAllCheckboxes, findAllHeadings, findEnclosingHeadings, findFieldById, formToJsonSchema, formatFillRecordSummary, getFieldId, injectCheckboxIds, injectHeaderIds, inspect, isAbortError, isCellRef, isConfigError, isFieldRef, isFormComplete, isLlmError, isMarkformError, isParseError, isPatchError, isQualifiedRef, isResearchForm, isRetryableError, isValidationError, parseCellValue, parseForm, parseMarkdownTable, parseRawTable, parseScopeRef, parseSession, resolveHarnessConfig, runResearch, scopeIssuesForItem, serializeForm, serializeReport, serializeScopeRef, serializeSession, validate, validateResearchForm };
1619
1666
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  import { $ as SetTablePatchSchema, A as MarkformSectionInputSchema, At as WireToolCallSchema, B as ProgressStateSchema, C as HarnessConfigSchema, Ct as UrlValueSchema, D as IssueReasonSchema, Dt as WireRequestFormatSchema, E as InspectResultSchema, Et as WireFormatSchema, F as NumberValueSchema, G as SessionTurnSchema, H as RunModeSchema, I as OptionIdSchema, J as SetMultiSelectPatchSchema, K as SetCheckboxesPatchSchema, L as OptionSchema, M as MultiSelectFieldSchema, Mt as YearFieldSchema, N as MultiSelectValueSchema, Nt as YearValueSchema, O as IssueScopeSchema, Ot as WireResponseFormatSchema, P as NumberFieldSchema, Q as SetStringPatchSchema, R as PatchSchema, S as FormSchemaSchema, St as UrlListValueSchema, T as InspectIssueSchema, Tt as ValidatorRefSchema, U as SessionFinalSchema, V as ProgressSummarySchema, W as SessionTranscriptSchema, X as SetSingleSelectPatchSchema, Y as SetNumberPatchSchema, Z as SetStringListPatchSchema, _ as FieldKindSchema, _t as TableRowPatchSchema, a as CheckboxProgressCountsSchema, at as SingleSelectFieldSchema, b as FieldSchema, bt as UrlFieldSchema, c as CheckboxesValueSchema, ct as SourceRangeSchema, d as DateFieldSchema, dt as StringListFieldSchema, et as SetUrlListPatchSchema, f as DateValueSchema, ft as StringListValueSchema, g as FieldGroupSchema, gt as TableFieldSchema, h as ExplicitCheckboxValueSchema, ht as TableColumnSchema, i as CheckboxModeSchema, it as SimpleCheckboxStateSchema, j as MultiCheckboxStateSchema, jt as WireToolResultSchema, k as MarkformFrontmatterSchema, kt as WireResponseStepSchema, l as ClearFieldPatchSchema, lt as StepResultSchema, m as DocumentationTagSchema, mt as StructureSummarySchema, n as ApplyResultSchema, nt as SetYearPatchSchema, o as CheckboxValueSchema, ot as SingleSelectValueSchema, p as DocumentationBlockSchema, pt as StringValueSchema, q as SetDatePatchSchema, r as CellResponseSchema, rt as SeveritySchema, s as CheckboxesFieldSchema, st as SourcePositionSchema, t as AnswerStateSchema, tt as SetUrlPatchSchema, u as ColumnTypeNameSchema, ut as StringFieldSchema, v as FieldProgressSchema, vt as TableRowResponseSchema, w as IdSchema, wt as ValidationIssueSchema, x as FieldValueSchema, xt as UrlListFieldSchema, y as FieldResponseSchema, yt as TableValueSchema, z as ProgressCountsSchema } from "./coreTypes-CTLr-NGd.mjs";
3
- import { _t as isPatchError, a as validate, at as MarkformConfigError, c as computeProgressSummary, ct as MarkformParseError, d as serializeForm, dt as ParseError, ft as isAbortError, gt as isParseError, ht as isMarkformError, i as inspect, it as MarkformAbortError, l as computeStructureSummary, lt as MarkformPatchError, mt as isLlmError, o as computeAllSummaries, ot as MarkformError, p as serializeReport, pt as isConfigError, s as computeFormState, st as MarkformLlmError, t as applyPatches, u as isFormComplete, ut as MarkformValidationError, vt as isRetryableError, yt as isValidationError } from "./apply-C7mO7VkZ.mjs";
4
- import { A as FormHarness, B as serializeScopeRef, E as FillRecordCollector, F as getFieldId, G as injectCheckboxIds, H as formToJsonSchema, I as isCellRef, J as findEnclosingHeadings, K as injectHeaderIds, L as isFieldRef, M as coerceInputContext, N as coerceToFieldPatch, O as MockAgent, P as findFieldById, R as isQualifiedRef, U as parseForm, V as fieldToJsonSchema, W as findAllCheckboxes, X as parseMarkdownTable, Y as parseCellValue, Z as parseRawTable, _ as fillForm, a as ExecutionMetadataSchema, b as scopeIssuesForItem, c as TimelineEntrySchema, d as ToolCallRecordSchema, f as ToolStatsSchema, g as resolveHarnessConfig, h as formatFillRecordSummary, i as runResearch, j as createHarness, k as createMockAgent, l as TimingBreakdownItemSchema, n as isResearchForm, o as FillRecordSchema, p as ToolSummarySchema, q as findAllHeadings, r as validateResearchForm, s as FillRecordStatusSchema, t as VERSION, u as TimingBreakdownSchema, v as ParallelHarness, y as createParallelHarness, z as parseScopeRef } from "./src-CbRnGzMK.mjs";
3
+ import { _t as isPatchError, a as validate, at as MarkformConfigError, c as computeProgressSummary, ct as MarkformParseError, d as serializeForm, dt as ParseError, ft as isAbortError, gt as isParseError, ht as isMarkformError, i as inspect, it as MarkformAbortError, l as computeStructureSummary, lt as MarkformPatchError, mt as isLlmError, o as computeAllSummaries, ot as MarkformError, p as serializeReport, pt as isConfigError, s as computeFormState, st as MarkformLlmError, t as applyPatches, u as isFormComplete, ut as MarkformValidationError, vt as isRetryableError, yt as isValidationError } from "./apply-KzQztrDV.mjs";
4
+ import { A as createMockAgent, B as parseScopeRef, D as FillRecordCollector, F as findFieldById, G as findAllCheckboxes, H as fieldToJsonSchema, I as getFieldId, J as findAllHeadings, K as injectCheckboxIds, L as isCellRef, M as createHarness, N as coerceInputContext, P as coerceToFieldPatch, Q as parseRawTable, R as isFieldRef, U as formToJsonSchema, V as serializeScopeRef, W as parseForm, X as parseCellValue, Y as findEnclosingHeadings, Z as parseMarkdownTable, _ as fillForm, a as ExecutionMetadataSchema, b as scopeIssuesForItem, c as TimelineEntrySchema, d as ToolCallRecordSchema, f as ToolStatsSchema, g as resolveHarnessConfig, h as formatFillRecordSummary, i as runResearch, j as FormHarness, k as MockAgent, l as TimingBreakdownItemSchema, n as isResearchForm, o as FillRecordSchema, p as ToolSummarySchema, q as injectHeaderIds, r as validateResearchForm, s as FillRecordStatusSchema, t as VERSION, u as TimingBreakdownSchema, v as ParallelHarness, x as BUILT_IN_PROVIDERS, y as createParallelHarness, z as isQualifiedRef } from "./src-B2uFvGli.mjs";
5
5
  import { n as serializeSession, t as parseSession } from "./session-BCcltrLA.mjs";
6
6
 
7
- export { AnswerStateSchema, ApplyResultSchema, CellResponseSchema, CheckboxModeSchema, CheckboxProgressCountsSchema, CheckboxValueSchema, CheckboxesFieldSchema, CheckboxesValueSchema, ClearFieldPatchSchema, ColumnTypeNameSchema, DateFieldSchema, DateValueSchema, DocumentationBlockSchema, DocumentationTagSchema, ExecutionMetadataSchema, ExplicitCheckboxValueSchema, FieldGroupSchema, FieldKindSchema, FieldProgressSchema, FieldResponseSchema, FieldSchema, FieldValueSchema, FillRecordCollector, FillRecordSchema, FillRecordStatusSchema, FormHarness, FormSchemaSchema, HarnessConfigSchema, IdSchema, InspectIssueSchema, InspectResultSchema, IssueReasonSchema, IssueScopeSchema, MarkformAbortError, MarkformConfigError, MarkformError, MarkformFrontmatterSchema, MarkformLlmError, MarkformParseError, MarkformPatchError, MarkformSectionInputSchema, MarkformValidationError, MockAgent, MultiCheckboxStateSchema, MultiSelectFieldSchema, MultiSelectValueSchema, NumberFieldSchema, NumberValueSchema, OptionIdSchema, OptionSchema, ParallelHarness, ParseError, PatchSchema, ProgressCountsSchema, ProgressStateSchema, ProgressSummarySchema, RunModeSchema, SessionFinalSchema, SessionTranscriptSchema, SessionTurnSchema, SetCheckboxesPatchSchema, SetDatePatchSchema, SetMultiSelectPatchSchema, SetNumberPatchSchema, SetSingleSelectPatchSchema, SetStringListPatchSchema, SetStringPatchSchema, SetTablePatchSchema, SetUrlListPatchSchema, SetUrlPatchSchema, SetYearPatchSchema, SeveritySchema, SimpleCheckboxStateSchema, SingleSelectFieldSchema, SingleSelectValueSchema, SourcePositionSchema, SourceRangeSchema, StepResultSchema, StringFieldSchema, StringListFieldSchema, StringListValueSchema, StringValueSchema, StructureSummarySchema, TableColumnSchema, TableFieldSchema, TableRowPatchSchema, TableRowResponseSchema, TableValueSchema, TimelineEntrySchema, TimingBreakdownItemSchema, TimingBreakdownSchema, ToolCallRecordSchema, ToolStatsSchema, ToolSummarySchema, UrlFieldSchema, UrlListFieldSchema, UrlListValueSchema, UrlValueSchema, VERSION, ValidationIssueSchema, ValidatorRefSchema, WireFormatSchema, WireRequestFormatSchema, WireResponseFormatSchema, WireResponseStepSchema, WireToolCallSchema, WireToolResultSchema, YearFieldSchema, YearValueSchema, applyPatches, coerceInputContext, coerceToFieldPatch, computeAllSummaries, computeFormState, computeProgressSummary, computeStructureSummary, createHarness, createMockAgent, createParallelHarness, fieldToJsonSchema, fillForm, findAllCheckboxes, findAllHeadings, findEnclosingHeadings, findFieldById, formToJsonSchema, formatFillRecordSummary, getFieldId, injectCheckboxIds, injectHeaderIds, inspect, isAbortError, isCellRef, isConfigError, isFieldRef, isFormComplete, isLlmError, isMarkformError, isParseError, isPatchError, isQualifiedRef, isResearchForm, isRetryableError, isValidationError, parseCellValue, parseForm, parseMarkdownTable, parseRawTable, parseScopeRef, parseSession, resolveHarnessConfig, runResearch, scopeIssuesForItem, serializeForm, serializeReport, serializeScopeRef, serializeSession, validate, validateResearchForm };
7
+ export { AnswerStateSchema, ApplyResultSchema, BUILT_IN_PROVIDERS, CellResponseSchema, CheckboxModeSchema, CheckboxProgressCountsSchema, CheckboxValueSchema, CheckboxesFieldSchema, CheckboxesValueSchema, ClearFieldPatchSchema, ColumnTypeNameSchema, DateFieldSchema, DateValueSchema, DocumentationBlockSchema, DocumentationTagSchema, ExecutionMetadataSchema, ExplicitCheckboxValueSchema, FieldGroupSchema, FieldKindSchema, FieldProgressSchema, FieldResponseSchema, FieldSchema, FieldValueSchema, FillRecordCollector, FillRecordSchema, FillRecordStatusSchema, FormHarness, FormSchemaSchema, HarnessConfigSchema, IdSchema, InspectIssueSchema, InspectResultSchema, IssueReasonSchema, IssueScopeSchema, MarkformAbortError, MarkformConfigError, MarkformError, MarkformFrontmatterSchema, MarkformLlmError, MarkformParseError, MarkformPatchError, MarkformSectionInputSchema, MarkformValidationError, MockAgent, MultiCheckboxStateSchema, MultiSelectFieldSchema, MultiSelectValueSchema, NumberFieldSchema, NumberValueSchema, OptionIdSchema, OptionSchema, ParallelHarness, ParseError, PatchSchema, ProgressCountsSchema, ProgressStateSchema, ProgressSummarySchema, RunModeSchema, SessionFinalSchema, SessionTranscriptSchema, SessionTurnSchema, SetCheckboxesPatchSchema, SetDatePatchSchema, SetMultiSelectPatchSchema, SetNumberPatchSchema, SetSingleSelectPatchSchema, SetStringListPatchSchema, SetStringPatchSchema, SetTablePatchSchema, SetUrlListPatchSchema, SetUrlPatchSchema, SetYearPatchSchema, SeveritySchema, SimpleCheckboxStateSchema, SingleSelectFieldSchema, SingleSelectValueSchema, SourcePositionSchema, SourceRangeSchema, StepResultSchema, StringFieldSchema, StringListFieldSchema, StringListValueSchema, StringValueSchema, StructureSummarySchema, TableColumnSchema, TableFieldSchema, TableRowPatchSchema, TableRowResponseSchema, TableValueSchema, TimelineEntrySchema, TimingBreakdownItemSchema, TimingBreakdownSchema, ToolCallRecordSchema, ToolStatsSchema, ToolSummarySchema, UrlFieldSchema, UrlListFieldSchema, UrlListValueSchema, UrlValueSchema, VERSION, ValidationIssueSchema, ValidatorRefSchema, WireFormatSchema, WireRequestFormatSchema, WireResponseFormatSchema, WireResponseStepSchema, WireToolCallSchema, WireToolResultSchema, YearFieldSchema, YearValueSchema, applyPatches, coerceInputContext, coerceToFieldPatch, computeAllSummaries, computeFormState, computeProgressSummary, computeStructureSummary, createHarness, createMockAgent, createParallelHarness, fieldToJsonSchema, fillForm, findAllCheckboxes, findAllHeadings, findEnclosingHeadings, findFieldById, formToJsonSchema, formatFillRecordSummary, getFieldId, injectCheckboxIds, injectHeaderIds, inspect, isAbortError, isCellRef, isConfigError, isFieldRef, isFormComplete, isLlmError, isMarkformError, isParseError, isPatchError, isQualifiedRef, isResearchForm, isRetryableError, isValidationError, parseCellValue, parseForm, parseMarkdownTable, parseRawTable, parseScopeRef, parseSession, resolveHarnessConfig, runResearch, scopeIssuesForItem, serializeForm, serializeReport, serializeScopeRef, serializeSession, validate, validateResearchForm };
package/dist/render.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
- import { a as renderJsonContent, c as renderViewContent, d as formatDuration, f as formatTokens, l as renderYamlContent, n as FILL_RECORD_STYLES, o as renderMarkdownContent, r as renderFillRecordContent, s as renderSourceContent, t as FILL_RECORD_SCRIPTS, u as escapeHtml } from "./fillRecordRenderer-CruJrLkj.mjs";
2
+ import { a as renderJsonContent, c as renderViewContent, d as formatDuration, f as formatTokens, l as renderYamlContent, n as FILL_RECORD_STYLES, o as renderMarkdownContent, r as renderFillRecordContent, s as renderSourceContent, t as FILL_RECORD_SCRIPTS, u as escapeHtml } from "./fillRecordRenderer-VBQ2vwPV.mjs";
3
3
 
4
4
  export { FILL_RECORD_SCRIPTS, FILL_RECORD_STYLES, escapeHtml, formatDuration, formatTokens, renderFillRecordContent, renderJsonContent, renderMarkdownContent, renderSourceContent, renderViewContent, renderYamlContent };
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { A as MarkformSectionInputSchema, R as PatchSchema, mt as StructureSummarySchema, z as ProgressCountsSchema } from "./coreTypes-CTLr-NGd.mjs";
3
- import { B as DEFAULT_ROLES, C as getNumberAttr, D as isTagNode, E as getValidateAttr, F as DEFAULT_MAX_TURNS, L as DEFAULT_PRIORITY, M as DEFAULT_MAX_PARALLEL_AGENTS, N as DEFAULT_MAX_PATCHES_PER_TURN, O as parseOptionText, P as DEFAULT_MAX_STEPS_PER_TURN, R as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, S as getBooleanAttr, T as getStringAttr, V as DEFAULT_ROLE_INSTRUCTIONS, Z as transformHarnessConfigToTs, _ as tryParseSentinelResponse, at as MarkformConfigError, b as extractOptionItems, bt as wrapApiError, c as computeProgressSummary, ct as MarkformParseError, d as serializeForm, h as preprocessCommentSyntax, i as inspect, j as DEFAULT_MAX_ISSUES_PER_TURN, k as AGENT_ROLE, l as computeStructureSummary, m as detectSyntaxStyle, r as getFieldsForRoles, t as applyPatches, tt as getWebSearchConfig, v as CHECKBOX_MARKERS, w as getStringArrayAttr, x as extractTableContent, y as extractFenceValue, z as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN } from "./apply-C7mO7VkZ.mjs";
3
+ import { B as DEFAULT_ROLES, C as getNumberAttr, D as isTagNode, E as getValidateAttr, F as DEFAULT_MAX_TURNS, L as DEFAULT_PRIORITY, M as DEFAULT_MAX_PARALLEL_AGENTS, N as DEFAULT_MAX_PATCHES_PER_TURN, O as parseOptionText, P as DEFAULT_MAX_STEPS_PER_TURN, R as DEFAULT_RESEARCH_MAX_ISSUES_PER_TURN, S as getBooleanAttr, T as getStringAttr, V as DEFAULT_ROLE_INSTRUCTIONS, Z as transformHarnessConfigToTs, _ as tryParseSentinelResponse, at as MarkformConfigError, b as extractOptionItems, bt as wrapApiError, c as computeProgressSummary, ct as MarkformParseError, d as serializeForm, h as preprocessCommentSyntax, i as inspect, j as DEFAULT_MAX_ISSUES_PER_TURN, k as AGENT_ROLE, l as computeStructureSummary, m as detectSyntaxStyle, r as getFieldsForRoles, t as applyPatches, tt as getWebSearchConfig, v as CHECKBOX_MARKERS, w as getStringArrayAttr, x as extractTableContent, y as extractFenceValue, z as DEFAULT_RESEARCH_MAX_PATCHES_PER_TURN } from "./apply-KzQztrDV.mjs";
4
4
  import { z } from "zod";
5
5
  import Markdoc from "@markdoc/markdoc";
6
6
  import YAML from "yaml";
@@ -9146,7 +9146,10 @@ var LiveAgent = class {
9146
9146
  this.callbacks = config.callbacks;
9147
9147
  this.executionId = config.executionId ?? "0-serial";
9148
9148
  this.toolChoice = config.toolChoice ?? "required";
9149
- if (this.enableWebSearch && this.provider) this.webSearchTools = loadWebSearchTools(this.provider);
9149
+ if (this.enableWebSearch) {
9150
+ if (config.providerTools) this.webSearchTools = config.providerTools;
9151
+ else if (this.provider) this.webSearchTools = loadWebSearchTools(this.provider);
9152
+ }
9150
9153
  }
9151
9154
  /**
9152
9155
  * Get list of available tool names for this agent.
@@ -9692,6 +9695,61 @@ const PROVIDERS = {
9692
9695
  }
9693
9696
  };
9694
9697
  /**
9698
+ * Built-in providers available by default.
9699
+ * Exported so callers can inspect which providers are built-in.
9700
+ */
9701
+ const BUILT_IN_PROVIDERS = Object.freeze({
9702
+ anthropic: "anthropic",
9703
+ openai: "openai",
9704
+ google: "google",
9705
+ xai: "xai",
9706
+ deepseek: "deepseek"
9707
+ });
9708
+ /** Known web search tool names from AI SDK providers. */
9709
+ const KNOWN_WEB_SEARCH_TOOLS = [
9710
+ "webSearch",
9711
+ "webSearch_20250305",
9712
+ "googleSearch",
9713
+ "webSearchPreview"
9714
+ ];
9715
+ /**
9716
+ * Extract web search tools from an AI SDK provider callable.
9717
+ * Duck-types the `.tools` property looking for known tool factory names.
9718
+ */
9719
+ function extractToolsFromProvider(provider) {
9720
+ const providerTools = provider.tools;
9721
+ if (!providerTools || typeof providerTools !== "object") return void 0;
9722
+ const extracted = {};
9723
+ for (const toolName of KNOWN_WEB_SEARCH_TOOLS) {
9724
+ const factory = providerTools[toolName];
9725
+ if (typeof factory === "function") try {
9726
+ const tool = factory({});
9727
+ if (tool) {
9728
+ const key = toolName === "googleSearch" ? "google_search" : "web_search";
9729
+ extracted[key] = tool;
9730
+ break;
9731
+ }
9732
+ } catch {}
9733
+ }
9734
+ return Object.keys(extracted).length > 0 ? extracted : void 0;
9735
+ }
9736
+ /**
9737
+ * Normalize a ProviderInput to a ProviderAdapter.
9738
+ * AI SDK provider callables are wrapped in an adapter shape.
9739
+ */
9740
+ function normalizeProvider(input) {
9741
+ if (typeof input === "function") return {
9742
+ model: (id) => input(id),
9743
+ tools: extractToolsFromProvider(input)
9744
+ };
9745
+ if ("model" in input && typeof input.model === "function") return input;
9746
+ throw new MarkformConfigError("Invalid provider: must be a ProviderAdapter (with .model() method) or an AI SDK provider callable", {
9747
+ option: "providers",
9748
+ expectedType: "ProviderAdapter | callable",
9749
+ receivedValue: typeof input
9750
+ });
9751
+ }
9752
+ /**
9695
9753
  * Parse a model ID string into provider and model components.
9696
9754
  *
9697
9755
  * @param modelIdString - Model ID in format `provider/model-id`
@@ -9712,12 +9770,6 @@ function parseModelId(modelIdString) {
9712
9770
  expectedType: "non-empty provider and model-id",
9713
9771
  receivedValue: modelIdString
9714
9772
  });
9715
- const supportedProviders = Object.keys(PROVIDERS);
9716
- if (!supportedProviders.includes(provider)) throw new MarkformConfigError(`Unknown provider: "${provider}". Supported providers: ${supportedProviders.join(", ")}`, {
9717
- option: "model",
9718
- expectedType: `one of: ${supportedProviders.join(", ")}`,
9719
- receivedValue: provider
9720
- });
9721
9773
  return {
9722
9774
  provider,
9723
9775
  modelId
@@ -9732,9 +9784,31 @@ function parseModelId(modelIdString) {
9732
9784
  * @returns Resolved model with provider info
9733
9785
  * @throws Error if provider not installed or API key missing
9734
9786
  */
9735
- async function resolveModel(modelIdString) {
9787
+ async function resolveModel(modelIdString, providers) {
9736
9788
  const { provider, modelId } = parseModelId(modelIdString);
9789
+ if (providers && provider in providers) {
9790
+ const adapter = normalizeProvider(providers[provider]);
9791
+ try {
9792
+ return {
9793
+ model: adapter.model(modelId),
9794
+ provider,
9795
+ modelId,
9796
+ tools: adapter.tools
9797
+ };
9798
+ } catch (error) {
9799
+ throw new MarkformConfigError(`Custom provider "${provider}" failed to resolve model "${modelId}": ${error instanceof Error ? error.message : String(error)}`, {
9800
+ option: "model",
9801
+ expectedType: "valid model ID",
9802
+ receivedValue: modelIdString
9803
+ });
9804
+ }
9805
+ }
9737
9806
  const providerConfig = PROVIDERS[provider];
9807
+ if (!providerConfig) throw new MarkformConfigError(`Unknown provider: "${provider}". Built-in providers: ${Object.keys(PROVIDERS).join(", ")}. To use a custom provider, pass it via the \`providers\` option.`, {
9808
+ option: "model",
9809
+ expectedType: "provider name or custom provider",
9810
+ receivedValue: provider
9811
+ });
9738
9812
  const apiKey = process.env[providerConfig.envVar];
9739
9813
  if (!apiKey) throw new MarkformConfigError(`Missing API key for "${provider}" provider (model: ${modelIdString}).\nSet the ${providerConfig.envVar} environment variable or add it to your .env file.`, {
9740
9814
  option: providerConfig.envVar,
@@ -10264,11 +10338,13 @@ async function fillForm(options) {
10264
10338
  }
10265
10339
  let model;
10266
10340
  let provider;
10341
+ let providerTools;
10267
10342
  if (!options._testAgent) try {
10268
10343
  if (typeof options.model === "string") {
10269
- const resolved = await resolveModel(options.model);
10344
+ const resolved = await resolveModel(options.model, options.providers);
10270
10345
  model = resolved.model;
10271
10346
  provider = resolved.provider;
10347
+ providerTools = resolved.tools;
10272
10348
  } else model = options.model;
10273
10349
  } catch (error) {
10274
10350
  const message = error instanceof Error ? error.message : String(error);
@@ -10310,6 +10386,7 @@ async function fillForm(options) {
10310
10386
  systemPromptAddition: options.systemPromptAddition,
10311
10387
  targetRole: targetRoles[0] ?? AGENT_ROLE,
10312
10388
  provider,
10389
+ providerTools,
10313
10390
  enableWebSearch: options.enableWebSearch,
10314
10391
  additionalTools: options.additionalTools,
10315
10392
  callbacks: mergedCallbacks,
@@ -11111,8 +11188,8 @@ function validateResearchForm(form) {
11111
11188
  //#endregion
11112
11189
  //#region src/index.ts
11113
11190
  /** Markform version (injected at build time). */
11114
- const VERSION = "0.1.22";
11191
+ const VERSION = "0.1.23";
11115
11192
 
11116
11193
  //#endregion
11117
- export { FormHarness as A, serializeScopeRef as B, resolveModel as C, computeExecutionPlan as D, FillRecordCollector as E, getFieldId as F, injectCheckboxIds as G, formToJsonSchema as H, isCellRef as I, findEnclosingHeadings as J, injectHeaderIds as K, isFieldRef as L, coerceInputContext as M, coerceToFieldPatch as N, MockAgent as O, findFieldById as P, isQualifiedRef as R, getProviderNames as S, createLiveAgent as T, parseForm as U, fieldToJsonSchema as V, findAllCheckboxes as W, parseMarkdownTable as X, parseCellValue as Y, parseRawTable as Z, fillForm as _, ExecutionMetadataSchema as a, scopeIssuesForItem as b, TimelineEntrySchema as c, ToolCallRecordSchema as d, ToolStatsSchema as f, resolveHarnessConfig as g, formatFillRecordSummary as h, runResearch as i, createHarness as j, createMockAgent as k, TimingBreakdownItemSchema as l, stripUnstableFillRecordFields as m, isResearchForm as n, FillRecordSchema as o, ToolSummarySchema as p, findAllHeadings as q, validateResearchForm as r, FillRecordStatusSchema as s, VERSION as t, TimingBreakdownSchema as u, ParallelHarness as v, buildMockWireFormat as w, getProviderInfo as x, createParallelHarness as y, parseScopeRef as z };
11118
- //# sourceMappingURL=src-CbRnGzMK.mjs.map
11194
+ export { createMockAgent as A, parseScopeRef as B, getProviderNames as C, FillRecordCollector as D, createLiveAgent as E, findFieldById as F, findAllCheckboxes as G, fieldToJsonSchema as H, getFieldId as I, findAllHeadings as J, injectCheckboxIds as K, isCellRef as L, createHarness as M, coerceInputContext as N, computeExecutionPlan as O, coerceToFieldPatch as P, parseRawTable as Q, isFieldRef as R, getProviderInfo as S, buildMockWireFormat as T, formToJsonSchema as U, serializeScopeRef as V, parseForm as W, parseCellValue as X, findEnclosingHeadings as Y, parseMarkdownTable as Z, fillForm as _, ExecutionMetadataSchema as a, scopeIssuesForItem as b, TimelineEntrySchema as c, ToolCallRecordSchema as d, ToolStatsSchema as f, resolveHarnessConfig as g, formatFillRecordSummary as h, runResearch as i, FormHarness as j, MockAgent as k, TimingBreakdownItemSchema as l, stripUnstableFillRecordFields as m, isResearchForm as n, FillRecordSchema as o, ToolSummarySchema as p, injectHeaderIds as q, validateResearchForm as r, FillRecordStatusSchema as s, VERSION as t, TimingBreakdownSchema as u, ParallelHarness as v, resolveModel as w, BUILT_IN_PROVIDERS as x, createParallelHarness as y, isQualifiedRef as z };
11195
+ //# sourceMappingURL=src-B2uFvGli.mjs.map