@zenera/cli 1.1.15 → 1.1.17
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 +201 -129
- package/dist/banner.d.ts +5 -1
- package/dist/banner.js +2 -2
- package/dist/catalog.js +19 -20
- package/dist/command.d.ts +5 -0
- package/dist/commands/check.js +5 -1
- package/dist/commands/init.js +41 -6
- package/dist/commands/run.js +4 -0
- package/dist/engine.js +6 -0
- package/dist/env.d.ts +20 -0
- package/dist/env.js +65 -0
- package/dist/keys.d.ts +2 -0
- package/dist/keys.js +2 -0
- package/dist/main.js +10 -6
- package/dist/sandbox.d.ts +9 -0
- package/dist/sandbox.js +23 -3
- package/dist/scaffold.d.ts +6 -0
- package/dist/scaffold.js +56 -15
- package/dist/validate.js +57 -15
- package/package.json +2 -2
- package/templates/editor/.github/copilot-instructions.md +501 -301
- package/templates/editor/.github/prompts/new-agent.prompt.md +6 -6
- package/templates/editor/.github/prompts/new-skill.prompt.md +7 -7
- package/templates/editor/.github/prompts/review-project.prompt.md +54 -15
- package/templates/editor/.github/prompts/sync-with-spec.prompt.md +229 -42
- package/templates/editor/.github/prompts/update-spec-from-feedback.prompt.md +142 -0
- package/templates/editor/.github/skills/zen-cli/SKILL.md +62 -6
- package/templates/editor/.github/skills/zen-cli/references/check.md +9 -6
- package/templates/editor/.github/skills/zen-cli/references/faker.md +14 -14
- package/templates/editor/.github/skills/zen-cli/references/frame.md +11 -9
- package/templates/editor/.github/skills/zen-cli/references/inspect.md +3 -3
- package/templates/editor/.github/skills/zen-cli/references/keys.md +9 -9
- package/templates/editor/.github/skills/zen-cli/references/memory.md +11 -11
- package/templates/editor/.github/skills/zen-cli/references/models.md +8 -8
- package/templates/editor/.github/skills/zen-cli/references/projects.md +23 -6
- package/templates/editor/.github/skills/zen-cli/references/rag.md +191 -56
- package/templates/editor/.github/skills/zen-cli/references/run.md +3 -3
- package/templates/editor/.github/skills/zen-cli/references/sandbox.md +14 -8
- package/templates/editor/.github/skills/zen-memory/SKILL.md +144 -72
- package/templates/editor/.github/skills/zen-memory/scripts/check-instructions.sh +115 -0
- package/templates/editor/.github/skills/zen-rag-docs/SKILL.md +71 -48
- package/templates/editor/.github/skills/zen-rag-schema/SKILL.md +67 -67
- package/templates/editor/.github/skills/zen-review/SKILL.md +123 -0
- package/templates/editor/.github/skills/zen-review/scripts/check-paths.sh +119 -0
- package/templates/editor/.github/skills/zen-review/scripts/review.sh +104 -0
- package/templates/editor/.github/skills/zen-spec-sync/SKILL.md +197 -0
- package/templates/editor/.github/skills/zen-spec-sync/scripts/snapshot.sh +200 -0
- package/templates/editor/.vscode/settings.json +46 -3
- package/templates/parts/memory-terms.yaml.tmpl +16 -0
- package/templates/parts/memory.yaml.tmpl +12 -0
- package/templates/project/SPECIFICATION.md.tmpl +7 -0
- package/templates/project/{INSTRUCTIONS.md → agents/instructions.md} +1 -1
- package/templates/project/agents/memory-instructions.md +278 -0
- package/templates/project/agents.yaml.tmpl +9 -0
- package/templates/project/assets/README.md +1 -1
- package/templates/project/env +22 -0
- package/templates/project/sandbox/Dockerfile.tmpl +3 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Projects
|
|
1
|
+
# Projects - `init`, `list`, `open`, `version`
|
|
2
2
|
|
|
3
3
|
## `zen init`
|
|
4
4
|
|
|
@@ -19,28 +19,45 @@ What it writes:
|
|
|
19
19
|
|
|
20
20
|
```
|
|
21
21
|
zenera.json { version, name }
|
|
22
|
-
INSTRUCTIONS.md house rules
|
|
23
22
|
agents.yaml the configuration
|
|
23
|
+
agents/instructions.md house rules, prepended to every agent
|
|
24
|
+
agents/memory-instructions.md more of them, about the memory store
|
|
24
25
|
agents/prompts/default.md the default agent's prompt
|
|
25
26
|
agents/skills/ empty, for skills
|
|
26
27
|
assets/README.md
|
|
27
28
|
sandbox/Dockerfile the image the sandbox builds
|
|
28
29
|
sessions/ empty
|
|
30
|
+
.env this project's environment, git-ignored
|
|
29
31
|
.gitignore
|
|
30
32
|
.vscode/settings.json editor files
|
|
31
33
|
.github/ copilot instructions, prompts, this skill
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
More house rules can be added by hand: any `agents/<topic>-instructions.md` is
|
|
37
|
+
read too, in filename order, and prepended to every agent. A capability that
|
|
38
|
+
needs standing rules - memory, say - gets its own file rather than another
|
|
39
|
+
section of `agents/instructions.md`. Memory's are not written from scratch:
|
|
40
|
+
`agents/memory-instructions.md` is the same file as
|
|
41
|
+
`.github/skills/zen-memory/references/memory-instructions.md`, which init puts
|
|
42
|
+
in the project as well, so a copy that was lost or went stale is restored rather
|
|
43
|
+
than rewritten - `.github/skills/zen-memory/scripts/check-instructions.sh` says
|
|
44
|
+
which of the two it is, and `… fix` does the copy.
|
|
45
|
+
|
|
46
|
+
The project's own files are never overwritten - `--force` is what allows
|
|
35
47
|
writing into an occupied directory, and the files already there stay. The
|
|
36
48
|
editor files are the exception: `.vscode/settings.json` and the `.github/` tree
|
|
37
49
|
are ours and are replaced on every `init` and every `zen open`, so edits to them
|
|
38
50
|
do not survive.
|
|
39
51
|
|
|
40
52
|
The default agent gets the file tools and a sandboxed shell, plus `exa:*` when
|
|
41
|
-
the keyring holds an Exa key.
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
the keyring holds an Exa key. It also gets memory: the store is scaffolded in
|
|
54
|
+
`memory/`, the agent is bound to it with `memory: true`, and it is vectorised by
|
|
55
|
+
the chosen provider's embedding model. A provider that publishes none -
|
|
56
|
+
Anthropic - gets the store without an `embeddings:` entry, and recall ranks by
|
|
57
|
+
term overlap until one is added; an entry naming a provider with no embeddings
|
|
58
|
+
API is a project that fails to load, not one that degrades.
|
|
59
|
+
|
|
60
|
+
**Choosing the model.** Without `--model`, the keyring is asked - not counted.
|
|
44
61
|
Stored credentials are probed, because holding a key is not the same as holding
|
|
45
62
|
a working one, and the model is picked from a provider that answers. A key from
|
|
46
63
|
the environment is taken at its word. Each provider has its own scaffolded
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# API search
|
|
1
|
+
# API search - `zen rag`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
4
|
zen rag schema <index|search|list|grep|trace|show|stats> [spec...]
|
|
5
5
|
```
|
|
6
6
|
|
|
7
|
-
Provided by `@zenera/rag`
|
|
7
|
+
Provided by `@zenera/rag` - `npm i -g @zenera/rag` if `zen rag` says it is not
|
|
8
8
|
installed.
|
|
9
9
|
|
|
10
|
-
Reads an OpenAPI/Swagger document as a **graph**
|
|
11
|
-
fields inside them, joined by the `$ref`s between them
|
|
10
|
+
Reads an OpenAPI/Swagger document as a **graph** - operations, schemas and the
|
|
11
|
+
fields inside them, joined by the `$ref`s between them - and makes it
|
|
12
12
|
searchable. The answer to a search is not a list of matches but the connected
|
|
13
13
|
piece of the API that matched: the operations, the schemas they carry and the
|
|
14
14
|
fields inside them, printed as text, a diagram, or TypeScript that compiles.
|
|
@@ -24,18 +24,18 @@ zen rag schema index <spec...> [--embedding <ref>] [-o <dir>] [--batch <n>]
|
|
|
24
24
|
|
|
25
25
|
| Flag | Default | Meaning |
|
|
26
26
|
| ------------------- | ------------- | ------------------------------------------------------------ |
|
|
27
|
-
| `--embedding <ref>` |
|
|
27
|
+
| `--embedding <ref>` | - | Which embedder makes the vectors. Omit it to see the choices |
|
|
28
28
|
| `-o`, `--out <dir>` | `./schema-db` | Where the index goes; `$ZEN_SCHEMA_DB` if set |
|
|
29
29
|
| `--batch <n>` | `96` | Texts per embedding request, and how often progress prints |
|
|
30
|
-
| `--no-sources` |
|
|
31
|
-
| `--quiet` |
|
|
30
|
+
| `--no-sources` | - | Keep no copy of the documents in the index |
|
|
31
|
+
| `--quiet` | - | No narration |
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
zen rag schema index openapi.yaml --embedding openai:text-embedding-3-small
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Unlike the faker, `$ref`s are **bundled, not dereferenced**: component names are
|
|
38
|
-
the node ids and the cycles between them are the edges. `discriminator` is kept
|
|
38
|
+
the node ids and the cycles between them are the edges. `discriminator` is kept -
|
|
39
39
|
it is what turns a `oneOf` into a tagged union a compiler can narrow.
|
|
40
40
|
|
|
41
41
|
What lands in `<out>`:
|
|
@@ -56,14 +56,14 @@ search with a different model is refused rather than quietly returning nonsense.
|
|
|
56
56
|
Every reading command takes `-d`, `--dir`. Without one:
|
|
57
57
|
|
|
58
58
|
1. `$ZEN_SCHEMA_DB`, if it is set.
|
|
59
|
-
2. Otherwise the **nearest index** to the working directory
|
|
59
|
+
2. Otherwise the **nearest index** to the working directory - here, then a
|
|
60
60
|
short way down, then up a level and again, stopping at your home directory.
|
|
61
61
|
The one used is named on stderr.
|
|
62
62
|
3. Otherwise `./schema-db`, so the error names the directory you expected.
|
|
63
63
|
|
|
64
64
|
What is looked for is a `manifest.json`, not a directory called `schema-db`, so
|
|
65
65
|
an index called anything else is found the same way. Two the same distance away
|
|
66
|
-
is refused rather than guessed at
|
|
66
|
+
is refused rather than guessed at - name one with `-d`, or set `ZEN_SCHEMA_DB`
|
|
67
67
|
once and stop typing it.
|
|
68
68
|
|
|
69
69
|
## `search`
|
|
@@ -80,7 +80,7 @@ methods` searches for the phrase _"list methods"_ and returns ranked guesses;
|
|
|
80
80
|
`zen rag schema list methods` is the listing. `search` is also the only read
|
|
81
81
|
command that embeds, so it is the only slow one.
|
|
82
82
|
|
|
83
|
-
### Terms
|
|
83
|
+
### Terms - repeatable, and the field is the point
|
|
84
84
|
|
|
85
85
|
| Term | Searches |
|
|
86
86
|
| ----------------------- | ---------------------------------------- |
|
|
@@ -103,22 +103,22 @@ search good. A request field belongs in `--input-property`, a response field in
|
|
|
103
103
|
|
|
104
104
|
| Flag | Default | Meaning |
|
|
105
105
|
| --------------------------- | ----------- | ------------------------------------------------------- |
|
|
106
|
-
| `-d`, `--dir <dir>` | found | Which index
|
|
106
|
+
| `-d`, `--dir <dir>` | found | Which index - see "Which index gets read" |
|
|
107
107
|
| `--embedding <ref>` | the index's | Must be the one the index was built with |
|
|
108
108
|
| `--direction <d>` | `any` | `input`, `output` or `any` |
|
|
109
109
|
| `--method-type <t>` | `any` | `read_only`, `read_write` or `any` |
|
|
110
|
-
| `--exclude-id <id>` |
|
|
111
|
-
| `--exclude-method <name>` |
|
|
112
|
-
| `--exclude-type <name>` |
|
|
113
|
-
| `--exclude-property <name>` |
|
|
110
|
+
| `--exclude-id <id>` | - | Drop a node. Repeatable |
|
|
111
|
+
| `--exclude-method <name>` | - | Drop an operation by name. Repeatable |
|
|
112
|
+
| `--exclude-type <name>` | - | Drop a schema by name. Repeatable |
|
|
113
|
+
| `--exclude-property <name>` | - | Drop a field by name. Repeatable |
|
|
114
114
|
| `--limit <n>` | `5` | Seeds kept per term |
|
|
115
115
|
| `--max-hops <n>` | `3` | How far apart two hits may be |
|
|
116
116
|
| `--max-nodes <n>` | `200` | Nodes per result |
|
|
117
117
|
| `--format <f>` | `text` | `text`, `mermaid`, `mermaid-flowchart`, `ts`, `openapi` |
|
|
118
|
-
| `--show-source` |
|
|
119
|
-
| `--no-docs` |
|
|
120
|
-
| `--interactive` |
|
|
121
|
-
| `--quiet` |
|
|
118
|
+
| `--show-source` | - | Tag each operation and schema with its document |
|
|
119
|
+
| `--no-docs` | - | Leave the descriptions out |
|
|
120
|
+
| `--interactive` | - | Prompt, search, refine. Needs a terminal |
|
|
121
|
+
| `--quiet` | - | No narration |
|
|
122
122
|
|
|
123
123
|
```
|
|
124
124
|
zen rag schema search --method "reset a user password" --format ts
|
|
@@ -130,7 +130,7 @@ The exclusions are what turn one search into a session: pass back the ids of
|
|
|
130
130
|
what you have already been shown to be shown something else instead of the same
|
|
131
131
|
thing again.
|
|
132
132
|
|
|
133
|
-
`--format ts` emits TypeScript closed over its own `$ref`s
|
|
133
|
+
`--format ts` emits TypeScript closed over its own `$ref`s - everything named is
|
|
134
134
|
also declared, so the output compiles on its own.
|
|
135
135
|
|
|
136
136
|
### `--interactive`
|
|
@@ -157,7 +157,7 @@ zen rag schema grep <pattern> [-d <dir>] [--name <p>] [--path <p>] [--kind <k>]
|
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
Exact, and therefore complete. `search` ranks, so it can only hand back the top
|
|
160
|
-
of a list
|
|
160
|
+
of a list - it cannot tell you that something is _not_ there. These can: they
|
|
161
161
|
read `graph.json` directly, with no embedder, no credential and no network.
|
|
162
162
|
|
|
163
163
|
| Flag | For | Meaning |
|
|
@@ -176,13 +176,13 @@ read `graph.json` directly, with no embedder, no credential and no network.
|
|
|
176
176
|
| `--quiet` | both | No narration |
|
|
177
177
|
|
|
178
178
|
Under `--json`: `{found, truncated, rows}` from `list`, `{found, truncated,
|
|
179
|
-
matches}` from `grep`. `grep` takes **one** pattern
|
|
180
|
-
spaces
|
|
179
|
+
matches}` from `grep`. `grep` takes **one** pattern - quote it if it has
|
|
180
|
+
spaces - and `list` **one** subject.
|
|
181
181
|
|
|
182
182
|
A pattern with `*` or `?` is a glob matched against the whole string; a plain
|
|
183
183
|
word is a substring. So `--name password` finds `ResetPasswordPayload`, and
|
|
184
184
|
`--name "Password*"` finds nothing, because nothing starts with it. `--regex`
|
|
185
|
-
makes it a regular expression instead
|
|
185
|
+
makes it a regular expression instead - the only way to say "one of these". On
|
|
186
186
|
`list` it applies to every pattern; on `grep` it applies to the pattern, while
|
|
187
187
|
`--name` and `--path` stay globs-or-substrings:
|
|
188
188
|
|
|
@@ -203,7 +203,7 @@ zen rag schema grep status --path "/invoices/*" --kind property
|
|
|
203
203
|
zen rag schema grep token --ids-only | xargs zen rag schema show --format ts
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
-
No match exits 0 with nothing on stdout
|
|
206
|
+
No match exits 0 with nothing on stdout - that is the answer, and unlike an
|
|
207
207
|
empty search it is a reliable one. Under `--limit`, `found` is still the true
|
|
208
208
|
total, so a shortened answer never misreports how much there is.
|
|
209
209
|
|
|
@@ -219,7 +219,7 @@ zen rag schema trace <pattern|id...> [-d <dir>] [--kind <k>] [--direction <d>]
|
|
|
219
219
|
The question `list` and `grep` leave you holding: you have found the field, so
|
|
220
220
|
**which call can reach it?** `trace` walks up the `$ref`s from every node of
|
|
221
221
|
that name to the operations that accept or return it, and prints the chain in
|
|
222
|
-
between. Also a plain graph read
|
|
222
|
+
between. Also a plain graph read - no embedder, no credential.
|
|
223
223
|
|
|
224
224
|
```
|
|
225
225
|
zen rag schema trace city
|
|
@@ -233,7 +233,7 @@ Property:Address.city
|
|
|
233
233
|
By hand that is three lookups and a guess: find the field, find what holds
|
|
234
234
|
`Address`, find what accepts _that_, and hope you followed every branch.
|
|
235
235
|
|
|
236
|
-
`search` does some of this already
|
|
236
|
+
`search` does some of this already - it stitches its seeds into one connected
|
|
237
237
|
piece and prints what each operation accepts and returns. But it links only
|
|
238
238
|
what **ranked**, only within `--max-hops`, and it never names the chain; and
|
|
239
239
|
`getUser` and `city` share no word, so the field has to rank on its own and the
|
|
@@ -245,14 +245,14 @@ there and are certain.
|
|
|
245
245
|
| `--kind <k>` | types + properties | `method`, `type` or `property`. Repeatable |
|
|
246
246
|
| `--direction <d>` | `any` | Keep only the calls that accept it, or return it |
|
|
247
247
|
| `--max-hops <n>` | `8` | How far up to walk |
|
|
248
|
-
| `--limit <n>` |
|
|
249
|
-
| `--routes <n>` |
|
|
250
|
-
| `--ids-only` |
|
|
251
|
-
| `--regex` |
|
|
252
|
-
| `--source <name>` |
|
|
253
|
-
| `--show-source` |
|
|
254
|
-
|
|
255
|
-
A bare word is matched the way `list --name` matches it
|
|
248
|
+
| `--limit <n>` | - | Trace at most n matching nodes |
|
|
249
|
+
| `--routes <n>` | - | Operations printed per node; `found` counts them all |
|
|
250
|
+
| `--ids-only` | - | Bare operation ids, one per line, for piping |
|
|
251
|
+
| `--regex` | - | Read the pattern as a regex; `--case-sensitive` too |
|
|
252
|
+
| `--source <name>` | - | Only nodes from one document |
|
|
253
|
+
| `--show-source` | - | Print which document each operation came from |
|
|
254
|
+
|
|
255
|
+
A bare word is matched the way `list --name` matches it - substring, or a glob
|
|
256
256
|
when it has `*` or `?`. A node id (`Type:User`) is taken as that node and not
|
|
257
257
|
as a pattern. Operations are left out of a name match on purpose: they are
|
|
258
258
|
where a trace ends.
|
|
@@ -263,7 +263,7 @@ zen rag schema trace "*Settings" --kind type
|
|
|
263
263
|
zen rag schema trace mfa_secret --ids-only | xargs zen rag schema show --format openapi
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
-
A node nothing carries prints `no operation reaches it`
|
|
266
|
+
A node nothing carries prints `no operation reaches it` - a real answer, and
|
|
267
267
|
one worth having: it means the schema is unreachable in this document.
|
|
268
268
|
|
|
269
269
|
## `show`
|
|
@@ -275,13 +275,13 @@ zen rag schema show [id...] [-d <dir>] [--format <f>] [--exact]
|
|
|
275
275
|
```
|
|
276
276
|
|
|
277
277
|
Prints named nodes with no search in between. Needs no embedder and no
|
|
278
|
-
credential
|
|
278
|
+
credential - it is a read of the graph.
|
|
279
279
|
|
|
280
280
|
Ids are one way in; `--method` and `--type` name things directly, which is
|
|
281
281
|
usually what you have. A bare name means exactly that name; add `*` to select
|
|
282
282
|
more than one. `--source <name>` takes a whole document, and `--show-source`
|
|
283
283
|
tags each node with the document it came from. `--exact` prints only what was
|
|
284
|
-
named instead of the neighbourhood around it
|
|
284
|
+
named instead of the neighbourhood around it - with `--format openapi` that is
|
|
285
285
|
a valid, self-contained slice of the specification. Without it the neighbours
|
|
286
286
|
are stitched in, up to `--max-nodes`.
|
|
287
287
|
|
|
@@ -315,9 +315,9 @@ documents it came from. Also needs no embedder.
|
|
|
315
315
|
| -------------------------- | ------------------------------------------------------------------- |
|
|
316
316
|
| `search_api` | The search above, with the same fields |
|
|
317
317
|
| `describe_types` | Named schemas as TypeScript, closed over what they refer to |
|
|
318
|
-
| `find_types_with_property` | Every schema with a field of this name
|
|
319
|
-
| `list_api` | Methods, types or fields by name
|
|
320
|
-
| `grep_api` | Every literal occurrence of a string
|
|
318
|
+
| `find_types_with_property` | Every schema with a field of this name - exact lookup, no searching |
|
|
319
|
+
| `list_api` | Methods, types or fields by name - complete, and counted in full |
|
|
320
|
+
| `grep_api` | Every literal occurrence of a string - the way to prove absence |
|
|
321
321
|
| `trace_api` | Up from a field or schema to the operations that carry it |
|
|
322
322
|
|
|
323
323
|
Only `search_api` ranks. Reach for the others whenever the question is whether
|
|
@@ -328,7 +328,7 @@ found and the endpoint to call is what is actually wanted.
|
|
|
328
328
|
They share the group `schema`, so an agent takes them with `schema:*` in its
|
|
329
329
|
`tools:`.
|
|
330
330
|
|
|
331
|
-
# Document search
|
|
331
|
+
# Document search - `zen rag docs`
|
|
332
332
|
|
|
333
333
|
```
|
|
334
334
|
zen rag docs <index|search|list|grep|show|stats> [args...]
|
|
@@ -347,17 +347,17 @@ zen rag docs index <path...> [--embedding <ref>] [-o <dir>] [--chunk-tokens <n>]
|
|
|
347
347
|
|
|
348
348
|
| Flag | Default | Meaning |
|
|
349
349
|
| -------------------- | ----------- | ------------------------------------------------------------ |
|
|
350
|
-
| `--embedding <ref>` |
|
|
350
|
+
| `--embedding <ref>` | - | Which embedder makes the vectors. Omit it to see the choices |
|
|
351
351
|
| `-o`, `--out <dir>` | `./docs-db` | Where the index goes; `$ZEN_DOCS_DB` if set |
|
|
352
352
|
| `--batch <n>` | `96` | Texts per embedding request |
|
|
353
353
|
| `--chunk-tokens <n>` | `384` | Target chunk size |
|
|
354
|
-
| `--quiet` |
|
|
354
|
+
| `--quiet` | - | No narration |
|
|
355
355
|
|
|
356
356
|
Paths may be files, directories or globs. `.md`, `.markdown`, `.txt` and
|
|
357
357
|
`.text` are read; hidden directories and `node_modules` are not.
|
|
358
358
|
|
|
359
359
|
Every document is **copied into the index**, and every quoted line is read back
|
|
360
|
-
out of that copy
|
|
360
|
+
out of that copy - so the index is one portable thing and what it quotes is the
|
|
361
361
|
document rather than a reconstruction of it. Each document is named by its path
|
|
362
362
|
relative to the common root of everything indexed, which is what keeps
|
|
363
363
|
`acme_4.1.0/api/routing.md` and `acme_4.2.0/api/routing.md` apart.
|
|
@@ -378,17 +378,19 @@ zen rag docs search [text...] [-f <pattern>] [-s <section>] [--kind <k>]
|
|
|
378
378
|
|
|
379
379
|
| Flag | Default | Meaning |
|
|
380
380
|
| ------------------------ | -------- | ---------------------------------------------------- |
|
|
381
|
-
| `-f`, `--file <pattern>` |
|
|
382
|
-
| `--exclude-file <p>` |
|
|
383
|
-
| `-s`, `--section <name>` |
|
|
384
|
-
| `--kind <k>` |
|
|
381
|
+
| `-f`, `--file <pattern>` | - | Only documents whose name matches. Repeatable |
|
|
382
|
+
| `--exclude-file <p>` | - | Drop documents whose name matches |
|
|
383
|
+
| `-s`, `--section <name>` | - | Only under this heading, and what nests in it |
|
|
384
|
+
| `--kind <k>` | - | `paragraph`, `list`, `table`, `table_row`, `code`, … |
|
|
385
385
|
| `--mode <m>` | `hybrid` | `hybrid`, `vector` or `text` for exact wording |
|
|
386
|
+
| `--text-query <text>` | - | Wording for the full-text leg, instead of `[text]` |
|
|
387
|
+
| `--vector-query <text>` | - | Wording for the vector leg, instead of `[text]` |
|
|
386
388
|
| `--limit <n>` | `8` | Passages kept |
|
|
387
389
|
| `-B`, `-A <n>` | `0` | Extra lines quoted before and after each passage |
|
|
388
390
|
| `--max-lines <n>` | `400` | A ceiling on the whole answer |
|
|
389
|
-
| `--exclude-id <id>` |
|
|
390
|
-
| `--hits` |
|
|
391
|
-
| `--interactive` |
|
|
391
|
+
| `--exclude-id <id>` | - | Drop a passage already seen. Repeatable |
|
|
392
|
+
| `--hits` | - | One line per passage instead of the text |
|
|
393
|
+
| `--interactive` | - | Prompt, search, narrow, search again |
|
|
392
394
|
|
|
393
395
|
**Narrowing is the interface.** Nobody finds the right paragraph on the first
|
|
394
396
|
ask; the second call is the same question inside one part of the tree.
|
|
@@ -403,7 +405,114 @@ zen rag docs search --mode text "X-RateLimit-Remaining"
|
|
|
403
405
|
A `--file` pattern with `*` or `?` is a glob over the whole document name and
|
|
404
406
|
a substring otherwise.
|
|
405
407
|
|
|
406
|
-
|
|
408
|
+
### Limiting the search scope
|
|
409
|
+
|
|
410
|
+
`--file` selects the documents that are allowed to contribute passages. Repeat
|
|
411
|
+
it to include multiple document families; use `--exclude-file` to subtract a
|
|
412
|
+
family. Both are applied before ranking, so a returned passage cannot come from
|
|
413
|
+
a document outside the selected set. Start with `list files` when the corpus
|
|
414
|
+
names are unknown:
|
|
415
|
+
|
|
416
|
+
```sh
|
|
417
|
+
zen rag docs list files -d <index-dir>
|
|
418
|
+
zen rag docs search -d <index-dir> --file "manual-*/**" "<question>"
|
|
419
|
+
zen rag docs search -d <index-dir> --file "guide-*/**" --file "reference-*/**" \
|
|
420
|
+
--exclude-file "*-archive/**" "<question>"
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
`--section` narrows the selected documents again, retaining a named heading and
|
|
424
|
+
all headings below it. It accepts a heading title, structure id, or structure
|
|
425
|
+
path printed by `list sections`. Combine it with `--file` when the same heading
|
|
426
|
+
exists in more than one document. `--kind` scopes by content shape: use `table`
|
|
427
|
+
or `table_row` for limits and matrices, and `code` for commands or examples.
|
|
428
|
+
|
|
429
|
+
```sh
|
|
430
|
+
zen rag docs list sections -d <index-dir> --file "manual-*/**"
|
|
431
|
+
zen rag docs search -d <index-dir> --file "manual-*/**" --section "Operations" \
|
|
432
|
+
--kind table_row "<question about a limit>"
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Search strategy
|
|
436
|
+
|
|
437
|
+
### How retrieval modes work
|
|
438
|
+
|
|
439
|
+
Search has two independent retrieval legs, followed by reciprocal-rank fusion
|
|
440
|
+
and a diversity pass. It does **not** run full-text search and then use a vector
|
|
441
|
+
model to rerank those same results.
|
|
442
|
+
|
|
443
|
+
| Mode | What runs | Best for | Caution |
|
|
444
|
+
| -------- | ---------------------------------------- | ------------------------------------------------------------- | ----------------------------------------------------- |
|
|
445
|
+
| `hybrid` | Full-text and vector legs, fused by rank | Default: concepts, explanations, broad questions | A broad corpus can still need `--file` or `--section` |
|
|
446
|
+
| `text` | Full-text only | Exact errors, headers, commands, identifiers, and phrases | Literal wording only; misses paraphrases |
|
|
447
|
+
| `vector` | Vector similarity only | A concept whose wording is unknown or differs from the corpus | Can retrieve topical but imprecise passages |
|
|
448
|
+
|
|
449
|
+
The full-text leg rewards words present in the chunk. The vector leg embeds the
|
|
450
|
+
question and retrieves similar meaning, even with different vocabulary. Hybrid
|
|
451
|
+
adds a rank-based contribution from each leg, so a passage supported by both
|
|
452
|
+
normally rises while a strong result from either leg can still appear. The final
|
|
453
|
+
diversity pass prevents near-identical neighbouring chunks from consuming the
|
|
454
|
+
whole answer.
|
|
455
|
+
|
|
456
|
+
**Use hybrid first.** Ask the user-facing question as a complete sentence. It
|
|
457
|
+
combines semantic similarity with the words in the corpus and is the strongest
|
|
458
|
+
default for concepts, explanations, and broad operational questions:
|
|
459
|
+
|
|
460
|
+
```sh
|
|
461
|
+
zen rag docs search -d <index-dir> "How is a failed request retried?"
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Treat the answer as candidates, not confirmation. Search ranks a fixed number
|
|
465
|
+
of passages, so it cannot prove an exact phrase is absent and may return a
|
|
466
|
+
nearby version or an incident that happens to share terms. Read the returned
|
|
467
|
+
line-numbered passage; then use `show` for its surrounding section or `grep`
|
|
468
|
+
for an exact existence check.
|
|
469
|
+
|
|
470
|
+
**Narrow before rewriting the question.** For a corpus with releases, products,
|
|
471
|
+
or repeated manuals, a broad term can retrieve a relevant-looking answer from
|
|
472
|
+
the wrong part of the tree. Keep the question and progressively constrain it:
|
|
473
|
+
|
|
474
|
+
```sh
|
|
475
|
+
zen rag docs list files -d <index-dir>
|
|
476
|
+
zen rag docs list sections -d <index-dir> --file "guide-*/**"
|
|
477
|
+
zen rag docs search -d <index-dir> --file "guide-*/**" --section "Operations" \
|
|
478
|
+
"How is a failed request retried?"
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Use `--kind table` or `--kind table_row` for a limit, entitlement, or matrix;
|
|
482
|
+
use `--kind code` for a command or configuration sample. Pass returned ids to
|
|
483
|
+
`--exclude-id` when the next answer must be new rather than a repeat.
|
|
484
|
+
|
|
485
|
+
**Use exact lookup for exact claims.** `--mode text` is for a known error,
|
|
486
|
+
header, command, identifier, or phrase. `grep` is stronger when the question is
|
|
487
|
+
whether that exact string appears anywhere, because it counts every match and
|
|
488
|
+
does not depend on vector ranking:
|
|
489
|
+
|
|
490
|
+
```sh
|
|
491
|
+
zen rag docs search -d <index-dir> --mode text "exact identifier"
|
|
492
|
+
zen rag docs grep -d <index-dir> "exact identifier"
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**Split the wording only when it is genuinely two wordings.** The text leg
|
|
496
|
+
wants a distinctive string likely to occur verbatim; the vector leg wants the
|
|
497
|
+
full intent. This is useful for an exact identifier plus an explanatory
|
|
498
|
+
question:
|
|
499
|
+
|
|
500
|
+
```sh
|
|
501
|
+
zen rag docs search -d <index-dir> --text-query "exact identifier" \
|
|
502
|
+
--vector-query "what it means, its constraints, and how to use it"
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Both flags run and fuse the two legs. One on its own runs only that leg.
|
|
506
|
+
`--text-query` and `--vector-query` replace positional `[text]` and settle the
|
|
507
|
+
mode themselves: do not combine them with `[text]` or `--mode`.
|
|
508
|
+
|
|
509
|
+
Split search is an expert control, not a stronger default. A generic text leg
|
|
510
|
+
such as a product name or common noun retrieves every incidental mention and
|
|
511
|
+
can displace the more useful semantic passages. Use it only when the text leg
|
|
512
|
+
is specific enough to add evidence rather than noise; otherwise stay with
|
|
513
|
+
ordinary hybrid search and narrow by file or section.
|
|
514
|
+
|
|
515
|
+
## `list`, `grep`, `show` - no embedder, no credential
|
|
407
516
|
|
|
408
517
|
```
|
|
409
518
|
zen rag docs list <files|sections|tables> [-f <pattern>] [-s <section>]
|
|
@@ -417,6 +526,32 @@ total even when `--limit` cuts the rows, so unlike a search it can answer
|
|
|
417
526
|
whether a string appears at all. `show` prints a document, a named section, or
|
|
418
527
|
a line range, verbatim.
|
|
419
528
|
|
|
529
|
+
### Reading a complete section or table
|
|
530
|
+
|
|
531
|
+
Search finds relevant passages, not necessarily every row of a table. When the
|
|
532
|
+
whole section or table is needed, use the exact readers instead of increasing a
|
|
533
|
+
search limit.
|
|
534
|
+
|
|
535
|
+
Read a heading and everything nested beneath it verbatim:
|
|
536
|
+
|
|
537
|
+
```sh
|
|
538
|
+
zen rag docs show -d <index-dir> "<document-name>" --section "<heading>"
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
For one complete table, list its metadata first. Each row reports the document
|
|
542
|
+
name and the table's inclusive `line` and `end` range. Give that range to
|
|
543
|
+
`show --lines` to print the complete table, including its header, verbatim:
|
|
544
|
+
|
|
545
|
+
```sh
|
|
546
|
+
zen rag docs list tables -d <index-dir> --file "<document-name>"
|
|
547
|
+
zen rag docs show -d <index-dir> "<document-name>" --lines <line>-<end>
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
Narrow `list tables` with `--file` or `--section` when the corpus has many
|
|
551
|
+
tables. `search --kind table` and `search --kind table_row` are useful to find
|
|
552
|
+
a relevant table, but remain ranked retrieval; use the listed line span when
|
|
553
|
+
the answer needs every row.
|
|
554
|
+
|
|
420
555
|
## Giving it to an agent
|
|
421
556
|
|
|
422
557
|
`@zenera/rag/docs/tools` exports four tools in the group `docs`:
|
|
@@ -424,8 +559,8 @@ a line range, verbatim.
|
|
|
424
559
|
| Tool | For |
|
|
425
560
|
| ------------- | --------------------------------------------------------------- |
|
|
426
561
|
| `search_docs` | The search above, with the same narrowing parameters |
|
|
427
|
-
| `list_docs` | The documents, their headings, or their tables
|
|
428
|
-
| `grep_docs` | Every matching line, counted in full
|
|
562
|
+
| `list_docs` | The documents, their headings, or their tables - no ranking |
|
|
563
|
+
| `grep_docs` | Every matching line, counted in full - the way to prove absence |
|
|
429
564
|
| `read_docs` | A section or a line range, verbatim and complete |
|
|
430
565
|
|
|
431
566
|
Only `search_docs` ranks. Every answer carries line numbers and `read_docs`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Running
|
|
1
|
+
# Running - `zen run`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
4
|
zen run [project] [prompt] [options]
|
|
@@ -49,8 +49,8 @@ git diff | zen run --quiet "summarise this diff"
|
|
|
49
49
|
|
|
50
50
|
A prompt is a request for an answer, not a conversation to pick up, so it
|
|
51
51
|
answers the three questions itself: **a fresh session**, **the directory you are
|
|
52
|
-
in** as the workspace, and **no confirmation**. Every flag still wins
|
|
53
|
-
`--session`, `--workspace` and `--read-only` override it
|
|
52
|
+
in** as the workspace, and **no confirmation**. Every flag still wins -
|
|
53
|
+
`--session`, `--workspace` and `--read-only` override it - and the TUI, where
|
|
54
54
|
there is someone to ask, still asks.
|
|
55
55
|
|
|
56
56
|
There is no `resume`. A session continues itself, because its state is what it
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# The sandbox
|
|
1
|
+
# The sandbox - `zen sandbox`
|
|
2
2
|
|
|
3
3
|
```
|
|
4
4
|
zen sandbox [status|up|pull|clean|disk] [options]
|
|
@@ -7,7 +7,7 @@ zen sandbox [status|up|pull|clean|disk] [options]
|
|
|
7
7
|
Shell commands run in a container over the session workspace, never on the
|
|
8
8
|
host. None of this is required: a run does all of it on its own, the first time
|
|
9
9
|
an agent that can reach a shell is about to start one. These subcommands are for
|
|
10
|
-
doing it deliberately
|
|
10
|
+
doing it deliberately - before a demo, in CI, or when diagnosing.
|
|
11
11
|
|
|
12
12
|
| Subcommand | What it does |
|
|
13
13
|
| ---------- | -------------------------------------------------------------- |
|
|
@@ -26,14 +26,14 @@ The engine is Podman. On macOS a machine has to exist and be running; `up`
|
|
|
26
26
|
offers to install and start one, and its size follows the project's `cpus` and
|
|
27
27
|
`memory`.
|
|
28
28
|
|
|
29
|
-
## Configuring it
|
|
29
|
+
## Configuring it - `sandbox:` in `agents.yaml`
|
|
30
30
|
|
|
31
31
|
Top level, and again per agent, where an agent's block is merged over the base.
|
|
32
32
|
|
|
33
33
|
| Key | Meaning |
|
|
34
34
|
| --------- | ---------------------------------------------------------------- |
|
|
35
35
|
| `image` | The image to run. Mutually exclusive with `build` |
|
|
36
|
-
| `build` | `{ dockerfile, context? }`
|
|
36
|
+
| `build` | `{ dockerfile, context? }` - build one instead. Excludes `image` |
|
|
37
37
|
| `cpus` | CPU limit |
|
|
38
38
|
| `memory` | Memory limit, in MiB |
|
|
39
39
|
| `network` | Whether the container has one |
|
|
@@ -47,11 +47,17 @@ Top level, and again per agent, where an agent's block is merged over the base.
|
|
|
47
47
|
`CREDENTIAL`: the keyring has already materialised real credentials into the
|
|
48
48
|
process environment, and a sandbox is the last place they should be forwarded to.
|
|
49
49
|
|
|
50
|
+
The door for those is the project's `.env`, which `zen init` writes and
|
|
51
|
+
`.gitignore` covers. `zen run` reads it before loading the project and forwards
|
|
52
|
+
every name in it into the container **by name**, so the value never reaches an
|
|
53
|
+
argv. `keys: false` and `zen run --no-keys` withhold it along with the API keys.
|
|
54
|
+
The shell's environment wins over the file; the keyring fills in the rest.
|
|
55
|
+
|
|
50
56
|
## `persist: true` is usually what you want
|
|
51
57
|
|
|
52
58
|
Only `/workspace` and `/home/agent` survive an ephemeral container. A
|
|
53
59
|
`pip install` as root, or an `apt-get install`, lands in the image's system
|
|
54
|
-
paths and is gone by the next run
|
|
60
|
+
paths and is gone by the next run - so the agent silently reinstalls its
|
|
55
61
|
toolchain every single time. `zen init` scaffolds `persist: true` for that
|
|
56
62
|
reason.
|
|
57
63
|
|
|
@@ -69,8 +75,8 @@ sandbox:
|
|
|
69
75
|
persist: true
|
|
70
76
|
```
|
|
71
77
|
|
|
72
|
-
The tag is content-addressed
|
|
73
|
-
context
|
|
78
|
+
The tag is content-addressed - a hash of the Dockerfile and every file in its
|
|
79
|
+
context - so a changed Dockerfile is a different image and a `persist: true`
|
|
74
80
|
container can never be left sitting on a stale rootfs. It is built only when
|
|
75
81
|
that tag is absent, which is safe precisely because the tag follows the content.
|
|
76
82
|
`zen sandbox pull` forces a rebuild.
|
|
@@ -87,5 +93,5 @@ prepared, and the message names the command to run for this platform. `zen check
|
|
|
87
93
|
distinguishes the two cases: a broken Dockerfile is an error, a laptop with no
|
|
88
94
|
Podman is a warning.
|
|
89
95
|
|
|
90
|
-
`zen sandbox clean` removes every container this CLI created
|
|
96
|
+
`zen sandbox clean` removes every container this CLI created - the way out of a
|
|
91
97
|
container left on a bad rootfs.
|