@sriinnu/kosha-discovery 0.6.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +95 -263
  2. package/dist/cli-cmd-model.d.ts +48 -0
  3. package/dist/cli-cmd-model.d.ts.map +1 -0
  4. package/dist/cli-cmd-model.js +231 -0
  5. package/dist/cli-cmd-model.js.map +1 -0
  6. package/dist/cli-cmd-query.d.ts +40 -0
  7. package/dist/cli-cmd-query.d.ts.map +1 -0
  8. package/dist/cli-cmd-query.js +303 -0
  9. package/dist/cli-cmd-query.js.map +1 -0
  10. package/dist/cli-commands.d.ts +65 -75
  11. package/dist/cli-commands.d.ts.map +1 -1
  12. package/dist/cli-commands.js +93 -543
  13. package/dist/cli-commands.js.map +1 -1
  14. package/dist/cli-format.d.ts +32 -0
  15. package/dist/cli-format.d.ts.map +1 -1
  16. package/dist/cli-format.js +51 -0
  17. package/dist/cli-format.js.map +1 -1
  18. package/dist/cli-help.d.ts +19 -0
  19. package/dist/cli-help.d.ts.map +1 -0
  20. package/dist/cli-help.js +150 -0
  21. package/dist/cli-help.js.map +1 -0
  22. package/dist/cli.js +4 -1
  23. package/dist/cli.js.map +1 -1
  24. package/dist/discovery/anthropic.d.ts +8 -1
  25. package/dist/discovery/anthropic.d.ts.map +1 -1
  26. package/dist/discovery/anthropic.js +26 -3
  27. package/dist/discovery/anthropic.js.map +1 -1
  28. package/dist/discovery/base.d.ts +26 -0
  29. package/dist/discovery/base.d.ts.map +1 -1
  30. package/dist/discovery/base.js +55 -2
  31. package/dist/discovery/base.js.map +1 -1
  32. package/dist/discovery/free-tier.d.ts +31 -0
  33. package/dist/discovery/free-tier.d.ts.map +1 -0
  34. package/dist/discovery/free-tier.js +47 -0
  35. package/dist/discovery/free-tier.js.map +1 -0
  36. package/dist/discovery/google.d.ts +8 -1
  37. package/dist/discovery/google.d.ts.map +1 -1
  38. package/dist/discovery/google.js +25 -3
  39. package/dist/discovery/google.js.map +1 -1
  40. package/dist/discovery/index.d.ts +3 -6
  41. package/dist/discovery/index.d.ts.map +1 -1
  42. package/dist/discovery/index.js +36 -55
  43. package/dist/discovery/index.js.map +1 -1
  44. package/dist/discovery/litellm-seed.d.ts +32 -0
  45. package/dist/discovery/litellm-seed.d.ts.map +1 -0
  46. package/dist/discovery/litellm-seed.js +252 -0
  47. package/dist/discovery/litellm-seed.js.map +1 -0
  48. package/dist/discovery/modelsdev-catalog.d.ts +95 -0
  49. package/dist/discovery/modelsdev-catalog.d.ts.map +1 -0
  50. package/dist/discovery/modelsdev-catalog.js +131 -0
  51. package/dist/discovery/modelsdev-catalog.js.map +1 -0
  52. package/dist/discovery/modelsdev-seed.d.ts +19 -0
  53. package/dist/discovery/modelsdev-seed.d.ts.map +1 -0
  54. package/dist/discovery/modelsdev-seed.js +203 -0
  55. package/dist/discovery/modelsdev-seed.js.map +1 -0
  56. package/dist/discovery/openai-compatible.d.ts.map +1 -1
  57. package/dist/discovery/openai-compatible.js +12 -1
  58. package/dist/discovery/openai-compatible.js.map +1 -1
  59. package/dist/discovery/openai.d.ts +9 -1
  60. package/dist/discovery/openai.d.ts.map +1 -1
  61. package/dist/discovery/openai.js +31 -8
  62. package/dist/discovery/openai.js.map +1 -1
  63. package/dist/discovery/promo-overrides.d.ts +54 -0
  64. package/dist/discovery/promo-overrides.d.ts.map +1 -0
  65. package/dist/discovery/promo-overrides.js +74 -0
  66. package/dist/discovery/promo-overrides.js.map +1 -0
  67. package/dist/discovery/public-seed.d.ts +30 -0
  68. package/dist/discovery/public-seed.d.ts.map +1 -0
  69. package/dist/discovery/public-seed.js +51 -0
  70. package/dist/discovery/public-seed.js.map +1 -0
  71. package/dist/discovery-contract.d.ts +14 -2
  72. package/dist/discovery-contract.d.ts.map +1 -1
  73. package/dist/discovery-contract.js +28 -0
  74. package/dist/discovery-contract.js.map +1 -1
  75. package/dist/enrichment/litellm-catalog.d.ts +81 -0
  76. package/dist/enrichment/litellm-catalog.d.ts.map +1 -0
  77. package/dist/enrichment/litellm-catalog.js +129 -0
  78. package/dist/enrichment/litellm-catalog.js.map +1 -0
  79. package/dist/enrichment/litellm.d.ts +9 -2
  80. package/dist/enrichment/litellm.d.ts.map +1 -1
  81. package/dist/enrichment/litellm.js +168 -20
  82. package/dist/enrichment/litellm.js.map +1 -1
  83. package/dist/index.d.ts +3 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +2 -0
  86. package/dist/index.js.map +1 -1
  87. package/dist/mcp-server.d.ts +18 -0
  88. package/dist/mcp-server.d.ts.map +1 -0
  89. package/dist/mcp-server.js +293 -0
  90. package/dist/mcp-server.js.map +1 -0
  91. package/dist/model-features.d.ts +77 -0
  92. package/dist/model-features.d.ts.map +1 -0
  93. package/dist/model-features.js +245 -0
  94. package/dist/model-features.js.map +1 -0
  95. package/dist/provider-catalog.d.ts +9 -0
  96. package/dist/provider-catalog.d.ts.map +1 -1
  97. package/dist/provider-catalog.js +22 -0
  98. package/dist/provider-catalog.js.map +1 -1
  99. package/dist/proxy.d.ts +31 -0
  100. package/dist/proxy.d.ts.map +1 -0
  101. package/dist/proxy.js +193 -0
  102. package/dist/proxy.js.map +1 -0
  103. package/dist/registry-discovery.d.ts.map +1 -1
  104. package/dist/registry-discovery.js +12 -2
  105. package/dist/registry-discovery.js.map +1 -1
  106. package/dist/registry-runtime.d.ts +40 -1
  107. package/dist/registry-runtime.d.ts.map +1 -1
  108. package/dist/registry-runtime.js +502 -30
  109. package/dist/registry-runtime.js.map +1 -1
  110. package/dist/registry-selection.js +2 -0
  111. package/dist/registry-selection.js.map +1 -1
  112. package/dist/registry.d.ts +9 -0
  113. package/dist/registry.d.ts.map +1 -1
  114. package/dist/registry.js +11 -1
  115. package/dist/registry.js.map +1 -1
  116. package/dist/server.d.ts +2 -0
  117. package/dist/server.d.ts.map +1 -1
  118. package/dist/server.js +6 -0
  119. package/dist/server.js.map +1 -1
  120. package/dist/tokenizer-family.d.ts +39 -0
  121. package/dist/tokenizer-family.d.ts.map +1 -0
  122. package/dist/tokenizer-family.js +92 -0
  123. package/dist/tokenizer-family.js.map +1 -0
  124. package/dist/types.d.ts +186 -0
  125. package/dist/types.d.ts.map +1 -1
  126. package/logo.png +0 -0
  127. package/package.json +15 -3
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="logo.svg" alt="Kosha — AI Model Discovery" width="140" />
2
+ <img src="logo.png" alt="Kosha — AI Model Discovery" width="140" />
3
3
  </p>
