@zenera/cli 1.1.35 → 1.1.37

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 (62) hide show
  1. package/dist/archive.js +1 -1
  2. package/dist/batch.js +2 -3
  3. package/dist/cache.js +1 -1
  4. package/dist/candidates.js +1 -1
  5. package/dist/catalog.d.ts +1 -1
  6. package/dist/catalog.js +1 -1
  7. package/dist/commands/cache.js +1 -1
  8. package/dist/commands/check.js +1 -3
  9. package/dist/commands/export.js +1 -3
  10. package/dist/commands/import.js +1 -2
  11. package/dist/commands/init.js +1 -4
  12. package/dist/commands/inspect.d.ts +1 -1
  13. package/dist/commands/inspect.js +1 -4
  14. package/dist/commands/key.js +1 -2
  15. package/dist/commands/list.js +4 -5
  16. package/dist/commands/memory.js +1 -2
  17. package/dist/commands/meta.js +2 -4
  18. package/dist/commands/models.d.ts +1 -1
  19. package/dist/commands/models.js +1 -2
  20. package/dist/commands/run.js +2 -2
  21. package/dist/commands/sandbox.js +1 -2
  22. package/dist/engine.d.ts +3 -90
  23. package/dist/engine.js +16 -302
  24. package/dist/history.js +1 -1
  25. package/dist/lib.d.ts +1 -2
  26. package/dist/lib.js +1 -2
  27. package/dist/liveness.d.ts +1 -1
  28. package/dist/liveness.js +1 -1
  29. package/dist/meta/host.d.ts +1 -2
  30. package/dist/meta/host.js +1 -2
  31. package/dist/meta/launch.js +3 -1
  32. package/dist/modelref.d.ts +1 -1
  33. package/dist/podman.d.ts +1 -1
  34. package/dist/podman.js +1 -1
  35. package/dist/resolve.d.ts +2 -2
  36. package/dist/resolve.js +2 -3
  37. package/dist/resources.js +1 -1
  38. package/dist/sandbox.d.ts +2 -60
  39. package/dist/sandbox.js +1 -200
  40. package/dist/term.d.ts +1 -22
  41. package/dist/term.js +3 -26
  42. package/dist/tui/app.js +1 -1
  43. package/dist/tui/models.d.ts +1 -1
  44. package/dist/validate.d.ts +1 -2
  45. package/dist/validate.js +1 -3
  46. package/package.json +4 -3
  47. package/dist/audit.d.ts +0 -58
  48. package/dist/audit.js +0 -148
  49. package/dist/env.d.ts +0 -20
  50. package/dist/env.js +0 -65
  51. package/dist/home.d.ts +0 -35
  52. package/dist/home.js +0 -112
  53. package/dist/ids.d.ts +0 -12
  54. package/dist/ids.js +0 -44
  55. package/dist/image.d.ts +0 -16
  56. package/dist/image.js +0 -85
  57. package/dist/keys.d.ts +0 -269
  58. package/dist/keys.js +0 -624
  59. package/dist/projects.d.ts +0 -91
  60. package/dist/projects.js +0 -303
  61. package/dist/session.d.ts +0 -112
  62. package/dist/session.js +0 -188
package/dist/engine.js CHANGED
@@ -1,306 +1,20 @@
1
- import { AgentRunner, FilePayloadStore, SANDBOX_MOUNT, SKILLS_MOUNT, Workspace, assertState, buildRunReport, exaTools, fileTools, lastText, loadProject, memoryDir, readProjectConfig, renderReportHtml, sandboxTools, turns, } from '@zenera/neo';
2
- import { existsSync } from 'node:fs';
3
- import { writeFile } from 'node:fs/promises';
4
- import { resolve } from 'node:path';
5
- import { pathToFileURL } from 'node:url';
6
- import { auditModels, describeIssue } from "./audit.js";
7
- import { loadProjectEnv } from "./env.js";
8
- import { readJson, writeJson } from "./home.js";
9
- import { KeyStore, assertUsable } from "./keys.js";
10
- import { projectMounts } from "./projects.js";
11
- import { buildSandbox, preflight, teardown, usesSandbox } from "./sandbox.js";
12
- import { acquire, createRun, readSessionMeta, writeRunMeta, writeSessionMeta, } from "./session.js";
13
- import { CliError, EXIT, invalidError, warn } from "./term.js";
1
+ import { describeIssue, openEngine, runEngine, } from '@zenera/engine';
2
+ import { preflight } from "./sandbox.js";
3
+ import { bold, dim, warn } from "./term.js";
14
4
  import { traceMermaid } from "./trace.js";
