@zenera/cli 1.1.37 → 1.1.40

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.
@@ -56,19 +56,18 @@ export const ALIASES = {
56
56
  mem: 'memory',
57
57
  edit: 'open',
58
58
  code: 'open',
59
- mock: 'faker',
60
59
  pack: 'export',
61
60
  archive: 'export',
62
61
  unpack: 'import',
63
62
  share: 'export',
64
63
  };
65
64
  export const EXTERNAL = {
66
- faker: {
67
- package: '@zenera/faker',
68
- summary: 'A mock API from an openapi/swagger document.',
69
- usage: 'zen faker <serve|build|cache> [spec...]',
70
- install: 'npm i -g @zenera/faker',
71
- banner: { head: 'Zenera', accent: 'Faker', subtitle: 'Mock API Server', hue: 'mint' },
65
+ gym: {
66
+ package: '@zenera/gym',
67
+ summary: 'Simulated API environments for agent training and evaluation.',
68
+ usage: 'zen gym <serve|build|cache|model> [spec...]',
69
+ install: 'npm i -g @zenera/gym',
70
+ banner: { head: 'Zenera', accent: 'Gym', subtitle: 'Agent Environments', hue: 'mint' },
72
71
  },
73
72
  rag: {
74
73
  package: '@zenera/rag',
@@ -136,7 +136,7 @@ async function status(project, image, asJson) {
136
136
  const found = await podmanStatus({ image });
137
137
  const all = found.ready ? await ownedContainers(found.engine) : [];
138
138
  // A container belongs to a session, and a session belongs to a project, so
139
- // a report about one project must not list another's — or the faker's,
139
+ // a report about one project must not list another's — or the gym's,
140
140
  // which wears the same label and belongs to no project at all.
141
141
  const containers = project ? ofProject(project.dir, all) : all;
142
142
  const idle = all.length > 0 ? idleContainers(all, await sessionOwners()) : [];
@@ -507,18 +507,18 @@ function projectRows(projects, loose) {
507
507
  ]);
508
508
  }
509
509
  if (loose.length > 0) {
510
- // Containers whose session directory is gone, and faker's, which are
510
+ // Containers whose session directory is gone, and gym's, which are
511
511
  // labelled the same way and belong to no project at all.
512
512
  const size = loose.reduce((n, c) => n + (c.size ?? 0), 0);
513
- const fakers = loose.filter((c) => c.key?.startsWith('faker-')).length;
513
+ const gyms = loose.filter((c) => c.key?.startsWith('gym-')).length;
514
514
  rows.push([
515
515
  dim('(unclaimed)'),
516
516
  dim('—'),
517
517
  dim('—'),
518
518
  dim(String(loose.length)),
519
519
  dim(bytes(size)),
520
- dim(fakers === loose.length
521
- ? `zen faker ${fakers === 1 ? 'server' : 'servers'}, no project`
520
+ dim(gyms === loose.length
521
+ ? `zen gym ${gyms === 1 ? 'server' : 'servers'}, no project`
522
522
  : 'no session owns these'),
523
523
  ]);
524
524
  }
package/dist/external.js CHANGED
@@ -11,7 +11,7 @@ import { CliError, EXIT, bold } from "./term.js";
11
11
  // Loading a command out of a sibling package
12
12
  //
13
13
  // The specifier is built rather than written, and that is the whole mechanism:
14
- // a literal `import('@zenera/faker/command')` would make the sibling a
14
+ // a literal `import('@zenera/gym/command')` would make the sibling a
15
15
  // compile-time dependency of `zen` — a project reference, a package.json entry,
16
16
  // and a cycle, since the sibling already depends on `zen`. Built, it is
17
17
  // resolved by Node at the moment the user asks for it and by nobody before.
package/dist/podman.js CHANGED
@@ -485,9 +485,9 @@ export function idleContainers(containers, owners) {
485
485
  if (c.state !== 'running') {
486
486
  return true;
487
487
  }
488
- const faker = /^faker-(\d+)$/.exec(c.key ?? '');
489
- if (faker) {
490
- return !pidAlive(Number(faker[1]));
488
+ const gym = /^gym-(\d+)$/.exec(c.key ?? '');
489
+ if (gym) {
490
+ return !pidAlive(Number(gym[1]));
491
491
  }
492
492
  const dir = c.key === undefined ? undefined : owners.get(c.key);
493
493
  return dir !== undefined && !isBusy(dir);
@@ -91,7 +91,7 @@ export interface MachineView {
91
91
  export interface ContainerView {
92
92
  name: string;
93
93
  id: string;
94
- kind: 'zen' | 'faker' | 'other';
94
+ kind: 'zen' | 'gym' | 'other';
95
95
  project?: string;
96
96
  orphaned: boolean;
97
97
  /** percent of one core */
@@ -128,7 +128,7 @@ export interface ResourceView {
128
128
  totals: {
129
129
  running: number;
130
130
  zen: number;
131
- faker: number;
131
+ gym: number;
132
132
  other: number;
133
133
  orphaned: number;
134
134
  memory: number;
package/dist/resources.js CHANGED
@@ -352,7 +352,7 @@ export function viewOf(now, before) {
352
352
  const prior = before?.stats.find((p) => p.id === s.id);
353
353
  const span = prior ? s.systemNano - prior.systemNano : 0;
354
354
  const measured = prior !== undefined && span > 0;
355
- const kind = !own ? 'other' : own.key?.startsWith('faker-') ? 'faker' : 'zen';
355
+ const kind = !own ? 'other' : own.key?.startsWith('gym-') ? 'gym' : 'zen';
356
356
  return {
357
357
  name: s.name,
358
358
  id: s.id,
@@ -393,7 +393,7 @@ export function viewOf(now, before) {
393
393
  totals: {
394
394
  running: containers.length,
395
395
  zen: containers.filter((c) => c.kind === 'zen').length,
396
- faker: containers.filter((c) => c.kind === 'faker').length,
396
+ gym: containers.filter((c) => c.kind === 'gym').length,
397
397
  other: containers.filter((c) => c.kind === 'other').length,
398
398
  orphaned: containers.filter((c) => c.orphaned).length,
399
399
  memory: containers.reduce((n, c) => n + c.memory, 0),
@@ -684,7 +684,7 @@ function containerHead(l, v, o) {
684
684
  const t = v.totals;
685
685
  const kinds = [
686
686
  t.zen ? `${t.zen} zen` : '',
687
- t.faker ? `${t.faker} faker` : '',
687
+ t.gym ? `${t.gym} gym` : '',
688
688
  t.other ? `${t.other} other` : '',
689
689
  ]
690
690
  .filter(Boolean)
@@ -700,7 +700,7 @@ function containerHead(l, v, o) {
700
700
  .filter(Boolean)
701
701
  .join(' · '));
702
702
  l.intro('Running ones only: a stopped container keeps its files but uses no memory or cpu. ' +
703
- 'zen makes one per session; zen faker servers and anything else in podman are listed too.');
703
+ 'zen makes one per session; zen gym servers and anything else in podman are listed too.');
704
704
  if (t.running === 0) {
705
705
  return;
706
706
  }
@@ -796,7 +796,7 @@ const COLUMNS = [
796
796
  width: 14,
797
797
  align: 'left',
798
798
  keep: 5,
799
- cell: (c) => [sp(clipTo(c.project ?? (c.kind === 'faker' ? '(faker)' : '—'), 14))],
799
+ cell: (c) => [sp(clipTo(c.project ?? (c.kind === 'gym' ? '(gym)' : '—'), 14))],
800
800
  },
801
801
  ];
802
802
  /** The columns that fit, in order, dropping the least needed until the name has room. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenera/cli",
3
- "version": "1.1.37",
3
+ "version": "1.1.40",
4
4
  "description": "Command-line front end for @zenera/neo: agentic projects you can run, share and commit.",
5
5
  "keywords": [
6
6
  "agents",
@@ -15,13 +15,13 @@
15
15
  "access": "public"
16
16
  },
17
17
  "author": "Andrey Ryabov",
18
- "homepage": "https://github.com/andreyryabov/ZeneraNeo#readme",
18
+ "homepage": "https://github.com/zenera-ai/ZeneraNeo#readme",
19
19
  "repository": {
20
20
  "type": "git",
21
- "url": "git+https://github.com/andreyryabov/ZeneraNeo.git",
21
+ "url": "git+https://github.com/zenera-ai/ZeneraNeo.git",
22
22
  "directory": "packages/cli"
23
23
  },
24
- "bugs": "https://github.com/andreyryabov/ZeneraNeo/issues",
24
+ "bugs": "https://github.com/zenera-ai/ZeneraNeo/issues",
25
25
  "type": "module",
26
26
  "bin": {
27
27
  "zen": "./dist/main.js",
@@ -54,9 +54,9 @@
54
54
  "@google/genai": "^2.30.0",
55
55
  "@inkjs/ui": "^2.0.0",
56
56
  "@openrouter/sdk": "^1.4.25",
57
- "@zenera/engine": "^1.1.37",
58
- "@zenera/neo": "^1.1.37",
59
- "@zenera/view": "^1.1.37",
57
+ "@zenera/engine": "^1.1.40",
58
+ "@zenera/neo": "^1.1.40",
59
+ "@zenera/view": "^1.1.40",
60
60
  "google-auth-library": "^10.0.0",
61
61
  "ink": "^7.1.1",
62
62
  "openai": "^6.0.0",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: zen-cli
3
- description: How to drive this project from the terminal with `zen` - running it, validating it, credentials, the sandbox, run reports, and the `faker` and `rag` modules.
3
+ description: How to drive this project from the terminal with `zen` - running it, validating it, credentials, the sandbox, run reports, and the `gym` and `rag` modules.
4
4
  ---
5
5
 
6
6
  # The `zen` command line
@@ -33,7 +33,7 @@ zen version
33
33
 
34
34
  zen meta <run|prompts|resume|model|dataset> [project] [args]
35
35
 
36
- zen faker <serve|build|cache> [spec...]
36
+ zen gym <serve|build|cache|model> [spec...]
37
37
  zen rag schema <index|restore|ready|search|list|grep|trace|show|stats> [spec...]
38
38
  zen rag docs <index|restore|ready|search|list|grep|show|stats> [path...]
39
39
  ```
@@ -61,7 +61,7 @@ guess a flag, and do not read them all.
61
61
  | The evaluation dataset: cases, drift, notes, drawing a sample | [dataset.md](./references/dataset.md) (and `zen-dataset` skill) |
62
62
  | Tuning the prose on the dataset: workers, applies, STATUS.md | [finetune.md](./references/finetune.md) |
63
63
  | Sharing a project: archives, what travels, importing one safely | [export.md](./references/export.md) |
64
- | `zen faker` - a mock API from an OpenAPI/Swagger document | [faker.md](./references/faker.md) |
64
+ | `zen gym` - a mock API from an OpenAPI/Swagger document | [gym.md](./references/gym.md) |
65
65
  | `zen rag` - searching an API description, or a pile of markdown | [rag.md](./references/rag.md) |
66
66
 
67
67
  ## The short version
@@ -37,7 +37,7 @@ Not listed in help, but they work.
37
37
  | `validate`, `doctor` | `check` |
38
38
  | `report` | `inspect` |
39
39
  | `edit`, `code` | `open` |
40
- | `mock` | `faker` |
40
+ | `mock` | `gym` |
41
41
 
42
42
  ## stdout is the answer, stderr is the narration
43
43
 
@@ -103,7 +103,7 @@ A real environment variable always beats the keyring.
103
103
  projects.json the registry: name -> directory
104
104
  keys.json credentials (0600)
105
105
  keys/ key files, for providers that hold a file
106
- faker/ generator cache for `zen faker`
106
+ gym/ generator cache for `zen gym`
107
107
 
108
108
  <project>/
109
109
  zenera.json { version, name }
@@ -1,11 +1,11 @@
1
- # Mock APIs - `zen faker`
1
+ # Agent API environments - `zen gym`
2
2
 
3
3
  ```
4
- zen faker <serve|build|cache> [spec...]
4
+ zen gym <serve|build|cache|model> [spec...]
5
5
  ```
6
6
 
7
- Alias: `zen mock`. Provided by `@zenera/faker` - `npm i -g @zenera/faker` if
8
- `zen faker` says it is not installed.
7
+ Provided by `@zenera/gym` - `npm i -g @zenera/gym` if
8
+ `zen gym` says it is not installed.
9
9
 
10
10
  Serves a mock API from one or more OpenAPI/Swagger documents. For each
11
11
  operation a **model writes a Python generator**, which is self-tested inside a
@@ -14,17 +14,18 @@ plausible, not `"string"` repeated.
14
14
 
15
15
  ## Subcommands
16
16
 
17
- | Command | What it does |
18
- | ----------------- | ----------------------------------------------------- |
19
- | `serve <spec...>` | Serve the documents. Generators are written on demand |
20
- | `build <spec...>` | Write every generator now and exit |
21
- | `cache ls\|clear` | What has been generated, or throw it away |
17
+ | Command | What it does |
18
+ | ----------------- | ---------------------------------------------------------- |
19
+ | `serve <spec...>` | Serve the documents. Generators are written on demand |
20
+ | `build <spec...>` | Write every generator now and exit |
21
+ | `cache ls\|clear` | What has been generated, or throw it away |
22
+ | `model [ref]` | Show or set the model; `--clear` forgets the stored choice |
22
23
 
23
24
  ```
24
- zen faker serve openapi.yaml
25
- zen faker serve api/*.yaml --port 9000 --seed 7
26
- zen faker build openapi.yaml --concurrency 8
27
- zen faker cache clear
25
+ zen gym serve openapi.yaml
26
+ zen gym serve api/*.yaml --port 9000 --seed 7
27
+ zen gym build openapi.yaml --concurrency 8
28
+ zen gym cache clear
28
29
  ```
29
30
 
30
31
  `build` is the one to run in CI or before a demo: it pays for every generator up
@@ -32,23 +33,25 @@ front and exits non-zero, with a table, if any could not be written.
32
33
 
33
34
  ## Options
34
35
 
35
- | Flag | Default | Meaning |
36
- | ------------------- | --------------------- | ----------------------------------------------- |
37
- | `--port <n>` | `8787` | Port to listen on |
38
- | `--host <h>` | `127.0.0.1` | Anything else is reachable off-machine |
39
- | `--model <ref>` | project default | Which model writes the generators |
40
- | `--image <ref>` | a baked image | Skip the baked image and use this one |
41
- | `--cache <dir>` | `~/.zenera/neo/faker` | Where generators live |
42
- | `--seed <n>` | - | Answer the same request the same way every time |
43
- | `--attempts <n>` | `3` | Tries per generator before giving up |
44
- | `--concurrency <n>` | `4` | Generators written at once |
45
- | `--timeout <s>` | `30` | Seconds one generator may take |
46
- | `--max-body <n>` | 1 MB | Largest request body accepted, in bytes |
47
- | `--rebuild` | - | Ignore what is cached and write it again |
48
- | `--no-cache` | - | Do not record what is written |
49
- | `--quiet` | - | No narration |
36
+ | Flag | Default | Meaning |
37
+ | ------------------- | ------------------- | ----------------------------------------------- |
38
+ | `--port <n>` | `8787` | Port to listen on |
39
+ | `--host <h>` | `127.0.0.1` | Anything else is reachable off-machine |
40
+ | `--model <ref>` | project default | Which model writes the generators |
41
+ | `--image <ref>` | a baked image | Skip the baked image and use this one |
42
+ | `--cache <dir>` | `~/.zenera/neo/gym` | Where generators live |
43
+ | `--seed <n>` | - | Answer the same request the same way every time |
44
+ | `--attempts <n>` | `3` | Tries per generator before giving up |
45
+ | `--concurrency <n>` | `4` | Generators written at once |
46
+ | `--timeout <s>` | `30` | Seconds one generator may take |
47
+ | `--max-body <n>` | 1 MB | Largest request body accepted, in bytes |
48
+ | `--rebuild` | - | Ignore what is cached and write it again |
49
+ | `--no-cache` | - | Do not record what is written |
50
+ | `--quiet` | - | No narration |
50
51
 
51
52
  Credentials come from the `zen` keyring - see [keys.md](keys.md).
53
+ Model selection: `--model`, `ZENERA_GYM_MODEL`, `~/.zenera/neo/gym.json`,
54
+ then the best model the available keys support.
52
55
 
53
56
  ## Serving
54
57
 
@@ -56,17 +59,19 @@ Binds the loopback address by default. On start it prints a table per document:
56
59
  paths, methods, and how many operations have a response schema and therefore get
57
60
  a generator.
58
61
 
59
- | Endpoint | Answers |
60
- | ----------------- | ------------------------- |
61
- | `/__faker/routes` | Every route it will serve |
62
- | `/__faker/health` | Whether it is up |
62
+ | Endpoint | Answers |
63
+ | --------------- | ------------------------- |
64
+ | `/__gym/routes` | Every route it will serve |
65
+ | `/__gym/health` | Whether it is up |
63
66
 
64
67
  Response headers:
65
68
 
66
- | Header | Meaning |
67
- | ------------------- | ----------------------------------------------------- |
68
- | `x-faker-operation` | The `operationId` that answered |
69
- | `x-faker-cache` | `hit` or `miss` - whether this call cost a model turn |
69
+ | Header | Meaning |
70
+ | ----------------- | ----------------------------------------------------- |
71
+ | `x-gym-operation` | The `operationId` that answered |
72
+ | `x-gym-cache` | `hit` or `miss` - whether this call cost a model turn |
73
+
74
+ Gym provides simulation, not task scoring, rewards, or a training loop.
70
75
 
71
76
  Incoming headers are filtered: `authorization`, `cookie` and anything matching
72
77
  `key|token|secret|password|credential` never reach a generator.
@@ -91,7 +96,7 @@ Probes are synthetic on purpose - real request bodies never reach a prompt.
91
96
 
92
97
  ## The cache
93
98
 
94
- Generators live in the machine's shared cache, `~/.zenera/neo/cache/faker-generator/`,
99
+ Generators live in the machine's shared cache, `~/.zenera/neo/cache/gym-generator/`,
95
100
  keyed by the operation's shape - so the same spec served from two directories is
96
101
  written once, and a spec edit produces a new key rather than a stale answer. A
97
102
  generator that a model gave up on is remembered for the life of the process, so
@@ -99,17 +104,17 @@ a hopeless operation is not re-asked on every request; a _transient_ failure - a
99
104
  429, a dropped socket - is not, because it is about this minute rather than this
100
105
  operation.
101
106
 
102
- `~/.zenera/neo/faker/` is the container's workspace, and scratch: a cache hit is
107
+ `~/.zenera/neo/gym/` is the container's workspace, and scratch: a cache hit is
103
108
  copied into it, because the container can only run what is under its mount.
104
109
 
105
- `zen faker cache ls` lists what has been generated. `zen faker cache clear`
110
+ `zen gym cache ls` lists what has been generated. `zen gym cache clear`
106
111
  removes the generators, the workspace and the container together. They have to
107
112
  go together: the container's name is a hash of its configuration, so deleting
108
113
  the workspace alone would leave a stopped container bind-mounted onto a
109
114
  directory that no longer exists, and every generator would fail with
110
115
  `python3: can't open file '/workspace/generators/…/gen.py'`.
111
116
 
112
- `zen cache ls --kind faker-generator` reaches the same entries from the other
117
+ `zen cache ls --kind gym-generator` reaches the same entries from the other
113
118
  side, along with everything else this machine has cached.
114
119
 
115
120
  ## Documents it accepts
@@ -77,7 +77,7 @@ turns gateway mode on without the keyring - and `zen key mode`/`ls`/`check`
77
77
  report and probe it (`bifrost/$BIFROST_API_KEY`), with nothing stored. In this
78
78
  mode `zen models` lists only
79
79
  what the gateway serves - see `models.md`. The full guide is
80
- [docs/gateway.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/gateway.md).
80
+ [docs/gateway.md](https://github.com/zenera-ai/ZeneraNeo/blob/main/docs/gateway.md).
81
81
 
82
82
  ### Vertex takes either shape
83
83
 
@@ -141,6 +141,6 @@ The frame does **not** materialise the keyring for you - each command that needs
141
141
  a credential opens the store itself. If `zen key ls` shows a key as live and a
142
142
  command still says `provider "openai": no api key - set OPENAI_API_KEY`, the
143
143
  credential is fine and the command is at fault. Everything that runs a model
144
- (`run`, `check`, `models`, `faker`, `rag`) already does this.
144
+ (`run`, `check`, `models`, `gym`, `rag`) already does this.
145
145
 
146
146
  Exit code `4` means no usable credential for what was asked.
@@ -58,7 +58,7 @@ stderr with a `⇄ bifrost mode` line, `browse` carries the same badge on every
58
58
  screen, and `--json` adds a `gateway` field. `zen models` then does go to the
59
59
  network, since one request covers every provider; `test` asks through the
60
60
  gateway too. The full guide is
61
- [docs/gateway.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/gateway.md).
61
+ [docs/gateway.md](https://github.com/zenera-ai/ZeneraNeo/blob/main/docs/gateway.md).
62
62
 
63
63
  ## Testing a model
64
64
 
@@ -34,7 +34,7 @@ zen rag schema index <spec...> [--embedding <ref>] [-o <dir>] [--batch <n>]
34
34
  zen rag schema index openapi.yaml --embedding openai:text-embedding-3-small
35
35
  ```
36
36
 
37
- Unlike the faker, `$ref`s are **bundled, not dereferenced**: component names are
37
+ Unlike the gym, `$ref`s are **bundled, not dereferenced**: component names are
38
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
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "https://raw.githubusercontent.com/andreyryabov/ZeneraNeo/main/packages/cli/templates/editor/.vscode/agents.schema.json",
3
+ "$id": "https://raw.githubusercontent.com/zenera-ai/ZeneraNeo/main/packages/cli/templates/editor/.vscode/agents.schema.json",
4
4
  "title": "Zenera Neo agents.yaml",
5
5
  "description": "Who exists in this project, what they may reach for, and which model answers for them. Written by `zen init` and replaced by every `zen init` and `zen open`, so it describes the version of `zen` in hand. The runtime is the authority: `zen check` reads the project the way a run does.",
6
6
  "type": "object",