4
4
 
5
5
  <h1 align="center">kosha-discovery — कोश</h1>
@@ -9,255 +9,122 @@
9
9
  <p align="center">
10
10
  <a href="https://www.npmjs.com/package/@sriinnu/kosha-discovery"><img src="https://img.shields.io/npm/v/%40sriinnu%2Fkosha-discovery?color=7C3AED&label=npm" alt="npm version" /></a>
11
11
  <a href="https://www.npmjs.com/package/@sriinnu/kosha-discovery"><img src="https://img.shields.io/npm/dm/%40sriinnu%2Fkosha-discovery?color=0EA5E9&label=downloads" alt="npm downloads" /></a>
12
- <a href="https://github.com/sriinnu/kosha-discovery/releases/tag/v0.6.1"><img src="https://img.shields.io/badge/release-v0.6.1-7C3AED?logo=github" alt="release v0.6.1" /></a>
13
12
  <a href="https://github.com/sriinnu/kosha-discovery/blob/main/LICENSE"><img src="https://img.shields.io/github/license/sriinnu/kosha-discovery?color=F59E0B" alt="license" /></a>
14
13
  <a href="https://www.npmjs.com/package/@sriinnu/kosha-discovery"><img src="https://img.shields.io/node/v/%40sriinnu%2Fkosha-discovery?color=5B21B6" alt="node version" /></a>
