{"version":3,"file":"read3.mjs","names":[],"sources":["../../src/commands/read.ts"],"sourcesContent":["import { defineCommand } from 'citty'\nimport { consola } from 'consola'\n\nexport default defineCommand({\n  meta: {\n    name: 'read',\n    description: 'Read a URL using a provider',\n  },\n  args: {\n    url: {\n      type: 'positional',\n      description: 'URL to read',\n      required: true,\n    },\n    provider: {\n      type: 'string',\n      description: 'Read provider to use',\n      default: 'jina',\n    },\n    format: {\n      type: 'string',\n      description: 'Response format: markdown, text, or html',\n    },\n    'max-tokens': {\n      type: 'string',\n      description: 'Maximum tokens to return',\n    },\n    json: {\n      type: 'boolean',\n      description: 'Output as JSON',\n      default: false,\n    },\n  },\n  async run({ args }) {\n    const { readUrl, readProviderNames } = await import('../core/read.ts')\n    const { AuthError, UnknownProviderError, EmptyUrlError, ReadNotSupportedError } = await import('../core/errors.ts')\n    let providerName = args.provider || 'jina'\n\n    try {\n      if (!args.url.trim()) {\n        consola.error('Read URL cannot be empty.')\n        process.exit(1)\n      }\n\n      const format = parseFormat(args.format)\n      if (!format.ok) {\n        consola.error(format.message)\n        process.exit(1)\n      }\n\n      const maxTokens = parseOptionalPositiveInt(args['max-tokens'], '--max-tokens')\n      if (!maxTokens.ok) {\n        consola.error(maxTokens.message)\n        process.exit(1)\n      }\n\n      await import('../providers/index.ts')\n      providerName = args.provider || 'jina'\n      const result = await readUrl(args.url, {\n        provider: providerName,\n        format: format.value,\n        maxTokens: maxTokens.value,\n      })\n\n      if (args.json) {\n        process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n        return\n      }\n\n      if (result.title) {\n        consola.log(`\\x1b[1m\\x1b[36m${sanitizeTerminalText(result.title)}\\x1b[0m`)\n      }\n      consola.log(`  ${sanitizeTerminalText(result.url)}`)\n      if (result.description) {\n        consola.log(`  \\x1b[90m${truncateSingleLine(sanitizeTerminalText(result.description), 160)}\\x1b[0m`)\n      }\n      consola.log('')\n      consola.log(sanitizeTerminalText(result.content))\n    }\n    catch (error) {\n      if (error instanceof EmptyUrlError) {\n        consola.error('Read URL cannot be empty.')\n        process.exit(1)\n      }\n      if (error instanceof AuthError) {\n        const authProvider = providerName || error.provider\n        consola.error(`Authentication failed for provider \"${authProvider}\".`)\n        consola.info(`Set the ${authProvider.toUpperCase()}_API_KEY environment variable.`)\n        process.exit(1)\n      }\n      if (error instanceof UnknownProviderError) {\n        consola.error(`Unknown provider: ${providerName}`)\n        consola.info(`Read-capable providers: ${readProviderNames.join(', ')}`)\n        process.exit(1)\n      }\n      if (error instanceof ReadNotSupportedError) {\n        consola.error(error.message)\n        process.exit(1)\n      }\n      throw error\n    }\n  },\n})\n\ntype ParsedOptionalNumber =\n  | { ok: true; value: number | undefined }\n  | { ok: false; message: string }\n\ntype ParsedFormat =\n  | { ok: true; value: 'markdown' | 'text' | 'html' | undefined }\n  | { ok: false; message: string }\n\nfunction parseOptionalPositiveInt(input: string | undefined, flagName: string): ParsedOptionalNumber {\n  if (input == null || input === '') {\n    return { ok: true, value: undefined }\n  }\n  if (!/^\\d+$/.test(input)) {\n    return { ok: false, message: `Invalid ${flagName} value. Expected a positive integer.` }\n  }\n  const value = Number.parseInt(input, 10)\n  if (value < 1) {\n    return { ok: false, message: `Invalid ${flagName} value. Expected a positive integer.` }\n  }\n  return { ok: true, value }\n}\n\nfunction parseFormat(input: string | undefined): ParsedFormat {\n  if (input == null || input === '') {\n    return { ok: true, value: undefined }\n  }\n  if (input === 'markdown' || input === 'text' || input === 'html') {\n    return { ok: true, value: input }\n  }\n  return { ok: false, message: 'Invalid --format value. Expected markdown, text, or html.' }\n}\n\nfunction truncateSingleLine(text: string, maxLength: number): string {\n  const singleLine = text.replace(/\\s+/g, ' ').trim()\n  return singleLine.length <= maxLength ? singleLine : `${singleLine.slice(0, maxLength - 1)}…`\n}\n\nfunction sanitizeTerminalText(text: string): string {\n  return text\n    .replace(/\\x1B\\][^\\x07]*(?:\\x07|\\x1B\\\\)/g, '')\n    .replace(/\\x1B\\[[0-?]*[ -/]*[@-~]/g, '')\n    .replace(/\\x1B[\\x20-\\x2F]*[\\x30-\\x7E]/g, '')\n    .replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '')\n}\n"],"mappings":"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"}