@zenera/cli 1.1.3 → 1.1.4
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 +160 -40
- package/dist/audit.d.ts +5 -2
- package/dist/audit.js +7 -2
- package/dist/catalog.d.ts +111 -0
- package/dist/catalog.js +439 -0
- package/dist/commands/check.js +39 -11
- package/dist/commands/index.d.ts +2 -2
- package/dist/commands/index.js +3 -2
- package/dist/commands/key.js +18 -0
- package/dist/commands/models.d.ts +0 -6
- package/dist/commands/models.js +546 -101
- package/dist/home.d.ts +2 -0
- package/dist/home.js +2 -0
- package/dist/keys.d.ts +9 -1
- package/dist/lib.d.ts +1 -0
- package/dist/lib.js +1 -0
- package/dist/liveness.d.ts +32 -0
- package/dist/liveness.js +194 -5
- package/dist/validate.d.ts +17 -1
- package/dist/validate.js +97 -7
- package/package.json +2 -2
- package/templates/editor/.github/copilot-instructions.md +30 -3
- package/templates/editor/.github/skills/zen-cli/SKILL.md +6 -3
- package/templates/editor/.github/skills/zen-cli/references/check.md +15 -19
- package/templates/editor/.github/skills/zen-cli/references/keys.md +5 -0
- package/templates/editor/.github/skills/zen-cli/references/models.md +108 -0
- package/templates/project/sandbox/Dockerfile +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Four commands, from nothing to an answer:
|
|
|
41
41
|
|
|
42
42
|
```sh
|
|
43
43
|
npm i -g @zenera/cli # every vendor SDK comes with it
|
|
44
|
-
zen key add openai #
|
|
44
|
+
zen key add openai # asks for the key without showing it; stored in ~/.zenera
|
|
45
45
|
zen init my-project # scaffolds a project and registers it
|
|
46
46
|
cd my-project && zen run "introduce yourself"
|
|
47
47
|
```
|
|
@@ -49,7 +49,7 @@ cd my-project && zen run "introduce yourself"
|
|
|
49
49
|
Then the rest of the loop:
|
|
50
50
|
|
|
51
51
|
```sh
|
|
52
|
-
zen run # nothing to say yet — a
|
|
52
|
+
zen run # nothing to say yet — a full-screen terminal app (a TUI)
|
|
53
53
|
zen check # validate the project and every file it names
|
|
54
54
|
zen inspect # open the last run's report.html
|
|
55
55
|
zen list --sessions # every project, its sessions and last run
|
|
@@ -150,17 +150,18 @@ you are not expected to hand-author `agents.yaml`.
|
|
|
150
150
|
|
|
151
151
|
## Commands
|
|
152
152
|
|
|
153
|
-
| Command | Does
|
|
154
|
-
| --------- |
|
|
155
|
-
| `init` | Creates a project here, or in `<dir>`, and registers it.
|
|
156
|
-
| `list` | Every known project: sessions, last run, whether one is live.
|
|
157
|
-
| `open` | Opens a project in your editor.
|
|
158
|
-
| `key` | The credential keyring — add, check, switch, remove.
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
153
|
+
| Command | Does |
|
|
154
|
+
| --------- | -------------------------------------------------------------------- |
|
|
155
|
+
| `init` | Creates a project here, or in `<dir>`, and registers it. |
|
|
156
|
+
| `list` | Every known project: sessions, last run, whether one is live. |
|
|
157
|
+
| `open` | Opens a project in your editor. |
|
|
158
|
+
| `key` | The credential keyring — add, check, switch, remove. |
|
|
159
|
+
| `models` | What this machine can use — list, search, test, pick. |
|
|
160
|
+
| `run` | Runs the project — the TUI on a terminal, a single answer otherwise. |
|
|
161
|
+
| `inspect` | Opens or rebuilds a run's `report.html`. |
|
|
162
|
+
| `check` | Validates the project and every file it names, and asks the models. |
|
|
163
|
+
| `sandbox` | Checks and prepares the container that command-line tools run in. |
|
|
164
|
+
| `version` | CLI, library and Node versions. |
|
|
164
165
|
|
|
165
166
|
Commands can also come from a package installed alongside this one, so a new
|
|
166
167
|
capability is a subcommand rather than a new binary to remember — one thing on
|
|
@@ -204,16 +205,16 @@ One keyring serves every provider, and a key goes in the same way whatever it
|
|
|
204
205
|
is for:
|
|
205
206
|
|
|
206
207
|
```sh
|
|
207
|
-
zen key add <provider> #
|
|
208
|
-
zen key add <provider> < key.txt # or pipe it
|
|
208
|
+
zen key add <provider> # asks for the key without showing it
|
|
209
|
+
zen key add <provider> < key.txt # or pipe it in
|
|
209
210
|
```
|
|
210
211
|
|
|
211
|
-
The value never
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
runs.
|
|
212
|
+
The value is never given as an argument — a command line is visible to anyone
|
|
213
|
+
listing running processes, is saved in your shell history and is captured in CI
|
|
214
|
+
logs — so piping it in and the hidden prompt are the only two ways. Entries live
|
|
215
|
+
in `~/.zenera/neo/keys.json`, in a file only you can read, and are copied into
|
|
216
|
+
the environment just before a run, so an environment variable you set yourself
|
|
217
|
+
always wins and a project checked out on a machine without `zen` still runs.
|
|
217
218
|
|
|
218
219
|
| Provider | The value is | Exported as |
|
|
219
220
|
| ------------ | ------------------------------------- | -------------------------------- |
|
|
@@ -234,22 +235,76 @@ A model reference is `[provider[/api]:]model`, and the first segment names a
|
|
|
234
235
|
**provider, not a vendor**. So `vertex:gemini-3.5-flash` and
|
|
235
236
|
`google:gemini-3.5-flash` are the same model reached through two different
|
|
236
237
|
services, needing two different credentials — and a bare `gpt-5.4-mini` goes to
|
|
237
|
-
the default provider, `openai`. `zen
|
|
238
|
-
project against what is stored, and
|
|
238
|
+
the default provider, `openai`. `zen check` resolves every reference in a
|
|
239
|
+
project against what is stored, says which credential each one needs, and spends
|
|
240
|
+
a few tokens asking each of them to answer — the only way to catch a model id
|
|
241
|
+
this account is not served. `--no-models` stops before the asking.
|
|
242
|
+
|
|
243
|
+
### Which models you can use
|
|
244
|
+
|
|
245
|
+
`zen check` answers _does my project work_. `zen models` answers _what can I
|
|
246
|
+
use_, needs no project, and asks the providers themselves:
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
zen models # who has a credential, and what is cached
|
|
250
|
+
zen models openai # everything OpenAI serves this account
|
|
251
|
+
zen models search haiku --tools --free # narrow it
|
|
252
|
+
zen models show openrouter:anthropic/claude-haiku-4.5
|
|
253
|
+
zen models test vertex:gemini-embedding-001 # one real call, one verdict
|
|
254
|
+
zen models pick --embedding # the first ref that answers, on stdout
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Listings are cached for a day in `~/.zenera/neo/catalog`. When a provider cannot
|
|
258
|
+
be asked the last listing is used and said to be stale; only if there was never
|
|
259
|
+
one does a short built-in list stand in.
|
|
260
|
+
|
|
261
|
+
`test` distinguishes three failures, because they want three different actions.
|
|
262
|
+
A **refused** model means the credential was rejected. A **blocked** one means
|
|
263
|
+
the credential was accepted and the account then said no — an API switched off,
|
|
264
|
+
an empty balance, a model this key was never granted — and the fix comes with
|
|
265
|
+
it:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
$ zen models test vertex:gemini-embedding-001
|
|
269
|
+
vertex:gemini-embedding-001 blocked Vertex AI API has not been used in project my-proj …
|
|
270
|
+
vertex:gemini-embedding-001: gcloud services enable aiplatform.googleapis.com --project my-proj
|
|
271
|
+
error 1 of 1 did not answer
|
|
272
|
+
find one that does: zen models pick --embedding
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
`pick` tries a short list of candidates one at a time and stops at the first
|
|
276
|
+
that works, printing the bare ref on stdout — so recovering from the above is
|
|
277
|
+
one substitution, whether a person or an agent is doing it:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
zen rag schema index --embedding "$(zen models pick --embedding)" ./specs/*.yaml
|
|
281
|
+
```
|
|
239
282
|
|
|
240
283
|
### Vertex AI
|
|
241
284
|
|
|
242
|
-
Vertex
|
|
285
|
+
Vertex takes two kinds of credential, and you never say which you are giving:
|
|
286
|
+
if the value is a path to a file that exists it is a service-account key, and
|
|
287
|
+
otherwise it is treated as an API key. The name you choose for the entry has no
|
|
288
|
+
say in it — `vertex/express` is simply an entry called `express`, exactly as
|
|
289
|
+
`vertex/prod` is one called `prod`, and either name can hold either kind.
|
|
243
290
|
|
|
244
291
|
The usual one is a **service-account JSON file** — give its path, not its
|
|
245
|
-
contents:
|
|
292
|
+
contents. Run the command with nothing piped and it asks:
|
|
293
|
+
|
|
294
|
+
```sh
|
|
295
|
+
zen key add vertex --location us-central1
|
|
296
|
+
# Paste the key, or a path to the file: /Users/you/keys/vertex-sa.json
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
The prompt is read by `zen`, not by your shell, so give a full path there — `~`
|
|
300
|
+
is not expanded. In a script, pipe the path in instead:
|
|
246
301
|
|
|
247
302
|
```sh
|
|
248
|
-
|
|
303
|
+
echo ~/keys/vertex-sa.json | zen key add vertex --location us-central1
|
|
249
304
|
```
|
|
250
305
|
|
|
251
|
-
The file is copied into `~/.zenera/neo/keys
|
|
252
|
-
cleaning up the original later cannot break it.
|
|
306
|
+
The file is copied into `~/.zenera/neo/keys/`, where only you can read it, so
|
|
307
|
+
moving or cleaning up the original later cannot break it.
|
|
253
308
|
|
|
254
309
|
- `--location <region>` is worth setting. It must be `global` or a **concrete
|
|
255
310
|
region**; multi-region names like `us` are rejected with a 404. `global`
|
|
@@ -258,10 +313,73 @@ cleaning up the original later cannot break it.
|
|
|
258
313
|
- `--project <id>` is only needed when the `project_id` inside the file is not
|
|
259
314
|
the project you want.
|
|
260
315
|
|
|
261
|
-
The alternative is an **express-mode API key
|
|
262
|
-
`VERTEX_API_KEY`.
|
|
316
|
+
The alternative is an **express-mode API key** — a single secret, stored under
|
|
317
|
+
`VERTEX_API_KEY`. It is the Vertex console's way of handing out access without a
|
|
318
|
+
service account, and it needs neither a project nor a region, so `--project` and
|
|
263
319
|
`--location` mean nothing there and are not stored.
|
|
264
320
|
|
|
321
|
+
### Gemini, three ways
|
|
322
|
+
|
|
323
|
+
The same Gemini models are reachable through three different credentials, and
|
|
324
|
+
which one you hold decides the prefix a model reference needs.
|
|
325
|
+
|
|
326
|
+
**AI Studio** — one key and nothing else to configure, the shortest way to a
|
|
327
|
+
working `gemini-3.5-flash`:
|
|
328
|
+
|
|
329
|
+
```sh
|
|
330
|
+
zen key add google # asks for the key without showing it
|
|
331
|
+
zen check # google:gemini-3.5-flash now resolves
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**Vertex, service account** — what production usually runs on. Give the path
|
|
335
|
+
and a region, because the file says which project it belongs to but never which
|
|
336
|
+
region to call:
|
|
337
|
+
|
|
338
|
+
```sh
|
|
339
|
+
echo ~/keys/vertex-sa.json | zen key add vertex --location us-central1
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Add `--project` only when the `project_id` inside the file is not the one you
|
|
343
|
+
want to bill:
|
|
344
|
+
|
|
345
|
+
```sh
|
|
346
|
+
echo ~/keys/vertex-sa.json \
|
|
347
|
+
| zen key add vertex --project other-project --location europe-west4
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Vertex, express mode** — paste the key at the prompt; no flags apply:
|
|
351
|
+
|
|
352
|
+
```sh
|
|
353
|
+
zen key add vertex
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Holding several at once is the ordinary case. Name them and switch:
|
|
357
|
+
|
|
358
|
+
```sh
|
|
359
|
+
echo ~/keys/prod-sa.json | zen key add vertex/prod --location us-central1
|
|
360
|
+
echo ~/keys/dev-sa.json | zen key add vertex/dev --location global
|
|
361
|
+
zen key add vertex/express # the express key, same provider
|
|
362
|
+
|
|
363
|
+
zen key use vertex/dev # which one the next run uses
|
|
364
|
+
zen key ls --check # all three, and whether they still work
|
|
365
|
+
zen key show vertex/prod # masked; --reveal prints the path
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
`google` and `vertex` can both be configured — they are separate entries for
|
|
369
|
+
separate services, and the reference picks:
|
|
370
|
+
|
|
371
|
+
```sh
|
|
372
|
+
zen run --model google:gemini-3.5-flash "summarise this repo"
|
|
373
|
+
zen run --model vertex:gemini-3.5-flash "summarise this repo"
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
If you have already run `gcloud auth application-default login`, that login is
|
|
377
|
+
itself a usable credential: `zen key ls` shows it as `adc`, marked `~` because
|
|
378
|
+
it came from outside the keyring, and Vertex works with nothing stored at all.
|
|
379
|
+
Anything already set in `GOOGLE_APPLICATION_CREDENTIALS`, `VERTEX_API_KEY` or
|
|
380
|
+
`GEMINI_API_KEY` is listed the same way and wins over the keyring, so it is
|
|
381
|
+
always visible which credential a run will actually use.
|
|
382
|
+
|
|
265
383
|
### More than one key per provider
|
|
266
384
|
|
|
267
385
|
Entries are named, so a provider can hold several and one of them is active:
|
|
@@ -275,32 +393,34 @@ zen key env openai # shell exports, for other tools
|
|
|
275
393
|
zen key rm openai/work
|
|
276
394
|
```
|
|
277
395
|
|
|
278
|
-
`zen key ls` marks the active entry with `*`, and
|
|
279
|
-
|
|
280
|
-
working provider actually comes from.
|
|
396
|
+
`zen key ls` marks the active entry with `*`, and anything it found outside the
|
|
397
|
+
keyring — in your environment, or in a `gcloud` login — with `~`, so it is always
|
|
398
|
+
clear where a working provider actually comes from.
|
|
281
399
|
|
|
282
400
|
## Concepts
|
|
283
401
|
|
|
284
402
|
- **Project** — a named directory holding a complete agent definition and the
|
|
285
403
|
sessions that ran against it. Self-describing: `agents.yaml` is what makes it
|
|
286
404
|
one, so moving or cloning the directory loses nothing.
|
|
287
|
-
- **Session** — a context that persists: one workspace, one memory, one
|
|
288
|
-
|
|
405
|
+
- **Session** — a context that persists: one workspace, one memory, one store
|
|
406
|
+
for large files, and a record of everything that happened, added to as it
|
|
407
|
+
goes. Resumable.
|
|
289
408
|
- **Run** — one prompt in, one answer out, inside a session. Recorded in full,
|
|
290
409
|
whether or not you were watching.
|
|
291
410
|
- **Workspace** — the directory the agents may read and write. A prompt given on
|
|
292
411
|
the command line uses the current directory; the TUI offers the session's own
|
|
293
412
|
empty folder and confirms anything outside it.
|
|
294
|
-
- **Keyring** — `~/.zenera/neo`,
|
|
295
|
-
environment just before a run, so
|
|
296
|
-
checked out on a machine without `zen` still runs.
|
|
413
|
+
- **Keyring** — `~/.zenera/neo`, readable only by you. Keys are copied into the
|
|
414
|
+
environment just before a run, so an environment variable you set yourself
|
|
415
|
+
always wins and a project checked out on a machine without `zen` still runs.
|
|
297
416
|
|
|
298
417
|
## The library underneath
|
|
299
418
|
|
|
300
419
|
This is a shell over
|
|
301
420
|
[`@zenera/neo`](https://www.npmjs.com/package/@zenera/neo) — agents, models,
|
|
302
|
-
tools, skills, memory and
|
|
303
|
-
want the runtime inside your own application rather than on a
|
|
421
|
+
tools, skills, memory and a running record of everything that happened. Use it
|
|
422
|
+
directly when you want the runtime inside your own application rather than on a
|
|
423
|
+
terminal:
|
|
304
424
|
[its README](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/neo/README.md).
|
|
305
425
|
|
|
306
426
|
## Documentation
|
package/dist/audit.d.ts
CHANGED
|
@@ -11,10 +11,13 @@ export interface ModelIssue {
|
|
|
11
11
|
provider: string;
|
|
12
12
|
/** the variable that would carry the credential */
|
|
13
13
|
env: string;
|
|
14
|
-
/** `missing` — nothing to authenticate with. `dead` — rejected when checked.
|
|
15
|
-
|
|
14
|
+
/** `missing` — nothing to authenticate with. `dead` — rejected when checked.
|
|
15
|
+
* `blocked` — accepted, and then refused by the account behind it. */
|
|
16
|
+
reason: 'missing' | 'dead' | 'blocked';
|
|
16
17
|
/** the provider's own words, when it was the one to say no */
|
|
17
18
|
detail?: string;
|
|
19
|
+
/** what to do about a refusal that a new key would not fix */
|
|
20
|
+
fix?: string;
|
|
18
21
|
/** the keyring provider the fix names, when the kind is one of them */
|
|
19
22
|
add?: Provider;
|
|
20
23
|
}
|
package/dist/audit.js
CHANGED
|
@@ -103,14 +103,15 @@ export function auditModels(projectDir, store) {
|
|
|
103
103
|
// reinstated between the check and the run, and a stale verdict must
|
|
104
104
|
// not be the thing that stops a run from being attempted.
|
|
105
105
|
const check = provider ? store.active(provider)?.check : undefined;
|
|
106
|
-
if (check?.state === 'dead') {
|
|
106
|
+
if (check?.state === 'dead' || check?.state === 'blocked') {
|
|
107
107
|
issues.push({
|
|
108
108
|
name,
|
|
109
109
|
role,
|
|
110
110
|
provider: need.provider,
|
|
111
111
|
env,
|
|
112
|
-
reason:
|
|
112
|
+
reason: check.state,
|
|
113
113
|
detail: check.detail,
|
|
114
|
+
fix: check.fix,
|
|
114
115
|
add: provider,
|
|
115
116
|
});
|
|
116
117
|
}
|
|
@@ -130,6 +131,10 @@ export function describeIssue(issue) {
|
|
|
130
131
|
return `${what} has no credential — ${issue.env} is not set; ${dim(fix)}`;
|
|
131
132
|
}
|
|
132
133
|
const why = issue.detail ? `: ${issue.detail}` : '';
|
|
134
|
+
if (issue.reason === 'blocked') {
|
|
135
|
+
const pick = `zen models pick --${issue.role === 'embedding' ? 'embedding' : 'chat'}`;
|
|
136
|
+
return `${what} authenticated and was then refused${why} — ${dim(issue.fix ?? pick)}`;
|
|
137
|
+
}
|
|
133
138
|
const fix = `zen key check ${issue.add ?? ''}`.trim();
|
|
134
139
|
return `${what} was rejected when last checked${why} — ${dim(fix)}`;
|
|
135
140
|
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type KeyCheck, type Provider } from './keys.ts';
|
|
2
|
+
/**
|
|
3
|
+
* What a model is *for*. A model can hold more than one — Gemini's embedding
|
|
4
|
+
* endpoint and its chat endpoint are the same catalog row on some providers —
|
|
5
|
+
* so this is a set rather than a field.
|
|
6
|
+
*/
|
|
7
|
+
export type Role = 'chat' | 'embedding' | 'image' | 'audio';
|
|
8
|
+
export interface CatalogEntry {
|
|
9
|
+
/** `provider:id` — paste-able straight into `agents.yaml` */
|
|
10
|
+
ref: string;
|
|
11
|
+
/** the id that goes on the wire, with any resource prefix already stripped */
|
|
12
|
+
id: string;
|
|
13
|
+
provider: Provider;
|
|
14
|
+
roles: Role[];
|
|
15
|
+
name?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
/** total tokens the model will accept in one request */
|
|
18
|
+
contextLength?: number;
|
|
19
|
+
maxOutputTokens?: number;
|
|
20
|
+
/** embeddings only, when the vendor publishes it */
|
|
21
|
+
dimensions?: number;
|
|
22
|
+
modalities?: {
|
|
23
|
+
input?: string[];
|
|
24
|
+
output?: string[];
|
|
25
|
+
};
|
|
26
|
+
supports?: {
|
|
27
|
+
tools?: boolean;
|
|
28
|
+
reasoning?: boolean;
|
|
29
|
+
vision?: boolean;
|
|
30
|
+
};
|
|
31
|
+
/** USD per token, as the vendor writes it — strings, because they are tiny */
|
|
32
|
+
pricing?: {
|
|
33
|
+
prompt?: string;
|
|
34
|
+
completion?: string;
|
|
35
|
+
free?: boolean;
|
|
36
|
+
};
|
|
37
|
+
/** ISO date the model was published, when known */
|
|
38
|
+
created?: string;
|
|
39
|
+
source: 'live' | 'curated';
|
|
40
|
+
}
|
|
41
|
+
/** A provider's listing, and an honest account of where it came from. */
|
|
42
|
+
export interface Catalog {
|
|
43
|
+
provider: Provider;
|
|
44
|
+
entries: CatalogEntry[];
|
|
45
|
+
/** `live` asked just now; `cache` a fresh file; `stale` an expired one; `curated` the fallback */
|
|
46
|
+
origin: 'live' | 'cache' | 'stale' | 'curated';
|
|
47
|
+
/** when the entries were actually fetched, not when they were read */
|
|
48
|
+
fetchedAt: string;
|
|
49
|
+
/** why the live call was not used, when it was tried and failed */
|
|
50
|
+
problem?: KeyCheck;
|
|
51
|
+
}
|
|
52
|
+
/** A day. Model lists change on the scale of weeks; a stale row costs a retry. */
|
|
53
|
+
export declare const CATALOG_TTL_MS: number;
|
|
54
|
+
/**
|
|
55
|
+
* Enough to work with when the provider cannot be asked — offline, no
|
|
56
|
+
* credential, or a listing endpoint that is down. Deliberately short: this is
|
|
57
|
+
* the set worth typing, not the set that exists.
|
|
58
|
+
*
|
|
59
|
+
* Anthropic publishes no embeddings API at all, which is why it has no
|
|
60
|
+
* embedding row here and why the registry throws rather than guessing.
|
|
61
|
+
*/
|
|
62
|
+
export declare const CURATED: Record<Provider, readonly Omit<CatalogEntry, 'ref' | 'provider' | 'source'>[]>;
|
|
63
|
+
/**
|
|
64
|
+
* The order `zen models pick` walks, per provider and per role.
|
|
65
|
+
*
|
|
66
|
+
* Cheap and fast first. `pick` exists to answer "give me something that works"
|
|
67
|
+
* in one round trip where it can, and the small models answer soonest and cost
|
|
68
|
+
* least when the answer is thrown away — which it always is.
|
|
69
|
+
*/
|
|
70
|
+
export declare const PREFERRED: Record<Provider, {
|
|
71
|
+
chat: readonly string[];
|
|
72
|
+
embedding: readonly string[];
|
|
73
|
+
}>;
|
|
74
|
+
/**
|
|
75
|
+
* Asks one provider what it serves. Throws whatever the SDK throws.
|
|
76
|
+
*
|
|
77
|
+
* `client` is a seam, not a feature: the four adapters are the part most likely
|
|
78
|
+
* to break when a vendor reshapes a payload, and they are untestable if the
|
|
79
|
+
* only way to reach them is a credential and a network. It mirrors
|
|
80
|
+
* `ProviderSpec.client`, which exists in the library for the same reason.
|
|
81
|
+
*/
|
|
82
|
+
export declare function fetchCatalog(provider: Provider, client?: unknown): Promise<CatalogEntry[]>;
|
|
83
|
+
export interface CatalogOptions {
|
|
84
|
+
/** ignore a fresh cache and ask the provider again */
|
|
85
|
+
refresh?: boolean;
|
|
86
|
+
/** do not make a network call at all — cache, however old, then curated */
|
|
87
|
+
offline?: boolean;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The listing for one provider, from the cheapest source that can answer.
|
|
91
|
+
*
|
|
92
|
+
* Fresh cache, else the provider, else a *stale* cache, else the curated table.
|
|
93
|
+
* Stale-before-curated is the important ordering: yesterday's real answer from
|
|
94
|
+
* this account beats today's guess about accounts in general, and a listing
|
|
95
|
+
* that failed because the wifi dropped should not silently shrink someone's
|
|
96
|
+
* model list to four rows.
|
|
97
|
+
*/
|
|
98
|
+
export declare function loadCatalog(provider: Provider, opts?: CatalogOptions): Promise<Catalog>;
|
|
99
|
+
/** Every provider asked at once — they are independent and mostly latency. */
|
|
100
|
+
export declare function loadCatalogs(providers: readonly Provider[], opts?: CatalogOptions): Promise<Catalog[]>;
|
|
101
|
+
export interface Filters {
|
|
102
|
+
roles?: readonly Role[];
|
|
103
|
+
tools?: boolean;
|
|
104
|
+
vision?: boolean;
|
|
105
|
+
free?: boolean;
|
|
106
|
+
minContext?: number;
|
|
107
|
+
}
|
|
108
|
+
export declare function matches(row: CatalogEntry, query: string, filters?: Filters): boolean;
|
|
109
|
+
/** The providers a search covers when none was named. */
|
|
110
|
+
export declare const catalogProviders: () => readonly Provider[];
|
|
111
|
+
//# sourceMappingURL=catalog.d.ts.map
|