@x12i/ai-tools 1.0.2
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.
- package/README.md +214 -0
- package/dist/AiModelsCatalogClient-4RF5BCDL.cjs +9 -0
- package/dist/AiModelsCatalogClient-4RF5BCDL.cjs.map +1 -0
- package/dist/AiModelsCatalogClient-B-dNLXX0.d.ts +29 -0
- package/dist/AiModelsCatalogClient-CSVlKql5.d.cts +29 -0
- package/dist/AiModelsCatalogClient-NUF3CBLW.js +9 -0
- package/dist/AiModelsCatalogClient-NUF3CBLW.js.map +1 -0
- package/dist/aliases/index.cjs +11 -0
- package/dist/aliases/index.cjs.map +1 -0
- package/dist/aliases/index.d.cts +21 -0
- package/dist/aliases/index.d.ts +21 -0
- package/dist/aliases/index.js +11 -0
- package/dist/aliases/index.js.map +1 -0
- package/dist/catalox/index.cjs +21 -0
- package/dist/catalox/index.cjs.map +1 -0
- package/dist/catalox/index.d.cts +23 -0
- package/dist/catalox/index.d.ts +23 -0
- package/dist/catalox/index.js +21 -0
- package/dist/catalox/index.js.map +1 -0
- package/dist/chunk-2PYACSZ5.cjs +1 -0
- package/dist/chunk-2PYACSZ5.cjs.map +1 -0
- package/dist/chunk-3E67S427.cjs +1 -0
- package/dist/chunk-3E67S427.cjs.map +1 -0
- package/dist/chunk-4NAY6HRP.js +137 -0
- package/dist/chunk-4NAY6HRP.js.map +1 -0
- package/dist/chunk-5HNFAYTO.cjs +254 -0
- package/dist/chunk-5HNFAYTO.cjs.map +1 -0
- package/dist/chunk-6QGDZTGH.js +127 -0
- package/dist/chunk-6QGDZTGH.js.map +1 -0
- package/dist/chunk-7Q742NI3.cjs +106 -0
- package/dist/chunk-7Q742NI3.cjs.map +1 -0
- package/dist/chunk-AJEKEWWB.js +106 -0
- package/dist/chunk-AJEKEWWB.js.map +1 -0
- package/dist/chunk-AV6OE2YQ.cjs +127 -0
- package/dist/chunk-AV6OE2YQ.cjs.map +1 -0
- package/dist/chunk-COK34C6P.js +1 -0
- package/dist/chunk-COK34C6P.js.map +1 -0
- package/dist/chunk-DJ5SWJDY.js +729 -0
- package/dist/chunk-DJ5SWJDY.js.map +1 -0
- package/dist/chunk-F2F4UEFD.cjs +75 -0
- package/dist/chunk-F2F4UEFD.cjs.map +1 -0
- package/dist/chunk-G2G4KSC5.js +30 -0
- package/dist/chunk-G2G4KSC5.js.map +1 -0
- package/dist/chunk-HHNHWYTP.cjs +105 -0
- package/dist/chunk-HHNHWYTP.cjs.map +1 -0
- package/dist/chunk-HN6UAQAE.cjs +83 -0
- package/dist/chunk-HN6UAQAE.cjs.map +1 -0
- package/dist/chunk-KHODXGPV.js +1 -0
- package/dist/chunk-KHODXGPV.js.map +1 -0
- package/dist/chunk-KQOALKKX.js +75 -0
- package/dist/chunk-KQOALKKX.js.map +1 -0
- package/dist/chunk-LYOU7CA2.cjs +30 -0
- package/dist/chunk-LYOU7CA2.cjs.map +1 -0
- package/dist/chunk-ML2FRR4L.js +105 -0
- package/dist/chunk-ML2FRR4L.js.map +1 -0
- package/dist/chunk-MLRHYOCD.js +160 -0
- package/dist/chunk-MLRHYOCD.js.map +1 -0
- package/dist/chunk-O2A6OVEH.js +240 -0
- package/dist/chunk-O2A6OVEH.js.map +1 -0
- package/dist/chunk-ONA73BU6.cjs +160 -0
- package/dist/chunk-ONA73BU6.cjs.map +1 -0
- package/dist/chunk-QCRLKVB3.cjs +137 -0
- package/dist/chunk-QCRLKVB3.cjs.map +1 -0
- package/dist/chunk-QWAX7VQO.cjs +240 -0
- package/dist/chunk-QWAX7VQO.cjs.map +1 -0
- package/dist/chunk-TF4L2NEC.cjs +729 -0
- package/dist/chunk-TF4L2NEC.cjs.map +1 -0
- package/dist/chunk-XRBZQQQU.js +254 -0
- package/dist/chunk-XRBZQQQU.js.map +1 -0
- package/dist/chunk-YHO57D2V.js +83 -0
- package/dist/chunk-YHO57D2V.js.map +1 -0
- package/dist/cli/index.cjs +403 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +403 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cost/index.cjs +7 -0
- package/dist/cost/index.cjs.map +1 -0
- package/dist/cost/index.d.cts +52 -0
- package/dist/cost/index.d.ts +52 -0
- package/dist/cost/index.js +7 -0
- package/dist/cost/index.js.map +1 -0
- package/dist/index.cjs +104 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +104 -0
- package/dist/index.js.map +1 -0
- package/dist/modelNameResolver-Bn8QnkSj.d.ts +80 -0
- package/dist/modelNameResolver-bZD-eBSJ.d.cts +80 -0
- package/dist/models/index.cjs +33 -0
- package/dist/models/index.cjs.map +1 -0
- package/dist/models/index.d.cts +75 -0
- package/dist/models/index.d.ts +75 -0
- package/dist/models/index.js +33 -0
- package/dist/models/index.js.map +1 -0
- package/dist/sync/index.cjs +38 -0
- package/dist/sync/index.cjs.map +1 -0
- package/dist/sync/index.d.cts +12 -0
- package/dist/sync/index.d.ts +12 -0
- package/dist/sync/index.js +38 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/toolbox/index.cjs +7 -0
- package/dist/toolbox/index.cjs.map +1 -0
- package/dist/toolbox/index.d.cts +72 -0
- package/dist/toolbox/index.d.ts +72 -0
- package/dist/toolbox/index.js +7 -0
- package/dist/toolbox/index.js.map +1 -0
- package/dist/types-DdGB3YaA.d.cts +278 -0
- package/dist/types-DdGB3YaA.d.ts +278 -0
- package/package.json +115 -0
- package/schemas/aliases.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# @x12i/ai-tools
|
|
2
|
+
|
|
3
|
+
TypeScript-first npm package for AI model catalog management, runtime cost calculation, project-local model aliases, and an integrated LLM utility belt — backed by [@x12i/catalox](https://www.npmjs.com/package/@x12i/catalox) and OpenRouter.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @x12i/ai-tools @x12i/catalox
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Optional peers: `firebase-admin`, `@x12i/helpers`, `openai`, `better-sqlite3` (for toolbox SQLite storage).
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createCataloxFromEnv } from "@x12i/catalox/firebase";
|
|
17
|
+
import {
|
|
18
|
+
ensureAiModelsCatalog,
|
|
19
|
+
AiModelsCatalogClient,
|
|
20
|
+
CostCalculator,
|
|
21
|
+
} from "@x12i/ai-tools";
|
|
22
|
+
|
|
23
|
+
const { catalox } = createCataloxFromEnv();
|
|
24
|
+
await ensureAiModelsCatalog(catalox);
|
|
25
|
+
|
|
26
|
+
const catalog = new AiModelsCatalogClient({ catalox });
|
|
27
|
+
const calculator = new CostCalculator(catalog);
|
|
28
|
+
|
|
29
|
+
const result = await calculator.calculate({
|
|
30
|
+
tokens: { prompt: 1000, completion: 500, total: 1500 },
|
|
31
|
+
provider: "openrouter",
|
|
32
|
+
modelUsed: "openai/gpt-4o",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(result.cost);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Reasoning models
|
|
39
|
+
|
|
40
|
+
After sync, each catalog record includes **`supportsReasoning`** — use it to branch prompts, token limits, or cost handling.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { getModelInfo, isReasoningModel } from "@x12i/ai-tools";
|
|
44
|
+
|
|
45
|
+
const model = await getModelInfo("openai/o3-mini");
|
|
46
|
+
if (model?.supportsReasoning) {
|
|
47
|
+
// pass OpenRouter `reasoning: { effort: "medium" }`, bill reasoning tokens, etc.
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Same check without loading the full record field:
|
|
51
|
+
isReasoningModel(model!);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Detection uses OpenRouter metadata:
|
|
55
|
+
|
|
56
|
+
- `supported_parameters` includes `reasoning` (or `include_reasoning`)
|
|
57
|
+
- pricing includes `internal_reasoning` (exposed as `pricing.reasoningUsdPerToken`)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx ai-tools models list --reasoning
|
|
61
|
+
npx ai-tools models count --reasoning
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Re-run `npm run seed` or `npx ai-tools sync` after upgrading so existing Firestore rows get `supportsReasoning` indexed.
|
|
65
|
+
|
|
66
|
+
## Smart model name resolution
|
|
67
|
+
|
|
68
|
+
Callers often pass messy `provider` + `model` pairs (typos, missing namespaces, version suffixes, aliases used as provider names, or no provider at all). **`ModelNameResolver`** normalises input and runs a deterministic strategy pipeline against the cached catalog (no network calls during resolution).
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { AiModelsCatalogClient, ModelNameResolver } from "@x12i/ai-tools";
|
|
72
|
+
|
|
73
|
+
const catalog = new AiModelsCatalogClient({ catalox });
|
|
74
|
+
const models = await catalog.getAllModels();
|
|
75
|
+
|
|
76
|
+
const resolver = new ModelNameResolver(models, { aliasRegistry });
|
|
77
|
+
const result = await catalog.resolveModel({
|
|
78
|
+
provider: "openrouter",
|
|
79
|
+
model: "gpt4o",
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (result.found) {
|
|
83
|
+
console.log(result.modelId); // openai/gpt-4o
|
|
84
|
+
console.log(result.confidence, result.resolvedVia);
|
|
85
|
+
console.log(result.routedViaOpenRouter);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### What it handles
|
|
90
|
+
|
|
91
|
+
| Input | Resolves to |
|
|
92
|
+
|-------|-------------|
|
|
93
|
+
| `openrouter` + `gpt-4o` | `openai/gpt-4o` (provider prefix inference) |
|
|
94
|
+
| `openrouter` + `gpt4o` | `openai/gpt-4o` (shorthand expansion) |
|
|
95
|
+
| `openrouter` + `gpt-4o-2024-08-06` | `openai/gpt-4o` (version suffix strip) |
|
|
96
|
+
| `openrouter` + `openai/claude-3-5-sonnet` | `anthropic/claude-3-5-sonnet-…` (cross-provider correction) |
|
|
97
|
+
| provider `best` (alias name) + any model | alias target (alias-as-provider correction) |
|
|
98
|
+
| model only (`gpt-4o`) | catalog alias or prefix inference |
|
|
99
|
+
| `ollama` + `llama3:8b` | passthrough (`record: null`, not an error) |
|
|
100
|
+
|
|
101
|
+
Each success includes `confidence`, `resolvedVia[]`, and `resolvedReason`. Below-threshold matches return `found: false` with `bestRejectedCandidate` when applicable.
|
|
102
|
+
|
|
103
|
+
### OpenRouter vs direct provider (env defaults)
|
|
104
|
+
|
|
105
|
+
When the **provider is omitted** or ambiguous, routing defaults come from your `.env` (loaded via [@x12/env](https://www.npmjs.com/package/@x12i/env)):
|
|
106
|
+
|
|
107
|
+
| Condition | Default routing |
|
|
108
|
+
|-----------|-----------------|
|
|
109
|
+
| `OPENROUTER_API_KEY` is set **and** `USE_OPENROUTER=true` or `USE_OPENROUTER=1` | OpenRouter |
|
|
110
|
+
| `OPENROUTER_API_KEY` is set **and** `{VENDOR}_API_KEY` is missing for the resolved vendor | OpenRouter |
|
|
111
|
+
| `{VENDOR}_API_KEY` is set (and `USE_OPENROUTER` not forcing OR) | Direct to that vendor |
|
|
112
|
+
|
|
113
|
+
**Vendor API key naming:** `{VENDOR}_API_KEY` where `VENDOR` is the catalog `providerId` in `UPPER_SNAKE_CASE` (hyphens → underscores).
|
|
114
|
+
|
|
115
|
+
Examples:
|
|
116
|
+
|
|
117
|
+
- `openai` → `OPENAI_API_KEY`
|
|
118
|
+
- `anthropic` → `ANTHROPIC_API_KEY`
|
|
119
|
+
- `meta-llama` → `META_LLAMA_API_KEY`
|
|
120
|
+
- `x-ai` → `X_AI_API_KEY`
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import {
|
|
124
|
+
loadOpenRouterRoutingEnv,
|
|
125
|
+
shouldDefaultRouteViaOpenRouter,
|
|
126
|
+
} from "@x12i/ai-tools";
|
|
127
|
+
|
|
128
|
+
const routing = loadOpenRouterRoutingEnv();
|
|
129
|
+
shouldDefaultRouteViaOpenRouter("openai", routing); // true if OR key set but OPENAI_API_KEY missing
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Explicit `provider: "openrouter"` always sets `routedViaOpenRouter: true`. Explicit direct providers (`openai`, `anthropic`, …) use direct routing unless env rules above apply.
|
|
133
|
+
|
|
134
|
+
### CLI
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npx ai-tools models resolve --provider openrouter --model gpt4o
|
|
138
|
+
npx ai-tools models resolve --model claude-sonnet --verbose
|
|
139
|
+
npx ai-tools models resolve --model turbomax-9000 --json
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Seed catalog (Firestore + OpenRouter)
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Requires .env: GOOGLE_SERVICE_ACCOUNT_BASE64, FIREBASE_PROJECT_ID
|
|
146
|
+
# OpenRouter /models is public — no API key required
|
|
147
|
+
npm run seed
|
|
148
|
+
npm run seed:verbose
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Tests
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npm test # unit tests (mocked)
|
|
155
|
+
npm run test:live # live Firestore/Catalox tests (uses .env)
|
|
156
|
+
npm run test:all # both
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## CLI
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npx ai-tools catalog ensure
|
|
163
|
+
npx ai-tools sync --verbose
|
|
164
|
+
npx ai-tools models list --provider openai
|
|
165
|
+
npx ai-tools models list --reasoning
|
|
166
|
+
npx ai-tools models resolve --model gpt4o --provider openrouter --verbose
|
|
167
|
+
npx ai-tools cost --model openai/gpt-4o --prompt-tokens 2000 --completion-tokens 800
|
|
168
|
+
npx ai-tools alias init
|
|
169
|
+
npx ai-tools alias set best anthropic/claude-opus-4 --provider openrouter
|
|
170
|
+
npx ai-tools alias check
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Environment variables
|
|
174
|
+
|
|
175
|
+
| Variable | Purpose |
|
|
176
|
+
|----------|---------|
|
|
177
|
+
| `OPENROUTER_API_KEY` | OpenRouter API key; used for routing defaults and optional sync auth |
|
|
178
|
+
| `USE_OPENROUTER` | Set to `true` or `1` to default API routing via OpenRouter when `OPENROUTER_API_KEY` is set |
|
|
179
|
+
| `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, … | Direct vendor keys — pattern `{PROVIDER_ID}_API_KEY` (see smart resolver above) |
|
|
180
|
+
| `GOOGLE_SERVICE_ACCOUNT_BASE64` | Firebase / Firestore credentials |
|
|
181
|
+
| `FIREBASE_PROJECT_ID` | GCP project |
|
|
182
|
+
| `FIRESTORE_DATABASE_ID` | Firestore database (default: `(default)`) |
|
|
183
|
+
| `AI_TOOLS_APP_ID` | Catalox appId (default: `ai-tools`) |
|
|
184
|
+
| `AI_TOOLS_CATALOG_ID` | Catalog id (default: `ai-models`) |
|
|
185
|
+
| `AI_TOOLS_CACHE_TTL_MS` | nx-cache TTL override |
|
|
186
|
+
| `AI_TOOLS_ALIASES_PATH` | Path to `aliases.json` |
|
|
187
|
+
|
|
188
|
+
## Subpath exports
|
|
189
|
+
|
|
190
|
+
- `@x12i/ai-tools` — main API (`ModelNameResolver`, `loadOpenRouterRoutingEnv`, catalog, cost, aliases)
|
|
191
|
+
- `@x12i/ai-tools/cost`
|
|
192
|
+
- `@x12i/ai-tools/toolbox`
|
|
193
|
+
- `@x12i/ai-tools/sync` — sync + resolver types
|
|
194
|
+
- `@x12i/ai-tools/catalox`
|
|
195
|
+
- `@x12i/ai-tools/aliases`
|
|
196
|
+
- `@x12i/ai-tools/models`
|
|
197
|
+
|
|
198
|
+
## Project aliases
|
|
199
|
+
|
|
200
|
+
Commit `./ai-tools/aliases.json` in your application repo so dev/staging/prod share the same model vocabulary. Alias targets that use shorthand or versioned ids are resolved through the same smart resolver as runtime model strings.
|
|
201
|
+
|
|
202
|
+
## Publishing
|
|
203
|
+
|
|
204
|
+
Scoped packages (`@x12i/...`) require public access on the free npm plan:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npm publish
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`package.json` includes `"publishConfig": { "access": "public" }`. If publish still fails, run `npm publish --access public`.
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
var _chunkF2F4UEFDcjs = require('./chunk-F2F4UEFD.cjs');
|
|
4
|
+
require('./chunk-TF4L2NEC.cjs');
|
|
5
|
+
require('./chunk-7Q742NI3.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
exports.AiModelsCatalogClient = _chunkF2F4UEFDcjs.AiModelsCatalogClient;
|
|
9
|
+
//# sourceMappingURL=AiModelsCatalogClient-4RF5BCDL.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/AiModelsCatalogClient-4RF5BCDL.cjs"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACF,wEAAC","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/AiModelsCatalogClient-4RF5BCDL.cjs"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Catalox } from '@x12i/catalox';
|
|
2
|
+
import { l as ModelResolverOptions, a as AiModelRecord, h as ModelResolutionInput, j as ModelResolutionResult } from './types-DdGB3YaA.js';
|
|
3
|
+
|
|
4
|
+
type AiModelsCatalogClientOptions = {
|
|
5
|
+
catalox: Catalox;
|
|
6
|
+
appId?: string;
|
|
7
|
+
catalogId?: string;
|
|
8
|
+
cacheTtlMs?: number;
|
|
9
|
+
resolverOptions?: Omit<ModelResolverOptions, "aliasRegistry">;
|
|
10
|
+
};
|
|
11
|
+
declare class AiModelsCatalogClient {
|
|
12
|
+
private readonly catalox;
|
|
13
|
+
private readonly appId;
|
|
14
|
+
private readonly catalogId;
|
|
15
|
+
private readonly cacheTtlMs;
|
|
16
|
+
private readonly resolverOptions;
|
|
17
|
+
constructor(options: AiModelsCatalogClientOptions);
|
|
18
|
+
private context;
|
|
19
|
+
getAllModels(): Promise<Map<string, AiModelRecord>>;
|
|
20
|
+
private resolver;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a (provider, model) pair to a canonical model id and catalog record.
|
|
23
|
+
*/
|
|
24
|
+
resolveModel(input: ModelResolutionInput, options?: ModelResolverOptions): Promise<ModelResolutionResult>;
|
|
25
|
+
getModel(modelId: string, provider?: string, options?: ModelResolverOptions): Promise<AiModelRecord | null>;
|
|
26
|
+
refresh(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { AiModelsCatalogClient as A, type AiModelsCatalogClientOptions as a };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Catalox } from '@x12i/catalox';
|
|
2
|
+
import { l as ModelResolverOptions, a as AiModelRecord, h as ModelResolutionInput, j as ModelResolutionResult } from './types-DdGB3YaA.cjs';
|
|
3
|
+
|
|
4
|
+
type AiModelsCatalogClientOptions = {
|
|
5
|
+
catalox: Catalox;
|
|
6
|
+
appId?: string;
|
|
7
|
+
catalogId?: string;
|
|
8
|
+
cacheTtlMs?: number;
|
|
9
|
+
resolverOptions?: Omit<ModelResolverOptions, "aliasRegistry">;
|
|
10
|
+
};
|
|
11
|
+
declare class AiModelsCatalogClient {
|
|
12
|
+
private readonly catalox;
|
|
13
|
+
private readonly appId;
|
|
14
|
+
private readonly catalogId;
|
|
15
|
+
private readonly cacheTtlMs;
|
|
16
|
+
private readonly resolverOptions;
|
|
17
|
+
constructor(options: AiModelsCatalogClientOptions);
|
|
18
|
+
private context;
|
|
19
|
+
getAllModels(): Promise<Map<string, AiModelRecord>>;
|
|
20
|
+
private resolver;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a (provider, model) pair to a canonical model id and catalog record.
|
|
23
|
+
*/
|
|
24
|
+
resolveModel(input: ModelResolutionInput, options?: ModelResolverOptions): Promise<ModelResolutionResult>;
|
|
25
|
+
getModel(modelId: string, provider?: string, options?: ModelResolverOptions): Promise<AiModelRecord | null>;
|
|
26
|
+
refresh(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { AiModelsCatalogClient as A, type AiModelsCatalogClientOptions as a };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-3E67S427.cjs');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunkQWAX7VQOcjs = require('../chunk-QWAX7VQO.cjs');
|
|
6
|
+
require('../chunk-7Q742NI3.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exports.AliasRegistry = _chunkQWAX7VQOcjs.AliasRegistry; exports.AliasResolver = _chunkQWAX7VQOcjs.AliasResolver;
|
|
11
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/aliases/index.cjs"],"names":[],"mappings":"AAAA,0GAA8B;AAC9B;AACE;AACA;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACA;AACF,iHAAC","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/aliases/index.cjs"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { d as AliasRegistry, u as ResolvedModelRef, f as AliasValidationReport } from '../types-DdGB3YaA.cjs';
|
|
2
|
+
export { b as AliasEntry, c as AliasFileSchema, e as AliasRegistryOptions } from '../types-DdGB3YaA.cjs';
|
|
3
|
+
import { A as AiModelsCatalogClient } from '../AiModelsCatalogClient-CSVlKql5.cjs';
|
|
4
|
+
import '@x12i/catalox';
|
|
5
|
+
|
|
6
|
+
type AliasResolverOptions = {
|
|
7
|
+
registry: AliasRegistry;
|
|
8
|
+
catalogClient: AiModelsCatalogClient;
|
|
9
|
+
};
|
|
10
|
+
declare class AliasResolver {
|
|
11
|
+
private readonly registry;
|
|
12
|
+
private readonly catalogClient;
|
|
13
|
+
constructor(options: AliasResolverOptions);
|
|
14
|
+
getModel(aliasName: string): Promise<ResolvedModelRef>;
|
|
15
|
+
getModels(aliasNames: string[]): Promise<ResolvedModelRef[]>;
|
|
16
|
+
getAllResolved(): Promise<ResolvedModelRef[]>;
|
|
17
|
+
validate(): Promise<AliasValidationReport>;
|
|
18
|
+
private resolveEntry;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { AliasRegistry, AliasResolver, type AliasResolverOptions, AliasValidationReport, ResolvedModelRef };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { d as AliasRegistry, u as ResolvedModelRef, f as AliasValidationReport } from '../types-DdGB3YaA.js';
|
|
2
|
+
export { b as AliasEntry, c as AliasFileSchema, e as AliasRegistryOptions } from '../types-DdGB3YaA.js';
|
|
3
|
+
import { A as AiModelsCatalogClient } from '../AiModelsCatalogClient-B-dNLXX0.js';
|
|
4
|
+
import '@x12i/catalox';
|
|
5
|
+
|
|
6
|
+
type AliasResolverOptions = {
|
|
7
|
+
registry: AliasRegistry;
|
|
8
|
+
catalogClient: AiModelsCatalogClient;
|
|
9
|
+
};
|
|
10
|
+
declare class AliasResolver {
|
|
11
|
+
private readonly registry;
|
|
12
|
+
private readonly catalogClient;
|
|
13
|
+
constructor(options: AliasResolverOptions);
|
|
14
|
+
getModel(aliasName: string): Promise<ResolvedModelRef>;
|
|
15
|
+
getModels(aliasNames: string[]): Promise<ResolvedModelRef[]>;
|
|
16
|
+
getAllResolved(): Promise<ResolvedModelRef[]>;
|
|
17
|
+
validate(): Promise<AliasValidationReport>;
|
|
18
|
+
private resolveEntry;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { AliasRegistry, AliasResolver, type AliasResolverOptions, AliasValidationReport, ResolvedModelRef };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkHHNHWYTPcjs = require('../chunk-HHNHWYTP.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
var _chunkF2F4UEFDcjs = require('../chunk-F2F4UEFD.cjs');
|
|
11
|
+
require('../chunk-TF4L2NEC.cjs');
|
|
12
|
+
require('../chunk-7Q742NI3.cjs');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
exports.AiModelsCatalogClient = _chunkF2F4UEFDcjs.AiModelsCatalogClient; exports.batchUpsertAiModelRecords = _chunkHHNHWYTPcjs.batchUpsertAiModelRecords; exports.decodeModelFirestoreDocId = _chunkHHNHWYTPcjs.decodeModelFirestoreDocId; exports.encodeModelFirestoreDocId = _chunkHHNHWYTPcjs.encodeModelFirestoreDocId; exports.sanitizeForFirestore = _chunkHHNHWYTPcjs.sanitizeForFirestore; exports.upsertAiModelRecord = _chunkHHNHWYTPcjs.upsertAiModelRecord;
|
|
21
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/catalox/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,ucAAC","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/catalox/index.cjs"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { A as AiModelsCatalogClient, a as AiModelsCatalogClientOptions } from '../AiModelsCatalogClient-CSVlKql5.cjs';
|
|
2
|
+
import { Firestore } from 'firebase-admin/firestore';
|
|
3
|
+
import { CataloxContext } from '@x12i/catalox';
|
|
4
|
+
import { a as AiModelRecord } from '../types-DdGB3YaA.cjs';
|
|
5
|
+
|
|
6
|
+
declare function encodeModelFirestoreDocId(modelId: string): string;
|
|
7
|
+
declare function decodeModelFirestoreDocId(docId: string): string;
|
|
8
|
+
|
|
9
|
+
/** Firestore rejects `undefined` — strip before write. */
|
|
10
|
+
declare function sanitizeForFirestore<T>(value: T): T;
|
|
11
|
+
type UpsertAiModelRecordOptions = {
|
|
12
|
+
firestore: Firestore;
|
|
13
|
+
context: CataloxContext;
|
|
14
|
+
catalogId: string;
|
|
15
|
+
record: AiModelRecord;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Upserts one ai-models row via Firestore (safe doc ids for `provider/model` ids).
|
|
19
|
+
*/
|
|
20
|
+
declare function upsertAiModelRecord(options: UpsertAiModelRecordOptions): Promise<void>;
|
|
21
|
+
declare function batchUpsertAiModelRecords(firestore: Firestore, catalogId: string, context: CataloxContext, records: AiModelRecord[]): Promise<void>;
|
|
22
|
+
|
|
23
|
+
export { batchUpsertAiModelRecords, decodeModelFirestoreDocId, encodeModelFirestoreDocId, sanitizeForFirestore, upsertAiModelRecord };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { A as AiModelsCatalogClient, a as AiModelsCatalogClientOptions } from '../AiModelsCatalogClient-B-dNLXX0.js';
|
|
2
|
+
import { Firestore } from 'firebase-admin/firestore';
|
|
3
|
+
import { CataloxContext } from '@x12i/catalox';
|
|
4
|
+
import { a as AiModelRecord } from '../types-DdGB3YaA.js';
|
|
5
|
+
|
|
6
|
+
declare function encodeModelFirestoreDocId(modelId: string): string;
|
|
7
|
+
declare function decodeModelFirestoreDocId(docId: string): string;
|
|
8
|
+
|
|
9
|
+
/** Firestore rejects `undefined` — strip before write. */
|
|
10
|
+
declare function sanitizeForFirestore<T>(value: T): T;
|
|
11
|
+
type UpsertAiModelRecordOptions = {
|
|
12
|
+
firestore: Firestore;
|
|
13
|
+
context: CataloxContext;
|
|
14
|
+
catalogId: string;
|
|
15
|
+
record: AiModelRecord;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Upserts one ai-models row via Firestore (safe doc ids for `provider/model` ids).
|
|
19
|
+
*/
|
|
20
|
+
declare function upsertAiModelRecord(options: UpsertAiModelRecordOptions): Promise<void>;
|
|
21
|
+
declare function batchUpsertAiModelRecords(firestore: Firestore, catalogId: string, context: CataloxContext, records: AiModelRecord[]): Promise<void>;
|
|
22
|
+
|
|
23
|
+
export { batchUpsertAiModelRecords, decodeModelFirestoreDocId, encodeModelFirestoreDocId, sanitizeForFirestore, upsertAiModelRecord };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
batchUpsertAiModelRecords,
|
|
3
|
+
decodeModelFirestoreDocId,
|
|
4
|
+
encodeModelFirestoreDocId,
|
|
5
|
+
sanitizeForFirestore,
|
|
6
|
+
upsertAiModelRecord
|
|
7
|
+
} from "../chunk-ML2FRR4L.js";
|
|
8
|
+
import {
|
|
9
|
+
AiModelsCatalogClient
|
|
10
|
+
} from "../chunk-KQOALKKX.js";
|
|
11
|
+
import "../chunk-DJ5SWJDY.js";
|
|
12
|
+
import "../chunk-AJEKEWWB.js";
|
|
13
|
+
export {
|
|
14
|
+
AiModelsCatalogClient,
|
|
15
|
+
batchUpsertAiModelRecords,
|
|
16
|
+
decodeModelFirestoreDocId,
|
|
17
|
+
encodeModelFirestoreDocId,
|
|
18
|
+
sanitizeForFirestore,
|
|
19
|
+
upsertAiModelRecord
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";//# sourceMappingURL=chunk-2PYACSZ5.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-2PYACSZ5.cjs"],"names":[],"mappings":"AAAA","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-2PYACSZ5.cjs"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";//# sourceMappingURL=chunk-3E67S427.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-3E67S427.cjs"],"names":[],"mappings":"AAAA","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-3E67S427.cjs"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AiModelsCatalogClient
|
|
3
|
+
} from "./chunk-KQOALKKX.js";
|
|
4
|
+
|
|
5
|
+
// src/models/filterModels.ts
|
|
6
|
+
function matchesSearch(record, search) {
|
|
7
|
+
const q = search.toLowerCase();
|
|
8
|
+
return record.modelId.toLowerCase().includes(q) || record.name.toLowerCase().includes(q) || record.description.toLowerCase().includes(q) || record.canonicalSlug.toLowerCase().includes(q) || record.aliases.some((a) => a.toLowerCase().includes(q));
|
|
9
|
+
}
|
|
10
|
+
function filterModels(models, filters = {}) {
|
|
11
|
+
let list = [...models];
|
|
12
|
+
if (filters.providerId) {
|
|
13
|
+
list = list.filter((m) => m.providerId === filters.providerId);
|
|
14
|
+
}
|
|
15
|
+
if (filters.status) {
|
|
16
|
+
list = list.filter((m) => m.status === filters.status);
|
|
17
|
+
}
|
|
18
|
+
if (filters.outputModality) {
|
|
19
|
+
list = list.filter((m) => m.outputModalities.includes(filters.outputModality));
|
|
20
|
+
}
|
|
21
|
+
if (filters.inputModality) {
|
|
22
|
+
list = list.filter((m) => m.inputModalities.includes(filters.inputModality));
|
|
23
|
+
}
|
|
24
|
+
if (filters.supportedParameter) {
|
|
25
|
+
list = list.filter((m) => m.supportedParameters.includes(filters.supportedParameter));
|
|
26
|
+
}
|
|
27
|
+
if (filters.supportsTools !== void 0) {
|
|
28
|
+
list = list.filter((m) => m.supportsTools === filters.supportsTools);
|
|
29
|
+
}
|
|
30
|
+
if (filters.supportsReasoning !== void 0) {
|
|
31
|
+
list = list.filter((m) => m.supportsReasoning === filters.supportsReasoning);
|
|
32
|
+
}
|
|
33
|
+
if (filters.search) {
|
|
34
|
+
list = list.filter((m) => matchesSearch(m, filters.search));
|
|
35
|
+
}
|
|
36
|
+
list.sort((a, b) => a.name.localeCompare(b.name));
|
|
37
|
+
const offset = filters.offset ?? 0;
|
|
38
|
+
const limit = filters.limit ?? list.length;
|
|
39
|
+
return list.slice(offset, offset + limit);
|
|
40
|
+
}
|
|
41
|
+
function countModels(models, filters = {}) {
|
|
42
|
+
return filterModels(models, { ...filters, limit: Number.MAX_SAFE_INTEGER, offset: 0 }).length;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/models/AiModelsService.ts
|
|
46
|
+
var AiModelsService = class {
|
|
47
|
+
client;
|
|
48
|
+
catalox;
|
|
49
|
+
appId;
|
|
50
|
+
catalogId;
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.catalox = options.catalox;
|
|
53
|
+
this.client = new AiModelsCatalogClient(options);
|
|
54
|
+
this.appId = options.appId ?? "ai-tools";
|
|
55
|
+
this.catalogId = options.catalogId ?? "ai-models";
|
|
56
|
+
}
|
|
57
|
+
context() {
|
|
58
|
+
return { appId: this.appId, superAdmin: true };
|
|
59
|
+
}
|
|
60
|
+
/** Load all models (cached). */
|
|
61
|
+
async getAllModels() {
|
|
62
|
+
return this.client.getAllModels();
|
|
63
|
+
}
|
|
64
|
+
/** List models with in-memory filters (fast after cache warm). */
|
|
65
|
+
async listModels(filters = {}) {
|
|
66
|
+
const all = await this.getAllModels();
|
|
67
|
+
const total = countModels(all.values(), filters);
|
|
68
|
+
const limit = filters.limit ?? 50;
|
|
69
|
+
const offset = filters.offset ?? 0;
|
|
70
|
+
const models = filterModels(all.values(), { ...filters, limit, offset });
|
|
71
|
+
return { models, total, limit, offset };
|
|
72
|
+
}
|
|
73
|
+
/** Count models matching filters. */
|
|
74
|
+
async countModels(filters = {}) {
|
|
75
|
+
const all = await this.getAllModels();
|
|
76
|
+
return countModels(all.values(), filters);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Full model record by id or alias (same resolution as cost calculator).
|
|
80
|
+
*/
|
|
81
|
+
async getModelInfo(modelIdOrAlias) {
|
|
82
|
+
return this.client.getModel(modelIdOrAlias);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Query via Catalox indexed fields (provider, status, output modality, tools).
|
|
86
|
+
* Falls back to in-memory filter when Catalox returns partial pages.
|
|
87
|
+
*/
|
|
88
|
+
async listModelsFromCatalog(filters = {}, options) {
|
|
89
|
+
const filter = {};
|
|
90
|
+
if (filters.providerId) filter.providerId = filters.providerId;
|
|
91
|
+
if (filters.status) filter.status = filters.status;
|
|
92
|
+
if (filters.outputModality) filter.primaryOutputModality = filters.outputModality;
|
|
93
|
+
if (filters.supportsTools !== void 0) filter.supportsTools = filters.supportsTools;
|
|
94
|
+
if (filters.supportsReasoning !== void 0) {
|
|
95
|
+
filter.supportsReasoning = filters.supportsReasoning;
|
|
96
|
+
}
|
|
97
|
+
const limit = filters.limit ?? 50;
|
|
98
|
+
const result = await this.catalox.listCatalogItems(this.context(), this.catalogId, {
|
|
99
|
+
limit: Math.min(limit, 1e4),
|
|
100
|
+
filter,
|
|
101
|
+
...options
|
|
102
|
+
});
|
|
103
|
+
let models = result.items.map((item) => item.data);
|
|
104
|
+
if (filters.supportedParameter) {
|
|
105
|
+
models = models.filter((m) => m.supportedParameters?.includes(filters.supportedParameter));
|
|
106
|
+
}
|
|
107
|
+
if (filters.inputModality) {
|
|
108
|
+
models = models.filter((m) => m.inputModalities?.includes(filters.inputModality));
|
|
109
|
+
}
|
|
110
|
+
if (filters.search) {
|
|
111
|
+
models = filterModels(models, { search: filters.search });
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
models,
|
|
115
|
+
total: models.length,
|
|
116
|
+
limit,
|
|
117
|
+
offset: filters.offset ?? 0
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
async resolve(modelIdOrAlias, provider) {
|
|
121
|
+
return this.client.resolveModel({ model: modelIdOrAlias, provider });
|
|
122
|
+
}
|
|
123
|
+
async refresh() {
|
|
124
|
+
await this.client.refresh();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
async function getModelInfo(service, modelIdOrAlias) {
|
|
128
|
+
return service.getModelInfo(modelIdOrAlias);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export {
|
|
132
|
+
filterModels,
|
|
133
|
+
countModels,
|
|
134
|
+
AiModelsService,
|
|
135
|
+
getModelInfo
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=chunk-4NAY6HRP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/models/filterModels.ts","../src/models/AiModelsService.ts"],"sourcesContent":["import type { AiModelRecord, ModelListFilters } from \"./types.js\";\n\nfunction matchesSearch(record: AiModelRecord, search: string): boolean {\n const q = search.toLowerCase();\n return (\n record.modelId.toLowerCase().includes(q) ||\n record.name.toLowerCase().includes(q) ||\n record.description.toLowerCase().includes(q) ||\n record.canonicalSlug.toLowerCase().includes(q) ||\n record.aliases.some((a) => a.toLowerCase().includes(q))\n );\n}\n\nexport function filterModels(\n models: Iterable<AiModelRecord>,\n filters: ModelListFilters = {},\n): AiModelRecord[] {\n let list = [...models];\n\n if (filters.providerId) {\n list = list.filter((m) => m.providerId === filters.providerId);\n }\n if (filters.status) {\n list = list.filter((m) => m.status === filters.status);\n }\n if (filters.outputModality) {\n list = list.filter((m) => m.outputModalities.includes(filters.outputModality!));\n }\n if (filters.inputModality) {\n list = list.filter((m) => m.inputModalities.includes(filters.inputModality!));\n }\n if (filters.supportedParameter) {\n list = list.filter((m) => m.supportedParameters.includes(filters.supportedParameter!));\n }\n if (filters.supportsTools !== undefined) {\n list = list.filter((m) => m.supportsTools === filters.supportsTools);\n }\n if (filters.supportsReasoning !== undefined) {\n list = list.filter((m) => m.supportsReasoning === filters.supportsReasoning);\n }\n if (filters.search) {\n list = list.filter((m) => matchesSearch(m, filters.search!));\n }\n\n list.sort((a, b) => a.name.localeCompare(b.name));\n\n const offset = filters.offset ?? 0;\n const limit = filters.limit ?? list.length;\n return list.slice(offset, offset + limit);\n}\n\nexport function countModels(\n models: Iterable<AiModelRecord>,\n filters: Omit<ModelListFilters, \"limit\" | \"offset\"> = {},\n): number {\n return filterModels(models, { ...filters, limit: Number.MAX_SAFE_INTEGER, offset: 0 }).length;\n}\n","import type { Catalox, CataloxContext } from \"@x12i/catalox\";\nimport type { CatalogQueryOptions } from \"@x12i/catalox\";\nimport { AiModelsCatalogClient } from \"../catalox/AiModelsCatalogClient.js\";\nimport { countModels, filterModels } from \"./filterModels.js\";\nimport type { AiModelRecord, ModelListFilters, ModelListResult } from \"./types.js\";\n\nexport type AiModelsServiceOptions = {\n catalox: Catalox;\n appId?: string;\n catalogId?: string;\n cacheTtlMs?: number;\n};\n\n/**\n * High-level model catalog API — list, filter, count, and get full model info.\n */\nexport class AiModelsService {\n private readonly client: AiModelsCatalogClient;\n private readonly catalox: Catalox;\n private readonly appId: string;\n private readonly catalogId: string;\n\n constructor(options: AiModelsServiceOptions) {\n this.catalox = options.catalox;\n this.client = new AiModelsCatalogClient(options);\n this.appId = options.appId ?? \"ai-tools\";\n this.catalogId = options.catalogId ?? \"ai-models\";\n }\n\n private context(): CataloxContext {\n return { appId: this.appId, superAdmin: true };\n }\n\n /** Load all models (cached). */\n async getAllModels(): Promise<Map<string, AiModelRecord>> {\n return this.client.getAllModels();\n }\n\n /** List models with in-memory filters (fast after cache warm). */\n async listModels(filters: ModelListFilters = {}): Promise<ModelListResult> {\n const all = await this.getAllModels();\n const total = countModels(all.values(), filters);\n const limit = filters.limit ?? 50;\n const offset = filters.offset ?? 0;\n const models = filterModels(all.values(), { ...filters, limit, offset });\n return { models, total, limit, offset };\n }\n\n /** Count models matching filters. */\n async countModels(filters: Omit<ModelListFilters, \"limit\" | \"offset\"> = {}): Promise<number> {\n const all = await this.getAllModels();\n return countModels(all.values(), filters);\n }\n\n /**\n * Full model record by id or alias (same resolution as cost calculator).\n */\n async getModelInfo(modelIdOrAlias: string): Promise<AiModelRecord | null> {\n return this.client.getModel(modelIdOrAlias);\n }\n\n /**\n * Query via Catalox indexed fields (provider, status, output modality, tools).\n * Falls back to in-memory filter when Catalox returns partial pages.\n */\n async listModelsFromCatalog(\n filters: ModelListFilters = {},\n options?: CatalogQueryOptions,\n ): Promise<ModelListResult> {\n const filter: Record<string, unknown> = {};\n if (filters.providerId) filter.providerId = filters.providerId;\n if (filters.status) filter.status = filters.status;\n if (filters.outputModality) filter.primaryOutputModality = filters.outputModality;\n if (filters.supportsTools !== undefined) filter.supportsTools = filters.supportsTools;\n if (filters.supportsReasoning !== undefined) {\n filter.supportsReasoning = filters.supportsReasoning;\n }\n\n const limit = filters.limit ?? 50;\n const result = await this.catalox.listCatalogItems(this.context(), this.catalogId, {\n limit: Math.min(limit, 10_000),\n filter,\n ...options,\n });\n\n let models = result.items.map((item) => item.data as unknown as AiModelRecord);\n\n if (filters.supportedParameter) {\n models = models.filter((m) => m.supportedParameters?.includes(filters.supportedParameter!));\n }\n if (filters.inputModality) {\n models = models.filter((m) => m.inputModalities?.includes(filters.inputModality!));\n }\n if (filters.search) {\n models = filterModels(models, { search: filters.search });\n }\n\n return {\n models,\n total: models.length,\n limit,\n offset: filters.offset ?? 0,\n };\n }\n\n async resolve(\n modelIdOrAlias: string,\n provider?: string,\n ): Promise<import(\"../sync/modelNameResolver/types.js\").ModelResolutionResult> {\n return this.client.resolveModel({ model: modelIdOrAlias, provider });\n }\n\n async refresh(): Promise<void> {\n await this.client.refresh();\n }\n}\n\n/** Convenience: getModelInfo */\nexport async function getModelInfo(\n service: AiModelsService,\n modelIdOrAlias: string,\n): Promise<AiModelRecord | null> {\n return service.getModelInfo(modelIdOrAlias);\n}\n"],"mappings":"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","names":[]}
|