@tabbio-technologies/cli 1.2.8
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/README.md +763 -0
- package/dist/chunks/chunk-7LNC3FIV.js +2019 -0
- package/dist/chunks/chunk-7LNC3FIV.js.map +7 -0
- package/dist/chunks/chunk-NAWA6NCZ.js +259 -0
- package/dist/chunks/chunk-NAWA6NCZ.js.map +7 -0
- package/dist/chunks/chunk-NK5RPNSV.js +15 -0
- package/dist/chunks/chunk-NK5RPNSV.js.map +7 -0
- package/dist/chunks/chunk-QVR5KIEQ.js +1976 -0
- package/dist/chunks/chunk-QVR5KIEQ.js.map +7 -0
- package/dist/chunks/chunk-VHHZFMIF.js +162 -0
- package/dist/chunks/chunk-VHHZFMIF.js.map +7 -0
- package/dist/chunks/chunk-Y6GWIFHI.js +227 -0
- package/dist/chunks/chunk-Y6GWIFHI.js.map +7 -0
- package/dist/chunks/entry-WENOOT6W.js +3492 -0
- package/dist/chunks/entry-WENOOT6W.js.map +7 -0
- package/dist/chunks/mount-NGUARMCL.js +79 -0
- package/dist/chunks/mount-NGUARMCL.js.map +7 -0
- package/dist/chunks/program-O2BA5L6Z.js +2755 -0
- package/dist/chunks/program-O2BA5L6Z.js.map +7 -0
- package/dist/chunks/status-I5UAQPBY.js +16 -0
- package/dist/chunks/status-I5UAQPBY.js.map +7 -0
- package/dist/cli.js +66 -0
- package/dist/cli.js.map +7 -0
- package/package.json +65 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/chat-model.ts", "../../src/core/capabilities.ts", "../../src/core/schema-flags.ts", "../../src/core/schema-spec.ts", "../../src/ui/render.ts", "../../src/ui/hooks.ts", "../../src/core/table.ts", "../../src/core/output.ts", "../../src/core/chat-artifacts.ts", "../../src/core/artifacts.ts", "../../src/ui/hyperlink.ts", "../../src/core/chat.ts", "../../src/core/chat-events.ts", "../../src/core/chat-tool-extras.ts", "../../src/core/chat-transcript.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Chat transcript types and pure helpers shared by the reducer\n * (`chat-transcript.ts`) and the Ink chat screen. No I/O, no Ink.\n */\nimport type { AgentMode } from '@tabbio/types';\nimport { marked } from 'marked';\nimport { type CapabilityKey, type ChatCapabilities, DEFAULT_CAPABILITIES } from './capabilities';\nimport type { AgentStreamEvent, ToolEventPayload } from './chat';\nimport type { ArtifactStatus, CapabilityDenial, ChatArtifact, ChatSource, DraftProgress } from './chat-artifacts';\n\nexport type ToolStage = 'running' | 'pending_approval' | 'completed' | 'failed' | 'declined';\nexport type NoticeTone = 'info' | 'error' | 'success' | 'attention';\nexport type ApprovalChoice = 'approve' | 'reject' | 'leave';\n\nexport type ChatToolCall = {\n id: string;\n name: string;\n title: string;\n args: Record<string, unknown>;\n stage: ToolStage;\n approvalId?: string;\n /** Set once the user decided an approval for this call. */\n decision?: ApprovalChoice;\n result?: unknown;\n preview?: string;\n startedAt: number;\n endedAt?: number;\n /**\n * Measured from the `tool-call` event's arrival to its matching\n * `tool-result` (same tool call id). Unset when no start was seen.\n */\n durationMs?: number;\n /** Approval left pending (\"decide later\"): final for display purposes. */\n left?: boolean;\n /** #512 research tools: a collapsible activity line with its sources. */\n research?: boolean;\n sources?: ChatSource[];\n /** #512 artifact tools: the card (kind, title, status, id) that replaces the plain row. */\n artifact?: ChatArtifact;\n /** #512 streaming writer progress (`artifact-draft`). */\n draft?: DraftProgress;\n /** #512 capability denial (quota, plan tier, flag off) shown under the row. */\n denial?: CapabilityDenial;\n};\n\nexport type TranscriptEntry =\n | { kind: 'user'; id: string; text: string }\n | { kind: 'assistant'; id: string }\n | { kind: 'markdown'; id: string; text: string; gap: boolean }\n | { kind: 'tool'; id: string; call: ChatToolCall; gap: boolean }\n | { kind: 'tool-detail'; id: string; call: ChatToolCall }\n | { kind: 'notice'; id: string; tone: NoticeTone; text: string; hint?: string }\n /** An artifact card whose row was already printed changed (ready, failed): one more row. */\n | { kind: 'artifact'; id: string; artifact: ChatArtifact }\n /** The turn's research sources, numbered, after the answer. */\n | { kind: 'sources'; id: string; sources: ChatSource[] };\n\nexport type LiveText = { kind: 'text'; id: string; text: string; committed: number; closed: boolean };\nexport type LiveTool = { kind: 'tool'; id: string; call: ChatToolCall };\nexport type LiveItem = LiveText | LiveTool;\n\nexport type ChatTurn = {\n id: string;\n startedAt: number;\n lastEventAt: number;\n items: LiveItem[];\n /** Every text delta of the turn, for reconciling with `finish.text`. */\n text: string;\n committedText: boolean;\n lastKind: 'label' | 'markdown' | 'tool';\n finished: boolean;\n finishReason?: string;\n error?: string;\n /** Research sources seen in this turn (deduplicated by URL). */\n sources: ChatSource[];\n};\n\nexport type PendingApproval = {\n approvalId: string;\n toolCallId: string;\n name: string;\n title: string;\n args: Record<string, unknown>;\n requestedAt: number;\n};\n\nexport type ChatState = {\n mode: AgentMode;\n threadId?: string;\n modelId?: string;\n entries: TranscriptEntry[];\n turn: ChatTurn | null;\n approvals: PendingApproval[];\n streaming: boolean;\n seq: number;\n /** Research / Image / Result controls sent with every seeker message. */\n capabilities: ChatCapabilities;\n /** The screen can show OSC 8 links: hold a ready artifact card until its preview link is minted. */\n links: boolean;\n};\n\ntype At = { at?: number };\n\nexport type ChatAction =\n | (AgentStreamEvent & At)\n | ({ type: 'submit'; text: string } & At)\n | { type: 'tick' }\n | ({ type: 'stream-failed'; message: string; hint?: string; cancelled?: boolean } & At)\n | ({ type: 'approval-decided'; approvalId: string; decision: ApprovalChoice; text?: string; error?: string } & At)\n | { type: 'notice'; tone: NoticeTone; text: string; hint?: string }\n | { type: 'new-thread' }\n | { type: 'set-thread'; threadId: string }\n | { type: 'history'; threadId: string; messages: Array<{ role: 'user' | 'assistant'; text: string }> }\n | { type: 'set-mode'; mode: AgentMode }\n | { type: 'set-model'; modelId?: string }\n | { type: 'expand-last-tool' }\n | { type: 'set-capability'; key: CapabilityKey; value: ChatCapabilities[CapabilityKey] }\n | ({\n type: 'artifact-status';\n artifactId: string;\n status?: ArtifactStatus;\n title?: string;\n previewUrl?: string;\n failure?: { code: string; message: string };\n /** Stop waiting for this card (poll gave up); print it as it is. */\n release?: boolean;\n } & At);\n\nexport function initialChatState(opts: {\n mode: AgentMode;\n threadId?: string;\n modelId?: string;\n capabilities?: ChatCapabilities;\n links?: boolean;\n}): ChatState {\n return {\n mode: opts.mode,\n threadId: opts.threadId,\n modelId: opts.modelId,\n entries: [],\n turn: null,\n approvals: [],\n streaming: false,\n seq: 0,\n capabilities: opts.capabilities ?? { ...DEFAULT_CAPABILITIES },\n links: opts.links ?? false,\n };\n}\n\nexport const FINAL_STAGES: ReadonlySet<ToolStage> = new Set<ToolStage>(['completed', 'failed', 'declined']);\n\n/** \"Job Search\" \u2192 \"Job search\"; falls back to the camelCase tool name. */\nexport function toolTitle(payload: Pick<ToolEventPayload, 'name' | 'display'>): string {\n const raw = payload.display?.title?.trim() || payload.name.replace(/([a-z0-9])([A-Z])/g, '$1 $2');\n return raw\n .split(/\\s+/)\n .map((w, i) => (i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : /^[A-Z][a-z]/.test(w) ? w.toLowerCase() : w))\n .join(' ');\n}\n\nexport function stageOf(payload: ToolEventPayload, fallback: ToolStage): ToolStage {\n const stage = payload.stage ?? payload.status;\n if (stage === 'completed' || stage === 'failed' || stage === 'declined' || stage === 'running') return stage;\n if (stage === 'pending_approval' || stage === 'pending' || stage === 'requires_approval') return 'pending_approval';\n return fallback;\n}\n\n/**\n * Offset up to which `text` is made of finished top-level blocks: every\n * block except the last content block, cut right after a newline. 0 when\n * nothing is safe to promote yet (Aider's stable-lines / live-window split).\n */\nexport function stableBoundary(text: string): number {\n let tokens: Array<{ type: string; raw: string }>;\n try {\n tokens = marked.lexer(text, { gfm: true }) as unknown as Array<{ type: string; raw: string }>;\n } catch {\n return 0;\n }\n let lastContent = -1;\n tokens.forEach((token, i) => {\n if (token.type !== 'space') lastContent = i;\n });\n if (lastContent <= 0) return 0;\n const prefix = tokens\n .slice(0, lastContent)\n .map((t) => t.raw)\n .join('');\n if (!prefix || !text.startsWith(prefix) || !prefix.endsWith('\\n')) return 0;\n return prefix.length;\n}\n\n/** Whitespace-insensitive comparison key for streamed vs final text. */\nexport function normalizeText(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n\n/** Destructive tools get the red rail and \"This cannot be undone\" (research \u00A75.8). */\nexport function isDestructiveTool(name: string): boolean {\n return /(delete|remove|revoke|withdraw|unpublish|send|close|reject|archive)/i.test(name);\n}\n", "/**\n * Composer capability controls for chat (PR #512): Research and Image\n * (`auto | on | off`) and the Result chip (`auto | summary | document |\n * slides | page | image`), sent as `capabilities` on every seeker message\n * together with the device timezone. The server resolves them against what\n * the account may use and ignores them on employer threads.\n *\n * Mirrors `AgentChatCapabilities` / `AgentCapabilities` from\n * `@tabbio/types` on `feature/agent-capabilities-phase1`; they are declared\n * here because the CLI builds against develop's types.\n *\n * The choice is sticky per profile (the app keeps it per device): slash\n * commands in the chat and `chat --save` store it in config.json under\n * `profiles.<name>.capabilities`.\n */\nimport type { AgentMode } from '@tabbio/types';\nimport { loadConfig, updateConfig } from './config';\nimport { usageError } from './errors';\n\nexport const TOGGLE_MODES = ['auto', 'on', 'off'] as const;\nexport const RESULT_MODES = ['auto', 'summary', 'document', 'slides', 'page', 'image'] as const;\n\nexport type ToggleMode = (typeof TOGGLE_MODES)[number];\nexport type ResultMode = (typeof RESULT_MODES)[number];\nexport type CapabilityKey = 'research' | 'image' | 'result';\n\n/** What the CLI keeps and shows. `result` is sent as `artifact`. */\nexport type ChatCapabilities = { research: ToggleMode; image: ToggleMode; result: ResultMode };\n\n/** Wire shape of `AgentChatRequest.capabilities`. */\nexport type WireCapabilities = { research: ToggleMode; image: ToggleMode; artifact: ResultMode };\n\nexport type CapabilityUnavailableReason = 'disabled' | 'not_allowlisted' | 'not_configured' | 'upgrade_required';\n\n/** `GET /api/agent/capabilities` (only the blocks the CLI reads). */\nexport type CapabilityAvailability = {\n research: { available: boolean; default?: ToggleMode; reason?: CapabilityUnavailableReason };\n image: { available: boolean; default?: ToggleMode; reason?: CapabilityUnavailableReason };\n artifacts: { available: boolean; reason?: CapabilityUnavailableReason };\n editing?: { available: boolean; reason?: CapabilityUnavailableReason };\n writer?: { available: boolean };\n publishing?: { available: boolean; reason?: CapabilityUnavailableReason; baseDomain?: string };\n};\n\nexport const DEFAULT_CAPABILITIES: ChatCapabilities = { research: 'auto', image: 'auto', result: 'auto' };\n\nexport const CAPABILITY_CHOICES: Record<CapabilityKey, readonly string[]> = {\n research: TOGGLE_MODES,\n image: TOGGLE_MODES,\n result: RESULT_MODES,\n};\n\n/** One-line help per choice (palette argument completion and `/help`). */\nexport const CAPABILITY_CHOICE_HELP: Record<CapabilityKey, Record<string, string>> = {\n research: { auto: 'Search the web when it helps', on: 'Always search first', off: 'Never search the web' },\n image: { auto: 'Only when you ask for one', on: 'Make an image (uses image credits)', off: 'Never make images' },\n result: {\n auto: 'Let the message decide',\n summary: 'Answer in the chat',\n document: 'A document (HTML and PDF)',\n slides: 'A slide deck (PPTX)',\n page: 'A web page (HTML)',\n image: 'An image',\n },\n};\n\nfunction isToggle(value: unknown): value is ToggleMode {\n return typeof value === 'string' && (TOGGLE_MODES as readonly string[]).includes(value);\n}\n\nfunction isResult(value: unknown): value is ResultMode {\n return typeof value === 'string' && (RESULT_MODES as readonly string[]).includes(value);\n}\n\n/** Parses `--research`, `--image`, `--result` or a slash argument; usage error (exit 2) otherwise. */\nexport function parseCapabilityMode(key: 'research' | 'image', value: string): ToggleMode;\nexport function parseCapabilityMode(key: 'result', value: string): ResultMode;\nexport function parseCapabilityMode(key: CapabilityKey, value: string): ToggleMode | ResultMode;\nexport function parseCapabilityMode(key: CapabilityKey, value: string): ToggleMode | ResultMode {\n const normalized = value.trim().toLowerCase();\n const alias = key === 'result' && (normalized === 'doc' || normalized === 'pdf') ? 'document' : key === 'result' && normalized === 'deck' ? 'slides' : normalized;\n if (key === 'result' ? isResult(alias) : isToggle(alias)) return alias as ToggleMode | ResultMode;\n throw usageError(`--${key} must be one of ${CAPABILITY_CHOICES[key].join(', ')}; got \"${value}\"`);\n}\n\n/** Lenient read of a stored value: anything unknown falls back to the default. */\nexport function sanitizeCapabilities(raw: unknown): ChatCapabilities {\n const record = raw && typeof raw === 'object' && !Array.isArray(raw) ? (raw as Record<string, unknown>) : {};\n return {\n research: isToggle(record.research) ? record.research : DEFAULT_CAPABILITIES.research,\n image: isToggle(record.image) ? record.image : DEFAULT_CAPABILITIES.image,\n result: isResult(record.result) ? record.result : DEFAULT_CAPABILITIES.result,\n };\n}\n\n/** The profile's saved choice (defaults when none). Never throws on a bad value. */\nexport function loadCapabilityPrefs(profileName: string): ChatCapabilities {\n try {\n const stored = loadConfig().profiles[profileName] as Record<string, unknown> | undefined;\n return sanitizeCapabilities(stored?.capabilities);\n } catch {\n return { ...DEFAULT_CAPABILITIES };\n }\n}\n\n/** Saves the choice for one profile (other profile fields are kept). */\nexport function saveCapabilityPrefs(profileName: string, capabilities: ChatCapabilities): void {\n updateConfig((config) => {\n config.profiles[profileName] = { ...config.profiles[profileName], capabilities: { ...capabilities } };\n });\n}\n\n/** Flags win over the saved choice, per control. */\nexport function resolveCapabilities(\n stored: ChatCapabilities,\n flags: { research?: string; image?: string; result?: string } = {},\n): ChatCapabilities {\n return {\n research: flags.research !== undefined ? parseCapabilityMode('research', flags.research) : stored.research,\n image: flags.image !== undefined ? parseCapabilityMode('image', flags.image) : stored.image,\n result: flags.result !== undefined ? parseCapabilityMode('result', flags.result) : stored.result,\n };\n}\n\nexport function toWireCapabilities(capabilities: ChatCapabilities): WireCapabilities {\n return { research: capabilities.research, image: capabilities.image, artifact: capabilities.result };\n}\n\n/** The device's IANA timezone (\"Asia/Dubai\"), or undefined when the runtime cannot tell. */\nexport function deviceTimeZone(): string | undefined {\n try {\n const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n return typeof zone === 'string' && zone ? zone : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The capability fields of one chat request. Employer turns send no\n * `capabilities` (the server ignores them there anyway); the timezone is\n * always sent because prompts date \"today\" with it.\n */\nexport function capabilityRequestFields(\n mode: AgentMode,\n capabilities: ChatCapabilities,\n timezone: string | undefined = deviceTimeZone(),\n): { capabilities?: WireCapabilities; timezone?: string } {\n return {\n ...(mode === 'employer' ? {} : { capabilities: toWireCapabilities(capabilities) }),\n ...(timezone ? { timezone } : {}),\n };\n}\n\n/** `research on \u00B7 image auto \u00B7 result document` (status bar and notices). */\nexport function describeCapabilities(capabilities: ChatCapabilities): string[] {\n return [`research ${capabilities.research}`, `image ${capabilities.image}`, `result ${capabilities.result}`];\n}\n\nconst REASON_TEXT: Record<CapabilityUnavailableReason, string> = {\n disabled: 'switched off on this server',\n not_allowlisted: 'not enabled for this account yet (canary or plan tier)',\n not_configured: 'the provider is not configured on this server',\n upgrade_required: 'needs a paid plan',\n};\n\nexport function reasonText(reason: string | undefined): string {\n return (reason && REASON_TEXT[reason as CapabilityUnavailableReason]) || reason || 'unavailable';\n}\n\n/**\n * Notices for controls the user asked for that this account cannot use, from\n * `GET /api/agent/capabilities` (the server then runs them `off`/`summary`).\n * Auto and off never warn.\n */\nexport function unavailableNotices(capabilities: ChatCapabilities, availability: CapabilityAvailability | null): string[] {\n if (!availability) return [];\n const notices: string[] = [];\n if (capabilities.research === 'on' && !availability.research.available) {\n notices.push(`Research is unavailable: ${reasonText(availability.research.reason)}. This message runs without it.`);\n }\n const wantsImage = capabilities.image === 'on' || capabilities.result === 'image';\n if (wantsImage && !availability.image.available) {\n notices.push(`Images are unavailable: ${reasonText(availability.image.reason)}. Tabbio answers in the chat instead.`);\n }\n const wantsFile = capabilities.result === 'document' || capabilities.result === 'slides' || capabilities.result === 'page';\n if (wantsFile && !availability.artifacts.available) {\n notices.push(`Documents, slides and pages are unavailable: ${reasonText(availability.artifacts.reason)}. Tabbio answers in the chat instead.`);\n }\n return notices;\n}\n", "/**\n * Tool input schemas (JSON Schema draft-07, produced from zod by Mastra) \u2192\n * command-line flags, and flags \u2192 the JSON arguments sent in `tools/call`.\n *\n * string / number / integer --cv-id <value>, --limit <int>\n * enum --visibility <public|private|unlisted> (validated, \"did you mean\")\n * boolean --open-to-work, --open-to-work=false\n * array of scalars repeatable (--skill a --skill b) and comma-split (--skill a,b);\n * a value starting with \"[\" is parsed as a JSON array\n * object, array of objects, JSON text on the flag (--filters '{\"a\":1}')\n * unions\n * nullable (T | null) the literal `null` sends JSON null (clears the field)\n *\n * Every flag is `--kebab-case` with a hidden camelCase alias (`--cvId`).\n * Schema properties whose flag would collide with a global or run-level flag\n * (`--json`, `--profile`, `--input`, \u2026) become `--in-<name>`; the original\n * JSON key is always what is sent.\n *\n * Commander only collects raw strings here; all coercion and validation lives\n * in the pure `parseToolInput()`, so generated commands and `tabbio run`\n * (which parses flags only after the catalog lookup) behave identically.\n */\nimport { Option } from 'commander';\nimport type { CatalogTool, JsonSchema } from './catalog';\nimport { usageError } from './errors';\nimport { type FlagSpec, type ScalarKind, TOOL_FLAGS_HELP_GROUP, flagNotes, placeholderFor, schemaToFlags } from './schema-spec';\n\nexport * from './schema-spec';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction collect(value: string, previous: unknown): string[] {\n return [...(Array.isArray(previous) ? (previous as string[]) : []), value];\n}\n\n/**\n * Commander options for a schema: the visible `--kebab` flag plus a hidden\n * camelCase alias. Values stay raw strings; see parseToolInput().\n */\nexport function schemaToOptions(schema: JsonSchema | undefined, specs = schemaToFlags(schema)): Option[] {\n const options: Option[] = [];\n for (const spec of specs) {\n const notes = flagNotes(spec);\n const help = [spec.description || spec.property, notes.length ? `(${notes.join('; ')})` : '']\n .filter(Boolean)\n .join(' ');\n const make = (flag: string) => {\n const option = new Option(`--${flag} ${placeholderFor(spec)}`, help);\n if (spec.kind === 'array') option.argParser(collect);\n return option;\n };\n options.push(make(spec.flag).helpGroup(TOOL_FLAGS_HELP_GROUP));\n if (spec.alias) options.push(make(spec.alias).hideHelp());\n }\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Parsing\n\nexport type ToolInputExtras = {\n /** Object from `--input` / `--input-file` / stdin; flags override its keys. */\n base?: Record<string, unknown>;\n /** Filled only when the key is still absent after flags and base (e.g. workflow userId). */\n defaults?: Record<string, unknown>;\n};\n\nexport type ParsedToolInput = {\n input: Record<string, unknown>;\n /** Required properties still missing, as JSON keys. */\n missingRequired: string[];\n};\n\nfunction levenshtein(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i += 1) {\n let prev = row[0] as number;\n row[0] = i;\n for (let j = 1; j <= b.length; j += 1) {\n const temp = row[j] as number;\n row[j] = Math.min((row[j] as number) + 1, (row[j - 1] as number) + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));\n prev = temp;\n }\n }\n return row[b.length] as number;\n}\n\n/** Closest candidate within a small edit distance, for \"did you mean\" hints. */\nexport function didYouMean(value: string, candidates: readonly string[]): string | undefined {\n const needle = value.toLowerCase();\n let best: { candidate: string; distance: number } | undefined;\n for (const candidate of candidates) {\n const lower = candidate.toLowerCase();\n const distance = lower.startsWith(needle) || needle.startsWith(lower) ? 1 : levenshtein(needle, lower);\n if (!best || distance < best.distance) best = { candidate, distance };\n }\n return best && best.distance <= Math.max(2, Math.floor(needle.length / 3)) ? best.candidate : undefined;\n}\n\nfunction flagLabel(spec: FlagSpec): string {\n return `--${spec.flag}`;\n}\n\nfunction coerceScalar(spec: FlagSpec, kind: ScalarKind, raw: unknown): unknown {\n const label = flagLabel(spec);\n if (kind === 'boolean') {\n if (raw === true || raw === null || raw === undefined) return true; // bare `--flag`\n if (raw === false) return false;\n const text = String(raw).trim().toLowerCase();\n if (['true', 'yes', '1', 'on'].includes(text)) return true;\n if (['false', 'no', '0', 'off'].includes(text)) return false;\n throw usageError(`${label} expects true or false, got \"${String(raw)}\"`);\n }\n const text = String(raw);\n if (kind === 'number' || kind === 'integer') {\n const value = Number(text.trim());\n if (text.trim() === '' || !Number.isFinite(value)) throw usageError(`${label} expects a number, got \"${text}\"`);\n if (kind === 'integer' && !Number.isInteger(value)) throw usageError(`${label} expects a whole number, got \"${text}\"`);\n return value;\n }\n if (kind === 'enum') {\n const allowed = spec.enumValues ?? [];\n const exact = allowed.find((v) => v === text) ?? allowed.find((v) => v.toLowerCase() === text.toLowerCase());\n if (exact !== undefined) return exact;\n const guess = didYouMean(text, allowed);\n throw usageError(\n `${label} must be one of ${allowed.join(', ')}; got \"${text}\"`,\n guess ? `Did you mean \"${guess}\"?` : undefined,\n );\n }\n return text;\n}\n\nfunction parseJsonFlag(spec: FlagSpec, raw: string): unknown {\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n if (spec.kind === 'json' && spec.jsonShape === 'any') return raw;\n throw usageError(\n `${flagLabel(spec)} expects JSON, got ${JSON.stringify(raw.length > 40 ? `${raw.slice(0, 40)}\u2026` : raw)}`,\n `Quote it for the shell, e.g. ${flagLabel(spec)} '${spec.jsonShape === 'array' ? '[\u2026]' : '{\"key\":\"value\"}'}'`,\n );\n }\n}\n\nfunction coerce(spec: FlagSpec, raw: unknown): unknown {\n if (spec.nullable && raw === 'null') return null;\n if (spec.kind === 'array') {\n const values = Array.isArray(raw) ? raw : [raw];\n const items: unknown[] = [];\n for (const value of values) {\n const text = String(value);\n if (text.trim().startsWith('[')) {\n const parsed = parseJsonFlag(spec, text);\n if (!Array.isArray(parsed)) throw usageError(`${flagLabel(spec)} expects a JSON array`);\n items.push(...parsed);\n continue;\n }\n for (const part of text.split(',')) {\n const trimmed = part.trim();\n if (trimmed) items.push(coerceScalar(spec, spec.itemKind ?? 'string', trimmed));\n }\n }\n return items;\n }\n if (spec.kind === 'json') {\n const parsed = typeof raw === 'string' ? parseJsonFlag(spec, raw) : raw;\n if (spec.jsonShape === 'object' && !isRecord(parsed)) throw usageError(`${flagLabel(spec)} expects a JSON object`);\n if (spec.jsonShape === 'array' && !Array.isArray(parsed)) throw usageError(`${flagLabel(spec)} expects a JSON array`);\n return parsed;\n }\n return coerceScalar(spec, spec.kind, raw);\n}\n\n/**\n * Builds the tool arguments. Precedence: flags > `extras.base` (the\n * `--input` object) > `extras.defaults`. Throws a usage CliError (exit 2) on\n * a bad value; missing required fields are reported, not thrown, so the\n * caller can open a form or print one combined error.\n */\nexport function parseToolInput(\n schema: JsonSchema | undefined,\n opts: Record<string, unknown>,\n extras: ToolInputExtras = {},\n): ParsedToolInput {\n const specs = schemaToFlags(schema);\n const input: Record<string, unknown> = { ...(extras.base ?? {}) };\n for (const spec of specs) {\n const primary = opts[spec.attr];\n const alias = spec.aliasAttr && spec.aliasAttr !== spec.attr ? opts[spec.aliasAttr] : undefined;\n let raw: unknown = primary !== undefined ? primary : alias;\n if (spec.kind === 'array' && Array.isArray(primary) && Array.isArray(alias)) raw = [...alias, ...primary];\n if (raw === undefined) continue;\n input[spec.property] = coerce(spec, raw);\n }\n for (const [key, value] of Object.entries(extras.defaults ?? {})) {\n if (input[key] === undefined && value !== undefined) input[key] = value;\n }\n const required = Array.isArray(schema?.required) ? schema.required : [];\n const missingRequired = required.filter((key) => input[key] === undefined);\n return { input, missingRequired };\n}\n\n/** Flag labels for JSON keys (for the combined \"missing required\" error). */\nexport function flagsForProperties(schema: JsonSchema | undefined, properties: readonly string[]): string[] {\n const specs = schemaToFlags(schema);\n return properties.map((property) => {\n const spec = specs.find((s) => s.property === property);\n return spec ? `--${spec.flag}` : property;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Describe\n\nexport type SchemaRow = {\n flag: string;\n alias?: string;\n property: string;\n type: string;\n required: boolean;\n nullable: boolean;\n description: string;\n notes: string[];\n};\n\nfunction typeLabel(spec: FlagSpec): string {\n if (spec.kind === 'enum') return (spec.enumValues ?? []).join('|');\n if (spec.kind === 'array') return `${spec.itemKind === 'enum' ? 'enum' : (spec.itemKind ?? 'string')}[]`;\n if (spec.kind === 'json') return spec.jsonShape === 'any' ? 'json' : spec.jsonShape ?? 'json';\n return spec.kind;\n}\n\n/** Rows for `tabbio tools describe`: required first, then schema order. */\nexport function describeSchema(schema: JsonSchema | undefined): SchemaRow[] {\n const rows = schemaToFlags(schema).map((spec) => ({\n flag: `--${spec.flag}`,\n ...(spec.alias ? { alias: `--${spec.alias}` } : {}),\n property: spec.property,\n type: typeLabel(spec),\n required: spec.required,\n nullable: spec.nullable,\n description: spec.description,\n notes: [...flagNotes(spec).filter((n) => n !== 'required'), ...(spec.nullable ? ['\"null\" clears it'] : [])],\n }));\n return [...rows.filter((r) => r.required), ...rows.filter((r) => !r.required)];\n}\n\nfunction exampleValue(spec: FlagSpec): string | null {\n switch (spec.kind) {\n case 'boolean':\n return null;\n case 'enum':\n return spec.enumValues?.[0] ?? '<value>';\n case 'number':\n case 'integer':\n return '<n>';\n case 'array':\n return spec.itemKind === 'enum' ? (spec.enumValues?.[0] ?? '<value>') : `<${spec.flag}>`;\n case 'json':\n return spec.jsonShape === 'array' ? `'[\u2026]'` : `'{\u2026}'`;\n default:\n return `<${spec.flag}>`;\n }\n}\n\n/** Keys the CLI fills itself for this tool (workflow `userId` from the session). */\nexport function autoFilledProperties(tool: Pick<CatalogTool, 'kind'>, schema: JsonSchema | undefined): string[] {\n return tool.kind === 'workflow' && isRecord(schema?.properties) && 'userId' in (schema?.properties ?? {})\n ? ['userId']\n : [];\n}\n\n/**\n * A copy-pasteable invocation with every required flag as a placeholder.\n * `commandPath` overrides the tool's own path (e.g. `run profile.update` for\n * tools that have no generated command).\n */\nexport function exampleInvocation(\n tool: Pick<CatalogTool, 'kind' | 'commandPath' | 'id'>,\n schema: JsonSchema | undefined,\n commandPath: readonly string[] = tool.commandPath,\n): string {\n if (tool.kind === 'agent') return `tabbio ${commandPath.join(' ')} \"What jobs fit my CV?\"`;\n const skip = new Set(autoFilledProperties(tool, schema));\n const parts = ['tabbio', ...commandPath];\n for (const spec of schemaToFlags(schema)) {\n if (!spec.required || skip.has(spec.property)) continue;\n const value = exampleValue(spec);\n parts.push(value === null ? `--${spec.flag}` : `--${spec.flag} ${value}`);\n }\n return parts.join(' ');\n}\n", "/**\n * Tool input schema \u2192 flag descriptors (the naming, typing and help-note half\n * of core/schema-flags.ts, which re-exports everything here).\n */\nimport { theme } from '../ui/theme';\nimport { type JsonSchema, kebabCase } from './catalog';\n\nexport type ScalarKind = 'string' | 'number' | 'integer' | 'boolean' | 'enum';\nexport type FlagKind = ScalarKind | 'array' | 'json';\n\nexport type FlagSpec = {\n /** Original JSON key sent to the tool. */\n property: string;\n /** Flag name without dashes (`cv-id`, `in-color`). */\n flag: string;\n /** Commander attribute name for `flag`. */\n attr: string;\n /** camelCase alias without dashes (`cvId`), when it differs from `flag`. */\n alias?: string;\n aliasAttr?: string;\n kind: FlagKind;\n /** Element kind for `array`. */\n itemKind?: ScalarKind;\n /** Allowed values for `enum` (or an array of enums). */\n enumValues?: string[];\n /** For `json`: what the parsed value must be. */\n jsonShape?: 'object' | 'array' | 'any';\n nullable: boolean;\n required: boolean;\n /** One-line help (first sentence, \u2264 80 chars). */\n description: string;\n /** Renamed to `in-<name>` because the natural flag is reserved. */\n renamed: boolean;\n defaultValue?: unknown;\n};\n\n/** Global flags (root program) that schema properties must never shadow. */\nexport const RESERVED_GLOBAL_FLAGS: readonly string[] = [\n 'json', 'profile', 'debug', 'yes', 'quiet', 'color', 'no-color', 'api-url', 'app-url', 'help', 'version',\n];\n\n/** Flags every tool command adds on top of the schema flags (see run-tool.ts). */\nexport const RUN_LEVEL_FLAGS: readonly string[] = ['input', 'input-file', 'fields', 'wait', 'timeout', 'output'];\n\nconst RESERVED = new Set([...RESERVED_GLOBAL_FLAGS, ...RUN_LEVEL_FLAGS]);\n\nexport const TOOL_FLAGS_HELP_GROUP = 'Tool flags:';\n\n/** Commander's attribute naming (`cv-id` \u2192 `cvId`). */\nexport function commanderAttr(flag: string): string {\n return flag\n .split('-')\n .reduce((acc, word, index) => (index === 0 ? word : acc + word.charAt(0).toUpperCase() + word.slice(1)), '');\n}\n\nconst ABBREVIATION = /(?:^|[\\s(])(?:e\\.g|i\\.e|etc|vs|approx|incl|min|max)$/i;\n\n/** First sentence of a description, whitespace-collapsed and capped. */\nexport function shortDescription(text: string | undefined, max = 80): string {\n if (!text) return '';\n const clean = text.replace(/\\s+/g, ' ').trim();\n // A sentence ends at . ! ? followed by a capital letter or the end, unless\n // the period closes an abbreviation (\"e.g. YYYY-MM\" stays one sentence).\n let end = clean.length;\n for (const match of clean.matchAll(/[.!?](?=\\s+[A-Z(]|$)/g)) {\n const index = match.index ?? 0;\n if (match[0] === '.' && ABBREVIATION.test(clean.slice(0, index))) continue;\n end = index + 1;\n break;\n }\n const first = clean.slice(0, end).replace(/\\.$/, '');\n if (first.length <= max) return first;\n return `${first.slice(0, max - 1).trimEnd()}${theme.symbols.ellipsis}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNullSchema(schema: JsonSchema): boolean {\n return schema.type === 'null' || (Array.isArray(schema.enum) && schema.enum.length === 1 && schema.enum[0] === null);\n}\n\n/** Strips `| null` from unions and `type: [T, \"null\"]`; reports nullability. */\nfunction unwrapNullable(schema: JsonSchema): { schema: JsonSchema; nullable: boolean } {\n let nullable = schema.nullable === true;\n const union = schema.anyOf ?? schema.oneOf;\n if (Array.isArray(union)) {\n const nonNull = union.filter((member) => !isNullSchema(member));\n if (nonNull.length < union.length) nullable = true;\n if (nonNull.length === 1) {\n const only = nonNull[0] as JsonSchema;\n return { schema: { ...only, description: only.description ?? schema.description }, nullable };\n }\n return { schema: { ...schema, anyOf: nonNull, oneOf: undefined }, nullable };\n }\n if (Array.isArray(schema.allOf) && schema.allOf.length === 1) {\n return unwrapNullable({ ...(schema.allOf[0] as JsonSchema), description: schema.description });\n }\n if (Array.isArray(schema.type)) {\n const types = schema.type.filter((type) => type !== 'null');\n if (types.length < schema.type.length) nullable = true;\n if (types.length === 1) return { schema: { ...schema, type: types[0] }, nullable };\n }\n return { schema, nullable };\n}\n\nfunction scalarKind(schema: JsonSchema): ScalarKind | null {\n if (Array.isArray(schema.enum) && schema.enum.length > 0 && schema.enum.every((v) => typeof v === 'string')) {\n return 'enum';\n }\n if (typeof schema.const === 'string') return 'enum';\n switch (schema.type) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'integer':\n return 'integer';\n case 'boolean':\n return 'boolean';\n default:\n return null;\n }\n}\n\nfunction enumValuesOf(schema: JsonSchema): string[] | undefined {\n if (typeof schema.const === 'string') return [schema.const];\n return Array.isArray(schema.enum) ? schema.enum.filter((v): v is string => typeof v === 'string') : undefined;\n}\n\ntype Classified = Pick<FlagSpec, 'kind' | 'itemKind' | 'enumValues' | 'jsonShape'>;\n\nfunction classify(schema: JsonSchema): Classified {\n const scalar = scalarKind(schema);\n if (scalar) return { kind: scalar, ...(scalar === 'enum' ? { enumValues: enumValuesOf(schema) } : {}) };\n if (schema.type === 'array') {\n const items = Array.isArray(schema.items) ? undefined : schema.items;\n const item = items ? unwrapNullable(items).schema : undefined;\n const itemKind = item ? scalarKind(item) : null;\n if (item && itemKind) {\n return { kind: 'array', itemKind, ...(itemKind === 'enum' ? { enumValues: enumValuesOf(item) } : {}) };\n }\n return { kind: 'json', jsonShape: 'array' };\n }\n if (schema.type === 'object' || schema.properties || schema.additionalProperties) {\n return { kind: 'json', jsonShape: 'object' };\n }\n return { kind: 'json', jsonShape: 'any' };\n}\n\nfunction safeFlagName(property: string): string {\n const name = kebabCase(property)\n .replace(/[^a-z0-9-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n return name || 'value';\n}\n\n/** Describes every top-level property of a tool input schema as a flag. */\nexport function schemaToFlags(schema: JsonSchema | undefined): FlagSpec[] {\n const properties = isRecord(schema?.properties) ? (schema?.properties as Record<string, JsonSchema>) : {};\n const required = new Set(Array.isArray(schema?.required) ? schema.required : []);\n const usedFlags = new Set<string>();\n const usedAttrs = new Set<string>();\n const specs: FlagSpec[] = [];\n\n for (const [property, rawProp] of Object.entries(properties)) {\n const { schema: prop, nullable } = unwrapNullable(isRecord(rawProp) ? rawProp : {});\n let flag = safeFlagName(property);\n const renamed = RESERVED.has(flag) || flag.startsWith('no-');\n if (renamed) flag = `in-${flag}`;\n for (let n = 2; usedFlags.has(flag); n += 1) flag = `${flag.replace(/-\\d+$/, '')}-${n}`;\n usedFlags.add(flag);\n const attr = commanderAttr(flag);\n usedAttrs.add(attr);\n\n const spec: FlagSpec = {\n property,\n flag,\n attr,\n ...classify(prop),\n nullable,\n required: required.has(property),\n description: shortDescription(prop.description ?? rawProp?.description ?? prop.title),\n renamed,\n ...(prop.default !== undefined ? { defaultValue: prop.default } : {}),\n };\n specs.push(spec);\n }\n\n // Aliases after every primary flag is known, so an alias never steals one.\n for (const spec of specs) {\n const alias = spec.property;\n if (spec.renamed || alias === spec.flag || !/^[A-Za-z][A-Za-z0-9_]*$/.test(alias)) continue;\n const aliasAttr = commanderAttr(alias);\n if (usedFlags.has(alias) || (aliasAttr !== spec.attr && usedAttrs.has(aliasAttr))) continue;\n spec.alias = alias;\n spec.aliasAttr = aliasAttr;\n usedAttrs.add(aliasAttr);\n }\n return specs;\n}\n\nexport function placeholderFor(spec: FlagSpec): string {\n switch (spec.kind) {\n case 'boolean':\n return '[boolean]';\n case 'number':\n return '<number>';\n case 'integer':\n return '<int>';\n case 'json':\n return '<json>';\n case 'enum': {\n const joined = (spec.enumValues ?? []).join('|');\n return joined && joined.length <= 32 ? `<${joined}>` : '<choice>';\n }\n default:\n return '<value>';\n }\n}\n\n/** Notes appended to the flag help (and shown by `tools describe`). */\nexport function flagNotes(spec: FlagSpec): string[] {\n const notes: string[] = [];\n if (spec.required) notes.push('required');\n if (spec.kind === 'enum' && placeholderFor(spec) === '<choice>') notes.push(`one of: ${spec.enumValues?.join(', ')}`);\n if (spec.kind === 'array') {\n notes.push('repeatable or comma-separated');\n if (spec.enumValues) notes.push(`each one of: ${spec.enumValues.join(', ')}`);\n }\n if (spec.kind === 'json') notes.push(spec.jsonShape === 'array' ? 'JSON array' : spec.jsonShape === 'object' ? 'JSON object' : 'JSON');\n if (spec.renamed) notes.push(`schema field \"${spec.property}\"`);\n if (spec.defaultValue !== undefined) notes.push(`default: ${JSON.stringify(spec.defaultValue)}`);\n return notes;\n}\n", "import type { ReactElement } from 'react';\nimport { CliError, ExitCode } from '../core/errors';\nimport type { MountOptions, MountOutcome, ScreenControls } from './mount';\n\nexport type { MountOptions, MountOutcome, ScreenControls } from './mount';\n\n/**\n * Guard for every Ink entry point (WP-C extends this file with renderScreen()).\n * Ink writes screen-control escapes into piped output and throws when it\n * cannot enable raw mode, so it must never run without a TTY on both ends.\n */\nexport function isInteractiveTerminal(\n stdin: { isTTY?: boolean } = process.stdin,\n stdout: { isTTY?: boolean } = process.stdout,\n): boolean {\n return Boolean(stdin.isTTY && stdout.isTTY);\n}\n\nexport function assertInteractive(\n what = 'This screen',\n stdin: { isTTY?: boolean } = process.stdin,\n stdout: { isTTY?: boolean } = process.stdout,\n): void {\n if (isInteractiveTerminal(stdin, stdout)) return;\n throw new CliError({\n code: 'NOT_INTERACTIVE',\n message: `${what} needs an interactive terminal`,\n hint: 'Run it in a terminal, or use the non-interactive form (e.g. --json, or pass the values as flags).',\n exitCode: ExitCode.Usage,\n });\n}\n\n/**\n * Mounts an Ink screen after the TTY guard. Ink and React load lazily here,\n * so commands that never render do not pay for them at startup.\n */\nexport async function renderScreen<T>(\n what: string,\n build: (controls: ScreenControls<T>) => ReactElement,\n opts: MountOptions = {},\n): Promise<MountOutcome<T>> {\n assertInteractive(what);\n const { mountScreen } = await import('./mount');\n return mountScreen(build, opts);\n}\n", "/**\n * Interactive hooks: the seam between the non-interactive command layer\n * (WP-B: `commands/tools`, `run`, `approvals`, generated commands) and the Ink\n * screens (WP-C: `ui/screens/*`).\n *\n * Commands call `getInteractiveHooks()` only when `process.stdout.isTTY &&\n * process.stdin.isTTY && !ctx.globals.json`. When no hooks are registered\n * (tests, or a build without the UI) they fall back to plain readline prompts\n * from `core/prompt.ts` and plain printers from `core/output.ts`.\n *\n * The UI registers its implementation once at startup via\n * `setInteractiveHooks()` (see `ui/index.ts`).\n */\nimport type { CommandContext } from '../core/context';\nimport type { ApprovalInfo, CatalogTool } from '../core/mcp';\n\nexport type ApprovalDecision = 'approve' | 'reject' | 'leave';\n\nexport type ToolRunMeta = {\n durationMs: number;\n requestId?: string;\n};\n\nexport interface InteractiveHooks {\n /** Full-screen catalog browser. Resolves when the user quits. */\n browseTools(\n ctx: CommandContext,\n tools: CatalogTool[],\n options: { query?: string; group?: string },\n ): Promise<void>;\n\n /**\n * Form for a tool's input schema, pre-filled with `initial` (flags already\n * parsed). Resolves with the complete input, or `null` when cancelled.\n */\n runToolForm(\n ctx: CommandContext,\n tool: CatalogTool,\n initial: Record<string, unknown>,\n options: { missingRequired: string[] },\n ): Promise<Record<string, unknown> | null>;\n\n /** Boxed approval prompt (yellow rail, y/n/l hotkeys, Esc = leave). */\n approvalPrompt(\n ctx: CommandContext,\n approval: ApprovalInfo & { args: Record<string, unknown> },\n ): Promise<ApprovalDecision>;\n\n /** Optional rich result panel; when absent, `core/output.ts` prints. */\n showResult?(\n ctx: CommandContext,\n tool: CatalogTool,\n result: unknown,\n meta: ToolRunMeta,\n ): Promise<void>;\n}\n\nlet registered: InteractiveHooks | null = null;\n\nexport function setInteractiveHooks(hooks: InteractiveHooks | null): void {\n registered = hooks;\n}\n\nexport function getInteractiveHooks(): InteractiveHooks | null {\n return registered;\n}\n\n/** True when a command may hand control to an Ink screen. */\nexport function canUseInteractiveUi(ctx: CommandContext): boolean {\n return Boolean(\n process.stdout.isTTY &&\n process.stdin.isTTY &&\n !ctx.globals.json &&\n !process.env.CI &&\n registered,\n );\n}\n", "/**\n * Pure table / key-value / cell formatting shared by the result printers\n * (core/output.ts) and list commands. Human cells are one line; TSV cells are\n * raw. Widths are terminal cells (wide CJK / emoji count 2).\n */\nimport { theme } from '../ui/theme';\nimport { relativeTime } from './io';\n\nexport type Row = Record<string, unknown>;\n\nexport function isRecord(value: unknown): value is Row {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Reads `a.b.c` from nested objects. */\nexport function getPath(value: unknown, path: string): unknown {\n let current: unknown = value;\n for (const key of path.split('.')) {\n if (!isRecord(current)) return undefined;\n current = current[key];\n }\n return current;\n}\n\nexport const ISO_DATE = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/;\n\nexport function isRowList(value: unknown): value is Row[] {\n return Array.isArray(value) && value.length > 0 && value.every(isRecord);\n}\n\n\n// ---------------------------------------------------------------------------\n// Cells\n\n/** Terminal cell width: wide East Asian + emoji count 2, combining marks 0. */\nexport function displayWidth(text: string): number {\n let width = 0;\n for (const char of text) {\n const code = char.codePointAt(0) ?? 0;\n if (code < 0x20 || (code >= 0x7f && code < 0xa0)) continue;\n if ((code >= 0x300 && code <= 0x36f) || (code >= 0x200b && code <= 0x200f) || code === 0xfe0f) continue;\n const wide =\n (code >= 0x1100 && code <= 0x115f) ||\n (code >= 0x2e80 && code <= 0xa4cf) ||\n (code >= 0xac00 && code <= 0xd7a3) ||\n (code >= 0xf900 && code <= 0xfaff) ||\n (code >= 0xfe30 && code <= 0xfe4f) ||\n (code >= 0xff00 && code <= 0xff60) ||\n (code >= 0xffe0 && code <= 0xffe6) ||\n (code >= 0x1f300 && code <= 0x1faff) ||\n (code >= 0x20000 && code <= 0x3fffd);\n width += wide ? 2 : 1;\n }\n return width;\n}\n\n/** Cuts to `max` cells, ending with the ellipsis when shortened. */\nexport function truncate(text: string, max: number): string {\n if (displayWidth(text) <= max) return text;\n const ellipsis = theme.symbols.ellipsis;\n const budget = Math.max(0, max - displayWidth(ellipsis));\n let out = '';\n let width = 0;\n for (const char of text) {\n const w = displayWidth(char);\n if (width + w > budget) break;\n out += char;\n width += w;\n }\n return `${out}${ellipsis}`;\n}\n\nfunction pad(text: string, width: number, align: 'left' | 'right'): string {\n const fill = ' '.repeat(Math.max(0, width - displayWidth(text)));\n return align === 'right' ? `${fill}${text}` : `${text}${fill}`;\n}\n\nexport function compactJson(value: unknown): string {\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n\n/** Human cell text: one line, relative dates, yes/no, joined scalar arrays. */\nexport function humanCell(value: unknown, now = Date.now()): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'boolean') return value ? 'yes' : 'no';\n if (typeof value === 'string') {\n if (ISO_DATE.test(value)) {\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) return relativeTime(date, now);\n }\n return value.replace(/\\s+/g, ' ').trim();\n }\n if (Array.isArray(value) && value.every((v) => v === null || typeof v !== 'object')) {\n return value.map((v) => humanCell(v, now)).join(', ');\n }\n if (typeof value === 'object') return compactJson(value);\n return String(value);\n}\n\n/** TSV cell: raw ISO dates, no truncation, tabs/newlines flattened. */\nexport function tsvCell(value: unknown): string {\n if (value === null || value === undefined) return '';\n const text = typeof value === 'object' ? compactJson(value) : String(value);\n return text.replace(/[\\t\\r\\n]+/g, ' ');\n}\n\n// ---------------------------------------------------------------------------\n// Columns\n\nexport type Column = { key: string; label: string; align: 'left' | 'right' };\n\nconst MAX_COLUMNS = 6;\n/** Slots filled first, in order; each takes the first key present. */\nconst PRIORITY: ReadonlyArray<readonly string[]> = [\n ['id'],\n ['title', 'name'],\n ['status', 'state', 'stage'],\n ['company', 'companyName', 'employer'],\n ['location'],\n ['isPublic', 'published', 'visibility'],\n ['updatedAt', 'createdAt'],\n];\n/** Foreign keys (`userId`, `template_id`, `jobIds`) and settings-like constants rank last. */\nconst LOW_VALUE = /^(?:.+Id|.+_id|.+Ids|default[A-Z_].*|(?:.*[a-z])?[Ll]ocale)$/;\n/** Constant columns are only dropped once there are enough rows to tell. */\nconst CONSTANT_MIN_ROWS = 3;\n\nexport function isScalar(value: unknown): boolean {\n return value === null || value === undefined || typeof value !== 'object';\n}\n\nfunction headerLabel(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .toUpperCase();\n}\n\nfunction column(key: string, rows: readonly Row[]): Column {\n const values = rows.map((r) => getPath(r, key)).filter((v) => v !== null && v !== undefined);\n const numeric = values.length > 0 && values.every((v) => typeof v === 'number');\n return { key, label: headerLabel(key), align: numeric ? 'right' : 'left' };\n}\n\nconst isEmpty = (value: unknown) => value === null || value === undefined || value === '';\n\n/**\n * Picks table columns. `--fields` wins verbatim. Otherwise, from scalar\n * columns that are not all empty (and, with \u2265 3 rows, not identical in every\n * row): the PRIORITY slots first, then dense short columns, dense long ones,\n * mostly-empty ones, and foreign keys / constants-like names last. Max six.\n */\nexport function pickColumns(rows: readonly Row[], fields?: readonly string[]): Column[] {\n if (fields?.length) return fields.map((f) => column(f, rows));\n const sample = rows.slice(0, 50);\n const keys: string[] = [];\n for (const row of sample) for (const key of Object.keys(row)) if (!keys.includes(key)) keys.push(key);\n const usable = keys.filter(\n (key) =>\n sample.every((r) => isScalar(r[key]) || (Array.isArray(r[key]) && (r[key] as unknown[]).every(isScalar))) &&\n sample.some((r) => !isEmpty(r[key])),\n );\n const constant = (key: string) => new Set(rows.map((r) => JSON.stringify(r[key] ?? null))).size === 1;\n const varying = rows.length >= CONSTANT_MIN_ROWS ? usable.filter((key) => !constant(key)) : usable;\n const pool = varying.length ? varying : usable;\n\n const chosen: string[] = [];\n for (const group of PRIORITY) {\n const key = group.find((k) => pool.includes(k));\n if (key) chosen.push(key);\n }\n const avgLength = (key: string) =>\n sample.reduce((sum, r) => sum + humanCell(r[key]).length, 0) / Math.max(1, sample.length);\n const tier = (key: string) => {\n if (LOW_VALUE.test(key)) return 3;\n if (sample.filter((r) => isEmpty(r[key])).length * 2 > sample.length) return 2;\n return avgLength(key) > 40 ? 1 : 0;\n };\n const rest = pool\n .filter((k) => !chosen.includes(k))\n .map((key, index) => ({ key, index, tier: tier(key) }))\n .sort((a, b) => a.tier - b.tier || a.index - b.index);\n for (const { key } of rest) {\n if (chosen.length >= MAX_COLUMNS) break;\n chosen.push(key);\n }\n return chosen.slice(0, MAX_COLUMNS).map((key) => column(key, rows));\n}\n\n/** Shrinks the widest columns until the row fits `max` cells. */\nexport function fitWidths(widths: number[], max: number | undefined, gap = 2): number[] {\n const out = [...widths];\n if (!max || max <= 0) return out;\n const total = () => out.reduce((a, b) => a + b, 0) + gap * Math.max(0, out.length - 1);\n const floor = 4;\n while (total() > max) {\n let widest = -1;\n for (let i = 0; i < out.length; i += 1) {\n if ((out[i] as number) > floor && (widest < 0 || (out[i] as number) > (out[widest] as number))) widest = i;\n }\n if (widest < 0) break;\n out[widest] = (out[widest] as number) - 1;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Formatters (pure) and printers\n\nexport type TableOptions = { fields?: readonly string[]; width?: number; now?: number };\n\nexport function formatTable(rows: readonly Row[], opts: TableOptions = {}): string[] {\n if (rows.length === 0) return [theme.dim('No results')];\n const columns = pickColumns(rows, opts.fields);\n if (columns.length === 0) return rows.map((r) => compactJson(r));\n const cells = rows.map((row) => columns.map((c) => humanCell(getPath(row, c.key), opts.now)));\n const natural = columns.map((c, i) => Math.max(displayWidth(c.label), ...cells.map((r) => displayWidth(r[i] as string))));\n const widths = fitWidths(natural, opts.width);\n const line = (values: string[], style?: (s: string) => string) =>\n values\n .map((v, i) => {\n const text = pad(truncate(v, widths[i] as number), widths[i] as number, (columns[i] as Column).align);\n return style ? style(text) : text;\n })\n .join(' ')\n .trimEnd();\n return [line(columns.map((c) => c.label), theme.dim), ...cells.map((r) => line(r))];\n}\n\nexport type KvOptions = { fields?: readonly string[]; width?: number; now?: number };\n\n/** `key value` rows; nested values as compact JSON (\u2264 100 chars); long text in full. */\nexport function formatKv(value: Row, opts: KvOptions = {}): string[] {\n const keys = opts.fields?.length ? [...opts.fields] : Object.keys(value);\n const rows = keys\n .map((key) => [key, getPath(value, key)] as const)\n .filter(([, v]) => v !== undefined);\n if (rows.length === 0) return [theme.dim('(empty)')];\n const width = Math.max(...rows.map(([k]) => displayWidth(k)));\n const lines: string[] = [];\n for (const [key, raw] of rows) {\n const label = theme.dim(pad(key, width, 'left'));\n if (typeof raw === 'string' && !ISO_DATE.test(raw)) {\n const [first = '', ...more] = raw.split(/\\r?\\n/);\n lines.push(`${label} ${first}`);\n for (const next of more) lines.push(`${' '.repeat(width)} ${next}`);\n continue;\n }\n const text = isScalar(raw) || (Array.isArray(raw) && raw.every(isScalar)) ? humanCell(raw, opts.now) : compactJson(raw);\n lines.push(`${label} ${truncate(text, 100)}`);\n }\n return lines;\n}\n", "/**\n * Result printers for tool commands (plan \u00A76, research \u00A74.1 and \u00A75.7).\n *\n * Mode resolution: `--json` / `--output <mode>` \u2192 `TABBIO_OUTPUT` \u2192 a TTY\n * gets the human view (`table`) \u2192 anything else gets TSV (`plain`).\n *\n * json `{ data, meta: { schemaVersion: 1, tool, durationMs, requestId? } }`,\n * pretty on a TTY, compact when piped\n * table human: arrays of objects \u2192 aligned table, wrappers such as\n * `{ cvs: [...], total }` \u2192 the table plus a count footer, objects \u2192\n * key/value rows, scalars \u2192 plain; never wraps, truncates with `\u2026`\n * tsv gh-style plain output: no header, no colour, no truncation, ISO dates\n *\n * Human output is for people only; JSON and TSV never contain ANSI.\n */\nimport { theme } from '../ui/theme';\nimport { type ToolRunMeta, canUseInteractiveUi, getInteractiveHooks } from '../ui/hooks';\nimport type { CatalogTool } from './catalog';\nimport type { CommandContext } from './context';\nimport { usageError } from './errors';\nimport {\n type KvOptions,\n type Row,\n type TableOptions,\n compactJson,\n displayWidth,\n formatKv,\n formatTable,\n getPath,\n humanCell,\n isRecord,\n isRowList,\n isScalar,\n pickColumns,\n tsvCell,\n} from './table';\n\nexport * from './table';\n\nexport type OutputMode = 'json' | 'table' | 'tsv';\n\n/** Accepted spellings for `--output` / `TABBIO_OUTPUT`. */\nconst MODE_ALIASES: Record<string, OutputMode> = {\n json: 'json',\n table: 'table',\n human: 'table',\n plain: 'tsv',\n tsv: 'tsv',\n};\n\nexport const JSON_SCHEMA_VERSION = 1;\n\nexport function parseOutputMode(value: string, source = '--output'): OutputMode {\n const mode = MODE_ALIASES[value.trim().toLowerCase()];\n if (!mode) throw usageError(`${source} must be one of json, table, plain, tsv; got \"${value}\"`);\n return mode;\n}\n\n/** flag \u2192 TABBIO_OUTPUT \u2192 TTY (table) \u2192 piped (tsv). */\nexport function resolveOutputMode(\n opts: { json?: boolean; output?: string },\n env: NodeJS.ProcessEnv = process.env,\n isTTY: boolean = Boolean(process.stdout.isTTY),\n): OutputMode {\n if (opts.json) return 'json';\n if (opts.output) return parseOutputMode(opts.output);\n if (env.TABBIO_OUTPUT?.trim()) return parseOutputMode(env.TABBIO_OUTPUT, 'TABBIO_OUTPUT');\n return isTTY ? 'table' : 'tsv';\n}\n\n/** Something to label a result with: a catalog tool or a static command id. */\nexport type ToolLike = Pick<CatalogTool, 'id'> & Partial<Pick<CatalogTool, 'commandPath' | 'title'>>;\n\nexport type RenderMeta = ToolRunMeta & {\n /** Resolved mode; resolved from ctx + env when omitted. */\n mode?: OutputMode;\n /** `--fields a,b.c` (already split). */\n fields?: string[];\n /** Extra JSON meta (e.g. `approval`). */\n extra?: Record<string, unknown>;\n /** Terminal width override (tests). */\n width?: number;\n};\n\nexport function parseFields(value: string | undefined): string[] | undefined {\n if (!value) return undefined;\n const fields = value.split(',').map((f) => f.trim()).filter(Boolean);\n return fields.length ? fields : undefined;\n}\n\nconst COUNT_KEYS = ['total', 'totalCount', 'count'];\n\n/**\n * Detects list wrappers such as `{ cvs: [...], defaultCvId, total }`: exactly\n * one array-valued key holding objects, on a record that is not itself an\n * entity (no `id`). An empty list counts only next to a count key or alone.\n */\nexport function findListWrapper(value: unknown): { key: string; rows: Row[] } | null {\n if (!isRecord(value) || 'id' in value) return null;\n const arrays = Object.entries(value).filter(([, v]) => Array.isArray(v));\n if (arrays.length !== 1) return null;\n const [key, list] = arrays[0] as [string, unknown[]];\n if (list.length === 0) {\n const counted = COUNT_KEYS.some((k) => typeof value[k] === 'number');\n return counted || Object.keys(value).length === 1 ? { key, rows: [] } : null;\n }\n return list.every(isRecord) ? { key, rows: list as Row[] } : null;\n}\n\nfunction countFooter(wrapper: Row, key: string, shown: number): string {\n const parts = [`${shown} ${shown === 1 ? 'item' : 'items'}`];\n const countKey = COUNT_KEYS.find((k) => typeof wrapper[k] === 'number');\n if (countKey) parts.push(`total ${wrapper[countKey] as number}`);\n const others = Object.keys(wrapper).filter((k) => k !== key && k !== countKey);\n if (others.length) parts.push('--json for all fields');\n return parts.join(' \u00B7 ');\n}\n\n/** Human view of any result (without the header line). */\nexport function formatHuman(result: unknown, opts: TableOptions = {}): string[] {\n if (result === null || result === undefined) return [theme.dim('(no output)')];\n if (typeof result === 'string') return result.split(/\\r?\\n/);\n if (!isRecord(result) && !Array.isArray(result)) return [String(result)];\n if (Array.isArray(result)) {\n if (result.length === 0 || isRowList(result)) return formatTable(result as Row[], opts);\n return result.map((item) => (isScalar(item) ? humanCell(item, opts.now) : compactJson(item)));\n }\n const wrapper = findListWrapper(result);\n if (wrapper) {\n return [...formatTable(wrapper.rows, opts), theme.dim(countFooter(result, wrapper.key, wrapper.rows.length))];\n }\n return formatKv(result, opts);\n}\n\n/** gh-style plain output: TSV rows for lists, `key<TAB>value` for objects. */\nexport function toTsv(result: unknown, fields?: readonly string[]): string {\n const rowsToTsv = (rows: readonly Row[]) => {\n const columns = pickColumns(rows, fields);\n return rows.map((row) => columns.map((c) => tsvCell(getPath(row, c.key))).join('\\t'));\n };\n let lines: string[];\n if (result === null || result === undefined) lines = [];\n else if (Array.isArray(result)) lines = isRowList(result) ? rowsToTsv(result) : result.map(tsvCell);\n else if (isRecord(result)) {\n const wrapper = findListWrapper(result);\n if (wrapper) lines = rowsToTsv(wrapper.rows);\n else {\n const keys = fields?.length ? fields : Object.keys(result);\n lines = keys.map((key) => `${key}\\t${tsvCell(getPath(result, key))}`);\n }\n } else lines = [String(result)];\n return lines.length ? `${lines.join('\\n')}\\n` : '';\n}\n\n/** Applies `--fields` to JSON data, keeping a list wrapper's shape. */\nexport function projectFields(result: unknown, fields?: readonly string[]): unknown {\n if (!fields?.length) return result;\n const pick = (row: Row) => Object.fromEntries(fields.map((f) => [f, getPath(row, f) ?? null]));\n if (Array.isArray(result)) return result.map((item) => (isRecord(item) ? pick(item) : item));\n if (isRecord(result)) {\n const wrapper = findListWrapper(result);\n if (wrapper) return { ...result, [wrapper.key]: wrapper.rows.map(pick) };\n return pick(result);\n }\n return result;\n}\n\nexport type JsonEnvelope = {\n data: unknown;\n meta: { schemaVersion: number; tool: string; durationMs: number; requestId?: string; [key: string]: unknown };\n};\n\nexport function jsonEnvelope(tool: ToolLike, data: unknown, meta: RenderMeta): JsonEnvelope {\n return {\n data: data === undefined ? null : data,\n meta: {\n schemaVersion: JSON_SCHEMA_VERSION,\n tool: tool.id,\n durationMs: Math.round(meta.durationMs),\n ...(meta.requestId ? { requestId: meta.requestId } : {}),\n ...(meta.extra ?? {}),\n },\n };\n}\n\n/** `--json` writer: pretty on a TTY, compact when piped. */\nexport function writeJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, process.stdout.isTTY ? 2 : 0)}\\n`);\n}\n\nexport function formatDuration(ms: number): string {\n if (ms < 60_000) return `${(Math.max(0, ms) / 1000).toFixed(2)}s`;\n const minutes = Math.floor(ms / 60_000);\n return `${minutes}m ${Math.round((ms % 60_000) / 1000)}s`;\n}\n\nfunction shortId(id: string): string {\n return id.length > 12 ? `${id.slice(0, 4)}${theme.symbols.ellipsis}${id.slice(-3)}` : id;\n}\n\n/** `\u2713 cv list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 0.84s \u00B7 req 7f3a\u2026c21` (the rule is the only accent). */\nexport function formatResultHeader(tool: ToolLike, meta: Pick<RenderMeta, 'durationMs' | 'requestId' | 'width'>): string {\n const name = (tool.commandPath?.length ? tool.commandPath.join(' ') : tool.id).trim();\n const right = [formatDuration(meta.durationMs), meta.requestId ? `req ${shortId(meta.requestId)}` : null]\n .filter(Boolean)\n .join(' \u00B7 ');\n const width = Math.min(meta.width ?? 80, 100);\n const used = displayWidth(theme.symbols.success) + 1 + displayWidth(name) + 2 + displayWidth(right) + 1;\n const rule = theme.symbols.line.repeat(Math.max(3, width - used));\n return `${theme.success(theme.symbols.success)} ${theme.bold(name)} ${theme.accent(rule)} ${theme.dim(right)}`;\n}\n\n/**\n * \"Nothing to show\" line for list commands. Human mode prints it on stdout;\n * piped (TSV) output prints it on stderr so the data stream stays empty and\n * parseable; JSON prints nothing here (the caller emits `[]`).\n */\nexport function printEmptyNotice(mode: OutputMode, message: string, opts: { quiet?: boolean } = {}): void {\n if (mode === 'json') return;\n if (mode === 'table') process.stdout.write(`${theme.dim(message)}\\n`);\n else if (!opts.quiet) process.stderr.write(`${theme.dim(message)}\\n`);\n}\n\nexport function printTable(rows: readonly Row[], opts: TableOptions = {}): void {\n const width = opts.width ?? process.stdout.columns;\n for (const line of formatTable(rows, { ...opts, width })) process.stdout.write(`${line}\\n`);\n}\n\nexport function printKv(value: Row, opts: KvOptions = {}): void {\n for (const line of formatKv(value, opts)) process.stdout.write(`${line}\\n`);\n}\n\n/**\n * Prints a tool result in the resolved mode. On an interactive TTY with the\n * Ink UI registered, the human view is handed to `hooks.showResult`.\n */\nexport async function renderResult(ctx: CommandContext, tool: ToolLike, result: unknown, meta: RenderMeta): Promise<void> {\n const mode = meta.mode ?? resolveOutputMode({ json: ctx.globals.json });\n if (mode === 'json') {\n writeJson(jsonEnvelope(tool, projectFields(result, meta.fields), meta));\n return;\n }\n if (mode === 'tsv') {\n process.stdout.write(toTsv(result, meta.fields));\n return;\n }\n const hooks = getInteractiveHooks();\n if (!meta.fields?.length && hooks?.showResult && canUseInteractiveUi(ctx) && 'mcpName' in tool) {\n await hooks.showResult(ctx, tool as CatalogTool, result, { durationMs: meta.durationMs, requestId: meta.requestId });\n return;\n }\n const width = meta.width ?? process.stdout.columns;\n if (!ctx.globals.quiet) process.stdout.write(`${formatResultHeader(tool, { ...meta, width })}\\n`);\n for (const line of formatHuman(result, { fields: meta.fields, width })) process.stdout.write(`${line}\\n`);\n}\n", "/**\n * Pure readers for what PR #512 puts on tool events: artifact cards\n * (`generateImage`, `createDocument`, `createPage`, the edit tools and\n * `artifactGet`, card type `artifact`), research results (card type\n * `research`, with `sources`), live writer drafts (`artifact-draft`) and\n * capability denials (`{ ok: false, error: { code, message, decision? } }`).\n * No I/O; the reducer and `ask` both use these.\n */\nimport type { ArtifactDraftPayload, ToolEventPayload } from './chat-events';\n\n/** Chat stream tool names (`name` on tool events). */\nexport const RESEARCH_TOOL_NAMES: ReadonlySet<string> = new Set(['webSearch', 'readUrl', 'readPdf', 'readGithubRepo', 'readSkill']);\nexport const ARTIFACT_CARD_TOOL_NAMES: ReadonlySet<string> = new Set([\n 'generateImage',\n 'createDocument',\n 'createPage',\n 'updatePage',\n 'updateDocument',\n 'editImage',\n 'artifactGet',\n]);\n\n/** MCP tool ids whose result is an artifact that may still be rendering (`run --wait` polls them). */\nexport const ARTIFACT_PRODUCING_TOOL_IDS: ReadonlySet<string> = new Set([\n 'artifact.generateImage',\n 'artifact.createDocument',\n 'artifact.createPage',\n 'artifact.updatePage',\n 'artifact.updateDocument',\n 'artifact.editImage',\n]);\n\nexport type ArtifactStatus = 'pending' | 'ready' | 'failed';\n\nexport type ChatArtifact = {\n id: string;\n kind: string;\n title: string;\n status: ArtifactStatus;\n versionNumber?: number;\n previewAvailable?: boolean;\n failure?: { code: string; message: string };\n /** Signed preview URL (15 min) for an OSC 8 link, once minted. */\n previewUrl?: string;\n /** Ready, and the screen is still minting the preview link: keep the card live. */\n linkPending?: boolean;\n /** Stop holding the card live (poll gave up or the turn moved on). */\n released?: boolean;\n};\n\nexport type ChatSource = { url: string; title: string; domain?: string };\n\nexport type DraftProgress = {\n phase: ArtifactDraftPayload['phase'];\n kind: string;\n artifactId: string;\n chars: number;\n lines: number;\n sections: number;\n headings: number;\n versionNumber?: number;\n error?: string;\n};\n\nexport type CapabilityDenial = { code: string; message: string; reason?: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | undefined {\n return typeof value === 'string' && value ? value : undefined;\n}\n\nexport function isResearchTool(payload: Pick<ToolEventPayload, 'name' | 'cardType'>): boolean {\n return payload.cardType === 'research' || RESEARCH_TOOL_NAMES.has(payload.name);\n}\n\nexport function isArtifactTool(payload: Pick<ToolEventPayload, 'name' | 'cardType'>): boolean {\n return payload.cardType === 'artifact' || ARTIFACT_CARD_TOOL_NAMES.has(payload.name);\n}\n\nconst STATUSES: ReadonlySet<string> = new Set(['pending', 'ready', 'failed']);\n\n/**\n * The artifact card in a tool result (`ArtifactToolResult`, also the\n * `PAGE_REJECTED` result, which is `ok: false` but still names the failed\n * artifact). Null for suggestions, lists and anything else.\n */\nexport function artifactFromResult(result: unknown): ChatArtifact | null {\n if (!isRecord(result)) return null;\n const id = str(result.artifactId);\n const status = str(result.status);\n if (!id || !status || !STATUSES.has(status) || result.mode === 'suggest') return null;\n const failure = isRecord(result.failure)\n ? { code: str(result.failure.code) ?? 'FAILED', message: str(result.failure.message) ?? '' }\n : undefined;\n return {\n id,\n kind: str(result.kind) ?? 'file',\n title: str(result.title) ?? 'Untitled',\n status: status as ArtifactStatus,\n ...(typeof result.versionNumber === 'number' ? { versionNumber: result.versionNumber } : {}),\n ...(typeof result.previewAvailable === 'boolean' ? { previewAvailable: result.previewAvailable } : {}),\n ...(failure ? { failure } : {}),\n };\n}\n\n/** `sources` of a research result (web search, URL, PDF, GitHub) or a skill read's single `source`. */\nexport function sourcesFromResult(result: unknown): ChatSource[] {\n if (!isRecord(result)) return [];\n const raw = Array.isArray(result.sources) ? result.sources : isRecord(result.source) ? [result.source] : [];\n return raw.filter(isRecord).flatMap((source) => {\n const url = str(source.url);\n if (!url) return [];\n return [{ url, title: str(source.title) ?? url, ...(str(source.domain) ? { domain: str(source.domain) } : {}) }];\n });\n}\n\n/** Appends new sources, keeping the first of each URL (the order numbers them). */\nexport function mergeSources(existing: readonly ChatSource[], incoming: readonly ChatSource[]): ChatSource[] {\n const seen = new Set(existing.map((s) => s.url));\n const merged = [...existing];\n for (const source of incoming) {\n if (seen.has(source.url)) continue;\n seen.add(source.url);\n merged.push(source);\n }\n return merged;\n}\n\n/** Error codes that mean \"this capability is not available right now\", not \"the tool broke\". */\nexport const CAPABILITY_DENIAL_CODES: ReadonlySet<string> = new Set([\n 'SUBSCRIPTION_ENTITLEMENT_DENIED',\n 'RESEARCH_DISABLED',\n 'RESEARCH_NOT_CONFIGURED',\n 'RESEARCH_RATE_LIMITED',\n 'IMAGE_DISABLED',\n 'ARTIFACTS_DISABLED',\n 'ARTIFACT_EDITS_DISABLED',\n 'ARTIFACT_LIMIT_REACHED',\n 'SITES_DISABLED',\n]);\n\nconst DENIAL_REASONS: Record<string, string> = {\n capability_quota_reached: 'daily quota',\n artifact_edit_quota_reached: 'daily edit quota',\n wrong_tier: 'plan tier',\n ai_daily_limit_reached: 'daily credits',\n RESEARCH_DISABLED: 'flag off',\n IMAGE_DISABLED: 'flag off',\n ARTIFACTS_DISABLED: 'flag off',\n ARTIFACT_EDITS_DISABLED: 'flag off',\n SITES_DISABLED: 'flag off',\n RESEARCH_NOT_CONFIGURED: 'not configured',\n ARTIFACT_LIMIT_REACHED: 'daily file cap',\n RESEARCH_RATE_LIMITED: 'hourly fetch cap',\n};\n\n/** A capability denial in a tool result, with a short reason (quota, tier, flag off\u2026). */\nexport function capabilityDenial(result: unknown): CapabilityDenial | null {\n if (!isRecord(result) || result.ok !== false || !isRecord(result.error)) return null;\n const code = str(result.error.code);\n if (!code || !CAPABILITY_DENIAL_CODES.has(code)) return null;\n const decision = isRecord(result.error.decision) ? result.error.decision : undefined;\n const reasonCode =\n str(decision?.reasonCode) ?? (Array.isArray(result.error.reasonCodes) ? str(result.error.reasonCodes[0]) : undefined) ?? code;\n const reason = DENIAL_REASONS[reasonCode] ?? reasonCode.toLowerCase().replace(/_/g, ' ');\n return { code, message: str(result.error.message) ?? 'This is not available right now.', reason };\n}\n\nconst RESEARCH_VERBS: Record<string, [running: string, done: string]> = {\n webSearch: ['Searching the web', 'Searched the web'],\n readUrl: ['Reading pages', 'Read pages'],\n readPdf: ['Reading a PDF', 'Read a PDF'],\n readGithubRepo: ['Reading a repository', 'Read a repository'],\n readSkill: ['Reading a skill', 'Read a skill'],\n};\n\n/** Activity-line title for a research tool (\"Searched the web\"). */\nexport function researchTitle(name: string, running: boolean): string | null {\n const verbs = RESEARCH_VERBS[name];\n return verbs ? verbs[running ? 0 : 1] : null;\n}\n\n/** Folds one `artifact-draft` event into the progress shown on the card. */\nexport function applyDraft(previous: DraftProgress | undefined, event: ArtifactDraftPayload): DraftProgress {\n const base: DraftProgress = previous ?? {\n phase: event.phase,\n kind: event.kind,\n artifactId: event.artifactId,\n chars: 0,\n lines: 0,\n sections: 0,\n headings: 0,\n };\n return {\n ...base,\n phase: event.phase,\n kind: event.kind || base.kind,\n artifactId: event.artifactId,\n chars: event.stats?.chars ?? base.chars + (event.textChars ?? 0),\n lines: event.stats?.lines ?? base.lines + (event.textLines ?? 0),\n sections: event.stats?.sections ?? base.sections,\n headings: event.outline ? event.outline.length : base.headings,\n ...(event.versionNumber !== undefined ? { versionNumber: event.versionNumber } : {}),\n ...(event.error ? { error: event.error.message || event.error.code } : {}),\n };\n}\n\n/** `writing \u00B7 120 lines`, `outline \u00B7 3 sections`, `checking`, `version 2`. */\nexport function draftSummary(draft: DraftProgress): string {\n switch (draft.phase) {\n case 'start':\n return 'starting';\n case 'code':\n return `writing \u00B7 ${draft.lines} ${draft.lines === 1 ? 'line' : 'lines'}`;\n case 'outline':\n return `writing \u00B7 ${draft.headings} ${draft.headings === 1 ? 'section' : 'sections'}`;\n case 'snapshot':\n return 'previewing';\n case 'checking':\n return 'checking';\n case 'end':\n return draft.versionNumber ? `version ${draft.versionNumber}` : 'written';\n case 'error':\n return `failed${draft.error ? `: ${draft.error}` : ''}`;\n default:\n return '';\n }\n}\n\n/** Default preview variant for `artifacts open` and chat links. */\nexport function previewVariantFor(kind: string): 'image' | 'html' {\n return kind === 'image' ? 'image' : 'html';\n}\n", "/**\n * The owner-scoped artifact REST API from PR #512 (`/api/artifacts`, app\n * JWT): list, detail, signed preview and download URLs (15 minutes),\n * versions, restore and delete, plus the helpers `tabbio artifacts` and\n * `run --wait` share: status polling and streaming a download to disk.\n *\n * Shapes mirror `AgentArtifactSummary` & co. in `packages/types/src/\n * artifacts.ts` on `feature/agent-capabilities-phase1`.\n */\nimport { createWriteStream, existsSync, renameSync, rmSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { Readable } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\nimport type { ReadableStream as WebReadableStream } from 'node:stream/web';\nimport { CliError, ExitCode, networkError, usageError } from './errors';\nimport type { ApiClient } from './http';\n\nexport type ArtifactKind = 'document' | 'slides' | 'image' | 'file' | 'page';\nexport type ArtifactState = 'pending' | 'ready' | 'failed';\nexport type ArtifactVariants = { html: boolean; pdf: boolean; pptx: boolean; image: boolean; thumbnail: boolean };\n\nexport type ArtifactSummary = {\n id: string;\n kind: ArtifactKind | string;\n title: string;\n status: ArtifactState;\n locale?: string;\n threadId: string | null;\n runId: string | null;\n variants: ArtifactVariants;\n formats: string[];\n image?: { width: number; height: number } | null;\n aspectRatio?: string | null;\n byteLength: number;\n sourceCount: number;\n error: { code: string; message: string } | null;\n createdAt: string;\n updatedAt: string;\n currentVersion?: { id: string; number: number } | null;\n versionCount?: number;\n site?: { id: string; name: string | null; url: string | null; status: string; hasUnpublishedChanges: boolean } | null;\n};\n\nexport type ArtifactDetail = ArtifactSummary & {\n document: unknown | null;\n sources: Array<{ id?: string; url: string; title: string; domain?: string }>;\n};\n\nexport type ArtifactList = { artifacts: ArtifactSummary[]; nextCursor: string | null };\n\nexport type SignedUrl = { url: string; variant: string; contentType: string; disposition: 'inline' | 'attachment'; expiresAt: string };\n\nexport type ArtifactVersionSummary = {\n id: string;\n number: number;\n status: ArtifactState;\n source: 'agent' | 'user' | 'restore';\n summary: string | null;\n restoredFrom: { versionId: string; number: number } | null;\n isCurrent: boolean;\n createdAt: string;\n updatedAt: string;\n publishedAs: { siteId: string; deployNumber: number; live: boolean } | null;\n checks: { errors: number; warnings: number };\n error?: { code: string; message: string } | null;\n};\n\nexport const ARTIFACT_KINDS = ['document', 'slides', 'image', 'page', 'file'] as const;\nexport const PREVIEW_VARIANTS = ['html', 'pdf', 'image', 'thumbnail'] as const;\nexport const DOWNLOAD_VARIANTS = ['pdf', 'pptx', 'image', 'html'] as const;\nexport type PreviewVariant = (typeof PREVIEW_VARIANTS)[number];\nexport type DownloadVariant = (typeof DOWNLOAD_VARIANTS)[number];\n\nconst BASE = '/api/artifacts';\nconst enc = encodeURIComponent;\n\nexport function listArtifacts(\n api: ApiClient,\n query: { kind?: string; status?: string; threadId?: string; limit?: number; cursor?: string } = {},\n): Promise<ArtifactList> {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) if (value !== undefined && value !== '') params.set(key, String(value));\n const qs = params.toString();\n return api.json<ArtifactList>(`${BASE}${qs ? `?${qs}` : ''}`);\n}\n\nexport function getArtifact(api: ApiClient, id: string): Promise<ArtifactDetail> {\n return api.json<ArtifactDetail>(`${BASE}/${enc(id)}`);\n}\n\nexport function previewUrl(\n api: ApiClient,\n id: string,\n opts: { variant: PreviewVariant; theme?: 'light' | 'dark'; versionId?: string },\n): Promise<SignedUrl> {\n const params = new URLSearchParams({ variant: opts.variant, ...(opts.theme ? { theme: opts.theme } : {}), ...(opts.versionId ? { versionId: opts.versionId } : {}) });\n return api.json<SignedUrl>(`${BASE}/${enc(id)}/preview-url?${params.toString()}`);\n}\n\nexport function downloadUrl(api: ApiClient, id: string, opts: { variant: DownloadVariant; versionId?: string }): Promise<SignedUrl> {\n const params = new URLSearchParams({ variant: opts.variant, ...(opts.versionId ? { versionId: opts.versionId } : {}) });\n return api.json<SignedUrl>(`${BASE}/${enc(id)}/download-url?${params.toString()}`);\n}\n\nexport function listVersions(api: ApiClient, id: string, opts: { limit?: number; cursor?: string } = {}) {\n const params = new URLSearchParams({ ...(opts.limit ? { limit: String(opts.limit) } : {}), ...(opts.cursor ? { cursor: opts.cursor } : {}) });\n const qs = params.toString();\n return api.json<{ versions: ArtifactVersionSummary[]; nextCursor: string | null }>(`${BASE}/${enc(id)}/versions${qs ? `?${qs}` : ''}`);\n}\n\nexport function restoreVersion(api: ApiClient, id: string, versionId: string) {\n return api.json<{ version: ArtifactVersionSummary; artifact: ArtifactSummary }>(\n `${BASE}/${enc(id)}/versions/${enc(versionId)}/restore`,\n { method: 'POST', body: {} },\n );\n}\n\nexport function deleteArtifact(api: ApiClient, id: string) {\n return api.json<{ id: string; deleted: boolean }>(`${BASE}/${enc(id)}`, { method: 'DELETE' });\n}\n\n/** `--format` \u2192 download variant. Image formats all map to the stored image. */\nexport function formatToVariant(format: string): DownloadVariant {\n const f = format.trim().toLowerCase().replace(/^\\./, '');\n if (f === 'pdf' || f === 'pptx' || f === 'html') return f;\n if (['image', 'png', 'jpg', 'jpeg', 'webp', 'gif'].includes(f)) return 'image';\n throw usageError(`--format must be pdf, pptx, html or an image format (png, jpg, webp); got \"${format}\"`);\n}\n\n/** The natural download of a kind, falling back to what is stored. */\nexport function defaultVariantFor(artifact: Pick<ArtifactSummary, 'kind' | 'variants'>): DownloadVariant {\n const v = artifact.variants;\n const preferred: DownloadVariant[] =\n artifact.kind === 'image' ? ['image'] : artifact.kind === 'slides' ? ['pptx', 'pdf', 'html'] : artifact.kind === 'page' ? ['html'] : ['pdf', 'html', 'pptx'];\n return preferred.find((variant) => v?.[variant]) ?? (preferred[0] as DownloadVariant);\n}\n\nconst IMAGE_EXT: Record<string, string> = { 'image/png': 'png', 'image/jpeg': 'jpg', 'image/webp': 'webp', 'image/gif': 'gif' };\n\nexport function extensionFor(variant: string, contentType?: string): string {\n if (variant === 'image') return IMAGE_EXT[(contentType ?? '').split(';')[0]?.trim().toLowerCase() ?? ''] ?? 'png';\n return variant;\n}\n\n/** A safe file name from the artifact title: letters and digits kept (any script), the rest dashes. */\nexport function safeFileName(title: string, ext: string): string {\n const base =\n title\n .normalize('NFKC')\n .replace(/[^\\p{L}\\p{N}]+/gu, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80)\n .replace(/-+$/, '') || 'artifact';\n return `${base}.${ext}`;\n}\n\n/** `--out` may be a directory (the default name goes inside it) or a file path. */\nexport function resolveOutputPath(out: string | undefined, fileName: string, cwd: string = process.cwd()): string {\n if (!out) return join(cwd, fileName);\n try {\n if (statSync(out).isDirectory()) return join(out, fileName);\n } catch {\n // not there yet: a file path\n }\n return out;\n}\n\nexport const WAIT_POLL_START_MS = 2_000;\nexport const WAIT_POLL_MAX_MS = 5_000;\nexport const DEFAULT_ARTIFACT_WAIT_MS = 5 * 60_000;\n\nexport type WaitOptions = {\n timeoutMs?: number;\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n onPoll?: (status: { status: ArtifactState; attempt: number }) => void;\n};\n\nconst defaultSleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/**\n * Polls until the artifact leaves `pending` (2 s, backing off to 5 s) or the\n * timeout passes. Network blips are retried; anything else is thrown.\n */\nexport async function waitForArtifact<T extends { status: ArtifactState }>(\n fetchStatus: () => Promise<T>,\n opts: WaitOptions = {},\n): Promise<{ artifact: T | null; timedOut: boolean }> {\n const sleep = opts.sleep ?? defaultSleep;\n const now = opts.now ?? Date.now;\n const deadline = now() + (opts.timeoutMs ?? DEFAULT_ARTIFACT_WAIT_MS);\n let interval = WAIT_POLL_START_MS;\n let last: T | null = null;\n for (let attempt = 1; ; attempt += 1) {\n try {\n last = await fetchStatus();\n opts.onPoll?.({ status: last.status, attempt });\n if (last.status !== 'pending') return { artifact: last, timedOut: false };\n } catch (error) {\n if (!(error instanceof CliError) || error.exitCode !== ExitCode.Network) throw error;\n }\n const remaining = deadline - now();\n if (remaining <= 0) return { artifact: last, timedOut: true };\n await sleep(Math.min(interval, remaining));\n interval = Math.min(WAIT_POLL_MAX_MS, Math.round(interval * 1.5));\n }\n}\n\nexport type DownloadProgress = { received: number; total: number | null };\n\n/**\n * Streams a signed URL to `dest`. The URL carries its own signature, so no\n * Authorization header is sent. Never overwrites an existing file unless\n * `force`; writes to a temporary file first and renames it into place.\n */\nexport async function downloadToFile(\n url: string,\n dest: string,\n opts: { force?: boolean; fetch?: typeof fetch; onProgress?: (p: DownloadProgress) => void; signal?: AbortSignal } = {},\n): Promise<{ path: string; bytes: number; contentType: string | null }> {\n if (existsSync(dest) && !opts.force) {\n throw new CliError({\n code: 'FILE_EXISTS',\n message: `${dest} already exists`,\n hint: 'Pass --force to overwrite it, or --out <path> for another name.',\n exitCode: ExitCode.Usage,\n });\n }\n const fetchImpl = opts.fetch ?? ((...args: Parameters<typeof fetch>) => fetch(...args));\n let response: Response;\n try {\n response = await fetchImpl(url, { signal: opts.signal });\n } catch (error) {\n throw networkError(new URL(url).origin, error);\n }\n if (!response.ok || !response.body) {\n throw new CliError({\n code: 'DOWNLOAD_FAILED',\n message: `The download failed (HTTP ${response.status})`,\n hint: 'Signed links last 15 minutes; run the command again for a fresh one.',\n exitCode: response.status === 404 ? ExitCode.NotFound : response.status >= 500 ? ExitCode.Server : ExitCode.Error,\n status: response.status,\n });\n }\n const totalHeader = Number(response.headers.get('content-length'));\n const total = Number.isFinite(totalHeader) && totalHeader > 0 ? totalHeader : null;\n const temp = `${dest}.part-${process.pid}`;\n let received = 0;\n const source = Readable.fromWeb(response.body as unknown as WebReadableStream<Uint8Array>);\n source.on('data', (chunk: Buffer) => {\n received += chunk.length;\n opts.onProgress?.({ received, total });\n });\n try {\n await pipeline(source, createWriteStream(temp, { mode: 0o644 }), { signal: opts.signal });\n if (existsSync(dest) && !opts.force) throw new CliError({ code: 'FILE_EXISTS', message: `${dest} already exists`, exitCode: ExitCode.Usage });\n renameSync(temp, dest);\n } catch (error) {\n rmSync(temp, { force: true });\n throw error;\n }\n return { path: dest, bytes: received, contentType: response.headers.get('content-type') };\n}\n", "/**\n * OSC 8 terminal hyperlinks (`ESC ] 8 ;; url BEL text ESC ] 8 ;; BEL`).\n * Only emitted where the terminal is known to support them; everywhere else\n * callers print the plain text (and the URL or a command next to it).\n */\n\n/** Mirrors the `supports-hyperlinks` heuristics without the dependency. */\nexport function supportsHyperlinks(\n env: NodeJS.ProcessEnv = process.env,\n isTTY: boolean = Boolean(process.stdout.isTTY),\n): boolean {\n const forced = env.FORCE_HYPERLINK?.trim();\n if (forced !== undefined && forced !== '') return forced !== '0' && forced.toLowerCase() !== 'false';\n if (!isTTY || env.CI || env.TERM === 'dumb' || env.NO_COLOR !== undefined && env.NO_COLOR !== '') return false;\n if (env.WT_SESSION || env.KITTY_WINDOW_ID || env.WEZTERM_PANE || env.GHOSTTY_RESOURCES_DIR) return true;\n if (env.TERM === 'xterm-kitty' || env.TERM === 'xterm-ghostty' || env.TERM === 'alacritty') return true;\n const vte = Number.parseInt(env.VTE_VERSION ?? '', 10);\n if (Number.isFinite(vte) && vte >= 5000) return true;\n switch (env.TERM_PROGRAM) {\n case 'iTerm.app': {\n const [major = 0, minor = 0] = (env.TERM_PROGRAM_VERSION ?? '').split('.').map((n) => Number.parseInt(n, 10) || 0);\n return major > 3 || (major === 3 && minor >= 1);\n }\n case 'WezTerm':\n case 'vscode':\n case 'ghostty':\n case 'Hyper':\n case 'Tabby':\n return true;\n default:\n return false;\n }\n}\n\nconst OSC = '\\u001b]8;;';\nconst BEL = '\\u0007';\n\n/** `text` as a link to `url`; `url` is sanitized (no control characters). */\nexport function hyperlink(text: string, url: string): string {\n const safe = [...url].filter((ch) => ch.charCodeAt(0) > 0x1f && ch.charCodeAt(0) !== 0x7f).join('');\n return `${OSC}${safe}${BEL}${text}${OSC}${BEL}`;\n}\n", "/**\n * Streaming chat client for `POST /api/agent/chat` (SSE) plus the thread and\n * approval endpoints the chat screen needs. Stream contract (apps/api\n * agent/AGENTS.md): every SSE `data:` line is `{ type, payload }`; comment\n * lines (`: heartbeat`) keep the connection warm and are ignored.\n *\n * Errors: server `error` events are yielded like any other event; transport\n * failures throw CliError (network, timeout, HTTP status); a user abort\n * throws the `CANCELLED` CliError (exit 130).\n */\nimport type {\n AgentApproval,\n AgentChatRequest,\n AgentMode,\n AgentModelsResponse,\n AgentThreadSummary,\n} from '@tabbio/types';\nimport { createParser } from 'eventsource-parser';\nimport type { WireCapabilities } from './capabilities';\nimport { type AgentStreamEvent, parseStreamEvent } from './chat-events';\nimport type { CommandContext } from './context';\nimport { CliError, ExitCode, interruptedError, networkError } from './errors';\nimport { parseJsonResponse } from './http';\nimport { debug } from './runtime';\n\nexport * from './chat-events';\nexport * from './chat-transcript';\n\n/**\n * `AgentChatRequest` plus the #512 fields (`capabilities`, `timezone`) that\n * develop's `@tabbio/types` does not declare yet, and the employer scope.\n */\nexport type ChatRequest = AgentChatRequest & { companyId?: string; capabilities?: WireCapabilities; timezone?: string };\n\nexport type ChatApi = Pick<CommandContext, 'api'>;\n\nexport type StreamChatOptions = {\n signal?: AbortSignal;\n /** Abort when nothing (not even a heartbeat) arrives for this long. Server heartbeats every 25 s. */\n idleTimeoutMs?: number;\n /** Hard cap for one turn. */\n timeoutMs?: number;\n};\n\nconst CHAT_PATH = '/api/agent/chat';\nconst DEFAULT_IDLE_MS = 90_000;\nconst DEFAULT_TURN_MS = 30 * 60_000;\n\n/** Scope headers the agent endpoints read (`x-agent-mode`, `x-company-id`). */\nexport function agentHeaders(mode: AgentMode, companyId?: string): Record<string, string> {\n return { 'x-agent-mode': mode, ...(companyId ? { 'x-company-id': companyId } : {}) };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isEventStream(response: Response): boolean {\n return (response.headers.get('content-type') ?? '').toLowerCase().includes('text/event-stream');\n}\n\n/** One SSE `data` line as sent (`data`) and as parsed (`event`, null for unknown types). */\nexport type StreamFrame = { data: string; event: AgentStreamEvent | null };\n\n/**\n * Streams one chat turn. Yields events in order; ends after the `finish`\n * event (or throws when the stream ends without one). Unknown event types\n * are skipped; `streamChatFrames` keeps them.\n */\nexport async function* streamChat(\n ctx: ChatApi,\n request: ChatRequest,\n opts: StreamChatOptions = {},\n): AsyncGenerator<AgentStreamEvent, void, void> {\n for await (const frame of streamChatFrames(ctx, request, opts)) {\n if (frame.event) yield frame.event;\n else debug(`chat: skipped stream event ${frame.data.slice(0, 80)}`);\n }\n}\n\n/**\n * Like streamChat, but yields every `data` line with its raw text, including\n * event types this CLI does not know (for `chat --json`, which must pass the\n * server's stream through unchanged).\n */\nexport async function* streamChatFrames(\n ctx: ChatApi,\n request: ChatRequest,\n opts: StreamChatOptions = {},\n): AsyncGenerator<StreamFrame, void, void> {\n const { companyId, ...body } = request;\n const controller = new AbortController();\n const userSignal = opts.signal;\n const onUserAbort = () => controller.abort(userSignal?.reason);\n if (userSignal?.aborted) throw interruptedError('Chat turn cancelled');\n userSignal?.addEventListener('abort', onUserAbort, { once: true });\n\n let stalled = false;\n let idleTimer: NodeJS.Timeout | undefined;\n const armIdle = () => {\n clearTimeout(idleTimer);\n idleTimer = setTimeout(() => {\n stalled = true;\n controller.abort(new Error('stream stalled'));\n }, opts.idleTimeoutMs ?? DEFAULT_IDLE_MS);\n idleTimer.unref?.();\n };\n const mapError = (error: unknown): CliError => {\n if (userSignal?.aborted) return interruptedError('Chat turn cancelled');\n if (stalled) {\n return new CliError({\n code: 'TIMEOUT',\n message: 'Tabbio stopped responding',\n hint: 'The stream went quiet. Try again; your thread keeps its history.',\n exitCode: ExitCode.Network,\n cause: error,\n });\n }\n if (error instanceof CliError) return error;\n return networkError(`${ctx.api.profile.apiUrl}${CHAT_PATH}`, error);\n };\n\n let reader: { cancel(): Promise<void> } | undefined;\n let done = false;\n try {\n armIdle();\n let response: Response;\n try {\n response = await ctx.api.raw(CHAT_PATH, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'text/event-stream',\n ...agentHeaders(body.mode, companyId),\n },\n body: JSON.stringify(companyId ? { ...body, companyId } : body),\n signal: controller.signal,\n timeoutMs: opts.timeoutMs ?? DEFAULT_TURN_MS,\n });\n } catch (error) {\n throw mapError(error);\n }\n\n if (!response.ok || !isEventStream(response)) {\n // Envelope / HTTP errors (403 entitlement, 400 validation) throw here.\n await parseJsonResponse(response);\n throw new CliError({\n code: 'BAD_RESPONSE',\n message: 'Tabbio answered the chat request without a stream',\n exitCode: ExitCode.Server,\n status: response.status,\n });\n }\n if (!response.body) throw new CliError({ code: 'BAD_RESPONSE', message: 'Empty chat stream', exitCode: ExitCode.Server });\n\n const queue: StreamFrame[] = [];\n const parser = createParser({\n onEvent(message) {\n if (message.data.trim()) queue.push({ data: message.data, event: parseStreamEvent(message.data) });\n },\n });\n const decoder = new TextDecoder();\n const activeReader = response.body.getReader();\n reader = activeReader;\n let sawFinish = false;\n\n for (;;) {\n let chunk: Awaited<ReturnType<typeof activeReader.read>>;\n try {\n chunk = await activeReader.read();\n } catch (error) {\n throw mapError(error);\n }\n if (chunk.done) break;\n armIdle();\n parser.feed(decoder.decode(chunk.value, { stream: true }));\n while (queue.length > 0) {\n const frame = queue.shift() as StreamFrame;\n if (frame.event?.type === 'finish') sawFinish = true;\n yield frame;\n }\n }\n parser.feed(`${decoder.decode()}\\n\\n`);\n while (queue.length > 0) {\n const frame = queue.shift() as StreamFrame;\n if (frame.event?.type === 'finish') sawFinish = true;\n yield frame;\n }\n done = true;\n if (!sawFinish) {\n if (userSignal?.aborted) throw interruptedError('Chat turn cancelled');\n throw new CliError({\n code: 'STREAM_ENDED',\n message: 'The chat stream ended before Tabbio finished',\n hint: 'Check your connection and try again.',\n exitCode: ExitCode.Network,\n retry: true,\n });\n }\n } finally {\n clearTimeout(idleTimer);\n userSignal?.removeEventListener('abort', onUserAbort);\n if (reader && !done) {\n controller.abort();\n await reader.cancel().catch(() => undefined);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Threads and approvals (JWT endpoints)\n\nexport type ChatScope = { mode: AgentMode; companyId?: string };\n\nexport type ThreadMessage = {\n id: string;\n role: 'user' | 'assistant';\n content: unknown;\n createdAt?: string;\n};\n\nexport type ThreadToolCall = {\n id: string;\n toolName: string;\n args: Record<string, unknown>;\n result?: unknown;\n status: string;\n createdAt?: string;\n};\n\nexport type ThreadMessages = { messages: ThreadMessage[]; toolCalls: ThreadToolCall[] };\n\n/** `{ approval, assistant: { runId, finishReason, text }, mcp?: { result } }` (not streamed). */\nexport type ApprovalDecisionResult = {\n approval: AgentApproval | null;\n assistant?: { runId?: string; finishReason?: string; text?: string };\n mcp?: { result: unknown };\n};\n\nexport function listThreads(ctx: ChatApi, scope: ChatScope): Promise<AgentThreadSummary[]> {\n const query = new URLSearchParams({ mode: scope.mode, ...(scope.companyId ? { companyId: scope.companyId } : {}) });\n return ctx.api.json<AgentThreadSummary[]>(`/api/agent/threads?${query.toString()}`, {\n headers: agentHeaders(scope.mode, scope.companyId),\n });\n}\n\nexport async function getThreadMessages(ctx: ChatApi, threadId: string, scope: ChatScope): Promise<ThreadMessages> {\n const data = await ctx.api.json<Partial<ThreadMessages>>(\n `/api/agent/threads/${encodeURIComponent(threadId)}/messages`,\n { headers: agentHeaders(scope.mode, scope.companyId) },\n );\n return { messages: data?.messages ?? [], toolCalls: data?.toolCalls ?? [] };\n}\n\nfunction decide(\n ctx: ChatApi,\n approvalId: string,\n action: 'confirm' | 'reject',\n scope?: Partial<ChatScope> & { reason?: string },\n): Promise<ApprovalDecisionResult> {\n return ctx.api.json<ApprovalDecisionResult>(`/api/agent/approvals/${encodeURIComponent(approvalId)}/${action}`, {\n method: 'POST',\n body: scope?.reason ? { reason: scope.reason } : {},\n headers: scope?.mode ? agentHeaders(scope.mode, scope.companyId) : undefined,\n // Confirming resumes the agent run server-side; it can take a while.\n timeoutMs: 5 * 60_000,\n });\n}\n\n/** Approves and executes. Chat approvals return the assistant continuation in `assistant.text`. */\nexport function confirmApproval(ctx: ChatApi, approvalId: string, scope?: Partial<ChatScope> & { reason?: string }) {\n return decide(ctx, approvalId, 'confirm', scope);\n}\n\nexport function rejectApproval(ctx: ChatApi, approvalId: string, scope?: Partial<ChatScope> & { reason?: string }) {\n return decide(ctx, approvalId, 'reject', scope);\n}\n\n/** `GET /api/agent/models`: the composer's model picker (ids for `/model <id>`). */\nexport function listModels(ctx: ChatApi, scope: ChatScope): Promise<AgentModelsResponse> {\n return ctx.api.json<AgentModelsResponse>(`/api/agent/models?mode=${encodeURIComponent(scope.mode)}`, {\n headers: agentHeaders(scope.mode, scope.companyId),\n });\n}\n\n/** Plain text of a stored message (`content` is a string or AI-SDK parts). */\nexport function messageText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n return content\n .map((part) => (isRecord(part) && typeof part.text === 'string' ? part.text : ''))\n .filter(Boolean)\n .join('\\n');\n }\n if (isRecord(content) && typeof content.text === 'string') return content.text;\n return '';\n}\n", "/**\n * The chat stream's event contract (`POST /api/agent/chat`, SSE): every\n * `data:` line is `{ type, payload }`. `parseStreamEvent` turns one line\n * into a typed event for the reducer; unknown types parse to null (and\n * `chat --json` still passes them through as they came, see chat.ts).\n *\n * PR #512 adds exactly one event type, `artifact-draft` (the streaming\n * writer's live progress, `ArtifactDraftEvent`). Everything else it adds\n * rides on the existing tool events: research results (`cardType:\n * 'research'`) carry `sources`, artifact tools (`cardType: 'artifact'`)\n * carry `artifactId` and `status`, and capability denials are tool results\n * shaped `{ ok: false, error: { code, message, status, decision? } }`.\n */\nimport type { AgentEventDisplay, AgentMode } from '@tabbio/types';\n\nexport type ToolEventPayload = {\n id: string;\n name: string;\n args: Record<string, unknown>;\n result?: unknown;\n status?: string;\n runId?: string;\n approvalId?: string;\n category?: string;\n entityType?: string;\n entityId?: string;\n display?: AgentEventDisplay;\n stage?: string;\n cardType?: string;\n};\n\nexport type ArtifactDraftPhase = 'start' | 'code' | 'outline' | 'snapshot' | 'checking' | 'end' | 'error';\n\n/**\n * `artifact-draft` payload (ArtifactDraftEvent on #512). `text` (code\n * appended since the last event) and `html` (a sanitized snapshot, up to\n * 1 MB) are dropped here: the terminal shows progress, not the file.\n */\nexport type ArtifactDraftPayload = {\n toolCallId: string;\n artifactId: string;\n kind: string;\n mode?: 'create' | 'edit';\n title: string;\n seq: number;\n phase: ArtifactDraftPhase;\n /** Characters of code received in this event (`text.length`). */\n textChars?: number;\n /** Newlines in this event's code. */\n textLines?: number;\n outline?: Array<{ heading: string; done: boolean }>;\n stats?: { chars: number; lines: number; sections: number };\n versionNumber?: number;\n error?: { code: string; message: string };\n};\n\nexport type AgentStreamEvent =\n | { type: 'start'; payload: { threadId?: string; mastraThreadId?: string; mode?: AgentMode; modelId?: string } }\n | { type: 'text-delta'; payload: { text: string } }\n | { type: 'tool-call'; payload: ToolEventPayload }\n | { type: 'tool-result'; payload: ToolEventPayload }\n | { type: 'tool-call-approval'; payload: ToolEventPayload & { approvalId: string } }\n | { type: 'artifact-draft'; payload: ArtifactDraftPayload }\n | { type: 'error'; payload: { message: string } }\n | {\n type: 'finish';\n payload: { threadId?: string; runId?: string; finishReason?: string; text?: string; messageId?: string };\n };\n\nexport type AgentStreamEventType = AgentStreamEvent['type'];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction toolPayload(raw: Record<string, unknown>): ToolEventPayload | null {\n const id = asString(raw.id);\n const name = asString(raw.name);\n if (!id || !name) return null;\n return {\n ...(raw as Partial<ToolEventPayload>),\n id,\n name,\n args: isRecord(raw.args) ? raw.args : {},\n display: isRecord(raw.display) ? (raw.display as AgentEventDisplay) : undefined,\n };\n}\n\nconst DRAFT_PHASES: ReadonlySet<string> = new Set(['start', 'code', 'outline', 'snapshot', 'checking', 'end', 'error']);\n\nfunction draftPayload(raw: Record<string, unknown>): ArtifactDraftPayload | null {\n const toolCallId = asString(raw.toolCallId);\n const artifactId = asString(raw.artifactId);\n const phase = asString(raw.phase);\n if (!toolCallId || !artifactId || !phase || !DRAFT_PHASES.has(phase)) return null;\n const text = asString(raw.text);\n const stats = isRecord(raw.stats) ? raw.stats : undefined;\n const error = isRecord(raw.error) ? raw.error : undefined;\n return {\n toolCallId,\n artifactId,\n kind: asString(raw.kind) ?? 'document',\n ...(raw.mode === 'create' || raw.mode === 'edit' ? { mode: raw.mode } : {}),\n title: asString(raw.title) ?? '',\n seq: asNumber(raw.seq) ?? 0,\n phase: phase as ArtifactDraftPhase,\n ...(text ? { textChars: text.length, textLines: text.split('\\n').length - 1 } : {}),\n ...(Array.isArray(raw.outline)\n ? {\n outline: raw.outline\n .filter(isRecord)\n .map((entry) => ({ heading: asString(entry.heading) ?? '', done: entry.done === true })),\n }\n : {}),\n ...(stats\n ? { stats: { chars: asNumber(stats.chars) ?? 0, lines: asNumber(stats.lines) ?? 0, sections: asNumber(stats.sections) ?? 0 } }\n : {}),\n ...(asNumber(raw.versionNumber) !== undefined ? { versionNumber: asNumber(raw.versionNumber) } : {}),\n ...(error ? { error: { code: asString(error.code) ?? 'ERROR', message: asString(error.message) ?? '' } } : {}),\n };\n}\n\n/** Parses one SSE `data` field into a typed event; unknown or malformed \u2192 null. */\nexport function parseStreamEvent(data: string): AgentStreamEvent | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(data);\n } catch {\n return null;\n }\n if (!isRecord(parsed) || typeof parsed.type !== 'string') return null;\n const payload = isRecord(parsed.payload) ? parsed.payload : {};\n switch (parsed.type) {\n case 'start':\n return {\n type: 'start',\n payload: {\n threadId: asString(payload.threadId),\n mastraThreadId: asString(payload.mastraThreadId),\n mode: payload.mode === 'employer' ? 'employer' : payload.mode === 'seeker' ? 'seeker' : undefined,\n modelId: asString(payload.modelId),\n },\n };\n case 'text-delta':\n return { type: 'text-delta', payload: { text: asString(payload.text) ?? '' } };\n case 'tool-call':\n case 'tool-result': {\n const tool = toolPayload(payload);\n return tool ? { type: parsed.type, payload: tool } : null;\n }\n case 'tool-call-approval': {\n const tool = toolPayload(payload);\n const approvalId = asString(payload.approvalId);\n return tool && approvalId ? { type: 'tool-call-approval', payload: { ...tool, approvalId } } : null;\n }\n case 'artifact-draft': {\n const draft = draftPayload(payload);\n return draft ? { type: 'artifact-draft', payload: draft } : null;\n }\n case 'error':\n return { type: 'error', payload: { message: asString(payload.message) ?? 'Tabbio hit an error' } };\n case 'finish':\n return {\n type: 'finish',\n payload: {\n threadId: asString(payload.threadId),\n runId: asString(payload.runId),\n finishReason: asString(payload.finishReason),\n text: asString(payload.text),\n messageId: asString(payload.messageId),\n },\n };\n default:\n return null;\n }\n}\n", "/**\n * What a #512 tool event adds to a chat tool row, as a patch the reducer\n * merges into the call: the research flag, verb title and sources; the\n * artifact card; a capability denial. Pure.\n */\nimport {\n type ChatArtifact,\n artifactFromResult,\n capabilityDenial,\n isArtifactTool,\n isResearchTool,\n researchTitle,\n sourcesFromResult,\n} from './chat-artifacts';\nimport type { ToolEventPayload } from './chat-events';\nimport type { ChatAction, ChatToolCall, ToolStage, TranscriptEntry } from './chat-model';\n\nexport type ArtifactStatusAction = Extract<ChatAction, { type: 'artifact-status' }>;\n\n/** True while the card must stay in the live region (rendering, or its link is being minted). */\nexport function holdsArtifact(call: Pick<ChatToolCall, 'artifact'>): boolean {\n const artifact = call.artifact;\n return Boolean(artifact && !artifact.released && (artifact.status === 'pending' || artifact.linkPending));\n}\n\n/** A card with its link state set: a ready card waits for its preview link when the screen can show links. */\nexport function withLinkState(artifact: ChatArtifact, links: boolean): ChatArtifact {\n const linkPending = links && artifact.status === 'ready' && !artifact.previewUrl;\n return { ...artifact, linkPending };\n}\n\nexport function toolExtras(\n payload: ToolEventPayload,\n stage: ToolStage,\n opts: { links: boolean; previous?: ChatToolCall },\n): Partial<ChatToolCall> {\n const extras: Partial<ChatToolCall> = {};\n if (isResearchTool(payload)) {\n extras.research = true;\n const title = researchTitle(payload.name, stage === 'running');\n if (title) extras.title = title;\n if (payload.result !== undefined) {\n const sources = sourcesFromResult(payload.result);\n if (sources.length) extras.sources = sources;\n }\n }\n if (payload.result !== undefined) {\n const denial = capabilityDenial(payload.result);\n if (denial) extras.denial = denial;\n if (isArtifactTool(payload) || opts.previous?.draft) {\n const artifact = artifactFromResult(payload.result);\n if (artifact) {\n const previous = opts.previous?.artifact;\n const merged = previous?.id === artifact.id && previous.previewUrl ? { ...artifact, previewUrl: previous.previewUrl } : artifact;\n extras.artifact = withLinkState(merged, opts.links);\n }\n }\n }\n return extras;\n}\n\n/** Applies an `artifact-status` action to a card. */\nexport function patchArtifact(artifact: ChatArtifact, action: ArtifactStatusAction, links: boolean): ChatArtifact {\n const next: ChatArtifact = {\n ...artifact,\n ...(action.status ? { status: action.status } : {}),\n ...(action.title ? { title: action.title } : {}),\n ...(action.previewUrl ? { previewUrl: action.previewUrl } : {}),\n ...(action.failure ? { failure: action.failure } : {}),\n ...(action.release ? { released: true } : {}),\n };\n const linked = withLinkState(next, links && !action.release);\n // A status-less update of a ready card means \"no link after all\" (minting failed).\n return action.previewUrl === undefined && action.status === undefined && artifact.status === 'ready'\n ? { ...linked, linkPending: false }\n : linked;\n}\n\n/** The last printed state of a card (its tool row or a later `artifact` row). */\nexport function lastShownArtifact(entries: readonly TranscriptEntry[], artifactId: string): ChatArtifact | undefined {\n for (let i = entries.length - 1; i >= 0; i -= 1) {\n const entry = entries[i] as TranscriptEntry;\n if (entry.kind === 'tool' && entry.call.artifact?.id === artifactId) return entry.call.artifact;\n if (entry.kind === 'artifact' && entry.artifact.id === artifactId) return entry.artifact;\n }\n return undefined;\n}\n", "/**\n * Pure chat transcript reducer (no Ink): `chatReducer(state, action)`.\n *\n * `entries` are committed, in order, and never change again; the screen\n * prints them through Ink `<Static>` into native scrollback. `turn.items` is\n * the live tail (running tool rows and the streaming markdown). Promotion\n * moves a strictly ordered prefix of the live items into `entries`:\n * - a tool row once it reached a final stage (or its approval was decided),\n * - a text segment once closed (a tool call followed it, or the turn ended),\n * - and, on `tick` (every ~50 ms), the stable top-level markdown blocks of\n * the open segment (every block except the last, cut at a line end).\n *\n * #512: an artifact card stays live while it renders (or while the screen\n * mints its preview link), then is committed; a status change after that\n * appends one `artifact` row. A settled turn appends its research `sources`.\n */\nimport type { AgentStreamEvent, ArtifactDraftPayload, ToolEventPayload } from './chat';\nimport { type ChatArtifact, applyDraft, mergeSources } from './chat-artifacts';\nimport {\n type ChatAction,\n type ChatState,\n type ChatToolCall,\n type ChatTurn,\n FINAL_STAGES,\n type LiveItem,\n type LiveTool,\n type PendingApproval,\n type ToolStage,\n type TranscriptEntry,\n normalizeText,\n stableBoundary,\n stageOf,\n toolTitle,\n} from './chat-model';\nimport { type ArtifactStatusAction, holdsArtifact, lastShownArtifact, patchArtifact, toolExtras } from './chat-tool-extras';\n\nexport * from './chat-model';\n\ntype Draft = { state: ChatState; now: number };\n\nfunction nextId(d: Draft, prefix: string): string {\n d.state = { ...d.state, seq: d.state.seq + 1 };\n return `${prefix}-${d.state.seq}`;\n}\n\nfunction push(d: Draft, entry: TranscriptEntry): void {\n d.state = { ...d.state, entries: [...d.state.entries, entry] };\n}\n\nfunction setTurn(d: Draft, turn: ChatTurn | null): void {\n d.state = { ...d.state, turn };\n}\n\nfunction commitMarkdown(d: Draft, turn: ChatTurn, text: string): ChatTurn {\n if (!text.trim()) return turn;\n push(d, { kind: 'markdown', id: nextId(d, 'md'), text, gap: turn.lastKind !== 'label' });\n return { ...turn, committedText: true, lastKind: 'markdown' };\n}\n\n/**\n * Moves the finished prefix of the live items into `entries`. `force`\n * (a new message) also commits cards still rendering; later status changes\n * then arrive as their own rows.\n */\nfunction promote(d: Draft, final: boolean, force = false): void {\n let turn = d.state.turn;\n if (!turn) return;\n const items = [...turn.items];\n while (items.length > 0) {\n const item = items[0] as LiveItem;\n if (item.kind === 'tool') {\n if (!force && ((!FINAL_STAGES.has(item.call.stage) && !item.call.left) || holdsArtifact(item.call))) break;\n const call = item.call.artifact ? { ...item.call, artifact: { ...item.call.artifact, linkPending: false } } : item.call;\n push(d, { kind: 'tool', id: nextId(d, 'tool'), call, gap: turn.lastKind === 'markdown' });\n turn = { ...turn, lastKind: 'tool' };\n items.shift();\n continue;\n }\n const pending = item.text.slice(item.committed);\n if (item.closed || final) {\n turn = commitMarkdown(d, turn, pending);\n items.shift();\n continue;\n }\n const boundary = stableBoundary(pending);\n if (boundary > 0) {\n turn = commitMarkdown(d, turn, pending.slice(0, boundary));\n items[0] = { ...item, committed: item.committed + boundary };\n }\n break;\n }\n turn = { ...turn, items };\n const settled = (turn.finished || force) && items.length === 0;\n if (settled && turn.sources.length) push(d, { kind: 'sources', id: nextId(d, 'sources'), sources: turn.sources });\n setTurn(d, settled ? null : turn);\n}\n\nfunction closeOpenText(items: LiveItem[]): LiveItem[] {\n return items.map((item) => (item.kind === 'text' && !item.closed ? { ...item, closed: true } : item));\n}\n\nfunction upsertTool(d: Draft, payload: ToolEventPayload, stage: ToolStage, extra: Partial<ChatToolCall> = {}): void {\n const turn = d.state.turn;\n if (!turn) return;\n const index = turn.items.findIndex((item) => item.kind === 'tool' && item.call.id === payload.id);\n const final = FINAL_STAGES.has(stage);\n const previous = index >= 0 ? (turn.items[index] as LiveTool).call : undefined;\n const enriched = toolExtras(payload, stage, { links: d.state.links, previous });\n extra = { ...enriched, ...extra };\n if (enriched.sources?.length) {\n setTurn(d, { ...turn, sources: mergeSources(turn.sources, enriched.sources) });\n }\n if (index >= 0) {\n const item = turn.items[index] as LiveTool;\n const finishing = final && item.call.endedAt === undefined;\n const call: ChatToolCall = {\n ...item.call,\n stage,\n args: Object.keys(payload.args).length ? payload.args : item.call.args,\n ...(payload.result !== undefined ? { result: payload.result } : {}),\n preview: payload.display?.preview ?? item.call.preview,\n ...(finishing ? { endedAt: d.now, durationMs: Math.max(0, d.now - item.call.startedAt) } : {}),\n ...extra,\n };\n const current = d.state.turn as ChatTurn;\n const items = [...current.items];\n items[index] = { ...item, call };\n setTurn(d, { ...current, items });\n return;\n }\n const call: ChatToolCall = {\n id: payload.id,\n name: payload.name,\n title: toolTitle(payload),\n args: payload.args,\n stage,\n ...(payload.result !== undefined ? { result: payload.result } : {}),\n preview: payload.display?.preview,\n startedAt: d.now,\n ...(final ? { endedAt: d.now } : {}),\n ...extra,\n };\n // A tool call ends the text segment before it.\n const current = d.state.turn as ChatTurn;\n setTurn(d, { ...current, items: [...closeOpenText(current.items), { kind: 'tool', id: payload.id, call }] });\n}\n\n/** `artifact-draft`: the writer's progress on the live card of that tool call. */\nfunction applyArtifactDraft(d: Draft, event: ArtifactDraftPayload): void {\n const turn = d.state.turn;\n const index = turn?.items.findIndex((item) => item.kind === 'tool' && item.call.id === event.toolCallId) ?? -1;\n if (!turn || index < 0) return;\n const item = turn.items[index] as LiveTool;\n const items = [...turn.items];\n items[index] = { ...item, call: { ...item.call, draft: applyDraft(item.call.draft, event) } };\n setTurn(d, { ...turn, items });\n}\n\n/** A card's status or link changed: update it while live, else append one row if anything changed. */\nfunction applyArtifactStatus(d: Draft, action: ArtifactStatusAction): void {\n const turn = d.state.turn;\n const index = turn?.items.findIndex((item) => item.kind === 'tool' && item.call.artifact?.id === action.artifactId) ?? -1;\n if (turn && index >= 0) {\n const item = turn.items[index] as LiveTool;\n const artifact = patchArtifact(item.call.artifact as ChatArtifact, action, d.state.links);\n const items = [...turn.items];\n items[index] = { ...item, call: { ...item.call, artifact } };\n setTurn(d, { ...turn, items });\n promote(d, false);\n return;\n }\n const shown = lastShownArtifact(d.state.entries, action.artifactId);\n if (!shown || action.release) return;\n const next = { ...patchArtifact(shown, action, false), linkPending: false };\n if (next.status === shown.status && next.previewUrl === shown.previewUrl) return;\n push(d, { kind: 'artifact', id: nextId(d, 'artifact'), artifact: next });\n}\n\nfunction finishTurn(d: Draft, payload: { finishReason?: string; text?: string; threadId?: string }): void {\n let turn = d.state.turn;\n if (!turn) return;\n const finalText = payload.text?.trim() ?? '';\n let items = closeOpenText(turn.items);\n let revision: string | null = null;\n let extraNote: string | null = null;\n if (payload.finishReason === 'error') {\n if (!turn.error && finalText) turn = { ...turn, error: finalText };\n else if (finalText && normalizeText(finalText) !== normalizeText(turn.error ?? '')) extraNote = finalText;\n } else if (finalText && normalizeText(finalText) !== normalizeText(turn.text)) {\n if (!normalizeText(turn.text) || !turn.committedText) {\n // Nothing printed yet: the server's final text replaces the streamed one.\n items = [...items.filter((item) => item.kind !== 'text'), { kind: 'text', id: 'final', text: finalText, committed: 0, closed: true }];\n } else {\n revision = finalText;\n }\n }\n turn = { ...turn, items, finished: true, finishReason: payload.finishReason };\n if (payload.threadId) d.state = { ...d.state, threadId: payload.threadId };\n setTurn(d, turn);\n promote(d, true);\n if (revision) {\n push(d, { kind: 'notice', id: nextId(d, 'note'), tone: 'info', text: 'Tabbio revised this answer:' });\n push(d, { kind: 'markdown', id: nextId(d, 'md'), text: revision, gap: false });\n }\n if (turn.error) push(d, { kind: 'notice', id: nextId(d, 'note'), tone: 'error', text: turn.error });\n if (extraNote) push(d, { kind: 'notice', id: nextId(d, 'note'), tone: 'info', text: extraNote });\n d.state = { ...d.state, streaming: false };\n}\n\nfunction applyStream(d: Draft, event: AgentStreamEvent): void {\n const turn = d.state.turn;\n if (event.type === 'start') {\n d.state = {\n ...d.state,\n threadId: event.payload.threadId ?? d.state.threadId,\n modelId: event.payload.modelId ?? d.state.modelId,\n };\n return;\n }\n if (!turn || turn.finished) return;\n setTurn(d, { ...turn, lastEventAt: d.now });\n switch (event.type) {\n case 'text-delta': {\n if (!event.payload.text) return;\n const current = d.state.turn as ChatTurn;\n const items = [...current.items];\n const last = items[items.length - 1];\n if (last?.kind === 'text' && !last.closed) items[items.length - 1] = { ...last, text: last.text + event.payload.text };\n else items.push({ kind: 'text', id: nextId(d, 'text'), text: event.payload.text, committed: 0, closed: false });\n setTurn(d, { ...current, items, text: current.text + event.payload.text });\n return;\n }\n case 'tool-call':\n upsertTool(d, event.payload, stageOf(event.payload, 'running'));\n promote(d, false);\n return;\n case 'tool-result':\n upsertTool(d, event.payload, stageOf(event.payload, 'completed'));\n promote(d, false);\n return;\n case 'artifact-draft':\n applyArtifactDraft(d, event.payload);\n return;\n case 'tool-call-approval': {\n upsertTool(d, event.payload, 'pending_approval', { approvalId: event.payload.approvalId });\n const approval: PendingApproval = {\n approvalId: event.payload.approvalId,\n toolCallId: event.payload.id,\n name: event.payload.name,\n title: toolTitle(event.payload),\n args: event.payload.args,\n requestedAt: d.now,\n };\n const others = d.state.approvals.filter((a) => a.approvalId !== approval.approvalId);\n d.state = { ...d.state, approvals: [...others, approval] };\n promote(d, false);\n return;\n }\n case 'error':\n setTurn(d, { ...(d.state.turn as ChatTurn), error: event.payload.message });\n return;\n case 'finish':\n finishTurn(d, event.payload);\n return;\n }\n}\n\nfunction resolveApproval(d: Draft, action: Extract<ChatAction, { type: 'approval-decided' }>): void {\n const approval = d.state.approvals.find((a) => a.approvalId === action.approvalId);\n d.state = { ...d.state, approvals: d.state.approvals.filter((a) => a.approvalId !== action.approvalId) };\n if (!approval) return;\n const decision = action.error ? 'leave' : action.decision;\n const stage: ToolStage = decision === 'approve' ? 'completed' : decision === 'reject' ? 'declined' : 'pending_approval';\n const decided: Partial<ChatToolCall> = { stage, decision, left: decision === 'leave', endedAt: d.now };\n const waited = { durationMs: Math.max(0, d.now - approval.requestedAt) };\n const turn = d.state.turn;\n const live = turn?.items.some((item) => item.kind === 'tool' && item.call.id === approval.toolCallId);\n if (turn && live) {\n const items = turn.items.map((item) =>\n item.kind === 'tool' && item.call.id === approval.toolCallId ? { ...item, call: { ...item.call, ...decided, ...waited } } : item,\n );\n setTurn(d, { ...turn, items });\n promote(d, false);\n } else {\n // The card collapses to one row (research \u00A75.8) even when the call row is gone.\n const call: ChatToolCall = {\n id: approval.toolCallId,\n name: approval.name,\n title: approval.title,\n args: approval.args,\n approvalId: approval.approvalId,\n startedAt: approval.requestedAt,\n ...decided,\n ...waited,\n } as ChatToolCall;\n push(d, { kind: 'tool', id: nextId(d, 'tool'), call, gap: false });\n }\n if (action.error) push(d, { kind: 'notice', id: nextId(d, 'note'), tone: 'error', text: action.error });\n if (action.text?.trim()) push(d, { kind: 'markdown', id: nextId(d, 'md'), text: action.text.trim(), gap: true });\n}\n\n/** The reducer with an injected clock (tests); an action's own `at` still wins. */\nexport function createChatReducer(now: () => number = Date.now): (state: ChatState, action: ChatAction) => ChatState {\n return (state, action) => reduceChat(state, action, now);\n}\n\nexport function chatReducer(state: ChatState, action: ChatAction): ChatState {\n return reduceChat(state, action, Date.now);\n}\n\nfunction reduceChat(state: ChatState, action: ChatAction, now: () => number): ChatState {\n const d: Draft = { state, now: 'at' in action && typeof action.at === 'number' ? action.at : now() };\n switch (action.type) {\n case 'submit': {\n if (d.state.turn) promote(d, true, true);\n push(d, { kind: 'user', id: nextId(d, 'user'), text: action.text });\n push(d, { kind: 'assistant', id: nextId(d, 'label') });\n const turn: ChatTurn = {\n id: `turn-${d.state.seq}`,\n startedAt: d.now,\n lastEventAt: d.now,\n items: [],\n text: '',\n committedText: false,\n lastKind: 'label',\n finished: false,\n sources: [],\n };\n d.state = { ...d.state, turn, streaming: true };\n return d.state;\n }\n case 'tick':\n promote(d, false);\n return d.state;\n case 'stream-failed': {\n const turn = d.state.turn;\n if (turn && !turn.finished) {\n setTurn(d, { ...turn, items: closeOpenText(turn.items), finished: true });\n promote(d, true);\n }\n push(d, {\n kind: 'notice',\n id: nextId(d, 'note'),\n tone: action.cancelled ? 'attention' : 'error',\n text: action.message,\n ...(action.hint ? { hint: action.hint } : {}),\n });\n d.state = { ...d.state, streaming: false };\n return d.state;\n }\n case 'approval-decided':\n resolveApproval(d, action);\n return d.state;\n case 'notice':\n push(d, { kind: 'notice', id: nextId(d, 'note'), tone: action.tone, text: action.text, ...(action.hint ? { hint: action.hint } : {}) });\n return d.state;\n case 'new-thread':\n d.state = { ...d.state, threadId: undefined };\n return d.state;\n case 'set-thread':\n d.state = { ...d.state, threadId: action.threadId };\n return d.state;\n case 'history':\n d.state = { ...d.state, threadId: action.threadId };\n for (const message of action.messages) {\n if (!message.text.trim()) continue;\n if (message.role === 'user') push(d, { kind: 'user', id: nextId(d, 'user'), text: message.text });\n else {\n push(d, { kind: 'assistant', id: nextId(d, 'label') });\n push(d, { kind: 'markdown', id: nextId(d, 'md'), text: message.text, gap: false });\n }\n }\n return d.state;\n case 'set-mode':\n d.state = { ...d.state, mode: action.mode, threadId: undefined };\n return d.state;\n case 'set-model':\n d.state = { ...d.state, modelId: action.modelId };\n return d.state;\n case 'set-capability':\n d.state = { ...d.state, capabilities: { ...d.state.capabilities, [action.key]: action.value } };\n return d.state;\n case 'artifact-status':\n applyArtifactStatus(d, action);\n return d.state;\n case 'expand-last-tool': {\n const last = [...d.state.entries].reverse().find((e): e is Extract<TranscriptEntry, { kind: 'tool' }> => e.kind === 'tool');\n if (last) push(d, { kind: 'tool-detail', id: nextId(d, 'detail'), call: last.call });\n return d.state;\n }\n default:\n applyStream(d, action);\n return d.state;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["isRecord", "text", "isRecord", "isRecord", "isRecord", "isRecord", "call", "current", "item", "isRecord"]
|
|
7
|
+
}
|