15
- <a href="https://github.com/sriinnu/kosha-discovery/actions/workflows/release-npm.yml"><img src="https://img.shields.io/github/actions/workflow/status/sriinnu/kosha-discovery/release-npm.yml?label=release%20workflow" alt="release workflow status" /></a>
16
- <a href="https://github.com/sriinnu/kosha-discovery/actions/workflows/update-kosha-snapshot.yml"><img src="https://img.shields.io/github/actions/workflow/status/sriinnu/kosha-discovery/update-kosha-snapshot.yml?label=snapshot%20workflow" alt="snapshot workflow status" /></a>
17
- <a href="https://github.com/sriinnu/kosha-discovery/actions/workflows/provider-smoke.yml"><img src="https://img.shields.io/github/actions/workflow/status/sriinnu/kosha-discovery/provider-smoke.yml?label=provider%20smoke" alt="provider smoke status" /></a>
18
- <a href="https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json"><img src="https://img.shields.io/badge/pricing%20source-LiteLLM-2563EB" alt="LiteLLM pricing source" /></a>
19
14
  </p>
20
15
 
21
- > **v0.6.1**adds OpenRouter prompt-cache read/write rates, a portable v1 registry manifest at `~/.kosha/registry.json`, honest cache-hit feedback on the CLI, a `kosha update` alias for `refresh`, and patches for two security-scanner false positives that were silently breaking OpenRouter ingestion.
22
-
23
- Kosha (कोश — treasury/repository) automatically discovers AI models across providers, resolves credentials from CLI tools and environment variables, enriches models with pricing data, and exposes the catalog via library, CLI, and HTTP API.
24
-
25
- ## Why
26
-
27
- AI applications hardcode model IDs, pricing, and provider configs. When providers add models or change pricing, every app breaks. Kosha solves this:
28
-
29
- - **Dynamic discovery** — fetches real model lists from provider APIs
30
- - **Offline direct catalogs** — OpenAI, Anthropic, and Google fallback model coverage even without API keys
31
- - **Smart credentials** — finds API keys from env vars, CLI tools (Claude, Copilot, Gemini CLI), and config files
32
- - **Pricing enrichment** — fills in input/output/reasoning/cache costs and context windows from litellm's community-maintained dataset
33
- - **Proxy vs origin pricing** — preserves route pricing and exposes origin-provider reference pricing for proxy-served models
34
- - **Persistent cache + portable manifest** — 24h on-disk cache at `~/.kosha/cache`, plus a stable v1 JSON manifest at `~/.kosha/registry.json` that any language or tool can read directly
35
- - **Model aliases** — `sonnet` → `claude-sonnet-4-20250514`, updated as models evolve
36
- - **Role matrix** — query provider -> model -> roles (`chat`, `embedding`, `image_generation`, etc.)
37
- - **Cheapest routing** — rank cheapest eligible models for tasks like embeddings or image generation
38
- - **Local LLM scanning** — detects Ollama models alongside cloud providers
39
- - **Three access patterns** — use as a library, CLI tool, or HTTP API
16
+ Kosha (कोश*treasury*) discovers AI models across providers, resolves credentials, enriches with pricing, and exposes the catalog through a library, CLI, HTTP API, and a built-in OpenAI-compatible proxy. One source of truth for model identity, pricing, and routing so your app doesn't break when providers ship new SKUs or change rates.
40
17
 
41
18
  ## Install
42
19
 
43
20
  ```bash
44
- npm install kosha-discovery # library or HTTP server
45
- npm install -g kosha-discovery # global `kosha` CLI
46
- ```
47
-
48
- Or with pnpm:
49
-
50
- ```bash
51
- pnpm add kosha-discovery
21
+ npm install @sriinnu/kosha-discovery # library / server
22
+ npm install -g @sriinnu/kosha-discovery # global `kosha` CLI
52
23
  ```
53
24
 