15
- /**
16
- * Wires the library to a session directory. Every store is file-backed and
17
- * rooted inside `.data/`, so a session is self-contained: copy the directory
18
- * and the whole conversation, its memory and its blobs travel with it.
19
- */
20
- export async function open(opts) {
21
- // Before the keyring, so the project's own file wins over the machine's
22
- // keys, and before the load, so `${VAR}` in agents.yaml can name anything
23
- // in it. The real environment still beats both.
24
- const env = loadProjectEnv(opts.project.dir);
25
- const keys = await KeyStore.open();
26
- keys.materialize();
27
- assertUsable(keys);
28
- // Said before the load, because the load stops at the first model it cannot
29
- // build: one SDK's words about one model, when the useful answer is which
30
- // of the project's models are reachable and which are not.
31
- for (const issue of auditModels(opts.project.dir, keys)) {
32
- if (!opts.quiet) {
33
- warn(describeIssue(issue));
34
- }
35
- }
36
- const meta = await readSessionMeta(opts.session);
37
- const workspace = resolve(meta.workspace);
38
- const payloads = new FilePayloadStore({ dir: opts.session.blobs, id: 'file' });
39
- // The config is read before the project is loaded because the sandbox is
40
- // configured by it and the tools have to exist before selectors can be
41
- // resolved against them. They are always registered, whether or not anyone
42
- // selects them: a project that names `sandbox:*` against an empty tool list
43
- // fails to load with "unknown tool", which would be a lie.
44
- let sandbox;
45
- let project;
46
- let files;
47
- let memory;
48
- try {
49
- const { root, config } = readProjectConfig(opts.project.dir);
50
- // Naming a directory declares the graph, but it cannot bind anyone to
51
- // it — so say when the run is pointed at a memory no agent will touch.
52
- if (opts.memoryDir && !opts.quiet && !config.agents.some((a) => a.memory)) {
53
- warn('--memory names a directory no agent uses — none has `memory: true`');
54
- }
55
- memory = memoryDir(root, config, opts.memoryDir);
56
- // Assets and the skill catalog are mounted for both, under one name.
57
- const mounts = projectMounts(root, config, opts.memoryDir);
58
- sandbox = buildSandbox({
59
- config,
60
- root,
61
- session: opts.session,
62
- workspace,
63
- readOnly: opts.readOnly,
64
- image: opts.image,
65
- keys: opts.keys,
66
- env: env?.names,
67
- mounts,
68
- ...(opts.disposable ? { persist: false } : {}),
69
- });
70
- const workspaceOptions = {
71
- root: workspace,
72
- readOnly: opts.readOnly,
73
- mount: sandbox.spec.workdir ?? SANDBOX_MOUNT,
74
- mounts,
75
- };
76
- // The same view the file tools have, so a path the agent just wrote
77
- // resolves the same way when it asks memory to keep a copy.
78
- files = new Workspace(workspaceOptions);
79
- project = await loadProject(opts.project.dir, {
80
- tools: [
81
- // Both groups are pointed at one directory, so both are told the
82
- // one name for it: whatever `run_command` prints a path as,
83
- // `read_file` accepts.
84
- ...fileTools(workspaceOptions),
85
- ...sandboxTools(sandbox.pool),
86
- // Registered whether or not a key exists: the credential is
87
- // read when a tool is called, so a project that names `exa:*`
88
- // loads on a machine that cannot yet search, and says so on the
89
- // turn that tried.
90
- ...exaTools(),
91
- ],
92
- skillsAt: SKILLS_MOUNT,
93
- memoryDir: opts.memoryDir,
94
- memoryReadOnly: opts.memoryReadOnly,
95
- payloads,
96
- resolveFile: (path) => files.within(path),
97
- });
98
- }
99
- catch (err) {
100
- throw invalidError(err instanceof Error ? err.message : String(err), `while loading ${opts.project.dir}`);
101
- }
102
- // Asked here rather than at the first `run_command`, so a host with no
103
- // container engine costs an error instead of a round trip. Nothing is
104
- // started: the container itself waits until something actually runs.
105
- if (usesSandbox(project)) {
106
- await preflight(sandbox, opts.yes);
107
- }
108
- // `recordRequests` is what makes the report show the exact bytes sent
109
- // rather than a reconstruction. It costs state size, and a CLI run is
110
- // written to disk once and inspected by a human — exactly the case the
111
- // library leaves it off for by default.
112
- //
113
- // `--model` becomes the runner's fallback rather than an alias, so it
114
- // overrides the config's `model:` without touching agents that pinned one.
115
- const runner = project.runner({
116
- recordRequests: true,
117
- model: opts.model ? project.models.model(opts.model) : undefined,
5
+ // ---------------------------------------------------------------------------
6
+ // `@zenera/engine` as the terminal hosts it: warnings in colour on stderr, a
7
+ // podman that can be installed on the spot, and a graph beside every run.
8
+ // ---------------------------------------------------------------------------
9
+ export { envelope, mounts, } from '@zenera/engine';
10
+ export function open(opts) {
11
+ return openEngine({
12
+ logger: { warn },
13
+ onIssue: (issue) => warn(describeIssue(issue, { bold, dim })),
14
+ preflight,
15
+ graph: traceMermaid,
16
+ ...opts,
118
17
  });
119
- const state = await loadState(opts.session);
120
- const lock = acquire(opts.session);
121
- return {
122
- project,
123
- runner,
124
- name: opts.project.name,
125
- workspace,
126
- workspaceMount: sandbox.spec.workdir ?? SANDBOX_MOUNT,
127
- files,
128
- readOnly: Boolean(opts.readOnly),
129
- session: opts.session,
130
- memory,
131
- state,
132
- sandbox,
133
- lock,
134
- close: async () => {
135
- await teardown(sandbox.pool);
136
- project.close();
137
- lock.release();
138
- },
139
- };
140
- }
141
- async function loadState(session) {
142
- if (!existsSync(session.state)) {
143
- return undefined;
144
- }
145
- const json = await readJson(session.state, undefined);
146
- try {
147
- return assertState(json);
148
- }
149
- catch {
150
- throw invalidError(`${session.state} is not a usable run state`, 'start a fresh session with --new');
151
- }
152
- }
153
- /** Every tree the agent can see, the workspace first. */
154
- export function mounts(engine) {
155
- return [
156
- { host: engine.workspace, at: engine.workspaceMount, readOnly: engine.readOnly },
157
- ...engine.sandbox.mounts.map((m) => ({
158
- host: m.host,
159
- at: m.at,
160
- readOnly: Boolean(m.readOnly),
161
- })),
162
- ];
163
- }
164
- /**
165
- * What one finished run looks like to a program: `zen run --json` prints it,
166
- * and a batch writes one beside every item. The same function on purpose — a
167
- * batch whose items were shaped differently would make every consumer of a
168
- * single run a special case.
169
- */
170
- export function envelope(engine, outcome) {
171
- return {
172
- session: { id: engine.session.id, dir: engine.session.dir },
173
- run: {
174
- id: outcome.run.id,
175
- dir: outcome.run.dir,
176
- input: outcome.run.input,
177
- output: outcome.run.output,
178
- state: outcome.run.state,
179
- meta: outcome.run.meta,
180
- ...(outcome.report ? { report: outcome.report } : {}),
181
- ...(outcome.graph ? { graph: outcome.graph } : {}),
182
- },
183
- mounts: mounts(engine),
184
- agent: outcome.result.agent,
185
- stopReason: outcome.result.stopReason,
186
- durationMs: outcome.durationMs,
187
- usage: outcome.result.usage,
188
- output: outcome.text,
189
- };
190
- }
191
- /**
192
- * One turn. The session's state decides whether this starts a run or continues
193
- * one — which is the whole of what `resume` used to be, and why it is not a
194
- * command.
195
- */
196
- export async function run(engine, input, onEvent, signal) {
197
- const startedAt = new Date();
198
- const stream = engine.state
199
- ? engine.runner.send(engine.state, input, { signal })
200
- : engine.runner.run(engine.project.entry, input, { signal });
201
- if (onEvent) {
202
- for await (const event of stream) {
203
- onEvent(event);
204
- }
205
- }
206
- const result = await stream.final();
207
- const durationMs = Date.now() - startedAt.getTime();
208
- engine.state = result.state;
209
- const outcome = await record(engine, input, result, startedAt, durationMs);
210
- if (result.stopReason === 'failed') {
211
- throw new CliError(result.state.error ?? 'the run failed', EXIT.failed, `report: ${outcome.run.report}`);
212
- }
213
- return outcome;
214
- }
215
- /**
216
- * Everything a finished turn leaves behind. The session state is written first:
217
- * if the report fails to render, the conversation is still resumable, which is
218
- * the ordering that loses least.
219
- */
220
- async function record(engine, input, result, startedAt, durationMs) {
221
- const { session } = engine;
222
- writeJson(session.state, result.state, 0o644);
223
- const meta = await readSessionMeta(session);
224
- meta.lastRunAt = new Date().toISOString();
225
- meta.title ??= title(input);
226
- writeSessionMeta(session, meta);
227
- const run = createRun(session);
228
- const text = await lastText(result.state, engine.runner.services.payloads);
229
- await writeFile(run.input, `${asText(input)}\n`, 'utf8');
230
- await writeFile(run.output, `${text}\n`, 'utf8');
231
- writeJson(run.state, result.state, 0o644);
232
- let report;
233
- try {
234
- const built = await buildRunReport(result.state, engine.runner.services.payloads, {
235
- title: `${engine.name} · ${run.id}`,
236
- architecture: await engine.runner.describe(),
237
- memory: engine.runner.services.memory?.store,
238
- mounts: [
239
- { at: engine.workspaceMount, href: pathToFileURL(engine.files.root).href },
240
- ...engine.files.mounts.map((m) => ({ at: m.at, href: pathToFileURL(m.host).href })),
241
- ],
242
- });
243
- await writeFile(run.report, renderReportHtml(built), 'utf8');
244
- report = run.report;
245
- }
246
- catch {
247
- // A report is a convenience. Losing it must not lose the run.
248
- }
249
- // The same trajectory for the other reader. `report.html` is for a person;
250
- // this is what `zen inspect graph` prints, written down while the state is
251
- // already in hand — a batch of a hundred items is otherwise a hundred more
252
- // commands to run before anything can be read.
253
- let graph;
254
- try {
255
- await writeFile(run.graph, traceMermaid(result.state, {
256
- runId: run.id,
257
- dir: run.dir,
258
- workspace: engine.workspace,
259
- memory: engine.memory,
260
- }), 'utf8');
261
- graph = run.graph;
262
- }
263
- catch {
264
- // Same rule as the report: a view of the run is not the run.
265
- }
266
- writeRunMeta(run, {
267
- version: 1,
268
- id: run.id,
269
- session: session.id,
270
- startedAt: startedAt.toISOString(),
271
- finishedAt: new Date().toISOString(),
272
- durationMs,
273
- agent: result.agent,
274
- stopReason: result.stopReason,
275
- turns: turns(result.state),
276
- usage: result.usage,
277
- workspace: engine.workspace,
278
- memory: engine.memory,
279
- error: result.state.error,
280
- });
281
- return { run, result, text, durationMs, report, graph };
282
- }
283
- function asText(input) {
284
- if (typeof input === 'string') {
285
- return input;
286
- }
287
- return input
288
- .map((part) => {
289
- if (typeof part === 'string') {
290
- return part;
291
- }
292
- if ('text' in part && typeof part.text === 'string') {
293
- return part.text;
294
- }
295
- // A media shorthand is a single key; naming it is more useful in a
296
- // transcript than printing the url or the base64 behind it.
297
- return `[${Object.keys(part)[0] ?? 'part'}]`;
298
- })
299
- .join('\n');
300
- }
301
- /** A session's label in a picker: the first thing that was ever asked of it. */
302
- function title(input) {
303
- const text = asText(input).replace(/\s+/g, ' ').trim();
304
- return text.length > 60 ? `${text.slice(0, 57)}…` : text;
305
18
  }
19
+ export const run = runEngine;
306
20
  //# sourceMappingURL=engine.js.map
package/dist/history.js CHANGED
@@ -1,7 +1,7 @@
1
+ import { sessionsDir } from '@zenera/engine';
1
2
  import { randomUUID } from 'node:crypto';
2
3
  import { appendFileSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from 'node:fs';
3
4
  import { dirname, join } from 'node:path';
4
- import { sessionsDir } from "./projects.js";
5
5
  // ---------------------------------------------------------------------------
6
6
  // The prompt's history
7
7
  //
package/dist/lib.d.ts CHANGED
@@ -1,10 +1,9 @@
1
+ export { assertNotEmpty, assertOwner, assertPrivate, assertUsable, describe, ensureDir, ensureHome, envNames, envOf, form, home, isOwner, isProvider, keyId, KeyStore, mask, OWNERS, parseRef, paths, PROVIDERS, readJson, SERVICES, SHAPES, writeJson, type CredentialForm, type KeyCheck, type KeyEntry, type KeyOwner, type Liveness, type Provider, type Service, } from '@zenera/engine';
1
2
  export { extract, invokedAs, one, parse, split, type Parsed, type Split } from './args.ts';
2
3
  export { bannerArt, printBanner, type BannerText } from './banner.ts';
3
4
  export { Cache, items as cacheItems, cacheKey, kinds as cacheKinds, clear as clearCache, NO_CACHE, sweep as sweepCache, type CacheEntry, type CacheItem, type CacheKind, type CacheOptions, type CacheStore, type Swept, } from './cache.ts';
4
5
  export { CATALOG_TTL_MS, CURATED, fetchCatalog, loadCatalog, loadCatalogs, matches, PREFERRED, type Catalog, type CatalogEntry, type CatalogOptions, type Filters, type Role, } from './catalog.ts';
5
6
  export type { Command, Context } from './command.ts';
6
- export { assertPrivate, ensureDir, ensureHome, home, paths, readJson, writeJson } from './home.ts';
7
- export { assertNotEmpty, assertOwner, assertUsable, describe, envNames, envOf, form, isOwner, isProvider, keyId, KeyStore, mask, OWNERS, parseRef, PROVIDERS, SERVICES, SHAPES, type CredentialForm, type KeyCheck, type KeyEntry, type KeyOwner, type Liveness, type Provider, type Service, } from './keys.ts';
8
7
  export { probe, probeAll } from './liveness.ts';
9
8
  export { engineDisk, ensurePodmanReady, ownedContainers, podmanStatus, removeContainers, type DiskLine, type EngineDisk, type OwnedContainer, type PodmanOptions, type PodmanStatus, } from './podman.ts';
10
9
  export { ago, bold, CliError, count, credentialError, cyan, dim, EXIT, fail, green, invalidError, isInteractive, italic, json, note, pad, red, table, underline, usageError, warn, write, writeAll, yellow, type ExitCode, } from './term.ts';
package/dist/lib.js CHANGED
@@ -21,12 +21,11 @@
21
21
  // writers go to stdout/stderr. That vocabulary belongs to startup. A server
22
22
  // must not let a `CliError` escape into a request handler.
23
23
  // ---------------------------------------------------------------------------
24
+ export { assertNotEmpty, assertOwner, assertPrivate, assertUsable, describe, ensureDir, ensureHome, envNames, envOf, form, home, isOwner, isProvider, keyId, KeyStore, mask, OWNERS, parseRef, paths, PROVIDERS, readJson, SERVICES, SHAPES, writeJson, } from '@zenera/engine';
24
25
  export { extract, invokedAs, one, parse, split } from "./args.js";
25
26
  export { bannerArt, printBanner } from "./banner.js";
26
27
  export { Cache, items as cacheItems, cacheKey, kinds as cacheKinds, clear as clearCache, NO_CACHE, sweep as sweepCache, } from "./cache.js";
27
28
  export { CATALOG_TTL_MS, CURATED, fetchCatalog, loadCatalog, loadCatalogs, matches, PREFERRED, } from "./catalog.js";
28
- export { assertPrivate, ensureDir, ensureHome, home, paths, readJson, writeJson } from "./home.js";
29
- export { assertNotEmpty, assertOwner, assertUsable, describe, envNames, envOf, form, isOwner, isProvider, keyId, KeyStore, mask, OWNERS, parseRef, PROVIDERS, SERVICES, SHAPES, } from "./keys.js";
30
29
  export { probe, probeAll } from "./liveness.js";
31
30
  export { engineDisk, ensurePodmanReady, ownedContainers, podmanStatus, removeContainers, } from "./podman.js";
32
31
  export { ago, bold, CliError, count, credentialError, cyan, dim, EXIT, fail, green, invalidError, isInteractive, italic, json, note, pad, red, table, underline, usageError, warn, write, writeAll, yellow, } from "./term.js";
@@ -1,5 +1,5 @@
1
+ import { type KeyCheck, type KeyEntry, type KeyStore } from '@zenera/engine';
1
2
  import { type Embedder, type Model } from '@zenera/neo';
2
- import { type KeyCheck, type KeyEntry, type KeyStore } from './keys.ts';
3
3
  export declare function classify(err: unknown): KeyCheck;
4
4
  /**
5
5
  * The cheapest authenticated call each SDK has. Nothing here reads a model or
package/dist/liveness.js CHANGED
@@ -1,5 +1,5 @@
1
+ import { envOf, SHAPES, } from '@zenera/engine';
1
2
  import { createModel, EXA_BASE_URL, GATEWAY_KEY_HEADER, isUnfunded, ModelRegistry, text, vertexRoute, } from '@zenera/neo';
2
- import { envOf, SHAPES, } from "./keys.js";
3
3
  // ---------------------------------------------------------------------------
4
4
  // Liveness
5
5
  //
@@ -1,8 +1,7 @@
1
+ export { envOf, paths, PROVIDERS, readJson, writeJson, type KeyEntry, type KeyStore, type Provider, } from '@zenera/engine';
1
2
  export { invokedAs, parse } from '../args.ts';
2
3
  export { loadCatalogs } from '../catalog.ts';
3
4
  export type { EventLine } from '../eventlog.ts';
4
- export { paths, readJson, writeJson } from '../home.ts';
5
- export { envOf, PROVIDERS, type KeyEntry, type KeyStore, type Provider } from '../keys.ts';
6
5
  export { PROVIDER_NAMES, splitRef } from '../modelref.ts';
7
6
  export { duration } from '../narrate.ts';
8
7
  export { rankModels } from '../rank.ts';
package/dist/meta/host.js CHANGED
@@ -5,10 +5,9 @@
5
5
  // other, so the layer can leave for a package of its own by turning this into
6
6
  // a dependency. `test/meta-boundary.test.ts` holds the line.
7
7
  // ---------------------------------------------------------------------------
8
+ export { envOf, paths, PROVIDERS, readJson, writeJson, } from '@zenera/engine';
8
9
  export { invokedAs, parse } from "../args.js";
9
10
  export { loadCatalogs } from "../catalog.js";
10
- export { paths, readJson, writeJson } from "../home.js";
11
- export { envOf, PROVIDERS } from "../keys.js";
12
11
  export { PROVIDER_NAMES, splitRef } from "../modelref.js";
13
12
  export { duration } from "../narrate.js";
14
13
  export { rankModels } from "../rank.js";
@@ -143,7 +143,9 @@ export function absorb(event, out, sink, width) {
143
143
  export async function launch(opts) {
144
144
  const shown = opts.sink ?? windowSink();
145
145
  const sink = opts.log ? tee(shown, opts.log) : shown;
146
- const width = opts.width ?? Math.max(40, (process.stderr.columns ?? 100) - 4);
146
+ // Without a terminal nothing wraps, and a cut line is lost from the log too.
147
+ const width = opts.width ??
148
+ (process.stderr.isTTY ? Math.max(40, (process.stderr.columns ?? 100) - 4) : Infinity);
147
149
  const start = opts.spawn ?? nodeSpawn;
148
150
  const out = { answer: '', exitCode: 0, events: [] };
149
151
  const child = start(opts.binary.command, [...opts.binary.args, ...opts.args], {
@@ -1,4 +1,4 @@
1
- import type { Provider } from './keys.ts';
1
+ import type { Provider } from '@zenera/engine';
2
2
  export declare const PROVIDER_NAMES: ReadonlySet<string>;
3
3
  /**
4
4
  * `vertex/gemini-3.8-flash` splits; `gpt-5.6-sol` does not. Only a known provider
package/dist/podman.d.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import { type ResolvedBuild } from '@zenera/engine';
1
2
  import { runProcess } from '@zenera/neo';
2
- import type { ResolvedBuild } from './image.ts';
3
3
  import { CliError } from './term.ts';
4
4
  export interface PodmanOptions {
5
5
  /** the image the project needs on disk before the first run */
package/dist/podman.js CHANGED
@@ -1,8 +1,8 @@
1
+ import { isBusy, isProjectDir, Registry, sessionIds, sessionsDir, } from '@zenera/engine';
1
2
  import { pidAlive, runProcess, SandboxError } from '@zenera/neo';
2
3
  import { readdirSync, readFileSync, statSync } from 'node:fs';
3
4
  import { homedir, platform } from 'node:os';
4
5
  import { join } from 'node:path';
5
- import { isBusy, isProjectDir, Registry, sessionIds, sessionsDir } from "./projects.js";
6
6
  import { CliError, confirm, dim, EXIT, isInteractive, note, progress } from "./term.js";
7
7
  const DEFAULT_MACHINE_CPUS = 2;
8
8
  const DEFAULT_MACHINE_MEMORY = 2048;
package/dist/resolve.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import * as Projects from './projects.ts';
2
- import { type SessionPaths } from './session.ts';
1
+ import * as Projects from '@zenera/engine';
2
+ import { type SessionPaths } from '@zenera/engine';
3
3
  export interface Wanted {
4
4
  project?: string;
5
5
  session?: string;
package/dist/resolve.js CHANGED
@@ -1,8 +1,7 @@
1
+ import * as Projects from '@zenera/engine';
2
+ import { createSession, listSessions, readSessionMeta, requireSession, sessionPaths, stamp, } from '@zenera/engine';
1
3
  import { existsSync } from 'node:fs';
2
4
  import { isAbsolute, relative, resolve, sep } from 'node:path';
3
- import { stamp } from "./ids.js";
4
- import * as Projects from "./projects.js";
5
- import { createSession, listSessions, readSessionMeta, requireSession, sessionPaths, } from "./session.js";
6
5
  import * as term from "./term.js";
7
6
  import { ago, bold, cyan, dim, usageError, yellow } from "./term.js";
8
7
  // ---------------------------------------------------------------------------
package/dist/resources.js CHANGED
@@ -1,8 +1,8 @@
1
+ import { isProjectDir, Registry, sessionIds, sessionsDir } from '@zenera/engine';
1
2
  import { runProcess } from '@zenera/neo';
2
3
  import { cpus as hostCpus, platform as hostPlatform, totalmem } from 'node:os';
3
4
  import { basename, join } from 'node:path';
4
5
  import { idleContainers, ownedContainers } from "./podman.js";
5
- import { isProjectDir, Registry, sessionIds, sessionsDir } from "./projects.js";
6
6
  import { ago, bytes } from "./term.js";
7
7
  import { wrap } from "./tui/wrap.js";
8
8
  const MIB = 1024 * 1024;
package/dist/sandbox.d.ts CHANGED
@@ -1,62 +1,4 @@
1
- import { SandboxPool, type AgentProject, type ProjectConfig, type SandboxMount, type SandboxSpec } from '@zenera/neo';
2
- import { type ResolvedBuild } from './image.ts';
3
- import type { SessionPaths } from './session.ts';
4
- export interface SandboxSetup {
5
- pool: SandboxPool;
6
- /** the resolved base spec, for `zn sandbox status` and the image pre-warm */
7
- spec: SandboxSpec;
8
- image: string;
9
- /** the Dockerfile behind `image`, when it came from one */
10
- build?: ResolvedBuild;
11
- /** host side of the container's `$HOME`, created only if it is ever needed */
12
- home: string;
13
- /** every tree bound into the container besides the workspace itself */
14
- mounts: readonly SandboxMount[];
15
- }
16
- export interface SandboxInputs {
17
- config: ProjectConfig;
18
- session: SessionPaths;
19
- workspace: string;
20
- /** the project directory, which `build:` paths are relative to */
21
- root: string;
22
- readOnly?: boolean;
23
- /**
24
- * Trees to mount besides the workspace and the home — the project's assets
25
- * and its skill catalog. The same array goes to the file tools, so a path
26
- * a command prints is a path `read_file` accepts.
27
- */
28
- mounts?: readonly SandboxMount[];
29
- /** `--image` */
30
- image?: string;
31
- /** `--no-keys`: refuse to forward credentials, whatever the config says */
32
- keys?: boolean;
33
- /**
34
- * Names from the project's `.env`, forwarded into the container the same
35
- * way a credential is — by name, so the value stays out of the argv.
36
- *
37
- * They travel with the keys rather than beside them: a `.env` is where an
38
- * api token lives, so `--no-keys` has to withhold it too or the flag is a
39
- * promise it does not keep.
40
- */
41
- env?: readonly string[];
42
- /** `false` overrides every `persist:` in the config, the agents' included */
43
- persist?: boolean;
44
- }
45
- export declare function buildSandbox(opts: SandboxInputs): SandboxSetup;
46
- /**
47
- * Whether anything in this project can reach a shell.
48
- *
49
- * Read off the *resolved* tool lists rather than off the config's selectors,
50
- * because `sandbox:*`, `*` and a bare name all mean the same thing by the time
51
- * the loader is done, and only one of those three is greppable.
52
- */
53
- export declare function usesSandbox(project: AgentProject): boolean;
54
- /**
55
- * Asked before the first turn rather than at the first tool call, so a missing
56
- * container engine costs nothing instead of costing a round trip and half a
57
- * plan. A project that never shells out never gets here at all.
58
- */
1
+ import type { SandboxSetup } from '@zenera/engine';
2
+ /** The engine's preflight on a terminal: podman is offered for install and started if needed. */
59
3
  export declare function preflight(setup: SandboxSetup, yes?: boolean): Promise<void>;
60
- /** Best-effort teardown: losing a container must never lose a run. */
61
- export declare function teardown(pool: SandboxPool): Promise<void>;
62
4
  //# sourceMappingURL=sandbox.d.ts.map