@zenera/cli 1.1.27 → 1.1.29

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 (51) hide show
  1. package/README.md +127 -75
  2. package/dist/audit.d.ts +2 -2
  3. package/dist/audit.js +11 -4
  4. package/dist/candidates.d.ts +9 -0
  5. package/dist/candidates.js +17 -0
  6. package/dist/catalog.d.ts +10 -5
  7. package/dist/catalog.js +93 -12
  8. package/dist/commands/completion.d.ts +9 -0
  9. package/dist/commands/completion.js +70 -0
  10. package/dist/commands/index.js +2 -0
  11. package/dist/commands/init.js +1 -1
  12. package/dist/commands/key.js +142 -11
  13. package/dist/commands/meta.d.ts +3 -0
  14. package/dist/commands/meta.js +235 -62
  15. package/dist/commands/models.d.ts +12 -0
  16. package/dist/commands/models.js +79 -112
  17. package/dist/completion-install.d.ts +16 -0
  18. package/dist/completion-install.js +85 -0
  19. package/dist/completion.d.ts +9 -0
  20. package/dist/completion.js +93 -0
  21. package/dist/keys.d.ts +27 -4
  22. package/dist/keys.js +63 -3
  23. package/dist/liveness.js +73 -3
  24. package/dist/main.js +22 -0
  25. package/dist/meta/model.d.ts +1 -1
  26. package/dist/meta/model.js +1 -1
  27. package/dist/postinstall.d.ts +2 -0
  28. package/dist/postinstall.js +10 -0
  29. package/dist/sandbox.js +4 -3
  30. package/dist/term.d.ts +2 -0
  31. package/dist/term.js +2 -0
  32. package/dist/tui/links.d.ts +2 -0
  33. package/dist/tui/links.js +31 -7
  34. package/dist/tui/models.d.ts +8 -1
  35. package/dist/tui/models.js +25 -18
  36. package/dist/validate.js +2 -2
  37. package/package.json +8 -6
  38. package/postinstall.mjs +7 -0
  39. package/templates/completions/zen.bash +16 -0
  40. package/templates/completions/zen.fish +22 -0
  41. package/templates/completions/zen.zsh +28 -0
  42. package/templates/editor/.github/copilot-instructions.md +5 -4
  43. package/templates/editor/.github/prompts/spec-edit.prompt.md +250 -0
  44. package/templates/editor/.github/skills/zen-analyze-run/SKILL.md +5 -0
  45. package/templates/editor/.github/skills/zen-cli/SKILL.md +2 -2
  46. package/templates/editor/.github/skills/zen-cli/references/keys.md +27 -2
  47. package/templates/editor/.github/skills/zen-cli/references/models.md +22 -23
  48. package/dist/meta/finetune/guard.d.ts +0 -29
  49. package/dist/meta/finetune/guard.js +0 -104
  50. package/dist/meta.d.ts +0 -291
  51. package/dist/meta.js +0 -981
package/README.md CHANGED
@@ -1,8 +1,15 @@
1
+ <div align="center">
2
+ <img
3
+ src="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/zenera-logo-with-media-queries.svg"
4
+ alt="Zenera Logo"
5
+ width="20"
6
+ />
7
+ <div>Powered By Zenera</div>
8
+ </div>
9
+ <br>
10
+
1
11
  <div align="center">
2
- <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/banner-cli-dark.svg">
4
- <img src="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/banner-cli-light.svg" alt="ZENERA CLI" width="720">
5
- </picture>
12
+ <img src="https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/banner-cli-with-media-queries.svg" alt="ZENERA CLI" width="720">
6
13
 