54
- ## Getting Started (CLI)
55
-
56
- ```bash
57
- # 1. First run — discovers all reachable providers and writes the cache + manifest
58
- kosha discover
59
- # → Anthropic: 3 models, OpenAI: 7 models, ...
60
- # → Cached to ~/.kosha/cache · Manifest: ~/.kosha/registry.json
61
-
62
- # 2. Subsequent commands read instantly from the 24h on-disk cache
63
- kosha list
64
- # → Loaded 380 models from cache (9h ago). Run "kosha update" to refresh.
65
-
66
- # 3. Force a fresh pull from all provider APIs
67
- kosha update # alias for `kosha refresh`
68
- ```
69
-
70
- After any discovery, a **stable, third-party-readable manifest** is written to
71
- `~/.kosha/registry.json`. It holds the full v1 snapshot — providers, models,
72
- pricing, capabilities, and health — in a documented schema. Any tool that can
73
- read JSON can consume it:
74
-
75
- ```bash
76
- jq '.models[] | select(.pricing.inputPerMillion < 0.1) | .modelId' ~/.kosha/registry.json
77
- ```
78
-
79
- ```python
80
- import json, pathlib
81
- data = json.loads(pathlib.Path("~/.kosha/registry.json").expanduser().read_text())
82
- print(len(data["models"]), "models from", len(data["providers"]), "providers")
83
- ```
84
-
85
- ## Development (pnpm)
86
-
87
- ```bash
88
- pnpm install
89
- pnpm run build
90
- pnpm run test
91
- ```
92
-
93
- ## Quick Start
25
+ ## Quick start
94
26
 
95
27
  ### Library
96
28
 
97
29
  ```typescript
98
- import { createKosha } from "kosha-discovery";
30
+ import { createKosha } from "@sriinnu/kosha-discovery";
99
31
 
100
32
  const kosha = await createKosha();
101
33
 
102
- const models = kosha.models(); // all models
103
- const embeddings = kosha.models({ mode: "embedding" }); // filter by mode
104
- const model = kosha.model("sonnet"); // resolve alias
105
- const cheapest = kosha.cheapestModels({ role: "image", limit: 3 });
106
-
107
- console.log(model.pricing); // { inputPerMillion: 3, outputPerMillion: 15, ... }
34
+ const models = kosha.models(); // all
35
+ const cheapest = kosha.cheapestModels({ role: "image" }); // ranked
36
+ const sonnet = kosha.model("sonnet"); // alias resolves
37
+ console.log(sonnet.pricing); // { inputPerMillion: 3, outputPerMillion: 15, ... }
108
38
  ```
109
39
 
110
40
  ### CLI
111
41
 
112
42
  ```bash
113
- kosha discover # discover all providers (writes cache + manifest)
114
- kosha list # list models (instant from cache)
115
- kosha list --provider anthropic # filter by provider
116
- kosha search gemini # fuzzy search
117
- kosha model sonnet # model details
118
- kosha cheapest --role embeddings # cheapest for a task
119
- kosha routes gpt-4o # all provider routes
120
- kosha providers # provider status
121
- kosha update # force re-discover (alias: refresh)
122
- kosha latest # force-fetch latest provider/model details
123
- kosha latest --provider openai # latest for one provider
124
- kosha serve --port 3000 # start HTTP API
43
+ kosha discover # discover all providers (writes cache + manifest)
44
+ kosha list --provider anthropic # filter from local cache
45
+ kosha model sonnet # details for one model (alias-aware)
46
+ kosha cheapest --role embeddings # rank cheapest for a role
47
+ kosha update # force a fresh fetch
48
+ kosha serve --port 3000 # HTTP API
125
49
  ```
126
50
 
127
- Results live at `~/.kosha/cache` (24h TTL) and `~/.kosha/registry.json` (stable
128
- v1 manifest). See [docs/cli.md](docs/cli.md) for the full reference.
129
-
130
- ### Auto-Fetch JSON Snapshot
51
+ After each discovery, a stable v1 manifest lands at `~/.kosha/registry.json` — any tool that reads JSON can consume it:
131
52
 
132
53
  ```bash
133
- # one-shot latest snapshot
134
- pnpm run autofetch:once
135
-
136
- # custom output/provider
137
- pnpm run autofetch:once -- --provider openai --output ./data/openai-latest.json
138
-
139
- # continuous loop (default 3600s)
140
- pnpm run autofetch -- --interval-seconds 900
54
+ jq '.models[] | select(.pricing.inputPerMillion < 0.1) | .modelId' ~/.kosha/registry.json
141
55
  ```
142
56
 
