@tabbio-technologies/cli 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/core/errors.ts", "../../src/core/io.ts", "../../src/core/config.ts", "../../src/core/fs-atomic.ts", "../../src/core/credentials.ts", "../../src/core/runtime.ts", "../../src/core/version.ts", "../../src/core/mcp.ts", "../../src/core/catalog.ts", "../../src/core/http.ts", "../../src/core/mcp-results.ts", "../../src/core/loopback.ts", "../../src/core/auth.ts"],
4
+ "sourcesContent": ["/**\n * Every failure the CLI reports is a CliError. The exit code is part of the\n * public contract (scripts branch on it), so mapping lives in one place.\n */\n\nexport const ExitCode = {\n Ok: 0,\n Error: 1,\n Usage: 2,\n Auth: 3,\n Forbidden: 4,\n NotFound: 5,\n ApprovalPending: 6,\n Network: 7,\n Server: 8,\n /** SIGINT / Ctrl-C (128 + 2). */\n Interrupted: 130,\n} as const;\n\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];\n\n/** Human reference printed by `tabbio help exit-codes`. */\nexport const EXIT_CODE_DOCS: ReadonlyArray<{ code: ExitCode; name: string; meaning: string }> = [\n { code: ExitCode.Ok, name: 'Ok', meaning: 'Success' },\n { code: ExitCode.Error, name: 'Error', meaning: 'General failure (including a failed tool)' },\n { code: ExitCode.Usage, name: 'Usage', meaning: 'Bad flags or input; missing required fields' },\n { code: ExitCode.Auth, name: 'Auth', meaning: 'Not signed in, session expired or token rejected' },\n { code: ExitCode.Forbidden, name: 'Forbidden', meaning: 'Not allowed (token scope, plan or permission)' },\n { code: ExitCode.NotFound, name: 'NotFound', meaning: 'The tool or resource does not exist' },\n { code: ExitCode.ApprovalPending, name: 'ApprovalPending', meaning: 'The action is waiting for approval' },\n { code: ExitCode.Network, name: 'Network', meaning: 'Could not reach Tabbio, or timed out' },\n { code: ExitCode.Server, name: 'Server', meaning: 'Tabbio failed on its side (5xx)' },\n { code: ExitCode.Interrupted, name: 'Interrupted', meaning: 'Cancelled with Ctrl-C' },\n];\n\nexport type CliErrorOptions = {\n code: string;\n message: string;\n hint?: string;\n exitCode: ExitCode;\n requestId?: string;\n /** HTTP status when the error came from the API. */\n status?: number;\n /** Whether retrying the same command may succeed. Defaults from the exit code. */\n retry?: boolean;\n cause?: unknown;\n};\n\nexport class CliError extends Error {\n readonly code: string;\n readonly hint?: string;\n readonly exitCode: ExitCode;\n readonly requestId?: string;\n readonly status?: number;\n readonly retry: boolean;\n\n constructor(opts: CliErrorOptions) {\n super(opts.message, opts.cause === undefined ? undefined : { cause: opts.cause });\n this.name = 'CliError';\n this.code = opts.code;\n this.hint = opts.hint;\n this.exitCode = opts.exitCode;\n this.requestId = opts.requestId;\n this.status = opts.status;\n this.retry =\n opts.retry ??\n (opts.exitCode === ExitCode.Network ||\n opts.exitCode === ExitCode.Server ||\n opts.code.toUpperCase() === 'RATE_LIMIT_EXCEEDED');\n }\n\n /** Shape printed by `--json` error output. Never includes the cause. */\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n ...(this.hint ? { hint: this.hint } : {}),\n exitCode: this.exitCode,\n retry: this.retry,\n ...(this.requestId ? { requestId: this.requestId } : {}),\n ...(this.status ? { status: this.status } : {}),\n };\n }\n}\n\nexport function isCliError(value: unknown): value is CliError {\n return value instanceof CliError;\n}\n\nconst AUTH_CODES = new Set([\n 'UNAUTHORIZED',\n 'UNAUTHENTICATED',\n 'AUTH_REQUIRED',\n 'SESSION_REUSE_DETECTED',\n 'SESSION_EXPIRED',\n 'INVALID_TOKEN',\n 'TOKEN_EXPIRED',\n 'NOT_SIGNED_IN',\n]);\n\nconst FORBIDDEN_CODES = new Set([\n 'FORBIDDEN',\n 'MCP_SCOPE_FORBIDDEN',\n 'INSUFFICIENT_SCOPE',\n 'SUBSCRIPTION_ENTITLEMENT_DENIED',\n 'UPGRADE_REQUIRED',\n 'PAYMENT_REQUIRED',\n 'ENTITLEMENT_REQUIRED',\n 'QUOTA_EXCEEDED',\n]);\n\nconst USAGE_CODES = new Set(['VALIDATION_ERROR', 'BAD_REQUEST', 'INVALID_INPUT', 'USAGE']);\n\nconst APPROVAL_CODES = new Set(['APPROVAL_PENDING', 'APPROVAL_REQUIRED']);\n\nconst NETWORK_CODES = new Set(['NETWORK_ERROR', 'TIMEOUT', 'REQUEST_ABORTED']);\n\nconst INTERRUPT_CODES = new Set(['CANCELLED', 'INTERRUPTED']);\n\nconst SERVER_CODES = new Set([\n 'INTERNAL_ERROR',\n 'SERVICE_UNAVAILABLE',\n 'DATABASE_UNAVAILABLE',\n 'BAD_RESPONSE',\n 'MCP_INTEGRATION_NOT_READY',\n]);\n\n/** Maps an API/envelope error code (and optional HTTP status) to an exit code. */\nexport function exitCodeForErrorCode(code: string, status?: number): ExitCode {\n const normalized = code.trim().toUpperCase();\n if (AUTH_CODES.has(normalized)) return ExitCode.Auth;\n if (FORBIDDEN_CODES.has(normalized)) return ExitCode.Forbidden;\n if (normalized === 'NOT_FOUND' || normalized.endsWith('_NOT_FOUND')) return ExitCode.NotFound;\n if (USAGE_CODES.has(normalized)) return ExitCode.Usage;\n if (APPROVAL_CODES.has(normalized)) return ExitCode.ApprovalPending;\n if (NETWORK_CODES.has(normalized)) return ExitCode.Network;\n if (INTERRUPT_CODES.has(normalized)) return ExitCode.Interrupted;\n if (SERVER_CODES.has(normalized)) return ExitCode.Server;\n return status === undefined ? ExitCode.Error : exitCodeForStatus(status);\n}\n\nexport function exitCodeForStatus(status: number): ExitCode {\n if (status === 400 || status === 422) return ExitCode.Usage;\n if (status === 401) return ExitCode.Auth;\n if (status === 402 || status === 403) return ExitCode.Forbidden;\n if (status === 404) return ExitCode.NotFound;\n if (status >= 500) return ExitCode.Server;\n return ExitCode.Error;\n}\n\nfunction codeForStatus(status: number): string {\n switch (status) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED';\n case 402:\n return 'PAYMENT_REQUIRED';\n case 403:\n return 'FORBIDDEN';\n case 404:\n return 'NOT_FOUND';\n case 409:\n return 'CONFLICT';\n case 429:\n return 'RATE_LIMIT_EXCEEDED';\n default:\n return status >= 500 ? 'INTERNAL_ERROR' : `HTTP_${status}`;\n }\n}\n\nfunction hintForCode(code: string, exitCode: ExitCode): string | undefined {\n if (exitCode === ExitCode.Auth) return 'Run `tabbio login` to sign in again.';\n if (code === 'RATE_LIMIT_EXCEEDED') return 'Wait a minute and try again.';\n if (code === 'UPGRADE_REQUIRED' || code === 'PAYMENT_REQUIRED' || code === 'ENTITLEMENT_REQUIRED') {\n return 'This needs a higher Tabbio plan. Manage your plan in the Tabbio app.';\n }\n if (exitCode === ExitCode.Server) return 'Tabbio had a problem on its side. Try again shortly.';\n return undefined;\n}\n\n/** Builds a CliError from an envelope `error` object. */\nexport function cliErrorFromEnvelope(\n error: { code?: string | null; message?: string | null },\n opts: { status?: number; requestId?: string; hint?: string } = {},\n): CliError {\n const code = (error.code || (opts.status ? codeForStatus(opts.status) : 'ERROR')).trim();\n const exitCode = exitCodeForErrorCode(code, opts.status);\n return new CliError({\n code,\n message: error.message?.trim() || defaultMessageForCode(code),\n hint: opts.hint ?? hintForCode(code.toUpperCase(), exitCode),\n exitCode,\n requestId: opts.requestId,\n status: opts.status,\n });\n}\n\n/** Builds a CliError for a non-envelope HTTP failure. */\nexport function cliErrorFromStatus(\n status: number,\n opts: { message?: string; requestId?: string } = {},\n): CliError {\n return cliErrorFromEnvelope(\n { code: codeForStatus(status), message: opts.message ?? `Request failed with HTTP ${status}` },\n { status, requestId: opts.requestId },\n );\n}\n\nfunction defaultMessageForCode(code: string): string {\n switch (code.toUpperCase()) {\n case 'UNAUTHORIZED':\n return 'You are not signed in or your session expired';\n case 'FORBIDDEN':\n return 'You do not have access to do that';\n case 'NOT_FOUND':\n return 'Not found';\n default:\n return `Request failed (${code})`;\n }\n}\n\nexport function notSignedInError(profile: string): CliError {\n return new CliError({\n code: 'NOT_SIGNED_IN',\n message: `Not signed in (profile \"${profile}\")`,\n hint: 'Run `tabbio login` to sign in.',\n exitCode: ExitCode.Auth,\n });\n}\n\n/** For commands that need the app JWT when only a personal MCP token is present. */\nexport function needsFullSignInError(feature: string): CliError {\n return new CliError({\n code: 'FULL_SIGN_IN_REQUIRED',\n message: `${feature} needs a full sign-in; a personal MCP token only works for tool commands`,\n hint: 'Run `tabbio login` (browser) or `tabbio login --email you@example.com`.',\n exitCode: ExitCode.Auth,\n });\n}\n\nexport function interruptedError(message = 'Cancelled'): CliError {\n return new CliError({ code: 'CANCELLED', message, exitCode: ExitCode.Interrupted, retry: false });\n}\n\nexport function usageError(message: string, hint?: string): CliError {\n return new CliError({ code: 'USAGE', message, hint, exitCode: ExitCode.Usage });\n}\n\nexport function networkError(url: string, cause: unknown): CliError {\n const timedOut =\n cause instanceof Error && (cause.name === 'TimeoutError' || cause.name === 'AbortError');\n let host = url;\n try {\n host = new URL(url).host;\n } catch {\n // keep the raw value\n }\n return new CliError({\n code: timedOut ? 'TIMEOUT' : 'NETWORK_ERROR',\n message: timedOut ? `Timed out talking to ${host}` : `Could not reach ${host}`,\n hint: 'Check your connection, or the API URL with `tabbio status` / `tabbio doctor`.',\n exitCode: ExitCode.Network,\n cause,\n });\n}\n\n/** Normalizes anything thrown into a CliError. Unknown errors keep exit code 1. */\nexport function toCliError(value: unknown): CliError {\n if (value instanceof CliError) return value;\n if (value instanceof Error) {\n return new CliError({\n code: 'UNEXPECTED',\n message: value.message || 'Unexpected error',\n exitCode: ExitCode.Error,\n cause: value,\n });\n }\n return new CliError({ code: 'UNEXPECTED', message: String(value), exitCode: ExitCode.Error });\n}\n", "import { theme } from '../ui/theme';\n\n/**\n * Minimal printers for the account/config commands (WP-A). Rich output\n * (tables, --fields, result panels) lives in core/output.ts (WP-B).\n * stdout carries results; stderr carries progress, prompts and errors.\n */\n\nexport function writeOut(text = ''): void {\n process.stdout.write(`${text}\\n`);\n}\n\n/** `--json` output: pretty on a TTY, compact when piped. */\nexport function printJson(value: unknown): void {\n const pretty = Boolean(process.stdout.isTTY);\n process.stdout.write(`${JSON.stringify(value, null, pretty ? 2 : 0)}\\n`);\n}\n\nexport type KvRow = [label: string, value: string | number | boolean | null | undefined];\n\n/** Aligned `label value` lines; rows with empty values are skipped. */\nexport function formatKeyValues(rows: readonly KvRow[]): string[] {\n const visible = rows.filter(([, value]) => value !== undefined && value !== null && value !== '');\n const width = Math.max(0, ...visible.map(([label]) => label.length));\n return visible.map(([label, value]) => `${theme.dim(label.padEnd(width))} ${String(value)}`);\n}\n\nexport function printKeyValues(rows: readonly KvRow[]): void {\n for (const line of formatKeyValues(rows)) writeOut(line);\n}\n\nexport function successLine(message: string): string {\n return `${theme.success(theme.symbols.success)} ${message}`;\n}\n\nexport function failureLine(message: string): string {\n return `${theme.error(theme.symbols.error)} ${message}`;\n}\n\nexport function heading(text: string): string {\n return theme.bold(text);\n}\n\n/** \"3m ago\", \"2h ago\", \"in 20h\" style relative time. */\nexport function relativeTime(date: Date, now = Date.now()): string {\n const diff = date.getTime() - now;\n const abs = Math.abs(diff);\n const units: Array<[number, string]> = [\n [86_400_000, 'd'],\n [3_600_000, 'h'],\n [60_000, 'm'],\n [1_000, 's'],\n ];\n for (const [ms, unit] of units) {\n if (abs >= ms) {\n const value = Math.floor(abs / ms);\n return diff < 0 ? `${value}${unit} ago` : `in ${value}${unit}`;\n }\n }\n return 'just now';\n}\n", "import { homedir } from 'node:os';\nimport { isAbsolute, join } from 'node:path';\nimport { z } from 'zod';\nimport { CliError, ExitCode, usageError } from './errors';\nimport { readFileIfExists, writeFileAtomic } from './fs-atomic';\n\nexport const DEFAULT_PROFILE = 'default';\n/** The v2 API is served from server.tabbio.com until the api.tabbio.com cutover. */\nexport const PRODUCTION_API_URL = 'https://server.tabbio.com';\nexport const PRODUCTION_APP_URL = 'https://app.tabbio.com';\nexport const MCP_PATH = '/api/mcp';\n\n/** Built-in profile presets, used when the profile has no stored URLs. */\nexport const PROFILE_PRESETS: Record<string, { apiUrl: string; appUrl: string }> = {\n [DEFAULT_PROFILE]: { apiUrl: PRODUCTION_API_URL, appUrl: PRODUCTION_APP_URL },\n local: { apiUrl: 'http://localhost:3001', appUrl: 'http://localhost:8081' },\n};\n\nexport type Profile = { name: string; apiUrl: string; appUrl: string; mcpUrl: string };\n\nconst profileConfigSchema = z\n .object({\n apiUrl: z.string().optional(),\n appUrl: z.string().optional(),\n mcpUrl: z.string().optional(),\n })\n .passthrough();\n\nconst configSchema = z\n .object({\n version: z.literal(1).default(1),\n currentProfile: z.string().optional(),\n profiles: z.record(profileConfigSchema).default({}),\n /** Set to false to disable the once-a-day npm update check. */\n updateCheck: z.boolean().optional(),\n })\n .passthrough();\n\nexport type ProfileConfig = z.infer<typeof profileConfigSchema>;\nexport type Config = z.infer<typeof configSchema>;\n\nexport type ValueSource = 'flag' | 'env' | 'config' | 'preset' | 'default' | 'derived';\n\nexport type ResolvedProfile = {\n profile: Profile;\n sources: { name: ValueSource; apiUrl: ValueSource; appUrl: ValueSource; mcpUrl: ValueSource };\n};\n\nexport type ResolveProfileOptions = { profile?: string; apiUrl?: string; appUrl?: string };\n\nconst PROFILE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,31}$/;\n\nfunction env(name: string): string | undefined {\n const value = process.env[name]?.trim();\n return value ? value : undefined;\n}\n\nfunction absoluteEnvDir(name: string): string | undefined {\n const value = env(name);\n return value && isAbsolute(value) ? value : undefined;\n}\n\nexport function configPaths(): {\n dir: string;\n configFile: string;\n credentialsFile: string;\n cacheDir: string;\n} {\n const explicit = env('TABBIO_CONFIG_DIR');\n const dir = explicit ?? join(absoluteEnvDir('XDG_CONFIG_HOME') ?? join(homedir(), '.config'), 'tabbio');\n const cacheDir =\n env('TABBIO_CACHE_DIR') ??\n (explicit\n ? join(dir, 'cache')\n : join(absoluteEnvDir('XDG_CACHE_HOME') ?? join(homedir(), '.cache'), 'tabbio'));\n return {\n dir,\n configFile: join(dir, 'config.json'),\n credentialsFile: join(dir, 'credentials.json'),\n cacheDir,\n };\n}\n\nexport function emptyConfig(): Config {\n return { version: 1, profiles: {} };\n}\n\nexport function loadConfig(): Config {\n const { configFile } = configPaths();\n const raw = readFileIfExists(configFile);\n if (raw === null || raw.trim() === '') return emptyConfig();\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (error) {\n throw new CliError({\n code: 'CONFIG_INVALID',\n message: `Config file is not valid JSON: ${configFile}`,\n hint: 'Fix the file or delete it to start fresh.',\n exitCode: ExitCode.Usage,\n cause: error,\n });\n }\n const parsed = configSchema.safeParse(json);\n if (!parsed.success) {\n throw new CliError({\n code: 'CONFIG_INVALID',\n message: `Config file has an unexpected shape: ${configFile}`,\n hint: parsed.error.errors[0]?.message ?? 'Fix the file or delete it to start fresh.',\n exitCode: ExitCode.Usage,\n });\n }\n return parsed.data;\n}\n\nexport function saveConfig(c: Config): void {\n const { configFile } = configPaths();\n writeFileAtomic(configFile, `${JSON.stringify(configSchema.parse(c), null, 2)}\\n`);\n}\n\n/** Load, mutate, save. Returns the saved config. */\nexport function updateConfig(mutate: (c: Config) => void): Config {\n const config = loadConfig();\n mutate(config);\n saveConfig(config);\n return config;\n}\n\nexport function assertProfileName(name: string): string {\n const trimmed = name.trim();\n if (!PROFILE_NAME_PATTERN.test(trimmed)) {\n throw usageError(\n `Invalid profile name \"${name}\"`,\n 'Use 1-32 letters, digits, \"-\" or \"_\", starting with a letter or digit.',\n );\n }\n return trimmed;\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n const host = hostname.replace(/^\\[|\\]$/g, '').toLowerCase();\n return host === 'localhost' || host.endsWith('.localhost') || host === '::1' || /^127\\./.test(host);\n}\n\n/**\n * Validates and normalizes a base URL. Plain http is only allowed for loopback\n * hosts (tokens travel in headers), unless TABBIO_ALLOW_INSECURE_HTTP=1.\n */\nexport function normalizeBaseUrl(value: string, label: string): string {\n let url: URL;\n try {\n url = new URL(value.trim());\n } catch {\n throw usageError(`${label} is not a valid URL: ${value}`);\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw usageError(`${label} must use http or https: ${value}`);\n }\n if (url.username || url.password) {\n throw usageError(`${label} must not contain credentials`);\n }\n if (url.protocol === 'http:' && !isLoopbackHost(url.hostname) && env('TABBIO_ALLOW_INSECURE_HTTP') !== '1') {\n throw usageError(\n `${label} must use https for non-local hosts: ${value}`,\n 'Set TABBIO_ALLOW_INSECURE_HTTP=1 only for trusted development networks.',\n );\n }\n url.search = '';\n url.hash = '';\n return url.toString().replace(/\\/+$/, '');\n}\n\nexport function resolveProfileName(opts: { profile?: string } = {}, config?: Config): {\n name: string;\n source: ValueSource;\n} {\n if (opts.profile?.trim()) return { name: assertProfileName(opts.profile), source: 'flag' };\n const fromEnv = env('TABBIO_PROFILE');\n if (fromEnv) return { name: assertProfileName(fromEnv), source: 'env' };\n const current = (config ?? loadConfig()).currentProfile;\n if (current?.trim()) return { name: assertProfileName(current), source: 'config' };\n return { name: DEFAULT_PROFILE, source: 'default' };\n}\n\n/** Precedence for every value: flag > env > config file > preset/default. */\nexport function resolveProfileWithSources(opts: ResolveProfileOptions = {}): ResolvedProfile {\n const config = loadConfig();\n const { name, source: nameSource } = resolveProfileName(opts, config);\n const stored = config.profiles[name] ?? {};\n const preset = PROFILE_PRESETS[name] ?? PROFILE_PRESETS[DEFAULT_PROFILE]!;\n\n const pick = (\n flag: string | undefined,\n envName: string,\n fromConfig: string | undefined,\n fallback: string,\n ): [string, ValueSource] => {\n if (flag?.trim()) return [flag, 'flag'];\n const fromEnv = env(envName);\n if (fromEnv) return [fromEnv, 'env'];\n if (fromConfig?.trim()) return [fromConfig, 'config'];\n return [fallback, PROFILE_PRESETS[name] && name !== DEFAULT_PROFILE ? 'preset' : 'default'];\n };\n\n const [apiRaw, apiSource] = pick(opts.apiUrl, 'TABBIO_API_URL', stored.apiUrl, preset.apiUrl);\n const [appRaw, appSource] = pick(opts.appUrl, 'TABBIO_APP_URL', stored.appUrl, preset.appUrl);\n const apiUrl = normalizeBaseUrl(apiRaw, 'API URL');\n const appUrl = normalizeBaseUrl(appRaw, 'App URL');\n\n // A stored MCP URL belongs to the stored API URL; an overridden API URL wins.\n let mcpUrl = `${apiUrl}${MCP_PATH}`;\n let mcpSource: ValueSource = 'derived';\n const envMcp = env('TABBIO_MCP_URL');\n if (envMcp) {\n mcpUrl = normalizeBaseUrl(envMcp, 'MCP URL');\n mcpSource = 'env';\n } else if (stored.mcpUrl?.trim() && apiSource !== 'flag' && apiSource !== 'env') {\n mcpUrl = normalizeBaseUrl(stored.mcpUrl, 'MCP URL');\n mcpSource = 'config';\n }\n\n return {\n profile: { name, apiUrl, appUrl, mcpUrl },\n sources: { name: nameSource, apiUrl: apiSource, appUrl: appSource, mcpUrl: mcpSource },\n };\n}\n\nexport function resolveProfile(opts: ResolveProfileOptions = {}): Profile {\n return resolveProfileWithSources(opts).profile;\n}\n\n/** Names of every profile known to the config file plus the built-in presets. */\nexport function listProfileNames(config: Config = loadConfig()): string[] {\n return Array.from(new Set([...Object.keys(PROFILE_PRESETS), ...Object.keys(config.profiles)])).sort();\n}\n", "import { randomBytes } from 'node:crypto';\nimport {\n chmodSync,\n closeSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n unlinkSync,\n writeSync,\n} from 'node:fs';\nimport { dirname } from 'node:path';\n\nexport const PRIVATE_DIR_MODE = 0o700;\nexport const PRIVATE_FILE_MODE = 0o600;\n\nconst isWindows = process.platform === 'win32';\n\n/** Creates the directory (recursively) and tightens it to `mode` on POSIX. */\nexport function ensurePrivateDir(dir: string, mode = PRIVATE_DIR_MODE): void {\n mkdirSync(dir, { recursive: true, mode });\n if (!isWindows) {\n const current = statSync(dir).mode & 0o777;\n if (current !== mode) chmodSync(dir, mode);\n }\n}\n\n/**\n * Writes `content` to `file` atomically: a sibling temp file is written with\n * the final mode, fsynced, then renamed over the target. Readers never see a\n * half-written file and a crash never leaves a truncated credential store.\n */\nexport function writeFileAtomic(file: string, content: string, mode = PRIVATE_FILE_MODE): void {\n ensurePrivateDir(dirname(file));\n const tmp = `${file}.${process.pid}.${randomBytes(6).toString('hex')}.tmp`;\n let fd: number | undefined;\n try {\n fd = openSync(tmp, 'wx', mode);\n writeSync(fd, content);\n fsyncSync(fd);\n closeSync(fd);\n fd = undefined;\n if (!isWindows) chmodSync(tmp, mode);\n renameSync(tmp, file);\n } catch (error) {\n if (fd !== undefined) closeSync(fd);\n rmSync(tmp, { force: true });\n throw error;\n }\n}\n\nexport function readFileIfExists(file: string): string | null {\n try {\n return readFileSync(file, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw error;\n }\n}\n\n/** Returns the POSIX permission bits of a path, or null if it does not exist. */\nexport function permissionBits(path: string): number | null {\n if (!existsSync(path)) return null;\n return statSync(path).mode & 0o777;\n}\n\nconst LOCK_STALE_MS = 30_000;\nconst LOCK_WAIT_MS = 15_000;\n\nfunction sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Cross-process mutex built on an exclusive lock file. Used around token\n * refresh: two CLI processes refreshing the same rotating refresh token would\n * trip the server's reuse detection and revoke the whole session family.\n */\nexport async function withFileLock<T>(lockFile: string, fn: () => Promise<T>): Promise<T> {\n ensurePrivateDir(dirname(lockFile));\n const started = Date.now();\n let fd: number | undefined;\n while (fd === undefined) {\n try {\n fd = openSync(lockFile, 'wx', PRIVATE_FILE_MODE);\n writeSync(fd, String(process.pid));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n try {\n const age = Date.now() - statSync(lockFile).mtimeMs;\n if (age > LOCK_STALE_MS) {\n unlinkSync(lockFile);\n continue;\n }\n } catch {\n continue;\n }\n if (Date.now() - started > LOCK_WAIT_MS) {\n throw new Error(`Timed out waiting for ${lockFile}`);\n }\n await sleep(50 + Math.floor(Math.random() * 50));\n }\n }\n try {\n return await fn();\n } finally {\n closeSync(fd);\n rmSync(lockFile, { force: true });\n }\n}\n", "import { join } from 'node:path';\nimport { z } from 'zod';\nimport { configPaths } from './config';\nimport { CliError, ExitCode } from './errors';\nimport {\n PRIVATE_DIR_MODE,\n PRIVATE_FILE_MODE,\n permissionBits,\n readFileIfExists,\n withFileLock,\n writeFileAtomic,\n} from './fs-atomic';\n\nexport type CredentialUser = { id: string; email: string; name?: string | null };\n\nexport type Credentials = {\n profile: string;\n accessToken?: string;\n accessTokenExpiresAt?: string;\n refreshToken?: string;\n /** Personal MCP token from `login --token` / `--with-token` (MCP-only mode). */\n mcpToken?: string;\n user?: CredentialUser;\n /**\n * Where the live secrets came from. Env-provided secrets (TABBIO_TOKEN,\n * TABBIO_ACCESS_TOKEN) are never written to disk; saveCredentials strips them.\n */\n origin?: { accessToken?: 'env' | 'store'; mcpToken?: 'env' | 'store' };\n};\n\nconst storedCredentialsSchema = z\n .object({\n accessToken: z.string().optional(),\n accessTokenExpiresAt: z.string().optional(),\n refreshToken: z.string().optional(),\n mcpToken: z.string().optional(),\n user: z\n .object({ id: z.string(), email: z.string(), name: z.string().nullable().optional() })\n .optional(),\n savedAt: z.string().optional(),\n })\n .passthrough();\n\nconst credentialsFileSchema = z.object({\n version: z.literal(1).default(1),\n profiles: z.record(storedCredentialsSchema).default({}),\n});\n\ntype CredentialsFile = z.infer<typeof credentialsFileSchema>;\ntype StoredCredentials = z.infer<typeof storedCredentialsSchema>;\n\nfunction env(name: string): string | undefined {\n const value = process.env[name]?.trim();\n return value ? value : undefined;\n}\n\nfunction readStore(): CredentialsFile {\n const { credentialsFile } = configPaths();\n const raw = readFileIfExists(credentialsFile);\n if (raw === null || raw.trim() === '') return { version: 1, profiles: {} };\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (error) {\n throw new CliError({\n code: 'CREDENTIALS_INVALID',\n message: `Credential store is corrupted: ${credentialsFile}`,\n hint: 'Delete the file and run `tabbio login` again.',\n exitCode: ExitCode.Auth,\n cause: error,\n });\n }\n const parsed = credentialsFileSchema.safeParse(json);\n if (!parsed.success) {\n throw new CliError({\n code: 'CREDENTIALS_INVALID',\n message: `Credential store has an unexpected shape: ${credentialsFile}`,\n hint: 'Delete the file and run `tabbio login` again.',\n exitCode: ExitCode.Auth,\n });\n }\n return parsed.data;\n}\n\nfunction writeStore(store: CredentialsFile): void {\n const { credentialsFile } = configPaths();\n writeFileAtomic(credentialsFile, `${JSON.stringify(store, null, 2)}\\n`, PRIVATE_FILE_MODE);\n}\n\nfunction toCredentials(profile: string, stored: StoredCredentials): Credentials {\n return {\n profile,\n ...(stored.accessToken ? { accessToken: stored.accessToken } : {}),\n ...(stored.accessTokenExpiresAt ? { accessTokenExpiresAt: stored.accessTokenExpiresAt } : {}),\n ...(stored.refreshToken ? { refreshToken: stored.refreshToken } : {}),\n ...(stored.mcpToken ? { mcpToken: stored.mcpToken } : {}),\n ...(stored.user ? { user: stored.user } : {}),\n };\n}\n\n/** Credentials exactly as stored on disk, ignoring env overrides. */\nexport function loadStoredCredentials(profile: string): Credentials | null {\n const stored = readStore().profiles[profile];\n if (!stored) return null;\n const creds = toCredentials(profile, stored);\n creds.origin = {\n ...(creds.accessToken ? { accessToken: 'store' as const } : {}),\n ...(creds.mcpToken ? { mcpToken: 'store' as const } : {}),\n };\n return creds;\n}\n\n/**\n * Stored credentials merged with env overrides. `TABBIO_TOKEN` (MCP token) and\n * `TABBIO_ACCESS_TOKEN` (app JWT) win over the store and never reach disk.\n */\nexport function loadCredentials(profile: string): Credentials | null {\n const stored = loadStoredCredentials(profile);\n const envMcp = env('TABBIO_TOKEN');\n const envAccess = env('TABBIO_ACCESS_TOKEN');\n if (!stored && !envMcp && !envAccess) return null;\n\n const creds: Credentials = stored ?? { profile, origin: {} };\n creds.origin = { ...creds.origin };\n if (envMcp) {\n creds.mcpToken = envMcp;\n creds.origin.mcpToken = 'env';\n }\n if (envAccess) {\n creds.accessToken = envAccess;\n // An env JWT has no known expiry and no refresh token of its own.\n delete creds.accessTokenExpiresAt;\n delete creds.refreshToken;\n creds.origin.accessToken = 'env';\n }\n return creds;\n}\n\nexport function saveCredentials(c: Credentials): void {\n const store = readStore();\n const next: StoredCredentials = { savedAt: new Date().toISOString() };\n const envMcp = env('TABBIO_TOKEN');\n const envAccess = env('TABBIO_ACCESS_TOKEN');\n const accessFromEnv = c.origin?.accessToken === 'env' || (envAccess && c.accessToken === envAccess);\n const mcpFromEnv = c.origin?.mcpToken === 'env' || (envMcp && c.mcpToken === envMcp);\n\n if (c.accessToken && !accessFromEnv) {\n next.accessToken = c.accessToken;\n if (c.accessTokenExpiresAt) next.accessTokenExpiresAt = c.accessTokenExpiresAt;\n }\n if (c.refreshToken) next.refreshToken = c.refreshToken;\n if (c.mcpToken && !mcpFromEnv) next.mcpToken = c.mcpToken;\n if (c.user) next.user = { id: c.user.id, email: c.user.email, name: c.user.name ?? null };\n\n // Keep what we cannot represent (e.g. a stored token hidden by an env override).\n const previous = store.profiles[c.profile];\n if (previous && accessFromEnv && previous.accessToken && !next.accessToken) {\n next.accessToken = previous.accessToken;\n if (previous.accessTokenExpiresAt) next.accessTokenExpiresAt = previous.accessTokenExpiresAt;\n if (!next.refreshToken && previous.refreshToken) next.refreshToken = previous.refreshToken;\n }\n if (previous && mcpFromEnv && previous.mcpToken && !next.mcpToken) next.mcpToken = previous.mcpToken;\n\n store.profiles[c.profile] = next;\n writeStore(store);\n}\n\nexport function clearCredentials(profile: string): void {\n const store = readStore();\n if (!(profile in store.profiles)) return;\n delete store.profiles[profile];\n writeStore(store);\n}\n\nexport function listCredentialProfiles(): string[] {\n return Object.keys(readStore().profiles).sort();\n}\n\n/** Serializes refreshes across CLI processes (see withFileLock). */\nexport function withCredentialsLock<T>(fn: () => Promise<T>): Promise<T> {\n return withFileLock(join(configPaths().dir, 'credentials.lock'), fn);\n}\n\n/** Loose permission check for `tabbio doctor`; returns human-readable issues. */\nexport function credentialPermissionIssues(): string[] {\n if (process.platform === 'win32') return [];\n const { dir, credentialsFile } = configPaths();\n const issues: string[] = [];\n const dirBits = permissionBits(dir);\n if (dirBits !== null && (dirBits & 0o077) !== 0) {\n issues.push(`${dir} is mode ${dirBits.toString(8)} (expected ${PRIVATE_DIR_MODE.toString(8)})`);\n }\n const fileBits = permissionBits(credentialsFile);\n if (fileBits !== null && (fileBits & 0o077) !== 0) {\n issues.push(\n `${credentialsFile} is mode ${fileBits.toString(8)} (expected ${PRIVATE_FILE_MODE.toString(8)})`,\n );\n }\n return issues;\n}\n\nconst KNOWN_PREFIXES = ['tabbio_mcp_'];\n\n/**\n * A display-safe fingerprint: known prefix (or first 3 chars) + last 4 chars,\n * e.g. `tabbio_mcp_\u2026a1b2`. Short secrets reveal nothing.\n */\nexport function fingerprint(secret: string): string {\n const value = secret.trim();\n if (value.length < 16) return '\u2026';\n const prefix = KNOWN_PREFIXES.find((p) => value.startsWith(p)) ?? value.slice(0, 3);\n return `${prefix}\u2026${value.slice(-4)}`;\n}\n\nconst SECRET_JSON_KEYS =\n /(\"(?:accessToken|refreshToken|token|secret|mcpToken|otp|code|password|cookie|authorization)\"\\s*:\\s*\")([^\"]*)(\")/gi;\n\n/** Removes anything that looks like a credential from free text (logs, errors). */\nexport function redactSecrets(text: string): string {\n return text\n .replace(/(Bearer\\s+)[A-Za-z0-9._~+/=-]+/gi, '$1[redacted]')\n .replace(/tabbio_mcp_[A-Za-z0-9_-]+/g, 'tabbio_mcp_[redacted]')\n .replace(/eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g, '[redacted-jwt]')\n .replace(SECRET_JSON_KEYS, '$1[redacted]$3')\n .replace(/((?:^|[?&;\\s])(?:code|state|token|refreshToken|otp)=)[^&\\s;]+/gi, '$1[redacted]')\n .replace(/((?:__Secure-|__Host-)?better-auth\\.[a-z_]+=)[^;\\s]+/gi, '$1[redacted]');\n}\n\n/** Redacts a URL's sensitive query parameters for debug output. */\nexport function redactUrl(url: string): string {\n try {\n const parsed = new URL(url);\n for (const key of Array.from(parsed.searchParams.keys())) {\n if (/code|state|token|otp|secret/i.test(key)) parsed.searchParams.set(key, '[redacted]');\n }\n return parsed.toString();\n } catch {\n return redactSecrets(url);\n }\n}\n", "import { hostname } from 'node:os';\nimport { redactSecrets } from './credentials';\nimport { theme } from '../ui/theme';\n\n/**\n * Process-wide options set once from the global flags. Lower layers (http,\n * mcp) read `debug` from here so the flag does not have to be threaded\n * through every call.\n */\nexport type GlobalOptions = {\n profile?: string;\n apiUrl?: string;\n appUrl?: string;\n json: boolean;\n color: boolean;\n debug: boolean;\n yes: boolean;\n quiet: boolean;\n};\n\nconst DEFAULT_GLOBALS: GlobalOptions = {\n json: false,\n color: true,\n debug: false,\n yes: false,\n quiet: false,\n};\n\nlet globals: GlobalOptions = { ...DEFAULT_GLOBALS, debug: process.env.TABBIO_DEBUG === '1' };\n\nexport function setGlobalOptions(partial: Partial<GlobalOptions>): GlobalOptions {\n globals = { ...globals, ...partial };\n return globals;\n}\n\nexport function getGlobalOptions(): GlobalOptions {\n return globals;\n}\n\nexport function resetGlobalOptions(): void {\n globals = { ...DEFAULT_GLOBALS };\n}\n\n/** True when both stdin and stdout are terminals and we are not in CI. */\nexport function isInteractive(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY) && !process.env.CI;\n}\n\n/** Hostname as sent in `x-tabbio-device-label`: printable ASCII, max 64 chars. */\nexport function deviceLabel(): string {\n const raw = process.env.TABBIO_DEVICE_LABEL?.trim() || hostname() || 'unknown-host';\n const clean = raw\n .replace(/\\.local$/i, '')\n .replace(/[^\\x20-\\x7E]/g, '')\n .trim();\n return (clean || 'unknown-host').slice(0, 64);\n}\n\n/** Debug trace to stderr. Always redacted; never prints bodies. */\nexport function debug(message: string): void {\n if (!globals.debug) return;\n process.stderr.write(`${theme.dim(`[debug] ${redactSecrets(message)}`)}\\n`);\n}\n\n/** Progress/info lines go to stderr so stdout stays parseable. */\nexport function info(message: string): void {\n if (globals.quiet) return;\n process.stderr.write(`${message}\\n`);\n}\n\nexport function warn(message: string, hint?: string): void {\n process.stderr.write(`${theme.warn(`${theme.symbols.warning} ${message}`)}\\n`);\n if (hint) process.stderr.write(` ${theme.dim(hint)}\\n`);\n}\n", "import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { configPaths, loadConfig } from './config';\nimport { readFileIfExists, writeFileAtomic } from './fs-atomic';\n\nfunction readPackageField(field: 'version' | 'name'): string | undefined {\n // Dev (tsx) path only: tsup replaces the constants below at build time.\n try {\n const pkg = JSON.parse(\n readFileSync(new URL('../../package.json', import.meta.url), 'utf8'),\n ) as Record<string, unknown>;\n const value = pkg[field];\n return typeof value === 'string' ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport const CLI_VERSION: string =\n typeof __TABBIO_CLI_VERSION__ !== 'undefined'\n ? __TABBIO_CLI_VERSION__\n : (readPackageField('version') ?? '0.0.0-dev');\n\nexport const CLI_PACKAGE_NAME: string =\n typeof __TABBIO_CLI_NAME__ !== 'undefined'\n ? __TABBIO_CLI_NAME__\n : (readPackageField('name') ?? '@tabbio-technologies/cli');\n\nexport function userAgent(): string {\n return `tabbio-cli/${CLI_VERSION} node/${process.versions.node} ${process.platform}-${process.arch}`;\n}\n\n/** Compares x.y.z versions numerically; a prerelease sorts before its release. */\nexport function compareVersions(a: string, b: string): number {\n const parse = (v: string) => {\n const [core = '', pre] = v.trim().replace(/^v/, '').split('-', 2);\n const nums = core.split('.').map((n) => Number.parseInt(n, 10) || 0);\n return { nums: [nums[0] ?? 0, nums[1] ?? 0, nums[2] ?? 0], pre };\n };\n const left = parse(a);\n const right = parse(b);\n for (let i = 0; i < 3; i += 1) {\n const diff = (left.nums[i] ?? 0) - (right.nums[i] ?? 0);\n if (diff !== 0) return diff > 0 ? 1 : -1;\n }\n if (left.pre && !right.pre) return -1;\n if (!left.pre && right.pre) return 1;\n return 0;\n}\n\nconst UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1000;\nconst UPDATE_CHECK_TIMEOUT_MS = 1_000;\n\ntype UpdateCache = { checkedAt: string; latest: string | null };\n\nexport function updateChecksDisabled(): boolean {\n if (process.env.TABBIO_NO_UPDATE_CHECK || process.env.CI) return true;\n if (!process.stderr.isTTY) return true;\n try {\n return loadConfig().updateCheck === false;\n } catch {\n return true;\n }\n}\n\nfunction cacheFile(): string {\n return join(configPaths().cacheDir, 'update-check.json');\n}\n\nfunction readUpdateCache(): UpdateCache | null {\n try {\n const raw = readFileIfExists(cacheFile());\n return raw ? (JSON.parse(raw) as UpdateCache) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Returns the newer published version, if any. Hits the npm registry at most\n * once a day (1s budget) and never throws.\n */\nexport async function checkForUpdate(\n opts: { fetch?: typeof fetch; now?: number } = {},\n): Promise<string | null> {\n if (updateChecksDisabled()) return null;\n const now = opts.now ?? Date.now();\n let cache = readUpdateCache();\n const stale = !cache || now - Date.parse(cache.checkedAt) > UPDATE_CHECK_TTL_MS;\n if (stale) {\n let latest: string | null = null;\n try {\n const response = await (opts.fetch ?? fetch)(\n `https://registry.npmjs.org/${CLI_PACKAGE_NAME}/latest`,\n { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS), headers: { accept: 'application/json' } },\n );\n if (response.ok) {\n const body = (await response.json()) as { version?: unknown };\n latest = typeof body.version === 'string' ? body.version : null;\n }\n } catch {\n latest = cache?.latest ?? null;\n }\n cache = { checkedAt: new Date(now).toISOString(), latest };\n try {\n writeFileAtomic(cacheFile(), JSON.stringify(cache), 0o600);\n } catch {\n // A read-only cache dir must never break a command.\n }\n }\n const latest = cache?.latest;\n return latest && compareVersions(latest, CLI_VERSION) > 0 ? latest : null;\n}\n", "import { createHash } from 'node:crypto';\nimport { readdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport type { CallToolRequest, CallToolResult, Tool } from '@modelcontextprotocol/sdk/types.js';\nimport { type Profile, configPaths } from './config';\nimport { type Credentials, fingerprint, redactUrl } from './credentials';\nimport { buildCatalog, findTool, type CatalogTool, type RawMcpTool } from './catalog';\nimport { CliError, ExitCode, needsFullSignInError, notSignedInError } from './errors';\nimport { ApiClient, baseHeaders, readRequestId } from './http';\nimport { readFileIfExists, writeFileAtomic } from './fs-atomic';\nimport { interpretToolResult, mapMcpTransportError, type ToolCallResult } from './mcp-results';\nimport { debug } from './runtime';\nimport { CLI_VERSION } from './version';\n\nexport type { CatalogTool, JsonSchema } from './catalog';\nexport type { ApprovalInfo, ToolCallResult } from './mcp-results';\nexport { detectApproval, interpretToolPayload, interpretToolResult } from './mcp-results';\n\n/** Catalog cache lifetime. `--refresh` bypasses it. */\nexport const CATALOG_TTL_MS = 60 * 60 * 1000;\nconst TOOL_TIMEOUT_MS = 2 * 60 * 1000;\nconst LONG_TOOL_TIMEOUT_MS = 10 * 60 * 1000;\n\n/**\n * Which credential authenticates MCP calls. `app-session` is the app JWT\n * (the API accepts it on /api/mcp like an OAuth access token); `personal-token`\n * is a `tabbio_mcp_\u2026` token from TABBIO_TOKEN or `login --token`.\n */\nexport type McpCredentialKind = 'app-session' | 'personal-token';\n\nexport type McpBearer = {\n kind: McpCredentialKind;\n source: 'env' | 'store';\n /** Display-safe fingerprint (`tabbio_mcp_\u2026a1b2`, `eyJ\u20269xYz`). */\n fingerprint: string;\n /** Stable cache identity: kind + user id (sessions) or token hash (tokens). */\n cacheIdentity: string;\n};\n\ntype CatalogCacheFile = { version: 1; fetchedAt: string; mcpUrl: string; kind: McpCredentialKind; tools: RawMcpTool[] };\n\nexport type McpConnectOptions = {\n /** Share refresh state with the command's ApiClient (recommended). */\n api?: ApiClient;\n /** Inject for tests. */\n fetch?: typeof fetch;\n clientName?: string;\n};\n\nexport type CallToolOptions = {\n /** Defaults: 2 min for tools, 10 min for workflows and the agent. */\n timeoutMs?: number;\n signal?: AbortSignal;\n onProgress?: (progress: { progress: number; total?: number; message?: string }) => void;\n};\n\nfunction sha(value: string, length = 16): string {\n return createHash('sha256').update(value).digest('hex').slice(0, length);\n}\n\n/**\n * Bearer precedence (coordinator decision 2026-09-25):\n * TABBIO_TOKEN \u2192 TABBIO_ACCESS_TOKEN \u2192 stored app session \u2192 stored personal token.\n */\nexport function selectMcpBearer(creds: Credentials | null): (McpBearer & { token: string }) | null {\n if (!creds) return null;\n const personal = (token: string, source: 'env' | 'store') => ({\n kind: 'personal-token' as const,\n source,\n token,\n fingerprint: fingerprint(token),\n cacheIdentity: `personal-token:${sha(token)}`,\n });\n const session = (token: string, source: 'env' | 'store') => ({\n kind: 'app-session' as const,\n source,\n token,\n fingerprint: fingerprint(token),\n // The JWT rotates daily; the user id keeps the cache stable across refreshes.\n cacheIdentity: `app-session:${creds.user?.id && source === 'store' ? creds.user.id : sha(token)}`,\n });\n if (creds.mcpToken && creds.origin?.mcpToken === 'env') return personal(creds.mcpToken, 'env');\n if (creds.accessToken && creds.origin?.accessToken === 'env') return session(creds.accessToken, 'env');\n if (creds.accessToken) return session(creds.accessToken, 'store');\n if (creds.mcpToken) return personal(creds.mcpToken, 'store');\n return null;\n}\n\n/** Public (token-free) description of the bearer, for status/doctor output. */\nexport function describeMcpBearer(creds: Credentials | null): McpBearer | null {\n const bearer = selectMcpBearer(creds);\n if (!bearer) return null;\n const { token: _token, ...rest } = bearer;\n return rest;\n}\n\nfunction cachePrefix(profile: Profile): string {\n return `catalog-${profile.name}-`;\n}\n\nfunction catalogCacheFile(profile: Profile, identity: string): string {\n return join(configPaths().cacheDir, `${cachePrefix(profile)}${sha(`${profile.mcpUrl}\\n${identity}`)}.json`);\n}\n\n/** Path of the on-disk catalog cache for a profile + active credential. */\nexport function catalogCachePath(profile: Profile, creds: Credentials | null): string | null {\n const bearer = selectMcpBearer(creds);\n return bearer ? catalogCacheFile(profile, bearer.cacheIdentity) : null;\n}\n\nfunction readCatalogCache(file: string): CatalogCacheFile | null {\n try {\n const raw = readFileIfExists(file);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as CatalogCacheFile;\n return parsed?.version === 1 && Array.isArray(parsed.tools) ? parsed : null;\n } catch {\n return null;\n }\n}\n\n/** Cached catalog without any network call (for `status` and offline help). */\nexport function readCachedCatalog(\n profile: Profile,\n creds: Credentials | null,\n): { fetchedAt: Date; tools: CatalogTool[]; ageMs: number; fresh: boolean; kind: McpCredentialKind } | null {\n const file = catalogCachePath(profile, creds);\n const cache = file ? readCatalogCache(file) : null;\n if (!cache) return null;\n const fetchedAt = new Date(cache.fetchedAt);\n const ageMs = Date.now() - fetchedAt.getTime();\n return { fetchedAt, tools: buildCatalog(cache.tools), ageMs, fresh: ageMs < CATALOG_TTL_MS, kind: cache.kind };\n}\n\n/** Removes cached catalogs for a profile, optionally keeping one file name. */\nexport function clearCatalogCache(profile: Profile, keep?: string): void {\n const { cacheDir } = configPaths();\n try {\n for (const file of readdirSync(cacheDir)) {\n if (file.startsWith(cachePrefix(profile)) && file !== keep) rmSync(join(cacheDir, file), { force: true });\n }\n } catch {\n // no cache dir yet\n }\n}\n\n/** Short JSON-RPC summary for --debug (method + tool name, never arguments). */\nfunction describeRpcBody(body: unknown): string {\n if (typeof body !== 'string') return '';\n try {\n const message = JSON.parse(body) as { method?: string; params?: { name?: string } };\n return [message.method, message.params?.name].filter(Boolean).join(' ');\n } catch {\n return '';\n }\n}\n\n/**\n * fetch wrapper for the MCP transport: sets the bearer on every request (so a\n * refreshed JWT is picked up by long-lived sessions such as `mcp serve`) and,\n * for the app session, refreshes once and replays the request on HTTP 401.\n * Replaying is safe: /api/mcp is stateless and a 401 means nothing ran.\n */\nfunction authedFetch(\n inner: typeof fetch,\n getToken: () => Promise<string>,\n refresh: (() => Promise<string>) | null,\n): typeof fetch {\n return async (input, init) => {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n const method = (init?.method ?? 'GET').toUpperCase();\n const send = async (token: string) => {\n const headers = new Headers(init?.headers);\n headers.set('authorization', `Bearer ${token}`);\n const started = Date.now();\n debug(`\u2192 ${method} ${redactUrl(url)} ${describeRpcBody(init?.body)}`.trimEnd());\n const response = await inner(input, { ...init, headers });\n const requestId = readRequestId(response.headers);\n debug(`\u2190 ${response.status} ${method} ${redactUrl(url)} ${Date.now() - started}ms${requestId ? ` req=${requestId}` : ''}`);\n return response;\n };\n\n const response = await send(await getToken());\n if (response.status !== 401 || !refresh) return response;\n await response.body?.cancel().catch(() => undefined);\n debug('MCP returned 401 for the app session; refreshing once');\n return send(await refresh());\n };\n}\n\n/**\n * A connection to the remote Tabbio MCP server (stateless streamable HTTP at\n * `/api/mcp`). Tool-level failures come back as `{ ok: false, error }` from\n * callTool(); transport, auth and network failures are thrown as CliError.\n */\nexport class McpSession {\n private catalog: CatalogTool[] | null = null;\n private rawTools: RawMcpTool[] | null = null;\n\n private constructor(\n readonly profile: Profile,\n readonly bearer: McpBearer,\n readonly client: Client,\n ) {}\n\n static async connect(profile: Profile, creds: Credentials | null, opts: McpConnectOptions = {}): Promise<McpSession> {\n const selected = selectMcpBearer(creds);\n if (!selected) throw notSignedInError(profile.name);\n const { token: initialToken, ...bearer } = selected;\n\n let getToken: () => Promise<string> = async () => initialToken;\n let refresh: (() => Promise<string>) | null = null;\n if (bearer.kind === 'app-session') {\n const api = opts.api ?? new ApiClient(profile, creds, { fetch: opts.fetch });\n // ensureAccessToken refreshes proactively within 5 min of expiry.\n getToken = () => api.ensureAccessToken();\n if (api.credentials?.refreshToken) refresh = () => api.refresh();\n }\n\n const transport = new StreamableHTTPClientTransport(new URL(profile.mcpUrl), {\n requestInit: { headers: baseHeaders() },\n fetch: authedFetch(opts.fetch ?? ((...args) => fetch(...args)), getToken, refresh),\n });\n const client = new Client({ name: opts.clientName ?? 'tabbio-cli', version: CLI_VERSION }, { capabilities: {} });\n try {\n await client.connect(transport);\n } catch (error) {\n await client.close().catch(() => undefined);\n throw mapMcpTransportError(error, { mcpUrl: profile.mcpUrl, profile: profile.name, kind: bearer.kind });\n }\n return new McpSession(profile, bearer, client);\n }\n\n /** Server-provided instructions (forwarded by `mcp serve`). */\n get instructions(): string | undefined {\n return this.client.getInstructions();\n }\n\n get serverVersion(): { name: string; version: string } | undefined {\n return this.client.getServerVersion();\n }\n\n /** Raw MCP tools, from the 1h on-disk cache unless `refresh` is set. */\n async listRawTools(opts: { refresh?: boolean } = {}): Promise<RawMcpTool[]> {\n if (this.rawTools && !opts.refresh) return this.rawTools;\n const file = catalogCacheFile(this.profile, this.bearer.cacheIdentity);\n if (!opts.refresh) {\n const cache = readCatalogCache(file);\n if (cache && cache.mcpUrl === this.profile.mcpUrl && Date.now() - Date.parse(cache.fetchedAt) < CATALOG_TTL_MS) {\n debug(`catalog cache hit (${cache.tools.length} tools)`);\n this.rawTools = cache.tools;\n return cache.tools;\n }\n }\n\n const tools: RawMcpTool[] = [];\n let cursor: string | undefined;\n try {\n do {\n const page = await this.client.listTools(cursor ? { cursor } : {});\n tools.push(...(page.tools as RawMcpTool[]));\n cursor = page.nextCursor;\n } while (cursor);\n } catch (error) {\n throw this.mapError(error);\n }\n\n this.rawTools = tools;\n this.catalog = null;\n try {\n const cache: CatalogCacheFile = {\n version: 1,\n fetchedAt: new Date().toISOString(),\n mcpUrl: this.profile.mcpUrl,\n kind: this.bearer.kind,\n tools,\n };\n writeFileAtomic(file, JSON.stringify(cache));\n clearCatalogCache(this.profile, file.split(/[\\\\/]/).pop());\n } catch (error) {\n debug(`could not write catalog cache: ${(error as Error).message}`);\n }\n return tools;\n }\n\n async listTools(opts: { refresh?: boolean } = {}): Promise<CatalogTool[]> {\n if (this.catalog && !opts.refresh) return this.catalog;\n this.catalog = buildCatalog(await this.listRawTools(opts));\n return this.catalog;\n }\n\n /** Resolves any accepted tool reference (id, MCP name, command path). */\n async resolveTool(ref: string): Promise<CatalogTool | undefined> {\n return findTool(await this.listTools(), ref);\n }\n\n /**\n * Calls a tool by id (`cv.list`), MCP name or command path. Approval-gated\n * tools return `{ ok: true, approval }` instead of executing.\n */\n async callTool(id: string, input: Record<string, unknown>, opts: CallToolOptions = {}): Promise<ToolCallResult> {\n const tool = await this.resolveTool(id);\n if (!tool) {\n return {\n ok: false,\n error: new CliError({\n code: 'UNKNOWN_TOOL',\n message: `Unknown tool: ${id}`,\n hint: 'Run `tabbio tools` to list tools, or `tabbio tools --refresh` to reload the catalog.',\n exitCode: ExitCode.NotFound,\n }),\n };\n }\n const long = tool.kind !== 'tool';\n const result = await this.callRaw(\n { name: tool.mcpName, arguments: input },\n { ...opts, timeoutMs: opts.timeoutMs ?? (long ? LONG_TOOL_TIMEOUT_MS : TOOL_TIMEOUT_MS) },\n );\n return interpretToolResult(result, tool.id);\n }\n\n /** Raw `tools/call` passthrough (used by the stdio bridge). Throws CliError on transport failure. */\n async callRaw(params: CallToolRequest['params'], opts: CallToolOptions = {}): Promise<CallToolResult> {\n try {\n const result = await this.client.callTool(params, undefined, {\n timeout: opts.timeoutMs ?? TOOL_TIMEOUT_MS,\n resetTimeoutOnProgress: true,\n ...(opts.signal ? { signal: opts.signal } : {}),\n ...(opts.onProgress ? { onprogress: opts.onProgress } : {}),\n });\n return result as CallToolResult;\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async close(): Promise<void> {\n await this.client.close().catch(() => undefined);\n }\n\n private mapError(error: unknown): CliError {\n return mapMcpTransportError(error, { mcpUrl: this.profile.mcpUrl, profile: this.profile.name, kind: this.bearer.kind });\n }\n}\n\n/** For commands that need the app JWT (chat, approvals): fail clearly on MCP-only profiles. */\nexport function assertJwtSession(creds: Credentials | null, profile: Profile, feature: string): void {\n if (creds?.accessToken) return;\n if (creds?.mcpToken) throw needsFullSignInError(feature);\n throw notSignedInError(profile.name);\n}\n\nexport type { Tool as McpTool };\n", "/**\n * Normalizes the MCP `tools/list` payload into the CLI's command catalog.\n *\n * Mapping (contract, see plan section 5):\n * cv.list \u2192 cv list\n * careerHighlight.upsert \u2192 career-highlight upsert\n * publicProfile.builderGet \u2192 public-profile builder-get\n * run_tailoredCvFlow \u2192 workflows run tailored-cv-flow\n * ask_tabbio \u2192 ask\n * publishArtifact \u2192 site publish (COMMAND_PATH_OVERRIDES)\n * mcp.approvalStatus \u2192 hidden (surfaced through `tabbio approvals`)\n */\n\n/** JSON Schema subset as produced by Mastra's zod \u2192 JSON Schema conversion. */\nexport type JsonSchema = {\n type?: string | string[];\n title?: string;\n description?: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n items?: JsonSchema | JsonSchema[];\n enum?: unknown[];\n const?: unknown;\n default?: unknown;\n format?: string;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n additionalProperties?: boolean | JsonSchema;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n nullable?: boolean;\n [key: string]: unknown;\n};\n\nexport type CatalogKind = 'tool' | 'workflow' | 'agent';\n\nexport type CatalogTool = {\n /** Canonical id: `_meta.tabbioToolId` (e.g. `cv.list`), else the MCP name. */\n id: string;\n /** Name to send in `tools/call` (e.g. `cvList`, `run_tailoredCvFlow`). */\n mcpName: string;\n title: string;\n description: string;\n readOnly: boolean;\n inputSchema: JsonSchema;\n kind: CatalogKind;\n /** Kebab-cased first segment (`career-highlight`); `workflows` / `ask` for those kinds. */\n group: string;\n /** Kebab-cased remainder (`upsert`, `builder-get`, `tailored-cv-flow`); '' for `ask`. */\n action: string;\n /** Full command path under `tabbio` (e.g. ['workflows', 'run', 'tailored-cv-flow']). */\n commandPath: string[];\n /** Not offered as a generated command (e.g. `mcp.approvalStatus`). */\n hidden: boolean;\n /** Raw MCP annotations (title, readOnlyHint, destructiveHint, \u2026). */\n annotations: Record<string, unknown>;\n /** Workflow or agent key for `run_<key>` / `ask_<key>` tools. */\n key?: string;\n};\n\n/** Raw MCP tool as returned by `tools/list`. */\nexport type RawMcpTool = {\n name: string;\n title?: string;\n description?: string;\n inputSchema?: unknown;\n outputSchema?: unknown;\n annotations?: Record<string, unknown> | null;\n _meta?: Record<string, unknown> | null;\n [key: string]: unknown;\n};\n\n/** Ids hidden from generated commands because a static command owns them. */\nexport const HIDDEN_TOOL_IDS = new Set(['mcp.approvalStatus']);\n\n/**\n * Tools whose id has no `scope.` prefix but belong in a group. PR #512's\n * publishing tools use their stream names as ids (`publishArtifact`), which\n * would otherwise land in `misc`.\n */\nexport const COMMAND_PATH_OVERRIDES: Readonly<Record<string, readonly [string, string]>> = {\n publishArtifact: ['site', 'publish'],\n unpublishArtifact: ['site', 'unpublish'],\n};\n\n/** The agent whose `ask_<key>` tool becomes plain `tabbio ask`. */\nexport const PRIMARY_AGENT_KEY = 'tabbio';\n\n/** camelCase / PascalCase / snake_case \u2192 kebab-case. */\nexport function kebabCase(value: string): string {\n return value\n .trim()\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .replace(/[\\s_.]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase();\n}\n\nfunction readString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\nfunction toSchema(value: unknown): JsonSchema {\n if (value && typeof value === 'object' && !Array.isArray(value)) return value as JsonSchema;\n return { type: 'object', properties: {} };\n}\n\n/** Command placement for an id / MCP name, without the rest of the metadata. */\nexport function commandPathFor(\n id: string,\n mcpName: string = id,\n): { kind: CatalogKind; group: string; action: string; commandPath: string[]; key?: string } {\n const agent = /^ask_(.+)$/.exec(mcpName);\n if (agent?.[1]) {\n const key = agent[1];\n if (key === PRIMARY_AGENT_KEY) {\n return { kind: 'agent', group: 'ask', action: '', commandPath: ['ask'], key };\n }\n const action = kebabCase(key);\n return { kind: 'agent', group: 'ask', action, commandPath: ['ask', action], key };\n }\n\n const workflow = /^run_(.+)$/.exec(mcpName);\n if (workflow?.[1]) {\n const key = workflow[1];\n const action = kebabCase(key);\n return {\n kind: 'workflow',\n group: 'workflows',\n action,\n commandPath: ['workflows', 'run', action],\n key,\n };\n }\n\n const override = COMMAND_PATH_OVERRIDES[id];\n if (override) {\n const [group, action] = override;\n return { kind: 'tool', group, action, commandPath: [group, action] };\n }\n\n const segments = id.split('.').filter(Boolean);\n if (segments.length >= 2) {\n const group = kebabCase(segments[0] as string);\n const action = segments.slice(1).map(kebabCase).join('-');\n return { kind: 'tool', group, action, commandPath: [group, action] };\n }\n\n const action = kebabCase(id);\n return { kind: 'tool', group: 'misc', action, commandPath: ['misc', action] };\n}\n\nexport function normalizeTool(raw: RawMcpTool): CatalogTool {\n const meta = raw._meta ?? {};\n const annotations = raw.annotations ?? {};\n const mcpName = raw.name;\n const id = readString(meta.tabbioToolId) ?? mcpName;\n const placement = commandPathFor(id, mcpName);\n const title =\n readString(annotations.title) ??\n readString(raw.title) ??\n (placement.kind === 'workflow'\n ? `Run workflow ${placement.action}`\n : placement.kind === 'agent'\n ? `Ask ${placement.key ?? 'Tabbio'}`\n : id);\n\n return {\n id,\n mcpName,\n title,\n description: readString(raw.description) ?? '',\n readOnly: annotations.readOnlyHint === true,\n inputSchema: toSchema(raw.inputSchema),\n kind: placement.kind,\n group: placement.group,\n action: placement.action,\n commandPath: placement.commandPath,\n hidden: HIDDEN_TOOL_IDS.has(id),\n annotations: { ...annotations },\n ...(placement.key ? { key: placement.key } : {}),\n };\n}\n\n/** Normalizes and sorts (by command path) a full `tools/list` result. */\nexport function buildCatalog(rawTools: readonly RawMcpTool[]): CatalogTool[] {\n return rawTools\n .filter((tool) => typeof tool?.name === 'string' && tool.name.length > 0)\n .map(normalizeTool)\n .sort((a, b) => a.commandPath.join(' ').localeCompare(b.commandPath.join(' ')));\n}\n\n/**\n * Finds a tool by any accepted reference: canonical id (`cv.list`), MCP name\n * (`cvList`, `run_tailoredCvFlow`), command path (`cv list`, `cv:list`,\n * `workflows run tailored-cv-flow`) or kebab id (`career-highlight.upsert`).\n */\nexport function findTool(tools: readonly CatalogTool[], ref: string): CatalogTool | undefined {\n const needle = ref.trim();\n if (!needle) return undefined;\n const exact = tools.find((t) => t.id === needle || t.mcpName === needle);\n if (exact) return exact;\n const lower = needle.toLowerCase();\n const asPath = lower.split(/[\\s:.]+/).filter(Boolean).map(kebabCase).join(' ');\n return tools.find(\n (t) =>\n t.id.toLowerCase() === lower ||\n t.commandPath.join(' ') === asPath ||\n [t.group, t.action].filter(Boolean).join(' ') === asPath ||\n (t.kind === 'workflow' && (t.action === asPath || t.key?.toLowerCase() === lower)),\n );\n}\n\n/** Distinct groups with their tools, for listings and command registration. */\nexport function groupCatalog(tools: readonly CatalogTool[]): Map<string, CatalogTool[]> {\n const groups = new Map<string, CatalogTool[]>();\n for (const tool of tools) {\n const list = groups.get(tool.group) ?? [];\n list.push(tool);\n groups.set(tool.group, list);\n }\n return groups;\n}\n", "import type { Profile } from './config';\nimport { activeCommandSignal } from './cancellation';\nimport {\n type Credentials,\n loadStoredCredentials,\n redactUrl,\n saveCredentials,\n withCredentialsLock,\n} from './credentials';\nimport {\n CliError,\n ExitCode,\n cliErrorFromEnvelope,\n cliErrorFromStatus,\n needsFullSignInError,\n networkError,\n notSignedInError,\n} from './errors';\nimport { debug, deviceLabel } from './runtime';\nimport { userAgent } from './version';\n\nexport type Envelope<T> = {\n data: T | null;\n error: { code: string; message: string } | null;\n meta: unknown;\n};\n\nexport type AuthMode = 'jwt' | 'none';\n\nexport type JsonRequestInit = {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n auth?: AuthMode;\n /** Per-request timeout; default 30s. */\n timeoutMs?: number;\n signal?: AbortSignal;\n};\n\nexport type ApiResult<T> = { data: T; meta: unknown; status: number; requestId?: string };\n\n/** Token payload returned by tokens/exchange, extension-exchange and refresh. */\nexport type TokenPayload = {\n accessToken: string;\n accessTokenExpiresAt: string;\n refreshToken?: string;\n user: { id: string; email: string; name?: string | null; username?: string };\n isPartner?: boolean;\n};\n\nexport type ApiClientOptions = {\n /** Inject for tests. Defaults to global fetch. */\n fetch?: typeof fetch;\n /** Persist refreshed credentials to disk (default true). */\n persist?: boolean;\n /** Called after a successful refresh with the new credentials. */\n onCredentialsChange?: (creds: Credentials) => void;\n /** Retry backoff base in ms (tests use 0). */\n retryDelayMs?: number;\n};\n\nexport const CLIENT_PLATFORM = 'cli';\nexport const CLIENT_PLATFORM_HEADER = 'x-tabbio-client-platform';\nexport const DEVICE_LABEL_HEADER = 'x-tabbio-device-label';\n/** Refresh proactively when the access token expires within this window. */\nexport const REFRESH_SKEW_MS = 5 * 60 * 1000;\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst RETRYABLE_STATUS = new Set([502, 503, 504]);\nconst MAX_RETRIES = 2;\n\nconst REQUEST_ID_HEADERS = ['x-request-id', 'x-railway-request-id', 'x-vercel-id', 'cf-ray'];\n\nexport function readRequestId(headers: Headers): string | undefined {\n for (const name of REQUEST_ID_HEADERS) {\n const value = headers.get(name);\n if (value) return value;\n }\n return undefined;\n}\n\n/** Headers sent on every CLI request (API and MCP). */\nexport function baseHeaders(): Record<string, string> {\n return {\n [CLIENT_PLATFORM_HEADER]: CLIENT_PLATFORM,\n [DEVICE_LABEL_HEADER]: deviceLabel(),\n 'user-agent': userAgent(),\n };\n}\n\nexport function isEnvelope(value: unknown): value is Envelope<unknown> {\n return typeof value === 'object' && value !== null && 'data' in value && 'error' in value;\n}\n\nfunction isExpiringSoon(creds: Credentials, now = Date.now()): boolean {\n if (!creds.accessTokenExpiresAt) return false;\n const expiresAt = Date.parse(creds.accessTokenExpiresAt);\n return Number.isFinite(expiresAt) && expiresAt - now < REFRESH_SKEW_MS;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** AbortSignal.any() is Node >= 20.3; this works on every Node 20. */\nexport function combineSignals(...signals: Array<AbortSignal | undefined>): AbortSignal {\n const present = signals.filter((s): s is AbortSignal => Boolean(s));\n if (present.length === 1) return present[0] as AbortSignal;\n const controller = new AbortController();\n for (const signal of present) {\n if (signal.aborted) {\n controller.abort(signal.reason);\n break;\n }\n signal.addEventListener('abort', () => controller.abort(signal.reason), { once: true });\n }\n return controller.signal;\n}\n\nexport class ApiClient {\n private creds: Credentials | null;\n private readonly fetchImpl: typeof fetch;\n private readonly opts: ApiClientOptions;\n private refreshing: Promise<string> | null = null;\n /** Request id of the most recent response, when the server sent one. */\n lastRequestId?: string;\n\n constructor(\n readonly profile: Profile,\n creds: Credentials | null,\n opts: ApiClientOptions = {},\n ) {\n this.creds = creds ? { ...creds } : null;\n this.opts = opts;\n this.fetchImpl = opts.fetch ?? ((...args) => fetch(...args));\n }\n\n get credentials(): Credentials | null {\n return this.creds;\n }\n\n /** JSON request; unwraps the `{ data, error, meta }` envelope or throws CliError. */\n async json<T>(path: string, init: JsonRequestInit = {}): Promise<T> {\n return (await this.request<T>(path, init)).data;\n }\n\n /** Like json() but also returns meta, status and request id. */\n async request<T>(path: string, init: JsonRequestInit = {}): Promise<ApiResult<T>> {\n const headers: Record<string, string> = { accept: 'application/json', ...init.headers };\n let body: string | undefined;\n if (init.body !== undefined) {\n headers['content-type'] = 'application/json';\n body = JSON.stringify(init.body);\n }\n const response = await this.raw(path, {\n method: init.method ?? 'GET',\n headers,\n body,\n auth: init.auth,\n timeoutMs: init.timeoutMs,\n signal: init.signal,\n });\n return parseJsonResponse<T>(response);\n }\n\n /** Low-level fetch with CLI headers, auth, refresh-on-401 and GET retries. */\n async raw(\n path: string,\n init: RequestInit & { auth?: AuthMode; timeoutMs?: number } = {},\n ): Promise<Response> {\n if (!path.startsWith('/')) throw new Error(`API path must start with \"/\": ${path}`);\n const { auth = 'jwt', timeoutMs, ...requestInit } = init;\n const method = (requestInit.method ?? 'GET').toUpperCase();\n const url = `${this.profile.apiUrl}${path}`;\n const idempotent = method === 'GET' || method === 'HEAD';\n\n let token = auth === 'jwt' ? await this.ensureAccessToken() : undefined;\n let refreshed = false;\n let attempt = 0;\n\n for (;;) {\n const headers = new Headers(requestInit.headers);\n for (const [key, value] of Object.entries(baseHeaders())) {\n if (!headers.has(key)) headers.set(key, value);\n }\n if (token) headers.set('authorization', `Bearer ${token}`);\n\n const signal = combineSignals(\n activeCommandSignal,\n AbortSignal.timeout(timeoutMs ?? DEFAULT_TIMEOUT_MS),\n requestInit.signal ?? undefined,\n );\n const started = Date.now();\n debug(`\u2192 ${method} ${redactUrl(url)}`);\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, {\n ...requestInit,\n method,\n headers,\n signal,\n });\n } catch (error) {\n if (activeCommandSignal.aborted || requestInit.signal?.aborted) throw error;\n debug(`\u2717 ${method} ${redactUrl(url)} ${(error as Error).message} ${Date.now() - started}ms`);\n if (idempotent && attempt < MAX_RETRIES) {\n attempt += 1;\n await sleep(this.backoff(attempt));\n continue;\n }\n throw networkError(url, error);\n }\n\n const requestId = readRequestId(response.headers);\n if (requestId) this.lastRequestId = requestId;\n debug(\n `\u2190 ${response.status} ${method} ${redactUrl(url)} ${Date.now() - started}ms${requestId ? ` req=${requestId}` : ''}`,\n );\n\n if (idempotent && RETRYABLE_STATUS.has(response.status) && attempt < MAX_RETRIES) {\n attempt += 1;\n await response.body?.cancel().catch(() => undefined);\n await sleep(this.backoff(attempt));\n continue;\n }\n\n if (response.status === 401 && auth === 'jwt' && !refreshed && this.canRefresh()) {\n refreshed = true;\n await response.body?.cancel().catch(() => undefined);\n token = await this.refresh();\n continue;\n }\n\n return response;\n }\n }\n\n /**\n * Returns a usable access token, refreshing first when it expires within\n * five minutes. Throws CliError (exit 3) when there is no JWT session.\n */\n async ensureAccessToken(): Promise<string> {\n const creds = this.creds;\n if (!creds?.accessToken) {\n if (creds?.mcpToken) throw needsFullSignInError('This command');\n throw notSignedInError(this.profile.name);\n }\n if (isExpiringSoon(creds) && this.canRefresh()) return this.refresh();\n return creds.accessToken;\n }\n\n /**\n * Rotates the refresh token once. The rotated token is persisted atomically\n * before it is used, under a cross-process lock; if another process already\n * rotated it, its result is adopted instead of refreshing twice (which the\n * server would treat as token reuse and revoke the session family).\n */\n refresh(): Promise<string> {\n if (!this.refreshing) {\n this.refreshing = this.doRefresh().finally(() => {\n this.refreshing = null;\n });\n }\n return this.refreshing;\n }\n\n private canRefresh(): boolean {\n return Boolean(this.creds?.refreshToken);\n }\n\n private backoff(attempt: number): number {\n const base = this.opts.retryDelayMs ?? 300;\n return base * 3 ** (attempt - 1) + (base ? Math.floor(Math.random() * base) : 0);\n }\n\n private async doRefresh(): Promise<string> {\n const persist = this.opts.persist !== false;\n const run = async () => {\n const current = this.creds;\n if (!current?.refreshToken) throw notSignedInError(this.profile.name);\n\n if (persist) {\n const onDisk = loadStoredCredentials(this.profile.name);\n if (\n onDisk?.refreshToken &&\n onDisk.refreshToken !== current.refreshToken &&\n onDisk.accessToken &&\n !isExpiringSoon(onDisk)\n ) {\n debug('adopting credentials refreshed by another tabbio process');\n this.creds = { ...current, ...onDisk, origin: current.origin };\n return onDisk.accessToken;\n }\n }\n\n let payload: TokenPayload;\n try {\n payload = await this.json<TokenPayload>('/api/auth/tokens/refresh', {\n method: 'POST',\n body: { refreshToken: current.refreshToken },\n auth: 'none',\n });\n } catch (error) {\n if (error instanceof CliError && error.exitCode !== ExitCode.Network) {\n throw new CliError({\n code: error.code === 'SESSION_REUSE_DETECTED' ? error.code : 'SESSION_EXPIRED',\n message: 'Your Tabbio session has expired',\n hint: 'Run `tabbio login` to sign in again.',\n exitCode: ExitCode.Auth,\n requestId: error.requestId,\n cause: error,\n });\n }\n throw error;\n }\n\n const next: Credentials = {\n ...current,\n accessToken: payload.accessToken,\n accessTokenExpiresAt: payload.accessTokenExpiresAt,\n refreshToken: payload.refreshToken ?? current.refreshToken,\n user: payload.user\n ? { id: payload.user.id, email: payload.user.email, name: payload.user.name ?? null }\n : current.user,\n origin: { ...current.origin, accessToken: 'store' },\n };\n if (persist) saveCredentials(next);\n this.creds = next;\n this.opts.onCredentialsChange?.(next);\n return payload.accessToken;\n };\n return persist ? withCredentialsLock(run) : run();\n }\n}\n\n/** Parses a JSON response: envelope first, HTTP status second. */\nexport async function parseJsonResponse<T>(response: Response): Promise<ApiResult<T>> {\n const requestId = readRequestId(response.headers);\n const text = await response.text();\n let parsed: unknown = undefined;\n if (text.trim()) {\n try {\n parsed = JSON.parse(text);\n } catch {\n if (!response.ok) throw cliErrorFromStatus(response.status, { requestId });\n throw new CliError({\n code: 'BAD_RESPONSE',\n message: 'Tabbio sent a response the CLI could not read',\n exitCode: ExitCode.Server,\n status: response.status,\n requestId,\n });\n }\n }\n\n if (isEnvelope(parsed)) {\n if (parsed.error) {\n throw cliErrorFromEnvelope(parsed.error, { status: response.status, requestId });\n }\n if (!response.ok) throw cliErrorFromStatus(response.status, { requestId });\n return { data: parsed.data as T, meta: parsed.meta ?? null, status: response.status, requestId };\n }\n\n if (!response.ok) {\n // Better Auth routes answer `{ code, message }` without the envelope.\n const record = (parsed ?? {}) as { code?: unknown; message?: unknown };\n if (typeof record.message === 'string' || typeof record.code === 'string') {\n throw cliErrorFromEnvelope(\n {\n code: typeof record.code === 'string' ? record.code : undefined,\n message: typeof record.message === 'string' ? record.message : undefined,\n },\n { status: response.status, requestId },\n );\n }\n throw cliErrorFromStatus(response.status, { requestId });\n }\n\n return { data: parsed as T, meta: null, status: response.status, requestId };\n}\n", "/**\n * Pure interpretation of MCP `tools/call` results and transport failures.\n * Kept separate from the session so it is trivially unit-testable.\n */\nimport { CliError, ExitCode, cliErrorFromEnvelope, exitCodeForStatus, networkError } from './errors';\n\nexport type ApprovalInfo = { approvalId: string; toolName: string; message: string; status?: string };\n\nexport type ToolCallResult =\n | { ok: true; result: unknown; approval?: ApprovalInfo }\n | { ok: false; error: CliError };\n\n/** Minimal structural view of an MCP CallToolResult. */\nexport type McpCallResultLike = {\n content?: Array<{ type: string; text?: string; [key: string]: unknown }>;\n structuredContent?: unknown;\n isError?: boolean;\n [key: string]: unknown;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Detects the approval-gated result shape returned by Tabbio tools over MCP:\n * `{ approvalRequired: true, approvalId, status, message, toolName }`.\n */\nexport function detectApproval(value: unknown, fallbackToolName = ''): ApprovalInfo | null {\n if (!isRecord(value) || value.approvalRequired !== true) return null;\n if (typeof value.approvalId !== 'string' || !value.approvalId) return null;\n return {\n approvalId: value.approvalId,\n toolName: typeof value.toolName === 'string' ? value.toolName : fallbackToolName,\n message:\n typeof value.message === 'string'\n ? value.message\n : 'This Tabbio action requires approval before it runs.',\n ...(typeof value.status === 'string' ? { status: value.status } : {}),\n };\n}\n\n/** Result payload: JSON from the first text item, else structuredContent. */\nexport function extractToolPayload(result: McpCallResultLike): unknown {\n const first = result.content?.[0];\n if (first?.type === 'text' && typeof first.text === 'string') {\n const text = first.text;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n if (result.structuredContent !== undefined) return result.structuredContent;\n return result.content ?? null;\n}\n\nfunction contentText(result: McpCallResultLike): string {\n return (result.content ?? [])\n .filter((item) => item.type === 'text' && typeof item.text === 'string')\n .map((item) => item.text as string)\n .join('\\n')\n .trim();\n}\n\n/** Pulls a human message and optional HTTP status out of an MCP error text. */\nexport function parseToolErrorText(text: string): { message: string; status?: number; code?: string } {\n const trimmed = text.trim();\n try {\n const json: unknown = JSON.parse(trimmed);\n if (isRecord(json)) {\n const cause = isRecord(json.cause) ? json.cause : undefined;\n const details = isRecord(json.details) ? json.details : undefined;\n const message =\n (typeof cause?.message === 'string' && cause.message) ||\n (typeof json.message === 'string' && json.message) ||\n trimmed;\n const status = [json.status, cause?.status, details?.status].find(\n (value): value is number => typeof value === 'number',\n );\n const code = typeof json.code === 'string' ? json.code : undefined;\n return { message: String(message).replace(/^Error:\\s*/, ''), status, code };\n }\n } catch {\n // plain text\n }\n return { message: trimmed.replace(/^Error:\\s*/, '') || 'The tool failed' };\n}\n\n/** Classifies a tool error message into a CliError with the right exit code. */\nexport function classifyToolError(\n toolName: string,\n message: string,\n status?: number,\n code?: string,\n): CliError {\n const make = (errCode: string, exitCode: CliError['exitCode'], hint?: string) =>\n new CliError({ code: errCode, message, hint, exitCode, status });\n\n if (/pass companyId/i.test(message)) {\n return make('MCP_SCOPE_FORBIDDEN', ExitCode.Forbidden, 'Pass the company id (e.g. --company-id <id>).');\n }\n if (/does not allow (writes|reads)|not scoped to|scoped to selected company/i.test(message)) {\n return make(\n 'MCP_SCOPE_FORBIDDEN',\n ExitCode.Forbidden,\n 'The personal token in use does not cover this. Sign in with `tabbio login` for full access.',\n );\n }\n if (/not available through the assistant/i.test(message)) return make('FORBIDDEN', ExitCode.Forbidden);\n if (/^Unknown tool/i.test(message)) {\n return make('UNKNOWN_TOOL', ExitCode.NotFound, 'Run `tabbio tools --refresh` to reload the catalog.');\n }\n if (/validation failed|invalid arguments/i.test(message)) return make('VALIDATION_ERROR', ExitCode.Usage);\n if (/requires an active company/i.test(message)) {\n return make('COMPANY_REQUIRED', ExitCode.Usage, 'Pass the company id (e.g. --company-id <id>).');\n }\n if (/missing authenticated user|unauthori[sz]ed/i.test(message)) {\n return make('UNAUTHORIZED', ExitCode.Auth, 'Run `tabbio login` to sign in again.');\n }\n if (code && code !== 'ERROR') {\n const mapped = cliErrorFromEnvelope({ code, message }, { status });\n if (mapped.exitCode !== ExitCode.Error) return mapped;\n }\n if (status) return make(status === 404 ? 'NOT_FOUND' : 'TOOL_ERROR', exitCodeForStatus(status));\n if (/\\bnot found\\b/i.test(message)) return make('NOT_FOUND', ExitCode.NotFound);\n return make('TOOL_ERROR', ExitCode.Error, toolName ? `Tool: ${toolName}` : undefined);\n}\n\n/** Turns a raw MCP call result into the CLI's ToolCallResult. */\nexport function interpretToolResult(result: McpCallResultLike, toolName: string): ToolCallResult {\n if (result.isError) {\n const parsed = parseToolErrorText(contentText(result) || 'The tool failed');\n return { ok: false, error: classifyToolError(toolName, parsed.message, parsed.status, parsed.code) };\n }\n\n return interpretToolPayload(extractToolPayload(result), toolName);\n}\n\n/**\n * The payload half of interpretToolResult: tool-level failures\n * (`{ ok: false, error }`, Mastra validation) become errors, approval\n * envelopes are detected. Also used on the output of an approval confirmed\n * from the terminal (`data.mcp.result`), which is a payload, not an MCP result.\n */\nexport function interpretToolPayload(payload: unknown, toolName: string): ToolCallResult {\n if (isRecord(payload)) {\n // Mastra input/output validation failures come back as a *successful* call.\n if (payload.error === true && typeof payload.message === 'string') {\n return { ok: false, error: classifyToolError(toolName, payload.message) };\n }\n // Tool-level `{ ok: false, error: { code, message } }` results.\n if (payload.ok === false && isRecord(payload.error)) {\n const err = payload.error;\n return {\n ok: false,\n error: cliErrorFromEnvelope(\n {\n code: typeof err.code === 'string' ? err.code : 'TOOL_ERROR',\n message: typeof err.message === 'string' ? err.message : 'The tool failed',\n },\n { status: typeof err.status === 'number' ? err.status : undefined },\n ),\n };\n }\n }\n\n const approval = detectApproval(payload, toolName);\n return approval ? { ok: true, result: payload, approval } : { ok: true, result: payload };\n}\n\nfunction readErrorDescription(text: string): string | undefined {\n const match = /\\{[\\s\\S]*\\}/.exec(text);\n if (!match) return undefined;\n try {\n const json = JSON.parse(match[0]) as { error_description?: unknown; message?: unknown; error?: unknown };\n if (typeof json.error_description === 'string') return json.error_description;\n if (typeof json.message === 'string') return json.message;\n if (typeof json.error === 'string') return json.error;\n } catch {\n return undefined;\n }\n return undefined;\n}\n\n/** Maps SDK transport / protocol errors to CliErrors. */\nexport function mapMcpTransportError(\n error: unknown,\n ctx: { mcpUrl: string; profile: string; kind?: 'app-session' | 'personal-token' },\n): CliError {\n if (error instanceof CliError) return error;\n const err = error as { name?: string; code?: unknown; message?: string; cause?: unknown };\n const message = err?.message ?? String(error);\n\n const isUnauthorized =\n err?.name === 'UnauthorizedError' ||\n (error as { constructor?: { name?: string } })?.constructor?.name === 'UnauthorizedError' ||\n (typeof err?.code === 'number' && err.code === 401);\n if (isUnauthorized) {\n const detail = readErrorDescription(message);\n const personal = ctx.kind === 'personal-token';\n return new CliError({\n code: personal ? 'MCP_TOKEN_REJECTED' : 'SESSION_EXPIRED',\n message: personal\n ? `The personal MCP token for profile \"${ctx.profile}\" was rejected${detail ? ` (${detail})` : ''}`\n : `Tabbio rejected the session for profile \"${ctx.profile}\"${detail ? ` (${detail})` : ''}`,\n hint: personal\n ? 'Tokens are revoked when a newer one is created in Settings \u2192 MCP access. Create one and run `tabbio login --token \u2026`, or sign in with `tabbio login`.'\n : 'Run `tabbio login` to sign in again.',\n exitCode: ExitCode.Auth,\n status: 401,\n cause: error,\n });\n }\n\n if (typeof err?.code === 'number' && err.code >= 400 && err.code < 600) {\n const detail = readErrorDescription(message);\n const exitCode = exitCodeForStatus(err.code);\n return new CliError({\n code: err.code === 404 ? 'MCP_ENDPOINT_NOT_FOUND' : err.code === 403 ? 'FORBIDDEN' : 'MCP_HTTP_ERROR',\n message:\n err.code === 404\n ? `No MCP endpoint at ${ctx.mcpUrl}`\n : `MCP request failed (HTTP ${err.code})${detail ? `: ${detail}` : ''}`,\n hint: err.code === 404 ? 'Check the API URL with `tabbio status`.' : undefined,\n exitCode,\n status: err.code,\n cause: error,\n });\n }\n\n if (err?.name === 'McpError' && typeof err.code === 'number') {\n if (err.code === -32001) {\n return new CliError({\n code: 'TIMEOUT',\n message: 'The Tabbio tool call timed out',\n hint: 'Long-running workflows may still finish; check `tabbio approvals` or the app.',\n exitCode: ExitCode.Network,\n cause: error,\n });\n }\n if (err.code === -32000) return networkError(ctx.mcpUrl, error);\n if (err.code === -32602) {\n return new CliError({ code: 'VALIDATION_ERROR', message, exitCode: ExitCode.Usage, cause: error });\n }\n return new CliError({ code: 'MCP_ERROR', message, exitCode: ExitCode.Error, cause: error });\n }\n\n if (err?.name === 'TypeError' || err?.name === 'AbortError' || err?.name === 'TimeoutError') {\n return networkError(ctx.mcpUrl, error);\n }\n\n return new CliError({ code: 'MCP_ERROR', message, exitCode: ExitCode.Error, cause: error });\n}\n", "import { randomBytes, timingSafeEqual } from 'node:crypto';\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport type { AddressInfo } from 'node:net';\nimport { WEB_PAGE_PALETTE } from '../ui/theme';\nimport { CliError, ExitCode, interruptedError } from './errors';\n\n/**\n * RFC 8252 loopback redirect receiver for `tabbio login` (browser hand-off).\n * Binds 127.0.0.1 only, on a random port, and accepts exactly one\n * `GET /callback?code=\u2026&state=\u2026` whose state matches.\n */\n\nexport const STATE_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;\nexport const CODE_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;\nexport const LOOPBACK_HOST = '127.0.0.1';\nexport const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;\n\nexport type CallbackValidation =\n | { ok: true; code: string }\n | { ok: false; status: number; reason: string; fatal: boolean };\n\n/** 256-bit state nonce, base64url (43 chars). */\nexport function generateState(): string {\n return randomBytes(32).toString('base64url');\n}\n\nfunction safeEqual(a: string, b: string): boolean {\n const left = Buffer.from(a);\n const right = Buffer.from(b);\n return left.length === right.length && timingSafeEqual(left, right);\n}\n\n/**\n * Pure validation of a callback URL. `fatal` means the login attempt is over\n * (the user declined in the browser); non-fatal failures are answered with an\n * error page while the listener keeps waiting for the genuine redirect.\n */\nexport function validateLoopbackCallback(url: URL, expectedState: string): CallbackValidation {\n if (url.pathname !== '/callback') {\n return { ok: false, status: 404, reason: 'Not found', fatal: false };\n }\n const state = url.searchParams.get('state') ?? '';\n if (!STATE_PATTERN.test(state) || !safeEqual(state, expectedState)) {\n return { ok: false, status: 400, reason: 'This sign-in link does not match the waiting terminal.', fatal: false };\n }\n const error = url.searchParams.get('error');\n if (error) {\n return {\n ok: false,\n status: 200,\n reason: error === 'access_denied' ? 'Connection was declined in the browser.' : `Connection failed: ${error.slice(0, 80)}`,\n fatal: true,\n };\n }\n const code = url.searchParams.get('code') ?? '';\n if (!CODE_PATTERN.test(code)) {\n return { ok: false, status: 400, reason: 'The connect code is missing or malformed.', fatal: false };\n }\n return { ok: true, code };\n}\n\nfunction paletteCss(): string {\n const vars = (p: Record<string, string>) =>\n Object.entries(p)\n .map(([key, value]) => `--${key}:${value}`)\n .join(';');\n const { light, dark, accent, onAccent } = WEB_PAGE_PALETTE;\n return `:root{${vars(light)};--accent:${accent};--on-accent:${onAccent}}\\n@media (prefers-color-scheme:dark){:root{${vars(dark)}}}`;\n}\n\nfunction escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (c) => `&#${c.charCodeAt(0)};`);\n}\n\n/** Small self-contained branded page; no external requests, no referrer. */\nexport function renderLoopbackPage(kind: 'success' | 'error', message: string): string {\n const title = kind === 'success' ? 'Tabbio CLI connected' : 'Tabbio CLI sign-in';\n const heading = kind === 'success' ? 'You are signed in to the Tabbio CLI' : 'Sign-in did not finish';\n const mark = kind === 'success' ? '&#10003;' : '!';\n return `<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<meta name=\"referrer\" content=\"no-referrer\"><title>${title}</title>\n<style>\n${paletteCss()}\n*{box-sizing:border-box}body{margin:0;min-height:100vh;display:grid;place-items:center;background:var(--bg);color:var(--fg);\nfont:16px/1.5 -apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;padding:24px}\nmain{max-width:420px;width:100%;background:var(--card);border:1px solid var(--line);border-radius:16px;padding:32px;text-align:start}\n.mark{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;background:var(--accent);color:var(--on-accent);font-weight:700;margin-bottom:16px}\nh1{font-size:20px;margin:0 0 8px}p{margin:0;color:var(--muted)}.brand{font-weight:600;color:var(--accent);margin-bottom:24px;font-size:14px}\n</style></head>\n<body><main><div class=\"brand\">tabbio</div><div class=\"mark\">${mark}</div><h1>${escapeHtml(heading)}</h1>\n<p dir=\"auto\">${escapeHtml(message)}</p></main></body></html>`;\n}\n\nexport type LoopbackServer = {\n port: number;\n /** Resolves with the connect code; rejects on timeout, decline or abort. */\n waitForCode(): Promise<string>;\n /**\n * Answers the browser tab that delivered the code. The tab is held open\n * until the CLI knows whether the code exchange worked, so the page never\n * claims success for a failed sign-in.\n */\n complete(kind: 'success' | 'error', message: string): void;\n close(): Promise<void>;\n};\n\nfunction send(res: ServerResponse, status: number, html: string) {\n res.writeHead(status, {\n 'content-type': 'text/html; charset=utf-8',\n 'cache-control': 'no-store',\n 'referrer-policy': 'no-referrer',\n 'content-security-policy': \"default-src 'none'; style-src 'unsafe-inline'\",\n 'x-content-type-options': 'nosniff',\n connection: 'close',\n });\n res.end(html);\n}\n\nexport async function startLoopbackServer(opts: {\n state: string;\n timeoutMs?: number;\n signal?: AbortSignal;\n}): Promise<LoopbackServer> {\n let settle: { resolve: (code: string) => void; reject: (error: Error) => void } | undefined;\n let outcome: { code?: string; error?: Error } | undefined;\n const finish = (result: { code?: string; error?: Error }) => {\n if (outcome) return;\n outcome = result;\n if (settle) {\n if (result.code) settle.resolve(result.code);\n else settle.reject(result.error ?? new Error('Login failed'));\n }\n };\n\n let port = 0;\n let pending: ServerResponse | undefined;\n const server = createServer((req: IncomingMessage, res: ServerResponse) => {\n // DNS-rebinding guard: only the literal loopback authority is accepted.\n if (req.headers.host !== `${LOOPBACK_HOST}:${port}`) {\n return send(res, 400, renderLoopbackPage('error', 'Unexpected host.'));\n }\n if (req.method !== 'GET') return send(res, 405, renderLoopbackPage('error', 'Method not allowed.'));\n const url = new URL(req.url ?? '/', `http://${LOOPBACK_HOST}:${port}`);\n if (outcome) {\n return send(res, 410, renderLoopbackPage('error', 'This sign-in already finished. Return to your terminal.'));\n }\n const result = validateLoopbackCallback(url, opts.state);\n if (result.ok) {\n pending = res;\n finish({ code: result.code });\n return;\n }\n send(res, result.status, renderLoopbackPage('error', result.reason));\n if (result.fatal) {\n finish({ error: new CliError({ code: 'LOGIN_DECLINED', message: result.reason, exitCode: ExitCode.Auth }) });\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(0, LOOPBACK_HOST, () => {\n server.off('error', reject);\n resolve();\n });\n });\n port = (server.address() as AddressInfo).port;\n\n const timeoutMs = opts.timeoutMs ?? LOGIN_TIMEOUT_MS;\n const timer = setTimeout(() => {\n finish({\n error: new CliError({\n code: 'LOGIN_TIMEOUT',\n message: `Timed out after ${Math.round(timeoutMs / 60000) || 1} min waiting for the browser`,\n hint: 'Run `tabbio login` again, or use `tabbio login --email you@example.com` on a machine without a browser.',\n exitCode: ExitCode.Auth,\n }),\n });\n }, timeoutMs);\n timer.unref();\n\n const onAbort = () => finish({ error: interruptedError('Login cancelled') });\n if (opts.signal?.aborted) onAbort();\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n\n const complete = (kind: 'success' | 'error', message: string) => {\n if (pending && !pending.writableEnded) send(pending, kind === 'success' ? 200 : 400, renderLoopbackPage(kind, message));\n pending = undefined;\n };\n\n const close = async () => {\n complete('error', 'Return to your terminal to see what happened.');\n clearTimeout(timer);\n opts.signal?.removeEventListener('abort', onAbort);\n server.closeAllConnections?.();\n await new Promise<void>((resolve) => server.close(() => resolve()));\n };\n\n return {\n port,\n waitForCode: () =>\n new Promise<string>((resolve, reject) => {\n if (!outcome) {\n settle = { resolve, reject };\n return;\n }\n if (outcome.code) resolve(outcome.code);\n else reject(outcome.error ?? new Error('Login failed'));\n }),\n complete,\n close,\n };\n}\n", "import type { Profile } from './config';\nimport { type Credentials, type CredentialUser, clearCredentials } from './credentials';\nimport { CliError, ExitCode, usageError } from './errors';\nimport { ApiClient, type TokenPayload, parseJsonResponse } from './http';\nimport { LOGIN_TIMEOUT_MS, generateState, startLoopbackServer } from './loopback';\nimport { clearCatalogCache } from './mcp';\nimport { debug } from './runtime';\n\nexport type LoginMethod = 'browser' | 'email' | 'token';\n\nexport type McpScopeType = 'personal' | 'company' | 'mixed';\n\n// NOTE: the CLI never calls POST /api/integrations/mcp/tokens. That endpoint\n// keeps one active personal token per user and revokes all others, so minting\n// one here would silently break the user's other MCP clients. MCP calls use\n// the app session JWT instead (see core/mcp.ts selectMcpBearer).\n\nexport type McpTokenSummary = {\n id: string;\n name: string;\n scopeType: McpScopeType;\n includePersonal: boolean;\n companyIds: string[];\n companies: Array<{ id: string; name: string; slug: string }>;\n maskedToken: string;\n tokenFingerprint: string;\n scopes: string[];\n lastUsedAt: string | null;\n expiresAt: string | null;\n createdAt: string;\n};\n\nexport type McpPendingApproval = {\n id: string;\n toolName: string;\n args: unknown;\n status: string;\n companyId: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\n/** `GET /api/integrations/mcp` (McpPersonalTokensService.getAccessState). */\nexport type McpAccessState = {\n serverUrl: string;\n tokens: McpTokenSummary[];\n scopes: Array<{\n scopeType: 'personal' | 'company';\n companyId: string | null;\n label: string;\n company?: { id: string; name: string; slug: string };\n }>;\n pendingApprovals: McpPendingApproval[];\n};\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nexport const OTP_MAX_ATTEMPTS = 3;\n\n/** True when a browser can plausibly be opened on this machine. */\nexport function hasDisplay(env: NodeJS.ProcessEnv = process.env, platform = process.platform): boolean {\n if (env.SSH_CONNECTION || env.SSH_TTY || env.SSH_CLIENT) return false;\n if (platform === 'darwin' || platform === 'win32') return true;\n return Boolean(env.DISPLAY || env.WAYLAND_DISPLAY);\n}\n\n/**\n * Plan section 3: explicit flag, then browser on a TTY with a display, then\n * email. `--non-interactive` is the browser flow without opening a browser.\n */\nexport function chooseLoginMethod(opts: {\n browser?: boolean;\n email?: string;\n token?: string;\n withToken?: boolean;\n nonInteractive?: boolean;\n isTTY: boolean;\n hasDisplay: boolean;\n}): LoginMethod {\n const flags = [\n opts.browser && '--browser',\n opts.email && '--email',\n opts.token && '--token',\n opts.withToken && '--with-token',\n ].filter(Boolean) as string[];\n if (flags.length > 1) throw usageError(`Choose one of ${flags.join(', ')}`);\n if (opts.nonInteractive && (opts.email || opts.token || opts.withToken)) {\n throw usageError('--non-interactive only applies to the browser flow');\n }\n if (opts.token || opts.withToken) return 'token';\n if (opts.email) return 'email';\n if (opts.browser || opts.nonInteractive) return 'browser';\n if (opts.isTTY && opts.hasDisplay) return 'browser';\n if (opts.isTTY) return 'email';\n throw usageError(\n 'No login method for a non-interactive session',\n 'Use `tabbio login --token <tabbio_mcp_\u2026>` or set TABBIO_TOKEN / TABBIO_ACCESS_TOKEN.',\n );\n}\n\nexport function assertEmail(email: string): string {\n const value = email.trim().toLowerCase();\n if (!EMAIL_PATTERN.test(value)) throw usageError(`Not a valid email address: ${email}`);\n return value;\n}\n\nexport function buildConnectUrl(appUrl: string, params: { port: number; state: string; device: string }): string {\n const url = new URL('/cli/connect', `${appUrl}/`);\n url.searchParams.set('port', String(params.port));\n url.searchParams.set('state', params.state);\n url.searchParams.set('device', params.device.slice(0, 64));\n return url.toString();\n}\n\n/** Joins `set-cookie` values into a `cookie` request header (name=value pairs only). */\nexport function cookieHeaderFromSetCookie(values: readonly string[]): string {\n return values\n .map((value) => value.split(';', 1)[0]?.trim() ?? '')\n .filter((pair) => pair.includes('=') && !pair.endsWith('='))\n .join('; ');\n}\n\nfunction toUser(user: TokenPayload['user']): CredentialUser {\n return { id: user.id, email: user.email, name: user.name ?? null };\n}\n\nfunction assertTokenPayload(payload: TokenPayload | null | undefined): TokenPayload {\n if (!payload?.accessToken || !payload.user?.id) {\n throw new CliError({ code: 'BAD_RESPONSE', message: 'Sign-in returned no session', exitCode: ExitCode.Server });\n }\n if (!payload.refreshToken) {\n // Only happens if the platform header was dropped (the server then sets a cookie instead).\n throw new CliError({\n code: 'NO_REFRESH_TOKEN',\n message: 'Sign-in returned no refresh token',\n hint: 'A proxy may be stripping the x-tabbio-client-platform header.',\n exitCode: ExitCode.Server,\n });\n }\n return payload;\n}\n\n/** `POST /api/auth/tokens/extension-exchange { code }` (public, single use, 60s TTL). */\nexport async function exchangeGrantCode(api: ApiClient, code: string): Promise<TokenPayload> {\n const payload = await api.json<TokenPayload>('/api/auth/tokens/extension-exchange', {\n method: 'POST',\n body: { code },\n auth: 'none',\n });\n return assertTokenPayload(payload);\n}\n\nexport type BrowserLoginOptions = {\n device: string;\n /** Opens the URL; resolves false when no browser could be launched. */\n openUrl: (url: string) => Promise<boolean>;\n /** Called with the connect URL before waiting (print it as a fallback). */\n onWaiting?: (url: string, opened: boolean, info: { state: string; port: number; expiresAt: string }) => void;\n timeoutMs?: number;\n signal?: AbortSignal;\n};\n\n/** Browser hand-off (RFC 8252 loopback). Returns the app session tokens. */\nexport async function loginWithBrowser(api: ApiClient, opts: BrowserLoginOptions): Promise<TokenPayload> {\n const state = generateState();\n const timeoutMs = opts.timeoutMs ?? LOGIN_TIMEOUT_MS;\n const server = await startLoopbackServer({ state, timeoutMs, signal: opts.signal });\n const expiresAt = new Date(Date.now() + timeoutMs).toISOString();\n try {\n const url = buildConnectUrl(api.profile.appUrl, { port: server.port, state, device: opts.device });\n const opened = await opts.openUrl(url).catch(() => false);\n opts.onWaiting?.(url, opened, { state, port: server.port, expiresAt });\n const code = await server.waitForCode();\n debug('received connect code on loopback');\n try {\n const payload = await exchangeGrantCode(api, code);\n server.complete('success', 'You can close this tab and return to your terminal.');\n return payload;\n } catch (error) {\n server.complete('error', 'The connection could not be completed. Check your terminal.');\n throw error;\n }\n } finally {\n await server.close();\n }\n}\n\n/** Better Auth: `POST /api/auth/email-otp/send-verification-otp`. */\nexport async function sendEmailOtp(api: ApiClient, email: string): Promise<void> {\n const response = await api.raw('/api/auth/email-otp/send-verification-otp', {\n method: 'POST',\n auth: 'none',\n headers: { 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify({ email, type: 'sign-in' }),\n });\n await parseJsonResponse(response);\n}\n\n/**\n * Better Auth `POST /api/auth/sign-in/email-otp`; returns the session cookie\n * header, or throws. INVALID_OTP is thrown with code INVALID_OTP for retry.\n */\nexport async function signInWithEmailOtp(api: ApiClient, email: string, otp: string): Promise<string> {\n const response = await api.raw('/api/auth/sign-in/email-otp', {\n method: 'POST',\n auth: 'none',\n headers: { 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify({ email, otp }),\n });\n const cookies = response.ok ? response.headers.getSetCookie() : [];\n await parseJsonResponse(response);\n const cookie = cookieHeaderFromSetCookie(cookies);\n if (!cookie) {\n throw new CliError({ code: 'BAD_RESPONSE', message: 'Sign-in returned no session cookie', exitCode: ExitCode.Server });\n }\n return cookie;\n}\n\n/** `POST /api/auth/tokens/exchange` with the Better Auth session cookie. */\nexport async function exchangeSessionCookie(api: ApiClient, cookie: string): Promise<TokenPayload> {\n const payload = await api.json<TokenPayload>('/api/auth/tokens/exchange', {\n method: 'POST',\n auth: 'none',\n headers: { cookie },\n });\n return assertTokenPayload(payload);\n}\n\nexport type EmailLoginOptions = {\n email: string;\n promptCode: (attempt: number) => Promise<string>;\n onInvalidCode?: (attemptsLeft: number) => void;\n};\n\n/** Headless login: send OTP, prompt (3 attempts), sign in, exchange cookie for tokens. */\nexport async function loginWithEmailOtp(api: ApiClient, opts: EmailLoginOptions): Promise<TokenPayload> {\n const email = assertEmail(opts.email);\n await sendEmailOtp(api, email);\n for (let attempt = 1; attempt <= OTP_MAX_ATTEMPTS; attempt += 1) {\n const otp = (await opts.promptCode(attempt)).replace(/\\s+/g, '');\n if (!otp) throw usageError('No code entered');\n try {\n const cookie = await signInWithEmailOtp(api, email, otp);\n return await exchangeSessionCookie(api, cookie);\n } catch (error) {\n if (!(error instanceof CliError)) throw error;\n const code = error.code.toUpperCase();\n if (code === 'INVALID_OTP' && attempt < OTP_MAX_ATTEMPTS) {\n opts.onInvalidCode?.(OTP_MAX_ATTEMPTS - attempt);\n continue;\n }\n if (code === 'INVALID_OTP' || code === 'TOO_MANY_ATTEMPTS' || code === 'OTP_EXPIRED') {\n throw new CliError({\n code,\n message: code === 'OTP_EXPIRED' ? 'That code expired' : 'Too many wrong codes',\n hint: 'Run `tabbio login --email` again to get a new code.',\n exitCode: ExitCode.Auth,\n requestId: error.requestId,\n });\n }\n throw error;\n }\n }\n throw new CliError({ code: 'TOO_MANY_ATTEMPTS', message: 'Too many wrong codes', exitCode: ExitCode.Auth });\n}\n\nexport function getMcpAccessState(api: ApiClient): Promise<McpAccessState> {\n return api.json<McpAccessState>('/api/integrations/mcp');\n}\n\n/** `POST /api/auth/tokens/logout { refreshToken }`: revokes the refresh token server-side. */\nexport async function revokeSession(api: ApiClient, refreshToken: string): Promise<void> {\n await api.json('/api/auth/tokens/logout', { method: 'POST', body: { refreshToken }, auth: 'none' });\n}\n\nexport function credentialsFromLogin(profile: Profile, payload: TokenPayload): Credentials {\n return {\n profile: profile.name,\n accessToken: payload.accessToken,\n accessTokenExpiresAt: payload.accessTokenExpiresAt,\n refreshToken: payload.refreshToken,\n user: toUser(payload.user),\n };\n}\n\n/**\n * Logout: end the session server-side (`tokens/logout`), then delete local\n * credentials and the catalog cache. The CLI never mints personal MCP tokens,\n * so there is none to revoke; a token given with `login --token` belongs to\n * the user and is left alone. Server failures become warnings.\n */\nexport async function logoutProfile(\n profile: Profile,\n creds: Credentials | null,\n opts: { fetch?: typeof fetch } = {},\n): Promise<{ warnings: string[]; revokedSession: boolean }> {\n const warnings: string[] = [];\n let revokedSession = false;\n // Env-provided secrets are never revoked; they belong to whoever set them.\n const refreshToken = creds?.origin?.accessToken === 'env' ? undefined : creds?.refreshToken;\n if (refreshToken) {\n try {\n await revokeSession(new ApiClient(profile, null, { fetch: opts.fetch, persist: false }), refreshToken);\n revokedSession = true;\n } catch (error) {\n warnings.push(`Could not end the session on the server: ${(error as Error).message}`);\n }\n }\n clearCredentials(profile.name);\n clearCatalogCache(profile);\n return { warnings, revokedSession };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["hostname", "join", "z", "z", "env", "join", "readFileSync", "join", "join", "latest", "rmSync", "join", "action", "sleep", "join", "rmSync", "send", "response", "randomBytes", "randomBytes", "heading", "env"]
7
+ }