7
14
  [![npm](https://img.shields.io/npm/v/@zenera/cli.svg)](https://www.npmjs.com/package/@zenera/cli)
8
15
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/andreyryabov/ZeneraNeo/blob/main/LICENSE)
@@ -110,6 +117,28 @@ Or without installing anything:
110
117
  npx @zenera/cli --help
111
118
  ```
112
119
 
120
+ Tab completion for zsh, bash and fish - commands, projects, stored prompts - is
121
+ set up automatically by the global npm install. It appends a guarded loader to
122
+ your current shell's startup file, once. **Open a new terminal** to activate it;
123
+ the installer cannot update the terminal where you ran npm.
124
+
125
+ Setup respects `ZDOTDIR` for zsh and `XDG_CONFIG_HOME` for fish. For Bash on
126
+ macOS it covers both login shells (the active `.bash_profile`, `.bash_login` or
127
+ `.profile`) and non-login shells (`.bashrc`). The loader does nothing when `zen`
128
+ is no longer installed.
129
+
130
+ Local installs and `npx` do not change shell files. Automatic setup is skipped
131
+ under root/sudo, in CI, on Windows, or when `$SHELL` is missing or unsupported.
132
+ Disabling lifecycle scripts with `--ignore-scripts` also disables setup.
133
+ If automatic setup is skipped or fails, or to enable another shell, run:
134
+
135
+ ```sh
136
+ zen completion --install # the shell you are in; --yes to skip the question
137
+ zen completion fish --install # or name one
138
+ ```
139
+
140
+ Or add it yourself: `eval "$(zen completion zsh)"` in `~/.zshrc`.
141
+
113
142
  ## Quickstart
114
143
 
115
144
  From nothing to a specialized agent system:
@@ -121,16 +150,15 @@ zen init my-project # scaffolds a project and registers it
121
150
  zen open my-project # open the specification and project in your editor
122
151
  ```
123
152
 
124
- In the editor, describe the job in `SPECIFICATION.md`, then send this in the
125
- agent chat:
153
+ In the editor, describe the job in `SPECIFICATION.md`. Then, back in the
154
+ terminal, let the meta agent build the system from it:
126
155
 
127
- ```
128
- /spec-sync-project
156
+ ```sh
157
+ zen meta run my-project /spec-sync-project
129
158
  ```
130
159
 
131
160
  It creates the specialists, responsibilities, tool access and handoffs the job
132
- needs. Back in the terminal, validate the generated system and run it against a
133
- real workspace:
161
+ needs. Validate the generated system and run it against a real workspace:
134
162
 
135
163
  ```sh
136
164
  zen check my-project
@@ -170,10 +198,11 @@ dashboard rewritten every second: what each item is doing right now, what the
170
198
  finished ones cost - per model, since agents may each use a different one - and
171
199
  what is still queued.
172
200
 
173
- To change what the system does, update `SPECIFICATION.md` and send
174
- `/spec-sync-project` again. The next section explains that workflow in detail.
201
+ To change what the system does, update `SPECIFICATION.md` and run
202
+ `zen meta run /spec-sync-project` again. The next section explains that workflow
203
+ in detail.
175
204
 
176
- ## You write the specification; a coding agent writes the system
205
+ ## You write the specification; the meta agent writes the system
177
206
 
178
207
  `zen init` writes `SPECIFICATION.md` first, and everything else in the folder
179
208
  implements it. Where the two disagree the specification wins, so a change to
@@ -201,9 +230,9 @@ nobody to hand work to, because there is no second job to hand on.
201
230
 
202
231
  ### How you actually edit it
203
232
 
204
- `SPECIFICATION.md` is ordinary Markdown, so any editor will do - but the loop is
205
- meant to be driven from a coding agent's chat, and `zen init` installs the
206
- prompts that make each step a single command:
233
+ `SPECIFICATION.md` is ordinary Markdown, so any editor will do. `zen init`
234
+ installs the prompts that make each step of the loop a single `zen meta run`
235
+ command:
207
236
 
208
237
  ```sh
209
238
  zen open my-project # or, standing in the folder: zen open
@@ -213,30 +242,29 @@ That launches the editor you already use: the one this terminal belongs to, or
213
242
  `$ZENERA_EDITOR`, or the first of VS Code, Cursor, Windsurf, Zed, Sublime Text
214
243
  or IntelliJ it can find. `--editor <cmd>` names one outright.
215
244
 
216
- In the window that opens:
217
-
218
245
  1. **Edit `SPECIFICATION.md`** - what the system is for, which agents exist,
219
246
  what each may reach for, and what _done_ means.
220
- 2. **Open the chat panel and send `/spec-sync-project`.** It reads the
221
- specification and every file implementing it, works out the difference in
222
- both directions, and changes the smallest thing that closes each gap.
247
+ 2. **Run `zen meta run /spec-sync-project`.** It reads the specification and
248
+ every file implementing it, works out the difference in both directions, and
249
+ changes the smallest thing that closes each gap.
223
250
  3. **Answer `SPECIFICATION-FEEDBACK.md`**, which it writes for anything it could
224
251
  not do without guessing. Every question carries two to four written-out
225
252
  answers, each with a `[ ]` box: tick one, delete the ones you do not want, or
226
253
  write your own in their place.
227
- 4. **Send `/spec-apply-feedback`.** It folds the answers you chose into
228
- `SPECIFICATION.md` - never into a prompt - and then `/spec-sync-project` again.
254
+ 4. **Run `zen meta run /spec-apply-feedback`.** It folds the answers you chose
255
+ into `SPECIFICATION.md` - never into a prompt - and then
256
+ `/spec-sync-project` again.
229
257
 
230
- Back in the terminal: `zen check`, then `zen run`.
258
+ Then: `zen check`, then `zen run`.
231
259
 
232
260
  <details>
233
- <summary>The chat commands <code>zen init</code> installs</summary>
261
+ <summary>The prompts <code>zen init</code> installs</summary>
234
262
 
235
- They are prompt files under `.github/prompts/`, which VS Code and its forks
236
- offer as chat slash-commands. Both `zen init` and `zen open` write them fresh,
237
- so they never go stale - and edits to them do not survive.
263
+ They are prompt files under `.github/prompts/`, and `zen meta run /<name>` runs
264
+ one (`zen meta prompts` lists them). Both `zen init` and `zen open` write them
265
+ fresh, so they never go stale - and edits to them do not survive.
238
266
 
239
- | In chat | Does |
267
+ | Prompt | Does |
240
268
  | ---------------------- | ---------------------------------------------------------------- |
241
269
  | `/spec-sync-project` | Makes every file match `SPECIFICATION.md`, both directions. |
242
270
  | `/spec-apply-feedback` | Folds your answers in `SPECIFICATION-FEEDBACK.md` into the spec. |
@@ -245,10 +273,8 @@ so they never go stale - and edits to them do not survive.
245
273
  | `/new-agent` | Adds an agent - prompt, wiring and hand-offs. |
246
274
  | `/new-skill` | Adds a skill under `agents/skills/`. |
247
275
 
248
- In an editor that does not support prompt files, paste the contents of
249
- `.github/prompts/spec-sync-project.prompt.md` into its chat instead - it is only a
250
- prompt. Alongside them, `.github/copilot-instructions.md` is the standing brief
251
- that explains this runtime to whatever agent is reading, and
276
+ Alongside them, `.github/copilot-instructions.md` is the standing brief that
277
+ explains this runtime to whatever coding agent opens the folder, and
252
278
  `.github/skills/zen-cli/` is the CLI's own reference for it.
253
279
 
254
280
  </details>
@@ -256,9 +282,9 @@ that explains this runtime to whatever agent is reading, and
256
282
  ### The self-improving loop
257
283
 
258
284
  ```
259
- edit SPECIFICATION.md → /spec-sync-project → zen check → zen run
260
- ↑ ↓
261
- └───── refine the spec <-──── zen inspect <-───────┘
285
+ edit SPECIFICATION.md → zen meta run /spec-sync-project → zen check → zen run
286
+ ↑ ↓
287
+ └─────────── refine the spec <-──── zen inspect <-─────────────┘
262
288
  ```
263
289
 
264
290
  `zen inspect` makes the record visible: the run trace, timing and token
@@ -266,7 +292,7 @@ statistics, agent architecture, and memory used during the run.
266
292
 
267
293
  ![Run inspection: trace, agent architecture, and memory](https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/docs/imgs/0910_480.gif)
268
294
 
269
- The agent in your editor can close the same loop without the page. `zen inspect
295
+ The meta agent can close the same loop without the page. `zen inspect
270
296
  graph` writes the whole run as one Mermaid flowchart - a line per node, short
271
297
  sequential ids, the tools counted in a header - which is small enough to read
272
298
  whole. Having spotted the loop or the branch that failed, it opens the two or
@@ -287,7 +313,7 @@ prompt that reads correctly and behaves wrongly explains itself.
287
313
  `ask` has two modes, decided by whether the question is given:
288
314
 
289
315
  - **One-shot** - a question on the line, in `--question-file`, or `--json`.
290
- For a script or the agent in your editor: no banner, no prompt, no picker.
316
+ For a script or the meta agent: no banner, no prompt, no picker.
291
317
  stdout is the answer and nothing else, and the command exits.
292
318
  - **Interactive** - no question. For you, at a terminal: `zen inspect ask`
293
319
  walks through the session, run and recorded LLM call (whichever are not
@@ -298,8 +324,8 @@ prompt that reads correctly and behaves wrongly explains itself.
298
324
  Every step is a command, and everything each one reads or writes is a plain
299
325
  file: the specification, the findings `zen check` prints with a code, a location
300
326
  and a fix, the record `zen inspect` renders of what the run actually did. So the
301
- loop does not need you standing in it. Hand the whole cycle to the agent in your
302
- editor and it runs on the system it just built - test it, read the failure,
327
+ loop does not need you standing in it. Hand the whole cycle to the meta agent
328
+ and it runs on the system it just built - test it, read the failure,
303
329
  change the sentence in the specification that caused it, rebuild, run again.
304
330
  "Fix my project" is one instruction. (The first time round, `scripts/_setup.sh`
305
331
  prepares the container the tools run in.)
@@ -344,7 +370,7 @@ Read a codebase and leave a short written note about it in the workspace.
344
370
  - Every claim in it comes from a file that was actually read.
345
371
  ```
346
372
 
347
- Send `/spec-sync-project` in the editor's chat. It writes `agents.yaml` - who
373
+ Run `zen meta run /spec-sync-project`. It writes `agents.yaml` - who
348
374
  exists, and what each may reach for:
349
375
 
350
376
  ```yaml
@@ -553,24 +579,25 @@ The commands to run next are printed for you to read and type.
553
579
 
554
580
  ## Commands
555
581
 
556
- | Command | Does |
557
- | --------- | -------------------------------------------------------------------- |
558
- | `init` | Creates a project here, or in `<dir>`, and registers it. |
559
- | `list` | Every known project: sessions, last run, whether one is live. |
560
- | `open` | Opens a project in your editor. |
561
- | `key` | The credential keyring - add, check, switch, remove. |
562
- | `models` | What this machine can use - list, search, test, pick. |
563
- | `run` | Runs the project - the TUI on a terminal, a single answer otherwise. |
564
- | `meta` | Runs the meta agent over the project - the one that edits it. |
565
- | `inspect` | Opens or rebuilds a run's `report.html`. |
566
- | `view` | Shows a folder in the browser, redrawn live as its files change. |
567
- | `memory` | What the agents remember - size, listing, one node, or a whole page. |
568
- | `check` | Validates the project and every file it names, and asks the models. |
569
- | `export` | Writes the project to a shareable zip archive. |
570
- | `import` | Unpacks one, registers it, and runs nothing in it. |
571
- | `sandbox` | Checks and prepares the container that command-line tools run in. |
572
- | `cache` | What work has been kept, and getting rid of it. |
573
- | `version` | CLI, library and Node versions. |
582
+ | Command | Does |
583
+ | ------------ | -------------------------------------------------------------------- |
584
+ | `init` | Creates a project here, or in `<dir>`, and registers it. |
585
+ | `list` | Every known project: sessions, last run, whether one is live. |
586
+ | `open` | Opens a project in your editor. |
587
+ | `key` | The credential keyring - add, check, switch, remove. |
588
+ | `models` | What this machine can use - list, search, test, pick. |
589
+ | `run` | Runs the project - the TUI on a terminal, a single answer otherwise. |
590
+ | `meta` | Runs the meta agent over the project - the one that edits it. |
591
+ | `inspect` | Opens or rebuilds a run's `report.html`. |
592
+ | `view` | Shows a folder in the browser, redrawn live as its files change. |
593
+ | `memory` | What the agents remember - size, listing, one node, or a whole page. |
594
+ | `check` | Validates the project and every file it names, and asks the models. |
595
+ | `export` | Writes the project to a shareable zip archive. |
596
+ | `import` | Unpacks one, registers it, and runs nothing in it. |
597
+ | `sandbox` | Checks and prepares the container that command-line tools run in. |
598
+ | `cache` | What work has been kept, and getting rid of it. |
599
+ | `completion` | Tab completion for zsh, bash and fish - printed, or installed. |
600
+ | `version` | CLI, library and Node versions. |
574
601
 
575
602
  ### Commands from other packages
576
603
 
@@ -645,8 +672,8 @@ an accident.
645
672
  the project: a coding agent rooted at the project directory, which reads
646
673
  `SPECIFICATION.md`, changes `agents.yaml`, the prompts and the skills, and runs
647
674
  whatever commands it needs to check itself - on the keys already in your
648
- keyring, and not on anybody's subscription. It is the loop your editor's chat
649
- panel drives, as a command you can put in a script.
675
+ keyring, and not on anybody's subscription. It is the spec-to-system loop as a
676
+ command you can put in a script.
650
677
 
651
678
  ```sh
652
679
  zen meta run "what does this project do?"
@@ -663,9 +690,9 @@ Every prompt goes through `run`, whether you typed it or it is a file: the
663
690
  alternative was a verb that appeared only sometimes, and a bare word after
664
691
  `zen meta` that was a subcommand on Tuesdays and a question on Wednesdays.
665
692
 
666
- It uses every tool without asking. The prompts it runs were written for an
667
- editor, where reading files, writing them and running commands is the whole
668
- point, and a `-p` run has nobody sitting there to answer the question - so the
693
+ It uses every tool without asking. The prompts it runs rely on reading files,
694
+ writing them and running commands, and a `-p` run has nobody sitting there to
695
+ answer the question - so the
669
696
  alternative is not a safer run but a stalled one. `--allow-tool read`,
670
697
  `--allow-tool 'shell(git:*)'` narrow it to what a particular run needs, and
671
698
  `--ask` puts the question back. It is your own checkout and your own key either
@@ -683,11 +710,10 @@ to `.tmp/logs/meta.<when>.log`, whose path is printed before the run starts, so
683
710
  kept beside it as `.tmp/logs/meta.<when>.md`, named again once it has printed -
684
711
  a terminal turns that into something you click.
685
712
 
686
- `zen meta run /<name>` is the part an editor cannot do for you from a script.
687
- The prompts under `.github/prompts/` - `/spec-sync-project`, `/project-review` -
688
- are what a chat panel offers as slash commands, and nothing outside an editor
689
- reads them. zen reads one, drops the frontmatter and sends the body - so the
690
- same prompt runs from the editor, from a terminal and from CI.
713
+ `zen meta run /<name>` runs a prompt file. The prompts under
714
+ `.github/prompts/` - `/spec-sync-project`, `/project-review` - are plain
715
+ Markdown with frontmatter. zen reads one, drops the frontmatter and sends the
716
+ body - so the same prompt runs from a terminal, a script and CI.
691
717
 
692
718
  A terminal has no menu dropping down as you type a slash, so
693
719
  `zen meta prompts` lists what this project holds, each with its description.
@@ -757,6 +783,9 @@ fixes and the memory are making runs cheaper; each case has its own
757
783
  every try. `start` prints a local address that shows those pages in a browser,
758
784
  with their diagrams drawn, updated in place as the tuning writes them.
759
785
 
786
+ The whole method, with how to write a rubric that tunes the right thing:
787
+ [docs/finetuning.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/finetuning.md).
788
+
760
789
  ## Credentials
761
790
 
762
791
  One keyring serves every provider, and a key goes in the same way whatever it
@@ -813,7 +842,6 @@ zen models openai # everything OpenAI serves this acco
813
842
  zen models search haiku --tools --free # narrow it
814
843
  zen models show openrouter:anthropic/claude-haiku-4.5
815
844
  zen models test vertex:gemini-embedding-001 # one real call, one verdict
816
- zen models pick --embedding # the first ref that answers, on stdout
817
845
  zen models browse # walk providers and models with the arrow keys
818
846
  ```
819
847
 
@@ -837,15 +865,15 @@ $ zen models test vertex:gemini-embedding-001
837
865
  vertex:gemini-embedding-001 blocked Vertex AI API has not been used in project my-proj …
838
866
  fix vertex:gemini-embedding-001 gcloud services enable aiplatform.googleapis.com --project my-proj
839
867
  error 1 of 1 did not answer
840
- find one that does: zen models pick --embedding
868
+ see what else there is: zen models ls --embeddings
841
869
  ```
842
870
 
843
- `zen models pick` tries a short list of candidates one at a time, stops at the
844
- first that works, and prints the bare reference on stdout. So recovering from
845
- the above is a single substitution, whether a person or an agent is doing it:
871
+ To take another model instead, list what the account serves, test one, and put
872
+ its ref in `agents.yaml` or the flag that needs it:
846
873
 
847
874
  ```sh
848
- zen rag schema index --embedding "$(zen models pick --embedding)" ./specs/*.yaml
875
+ zen models ls --embeddings
876
+ zen models test openai:text-embedding-3-small
849
877
  ```
850
878
 
851
879
  `zen models browse [provider]` is the interactive way in: arrow keys through
@@ -1023,6 +1051,26 @@ clear where a working provider actually comes from.
1023
1051
 
1024
1052
  </details>
1025
1053
 
1054
+ <details>
1055
+ <summary><strong>Every model through a Bifrost gateway</strong></summary>
1056
+
1057
+ With one virtual key in place of every vendor key:
1058
+
1059
+ ```sh
1060
+ zen key add bifrost --url https://bifrost.example.com
1061
+ zen key mode bifrost # every run goes through the gateway
1062
+ zen key mode direct # back to the vendor keys
1063
+ ```
1064
+
1065
+ `agents.yaml` does not change. Each model keeps its own vendor's protocol and
1066
+ is sent to the gateway's matching endpoint - `vertex:gemini-3.5-flash` reaches
1067
+ `/genai` as `vertex/gemini-3.5-flash` - so thinking and cache accounting
1068
+ survive the trip. The whole story - variables, the sandbox, `zen models`, known
1069
+ limits - is in
1070
+ [docs/gateway.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/gateway.md).
1071
+
1072
+ </details>
1073
+
1026
1074
  ## Cache - work you have already paid for
1027
1075
 
1028
1076
  Embedding a paragraph, parsing a document, asking a provider what it serves: all
@@ -1072,6 +1120,10 @@ terminal:
1072
1120
  - making an API description searchable and mockable.
1073
1121
  - [docs/memory.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/memory.md)
1074
1122
  - what agents keep between sessions.
1123
+ - [docs/finetuning.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/finetuning.md)
1124
+ - building a dataset, writing rubrics, and tuning the project on them.
1125
+ - [docs/gateway.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/gateway.md)
1126
+ - every model through a Bifrost gateway, with one virtual key.
1075
1127
 
1076
1128
  ## License
1077
1129
 
package/dist/audit.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type ModelRequirement } from '@zenera/neo';
2
- import { type KeyStore, type Provider } from './keys.ts';
2
+ import { type KeyOwner, type KeyStore } from './keys.ts';
3
3
  /** Which key of the config named a reference: `model:`/`models:` or `embedding:`/`embeddings:`. */
4
4
  export type DeclaredRole = 'model' | 'embedding';
5
5
  export interface ModelIssue {
@@ -19,7 +19,7 @@ export interface ModelIssue {
19
19
  /** what to do about a refusal that a new key would not fix */
20
20
  fix?: string;
21
21
  /** the keyring provider the fix names, when the kind is one of them */
22
- add?: Provider;
22
+ add?: KeyOwner;
23
23
  }
24
24
  /**
25
25
  * Whether a requirement is actually met, and under which variable.
package/dist/audit.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { projectRegistry, readProjectConfig, } from '@zenera/neo';
2
- import { envNames, form, gcloudAdc, isProvider, SHAPES, } from "./keys.js";
2
+ import { envNames, form, gcloudAdc, isOwner, isProvider, SHAPES, } from "./keys.js";
3
3
  import { bold, dim } from "./term.js";
4
4
  /**
5
5
  * Every model the project names, keyed by how one would refer to it.
@@ -48,6 +48,9 @@ function declared(config) {
48
48
  * such answer, so it names the form the provider is usually reached by.
49
49
  */
50
50
  export function credentialFor(need) {
51
+ if (need.gateway) {
52
+ return { env: need.apiKeyEnv, present: need.satisfied };
53
+ }
51
54
  const provider = isProvider(need.kind) ? need.kind : undefined;
52
55
  // A provider with a file form can authenticate without an api key, which is
53
56
  // the only thing `satisfied` knows how to look for.
@@ -86,7 +89,11 @@ export function auditModels(projectDir, store) {
86
89
  continue;
87
90
  }
88
91
  const { env, present } = credentialFor(need);
89
- const provider = isProvider(need.kind) ? need.kind : undefined;
92
+ const provider = need.gateway && isOwner(need.gateway)
93
+ ? need.gateway
94
+ : isProvider(need.kind)
95
+ ? need.kind
96
+ : undefined;
90
97
  if (!present) {
91
98
  issues.push({
92
99
  name,
@@ -132,8 +139,8 @@ export function describeIssue(issue) {
132
139
  }
133
140
  const why = issue.detail ? `: ${issue.detail}` : '';
134
141
  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)}`;
142
+ const list = `zen models ls --${issue.role === 'embedding' ? 'embeddings' : 'chat'}`;
143
+ return `${what} authenticated and was then refused${why} — ${dim(issue.fix ?? list)}`;
137
144
  }
138
145
  const fix = `zen key check ${issue.add ?? ''}`.trim();
139
146
  return `${what} was rejected when last checked${why} — ${dim(fix)}`;
@@ -0,0 +1,9 @@
1
+ export interface Candidate {
2
+ value: string;
3
+ description?: string;
4
+ }
5
+ /** Candidates the word being typed is a prefix of. */
6
+ export declare const matching: (found: readonly Candidate[], prefix: string) => Candidate[];
7
+ /** Registered projects whose directory is still there. */
8
+ export declare function projectNames(): Promise<Candidate[]>;
9
+ //# sourceMappingURL=candidates.d.ts.map
@@ -0,0 +1,17 @@
1
+ import { existsSync } from 'node:fs';
2
+ import * as Projects from "./projects.js";
3
+ /** Candidates the word being typed is a prefix of. */
4
+ export const matching = (found, prefix) => found.filter((c) => c.value.startsWith(prefix));
5
+ /** Registered projects whose directory is still there. */
6
+ export async function projectNames() {
7
+ try {
8
+ const registry = await Projects.Registry.open();
9
+ return registry.entries
10
+ .filter((e) => existsSync(e.path))
11
+ .map((e) => ({ value: e.name, description: e.path }));
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
17
+ //# sourceMappingURL=candidates.js.map
package/dist/catalog.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type Gateway } from '@zenera/neo';
1
2
  import { type KeyCheck, type Provider } from './keys.ts';
2
3
  /**
3
4
  * What a model is *for*. A model can hold more than one — Gemini's embedding
@@ -50,6 +51,11 @@ export interface Catalog {
50
51
  fetchedAt: string;
51
52
  /** why the live call was not used, when it was tried and failed */
52
53
  problem?: KeyCheck;
54
+ /** the gateway it was listed through, when the keyring is in a gateway mode */
55
+ via?: {
56
+ name: string;
57
+ url: string;
58
+ };
53
59
  }
54
60
  /** A day. Model lists change on the scale of weeks; a stale row costs a retry. */
55
61
  export declare const CATALOG_TTL_MS: number;
@@ -64,11 +70,8 @@ export declare const CATALOG_KIND = "catalog";
64
70
  */
65
71
  export declare const CURATED: Record<Provider, readonly Omit<CatalogEntry, 'ref' | 'provider' | 'source'>[]>;
66
72
  /**
67
- * The order `zen models pick` walks, per provider and per role.
68
- *
69
- * Cheap and fast first. `pick` exists to answer "give me something that works"
70
- * in one round trip where it can, and the small models answer soonest and cost
71
- * least when the answer is thrown away — which it always is.
73
+ * The cheap, fast models per provider and role, best first. `zen init` takes
74
+ * its default embedder from here.
72
75
  */
73
76
  export declare const PREFERRED: Record<Provider, {
74
77
  chat: readonly string[];
@@ -85,6 +88,8 @@ export declare function fromVertexPartners(): Promise<CatalogEntry[]>;
85
88
  * `partners` is the same seam for Vertex's second listing.
86
89
  */
87
90
  export declare function fetchCatalog(provider: Provider, client?: unknown, partners?: () => Promise<CatalogEntry[]>): Promise<CatalogEntry[]>;
91
+ /** What the gateway serves under one provider's name, enriched like a vendor listing. */
92
+ export declare function fetchGatewayCatalog(provider: Provider, at: Gateway): Promise<CatalogEntry[]>;
88
93
  /** The key one provider's listing is filed under, version and all. */
89
94
  export declare const catalogKey: (provider: Provider) => string;
90
95
  export interface CatalogOptions {