143
- By default this writes JSON to `./data/kosha-latest.json`.
144
-
145
- ### CI / Smoke Checks
146
-
147
- Workflow files:
148
-
149
- - `.github/workflows/update-kosha-snapshot.yml`
150
- - `.github/workflows/provider-smoke.yml`
151
-
152
- Snapshot workflow:
153
-
154
- - Scheduled: weekly (Monday 06:00 UTC)
155
- - Manual: GitHub UI -> Actions -> `Update Kosha Snapshot` -> `Run workflow`
156
- - Optional manual inputs:
157
- - `provider` (empty = all providers)
158
- - `output` (default `data/kosha-latest.json`)
159
- - Disable scheduled runs without removing the workflow by setting `KOSHA_SNAPSHOT_SCHEDULE_ENABLED=false`
160
- - Manual `Run workflow` still works even when schedule is disabled
161
-
162
- Provider smoke workflow:
163
-
164
- - Scheduled: nightly (03:00 UTC)
165
- - Manual: GitHub UI -> Actions -> `Provider Smoke Checks` -> `Run workflow`
166
- - Runs only when repository variable `KOSHA_PROVIDER_SMOKE_ENABLED=true`
167
- - Manual dispatch can override that gate with `force=true`
168
- - Installs with pnpm, builds, then runs a node inline smoke script against real provider endpoints
169
- - Providers without the required secrets are skipped instead of failing the job
170
- - Always uploads `artifacts/provider-smoke-report.json`
171
-
172
- Provider smoke secrets:
173
-
174
- - OpenAI: `OPENAI_API_KEY`
175
- - Google/Gemini: `GOOGLE_API_KEY` or `GEMINI_API_KEY`
176
- - Mistral: `MISTRAL_API_KEY`
177
- - DeepSeek: `DEEPSEEK_API_KEY`
178
- - Moonshot: `MOONSHOT_API_KEY` or `KIMI_API_KEY`
179
- - GLM: `GLM_API_KEY` or `ZHIPUAI_API_KEY`
180
- - Z.AI: `ZAI_API_KEY`
181
- - MiniMax: `MINIMAX_API_KEY`
182
- - OpenRouter: optional `OPENROUTER_API_KEY`
183
- - Bedrock: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION`
184
- - Vertex AI: `GOOGLE_APPLICATION_CREDENTIALS_JSON`, `GOOGLE_CLOUD_PROJECT`
185
-
186
- Security controls in these workflows:
187
-
188
- - Snapshot workflow commits only the configured snapshot file path plus its checksum file, never broad `git add -A`
189
- - Snapshot workflow validates the generated snapshot against a local JSON schema before commit
190
- - Snapshot workflow runs a high-signal secret-pattern scan on snapshot output before commit
191
- - Snapshot workflow writes `data/kosha-latest.sha256` alongside the snapshot
192
- - Snapshot workflow uploads an always-on artifact with run metadata, provider summaries, and failure details
193
- - Provider smoke workflow never echoes secret values and records a machine-readable JSON report
57
+ ### HTTP API
194
58
 
195
- ### Branch Protection Audit
59
+ ```
60
+ GET /api/models[?provider=…&role=…] GET /api/models/:idOrAlias
61
+ GET /api/models/:idOrAlias/routes GET /api/models/cheapest?role=…
62
+ GET /api/providers GET /api/roles
63
+ POST /api/refresh GET /health
64
+ ```
196
65
 
197
- Workflow file: `.github/workflows/branch-protection-check.yml`
66
+ ### Proxy
198
67
 
199
- - Runs on `main` and via `workflow_dispatch`
200
- - Reads the `main` branch protection rule through the GitHub API
201
- - Expects the required status checks list to include `Branch Protection Check / audit`
202
- - Uploads a warning artifact instead of failing when the token cannot read branch protection settings
68
+ Kosha runs as an OpenAI-compatible proxy. Point your SDK at `http://localhost:3000/proxy/v1` and it resolves the model, picks the right provider, injects credentials, and forwards — streaming included.
203
69
 
204
- Keep that check name stable when you rename the workflow or job, and update the protection rule whenever you add more required checks.
70
+ ```bash
71
+ kosha serve # start on :3000
72
+ ```
205
73
 
206
- ### Where Data Is Stored
74
+ ```typescript
75
+ import OpenAI from "openai";
76
+
77
+ const client = new OpenAI({
78
+ baseURL: "http://localhost:3000/proxy/v1",
79
+ apiKey: "not-used", // kosha resolves credentials from env
80
+ });
81
+
82
+ // Use any canonical model ID or alias
83
+ const res = await client.chat.completions.create({
84
+ model: "sonnet",
85
+ messages: [{ role: "user", content: "hello" }],
86
+ });
87
+
88
+ // Let kosha pick the cheapest model you have a key for
89
+ const cheap = await client.chat.completions.create({
90
+ model: "kosha:cheapest",
91
+ messages: [{ role: "user", content: "hello" }],
92
+ });
93
+
94
+ // Cheapest model with tool_use and at least 128k context
95
+ const routed = await client.chat.completions.create({
96
+ model: "kosha:cheapest[tool_use,128k]",
97
+ messages: [{ role: "user", content: "hello" }],
98
+ });
99
+ ```
207
100
 
