{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cli/index.cjs","../../src/cli/index.ts","../../src/cli/report.ts","../../src/cli/commands/catalog.ts","../../src/cli/commands/cost.ts","../../src/cli/commands/models.ts"],"names":["program"],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cli/index.cjs","sourcesContent":[null,"#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { registerCatalogCommand } from \"./commands/catalog.js\";\nimport { registerCostCommand } from \"./commands/cost.js\";\nimport { registerModelsCommand } from \"./commands/models.js\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\nconst pkg = JSON.parse(\n  readFileSync(join(dirname(fileURLToPath(import.meta.url)), \"../../package.json\"), \"utf8\"),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n  .name(\"ai-tools\")\n  .description(\"@x12i/ai-tools — AI model catalog, cost calculation, and utilities\")\n  .version(pkg.version);\n\nregisterCatalogCommand(program);\nregisterModelsCommand(program);\nregisterCostCommand(program);\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n  console.error(error instanceof Error ? error.message : error);\n  process.exit(1);\n});\n","export function emitJson(data: unknown): void {\n  console.log(JSON.stringify(data, null, 2));\n}\n\nexport function emitHuman(lines: string[]): void {\n  for (const line of lines) {\n    console.log(line);\n  }\n}\n","import type { Command } from \"commander\";\nimport { refreshAiModelsCatalog, verifyAiModelsCatalog } from \"../../catalog/index.js\";\nimport { emitHuman, emitJson } from \"../report.js\";\n\nexport function registerCatalogCommand(program: Command): void {\n  const catalog = program.command(\"catalog\").description(\"Model catalog load and health commands\");\n\n  catalog\n    .command(\"refresh\")\n    .description(\"Fetch catalogs from open-assets.x12i.com and warm the cache\")\n    .option(\"--bundled-only\", \"Use bundled src/data catalogs only (no HTTP)\")\n    .option(\"--json\", \"Machine-readable JSON on stdout\")\n    .action(async (opts: { bundledOnly?: boolean; json?: boolean }) => {\n      const result = await refreshAiModelsCatalog({ bundledOnly: opts.bundledOnly });\n      if (opts.json) {\n        emitJson(result);\n      } else {\n        emitHuman([\n          \"✔  Catalog refresh complete\",\n          `  Direct: ${result.directCount} (${result.directSource})`,\n          `  OpenRouter: ${result.openRouterCount} (${result.openRouterSource})`,\n        ]);\n      }\n    });\n\n  catalog\n    .command(\"verify\")\n    .description(\"Validate direct + OpenRouter catalogs load successfully\")\n    .option(\"--bundled-only\", \"Use bundled src/data catalogs only (no HTTP)\")\n    .option(\"--json\", \"Machine-readable JSON on stdout\")\n    .action(async (opts: { bundledOnly?: boolean; json?: boolean }) => {\n      const report = await verifyAiModelsCatalog({ bundledOnly: opts.bundledOnly });\n\n      if (opts.json) {\n        emitJson(report);\n      } else {\n        emitHuman([\n          report.ok ? \"✔  Catalog verification passed\" : \"✗  Catalog verification FAILED\",\n          `  Direct models:     ${report.directCount} (${report.directSource})`,\n          `  OpenRouter models: ${report.openRouterCount} (${report.openRouterSource})`,\n          `  Direct URL:        ${report.directUrl}`,\n          `  OpenRouter URL:    ${report.openRouterUrl}`,\n        ]);\n      }\n\n      if (!report.ok) {\n        process.exit(1);\n      }\n    });\n}\n","import type { Command } from \"commander\";\nimport { CostCalculator } from \"../../cost/CostCalculator.js\";\nimport { AiModelsCatalogClient } from \"../../catalog/AiModelsCatalogClient.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction formatUsd(n: number): string {\n  return `$${n.toFixed(6)}`;\n}\n\nexport function registerCostCommand(program: Command): void {\n  program\n    .command(\"cost\")\n    .description(\"Estimate cost from catalog pricing\")\n    .requiredOption(\"--model <id>\", \"Model id or profile/choice key\")\n    .requiredOption(\"--prompt-tokens <n>\", \"Prompt token count\", (v) => Number.parseInt(v, 10))\n    .requiredOption(\n      \"--completion-tokens <n>\",\n      \"Completion token count\",\n      (v) => Number.parseInt(v, 10),\n    )\n    .option(\"--cached-tokens <n>\", \"Cached token count\", (v) => Number.parseInt(v, 10))\n    .option(\"--reasoning-tokens <n>\", \"Reasoning token count\", (v) => Number.parseInt(v, 10))\n    .option(\"--provider <id>\", \"Provider for pricing selection\", \"openrouter\")\n    .option(\"--json\", \"Output raw AiCostResult JSON\")\n    .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n    .action(async (opts: {\n      model: string;\n      promptTokens: number;\n      completionTokens: number;\n      cachedTokens?: number;\n      reasoningTokens?: number;\n      provider: string;\n      json?: boolean;\n      bundledOnly?: boolean;\n    }) => {\n      const catalogClient = new AiModelsCatalogClient({\n        cacheTtlMs: resolveCatalogCacheTtlMs(),\n        bundledOnly: opts.bundledOnly,\n      });\n\n      const calculator = new CostCalculator(catalogClient);\n\n      const result = await calculator.calculate({\n        tokens: {\n          prompt: opts.promptTokens,\n          completion: opts.completionTokens,\n          total: opts.promptTokens + opts.completionTokens,\n          cached: opts.cachedTokens,\n          reasoning: opts.reasoningTokens,\n        },\n        provider: opts.provider,\n        modelUsed: opts.model,\n      });\n\n      if (opts.json) {\n        console.log(JSON.stringify(result, null, 2));\n        return;\n      }\n\n      const b = result.breakdown;\n      console.log(`Model:        ${result.resolvedModelId}`);\n      if (result.usedModel && result.usedModel !== result.resolvedModelId) {\n        console.log(`Used model:   ${result.usedModel}`);\n      }\n      console.log(\n        `Prompt:       ${opts.promptTokens.toLocaleString()} tokens  →  ${formatUsd(b?.promptCostUsd ?? 0)}`,\n      );\n      console.log(\n        `Completion:   ${opts.completionTokens.toLocaleString()} tokens  →  ${formatUsd(b?.completionCostUsd ?? 0)}`,\n      );\n      console.log(\n        `Request fee:              →  ${formatUsd(b?.requestFlatCostUsd ?? 0)}`,\n      );\n      console.log(\"─\".repeat(38));\n      console.log(`Total:                    →  ${formatUsd(result.cost)}`);\n      console.log(\n        `Via OpenRouter: ${result.routedViaOpenRouter ? \"yes\" : \"no\"}`,\n      );\n    });\n}\n","import type { Command } from \"commander\";\nimport { AiModelsService } from \"../../models/AiModelsService.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction service(opts: { bundledOnly?: boolean }) {\n  return new AiModelsService({\n    cacheTtlMs: resolveCatalogCacheTtlMs(),\n    bundledOnly: opts.bundledOnly,\n  });\n}\n\nexport function registerModelsCommand(program: Command): void {\n  const models = program.command(\"models\").description(\"Inspect model catalogs\");\n\n  models\n    .command(\"list\")\n    .description(\"List models with optional filters\")\n    .option(\"--provider <id>\", \"Filter by providerId (e.g. openai, anthropic)\")\n    .option(\"--output-modality <m>\", \"Filter by output modality (text, image, audio, …)\")\n    .option(\"--input-modality <m>\", \"Filter by input modality\")\n    .option(\"--parameter <p>\", \"Filter by supported parameter (e.g. tools)\")\n    .option(\"--tools\", \"Only models that support tools\")\n    .option(\"--reasoning\", \"Only reasoning / thinking models\")\n    .option(\"--search <q>\", \"Search name, id, description\")\n    .option(\"--json\", \"Output raw JSON\")\n    .option(\"--limit <n>\", \"Max rows\", \"50\")\n    .option(\"--offset <n>\", \"Skip rows\", \"0\")\n    .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n    .action(async (opts: {\n      provider?: string;\n      outputModality?: string;\n      inputModality?: string;\n      parameter?: string;\n      tools?: boolean;\n      reasoning?: boolean;\n      search?: string;\n      json?: boolean;\n      limit?: string;\n      offset?: string;\n      bundledOnly?: boolean;\n    }) => {\n      const { models: rows, total } = await service(opts).listModels({\n        providerId: opts.provider,\n        outputModality: opts.outputModality,\n        inputModality: opts.inputModality,\n        supportedParameter: opts.parameter,\n        supportsTools: opts.tools ? true : undefined,\n        supportsReasoning: opts.reasoning ? true : undefined,\n        search: opts.search,\n        limit: Number.parseInt(opts.limit ?? \"50\", 10),\n        offset: Number.parseInt(opts.offset ?? \"0\", 10),\n      });\n\n      if (opts.json) {\n        console.log(JSON.stringify({ total, models: rows }, null, 2));\n        return;\n      }\n\n      console.log(\n        \"MODEL ID\".padEnd(42),\n        \"PROVIDER\".padEnd(14),\n        \"OUTPUT\".padEnd(10),\n        \"R\".padEnd(3),\n        \"NAME\",\n      );\n      console.log(\"─\".repeat(104));\n      for (const m of rows) {\n        console.log(\n          m.modelId.padEnd(42),\n          m.providerId.padEnd(14),\n          m.primaryOutputModality.padEnd(10),\n          (m.supportsReasoning ? \"yes\" : \"no\").padEnd(3),\n          m.name.slice(0, 40),\n        );\n      }\n      console.log(`\\n${rows.length} shown · ${total} matching`);\n    });\n\n  models\n    .command(\"get\")\n    .description(\"Get full model record by ID or alias\")\n    .argument(\"<modelId>\", \"Model ID or alias\")\n    .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n    .action(async (modelId: string, opts: { bundledOnly?: boolean }) => {\n      const model = await service(opts).getModelInfo(modelId);\n      if (!model) {\n        console.error(`Model not found: ${modelId}`);\n        process.exit(1);\n      }\n      console.log(JSON.stringify(model, null, 2));\n    });\n\n  models\n    .command(\"resolve\")\n    .description(\"Resolve provider + model to canonical id\")\n    .requiredOption(\"--model <m>\", \"Model string (required)\")\n    .option(\"--provider <p>\", \"Provider hint (openrouter, openai, …)\")\n    .option(\"--threshold <n>\", \"Confidence threshold 0–1\", \"0.6\")\n    .option(\"--json\", \"Output raw ModelResolutionResult JSON\")\n    .option(\"--verbose\", \"Show strategy trail\")\n    .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n    .action(async (opts: {\n      model: string;\n      provider?: string;\n      threshold?: string;\n      json?: boolean;\n      verbose?: boolean;\n      bundledOnly?: boolean;\n    }) => {\n      const result = await service(opts).resolve(opts.model, opts.provider);\n\n      if (opts.json) {\n        console.log(JSON.stringify(result, null, 2));\n        return;\n      }\n\n      const providerLabel = opts.provider ?? \"unspecified\";\n      console.log(`Input:     provider=\"${providerLabel}\"  model=\"${opts.model}\"`);\n\n      if (opts.verbose && result.found) {\n        console.log(`Normalised: model=\"${result.normalisedInput}\"`);\n        console.log(\"\\nStrategy trail:\");\n        for (const s of result.resolvedVia) {\n          console.log(`  • ${s}`);\n        }\n        console.log();\n      }\n\n      if (!result.found) {\n        console.log(\"Result:    NOT FOUND\");\n        console.log(`Reason:    ${result.reason}`);\n        if (result.bestRejectedCandidate) {\n          console.log(\n            `Candidate: ${result.bestRejectedCandidate.modelId} (confidence ${result.bestRejectedCandidate.confidence.toFixed(2)})`,\n          );\n        }\n        console.log('Tip:       Run \"ai-tools catalog refresh\" or pass a profile/choice key / concrete model id.');\n        process.exit(1);\n        return;\n      }\n\n      console.log(`Resolved:  ${result.modelId}`);\n      console.log(`Name:      ${result.record?.name ?? \"(no catalog record)\"}`);\n      console.log(`Strategy:  ${result.resolvedVia.join(\" → \")}`);\n      console.log(`Confidence: ${result.confidence.toFixed(2)}`);\n      console.log(`Via OR:    ${result.routedViaOpenRouter ? \"yes\" : \"no\"}`);\n    });\n\n  models\n    .command(\"vendor\")\n    .description(\"Find model vendor from model name alone (best-effort)\")\n    .requiredOption(\"--model <m>\", \"Model string (required)\")\n    .option(\"--openrouter\", \"Return OpenRouter transport shape (provider openrouter, model vendor/slug)\")\n    .option(\"--json\", \"Output raw JSON\")\n    .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n    .action(async (opts: {\n      model: string;\n      openrouter?: boolean;\n      json?: boolean;\n      bundledOnly?: boolean;\n    }) => {\n      const ref = await service(opts).resolveVendor(opts.model, {\n        asOpenRouter: opts.openrouter,\n      });\n\n      if (opts.json) {\n        console.log(JSON.stringify(ref, null, 2));\n        if (!ref) process.exit(1);\n        return;\n      }\n\n      console.log(`Input:  model=\"${opts.model}\"`);\n      if (!ref) {\n        console.log(\"Result: NOT FOUND\");\n        process.exit(1);\n        return;\n      }\n\n      console.log(`Vendor:   ${ref.provider}`);\n      console.log(`Model:    ${ref.model}`);\n    });\n\n  models\n    .command(\"count\")\n    .description(\"Count models matching filters\")\n    .option(\"--provider <id>\", \"Filter by providerId\")\n    .option(\"--output-modality <m>\", \"Filter by output modality\")\n    .option(\"--parameter <p>\", \"Filter by supported parameter\")\n    .option(\"--tools\", \"Only models that support tools\")\n    .option(\"--reasoning\", \"Only reasoning / thinking models\")\n    .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n    .action(async (opts: {\n      provider?: string;\n      outputModality?: string;\n      parameter?: string;\n      tools?: boolean;\n      reasoning?: boolean;\n      bundledOnly?: boolean;\n    }) => {\n      const n = await service(opts).countModels({\n        providerId: opts.provider,\n        outputModality: opts.outputModality,\n        supportedParameter: opts.parameter,\n        supportsTools: opts.tools ? true : undefined,\n        supportsReasoning: opts.reasoning ? true : undefined,\n      });\n      console.log(n);\n    });\n}\n"]}