@zenera/cli 1.1.48 → 1.1.49

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/dist/batch.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { RunIdentity } from '@zenera/neo';
1
2
  import type { BatchItem, BatchRequest } from './request.ts';
2
3
  /**
3
4
  * Many questions, one project, at once.
@@ -34,6 +35,8 @@ export interface BatchOptions {
34
35
  readOnly?: boolean;
35
36
  keys?: boolean;
36
37
  yes?: boolean;
38
+ /** `--as`: who every item acts for */
39
+ user?: RunIdentity;
37
40
  /** a second home for the combined envelope */
38
41
  out?: string;
39
42
  json: boolean;
package/dist/batch.js CHANGED
@@ -228,6 +228,7 @@ async function runItem(item, ctx) {
228
228
  memoryDir: ctx.memory,
229
229
  memoryReadOnly: ctx.memoryReadOnly,
230
230
  keys: ctx.opts.keys,
231
+ user: ctx.opts.user,
231
232
  yes: true,
232
233
  // The project's own problems are the batch's, not each item's.
233
234
  quiet: true,
@@ -1,6 +1,6 @@
1
1
  import * as Projects from '@zenera/engine';
2
2
  import { display } from '@zenera/engine';
3
- import { usageByModel } from '@zenera/neo';
3
+ import { identityFromEnv, usageByModel } from '@zenera/neo';
4
4
  import { writeFile } from 'node:fs/promises';
5
5
  import { resolve } from 'node:path';
6
6
  import { parse } from "../args.js";
@@ -41,6 +41,9 @@ export const run = {
41
41
  ' --image <ref> Use this container image to run commands in.',
42
42
  ' --read-only Take away every tool that can write.',
43
43
  ' --no-keys Do not pass API keys into the container.',
44
+ ' --as <user> Act for this user: what `current_user` answers and $ZEN_USER_ID',
45
+ ' holds. An email also sets $ZEN_USER_EMAIL. For trying',
46
+ ' a project; the Zenera app passes the signed-in user.',
44
47
  ' --plain Never open the TUI. Needs a prompt.',
45
48
  ' --theme <dark|light> Colours for the TUI. Default: auto.',
46
49
  ' --out <file> Put the answer in this file instead of on screen.',
@@ -129,6 +132,7 @@ export const run = {
129
132
  model: { type: 'string' },
130
133
  image: { type: 'string' },
131
134
  'no-keys': { type: 'boolean' },
135
+ as: { type: 'string' },
132
136
  'read-only': { type: 'boolean' },
133
137
  yes: { type: 'boolean' },
134
138
  plain: { type: 'boolean' },
@@ -201,6 +205,7 @@ export const run = {
201
205
  memoryDir: request?.memory ?? (values.memory ? resolve(ctx.cwd, values.memory) : undefined),
202
206
  memoryReadOnly: values['memory-read-only'],
203
207
  keys: values['no-keys'] ? false : undefined,
208
+ user: asUser(values.as),
204
209
  yes: values.yes || ctx.json,
205
210
  disposable: values.disposable,
206
211
  });
@@ -236,6 +241,31 @@ export const run = {
236
241
  // ---------------------------------------------------------------------------
237
242
  // Many shots
238
243
  // ---------------------------------------------------------------------------
244
+ /**
245
+ * `--as`, as the identity a run acts for. Always `local` — saying who you are
246
+ * on your own machine is a test, not a login. The other fields still come from
247
+ * `ZEN_USER_*` when exported, so `ZEN_USER_ROLE=viewer zen run --as ann` tries
248
+ * a role too. Unset, the engine reads the environment by itself.
249
+ */
250
+ function asUser(as) {
251
+ if (as === undefined) {
252
+ return undefined;
253
+ }
254
+ const id = as.trim();
255
+ if (!id) {
256
+ throw usageError('--as needs a user', 'an id or an email, e.g. --as ann@example.com');
257
+ }
258
+ const env = identityFromEnv({ ...process.env, ZEN_USER_ID: id });
259
+ return {
260
+ ...env,
261
+ id,
262
+ email: env?.email ?? (id.includes('@') ? id : undefined),
263
+ source: 'local',
264
+ };
265
+ }
266
+ // ---------------------------------------------------------------------------
267
+ // Many shots
268
+ // ---------------------------------------------------------------------------
239
269
  /**
240
270
  * Flags that mean something to one run and nothing to a hundred. Refused by
241
271
  * name rather than ignored: a `--workspace` that was quietly dropped is a batch
@@ -276,6 +306,7 @@ async function batch(ctx, values, rest, piped) {
276
306
  image: values.image,
277
307
  readOnly: values['read-only'],
278
308
  keys: values['no-keys'] ? false : undefined,
309
+ user: asUser(values.as),
279
310
  yes: values.yes,
280
311
  out: values.out,
281
312
  json: ctx.json,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenera/cli",
3
- "version": "1.1.48",
3
+ "version": "1.1.49",
4
4
  "description": "Command-line front end for @zenera/neo: agentic projects you can run, share and commit.",
5
5
  "keywords": [
6
6
  "agents",
@@ -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.48",
58
- "@zenera/neo": "^1.1.48",
59
- "@zenera/view": "^1.1.48",
57
+ "@zenera/engine": "^1.1.49",
58
+ "@zenera/neo": "^1.1.49",
59
+ "@zenera/view": "^1.1.49",
60
60
  "google-auth-library": "^10.0.0",
61
61
  "ink": "^7.1.1",
62
62
  "openai": "^6.0.0",