208
- - Git repo: model/provider discovery data is **not** committed by default.
209
- - Runtime cache: `~/.kosha/cache/*.json` (machine-local, TTL-based).
210
- - Exported snapshot: only if you run `autofetch`/`autofetch:once` with an output file and commit it yourself.
211
- - Stable manifest: `~/.kosha/registry.json` is rewritten after every discovery and holds the full v1 snapshot for third-party consumers.
101
+ **`kosha:cheapest` filter syntax** (comma-separated, combinable):
212
102
 
213
- ### HTTP API
103
+ | Filter | Example | Meaning |
104
+ |--------|---------|---------|
105
+ | capability | `tool_use`, `vision` | model must have this tag |
106
+ | `<N>k` | `128k`, `200k` | minimum context window |
107
+ | `provider:<id>` | `provider:groq` | pin to a specific provider |
214
108
 
215
- ```bash
216
- kosha serve --port 3000
217
- ```
109
+ The response always includes `x-kosha-model`, `x-kosha-provider`, and `x-kosha-requested` headers so the caller knows exactly what ran.
218
110
 
219
- ```
220
- GET /api/models — All models (filterable)
221
- GET /api/models/cheapest — Cheapest ranked models
222
- GET /api/models/:idOrAlias — Single model
223
- GET /api/models/:idOrAlias/routes — All provider routes
224
- GET /api/roles — Provider → model → roles matrix
225
- GET /api/providers — All providers
226
- POST /api/refresh — Re-discover
227
- GET /health — Health check
228
- ```
111
+ Supported transports: `openai`, `openai-compatible-http`, `ollama`. Anthropic, Google, Bedrock, and Vertex require wire-format translation — not yet proxied.
229
112
 
230
- ## Supported Providers
113
+ ## Supported providers
231
114
 
232
- | Provider | Discovery | Credential Sources |
233
- |----------|-----------|-------------------|
234
- | Anthropic | API (`/v1/models`) | `ANTHROPIC_API_KEY`, Claude CLI, Codex CLI |
235
- | OpenAI | API (`/v1/models`) | `OPENAI_API_KEY`, GitHub Copilot tokens |
236
- | Google | API (`/v1beta/models`) | `GOOGLE_API_KEY`, `GEMINI_API_KEY`, Gemini CLI, gcloud |
115
+ | Provider | Discovery | Credential sources |
116
+ |----------|-----------|--------------------|
117
+ | Anthropic | `/v1/models` | `ANTHROPIC_API_KEY`, Claude CLI, Codex CLI |
118
+ | OpenAI | `/v1/models` | `OPENAI_API_KEY`, GitHub Copilot tokens |
119
+ | Google | `/v1beta/models` | `GOOGLE_API_KEY`, `GEMINI_API_KEY`, Gemini CLI, gcloud |
237
120
  | AWS Bedrock | SDK → CLI → static | `AWS_ACCESS_KEY_ID`, `~/.aws/credentials`, SSO, IAM |
238
- | Vertex AI | API + gcloud | `GOOGLE_APPLICATION_CREDENTIALS`, gcloud ADC |
239
- | Ollama | Local API | None needed (local) |
240
- | OpenRouter | API | `OPENROUTER_API_KEY` (optional) |
241
- | NVIDIA | API | `NVIDIA_API_KEY` |
242
- | Together AI | API | `TOGETHER_API_KEY` |
243
- | Fireworks AI | API | `FIREWORKS_API_KEY` |
244
- | Groq | API | `GROQ_API_KEY` |
245
- | Mistral AI | API | `MISTRAL_API_KEY` |
246
- | DeepInfra | API | `DEEPINFRA_API_KEY` |
247
- | Cohere | API | `CO_API_KEY` |
248
- | Cerebras | API | `CEREBRAS_API_KEY` |
249
- | Perplexity | API | `PERPLEXITY_API_KEY` |
250
- | DeepSeek | API | `DEEPSEEK_API_KEY` |
251
- | Moonshot (Kimi) | API | `MOONSHOT_API_KEY` / `KIMI_API_KEY` |
252
- | GLM (Zhipu) | API | `GLM_API_KEY` / `ZHIPUAI_API_KEY` |
253
- | Z.AI | API | `ZAI_API_KEY` |
254
- | MiniMax | API | `MINIMAX_API_KEY` |
255
-
256
- ## Security
257
-
258
- All external data (API responses, CLI output, cache reads) is scanned for 9 threat types before use: credential leaks, base64 payloads, script/shell injection, data URIs, null bytes, prototype pollution, hex blobs, and oversized strings. A pre-commit hook blocks secrets at commit time.
259
-
260
- See [docs/security.md](docs/security.md) for the full threat catalogue and architecture.
121
+ | Vertex AI | API + gcloud | `GOOGLE_APPLICATION_CREDENTIALS`, ADC |
122
+ | Ollama | local API | (local) |
123
+ | OpenRouter | API | `OPENROUTER_API_KEY` *(optional)* |
124
+ | NVIDIA / Together / Fireworks / Groq / Cerebras / Cohere / DeepInfra / Perplexity | API | provider key env var |
125
+ | DeepSeek / Mistral / Moonshot (Kimi) / GLM (Zhipu) / Z.AI / MiniMax | API | provider key env var |
126
+
127
+ Full credential setup: [docs/credentials.md](docs/credentials.md).
261
128
 
