@zenera/cli 1.1.3 → 1.1.5
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 +4 -3
- 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/scaffold.js +9 -0
- 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/api-schema-index/SKILL.md +130 -9
- package/templates/editor/.github/skills/zen-cli/SKILL.md +7 -4
- 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/editor/.github/skills/zen-cli/references/rag.md +65 -3
- package/templates/project/sandbox/{Dockerfile → Dockerfile.tmpl} +3 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: api-schema-index
|
|
3
|
-
description: What a schema index is, how it finds the right call inside a large OpenAPI/Swagger document, and how to build and query one with `zen rag schema` (or `npx @zenera/cli`) —
|
|
3
|
+
description: What a schema index is, how it finds the right call inside a large OpenAPI/Swagger document, and how to build and query one with `zen rag schema` (or `npx @zenera/cli`) — searching it by meaning, listing and grepping it exactly, and giving it to an agent as tools.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# The schema index
|
|
7
7
|
|
|
8
8
|
A schema index is an OpenAPI/Swagger description turned into something that can
|
|
9
9
|
be **asked a question**. It is built once, on disk, and answered from without a
|
|
10
|
-
model: `zen rag schema index` writes it,
|
|
10
|
+
model: `zen rag schema index` writes it, and five commands read it.
|
|
11
11
|
|
|
12
12
|
It exists because a real specification does not fit in a context window, and
|
|
13
13
|
grepping it does not help. The parts that answer "how do I reset a password?"
|
|
@@ -15,6 +15,33 @@ are scattered on purpose: the field is on a schema, the schema is a request
|
|
|
15
15
|
body, the request body belongs to one operation out of three hundred, and the
|
|
16
16
|
word "password" appears in forty places that are not the one you want.
|
|
17
17
|
|
|
18
|
+
## The commands
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
zen rag schema <index|search|list|grep|show|stats> [spec...]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Command | Answers | Embedder? | Typical |
|
|
25
|
+
| -------- | -------------------------------------- | --------- | ------- |
|
|
26
|
+
| `index` | builds the thing | yes | minutes |
|
|
27
|
+
| `search` | _what is this API's way to do X?_ | **yes** | seconds |
|
|
28
|
+
| `list` | _what methods/types/fields are there?_ | no | instant |
|
|
29
|
+
| `grep` | _does the string X appear anywhere?_ | no | instant |
|
|
30
|
+
| `show` | _print exactly these things_ | no | instant |
|
|
31
|
+
| `stats` | _what is in this index?_ | no | instant |
|
|
32
|
+
|
|
33
|
+
Only `search` ranks, and only `search` costs a network round trip — it embeds
|
|
34
|
+
the query before it can compare anything. The other four read `graph.json` off
|
|
35
|
+
the disk and answer in milliseconds, so reach for `search` when the question is
|
|
36
|
+
vague and for `list`/`grep` when it is precise. If a search feels slow, it is
|
|
37
|
+
that one embedding call, not the index: near-zero CPU for several seconds is
|
|
38
|
+
the tell.
|
|
39
|
+
|
|
40
|
+
> **`search` takes bare words as the query, not as a subcommand.**
|
|
41
|
+
> `zen rag schema search list methods` does not list anything — it runs a
|
|
42
|
+
> semantic search for the phrase _"list methods"_ and returns ten ranked
|
|
43
|
+
> guesses. The listing command is `zen rag schema list methods`.
|
|
44
|
+
|
|
18
45
|
## Why it is a graph and not a search box
|
|
19
46
|
|
|
20
47
|
Two structures, kept together, because neither answers alone:
|
|
@@ -236,7 +263,8 @@ quit
|
|
|
236
263
|
|
|
237
264
|
## Reading it without searching
|
|
238
265
|
|
|
239
|
-
|
|
266
|
+
None of these need an embedder or a credential — they are plain reads of the
|
|
267
|
+
graph on disk.
|
|
240
268
|
|
|
241
269
|
```sh
|
|
242
270
|
zen rag schema show Type:Invoice Method:listInvoices --format ts
|
|
@@ -248,9 +276,96 @@ an index and what built it — counts by kind, the embedding model, the document
|
|
|
248
276
|
it came from. `stats` is the fastest way to answer "is this index the one I
|
|
249
277
|
think it is?".
|
|
250
278
|
|
|
279
|
+
### Which one to reach for
|
|
280
|
+
|
|
281
|
+
| The question | The command |
|
|
282
|
+
| ------------------------------------------------ | ---------------------------------------- |
|
|
283
|
+
| "how do I reset a password with this API?" | `search --method "reset a password"` |
|
|
284
|
+
| "what does the create-user request look like?" | `search --input-type "create user"` |
|
|
285
|
+
| "what operations exist under /users?" | `list methods --path "*/users*"` |
|
|
286
|
+
| "how many operations are there at all?" | `list methods` (or `--json` for `found`) |
|
|
287
|
+
| "is there a field called `mfa_secret` anywhere?" | `grep mfa_secret` |
|
|
288
|
+
| "which schemas mention tenancy?" | `grep tenancy --kind type` |
|
|
289
|
+
| "give me `GetUser` as OpenAPI" | `show --method GetUser --format openapi` |
|
|
290
|
+
| "is this index the right one?" | `stats` |
|
|
291
|
+
|
|
292
|
+
The rule: **a question about meaning is a `search`; a question about presence,
|
|
293
|
+
count or spelling is a `list` or a `grep`.** Search cannot answer the second
|
|
294
|
+
kind, because a ranking always returns its best guesses whether or not any of
|
|
295
|
+
them are right.
|
|
296
|
+
|
|
297
|
+
### Exact matching, when the question is whether something exists
|
|
298
|
+
|
|
299
|
+
Search **ranks**. A ranking returns the top of a list, which means it can never
|
|
300
|
+
tell you that something is absent — "no results" and "not there" look the same.
|
|
301
|
+
When that is the actual question, do not search:
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
zen rag schema list <methods|types|properties> [-d <dir>] [filters…]
|
|
305
|
+
zen rag schema grep <pattern> [-d <dir>] [filters…]
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
| Flag | For | Meaning |
|
|
309
|
+
| ------------------- | ------ | ---------------------------------------------- |
|
|
310
|
+
| `--name <p>` | `list` | Match the name. Repeatable |
|
|
311
|
+
| `--path <p>` | `list` | Match the route (methods). Repeatable |
|
|
312
|
+
| `--method-type <t>` | `list` | `read_only`, `read_write` or `any` |
|
|
313
|
+
| `--direction <d>` | `list` | `input`, `output` or `any` |
|
|
314
|
+
| `--regex` | `grep` | Read the pattern as a regular expression |
|
|
315
|
+
| `--case-sensitive` | `grep` | Stop ignoring case |
|
|
316
|
+
| `--kind <k>` | `grep` | `method`, `type` or `property`. Repeatable |
|
|
317
|
+
| `--ids-only` | `grep` | Bare ids, one per line, for piping |
|
|
318
|
+
| `--source <name>` | both | Only one document, as `stats` names it |
|
|
319
|
+
| `--limit <n>` | both | Print at most n; `found` still counts them all |
|
|
320
|
+
| `--json` | both | `{found, truncated, rows}` / `…, matches}` |
|
|
321
|
+
| `--quiet` | both | No narration |
|
|
322
|
+
|
|
323
|
+
```sh
|
|
324
|
+
zen rag schema list methods # all of them, sorted by route
|
|
325
|
+
zen rag schema list methods --path "*/users*" # every route under /users
|
|
326
|
+
zen rag schema list methods --method-type read_only
|
|
327
|
+
zen rag schema list types --name "*Password*" # every schema so named
|
|
328
|
+
zen rag schema list types --direction output # everything a call can return
|
|
329
|
+
zen rag schema list properties --name password # every field so named
|
|
330
|
+
zen rag schema grep password # every literal occurrence
|
|
331
|
+
zen rag schema grep "pass(word|phrase)" --regex
|
|
332
|
+
zen rag schema grep password --kind type --ids-only
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
`list` walks one kind of node and matches its structured fields; `grep` matches
|
|
336
|
+
the text of every node in the index — the same text the search was built from,
|
|
337
|
+
so the two agree on what the API says. A pattern with `*` or `?` is a glob
|
|
338
|
+
matched against the whole string; a plain word is a substring, so `--name
|
|
339
|
+
password` finds `ResetPasswordPayload` and `--name "Password*"` finds nothing.
|
|
340
|
+
|
|
341
|
+
Both report `found` as the true total even when `--limit` shortens what is
|
|
342
|
+
printed, so a cut answer never misreports how much there is. Nothing matching
|
|
343
|
+
exits 0 with empty stdout — and that emptiness is trustworthy, which is the
|
|
344
|
+
whole point of them.
|
|
345
|
+
|
|
346
|
+
`grep --ids-only` composes:
|
|
347
|
+
|
|
348
|
+
```sh
|
|
349
|
+
zen rag schema grep token --ids-only | xargs zen rag schema show --format ts
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Naming what you want in `show`
|
|
353
|
+
|
|
354
|
+
```sh
|
|
355
|
+
zen rag schema show --method GetCurrentUserInfo --format openapi --exact
|
|
356
|
+
zen rag schema show --type "*Invoice*" --format ts
|
|
357
|
+
zen rag schema show --source billing-api --format openapi
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Ids are one way in, but `--method` and `--type` take the names you already
|
|
361
|
+
have. A bare name means exactly that name; add `*` to take more than one.
|
|
362
|
+
`--exact` prints only what was named instead of the neighbourhood around it,
|
|
363
|
+
which with `--format openapi` gives a valid self-contained slice of the
|
|
364
|
+
specification — enough to generate a client or a mock payload from.
|
|
365
|
+
|
|
251
366
|
## Giving it to an agent
|
|
252
367
|
|
|
253
|
-
The same engine, as
|
|
368
|
+
The same engine, as five tools in the group `schema`. An agent takes them all
|
|
254
369
|
with `schema:*` in its `tools:`.
|
|
255
370
|
|
|
256
371
|
```ts
|
|
@@ -269,12 +384,16 @@ const project = await loadProject('./my-project', { tools: schemaTools(index) })
|
|
|
269
384
|
| `search_api` | the search above, with the same fields |
|
|
270
385
|
| `describe_types` | named schemas as TypeScript, closed over what they refer to |
|
|
271
386
|
| `find_types_with_property` | every schema with a field of this name — exact lookup, no searching |
|
|
272
|
-
| `
|
|
387
|
+
| `list_api` | methods, types or fields by name — complete, and counted in full |
|
|
388
|
+
| `grep_api` | every literal occurrence of a string — the way to prove absence |
|
|
273
389
|
|
|
274
|
-
`
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
390
|
+
Only `search_api` ranks; the other four are exact. `find_types_with_property`
|
|
391
|
+
is the one for the repair loop. When `tsc` says `'password' does not exist in
|
|
392
|
+
type 'PublicUserProfile'`, the model does not need the word explained again —
|
|
393
|
+
it needs the list of types that _do_ have one, and embedding the word will only
|
|
394
|
+
rank the guess it already made near the top. `grep_api` is the same instinct
|
|
395
|
+
widened: it is how a model checks that a search returning nothing really means
|
|
396
|
+
there is nothing.
|
|
278
397
|
|
|
279
398
|
Tell the agent in its prompt to search before it writes a call, and to put the
|
|
280
399
|
intent in the narrow field. A model left to itself puts everything in `all`.
|
|
@@ -290,3 +409,5 @@ intent in the narrow field. A model left to itself puts everything in `all`.
|
|
|
290
409
|
| A usage error before any credential is asked for | Deliberate: everything about the invocation is checked first, so a typo is a typo |
|
|
291
410
|
| Nothing matched | Exit 0 with an empty answer. Try fewer words, or `--all` instead of a narrow field |
|
|
292
411
|
| Answers about the wrong version of the API | Nothing watches the document. Re-index after it changes |
|
|
412
|
+
| A search took ten seconds, using no CPU | One embedding round trip, not the index. `list`/`grep` make none |
|
|
413
|
+
| `search <word> <word>` gave ranked nonsense | Bare words after `search` are the QUERY, not a subcommand. You meant `list`/`grep` |
|
|
@@ -21,14 +21,14 @@ zen list [--sessions] [--prune]
|
|
|
21
21
|
zen run [project] [prompt] [options]
|
|
22
22
|
zen open [project] [--editor <cmd>] [--wait]
|
|
23
23
|
zen key <ls|add|use|check|rm|show|env> [ref] [options]
|
|
24
|
-
zen models
|
|
25
|
-
zen check [name|dir] [--project <name|dir>] [--no-sandbox] [--strict] [--quiet]
|
|
24
|
+
zen models <providers|ls|search|show|test|pick> [ref] [options]
|
|
25
|
+
zen check [name|dir] [--project <name|dir>] [--no-sandbox] [--no-models] [--strict] [--quiet]
|
|
26
26
|
zen inspect [run] [--session <id>] [--open] [--rebuild] [--serve [port]]
|
|
27
27
|
zen sandbox [status|up|pull|clean|disk] [options]
|
|
28
28
|
zen version
|
|
29
29
|
|
|
30
30
|
zen faker <serve|build|cache> [spec...]
|
|
31
|
-
zen rag schema <index|search|show|stats> [spec...]
|
|
31
|
+
zen rag schema <index|search|list|grep|show|stats> [spec...]
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
## Read the reference before answering
|
|
@@ -42,8 +42,9 @@ guess a flag, and do not read them all.
|
|
|
42
42
|
| Global flags, `--json`, exit codes, environment, where files live | [frame.md](./references/frame.md) |
|
|
43
43
|
| Creating, finding or opening a project | [projects.md](./references/projects.md) |
|
|
44
44
|
| Running: the TUI, one-shot answers, sessions, workspaces, overrides | [run.md](./references/run.md) |
|
|
45
|
-
| Validating: `zen check`,
|
|
45
|
+
| Validating: `zen check`, what it can and cannot see | [check.md](./references/check.md) |
|
|
46
46
|
| API keys, providers, the keyring, "no credential" errors | [keys.md](./references/keys.md) |
|
|
47
|
+
| Which models exist, whether one works, recovering from a refusal | [models.md](./references/models.md) |
|
|
47
48
|
| The container shell commands run in, images, `persist` | [sandbox.md](./references/sandbox.md) |
|
|
48
49
|
| Run reports, trajectories, what a session directory holds | [inspect.md](./references/inspect.md) |
|
|
49
50
|
| `zen faker` — a mock API from an OpenAPI/Swagger document | [faker.md](./references/faker.md) |
|
|
@@ -58,6 +59,8 @@ zen run the TUI
|
|
|
58
59
|
zen run "what changed?" one answer, this directory as the workspace
|
|
59
60
|
zen inspect --open what the model was actually given
|
|
60
61
|
zen key ls --check which credentials still work
|
|
62
|
+
zen models test <ref> whether one model actually answers
|
|
63
|
+
zen models pick --embedding the first embedder that does, on stdout
|
|
61
64
|
```
|
|
62
65
|
|
|
63
66
|
Run `zen check` after any edit to `agents.yaml`, a prompt or a skill: it reads
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# Validating — `zen check`
|
|
1
|
+
# Validating — `zen check`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
It reads the project without running it, and spends a few tokens asking each
|
|
4
|
+
model to answer once; `--no-models` gives an answer that costs nothing at all.
|
|
5
5
|
|
|
6
6
|
## `zen check`
|
|
7
7
|
|
|
8
8
|
```
|
|
9
|
-
zen check [name|dir] [--project <name|dir>] [--no-sandbox] [--strict] [--quiet]
|
|
9
|
+
zen check [name|dir] [--project <name|dir>] [--no-sandbox] [--no-models] [--strict] [--quiet]
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
Aliases: `validate`, `doctor`.
|
|
@@ -19,6 +19,7 @@ with a code, a location and the fix for it.
|
|
|
19
19
|
| ----------------------- | --------------------------------------------------- |
|
|
20
20
|
| `--project <name\|dir>` | Which project |
|
|
21
21
|
| `--no-sandbox` | Skip building and smoke-testing the container image |
|
|
22
|
+
| `--no-models` | Skip asking each model to answer |
|
|
22
23
|
| `--strict` | Warnings count as failure |
|
|
23
24
|
| `--quiet` | The findings and nothing else |
|
|
24
25
|
|
|
@@ -39,10 +40,16 @@ checked too. A word that is neither is a usage error (exit 2), not a report.
|
|
|
39
40
|
reachable from some agent.
|
|
40
41
|
- Every declared model and embedding resolves to a provider, and that provider
|
|
41
42
|
has a credential on this machine.
|
|
43
|
+
- Unless `--no-models`, every model that has a credential is **asked to answer**
|
|
44
|
+
once. A key that authenticates says nothing about the id it is spent on, so
|
|
45
|
+
this is the only way to catch a misspelt, retired or ungranted model. A refusal
|
|
46
|
+
is an error (`model.refused`, `embedding.refused`); a model that never answered
|
|
47
|
+
is a warning (`.unreachable`), because that is the network's problem and not
|
|
48
|
+
the project's.
|
|
42
49
|
- The sandbox: paths stay inside the project, the Dockerfile and its context
|
|
43
50
|
exist, and — unless `--no-sandbox` — the image **builds** and one command runs
|
|
44
|
-
in it, against a temporary directory rather than your workspace.
|
|
45
|
-
|
|
51
|
+
in it, against a temporary directory rather than your workspace. No container
|
|
52
|
+
engine at all is a warning, not an error.
|
|
46
53
|
|
|
47
54
|
### Findings
|
|
48
55
|
|
|
@@ -59,6 +66,8 @@ skills.no-catalog skills.unreachable skill.unused
|
|
|
59
66
|
assets.missing assets.overbroad sandbox.dockerfile.missing
|
|
60
67
|
sandbox.build sandbox.smoke sandbox.start / .unchecked
|
|
61
68
|
provider.invalid model.none model.unresolvable
|
|
69
|
+
model.refused model.unreachable model.unusable
|
|
70
|
+
embedding.refused embedding.unreachable embedding.unusable
|
|
62
71
|
credential.* service.credential
|
|
63
72
|
```
|
|
64
73
|
|
|
@@ -77,16 +86,3 @@ model with `reasoningEffort` and tools on the default chat-completions API is a
|
|
|
77
86
|
valid configuration that fails at runtime with _"Function tools with
|
|
78
87
|
reasoning_effort are not supported … in /v1/chat/completions"_. Set
|
|
79
88
|
`api: responses` alongside it.
|
|
80
|
-
|
|
81
|
-
## `zen models`
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
zen models [--project <name|dir>]
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
The narrower question: what each agent would actually talk to. It resolves every
|
|
88
|
-
provider, model and embedding the project declares, says which credential each
|
|
89
|
-
one needs and whether it is present, and calls nothing.
|
|
90
|
-
|
|
91
|
-
Reach for `zen models` when a run says a model has no credential and for
|
|
92
|
-
`zen check` when something structural is wrong.
|
|
@@ -97,6 +97,11 @@ the verdict:
|
|
|
97
97
|
- **live** — authenticated. A rate-limited answer counts as live, because it
|
|
98
98
|
proves the credential.
|
|
99
99
|
- **dead** — the provider rejected it. A verdict.
|
|
100
|
+
- **blocked** — the credential was accepted and the **account** refused: an API
|
|
101
|
+
switched off in the project, an empty balance, a model this key was never
|
|
102
|
+
granted. Do not rotate the key; a new one is refused identically. The check
|
|
103
|
+
carries a `fix` — for a disabled Google API, the exact
|
|
104
|
+
`gcloud services enable <api> --project <id>`.
|
|
100
105
|
- **unknown** — the provider could not be asked. Says nothing about the key;
|
|
101
106
|
usually the network.
|
|
102
107
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Models — `zen models`
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
zen models <providers|ls|search|show|test|pick> [ref] [options]
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Alias: `model`.
|
|
8
|
+
|
|
9
|
+
Answers **what can I use**. `zen check` answers the other question — whether one
|
|
10
|
+
particular project works — and needs a project to do it. This one needs nothing
|
|
11
|
+
but a credential.
|
|
12
|
+
|
|
13
|
+
## Subcommands
|
|
14
|
+
|
|
15
|
+
| Command | What it does |
|
|
16
|
+
| --------------------------- | ------------------------------------------------------ |
|
|
17
|
+
| `zen models` | Providers, credential source, how many models, how old |
|
|
18
|
+
| `zen models <provider>` | Short for `ls <provider>` |
|
|
19
|
+
| `zen models ls [provider]` | Everything it serves |
|
|
20
|
+
| `zen models search <query>` | Narrow it |
|
|
21
|
+
| `zen models show <ref>` | One model, every field the vendor gave |
|
|
22
|
+
| `zen models test <ref> …` | One real minimal call per ref, and a verdict |
|
|
23
|
+
| `zen models pick` | The first ref that answers, printed on stdout |
|
|
24
|
+
|
|
25
|
+
Filters, on `ls` and `search`: `--chat`, `--embeddings`, `--images`, `--audio`,
|
|
26
|
+
`--tools`, `--vision`, `--free`, `--min-context <n>`, `--provider <name>`,
|
|
27
|
+
`--limit <n>`, `--all`, `--refresh`.
|
|
28
|
+
|
|
29
|
+
`pick` requires `--chat` or `--embedding`, and takes `--provider` and `--limit`.
|
|
30
|
+
|
|
31
|
+
## Where the lists come from
|
|
32
|
+
|
|
33
|
+
The providers themselves, cached for a day in `~/.zenera/neo/catalog`. When a
|
|
34
|
+
provider cannot be asked, the last listing is used and reported as stale; only
|
|
35
|
+
if there was never one does a short built-in list stand in. Every row says which
|
|
36
|
+
it was — `--json` carries `source` per model and `origin` per provider.
|
|
37
|
+
|
|
38
|
+
`--refresh` bypasses the cache. It is the only thing that does.
|
|
39
|
+
|
|
40
|
+
`zen models` on its own does **not** go to the network. `ls` and `search` do.
|
|
41
|
+
|
|
42
|
+
## Testing a model
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
zen models test openai:gpt-4o-mini
|
|
46
|
+
zen models test vertex:gemini-embedding-001 --embedding
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The role is taken from the flag, else from what the provider says the model is
|
|
50
|
+
for, else from the id. One minimal call: `ok` for a chat model, one short vector
|
|
51
|
+
for an embedder — the embedding's width is reported, which matters because a
|
|
52
|
+
model serving a different number of dimensions is not interchangeable with the
|
|
53
|
+
one an index was built on.
|
|
54
|
+
|
|
55
|
+
Four verdicts, and they want four different actions:
|
|
56
|
+
|
|
57
|
+
| Verdict | Means | Do |
|
|
58
|
+
| ----------- | -------------------------------------------- | -------------------------- |
|
|
59
|
+
| `answers` | it works | nothing |
|
|
60
|
+
| `refused` | the credential was rejected | `zen key check <provider>` |
|
|
61
|
+
| `blocked` | the credential was fine, the account said no | the `fix` printed under it |
|
|
62
|
+
| `no answer` | it could not be reached | try again |
|
|
63
|
+
|
|
64
|
+
Exit `0` when every ref answered, `4` when any did not, `2` for a ref that does
|
|
65
|
+
not parse.
|
|
66
|
+
|
|
67
|
+
## Recovering from a blocked model
|
|
68
|
+
|
|
69
|
+
This is what the command is for.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
$ zen models test vertex:gemini-embedding-001
|
|
73
|
+
vertex:gemini-embedding-001 blocked Vertex AI API has not been used in project my-proj …
|
|
74
|
+
vertex:gemini-embedding-001: gcloud services enable aiplatform.googleapis.com --project my-proj
|
|
75
|
+
error 1 of 1 did not answer
|
|
76
|
+
find one that does: zen models pick --embedding
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Two ways out. Run the `gcloud` line, or take a different model:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
$ zen models pick --embedding
|
|
83
|
+
openai:text-embedding-3-small
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`pick` tries a short ordered list one at a time and stops at the first that
|
|
87
|
+
works. Sequential on purpose — the goal is one working ref, not a survey. The
|
|
88
|
+
ref goes to **stdout alone and unstyled**, so it substitutes directly:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
zen rag schema index --embedding "$(zen models pick --embedding)" ./specs/*.yaml
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`zen models pick --embedding --json` gives `{ref, provider, model, role,
|
|
95
|
+
dimensions, ms, tried}` — `tried` lists every candidate and why it was passed
|
|
96
|
+
over, so a caller can see _why_ a provider was skipped rather than only that it
|
|
97
|
+
was.
|
|
98
|
+
|
|
99
|
+
When nothing answers, exit `4` and the table of everything tried.
|
|
100
|
+
|
|
101
|
+
## What it will not do
|
|
102
|
+
|
|
103
|
+
There is no `test --all`. A sweep across every model on the machine is a bill,
|
|
104
|
+
not a diagnostic — name the refs you care about, or use `pick`.
|
|
105
|
+
|
|
106
|
+
There is no ranking. The candidate order in `pick` is cheapest-and-fastest
|
|
107
|
+
first, which is about how quickly an answer arrives, not about which model is
|
|
108
|
+
better.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# API search — `zen rag`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
|
-
zen rag schema <index|search|show|stats> [spec...]
|
|
4
|
+
zen rag schema <index|search|list|grep|show|stats> [spec...]
|
|
5
5
|
```
|
|
6
6
|
|
|
7
7
|
Provided by `@zenera/rag` — `npm i -g @zenera/rag` if `zen rag` says it is not
|
|
@@ -58,6 +58,11 @@ zen rag schema search [terms…] [filters…]
|
|
|
58
58
|
Every argument is validated before an embedder is constructed, so a typo is a
|
|
59
59
|
usage error rather than a credential error.
|
|
60
60
|
|
|
61
|
+
**Bare words are the query, not a subcommand.** `zen rag schema search list
|
|
62
|
+
methods` searches for the phrase _"list methods"_ and returns ranked guesses;
|
|
63
|
+
`zen rag schema list methods` is the listing. `search` is also the only read
|
|
64
|
+
command that embeds, so it is the only slow one.
|
|
65
|
+
|
|
61
66
|
### Terms — repeatable, and the field is the point
|
|
62
67
|
|
|
63
68
|
| Term | Searches |
|
|
@@ -126,15 +131,67 @@ reset forget it, exclusions included
|
|
|
126
131
|
quit
|
|
127
132
|
```
|
|
128
133
|
|
|
134
|
+
## `list` and `grep`
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
zen rag schema list <methods|types|properties> [-d <dir>] [--name <p>] [--path <p>]
|
|
138
|
+
zen rag schema grep <pattern> [-d <dir>] [--regex] [--kind <k>] [--ids-only]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Exact, and therefore complete. `search` ranks, so it can only hand back the top
|
|
142
|
+
of a list — it cannot tell you that something is _not_ there. These can: they
|
|
143
|
+
read `graph.json` directly, with no embedder, no credential and no network.
|
|
144
|
+
|
|
145
|
+
| Flag | For | Meaning |
|
|
146
|
+
| ------------------- | ------ | -------------------------------------------- |
|
|
147
|
+
| `--name <p>` | `list` | Match the name. Repeatable |
|
|
148
|
+
| `--path <p>` | `list` | Match the route. Repeatable |
|
|
149
|
+
| `--source <name>` | both | Only nodes from one document |
|
|
150
|
+
| `--method-type <t>` | `list` | `read_only`, `read_write` or `any` |
|
|
151
|
+
| `--direction <d>` | `list` | `input`, `output` or `any` |
|
|
152
|
+
| `--regex` | `grep` | Read the pattern as a regular expression |
|
|
153
|
+
| `--case-sensitive` | `grep` | Stop ignoring case |
|
|
154
|
+
| `--kind <k>` | `grep` | `method`, `type` or `property`. Repeatable |
|
|
155
|
+
| `--ids-only` | `grep` | Just the ids, one per line, for piping |
|
|
156
|
+
| `--limit <n>` | both | Rows to print. `found` still counts them all |
|
|
157
|
+
|
|
158
|
+
A pattern with `*` or `?` is a glob matched against the whole string; a plain
|
|
159
|
+
word is a substring. So `--name password` finds `ResetPasswordPayload`, and
|
|
160
|
+
`--name "Password*"` finds nothing, because nothing starts with it.
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
zen rag schema list methods --path "*/users*"
|
|
164
|
+
zen rag schema list types --name "*Password*"
|
|
165
|
+
zen rag schema grep password
|
|
166
|
+
zen rag schema grep "pass(word|phrase)" --regex
|
|
167
|
+
zen rag schema grep token --ids-only | xargs zen rag schema show --format ts
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
No match exits 0 with nothing on stdout — that is the answer, and unlike an
|
|
171
|
+
empty search it is a reliable one. Under `--limit`, `found` is still the true
|
|
172
|
+
total, so a shortened answer never misreports how much there is.
|
|
173
|
+
|
|
129
174
|
## `show`
|
|
130
175
|
|
|
131
176
|
```
|
|
132
|
-
zen rag schema show
|
|
177
|
+
zen rag schema show [id...] [-d <dir>] [--format <f>]
|
|
178
|
+
[--method <name>] [--type <name>] [--source <name>] [--exact]
|
|
133
179
|
```
|
|
134
180
|
|
|
135
181
|
Prints named nodes with no search in between. Needs no embedder and no
|
|
136
182
|
credential — it is a read of the graph.
|
|
137
183
|
|
|
184
|
+
Ids are one way in; `--method` and `--type` name things directly, which is
|
|
185
|
+
usually what you have. A bare name means exactly that name; add `*` to select
|
|
186
|
+
more than one. `--source <name>` takes a whole document. `--exact` prints only
|
|
187
|
+
what was named instead of the neighbourhood around it — with `--format openapi`
|
|
188
|
+
that is a valid, self-contained slice of the specification.
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
zen rag schema show --method GetCurrentUserInfo --format openapi --exact
|
|
192
|
+
zen rag schema show --type "*Invoice*" --format ts
|
|
193
|
+
```
|
|
194
|
+
|
|
138
195
|
## `stats`
|
|
139
196
|
|
|
140
197
|
```
|
|
@@ -153,7 +210,12 @@ documents it came from. Also needs no embedder.
|
|
|
153
210
|
| `search_api` | The search above, with the same fields |
|
|
154
211
|
| `describe_types` | Named schemas as TypeScript, closed over what they refer to |
|
|
155
212
|
| `find_types_with_property` | Every schema with a field of this name — exact lookup, no searching |
|
|
156
|
-
| `
|
|
213
|
+
| `list_api` | Methods, types or fields by name — complete, and counted in full |
|
|
214
|
+
| `grep_api` | Every literal occurrence of a string — the way to prove absence |
|
|
215
|
+
|
|
216
|
+
Only `search_api` ranks. Reach for the others whenever the question is whether
|
|
217
|
+
something exists, because a search that returns nothing and a thing that is not
|
|
218
|
+
there look exactly the same.
|
|
157
219
|
|
|
158
220
|
They share the group `schema`, so an agent takes them with `schema:*` in its
|
|
159
221
|
`tools:`.
|
|
@@ -18,4 +18,6 @@ COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
|
|
|
18
18
|
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
|
|
19
19
|
&& ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
# Pinned to the `zen` that wrote this file, so the tools in the container are
|
|
22
|
+
# the ones the session outside it was built by. Bump both together.
|
|
23
|
+
RUN npm install -g @zenera/cli@{{version}} @zenera/rag@{{version}}
|