@tabbio-technologies/cli 1.2.8 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +86 -19
  3. package/dist/chunks/{chunk-7LNC3FIV.js → chunk-GGJEDG3P.js} +95 -14
  4. package/dist/chunks/{chunk-7LNC3FIV.js.map → chunk-GGJEDG3P.js.map} +4 -4
  5. package/dist/chunks/{chunk-Y6GWIFHI.js → chunk-KBIQKZUK.js} +3 -53
  6. package/dist/chunks/chunk-KBIQKZUK.js.map +7 -0
  7. package/dist/chunks/{chunk-QVR5KIEQ.js → chunk-KHLGZ5IV.js} +1796 -244
  8. package/dist/chunks/chunk-KHLGZ5IV.js.map +7 -0
  9. package/dist/chunks/{chunk-NAWA6NCZ.js → chunk-NRFVKK3S.js} +37 -96
  10. package/dist/chunks/chunk-NRFVKK3S.js.map +7 -0
  11. package/dist/chunks/chunk-TP3CRQJD.js +106 -0
  12. package/dist/chunks/chunk-TP3CRQJD.js.map +7 -0
  13. package/dist/chunks/{entry-WENOOT6W.js → entry-ZAXWZSEE.js} +2023 -770
  14. package/dist/chunks/entry-ZAXWZSEE.js.map +7 -0
  15. package/dist/chunks/{mount-NGUARMCL.js → mount-36JUVX3R.js} +3 -2
  16. package/dist/chunks/{mount-NGUARMCL.js.map → mount-36JUVX3R.js.map} +1 -1
  17. package/dist/chunks/{program-O2BA5L6Z.js → program-J6GENE2V.js} +314 -375
  18. package/dist/chunks/program-J6GENE2V.js.map +7 -0
  19. package/dist/chunks/{status-I5UAQPBY.js → status-2C7BECKK.js} +3 -3
  20. package/dist/cli.js +1 -1
  21. package/package.json +4 -8
  22. package/dist/chunks/chunk-NAWA6NCZ.js.map +0 -7
  23. package/dist/chunks/chunk-QVR5KIEQ.js.map +0 -7
  24. package/dist/chunks/chunk-Y6GWIFHI.js.map +0 -7
  25. package/dist/chunks/entry-WENOOT6W.js.map +0 -7
  26. package/dist/chunks/program-O2BA5L6Z.js.map +0 -7
  27. /package/dist/chunks/{status-I5UAQPBY.js.map → status-2C7BECKK.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/core/schema-flags.ts", "../../src/core/schema-spec.ts", "../../src/core/chat-model.ts", "../../src/core/capabilities.ts", "../../src/ui/render.ts", "../../src/commands/login.ts", "../../src/core/prompt.ts", "../../src/ui/hooks.ts", "../../src/core/table.ts", "../../src/core/output.ts", "../../src/core/chat-artifacts.ts", "../../src/core/artifacts.ts", "../../src/core/artifact-save.ts", "../../src/ui/hyperlink.ts", "../../src/core/chat.ts", "../../src/core/chat-events.ts", "../../../../packages/utils/src/public-url.ts", "../../src/core/chat-card-fields.ts", "../../src/core/chat-card-kinds.ts", "../../src/core/chat-card-cv.ts", "../../src/core/chat-cards.ts", "../../src/core/chat-tool-extras.ts", "../../src/core/chat-text.ts", "../../src/core/chat-draft.ts", "../../src/core/chat-transcript.ts", "../../src/core/chat-save-targets.ts", "../../src/ui/components/cards/card-lines.ts"],
4
+ "sourcesContent": ["/**\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", "/**\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 { SavedFile } from './artifact-save';\nimport type { AgentStreamEvent, ToolEventPayload } from './chat';\nimport type { ArtifactStatus, CapabilityDenial, ChatArtifact, ChatSource, DraftProgress } from './chat-artifacts';\nimport type { ChatCard } from './chat-cards';\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 /** The card the app would show for this result, printed under the row. */\n card?: ChatCard;\n /** Files saved for this call (artifact or CV export) while its row was still live. */\n saved?: SavedFiles;\n};\n\n/** The first lines of a saved text file, for the inline preview. */\nexport type SavedPreview = { path: string; lines: string[]; total: number };\n\n/** Files written to disk for an artifact or a CV export (chat auto-save, `/save`, `/download`). */\nexport type SavedFiles = {\n artifactId?: string;\n cvId?: string;\n title?: string;\n /** Artifact kind (`page`, `document`, `slides`, `image`) or `cv`. */\n kind?: string;\n files: SavedFile[];\n preview?: SavedPreview;\n /** Saving failed: the reason (the entry then says how to retry). */\n error?: string;\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 /** A tool result as the app's card: numbered rows, links, a next step. */\n | { kind: 'card'; id: string; card: ChatCard; toolCallId: string }\n /** Files saved to disk, with a short preview of a text file. */\n | { kind: 'saved'; id: string; saved: SavedFiles };\n\n/** `start`: this segment's offset in the turn's text (every delta, in order). */\nexport type LiveText = { kind: 'text'; id: string; text: string; committed: number; closed: boolean; start?: number };\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 /** Offsets in `text` where each text segment started. */\n segments?: number[];\n /** A suspected repeat of earlier text starts here: held back from scrollback and the live view. */\n echoAt?: number;\n /** Internal tool calls of this turn (working memory): no row, only in the raw `ctrl+o` view. */\n hidden?: ChatToolCall[];\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 /** The profile's app URL (public job links on cards); production when unset. */\n appUrl?: string;\n /** Hidden internal calls of settled turns, with the entry count when they settled (for `ctrl+o`). */\n hiddenCalls?: Array<{ call: ChatToolCall; at: number }>;\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 versionId?: string;\n versionNumber?: number;\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 /** Files were saved (or saving failed) for an artifact or a CV export tool call. */\n | ({ type: 'files-saved'; toolCallId?: string; saved: SavedFiles } & At);\n\nexport function initialChatState(opts: {\n mode: AgentMode;\n threadId?: string;\n modelId?: string;\n capabilities?: ChatCapabilities;\n links?: boolean;\n appUrl?: string;\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 ...(opts.appUrl ? { appUrl: opts.appUrl } : {}),\n };\n}\n\n/** Every card in the transcript, oldest first (for `/open <n>` via `latestCardLinks`). */\nexport function cardsInTranscript(entries: readonly TranscriptEntry[]): ChatCard[] {\n return entries.flatMap((entry) => (entry.kind === 'card' ? [entry.card] : []));\n}\n\n/**\n * Internal tools the app never shows (its HIDDEN_TOOLS): the agent's working\n * memory. They get no transcript row; `ctrl+o` still shows them raw and\n * `chat --json` passes their events through unchanged.\n */\nexport const HIDDEN_TOOL_NAMES: ReadonlySet<string> = new Set(['updateWorkingMemory', 'getWorkingMemory', 'clearWorkingMemory']);\n\nexport function isHiddenTool(name: string): boolean {\n return HIDDEN_TOOL_NAMES.has(name);\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", "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", "import type { Command } from 'commander';\nimport open from 'open';\nimport {\n chooseLoginMethod,\n credentialsFromLogin,\n hasDisplay,\n loginWithBrowser,\n loginWithEmailOtp,\n revokeSession,\n} from '../core/auth';\nimport { type Profile, type ResolvedProfile, updateConfig } from '../core/config';\nimport { type CommandContext, createCommandContext } from '../core/context';\nimport { type Credentials, fingerprint, loadStoredCredentials, saveCredentials } from '../core/credentials';\nimport { usageError } from '../core/errors';\nimport { ApiClient, type TokenPayload } from '../core/http';\nimport { printJson, successLine, writeOut } from '../core/io';\nimport { McpSession, clearCatalogCache } from '../core/mcp';\nimport { promptLine, promptSecret } from '../core/prompt';\nimport { debug, deviceLabel, info, warn } from '../core/runtime';\nimport { theme } from '../ui/theme';\n\ntype LoginOptions = {\n browser?: boolean;\n email?: string;\n token?: string;\n withToken?: boolean;\n nonInteractive?: boolean;\n};\n\n/** `--with-token`: the whole of stdin is the token (e.g. `tabbio login --with-token < token.txt`). */\nexport async function readTokenFromStdin(stdin: NodeJS.ReadStream = process.stdin): Promise<string> {\n if (stdin.isTTY) {\n throw usageError('--with-token reads the token from stdin', 'Pipe it in: `tabbio login --with-token < token.txt`.');\n }\n const chunks: Buffer[] = [];\n for await (const chunk of stdin) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n const token = Buffer.concat(chunks).toString('utf8').trim();\n if (!token) throw usageError('No token on stdin');\n return token;\n}\n\n/** Saves --api-url / --app-url given on the command line into the profile. */\nexport function persistProfileUrls(profile: Profile, sources: ResolvedProfile['sources']): void {\n if (sources.apiUrl !== 'flag' && sources.appUrl !== 'flag') return;\n updateConfig((config) => {\n const current = config.profiles[profile.name] ?? {};\n config.profiles[profile.name] = {\n ...current,\n ...(sources.apiUrl === 'flag' ? { apiUrl: profile.apiUrl } : {}),\n ...(sources.appUrl === 'flag' ? { appUrl: profile.appUrl } : {}),\n };\n });\n}\n\n/** Best effort: end the profile's previous server session after a new sign-in. */\nasync function revokePrevious(profile: Profile, refreshToken: string | undefined, keep?: string, fetchImpl?: typeof fetch): Promise<void> {\n if (!refreshToken || refreshToken === keep) return;\n await revokeSession(new ApiClient(profile, null, { persist: false, fetch: fetchImpl }), refreshToken).catch((error: Error) =>\n debug(`previous session not revoked: ${error.message}`),\n );\n}\n\ntype SessionTarget = Pick<CommandContext, 'profile' | 'sources'>;\n\n/**\n * Stores a new app session (any login flow): saves the credentials, drops the\n * catalog cache of the previous credential, persists --api-url/--app-url and\n * ends the previous server session. Shared by `tabbio login` and `/login`.\n */\nexport async function saveAppSession(ctx: SessionTarget, payload: TokenPayload, opts: { fetch?: typeof fetch } = {}): Promise<Credentials> {\n const previous = loadStoredCredentials(ctx.profile.name);\n // The app session also authenticates MCP; any stored personal token is dropped.\n const creds = credentialsFromLogin(ctx.profile, payload);\n saveCredentials(creds);\n clearCatalogCache(ctx.profile);\n persistProfileUrls(ctx.profile, ctx.sources);\n await revokePrevious(ctx.profile, previous?.refreshToken, payload.refreshToken, opts.fetch);\n return creds;\n}\n\n/**\n * Checks a personal MCP token with `tools/list` (which also writes the\n * catalog cache), then stores it in place of any session. Shared by\n * `tabbio login --token` and `/login token`.\n */\nexport async function saveTokenSession(\n ctx: SessionTarget,\n rawToken: string,\n opts: { fetch?: typeof fetch } = {},\n): Promise<{ token: string; toolCount: number; visibleTools: number }> {\n const token = rawToken.trim();\n if (!token) throw usageError('No token entered');\n const probe = { profile: ctx.profile.name, mcpToken: token };\n const session = await McpSession.connect(ctx.profile, probe, opts.fetch ? { fetch: opts.fetch } : {});\n let toolCount = 0;\n let visibleTools = 0;\n try {\n const tools = await session.listTools({ refresh: true });\n toolCount = tools.length;\n visibleTools = tools.filter((t) => !t.hidden).length;\n } finally {\n await session.close();\n }\n const previous = loadStoredCredentials(ctx.profile.name);\n saveCredentials(probe);\n persistProfileUrls(ctx.profile, ctx.sources);\n await revokePrevious(ctx.profile, previous?.refreshToken, undefined, opts.fetch);\n return { token, toolCount, visibleTools };\n}\n\n/** \"Sara Ahmed <sara@acme.ae>\", or the email alone. */\nexport function describeUser(user: Credentials['user'] | null | undefined): string {\n if (!user) return 'your account';\n return user.name ? `${user.name} <${user.email}>` : user.email;\n}\n\n/** `--token` / `--with-token`: MCP-only mode with a user-created personal token. */\nasync function loginWithToken(ctx: CommandContext, rawToken: string): Promise<void> {\n if (!rawToken.trim().startsWith('tabbio_mcp_')) {\n warn('This is not a tabbio_mcp_ token; treating it as an OAuth access token.');\n }\n const { token, toolCount } = await saveTokenSession(ctx, rawToken);\n\n if (ctx.globals.json) {\n printJson({\n profile: ctx.profile.name,\n method: 'token',\n user: null,\n mcp: { kind: 'personal-token', token: fingerprint(token) },\n tools: toolCount,\n });\n return;\n }\n writeOut(successLine(`Token accepted \u00B7 ${toolCount} tools available \u00B7 profile ${ctx.profile.name}`));\n writeOut(theme.dim(' MCP-only mode: `tabbio chat` and approving actions need `tabbio login` (browser or --email).'));\n}\n\nasync function obtainSession(ctx: CommandContext, method: 'browser' | 'email', opts: LoginOptions): Promise<TokenPayload> {\n const api = new ApiClient(ctx.profile, null, { persist: false });\n if (method === 'email') {\n const email = opts.email?.trim() || (await promptLine('Email: '));\n info(`Sending a sign-in code to ${email}\u2026`);\n return loginWithEmailOtp(api, {\n email,\n promptCode: (attempt) => promptSecret(attempt === 1 ? 'Enter the 6-digit code: ' : 'Try the code again: '),\n onInvalidCode: (left) => warn(`That code did not match. ${left} attempt${left === 1 ? '' : 's'} left.`),\n });\n }\n\n const agentMode = Boolean(opts.nonInteractive);\n if (!agentMode) info(`Connecting this computer (${deviceLabel()}) to Tabbio\u2026`);\n const controller = new AbortController();\n const onSigint = () => controller.abort();\n process.once('SIGINT', onSigint);\n try {\n return await loginWithBrowser(api, {\n device: deviceLabel(),\n signal: controller.signal,\n openUrl: async (url) => {\n if (agentMode) return false;\n try {\n await open(url);\n return true;\n } catch {\n return false;\n }\n },\n onWaiting: (url, opened, details) => {\n if (agentMode) {\n // One JSON line for the calling agent; the result line follows on completion.\n printJson({ url, state: details.state, expiresAt: details.expiresAt });\n return;\n }\n info(opened ? theme.dim('If your browser did not open, visit:') : 'Open this URL to continue:');\n info(` ${theme.accent(url)}`);\n info(theme.dim('Waiting for you to approve in the browser\u2026 (Ctrl-C to cancel)'));\n },\n });\n } finally {\n process.off('SIGINT', onSigint);\n }\n}\n\nasync function runLogin(opts: LoginOptions, cmd: Command): Promise<void> {\n const ctx = createCommandContext(cmd);\n if (opts.nonInteractive) ctx.globals.json = true;\n const method = chooseLoginMethod({\n browser: opts.browser,\n email: opts.email,\n token: opts.token,\n withToken: opts.withToken,\n nonInteractive: opts.nonInteractive,\n isTTY: Boolean(process.stdin.isTTY && process.stderr.isTTY),\n hasDisplay: hasDisplay(),\n });\n if (method === 'token') {\n return loginWithToken(ctx, opts.withToken ? await readTokenFromStdin() : (opts.token ?? ''));\n }\n\n const payload = await obtainSession(ctx, method, opts);\n const creds = await saveAppSession(ctx, payload);\n\n if (ctx.globals.json) {\n printJson({\n profile: ctx.profile.name,\n method,\n apiUrl: ctx.profile.apiUrl,\n user: creds.user ?? null,\n mcp: { kind: 'app-session' },\n });\n return;\n }\n writeOut(successLine(`Signed in as ${theme.bold(describeUser(creds.user))} \u00B7 profile ${ctx.profile.name}`));\n if (process.env.TABBIO_TOKEN) {\n warn('TABBIO_TOKEN is set, so tool commands keep using that personal token.');\n }\n writeOut(theme.dim(' Next: tabbio (home) \u00B7 tabbio chat \u00B7 tabbio tools \u00B7 tabbio status'));\n}\n\nexport function registerLoginCommand(program: Command): void {\n program\n .command('login')\n .description('Sign in (browser by default; --email for SSH/headless; --token for MCP-only)')\n .option('--browser', 'Approve this computer in your browser')\n .option('--email <address>', 'Sign in with a one-time code sent to this email')\n .option('--token <token>', 'Use a personal MCP token (tabbio_mcp_\u2026); tool commands only')\n .option('--with-token', 'Read a personal MCP token from stdin (CI)')\n .option(\n '--non-interactive',\n 'For agents: print {\"url\",\"state\",\"expiresAt\"} as JSON, wait for the browser approval, never prompt',\n )\n .addHelpText(\n 'after',\n '\\nThe browser flow opens <app-url>/cli/connect and receives the session on 127.0.0.1.\\n' +\n 'Environment: TABBIO_TOKEN / TABBIO_ACCESS_TOKEN override stored credentials (never saved).',\n )\n .action(async (opts: LoginOptions, cmd: Command) => runLogin(opts, cmd));\n}\n", "import { createInterface } from 'node:readline';\nimport { type CliError, interruptedError, usageError } from './errors';\n\n/**\n * Tiny prompt helpers for the non-Ink commands (login, logout). Prompts are\n * written to stderr so stdout stays clean for `--json`.\n */\n\nfunction cancelled(): CliError {\n return interruptedError();\n}\n\n/** Reads one line. Works for TTY and piped stdin (e.g. `echo 123456 | tabbio login --email \u2026`). */\nexport function promptLine(question: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const rl = createInterface({ input: process.stdin, output: process.stderr, terminal: Boolean(process.stdin.isTTY) });\n let answered = false;\n rl.once('SIGINT', () => {\n rl.close();\n reject(cancelled());\n });\n rl.once('close', () => {\n if (!answered) reject(usageError('No input received'));\n });\n rl.question(question, (answer) => {\n answered = true;\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\n/**\n * Reads a secret with masked echo (`\u2022` per character) on a TTY. Falls back to\n * a plain line read when stdin is not a terminal.\n */\nexport function promptSecret(question: string): Promise<string> {\n const stdin = process.stdin;\n if (!stdin.isTTY || typeof stdin.setRawMode !== 'function') return promptLine(question);\n\n return new Promise((resolve, reject) => {\n let value = '';\n process.stderr.write(question);\n const wasRaw = stdin.isRaw;\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding('utf8');\n\n const finish = (error?: CliError) => {\n stdin.off('data', onData);\n stdin.setRawMode(wasRaw);\n stdin.pause();\n process.stderr.write('\\n');\n if (error) reject(error);\n else resolve(value.trim());\n };\n\n const onData = (chunk: string) => {\n for (const char of chunk) {\n if (char === '\\u0003') return finish(cancelled()); // Ctrl-C\n if (char === '\\u0004' && value === '') return finish(cancelled()); // Ctrl-D\n if (char === '\\r' || char === '\\n') return finish();\n if (char === '\\u007f' || char === '\\b') {\n if (value.length > 0) {\n value = value.slice(0, -1);\n process.stderr.write('\\b \\b');\n }\n continue;\n }\n if (char < ' ') continue;\n value += char;\n process.stderr.write('\u2022');\n }\n };\n stdin.on('data', onData);\n });\n}\n\n/**\n * Yes/no confirmation. `assumeYes` (from `--yes`) short-circuits to true; a\n * non-interactive session without `--yes` fails with exit code 2.\n */\nexport async function confirm(\n question: string,\n opts: { defaultYes?: boolean; assumeYes?: boolean } = {},\n): Promise<boolean> {\n if (opts.assumeYes) return true;\n if (!process.stdin.isTTY) {\n throw usageError(`${question} (needs confirmation)`, 'Re-run with --yes to confirm non-interactively.');\n }\n const suffix = opts.defaultYes ? ' [Y/n] ' : ' [y/N] ';\n const answer = (await promptLine(`${question}${suffix}`)).toLowerCase();\n if (!answer) return Boolean(opts.defaultYes);\n return answer === 'y' || answer === 'yes';\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 versionId?: string;\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 ...(str(result.versionId) ? { versionId: str(result.versionId) } : {}),\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 { randomUUID } from 'node:crypto';\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, interruptedError, 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 type ArtifactVersionDetail = ArtifactVersionSummary & { variants: ArtifactVariants };\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, signal?: AbortSignal): Promise<ArtifactDetail> {\n return api.json<ArtifactDetail>(`${BASE}/${enc(id)}`, { signal });\n}\n\nexport function getArtifactVersion(api: ApiClient, id: string, versionId: string, signal?: AbortSignal): Promise<ArtifactVersionDetail> {\n return api.json<ArtifactVersionDetail>(`${BASE}/${enc(id)}/versions/${enc(versionId)}`, { signal });\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; signal?: AbortSignal }): 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()}`, { signal: opts.signal });\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 signal?: AbortSignal;\n};\n\nconst defaultSleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\nfunction assertNotCancelled(signal?: AbortSignal): void {\n if (signal?.aborted) throw interruptedError('File save cancelled');\n}\n\nfunction sleepUntilPoll(ms: number, sleep: (ms: number) => Promise<void>, signal?: AbortSignal): Promise<void> {\n if (!signal) return sleep(ms);\n assertNotCancelled(signal);\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n reject(interruptedError('File save cancelled'));\n };\n let timer: ReturnType<typeof setTimeout> | undefined;\n signal.addEventListener('abort', onAbort, { once: true });\n if (signal.aborted) {\n onAbort();\n return;\n }\n if (sleep === defaultSleep) {\n timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n } else {\n sleep(ms).then(\n () => { signal.removeEventListener('abort', onAbort); resolve(); },\n (error: unknown) => { signal.removeEventListener('abort', onAbort); reject(error); },\n );\n }\n });\n}\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 assertNotCancelled(opts.signal);\n try {\n last = await fetchStatus();\n assertNotCancelled(opts.signal);\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 sleepUntilPoll(Math.min(interval, remaining), sleep, opts.signal);\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-${randomUUID()}`;\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, { flags: 'wx', mode: 0o600 }), { signal: opts.signal });\n assertNotCancelled(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 * Saving artifacts (pages, documents, slides, images) and CV exports to disk\n * (package Y implements; package X wires `/save`, `/show`, `/download`).\n *\n * Files land in `TABBIO_ARTIFACTS_DIR` or `<cwd>/tabbio-artifacts`, named\n * `<slug-of-title>-<last 6 of id>.<ext>`, and are never overwritten: a taken\n * name gets `-2`, `-3`. Artifacts come from their signed download URLs (no\n * Authorization header); CV exports from the same authenticated export\n * routes the app uses (`GET /api/cv/export/:format`, `GET /api/cv/:id/export/:format`).\n */\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport {\n type ArtifactDetail,\n type DownloadVariant,\n defaultVariantFor,\n downloadToFile,\n downloadUrl,\n extensionFor,\n formatToVariant,\n getArtifact,\n getArtifactVersion,\n} from './artifacts';\nimport { activeCommandSignal } from './cancellation';\nimport type { CommandContext } from './context';\nimport { CliError, ExitCode, isCliError, usageError } from './errors';\nimport { combineSignals, parseJsonResponse } from './http';\n\nexport type SavedFile = { path: string; bytes: number; kind: string };\n\n/** CV export formats the API serves. */\nexport const CV_EXPORT_FORMATS = ['pdf', 'docx', 'txt', 'md'] as const;\n\n/** `TABBIO_ARTIFACTS_DIR`, else `<cwd>/tabbio-artifacts`. Created on first save. */\nexport function artifactsDir(env: NodeJS.ProcessEnv = process.env, cwd = process.cwd()): string {\n const custom = env.TABBIO_ARTIFACTS_DIR?.trim();\n return custom ? resolve(cwd, custom) : join(cwd, 'tabbio-artifacts');\n}\n\n/** `TABBIO_NO_ARTIFACT_SAVE=1` (or true/yes) turns chat and ask auto-save off. */\nexport function autoSaveDisabled(env: NodeJS.ProcessEnv = process.env): boolean {\n const value = env.TABBIO_NO_ARTIFACT_SAVE?.trim().toLowerCase();\n return Boolean(value && value !== '0' && value !== 'false' && value !== 'no');\n}\n\nfunction ensureDir(dir: string): void {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n}\n\n/** `Portfolio: Sara Ahmed` + `cmui\u20269r7z2q` \u2192 `portfolio-sara-ahmed-9r7z2q`. */\nexport function artifactBaseName(title: string, id: string): string {\n const slug =\n title\n .normalize('NFKC')\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 60)\n .replace(/-+$/, '') || 'artifact';\n const short = id.replace(/[^A-Za-z0-9]/g, '').slice(-6).toLowerCase();\n return short ? `${slug}-${short}` : slug;\n}\n\n/** `<dir>/<base>.<ext>`, or `<base>-2.<ext>`, `-3`\u2026 when taken. */\nexport function uniquePath(dir: string, base: string, ext: string): string {\n const suffix = ext ? `.${ext}` : '';\n let candidate = join(dir, `${base}${suffix}`);\n for (let n = 2; existsSync(candidate); n += 1) candidate = join(dir, `${base}-${n}${suffix}`);\n return candidate;\n}\n\n/** `./tabbio-artifacts/x.html` inside the working directory, `~/\u2026` under home, else absolute. */\nexport function displayPath(path: string, cwd = process.cwd(), home = homedir()): string {\n const rel = relative(cwd, path);\n if (rel && !rel.startsWith('..') && !isAbsolute(rel)) return `.${sep}${rel}`;\n const fromHome = relative(home, path);\n if (home && fromHome && !fromHome.startsWith('..') && !isAbsolute(fromHome)) return `~${sep}${fromHome}`;\n return path;\n}\n\n/** `830 B`, `12 KB`, `1.4 MB`. */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.max(1, Math.round(bytes / 1024))} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nconst TEXT_EXTENSIONS = new Set(['html', 'htm', 'md', 'markdown', 'txt', 'csv', 'json', 'svg', 'css', 'js']);\n\n/** Files worth an inline preview (text, not PDF, decks or images). */\nexport function isTextFile(path: string): boolean {\n const ext = path.split('.').pop()?.toLowerCase() ?? '';\n return TEXT_EXTENSIONS.has(ext);\n}\n\n/**\n * What to download for a ready artifact: a page its HTML; a document its\n * HTML and PDF when the API offers both; slides the PPTX; an image the image.\n */\nexport function variantsToSave(artifact: Pick<ArtifactDetail, 'kind' | 'variants'>): DownloadVariant[] {\n const v = artifact.variants ?? { html: false, pdf: false, pptx: false, image: false, thumbnail: false };\n switch (artifact.kind) {\n case 'page':\n return ['html'];\n case 'image':\n return ['image'];\n case 'slides':\n return v.pptx ? ['pptx'] : [defaultVariantFor(artifact)];\n case 'document': {\n const both = (['html', 'pdf'] as const).filter((variant) => v[variant]);\n return both.length ? [...both] : [defaultVariantFor(artifact)];\n }\n default:\n return [defaultVariantFor(artifact)];\n }\n}\n\nfunction notReadyError(id: string, failed: boolean, message?: string): CliError {\n return failed\n ? new CliError({ code: 'ARTIFACT_FAILED', message: message ?? 'No file was made', exitCode: ExitCode.Error })\n : new CliError({\n code: 'ARTIFACT_NOT_READY',\n message: 'This file is still being created',\n hint: `Wait for it with \\`tabbio artifacts wait ${id}\\`, then save it again.`,\n exitCode: ExitCode.Error,\n });\n}\n\n/** Downloads a ready artifact into `dir` (or `artifactsDir()`), never overwriting. */\nexport async function saveArtifactToDisk(\n ctx: CommandContext,\n artifactId: string,\n opts: { dir?: string; formats?: string[]; versionId?: string; signal?: AbortSignal } = {},\n): Promise<SavedFile[]> {\n const signal = combineSignals(activeCommandSignal, opts.signal);\n const [artifact, version] = await Promise.all([\n getArtifact(ctx.api, artifactId, signal),\n opts.versionId ? getArtifactVersion(ctx.api, artifactId, opts.versionId, signal) : Promise.resolve(null),\n ]);\n const status = version?.status ?? artifact.status;\n if (status !== 'ready') throw notReadyError(artifactId, status === 'failed', version?.error?.message ?? artifact.error?.message);\n if (signal.aborted) throw new CliError({ code: 'INTERRUPTED', message: 'File save cancelled', exitCode: ExitCode.Interrupted });\n const variants = opts.formats?.length ? [...new Set(opts.formats.map(formatToVariant))] : variantsToSave({ kind: artifact.kind, variants: version?.variants ?? artifact.variants });\n const dir = opts.dir ? resolve(opts.dir) : artifactsDir();\n ensureDir(dir);\n const base = artifactBaseName(artifact.title, artifact.id || artifactId);\n const saved: SavedFile[] = [];\n for (const [i, variant] of variants.entries()) {\n try {\n const signed = await downloadUrl(ctx.api, artifactId, { variant, versionId: opts.versionId, signal });\n const dest = uniquePath(dir, base, extensionFor(variant, signed.contentType));\n const file = await downloadToFile(signed.url, dest, { signal });\n saved.push({ path: file.path, bytes: file.bytes, kind: variant });\n } catch (error) {\n // The first format is the file; a second one (a document's PDF) may still be rendering.\n if (i === 0 || !isCliError(error) || error.code !== 'ARTIFACT_NOT_READY') throw error;\n }\n }\n return saved;\n}\n\nfunction isMainCv(cvId: string | null | undefined): boolean {\n const id = cvId?.trim().toLowerCase() ?? '';\n return !id || id === 'master' || id === 'main';\n}\n\n/** A safe file name from `content-disposition` (`filename*` or `filename`), without its extension. */\nexport function dispositionBaseName(header: string | null): string | null {\n if (!header) return null;\n const star = /filename\\*\\s*=\\s*(?:UTF-8'')?([^;]+)/i.exec(header)?.[1];\n const plain = /filename\\s*=\\s*\"?([^\";]+)\"?/i.exec(header)?.[1];\n let name = star ?? plain;\n if (!name) return null;\n try {\n name = decodeURIComponent(name.trim().replace(/^\"|\"$/g, ''));\n } catch {\n name = name.trim();\n }\n const base = name\n .split(/[\\\\/]/)\n .pop()\n ?.replace(/\\.[A-Za-z0-9]{1,5}$/, '')\n .normalize('NFKC')\n .replace(/[^\\p{L}\\p{N}._-]+/gu, '-')\n .replace(/^[-.]+|[-.]+$/g, '')\n .slice(0, 80);\n return base || null;\n}\n\n/**\n * Downloads a CV export into the artifacts dir. `cvId` null, empty or\n * `master` is the main CV (`GET /api/cv/export/:format`); anything else is\n * that CV (`GET /api/cv/:id/export/:format`). Signed in with the app session.\n */\nexport async function saveCvExportToDisk(\n ctx: CommandContext,\n cvId: string | null,\n opts: { format?: string; dir?: string; signal?: AbortSignal } = {},\n): Promise<SavedFile> {\n const signal = combineSignals(activeCommandSignal, opts.signal);\n const format = (opts.format ?? 'pdf').trim().toLowerCase().replace(/^\\./, '');\n if (!(CV_EXPORT_FORMATS as readonly string[]).includes(format)) {\n throw usageError(`CV exports are ${CV_EXPORT_FORMATS.join(', ')}; got \"${opts.format}\"`);\n }\n const main = isMainCv(cvId);\n const path = main ? `/api/cv/export/${format}` : `/api/cv/${encodeURIComponent(String(cvId))}/export/${format}`;\n const response = await ctx.api.raw(path, { method: 'GET', headers: { accept: '*/*' }, timeoutMs: 180_000, signal });\n if (!response.ok) {\n await parseJsonResponse(response);\n throw new CliError({ code: 'EXPORT_FAILED', message: `The CV export failed (HTTP ${response.status})`, exitCode: ExitCode.Server });\n }\n if (signal.aborted) throw new CliError({ code: 'INTERRUPTED', message: 'File save cancelled', exitCode: ExitCode.Interrupted });\n const dir = opts.dir ? resolve(opts.dir) : artifactsDir();\n ensureDir(dir);\n const fallback = main ? 'main-cv' : artifactBaseName('cv', String(cvId));\n const base = dispositionBaseName(response.headers.get('content-disposition')) ?? fallback;\n const dest = uniquePath(dir, base, format);\n const url = `${ctx.api.profile.apiUrl}${path}`;\n const file = await downloadToFile(url, dest, { fetch: async () => response, signal });\n return { path: file.path, bytes: file.bytes, kind: format };\n}\n\n/** The first `maxLines` lines of a saved text file, for the inline code preview and `/show`. */\nexport async function readSavedPreview(path: string, maxLines = 12): Promise<{ lines: string[]; total: number }> {\n const text = await readFile(path, 'utf8');\n const lines = text.replace(/\\r\\n?/g, '\\n').split('\\n');\n if (lines.length > 1 && lines[lines.length - 1] === '') lines.pop();\n return { lines: lines.slice(0, Math.max(0, maxLines)), total: lines.length };\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", "const DEFAULT_PUBLIC_SITE_URL = 'https://www.tabbio.com';\nconst DEFAULT_APP_SITE_URL = 'https://app.tabbio.com';\nconst DEFAULT_PUBLIC_DOMAIN = 'tabbio.com';\n// A handle may start with a letter OR a digit. Phone-number-style handles\n// (e.g. \"0501414197ff\") are real, registered CVs, but a letter-only first\n// character silently rejected them: getPublicHandleFromHostname then returned\n// null, the proxy skipped its subdomain branch, and `{handle}.tabbio.com`\n// served a full, indexable duplicate of the marketing site instead of the CV.\n//\n// Length is 3\u201363: the maximum length of a single DNS label, which is the real\n// constraint on a `{handle}.tabbio.com` subdomain. It was 3\u201339, borrowed from\n// USERNAME_MAX_LENGTH, but company career pages do not use the username policy -\n// `companySlugSchema` allows 48 characters. A 40-to-48-character company slug\n// was therefore accepted at creation and then unroutable: isPublicHandleLike\n// returned false, so the proxy skipped its subdomain branch and locale-prefixed\n// the path into a 404, while the matching subdomain was treated as a\n// non-canonical wildcard and bounced to the www root. This regex governs\n// routing only; USERNAME_MAX_LENGTH stays 39 as a deliberate product cap on\n// what a person may register.\n//\n// Still: alphanumeric start/end, no leading/trailing hyphen and no \"--\" (that\n// sequence is reserved for job slugs); reserved labels are excluded separately\n// by isPublicHandleLike.\nconst HANDLE_SEGMENT_REGEX = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;\n\nexport const RESERVED_PUBLIC_SUBDOMAINS = [\n 'www',\n 'app',\n 'api',\n 'server',\n 'v2',\n 'beta',\n 'beta-api',\n 'staging',\n 'admin',\n // The partner portal is its own app on partners.tabbio.com. Reserving the\n // label keeps it out of the handle space so no user or company can claim it\n // and shadow the host through wildcard DNS.\n 'partners',\n 'mail',\n 'cdn',\n 'static',\n 'assets',\n 'jobs',\n 'companies',\n 'support',\n 'help',\n // Public skill share pages (skills.tabbio.com/<skillId>); reserving both\n // labels keeps the singular from ever resolving as a profile handle.\n 'skills',\n 'skill',\n // The public CV Health check (cvhealth.tabbio.com, served by apps/web). The\n // hyphenated spelling is reserved with it so neither can become a handle\n // that reads as the first-party check.\n 'cvhealth',\n 'cv-health',\n // apps/docs and apps/changelog run on their own hosts. Both labels were\n // already blocked at signup by RESERVED_USERNAMES, so handle registration\n // was never exposed - but this list is what governs host semantics, and a\n // label that names a first-party deployment must not be handle-like here\n // either. Keeping the two lists in agreement is what stops a subdomain from\n // being routed as a profile.\n 'docs',\n 'changelog',\n // The developer portal (apps/developer) runs on developer.tabbio.com. The two\n // near-misses are reserved with it: a handle at developers.* or dev.* would\n // read as a first-party developer surface without being one.\n 'developer',\n 'developers',\n 'dev',\n // The developer platform (apps/platform) runs on platform.tabbio.com, and the\n // admin console (apps/admin) on console.tabbio.com. `dashboard` is the\n // near-miss reserved with them: a handle there would read as a first-party\n // control surface without being one.\n 'platform',\n 'console',\n 'dashboard',\n] as const;\n\nconst RESERVED_PUBLIC_SUBDOMAIN_SET = new Set<string>(\n RESERVED_PUBLIC_SUBDOMAINS,\n);\n\nexport type PublicJobSlugKind = 'native' | 'external';\nexport type PublicProfileUrlOwnerKind = 'user' | 'company';\n\nexport interface ParsedPublicJobSlug {\n kind: PublicJobSlugKind;\n id: string;\n catalogJobId: string;\n}\n\nexport interface PublicUserUrlSet {\n hub: string;\n cv: string;\n resumeJson: string;\n displayHandle: string;\n}\n\nexport interface PublicCompanyUrlSet {\n hub: string;\n jobs: string;\n displayHandle: string;\n}\n\nexport type PublicProfileUrlSet = PublicUserUrlSet | PublicCompanyUrlSet;\n\nexport interface PublicJobSlugInput {\n publicSlug?: string | null;\n id: string;\n title: string;\n isExternal?: boolean;\n company?: {\n name?: string | null;\n } | null;\n /**\n * Location, when the record carries one. It is part of the slug because ATS\n * feeds post one role per location under an identical title: nine Mindrift\n * \"Ex-MBB Strategy Consultant\" requisitions across nine countries, five Apt\n * Resources technician roles across five Saudi cities. Each is a real separate\n * opening with its own upstream apply URL, so they must stay separate URLs -\n * but without the location they were separate URLs sharing one slug prefix and\n * one title tag, which is a near-duplicate set rather than nine pages.\n */\n city?: string | null;\n country?: string | null;\n}\n\nfunction normalizeBaseUrl(baseUrl: string | undefined, fallback: string) {\n const clean = typeof baseUrl === 'string' && baseUrl.trim().length > 0 ? baseUrl.trim() : fallback;\n return clean.endsWith('/') ? clean.slice(0, -1) : clean;\n}\n\nfunction getLocalPublicBaseUrl(baseUrl: string | undefined) {\n const normalized = normalizeBaseUrl(baseUrl, DEFAULT_PUBLIC_SITE_URL);\n\n try {\n const parsed = new URL(\n normalized.startsWith('http://') || normalized.startsWith('https://')\n ? normalized\n : `https://${normalized}`,\n );\n const hostname = parsed.hostname.toLowerCase();\n if (\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n hostname === '127.0.0.1' ||\n hostname === '[::1]' ||\n hostname === '::1'\n ) {\n return parsed.origin;\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\nfunction normalizePath(pathname: string) {\n return pathname.startsWith('/') ? pathname : `/${pathname}`;\n}\n\nexport function getPublicRootDomain(value = DEFAULT_PUBLIC_DOMAIN) {\n const clean = normalizeBaseUrl(value, DEFAULT_PUBLIC_DOMAIN)\n .replace(/^https?:\\/\\//, '')\n .split('/')[0]\n .toLowerCase();\n if (!clean) {\n return DEFAULT_PUBLIC_DOMAIN;\n }\n\n try {\n const parsed = new URL(\n clean.includes('://') ? clean : `https://${clean}`,\n );\n // Strip a leading `www.` so profile subdomains are always built on the\n // registrable domain, regardless of whether the configured site URL uses\n // www. Without this, a base of `https://www.tabbio.com` would produce\n // `{handle}.www.tabbio.com` instead of `{handle}.tabbio.com` (and break\n // subdomain handle detection the same way). `www` is a reserved subdomain,\n // so it is never a real profile root.\n return parsed.host.toLowerCase().replace(/^www\\./, '');\n } catch {\n return clean.replace(/^www\\./, '');\n }\n}\n\nexport function normalizePublicHandle(handle: string | null | undefined) {\n return typeof handle === 'string'\n ? handle.trim().replace(/^@+/, '').replace(/_/g, '-').toLowerCase()\n : '';\n}\n\nexport function isPublicHandleLike(handle: string | null | undefined) {\n const normalized = normalizePublicHandle(handle);\n return (\n HANDLE_SEGMENT_REGEX.test(normalized) &&\n !normalized.includes('--') &&\n !isReservedPublicSubdomain(normalized)\n );\n}\n\nexport function isReservedPublicSubdomain(value: string | null | undefined) {\n const normalized = normalizePublicHandle(value);\n return RESERVED_PUBLIC_SUBDOMAIN_SET.has(normalized);\n}\n\nexport function buildCanonicalProfileUrl(handle: string, baseUrl = DEFAULT_PUBLIC_SITE_URL) {\n const normalized = normalizePublicHandle(handle);\n return `${normalizeBaseUrl(baseUrl, DEFAULT_PUBLIC_SITE_URL)}/${encodeURIComponent(normalized)}`;\n}\n\nexport function buildPersonHubUrl(handle: string, baseUrl = DEFAULT_PUBLIC_SITE_URL) {\n return buildCanonicalProfileUrl(handle, baseUrl);\n}\n\nexport function buildPrettyProfileUrl(handle: string, domain = DEFAULT_PUBLIC_DOMAIN) {\n return buildPersonCvUrl(handle, domain);\n}\n\nexport function buildPersonCvUrl(\n handle: string,\n domain = DEFAULT_PUBLIC_DOMAIN,\n locale?: string | null,\n) {\n const normalized = normalizePublicHandle(handle);\n const localPublicBaseUrl = getLocalPublicBaseUrl(domain);\n const normalizedLocale = typeof locale === 'string' ? locale.trim().replace(/^\\/+|\\/+$/g, '') : '';\n if (localPublicBaseUrl) {\n return `${localPublicBaseUrl}/${encodeURIComponent(normalized)}/cv`;\n }\n\n const rootDomain = getPublicRootDomain(domain);\n const base = `https://${normalized}.${rootDomain}`;\n return normalizedLocale ? `${base}/${encodeURIComponent(normalizedLocale)}` : base;\n}\n\n/**\n * Stable public URL for one tailored CV owned by a person handle.\n *\n * The person's root subdomain remains the canonical main WebCV. Tailored CVs\n * live below `/cv/:slug`, while local development keeps the handle in the\n * pathname because wildcard localhost subdomains are not assumed.\n */\nexport function buildPersonTailoredCvUrl(\n handle: string,\n slug: string,\n domain = DEFAULT_PUBLIC_DOMAIN,\n) {\n const normalizedHandle = normalizePublicHandle(handle);\n const normalizedSlug = slug.trim();\n const localPublicBaseUrl = getLocalPublicBaseUrl(domain);\n if (localPublicBaseUrl) {\n return `${localPublicBaseUrl}/${encodeURIComponent(normalizedHandle)}/cv/${encodeURIComponent(normalizedSlug)}`;\n }\n\n return `${buildPersonCvUrl(normalizedHandle, domain)}/cv/${encodeURIComponent(normalizedSlug)}`;\n}\n\nexport interface SplitCvHandle {\n /** The leading subdomain segment, e.g. \"jane\" in \"jane.tabbio.com\". */\n handle: string;\n /** The remaining domain suffix including the leading dot, e.g. \".tabbio.com\". */\n suffix: string;\n}\n\n/**\n * Splits a public CV URL into its handle and domain suffix for two-tone display\n * (handle in the text color, suffix muted). Strips any protocol first and splits\n * at the first dot; a dotless value returns the whole string as the handle.\n */\nexport function splitCvHandle(url: string | null | undefined): SplitCvHandle {\n const clean = (url ?? '').replace(/^https?:\\/\\//, '');\n const dotIdx = clean.indexOf('.');\n if (dotIdx === -1) return { handle: clean, suffix: '' };\n return { handle: clean.slice(0, dotIdx), suffix: clean.slice(dotIdx) };\n}\n\nexport function buildPersonCvLocaleUrl(\n handle: string,\n locale: string,\n domain = DEFAULT_PUBLIC_DOMAIN,\n) {\n return buildPersonCvUrl(handle, domain, locale);\n}\n\nexport function buildCanonicalCvUrl(handle: string, domain = DEFAULT_PUBLIC_DOMAIN) {\n return buildPersonCvUrl(handle, domain);\n}\n\nexport function buildPersonCvPathUrl(handle: string, baseUrl = DEFAULT_PUBLIC_SITE_URL) {\n return `${buildCanonicalProfileUrl(handle, baseUrl)}/cv`;\n}\n\nexport function buildPersonResumeJsonUrl(\n handle: string,\n domain = DEFAULT_PUBLIC_DOMAIN,\n) {\n const normalized = normalizePublicHandle(handle);\n const localPublicBaseUrl = getLocalPublicBaseUrl(domain);\n if (localPublicBaseUrl) {\n return `${localPublicBaseUrl}/${encodeURIComponent(normalized)}/resume.json`;\n }\n\n return `${buildPersonCvUrl(handle, domain)}/resume.json`;\n}\n\nexport function buildPersonResumeJsonPathUrl(\n handle: string,\n baseUrl = DEFAULT_PUBLIC_SITE_URL,\n) {\n return `${buildCanonicalProfileUrl(handle, baseUrl)}/resume.json`;\n}\n\nexport function buildPersonPrivateCvShareUrl(\n handle: string,\n token: string,\n domain = DEFAULT_PUBLIC_DOMAIN,\n) {\n const normalized = normalizePublicHandle(handle);\n const localPublicBaseUrl = getLocalPublicBaseUrl(domain);\n if (localPublicBaseUrl) {\n return `${localPublicBaseUrl}/${encodeURIComponent(normalized)}/s/${encodeURIComponent(token)}`;\n }\n\n return `${buildPersonCvUrl(handle, domain)}/s/${encodeURIComponent(token)}`;\n}\n\nexport function buildLegacyCvShareUrl(\n token: string,\n appUrl = DEFAULT_APP_SITE_URL,\n) {\n return new URL(\n `/cv-share/${encodeURIComponent(token)}`,\n normalizeBaseUrl(appUrl, DEFAULT_APP_SITE_URL),\n ).toString();\n}\n\nexport function buildPublicProfileUrls(\n ownerKind: 'user',\n handle: string,\n options?: { publicSiteUrl?: string; publicDomain?: string },\n): PublicUserUrlSet;\nexport function buildPublicProfileUrls(\n ownerKind: 'company',\n handle: string,\n options?: { publicSiteUrl?: string; publicDomain?: string },\n): PublicCompanyUrlSet;\nexport function buildPublicProfileUrls(\n ownerKind: PublicProfileUrlOwnerKind,\n handle: string,\n options: { publicSiteUrl?: string; publicDomain?: string } = {},\n): PublicProfileUrlSet {\n const normalized = normalizePublicHandle(handle);\n const publicSiteUrl = options.publicSiteUrl ?? DEFAULT_PUBLIC_SITE_URL;\n const publicDomain = options.publicDomain ?? publicSiteUrl;\n const hub = buildCanonicalProfileUrl(normalized, publicSiteUrl);\n\n if (ownerKind === 'user') {\n const cv = buildPersonCvUrl(normalized, publicDomain);\n return {\n hub,\n cv,\n resumeJson: buildPersonResumeJsonUrl(normalized, publicDomain),\n displayHandle: normalized,\n };\n }\n\n return {\n hub,\n jobs: `${hub.replace(/\\/$/, '')}/jobs`,\n displayHandle: normalized,\n };\n}\n\nexport function getPublicHandleFromHostname(\n hostname: string | null | undefined,\n rootDomains: string | string[] = DEFAULT_PUBLIC_DOMAIN,\n) {\n const host = (hostname ?? '').split(':')[0]?.toLowerCase() ?? '';\n if (!host) return null;\n\n const domains = (Array.isArray(rootDomains) ? rootDomains : [rootDomains])\n .map(getPublicRootDomain)\n .filter(Boolean)\n .sort((a, b) => b.length - a.length);\n\n for (const rootDomain of domains) {\n if (host === rootDomain || !host.endsWith(`.${rootDomain}`)) {\n continue;\n }\n\n const subdomain = host.slice(0, -(rootDomain.length + 1));\n if (!subdomain || subdomain.includes('.')) {\n continue;\n }\n\n if (isPublicHandleLike(subdomain)) {\n return normalizePublicHandle(subdomain);\n }\n }\n\n return null;\n}\n\nexport function buildAppJobUrl(\n catalogJobId: string,\n baseUrl = DEFAULT_APP_SITE_URL,\n returnTo?: string | null,\n) {\n const url = new URL(\n `/jobs/${encodeURIComponent(catalogJobId)}`,\n normalizeBaseUrl(baseUrl, DEFAULT_APP_SITE_URL),\n );\n if (returnTo) {\n url.searchParams.set('returnTo', returnTo);\n }\n return url.toString();\n}\n\n// \u2500\u2500\u2500 Catalog job route ids \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Catalog job ids are colon-form (`native:<id>` / `external:<id>`), but a\n// colon breaks as a URL path segment, so routes, post-auth targets, and the\n// apply handoff carry the dash form (`native-<id>` / `external-<id>`). These\n// helpers are the single owner of that conversion: apps must not hand-roll\n// `replace(':', '-')`.\n\nconst CATALOG_JOB_ID_FORMS = /^(native|external)[:-](.*)$/;\n\n/** Strict dash-form route id as it appears in URLs and `jobs:` targets. */\nexport const CATALOG_JOB_ROUTE_ID_PATTERN = /^(native|external)-[A-Za-z0-9_-]+$/;\n\n/** Catalog id in either form \u2192 URL-safe dash form (`native-<id>`). */\nexport function toCatalogJobRouteId(catalogJobId: string) {\n const match = catalogJobId.match(CATALOG_JOB_ID_FORMS);\n return match ? `${match[1]}-${match[2]}` : catalogJobId;\n}\n\n/** Route id in either form \u2192 colon-form catalog id (`native:<id>`). */\nexport function fromCatalogJobRouteId(routeId: string) {\n const match = routeId.match(CATALOG_JOB_ID_FORMS);\n return match ? `${match[1]}:${match[2]}` : routeId;\n}\n\n/**\n * Public \"Apply\" entry for a catalog job. Points at the app's unguarded\n * /jobs-handoff shim: which forks on auth state (login \u2192 onboarding \u2192 job)\n * and survives the sign-in navigator remount: NOT at /jobs/<id>, which is\n * only reliably reachable with an already-open session.\n */\nexport function buildAppJobApplyUrl(\n catalogJobId: string,\n baseUrl = DEFAULT_APP_SITE_URL,\n) {\n const routeId = toCatalogJobRouteId(catalogJobId);\n return new URL(\n `/jobs-handoff?id=${encodeURIComponent(routeId)}`,\n normalizeBaseUrl(baseUrl, DEFAULT_APP_SITE_URL),\n ).toString();\n}\n\nexport function buildCanonicalJobUrl(\n slug: string,\n baseUrl = DEFAULT_PUBLIC_SITE_URL,\n locale = 'en',\n) {\n // The public jobs board is locale-prefixed (/en/jobs, /ar/jobs); bare /jobs\n // 308s to the default locale, so canonicals must carry the prefix.\n return `${normalizeBaseUrl(baseUrl, DEFAULT_PUBLIC_SITE_URL)}/${locale}/jobs/${encodeURIComponent(slug)}`;\n}\n\nfunction slugifyPublicText(value: string) {\n return value\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .replace(/-{2,}/g, '-')\n .slice(0, 80)\n .replace(/-+$/g, '');\n}\n\nfunction getJobSlugParts(job: PublicJobSlugInput) {\n const nativePrefix = 'native:';\n const externalPrefix = 'external:';\n if (job.id.startsWith(nativePrefix)) {\n return { kind: 'native' as const, id: job.id.slice(nativePrefix.length) };\n }\n if (job.id.startsWith(externalPrefix)) {\n return { kind: 'external' as const, id: job.id.slice(externalPrefix.length) };\n }\n return { kind: job.isExternal ? ('external' as const) : ('native' as const), id: job.id };\n}\n\nexport function buildPublicJobSlug(job: PublicJobSlugInput) {\n const { kind, id } = getJobSlugParts(job);\n const suffix = '--' + (kind === 'native' ? 'n' : 'e') + '_' + encodeURIComponent(id);\n if (job.publicSlug?.endsWith(suffix) && /^[a-z0-9][a-z0-9-]*--[ne]_[a-zA-Z0-9_%.-]+$/.test(job.publicSlug)) {\n return job.publicSlug;\n }\n const companyName = job.company?.name?.trim();\n // City first, falling back to country: \"at Mindrift Qatar\" distinguishes the\n // nine identically-titled requisitions, and a bare country is still a\n // differentiator when the feed gives no city.\n const place = job.city?.trim() || job.country?.trim() || '';\n const withCompany = companyName ? `${job.title} at ${companyName}` : job.title;\n const base =\n slugifyPublicText(place ? `${withCompany} ${place}` : withCompany) || 'job';\n const suffixKind = kind === 'native' ? 'n' : 'e';\n return `${base}--${suffixKind}_${encodeURIComponent(id)}`;\n}\n\nexport function parsePublicJobSlug(slug: string): ParsedPublicJobSlug | null {\n const match = slug.match(/--([ne])_([^/]+)$/);\n if (!match) {\n return null;\n }\n\n const kind: PublicJobSlugKind = match[1] === 'n' ? 'native' : 'external';\n const id = decodeURIComponent(match[2] ?? '').trim();\n if (!id) {\n return null;\n }\n\n return {\n kind,\n id,\n catalogJobId: `${kind}:${id}`,\n };\n}\n\nexport function buildPublicPath(pathname: string, baseUrl = DEFAULT_PUBLIC_SITE_URL) {\n return `${normalizeBaseUrl(baseUrl, DEFAULT_PUBLIC_SITE_URL)}${normalizePath(pathname)}`;\n}\n", "/**\n * Field readers the card builders share (`chat-card-kinds.ts`): defensive\n * access to unknown tool results, job links, match scores, schedules and\n * short relative times. Pure.\n */\nimport { relativeTime } from './io';\n\nexport type Rec = Record<string, unknown>;\n\nexport function isRec(value: unknown): value is Rec {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function rec(value: unknown): Rec | undefined {\n return isRec(value) ? value : undefined;\n}\n\nexport function str(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\nexport function num(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\n/** The records of a list result: the value itself when it is an array, else the first array under `keys`. */\nexport function listOf(result: unknown, ...keys: string[]): Rec[] {\n if (Array.isArray(result)) return result.filter(isRec);\n const record = rec(result);\n if (!record) return [];\n for (const key of keys) {\n const value = record[key];\n if (Array.isArray(value)) return value.filter(isRec);\n }\n return [];\n}\n\n/** An http(s) URL, else undefined (never a `javascript:` or relative link). */\nexport function httpUrl(value: unknown): string | undefined {\n const text = str(value);\n // eslint-disable-next-line no-control-regex\n return text && !/[\\u0000-\\u001f\\u007f-\\u009f]/.test(text) && /^https?:\\/\\/\\S+$/i.test(text) ? text : undefined;\n}\n\n/**\n * The marketing site for an app URL: `app.tabbio.com` \u2192 `tabbio.com`,\n * localhost \u2192 the local web app on 3000.\n */\nexport function publicSiteUrl(appUrl: string): string {\n try {\n const url = new URL(appUrl);\n if (['localhost', '127.0.0.1', '[::1]', '::1'].includes(url.hostname)) return 'http://localhost:3000';\n const host = url.hostname.startsWith('app.') ? url.hostname.slice(4) : url.hostname;\n return `${url.protocol}//${host}${url.port ? `:${url.port}` : ''}`;\n } catch {\n return 'https://tabbio.com';\n }\n}\n\nexport function companyName(job: Rec): string | undefined {\n const company = job.company;\n return (isRec(company) ? str(company.name) : str(company)) ?? str(job.companyName);\n}\n\n/**\n * Where a job row links: the employer's apply page (`applicationUrl`,\n * `applyUrl`, the source's direct apply or listing URL), else the public\n * job page when the job has a slug. Undefined when there is none.\n */\nexport function jobLink(job: Rec, siteUrl: string): string | undefined {\n const source = rec(job.sourceInfo);\n const direct =\n httpUrl(job.applicationUrl) ?? httpUrl(job.applyUrl) ?? httpUrl(source?.directApplyUrl) ?? httpUrl(source?.sourceUrl);\n if (direct) return direct;\n const slug = str(job.publicSlug) ?? str(job.slug);\n if (slug) return `${siteUrl}/en/jobs/${encodeURIComponent(slug)}`;\n return httpUrl(job.canonicalUrl);\n}\n\n/** `74% match` from a 0..1 (or 0..100) score. */\nexport function matchLabel(score: unknown): string | undefined {\n const value = num(score);\n if (value === undefined || value <= 0) return undefined;\n return `${Math.round(value <= 1 ? value * 100 : value)}% match`;\n}\n\n/** `3d ago` for a past date string, `in 5h` for a future one. */\nexport function when(value: unknown, now: number): string | undefined {\n const text = typeof value === 'string' ? value : value instanceof Date ? value.toISOString() : undefined;\n if (!text) return undefined;\n const date = new Date(text);\n return Number.isNaN(date.getTime()) ? undefined : relativeTime(date, now);\n}\n\nconst DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n\n/** `daily 09:00`, `weekly Mon 09:00`, `hourly`, else the cron expression itself. */\nexport function scheduleLabel(cron: unknown): string | undefined {\n const text = str(cron);\n if (!text) return undefined;\n const parts = text.split(/\\s+/);\n if (parts.length !== 5) return text;\n const [minute, hour, dom, month, dow] = parts as [string, string, string, string, string];\n const time = /^\\d+$/.test(minute) && /^\\d+$/.test(hour) ? `${hour.padStart(2, '0')}:${minute.padStart(2, '0')}` : null;\n if (/^\\d+$/.test(minute) && hour === '*' && dom === '*' && month === '*' && dow === '*') return 'hourly';\n if (time && dom === '*' && month === '*' && dow === '*') return `daily ${time}`;\n if (time && dom === '*' && month === '*' && /^[0-6]$/.test(dow)) return `weekly ${DAYS[Number(dow)]} ${time}`;\n if (time && dom === '*' && month === '*' && dow === '1-5') return `weekdays ${time}`;\n if (time && /^\\d+$/.test(dom) && month === '*' && dow === '*') return `monthly on day ${dom} ${time}`;\n return text;\n}\n\n/** One line of a longer text, collapsed and cut to `max` characters. */\nexport function excerpt(value: unknown, max = 320): string | undefined {\n const text = str(value);\n if (!text) return undefined;\n const flat = text.replace(/\\s+/g, ' ');\n return flat.length > max ? `${flat.slice(0, max - 1).trimEnd()}\u2026` : flat;\n}\n\n/** `camelCase_key` \u2192 `Camel case key`. */\nexport function humanKey(key: string): string {\n const words = key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .trim()\n .toLowerCase();\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n/** A short, readable value for a generic row: arrays as `n items`, never JSON. */\nexport function scalarLabel(value: unknown): string | undefined {\n if (value === null || value === undefined) return undefined;\n if (typeof value === 'boolean') return value ? 'yes' : 'no';\n if (typeof value === 'number') return Number.isFinite(value) ? String(value) : undefined;\n if (typeof value === 'string') return value.trim() ? value.replace(/\\s+/g, ' ').trim() : undefined;\n if (Array.isArray(value)) return `${value.length} ${value.length === 1 ? 'item' : 'items'}`;\n if (isRec(value)) {\n const name = str(value.title) ?? str(value.name) ?? str(value.label);\n if (name) return name;\n const n = Object.keys(value).length;\n return n ? `${n} ${n === 1 ? 'field' : 'fields'}` : undefined;\n }\n return undefined;\n}\n", "/**\n * One builder per card kind: tool result in, `ChatCard` out (or null when\n * there is nothing worth a card). Field names follow the app's cards in\n * `apps/mobile/src/components/assistant-ui/tool-cards/*` and the real\n * payloads captured from the API. Pure.\n */\nimport type { CardLink, CardRow, ChatCard } from './chat-cards';\nimport {\n type Rec,\n companyName,\n excerpt,\n httpUrl,\n humanKey,\n isRec,\n jobLink,\n listOf,\n matchLabel,\n num,\n rec,\n scalarLabel,\n scheduleLabel,\n str,\n when,\n} from './chat-card-fields';\n\nexport type BuildOpts = { siteUrl: string; now: number };\n\n/** Rows a list card shows; the rest is summarised as `+N more`. */\nexport const MAX_CARD_ROWS = 8;\n\nexport function card(kind: ChatCard['kind'], title: string, rows: CardRow[], extra: Partial<ChatCard> = {}): ChatCard {\n const links = rows.flatMap((row) => (row.link ? [row.link] : []));\n return { kind, title, rows, links, ...extra };\n}\n\nexport function counted(noun: string, shown: number, total: number): string {\n return total > shown ? `${noun} \u00B7 ${shown} of ${total}` : `${noun} \u00B7 ${total}`;\n}\n\nfunction jobRow(job: Rec, n: number, opts: BuildOpts): CardRow {\n const title = str(job.title) ?? 'Untitled role';\n const url = jobLink(job, opts.siteUrl);\n const id = str(job.id);\n const meta = [\n companyName(job),\n str(job.location),\n str(job.workMode),\n str(job.type),\n matchLabel(job.matchScore),\n job.applied === true ? 'applied' : undefined,\n when(job.postedAt, opts.now),\n url ? undefined : 'no link',\n ].filter((part): part is string => Boolean(part));\n const link: CardLink | undefined = url ? { n, label: title, url, ...(id ? { jobId: id, jobTitle: title } : {}) } : undefined;\n return { n, title, meta, ...(link ? { link } : {}), ...(id ? { job: { id, title } } : {}) };\n}\n\nexport function jobListCard(result: unknown, opts: BuildOpts): ChatCard | null {\n const jobs = listOf(result, 'jobs', 'items', 'savedJobs');\n if (!jobs.length) return null;\n const total = num(rec(result)?.total) ?? jobs.length;\n const rows = jobs.slice(0, MAX_CARD_ROWS).map((job, i) => jobRow(rec(job.job) ?? job, i + 1, opts));\n return card('job-list', counted('Jobs', rows.length, Math.max(total, jobs.length)), rows, {\n hint: '/open <n> opens a job \u00B7 /apply <n> prepares an application',\n ...(jobs.length > rows.length ? { more: jobs.length - rows.length } : {}),\n });\n}\n\nexport function jobDetailCard(result: unknown, opts: BuildOpts): ChatCard | null {\n const job = rec(rec(result)?.job) ?? rec(result);\n if (!job || !str(job.title)) return null;\n const row = jobRow(job, 1, opts);\n const status = str(job.status);\n const body = excerpt(job.summary ?? job.description);\n return card('job-detail', 'Job', [\n { ...row, meta: [...(row.meta ?? []), ...(status && status !== 'active' ? [status] : [])], ...(body ? { body } : {}) },\n ], { hint: row.link ? '/open 1 opens the job \u00B7 /apply 1 prepares an application' : '/apply 1 prepares an application' });\n}\n\nexport function labelRow(label: string, value: string | undefined, body?: string): CardRow[] {\n if (!value && !body) return [];\n return [{ label, title: value ?? '', ...(body ? { body } : {}) }];\n}\n\nexport function applicationPreviewCard(result: unknown, opts: BuildOpts): ChatCard | null {\n const r = rec(result);\n if (!r) return null;\n const job = rec(r.job) ?? {};\n const title = str(job.title) ?? 'This job';\n const existing = rec(r.existingApplication);\n const redirect = r.redirectRequired === true;\n const ready = r.readyToSubmit === true;\n const url = httpUrl(r.redirectUrl) ?? httpUrl(existing?.redirectUrl) ?? httpUrl(existing?.applicationUrl) ?? jobLink(job, opts.siteUrl);\n const id = str(job.id);\n const link: CardLink | undefined = url\n ? { n: 1, label: redirect ? 'Apply on the employer site' : title, url, ...(id ? { jobId: id, jobTitle: title } : {}) }\n : undefined;\n const status = str(existing?.status)\n ? `already ${str(existing?.status)}`\n : ready\n ? 'ready to submit'\n : redirect\n ? 'continues on the employer site'\n : 'needs a few details';\n const notes = Array.isArray(r.notes) ? r.notes.filter((note): note is string => typeof note === 'string').join(' ') : str(r.notes);\n const rows: CardRow[] = [\n {\n n: 1,\n title,\n meta: [companyName(job), str(job.location)].filter((part): part is string => Boolean(part)),\n ...(link ? { link } : {}),\n ...(id ? { job: { id, title } } : {}),\n },\n ...labelRow('Status', status),\n ...labelRow('Ready to submit', ready ? 'yes' : 'no'),\n ...labelRow('CV', str(rec(r.cv)?.title) ?? (r.cv === null ? 'none yet' : undefined)),\n ...labelRow('Cover letter', undefined, excerpt(r.coverLetter, 480)),\n ...labelRow('Note', excerpt(notes, 200)),\n ];\n const hint = [\n link ? `/open 1 ${redirect ? 'applies on the employer site' : 'opens the job'}` : null,\n ready ? \"reply 'submit' to send it (you approve it first)\" : \"/apply <n> or reply 'submit' to continue\",\n ].filter(Boolean);\n return card('application-preview', 'Application', rows, { hint: hint.join(' \u00B7 ') });\n}\n\nexport function applicationConfirmCard(result: unknown, opts: BuildOpts): ChatCard | null {\n const r = rec(result);\n if (!r) return null;\n const application = rec(r.application) ?? r;\n const job = rec(r.job) ?? rec(application.job) ?? {};\n const title = str(job.title) ?? str(application.jobTitle) ?? 'Application';\n const url = httpUrl(r.redirectUrl) ?? httpUrl(application.redirectUrl) ?? httpUrl(application.applicationUrl);\n const outcome = str(r.outcome)?.replace(/_/g, ' ');\n const rows: CardRow[] = [\n {\n n: 1,\n title,\n meta: [companyName(job) ?? str(rec(r.company)?.name), when(application.submittedAt ?? application.appliedAt, opts.now)].filter(\n (part): part is string => Boolean(part),\n ),\n ...(url ? { link: { n: 1, label: title, url } } : {}),\n },\n ...labelRow('Outcome', outcome),\n ...labelRow('Status', str(application.status)),\n ...labelRow('Message', excerpt(r.message, 200)),\n ];\n return card('application-confirm', 'Application', rows, url ? { hint: '/open 1 finishes it on the employer site' } : {});\n}\n\nexport function applicationListCard(result: unknown, opts: BuildOpts): ChatCard | null {\n const apps = listOf(result, 'applications', 'items', 'history', 'intents');\n if (!apps.length) return null;\n const rows = apps.slice(0, MAX_CARD_ROWS).map((app, i): CardRow => {\n const job = rec(app.job) ?? {};\n const title = str(job.title) ?? str(app.jobTitle) ?? str(app.title) ?? 'Application';\n const url = httpUrl(app.redirectUrl) ?? httpUrl(app.applicationUrl) ?? jobLink(job, opts.siteUrl);\n const meta = [\n companyName(job) ?? str(rec(app.company)?.name),\n str(app.status)?.replace(/_/g, ' '),\n when(app.updatedAt ?? app.submittedAt ?? app.appliedAt ?? app.preparedAt, opts.now),\n ].filter((part): part is string => Boolean(part));\n return { n: i + 1, title, meta, ...(url ? { link: { n: i + 1, label: title, url } } : {}) };\n });\n return card('application-list', counted('Applications', rows.length, apps.length), rows, {\n ...(apps.length > rows.length ? { more: apps.length - rows.length } : {}),\n ...(rows.some((row) => row.link) ? { hint: '/open <n> opens an application' } : {}),\n });\n}\n\nexport function skillListCard(result: unknown): ChatCard | null {\n const skills = listOf(result, 'skills', 'items');\n if (!skills.length) return null;\n const total = num(rec(result)?.total) ?? skills.length;\n const rows = skills.slice(0, MAX_CARD_ROWS).flatMap((skill, i): CardRow[] => {\n const id = str(skill.skillId) ?? str(skill.id);\n if (!id) return [];\n const command = `/${id.replace(/^\\/+/, '').toLowerCase()}`;\n const tier = str(skill.tier);\n const meta = [str(skill.name), tier && tier !== 'free' ? tier : undefined].filter((part): part is string => Boolean(part));\n const body = excerpt(skill.description, 160);\n return [{ n: i + 1, title: command, meta, ...(body ? { body, bodyLines: 1 } : {}), action: command }];\n });\n if (!rows.length) return null;\n return card('skill-list', counted('Skills', rows.length, Math.max(total, skills.length)), rows, {\n hint: 'Type /<skill-id> to run a skill',\n ...(skills.length > rows.length ? { more: skills.length - rows.length } : {}),\n });\n}\n\nfunction automationMeta(item: Rec, now: number): string[] {\n const last = when(item.lastRunAt, now);\n const lastStatus = str(item.lastRunStatus)?.replace(/_/g, ' ');\n const next = when(item.nextRunAt, now);\n return [\n str(item.status)?.replace(/_/g, ' '),\n scheduleLabel(item.cron),\n last ? `last run ${last}${lastStatus ? ` (${lastStatus})` : ''}` : 'never run',\n next ? `next ${next}` : undefined,\n ].filter((part): part is string => Boolean(part));\n}\n\nexport function automationListCard(result: unknown, opts: BuildOpts, runs: boolean): ChatCard | null {\n const items = listOf(result, runs ? 'runs' : 'automations', 'items');\n if (!items.length) return null;\n const rows = items.slice(0, MAX_CARD_ROWS).map((item, i): CardRow => {\n if (!runs) return { n: i + 1, title: str(item.name) ?? 'Automation', meta: automationMeta(item, opts.now) };\n const started = when(item.startTime ?? item.scheduledTime ?? item.createdAt, opts.now);\n const meta = [str(item.triggerType), started, excerpt(item.errorSummary, 80)].filter((part): part is string => Boolean(part));\n return { n: i + 1, title: (str(item.status) ?? 'run').replace(/_/g, ' '), meta };\n });\n return card('automation-list', counted(runs ? 'Runs' : 'Automations', rows.length, items.length), rows, {\n ...(items.length > rows.length ? { more: items.length - rows.length } : {}),\n });\n}\n\nexport function automationDetailCard(result: unknown, opts: BuildOpts, run: boolean): ChatCard | null {\n const r = rec(result);\n if (!r) return null;\n const automation = rec(r.automation) ?? (run ? undefined : r);\n const runRec = rec(r.run) ?? (run ? r : undefined);\n const name = str(automation?.name) ?? str(r.name) ?? str(rec(r.plan)?.name);\n if (!name && !runRec) return null;\n const rows: CardRow[] = [\n { title: name ?? 'Automation', meta: automation ? automationMeta(automation, opts.now) : [] },\n ...labelRow('Run', str(runRec?.status)?.replace(/_/g, ' ')),\n ...labelRow('Started', when(runRec?.startTime ?? runRec?.createdAt, opts.now)),\n ...labelRow('Problem', excerpt(runRec?.errorSummary ?? r.message, 200)),\n ];\n return card(run ? 'automation-run' : 'automation-detail', run ? 'Automation run' : 'Automation', rows);\n}\n\nexport function profileSummaryCard(result: unknown): ChatCard | null {\n const r = rec(result);\n if (!r) return null;\n const p = rec(r.profile) ?? r;\n const count = (value: unknown) => (Array.isArray(value) && value.length ? String(value.length) : undefined);\n const experiences = listOf(r, 'experiences', 'experience');\n const latest = experiences[0];\n const latestRole = latest ? [str(latest.title), str(latest.company)].filter(Boolean).join(' at ') : undefined;\n const rows: CardRow[] = [\n { title: str(p.name) ?? 'Your profile', meta: [str(p.headline) ?? str(p.title), str(p.location)].filter((x): x is string => Boolean(x)) },\n ...labelRow('Experience', experiences.length ? `${experiences.length} ${experiences.length === 1 ? 'role' : 'roles'}${latestRole ? `, latest ${latestRole}` : ''}` : undefined),\n ...labelRow('Education', count(r.education ?? r.educations)),\n ...labelRow('Certifications', count(r.certifications)),\n ...labelRow('Projects', count(r.projects)),\n ...labelRow('Email', str(p.contactEmail) ?? str(p.email)),\n ...labelRow('Summary', undefined, excerpt(p.summary ?? p.about ?? p.bio, 240)),\n ];\n let n = 0;\n for (const key of ['website', 'linkedin', 'github', 'behance', 'dribbble']) {\n const url = httpUrl(p[key]);\n if (!url) continue;\n n += 1;\n rows.push({ n, label: humanKey(key), title: url, link: { n, label: humanKey(key), url } });\n }\n return card('profile-summary', 'Profile', rows, n ? { hint: '/open <n> opens a link' } : {});\n}\n\nexport function companyListCard(result: unknown): ChatCard | null {\n const companies = listOf(result, 'companies', 'items');\n if (!companies.length) return null;\n const rows = companies.slice(0, MAX_CARD_ROWS).map((company, i): CardRow => {\n const title = str(company.name) ?? 'Company';\n const url = httpUrl(company.website);\n const meta = [str(company.industry), str(company.location), str(company.employeeCount), str(company.id)].filter(\n (part): part is string => Boolean(part),\n );\n return { n: i + 1, title, meta, ...(url ? { link: { n: i + 1, label: title, url } } : {}) };\n });\n return card('company-list', counted('Companies', rows.length, companies.length), rows, {\n ...(companies.length > rows.length ? { more: companies.length - rows.length } : {}),\n });\n}\n\n/** Keys a generic card never shows (internal plumbing and noise). */\nconst GENERIC_SKIP = new Set(['success', 'ok', 'userId', 'display', 'message', 'decision', 'featureKey']);\n\n/** Up to eight `label value` rows; arrays as `n items`, never raw JSON. Null when nothing is worth showing. */\nexport function genericCard(result: unknown, title: string): ChatCard | null {\n if (typeof result === 'string') {\n const body = excerpt(result, 480);\n return body ? card('generic', title, [{ title: '', body }]) : null;\n }\n const list = Array.isArray(result) ? result.filter(isRec) : [];\n if (list.length) {\n const rows = list.slice(0, MAX_CARD_ROWS).map((item, i): CardRow => ({\n n: i + 1,\n title: str(item.title) ?? str(item.name) ?? str(item.label) ?? str(item.id) ?? `Item ${i + 1}`,\n meta: [str(item.status), str(item.type), str(item.id) !== str(item.title) ? str(item.id) : undefined].filter(\n (part): part is string => Boolean(part),\n ),\n }));\n return card('generic', counted(title, rows.length, list.length), rows, list.length > rows.length ? { more: list.length - rows.length } : {});\n }\n const r = rec(result);\n if (!r) return null;\n const rows = Object.entries(r)\n .filter(([key]) => !GENERIC_SKIP.has(key))\n .flatMap(([key, value]): CardRow[] => {\n const text = scalarLabel(value);\n return text ? [{ label: humanKey(key), title: text }] : [];\n });\n if (!rows.length) return null;\n return card('generic', title, rows.slice(0, MAX_CARD_ROWS), rows.length > MAX_CARD_ROWS ? { more: rows.length - MAX_CARD_ROWS } : {});\n}\n", "/**\n * CV cards: the list (`cvList`), one CV, an export, a share link or access\n * invite, and publishing. Pure; see `chat-card-kinds.ts` for the others.\n */\nimport type { CardRow, ChatCard } from './chat-cards';\nimport { buildPersonCvUrl } from '@tabbio/utils/public-url';\nimport { type Rec, excerpt, httpUrl, isRec, listOf, rec, str, when } from './chat-card-fields';\nimport { type BuildOpts, MAX_CARD_ROWS, card, counted } from './chat-card-kinds';\n\nexport function cvListCard(result: unknown, opts: BuildOpts): ChatCard | null {\n const r = rec(result);\n const cvs = listOf(result, 'cvs');\n const main = rec(r?.mainCv);\n if (!cvs.length && !main) return null;\n const defaultId = str(r?.defaultCvId) ?? str(main?.id) ?? 'master';\n const all: Rec[] = [...(main ? [main] : []), ...cvs];\n const rows = all.slice(0, MAX_CARD_ROWS).map((cv, i): CardRow => {\n const id = str(cv.id) ?? 'master';\n const isProfile = cv === main;\n const meta = [\n id === defaultId ? 'main' : undefined,\n isProfile ? 'profile CV' : undefined,\n when(cv.updatedAt, opts.now) ? `updated ${when(cv.updatedAt, opts.now)}` : undefined,\n cv.isPublic === true ? 'public' : undefined,\n id,\n ].filter((part): part is string => Boolean(part));\n return { n: i + 1, title: str(cv.title) ?? 'Untitled CV', meta, action: `/download ${id}` };\n });\n return card('cv-list', counted('CVs', rows.length, all.length), rows, {\n hint: '/download <id> saves a PDF to ./tabbio-artifacts',\n ...(all.length > rows.length ? { more: all.length - rows.length } : {}),\n });\n}\n\nexport function cvDetailCard(result: unknown, opts: BuildOpts): ChatCard | null {\n const r = rec(rec(result)?.cv) ?? rec(result);\n if (!r) return null;\n const id = str(r.id) ?? str(r.cvId);\n const title = str(r.displayTitle) ?? str(r.title) ?? str(r.targetLabel);\n if (!id && !title) return null;\n const target = rec(r.targetJob);\n const meta = [\n target ? [str(target.title), str(target.companyName)].filter(Boolean).join(' at ') || undefined : undefined,\n r.isPublic === true ? 'public' : undefined,\n when(r.updatedAt, opts.now) ? `updated ${when(r.updatedAt, opts.now)}` : undefined,\n id,\n ].filter((part): part is string => Boolean(part));\n const body = excerpt(r.summary, 240);\n return card('cv-detail', 'CV', [\n { n: 1, title: title ?? 'CV', meta, ...(body ? { body } : {}), ...(id ? { action: `/download ${id}` } : {}) },\n ]);\n}\n\nexport function cvExportCard(result: unknown): ChatCard | null {\n const r = rec(result);\n if (!r || !Array.isArray(r.formats)) return null;\n const id = str(r.cvId) ?? 'master';\n const formats = r.formats.filter(isRec).map((f) => {\n const label = str(f.label) ?? str(f.format)?.toUpperCase() ?? '';\n return f.locked === true ? `${label} (paid plans)` : label;\n });\n return card('cv-export', 'CV export', [\n {\n n: 1,\n title: str(r.cvTitle) ?? 'My CV',\n meta: [r.isTailored === true ? 'tailored CV' : 'main CV', ...formats.filter(Boolean)],\n action: `/download ${id}`,\n },\n ]);\n}\n\nexport function cvShareCard(result: unknown, opts: BuildOpts, grant: boolean): ChatCard | null {\n const r = rec(result);\n if (!r) return null;\n const url = httpUrl(grant ? r.inviteUrl : r.shareUrl) ?? httpUrl(r.shareUrl) ?? httpUrl(r.inviteUrl);\n const title = str(r.cvTitle) ?? 'Your CV';\n const permissions = Array.isArray(r.permissions) ? r.permissions.filter((p): p is string => typeof p === 'string') : [];\n const expires = when(r.expiresAt, opts.now);\n const meta = [\n r.isTailored === true ? 'tailored CV' : 'main CV',\n grant ? str(r.granteeEmail) : undefined,\n grant ? str(r.role) : undefined,\n grant ? str(r.status) : undefined,\n permissions.length ? permissions.join(', ') : undefined,\n r.allowDownload === true ? 'downloads allowed' : undefined,\n grant ? undefined : expires ? `expires ${expires}` : 'no expiry',\n ].filter((part): part is string => Boolean(part));\n const row: CardRow = { n: 1, title, meta, ...(url ? { link: { n: 1, label: grant ? 'Invite link' : 'Share link', url } } : {}) };\n return card('cv-share', grant ? 'CV access invite' : 'CV share link', [row], url ? { hint: '/open 1 opens the link' } : {});\n}\n\nexport function cvPublishCard(result: unknown, opts: BuildOpts, published: boolean): ChatCard | null {\n const r = rec(result);\n if (!r) return null;\n const handle = str(r.username) ?? str(r.handle);\n const url = published ? (handle ? buildPersonCvUrl(handle, opts.siteUrl) : httpUrl(r.publicUrl)) : undefined;\n const title = str(r.title) ?? 'CV';\n const meta = [published ? 'public' : 'private', str(r.id)].filter((part): part is string => Boolean(part));\n const row: CardRow = { n: 1, title, meta, ...(url ? { link: { n: 1, label: title, url } } : {}) };\n return card('cv-publish', published ? 'Published CV' : 'CV unpublished', [row], url ? { hint: '/open 1 opens the public CV' } : {});\n}\n", "/**\n * Terminal cards for tool results (package Y implements; package X wires the\n * slash commands that act on them). Pure: no I/O, no Ink.\n *\n * A `ChatCard` is what the transcript prints under a tool row when the app\n * would show a card: numbered rows the user can act on with `/open <n>`,\n * `/apply <n>` or `/download <id>`. The builders live in\n * `chat-card-kinds.ts` and `chat-card-cv.ts`.\n */\nimport type { ToolEventPayload } from './chat';\nimport { isArtifactTool, isResearchTool } from './chat-artifacts';\nimport { cvDetailCard, cvExportCard, cvListCard, cvPublishCard, cvShareCard } from './chat-card-cv';\nimport { isRec, publicSiteUrl } from './chat-card-fields';\nimport {\n type BuildOpts,\n applicationConfirmCard,\n applicationListCard,\n applicationPreviewCard,\n automationDetailCard,\n automationListCard,\n companyListCard,\n genericCard,\n jobDetailCard,\n jobListCard,\n profileSummaryCard,\n skillListCard,\n} from './chat-card-kinds';\n\nexport type CardKind =\n | 'job-list'\n | 'job-detail'\n | 'application-preview'\n | 'application-confirm'\n | 'application-list'\n | 'cv-list'\n | 'cv-detail'\n | 'cv-export'\n | 'cv-share'\n | 'cv-publish'\n | 'skill-list'\n | 'automation-list'\n | 'automation-detail'\n | 'automation-run'\n | 'profile-summary'\n | 'company-list'\n | 'generic';\n\nexport type CardLink = {\n /** 1-based number shown in the row; `/open <n>` uses it. */\n n: number;\n label: string;\n url: string;\n /** For `/apply <n>`: the catalog job id and title. */\n jobId?: string;\n jobTitle?: string;\n};\n\nexport type CardRow = {\n /** Number shown at the start of the row when the card is numbered. */\n n?: number;\n title: string;\n /** A dim key before the title, for detail rows (`Status ready to submit`). */\n label?: string;\n /** Short dim details after the title (company, location, status ...). */\n meta?: string[];\n /** Optional second line (cover letter excerpt, summary ...). */\n body?: string;\n /** Lines the body may wrap to (default 3). */\n bodyLines?: number;\n link?: CardLink;\n /** A command the user can run for this row, printed dim (e.g. `/download cv_1`). */\n action?: string;\n /** The catalog job this row is about, for `/apply <n>` (also when the row has no link). */\n job?: { id: string; title: string };\n};\n\nexport type ChatCard = {\n kind: CardKind;\n title: string;\n rows: CardRow[];\n /** Footer hint such as \"/open 1 opens the job page \u00B7 /apply 2 prepares an application\". */\n hint?: string;\n /** Every link on the card, numbered, for `/open <n>`. */\n links: CardLink[];\n /** Items the result had beyond the rows shown. */\n more?: number;\n};\n\n/** Internal tools the app never shows a card for (its HIDDEN_TOOLS), plus activity-only reads. */\nconst NO_CARD_TOOLS: ReadonlySet<string> = new Set([\n 'updateWorkingMemory',\n 'clearWorkingMemory',\n 'getWorkingMemory',\n 'tailoredCvFlow',\n 'seekerApplyFlow',\n 'autoApplyQueueFlow',\n 'catalogApplyFlow',\n 'catalogAutoApplyQueueFlow',\n 'documentIngestionFlow',\n 'employerJobPostFlow',\n 'candidateOutreachFlow',\n 'talentPipelineFlow',\n 'skillsLoad',\n 'skillPrepareRun',\n 'cvCompareWithMaster',\n 'novaPause',\n 'novaResume',\n 'exportMemory',\n 'memoryGraphGet',\n 'artifactRead',\n]);\n\n/** Tool name \u2192 card (the app dispatches on the tool name first: `cvList` is `cv-detail` on the wire). */\nconst KIND_BY_TOOL: Record<string, CardKind> = {\n jobSearch: 'job-list',\n jobRecommend: 'job-list',\n catalogJobSearch: 'job-list',\n catalogSavedJobList: 'job-list',\n jobListByCompany: 'job-list',\n jobGet: 'job-detail',\n catalogJobGet: 'job-detail',\n jobDraft: 'job-detail',\n jobUpdate: 'job-detail',\n jobPublish: 'job-detail',\n jobClose: 'job-detail',\n applicationPrepare: 'application-preview',\n catalogApplyPrepare: 'application-preview',\n applicationSubmit: 'application-confirm',\n catalogApplySubmit: 'application-confirm',\n applicationGet: 'application-confirm',\n applicationUpdateStatus: 'application-confirm',\n applicationWithdraw: 'application-confirm',\n applicationTrack: 'application-list',\n catalogApplyTrack: 'application-list',\n applicationListByJob: 'application-list',\n cvList: 'cv-list',\n cvCreate: 'cv-detail',\n cvDuplicate: 'cv-detail',\n cvTailor: 'cv-detail',\n cvUpdateSummary: 'cv-detail',\n cvGet: 'cv-detail',\n cvUpdate: 'cv-detail',\n cvUpdateOverrides: 'cv-detail',\n cvSetFitToOnePage: 'cv-detail',\n cvGetResolved: 'cv-detail',\n cvExport: 'cv-export',\n cvShareLinkCreate: 'cv-share',\n cvAccessGrantCreate: 'cv-share',\n cvPublish: 'cv-publish',\n cvUnpublish: 'cv-publish',\n skillsList: 'skill-list',\n novaList: 'automation-list',\n novaRunHistory: 'automation-list',\n novaCompile: 'automation-detail',\n novaActivate: 'automation-detail',\n novaRunNow: 'automation-run',\n profileGet: 'profile-summary',\n companyList: 'company-list',\n};\n\nconst KNOWN_CARD_TYPES: ReadonlySet<string> = new Set<CardKind>([\n 'job-list',\n 'job-detail',\n 'application-preview',\n 'application-confirm',\n 'application-list',\n 'cv-detail',\n 'cv-export',\n 'cv-share',\n 'cv-publish',\n 'skill-list',\n 'automation-list',\n 'automation-detail',\n 'automation-run',\n 'profile-summary',\n 'company-list',\n]);\n\nfunction kindOf(payload: Pick<ToolEventPayload, 'name' | 'cardType'>): CardKind {\n const byName = KIND_BY_TOOL[payload.name];\n if (byName) return byName;\n if (payload.cardType === 'automation-run-list') return 'automation-list';\n return payload.cardType && KNOWN_CARD_TYPES.has(payload.cardType) ? (payload.cardType as CardKind) : 'generic';\n}\n\n/** A failed or refused result: the tool row already says so. */\nfunction isFailure(result: unknown): boolean {\n if (!isRec(result)) return false;\n return result.ok === false || result.error === true || (isRec(result.error) && typeof result.error.code === 'string');\n}\n\n/** \"Job Search\" / \"catalogJobSearch\" \u2192 \"Catalog job search\". */\nfunction cardTitle(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 const text = raw.replace(/\\s+/g, ' ').trim();\n return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();\n}\n\n/** Builds the card for a finished tool call, or null when the result needs no card. */\nexport function cardFromToolResult(payload: ToolEventPayload, opts: { appUrl: string; now?: number }): ChatCard | null {\n const { result } = payload;\n if (result === undefined || result === null) return null;\n if (payload.stage === 'failed' || payload.status === 'failed' || isFailure(result)) return null;\n if (NO_CARD_TOOLS.has(payload.name) || isResearchTool(payload) || isArtifactTool(payload)) return null;\n if (payload.cardType === 'artifact-suggestions' || payload.cardType === 'site-publish') return null;\n if (isRec(result) && result.approvalRequired === true) return null;\n const build: BuildOpts = { siteUrl: publicSiteUrl(opts.appUrl), now: opts.now ?? Date.now() };\n switch (kindOf(payload)) {\n case 'job-list':\n return jobListCard(result, build);\n case 'job-detail':\n return jobDetailCard(result, build);\n case 'application-preview':\n return applicationPreviewCard(result, build);\n case 'application-confirm':\n return applicationConfirmCard(result, build);\n case 'application-list':\n return applicationListCard(result, build);\n case 'cv-list':\n return cvListCard(result, build);\n case 'cv-detail':\n // `cvList` is `cv-detail` on the wire; a list result is still a list.\n return isRec(result) && Array.isArray(result.cvs) ? cvListCard(result, build) : cvDetailCard(result, build);\n case 'cv-export':\n return cvExportCard(result);\n case 'cv-share':\n return cvShareCard(result, build, payload.name === 'cvAccessGrantCreate');\n case 'cv-publish':\n return cvPublishCard(result, build, payload.name !== 'cvUnpublish');\n case 'skill-list':\n return skillListCard(result);\n case 'automation-list':\n return automationListCard(result, build, payload.name === 'novaRunHistory' || payload.cardType === 'automation-run-list');\n case 'automation-detail':\n return automationDetailCard(result, build, false);\n case 'automation-run':\n return automationDetailCard(result, build, true);\n case 'profile-summary':\n return profileSummaryCard(result);\n case 'company-list':\n return companyListCard(result);\n default:\n return genericCard(result, cardTitle(payload));\n }\n}\n\n/** The links of the most recent card that has any, newest card first (what `/open <n>` resolves). */\nexport function latestCardLinks(cards: readonly ChatCard[]): CardLink[] {\n for (let i = cards.length - 1; i >= 0; i -= 1) {\n const card = cards[i] as ChatCard;\n if (card.links.length) return card.links;\n }\n return [];\n}\n\n/** Link `n` of the newest card with links, or undefined. */\nexport function findCardLink(cards: readonly ChatCard[], n: number): CardLink | undefined {\n return latestCardLinks(cards).find((link) => link.n === n);\n}\n\n/** Job `n` of the newest card that lists jobs (for `/apply <n>`, rows without a link included). */\nexport function findCardJob(cards: readonly ChatCard[], n: number): { id: string; title: string } | undefined {\n for (let i = cards.length - 1; i >= 0; i -= 1) {\n const rows = (cards[i] as ChatCard).rows.filter((row) => row.job);\n if (rows.length) return rows.find((row) => row.n === n)?.job;\n }\n return undefined;\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.versionId ? { versionId: action.versionId } : {}),\n ...(action.versionNumber !== undefined ? { versionNumber: action.versionNumber } : {}),\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 * The streamed answer versus `finish.text`, and the guard against an answer\n * said twice. Pure; the transcript reducer uses it.\n *\n * Why: Flash-Lite sometimes repeats its whole answer once. The server's\n * repetition guard (`AgentTextStreamAccumulator`) only trips after three\n * repeats, and Mastra's `output.text` (the `finish.text`) is every raw text\n * chunk joined, so both the stream and `finish.text` can carry the answer\n * twice (\"...positions above?Here are the relevant...\"). The reducer holds a\n * suspected repeat back from scrollback while it streams, drops it when it\n * turns out to be a complete copy, and only says \"Tabbio revised this\n * answer\" when the final text is really different.\n */\n\n/** Compact characters a suspected repeat needs before it is held back. */\nexport const ECHO_HOLD_CHARS = 24;\n/** A repeated block this long (normalised) is dropped wherever it starts. */\nexport const ECHO_COLLAPSE_CHARS = 80;\n/** A whole answer said twice is dropped from this length on. */\nexport const WHOLE_REPEAT_CHARS = 16;\n\ntype Compact = { text: string; index: number[] };\n\n/** The text without whitespace, with the raw offset of every kept character. */\nfunction compact(raw: string): Compact {\n let text = '';\n const index: number[] = [];\n for (let i = 0; i < raw.length; i += 1) {\n const ch = raw[i] as string;\n if (ch === ' ' || ch === '\\n' || ch === '\\t' || ch === '\\r' || ch === '\\f' || ch === '\\v' || ch === '\u00A0') continue;\n text += ch;\n index.push(i);\n }\n return { text, index };\n}\n\n/** Whitespace-insensitive key (the same idea as `normalizeText`, without the spaces). */\nexport function compactKey(raw: string): string {\n return compact(raw).text;\n}\n\n/** Raw offset just after the first `n` compact characters of `raw`. */\nexport function rawOffsetAfter(raw: string, n: number): number {\n if (n <= 0) return 0;\n const { index } = compact(raw);\n const last = index[Math.min(n, index.length) - 1];\n return last === undefined ? 0 : last + 1;\n}\n\nexport type Echo = {\n /** Raw offset where the repeated text starts. */\n at: number;\n /** Raw offset right after the block it repeats (whitespace before the repeat excluded). */\n cut: number;\n /** The repeat already covers the whole block. */\n complete: boolean;\n /** Compact length of the repeated tail. */\n length: number;\n /** The repeated block is the start of the text: the whole answer said again. */\n fromStart: boolean;\n};\n\nfunction lineStarts(raw: string): number[] {\n const starts: number[] = [];\n for (let i = raw.indexOf('\\n'); i !== -1; i = raw.indexOf('\\n', i + 1)) starts.push(i + 1);\n return starts;\n}\n\n/**\n * The earliest tail of `raw` that repeats a block starting at the beginning\n * of the text, of a line, or of one of `starts` (the turn's text segments):\n * the tail is a prefix of that block, at least `ECHO_HOLD_CHARS` long.\n * Null when nothing repeats.\n */\nexport function findEcho(raw: string, starts: readonly number[] = []): Echo | null {\n const c = compact(raw);\n const n = c.text.length;\n if (n < 2 * ECHO_HOLD_CHARS) return null;\n const candidates = new Set<number>();\n const toCompact = (offset: number) => {\n // First compact character at or after the raw offset.\n let lo = 0;\n let hi = c.index.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if ((c.index[mid] as number) < offset) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n };\n for (const offset of [0, ...starts, ...lineStarts(raw)]) candidates.add(toCompact(offset));\n let best: Echo | null = null;\n for (const q of [...candidates].sort((a, b) => a - b)) {\n if (n - q < 2 * ECHO_HOLD_CHARS) continue;\n const opening = c.text.slice(q, q + ECHO_HOLD_CHARS);\n for (let p = c.text.indexOf(opening, q + ECHO_HOLD_CHARS); p !== -1; p = c.text.indexOf(opening, p + 1)) {\n const tail = n - p;\n if (tail > p - q) continue;\n if (!c.text.startsWith(c.text.slice(p), q)) continue;\n const echo: Echo = {\n at: c.index[p] as number,\n cut: (c.index[p - 1] as number) + 1,\n complete: tail === p - q,\n length: tail,\n fromStart: q === 0,\n };\n if (!best || echo.at < best.at) best = echo;\n break;\n }\n }\n return best;\n}\n\n/**\n * Where to cut `raw` so a repeated copy is dropped: the whole text said\n * twice, or a complete repeat of at least `ECHO_COLLAPSE_CHARS`. Null when\n * there is nothing to drop.\n */\nexport function repeatCut(raw: string, starts: readonly number[] = []): number | null {\n const c = compact(raw);\n const n = c.text.length;\n if (n % 2 === 0 && n / 2 >= WHOLE_REPEAT_CHARS && c.text.slice(0, n / 2) === c.text.slice(n / 2)) {\n return (c.index[n / 2 - 1] as number) + 1;\n }\n const echo = findEcho(raw, starts);\n return echo?.complete && echo.length >= ECHO_COLLAPSE_CHARS ? echo.cut : null;\n}\n\n/** `raw` without a repeated copy (see `repeatCut`), trailing whitespace trimmed. */\nexport function collapseRepeat(raw: string, starts: readonly number[] = []): string {\n const cut = repeatCut(raw, starts);\n return cut === null ? raw : raw.slice(0, cut).trimEnd();\n}\n\n/** True when `head` is made only of prefixes of `full` (adapters that resend the text so far). */\nfunction isSnapshotHead(head: string, full: string): boolean {\n let rest = head;\n while (rest) {\n let k = 0;\n while (k < rest.length && k < full.length && rest[k] === full[k]) k += 1;\n if (k === 0) return false;\n rest = rest.slice(k);\n }\n return true;\n}\n\nexport type FinalPlan =\n /** The final text says what was streamed: nothing to print. */\n | { kind: 'same' }\n /** The final text continues the streamed one: print only `text`. */\n | { kind: 'append'; text: string }\n /** A genuinely different answer. */\n | { kind: 'different'; text: string };\n\n/**\n * What to do with `finish.text` given the text already streamed. Both are\n * compared without whitespace, after dropping a repeated copy.\n */\nexport function planFinal(streamed: string, finalText: string): FinalPlan {\n const final = collapseRepeat(finalText.trim());\n const f = compactKey(final);\n const s = compactKey(streamed);\n if (!f || f === s) return { kind: 'same' };\n if (!s) return { kind: 'different', text: final };\n if (f.startsWith(s)) {\n const rest = final.slice(rawOffsetAfter(final, s.length));\n // The \"rest\" is the streamed answer's last block said again (text before a tool, then the answer twice).\n const r = f.slice(s.length);\n if (!rest.trim() || (r.length >= WHOLE_REPEAT_CHARS && s.endsWith(r))) return { kind: 'same' };\n return { kind: 'append', text: rest };\n }\n if (s.startsWith(f)) return { kind: 'same' };\n if (f.endsWith(s) && isSnapshotHead(f.slice(0, f.length - s.length), s)) return { kind: 'same' };\n return { kind: 'different', text: final };\n}\n", "/**\n * The transcript reducer's working draft and its two central moves:\n * `promote` (finished live items into scrollback, with the repeat guard) and\n * `finishTurn` (the `finish` event: reconcile the streamed text with\n * `finish.text`). Pure; `chat-transcript.ts` holds the reducer itself.\n */\nimport {\n type ChatState,\n type ChatToolCall,\n type ChatTurn,\n FINAL_STAGES,\n type LiveItem,\n type LiveText,\n type TranscriptEntry,\n normalizeText,\n stableBoundary,\n} from './chat-model';\nimport { holdsArtifact } from './chat-tool-extras';\nimport { ECHO_COLLAPSE_CHARS, findEcho, planFinal, repeatCut } from './chat-text';\n\nexport type Draft = { state: ChatState; now: number };\n\n/** Hidden internal calls remembered for `ctrl+o`. */\nconst HIDDEN_CALLS_KEPT = 20;\n\nexport function nextId(d: Draft, prefix: string): string {\n d.state = { ...d.state, seq: d.state.seq + 1 };\n return `${prefix}-${d.state.seq}`;\n}\n\nexport function push(d: Draft, entry: TranscriptEntry): void {\n d.state = { ...d.state, entries: [...d.state.entries, entry] };\n}\n\nexport function 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/** A finished tool row, then its card and any files saved while it was live. */\nfunction commitTool(d: Draft, turn: ChatTurn, call: ChatToolCall): ChatTurn {\n const { card, saved, ...row } = call;\n push(d, { kind: 'tool', id: nextId(d, 'tool'), call: row, gap: turn.lastKind === 'markdown' });\n if (card) push(d, { kind: 'card', id: nextId(d, 'card'), card, toolCallId: call.id });\n if (saved) push(d, { kind: 'saved', id: nextId(d, 'saved'), saved });\n return { ...turn, lastKind: 'tool' };\n}\n\nexport function closeOpenText(items: LiveItem[]): LiveItem[] {\n return items.map((item) => (item.kind === 'text' && !item.closed ? { ...item, closed: true } : item));\n}\n\n/**\n * Drops the text after `cut` (an offset in `turn.text`) that is not printed\n * yet: a repeated copy of the answer. Printed text is never taken back.\n */\nexport function dropTextAfter(turn: ChatTurn, cut: number): ChatTurn {\n let end = cut;\n const items = turn.items.flatMap((item): LiveItem[] => {\n if (item.kind !== 'text' || item.start === undefined) return [item];\n const keep = Math.max(cut - item.start, item.committed);\n if (keep >= item.text.length) return [item];\n end = Math.max(end, item.start + keep);\n return keep > 0 || item.committed > 0 ? [{ ...item, text: item.text.slice(0, keep) }] : [];\n });\n const { echoAt: _echoAt, ...rest } = turn;\n return { ...rest, items, text: turn.text.slice(0, end) };\n}\n\nfunction hasPendingText(turn: ChatTurn): boolean {\n return turn.items.some((item) => item.kind === 'text' && item.text.length > item.committed);\n}\n\n/**\n * The repeat guard: a tail of the turn's text that repeats an earlier block\n * is held back (`echoAt`) while it streams, and dropped once it is a\n * complete copy of at least `ECHO_COLLAPSE_CHARS` characters.\n */\nfunction guardRepeat(turn: ChatTurn): ChatTurn {\n if (!hasPendingText(turn)) return turn.echoAt === undefined ? turn : { ...turn, echoAt: undefined };\n const echo = findEcho(turn.text, turn.segments ?? []);\n if (echo?.complete && echo.length >= ECHO_COLLAPSE_CHARS) return dropTextAfter(turn, echo.cut);\n if (echo?.at === turn.echoAt) return turn;\n return { ...turn, echoAt: echo?.at };\n}\n\n/** How much of an open segment may be committed: finished blocks before any held-back repeat. */\nfunction committable(item: LiveText, echoAt: number | undefined): number {\n const pending = item.text.slice(item.committed);\n if (echoAt === undefined || item.start === undefined) return stableBoundary(pending);\n const limit = echoAt - item.start - item.committed;\n if (limit <= 0) return 0;\n return limit >= pending.length ? stableBoundary(pending) : stableBoundary(pending.slice(0, limit));\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 */\nexport function promote(d: Draft, final: boolean, force = false): void {\n if (!d.state.turn) return;\n let turn = final ? d.state.turn : guardRepeat(d.state.turn);\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 turn = commitTool(d, turn, call);\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 = committable(item, turn.echoAt);\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 if (settled && turn.hidden?.length) {\n const at = d.state.entries.length;\n const kept = [...(d.state.hiddenCalls ?? []), ...turn.hidden.map((call) => ({ call, at }))].slice(-HIDDEN_CALLS_KEPT);\n d.state = { ...d.state, hiddenCalls: kept };\n }\n setTurn(d, settled ? null : turn);\n}\n\n/** The finish event: the streamed text (without a repeated copy) against `finish.text`. */\nexport function 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 const cut = repeatCut(turn.text, turn.segments ?? []);\n if (cut !== null) turn = dropTextAfter(turn, cut);\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) {\n const plan = planFinal(turn.text, finalText);\n if (plan.kind === 'append') {\n const last = items[items.length - 1];\n items =\n last?.kind === 'text'\n ? [...items.slice(0, -1), { ...last, text: last.text + plan.text }]\n : [...items, { kind: 'text', id: 'final', text: plan.text.replace(/^\\s+/, ''), committed: 0, closed: true }];\n } else if (plan.kind === 'different') {\n if (!turn.text.trim() || !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: plan.text, committed: 0, closed: true }];\n } else {\n revision = plan.text;\n }\n }\n }\n turn = { ...turn, items, finished: true, finishReason: payload.finishReason, echoAt: undefined };\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", "/**\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 *\n * A finished tool whose result the app shows as a card is followed by a\n * `card` entry (`chat-cards.ts`), and files saved for it by a `saved` entry.\n * `promote`, `finishTurn` and the duplicate-answer guard live in\n * `chat-draft.ts` / `chat-text.ts`.\n */\nimport type { AgentStreamEvent, ArtifactDraftPayload, ToolEventPayload } from './chat';\nimport { type ChatArtifact, applyDraft, mergeSources } from './chat-artifacts';\nimport { cardFromToolResult } from './chat-cards';\nimport { type Draft, closeOpenText, finishTurn, nextId, promote, push, setTurn } from './chat-draft';\nimport {\n type ChatAction,\n type ChatState,\n type ChatToolCall,\n type ChatTurn,\n FINAL_STAGES,\n type LiveTool,\n type PendingApproval,\n type SavedFiles,\n type ToolStage,\n type TranscriptEntry,\n isHiddenTool,\n stageOf,\n toolTitle,\n} from './chat-model';\nimport { PRODUCTION_APP_URL } from './config';\nimport { type ArtifactStatusAction, lastShownArtifact, patchArtifact, toolExtras } from './chat-tool-extras';\n\nexport * from './chat-model';\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 (final && payload.result !== undefined) {\n const card = cardFromToolResult({ ...payload, stage }, { appUrl: d.state.appUrl ?? PRODUCTION_APP_URL, now: d.now });\n if (card) extra = { ...extra, card };\n }\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\n/** An internal call (working memory): kept on the turn for `ctrl+o`, never a row, never splits the text. */\nfunction upsertHidden(d: Draft, payload: ToolEventPayload, stage: ToolStage): void {\n const turn = d.state.turn as ChatTurn;\n const hidden = turn.hidden ?? [];\n const previous = hidden.find((call) => call.id === payload.id);\n const final = FINAL_STAGES.has(stage);\n const call: ChatToolCall = {\n ...(previous ?? { id: payload.id, name: payload.name, title: toolTitle(payload), args: payload.args, startedAt: d.now }),\n stage,\n ...(Object.keys(payload.args).length ? { args: payload.args } : {}),\n ...(payload.result !== undefined ? { result: payload.result } : {}),\n ...(final && previous && previous.endedAt === undefined ? { endedAt: d.now, durationMs: Math.max(0, d.now - previous.startedAt) } : {}),\n ...(final && !previous ? { endedAt: d.now } : {}),\n };\n const next = previous ? hidden.map((c) => (c.id === payload.id ? call : c)) : [...hidden, call];\n setTurn(d, { ...turn, hidden: next });\n}\n\n/** `ctrl+o`: the last tool of the latest turn (a hidden call only when the turn had no visible tool). */\nfunction expandLastTool(d: Draft): void {\n const entries = d.state.entries;\n let lastUser = -1;\n let lastTool = -1;\n entries.forEach((entry, i) => {\n if (entry.kind === 'user') lastUser = i;\n if (entry.kind === 'tool') lastTool = i;\n });\n const hidden = (d.state.hiddenCalls ?? []).filter((h) => h.at > lastUser).at(-1);\n const visible = lastTool >= 0 ? (entries[lastTool] as Extract<TranscriptEntry, { kind: 'tool' }>) : undefined;\n const call = visible && lastTool > lastUser ? visible.call : (hidden?.call ?? visible?.call);\n if (call) push(d, { kind: 'tool-detail', id: nextId(d, 'detail'), call });\n}\n\n/** Files saved for an artifact or a CV export: under its row while live, else one entry now. */\nfunction applyFilesSaved(d: Draft, toolCallId: string | undefined, saved: SavedFiles): void {\n const turn = d.state.turn;\n const matches = (call: ChatToolCall) =>\n (toolCallId !== undefined && call.id === toolCallId) || (saved.artifactId !== undefined && call.artifact?.id === saved.artifactId);\n const index = turn?.items.findIndex((item) => item.kind === 'tool' && matches(item.call)) ?? -1;\n if (turn && index >= 0) {\n const item = turn.items[index] as LiveTool;\n const items = [...turn.items];\n items[index] = { ...item, call: { ...item.call, saved } };\n setTurn(d, { ...turn, items });\n promote(d, false);\n return;\n }\n push(d, { kind: 'saved', id: nextId(d, 'saved'), saved });\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 let segments = current.segments;\n if (last?.kind === 'text' && !last.closed) items[items.length - 1] = { ...last, text: last.text + event.payload.text };\n else {\n const start = current.text.length;\n items.push({ kind: 'text', id: nextId(d, 'text'), text: event.payload.text, committed: 0, closed: false, start });\n segments = [...(segments ?? []), start];\n }\n setTurn(d, { ...current, items, text: current.text + event.payload.text, ...(segments ? { segments } : {}) });\n return;\n }\n case 'tool-call':\n case 'tool-result': {\n const stage = stageOf(event.payload, event.type === 'tool-call' ? 'running' : 'completed');\n if (isHiddenTool(event.payload.name)) upsertHidden(d, event.payload, stage);\n else upsertTool(d, event.payload, stage);\n promote(d, false);\n return;\n }\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 'files-saved':\n applyFilesSaved(d, action.toolCallId, action.saved);\n return d.state;\n case 'expand-last-tool':\n expandLastTool(d);\n return d.state;\n default:\n applyStream(d, action);\n return d.state;\n }\n}\n", "/**\n * What the chat saves to disk on its own (auto-save): every artifact a\n * create or edit tool made once it is ready (each version once), and every\n * `cvExport` result (the format asked for, else the PDF). Pure; the chat\n * screen's `useAutoSave` does the I/O.\n */\nimport type { ChatArtifact } from './chat-artifacts';\nimport type { ChatState, ChatToolCall } from './chat-model';\n\nexport type SaveTarget =\n | { type: 'artifact'; key: string; artifactId: string; versionId?: string; title: string; kind: string; toolCallId?: string }\n | { type: 'cv'; key: string; cvId: string; title: string; format: string; toolCallId: string };\n\n/** Tools whose result is a file this chat made (reading an existing file with `artifactGet` saves nothing). */\nexport const PRODUCING_TOOLS: ReadonlySet<string> = new Set(['generateImage', 'createDocument', 'createPage', 'updatePage', 'updateDocument', 'editImage']);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The export format to save: the one asked for, else PDF, else the first one the plan allows. */\nexport function cvExportFormat(requested: unknown, formats: unknown): string | null {\n const open = (Array.isArray(formats) ? formats : [])\n .filter(isRecord)\n .filter((f) => f.locked !== true && typeof f.format === 'string')\n .map((f) => String(f.format).toLowerCase());\n const asked = typeof requested === 'string' ? requested.toLowerCase() : '';\n if (asked && open.includes(asked)) return asked;\n if (open.includes('pdf')) return 'pdf';\n return open[0] ?? null;\n}\n\nfunction cvTarget(call: ChatToolCall): SaveTarget | null {\n if (call.name !== 'cvExport' || call.stage !== 'completed' || !isRecord(call.result)) return null;\n const format = cvExportFormat(call.args.format, call.result.formats);\n if (!format) return null;\n const cvId = typeof call.result.cvId === 'string' && call.result.cvId ? call.result.cvId : 'master';\n const title = typeof call.result.cvTitle === 'string' && call.result.cvTitle ? call.result.cvTitle : 'My CV';\n return { type: 'cv', key: `cv:${call.id}:${format}`, cvId, title, format, toolCallId: call.id };\n}\n\nfunction artifactTarget(artifact: ChatArtifact, toolCallId?: string): SaveTarget | null {\n if (artifact.status !== 'ready') return null;\n return {\n type: 'artifact',\n key: `artifact:${artifact.id}:${artifact.versionNumber ?? 0}`,\n artifactId: artifact.id,\n ...(artifact.versionId ? { versionId: artifact.versionId } : {}),\n title: artifact.title,\n kind: artifact.kind,\n ...(toolCallId ? { toolCallId } : {}),\n };\n}\n\n/** Everything in the transcript and the live turn that should be on disk, in order, once per key. */\nexport function saveTargets(state: Pick<ChatState, 'entries' | 'turn'>): SaveTarget[] {\n const targets = new Map<string, SaveTarget>();\n const made = new Set<string>();\n const add = (target: SaveTarget | null) => {\n if (target && !targets.has(target.key)) targets.set(target.key, target);\n };\n const addCall = (call: ChatToolCall) => {\n add(cvTarget(call));\n if (!call.artifact || !PRODUCING_TOOLS.has(call.name)) return;\n made.add(call.artifact.id);\n add(artifactTarget(call.artifact, call.id));\n };\n for (const entry of state.entries) {\n if (entry.kind === 'tool') addCall(entry.call);\n // A card that turned ready after its row was printed.\n else if (entry.kind === 'artifact' && made.has(entry.artifact.id)) add(artifactTarget(entry.artifact));\n }\n for (const item of state.turn?.items ?? []) if (item.kind === 'tool') addCall(item.call);\n return [...targets.values()];\n}\n", "/**\n * Cards and saved-file entries as terminal lines (ANSI, OSC 8 links where\n * the terminal supports them). One implementation for the chat transcript\n * (`CardView`, `SavedFilesView`) and the plain output of `tabbio ask`.\n */\nimport { displayPath, formatBytes } from '../../../core/artifact-save';\nimport type { CardLink, CardRow, ChatCard } from '../../../core/chat-cards';\nimport type { SavedFiles } from '../../../core/chat-model';\nimport { hyperlink } from '../../hyperlink';\nimport { theme } from '../../theme';\nimport { displayWidth, padEnd, safeTerminalText, truncate, wrapWords } from '../../text';\n\nexport type LineOpts = { width: number; links: boolean };\n\nconst MIN_WIDTH = 24;\nconst MAX_LABEL = 16;\n\nfunction linked(text: string, link: CardLink | undefined, links: boolean): string {\n return link && links && safeTerminalText(link.url) === link.url ? hyperlink(text, link.url) : text;\n}\n\nfunction labelRowLines(row: CardRow, numberWidth: number, pad: string, labelWidth: number, width: number, links: boolean): string[] {\n const label = theme.dim(padEnd(truncate(safeTerminalText(row.label ?? ''), labelWidth), labelWidth));\n const valueWidth = Math.max(8, width - displayWidth(pad) - labelWidth - 2);\n const valuePad = `${pad}${' '.repeat(labelWidth + 2)}`;\n // A detail row with a link carries its number too (`/open 2`).\n const lead = row.n !== undefined && numberWidth ? `${theme.dim(String(row.n).padStart(numberWidth))} ` : pad;\n const lines: string[] = [];\n if (row.title) lines.push(`${lead}${label} ${linked(truncate(safeTerminalText(row.title), valueWidth), row.link, links)}`);\n const body = row.body ? wrapWords(safeTerminalText(row.body), valueWidth, row.bodyLines ?? 3) : [];\n body.forEach((line, i) => lines.push(i === 0 && !row.title ? `${lead}${label} ${line}` : `${valuePad}${line}`));\n if (row.link && row.link.url !== row.title) lines.push(`${valuePad}${theme.dim(safeTerminalText(row.link.url))}`);\n return lines;\n}\n\nfunction itemRowLines(row: CardRow, numberWidth: number, pad: string, width: number, links: boolean): string[] {\n const contentWidth = Math.max(8, width - displayWidth(pad));\n const number = row.n !== undefined && numberWidth ? `${theme.dim(String(row.n).padStart(numberWidth))} ` : pad;\n const url = row.link && row.link.url !== row.title ? safeTerminalText(row.link.url) : undefined;\n const title = truncate(safeTerminalText(row.title), contentWidth);\n const shown = linked(theme.bold(title), row.link, links);\n const lines: string[] = [];\n // The plain URL follows the title so it can be copied where OSC 8 links do not work.\n if (url && displayWidth(title) + 2 + displayWidth(url) <= contentWidth) lines.push(`${number}${shown} ${theme.dim(url)}`);\n else {\n lines.push(`${number}${shown}`);\n if (url) lines.push(`${pad}${theme.dim(url)}`);\n }\n if (row.meta?.length) lines.push(`${pad}${theme.dim(truncate(row.meta.map(safeTerminalText).join(` ${theme.symbols.middot} `), contentWidth))}`);\n if (row.body) for (const line of wrapWords(safeTerminalText(row.body), contentWidth, row.bodyLines ?? 3)) lines.push(`${pad}${line}`);\n if (row.action && row.action !== row.title) lines.push(`${pad}${theme.dim(`${theme.symbols.arrowRight} ${safeTerminalText(row.action)}`)}`);\n return lines;\n}\n\n/**\n * `Jobs \u00B7 2` then numbered rows (`1 Title https://\u2026`, dim meta, body,\n * action), detail rows (`Status ready to submit`), `+N more` and the hint.\n */\nexport function cardLines(card: ChatCard, opts: LineOpts): string[] {\n const width = Math.max(MIN_WIDTH, opts.width);\n const numbers = card.rows.filter((row) => row.n !== undefined).map((row) => row.n as number);\n const numberWidth = numbers.length ? String(Math.max(...numbers)).length : 0;\n const pad = ' '.repeat(numberWidth ? numberWidth + 2 : 0);\n const labelWidth = Math.min(MAX_LABEL, Math.max(0, ...card.rows.filter((row) => row.label).map((row) => displayWidth(safeTerminalText(row.label ?? '')))));\n const lines = [theme.dim(truncate(safeTerminalText(card.title), width))];\n for (const row of card.rows) {\n lines.push(...(row.label ? labelRowLines(row, numberWidth, pad, labelWidth, width, opts.links) : itemRowLines(row, numberWidth, pad, width, opts.links)));\n }\n if (card.more) lines.push(`${pad}${theme.dim(`+${card.more} more`)}`);\n if (card.hint) {\n // Wrapped, never cut: the hint is the next step.\n const arrow = `${theme.symbols.arrowRight} `;\n wrapWords(safeTerminalText(card.hint), width - displayWidth(arrow)).forEach((line, i) => lines.push(theme.dim(`${i === 0 ? arrow : ' '.repeat(displayWidth(arrow))}${line}`)));\n }\n return lines;\n}\n\n/** A preview line as plain printable text: tabs as two spaces, control characters dropped. */\nfunction printable(line: string): string {\n // eslint-disable-next-line no-control-regex\n return line.replace(/\\t/g, ' ').replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, '');\n}\n\n/**\n * `\u2713 Saved ./tabbio-artifacts/portfolio-9r7z2q.html (12 KB)`, one line per\n * file, then for a text file its first lines in a dim block and how to see\n * the rest. A failed save says why and how to retry.\n */\nexport function savedLines(saved: SavedFiles, opts: { width: number; cwd?: string }): string[] {\n const width = Math.max(MIN_WIDTH, opts.width);\n const retry = saved.artifactId ? `/save ${safeTerminalText(saved.artifactId)}` : saved.cvId ? `/download ${safeTerminalText(saved.cvId)}` : null;\n if (saved.error) {\n const what = saved.title ? `\"${safeTerminalText(saved.title)}\"` : safeTerminalText(saved.artifactId ?? 'the file');\n return [\n `${theme.attention(theme.symbols.attention)} Could not save ${what}: ${safeTerminalText(saved.error)}`,\n ...(retry ? [theme.dim(` ${theme.symbols.arrowRight} ${retry} to try again`)] : []),\n ];\n }\n const lines = saved.files.map(\n (file) => `${theme.success(theme.symbols.success)} Saved ${displayPath(file.path, opts.cwd)} ${theme.dim(`(${formatBytes(file.bytes)})`)}`,\n );\n const preview = saved.preview;\n if (preview?.lines.length) {\n const inner = Math.max(8, width - 4);\n for (const line of preview.lines) lines.push(theme.dim(` ${theme.symbols.gutter} ${truncate(printable(line), inner)}`));\n const hidden = preview.total - preview.lines.length;\n const hints = [\n hidden > 0 ? `+${hidden} lines` : null,\n saved.artifactId ? `/show ${saved.artifactId} for the full file` : null,\n saved.artifactId ? `/open ${saved.artifactId} in the browser` : null,\n ].filter((hint): hint is string => Boolean(hint));\n // Not truncated: the commands must stay whole (the line wraps instead).\n if (hints.length) lines.push(theme.dim(` ${hints.join(` ${theme.symbols.middot} `)}`));\n }\n return lines;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["isRecord", "text", "resolve", "isRecord", "displayWidth", "truncate", "isRecord", "counted", "displayWidth", "isRecord", "resolve", "existsSync", "join", "join", "existsSync", "isRecord", "str", "str", "rows", "str", "card", "linked", "card", "card", "call", "current", "item", "isRecord", "isRecord", "open", "pad", "card"]
7
+ }