262
129
  ## Architecture
263
130
 
@@ -265,70 +132,35 @@ See [docs/security.md](docs/security.md) for the full threat catalogue and archi
265
132
  <img src="architecture.svg" alt="Kosha Architecture" width="720" />
266
133
  </p>
267
134
 
268
- ```
269
- ┌─────────────────────────────────────────────────────┐
270
- │ Your Application │
271
- │ import { createKosha } from "kosha" │
272
- └───────────────────────┬─────────────────────────────┘
273
-
274
- ┌───────────────────────▼─────────────────────────────┐
275
- │ ModelRegistry │
276
- │ models() · providerRoles() · cheapestModels() │
277
- └──┬──────────┬──────────────┬───────────────┬────────┘
278
- │ │ │ │
279
- ┌──▼───┐ ┌───▼────────┐ ┌───▼──────────┐ ┌──▼─────────┐
280
- │Alias │ │ Discovery │ │ Enrichment │ │ Resilience │
281
- │System│ │ Layer │ │ Layer │ │ Layer │
282
- └──────┘ └───┬────────┘ └──────┬───────┘ └────────────┘
283
- │ │ CircuitBreaker
284
- ┌────────┼────────┐ │ HealthTracker
285
- ▼ ▼ ▼ ▼ StaleCachePolicy
286
- Direct OpenAI- Cloud litellm
287
- API Compatible Proxies JSON
288
- ```
135
+ Discovery layer talks to provider APIs and local catalogs. Enrichment layer fills pricing and context windows from the LiteLLM catalog and models.dev. Resilience layer (circuit breaker + stale-cache fallback + health tracker) keeps a flaky provider a degraded read, never a crash. Manifest layer writes a v1-stable JSON snapshot so downstream consumers — `tokmeter`, `chitragupta`, `ayuh` — read prices from one source instead of inventing their own. Proxy layer exposes an OpenAI-compatible endpoint that resolves `kosha:cheapest[…]` hints at request time, injects credentials, and forwards to the winning provider.
289
136
 
290
- ## Documentation
137
+ ## Docs
291
138
 
292
- | Doc | What's in it |
293
- |-----|-------------|
294
- | [Credentials](docs/credentials.md) | Setup for all 21 providers (env vars, CLI tools, config files) |
295
- | [CLI Reference](docs/cli.md) | All commands, flags, and example output |
296
- | [HTTP API](docs/api.md) | All endpoints, parameters, and response schemas |
297
- | [Configuration](docs/configuration.md) | Aliases, routing, pricing enrichment, programmatic config |
298
- | [Architecture](docs/architecture.md) | Discovery flow, module map, data pipeline, adding providers |
299
- | [Resilience](docs/resilience.md) | Circuit breakers, stale cache fallback, health monitoring |
139
+ | | |
140
+ |---|---|
141
+ | [Credentials](docs/credentials.md) | Env vars, CLI tools, and config files for every provider |
142
+ | [CLI](docs/cli.md) | Commands, flags, examples |
143
+ | [HTTP API](docs/api.md) | Endpoints, parameters, response schemas |
144
+ | [Configuration](docs/configuration.md) | Aliases, routing, enrichment, programmatic config |
145
+ | [Architecture](docs/architecture.md) | Discovery flow, module map, adding providers |
146
+ | [Resilience](docs/resilience.md) | Circuit breakers, stale cache, health |
300
147
  | [Security](docs/security.md) | Threat catalogue, runtime scanning, pre-commit hook |
301
148
  | [Discovery Plane v1](docs/discovery-plane-v1.md) | Stable daemon contract (deltas, SSE watch, binding hints) |
302
149
 
303
- ## Release & Tagging
150
+ ## Release
304
151
 
305
- Package: `@sriinnu/kosha-discovery`
152
+ Tag-driven via GitHub Actions:
306
153
 
307
- This repo uses a human-in-the-loop release flow:
308
-
309
- 1. Update version in `package.json` and lockfiles locally.
310
- 2. Create a signed tag and push it:
311
- ```bash
312
- git tag -s v0.6.0 -m "v0.6.0"
313
- git push origin v0.6.0
314
- ```
315
- 3. In GitHub Actions, run `Manual Release (Tag + npm)` and provide `tag=v0.6.0`.
316
- 4. Workflow verifies tag/version match, builds/tests, then publishes to npm (if enabled) and creates a GitHub Release.
154
+ ```bash
155
+ git tag -s vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z
156
+ # Actions "Manual Release (Tag + npm)" → run with tag=vX.Y.Z
157
+ ```
317
158
 
318
- Required secret for publish:
319
- - `NPM_TOKEN` (publish rights for `@sriinnu` scope)
159
+ The workflow checks tag ↔ package.json match, builds, tests, publishes to npm, and creates the GitHub Release. Requires the `NPM_TOKEN` secret.
320
160
 
321
161
  ## Credits
322
162
 
323
- - **[litellm](https://github.com/BerriAI/litellm)** -- Community-maintained model pricing database
324
- - **[openrouter](https://openrouter.ai)** -- Model aggregation API
325
- - **[ollama](https://ollama.ai)** -- Local LLM runtime
326
- - **[chitragupta](https://github.com/sriinnu/chitragupta)** -- Autonomous AI Agent Platform whose registry patterns inspired kosha
327
- - **[takumi](https://github.com/sriinnu/takumi)** -- AI coding agent TUI whose routing needs drove kosha's creation
328
-
329
- ## What "Kosha" Means
330
-
331
- `Kosha` comes from Sanskrit -- a container, treasury, or layered sheath of knowledge. A standalone model-discovery utility for any AI system.
163
+ [litellm](https://github.com/BerriAI/litellm) (pricing data) · [openrouter](https://openrouter.ai) · [ollama](https://ollama.ai) · [chitragupta](https://github.com/sriinnu/chitragupta) (registry patterns) · [takumi](https://github.com/sriinnu/takumi) (routing needs that drove kosha's creation).
332
164
 
333
165
  ## License
334
166
 
@@ -0,0 +1,48 @@
1
+ /**
2
+ * cli-cmd-model.ts — Pricing-heavy model detail commands.
3
+ *
4
+ * Contains `cmdModel`, `cmdResolve`, and `cmdRoutes` — the three commands
5
+ * that display detailed per-model information including multi-tier pricing
6
+ * (cache, reasoning, batch, origin).
7
+ *
8
+ * Extracted from `cli-commands.ts` to keep each module under 450 LOC.
9
+ *
10
+ * @module cli-cmd-model
11
+ */
12
+ import type { ModelRegistry } from "./registry.js";
13
+ /**
14
+ * Show detailed information for a single model identified by id or alias.
15
+ *
16
+ * If an exact match is not found, falls back to fuzzy substring search.
17
+ * Single fuzzy match is shown automatically; multiple matches produce a
18
+ * disambiguation list (capped at 5 suggestions).
19
+ *
20
+ * @param registry The model registry to look up.
21
+ * @param idOrAlias A model id, display name, or alias.
22
+ * @param flags CLI flags (supports `--json`).
23
+ */
24
+ export declare function cmdModel(registry: ModelRegistry, idOrAlias: string, flags: Record<string, string | boolean>): Promise<void>;
25
+ /**
26
+ * Resolve a model alias to its canonical provider ID.
27
+ * Unknown aliases are returned as-is with a yellow warning.
28
+ *
29
+ * @param registry The model registry containing alias mappings.
30
+ * @param alias The alias string to resolve.
31
+ * @param flags CLI flags (supports `--json`).
32
+ */
33
+ export declare function cmdResolve(registry: ModelRegistry, alias: string, flags: Record<string, string | boolean>): Promise<void>;
34
+ /**
35
+ * Show every provider route through which a model can be accessed.
36
+ *
37
+ * A "route" is a serving-layer entry whose normalized model ID matches the
38
+ * given identifier. Output includes direct/preferred markers, origin provider,
39
+ * model version hint, and serving base URL.
40
+ *
41
+ * Pricing columns show `—` when data is unavailable.
42
+ *
43
+ * @param registry The model registry to query.
44
+ * @param modelId Canonical model ID or alias to look up.
45
+ * @param flags CLI flags (supports `--json`).
46
+ */
47
+ export declare function cmdRoutes(registry: ModelRegistry, modelId: string, flags: Record<string, string | boolean>): Promise<void>;
48
+ //# sourceMappingURL=cli-cmd-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-cmd-model.d.ts","sourceRoot":"","sources":["../src/cli-cmd-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAWnD;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EjI;AAID;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D/H;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ChI"}