@zenera/cli 1.1.30 → 1.1.32
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 +13 -0
- package/dist/catalog.js +30 -18
- package/dist/commands/meta.js +14 -13
- package/dist/keys.d.ts +6 -1
- package/dist/keys.js +6 -1
- package/dist/meta/model.d.ts +11 -2
- package/dist/meta/model.js +12 -3
- package/dist/meta/wire.d.ts +7 -0
- package/dist/meta/wire.js +26 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
[](https://www.npmjs.com/package/@zenera/cli)
|
|
15
15
|
[](https://github.com/andreyryabov/ZeneraNeo/blob/main/LICENSE)
|
|
16
16
|
[](https://nodejs.org)
|
|
17
|
+
[](https://github.com/andreyryabov/ZeneraNeo/actions/workflows/ci.yml)
|
|
18
|
+
|
|
19
|
+
[Install](#install) · [Quickstart](#quickstart) · [Commands](#commands) · [Documentation](#documentation) · [Family](#the-rest-of-the-family) · [License](#license)
|
|
17
20
|
|
|
18
21
|
</div>
|
|
19
22
|
|
|
@@ -1125,6 +1128,16 @@ terminal:
|
|
|
1125
1128
|
- [docs/gateway.md](https://github.com/andreyryabov/ZeneraNeo/blob/main/docs/gateway.md)
|
|
1126
1129
|
- every model through a Bifrost gateway, with one virtual key.
|
|
1127
1130
|
|
|
1131
|
+
## The rest of the family
|
|
1132
|
+
|
|
1133
|
+
| Package | What it is |
|
|
1134
|
+
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
1135
|
+
| **`@zenera/cli`** | `zen` - agent projects on the command line |
|
|
1136
|
+
| [`@zenera/neo`](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/neo/README.md) | the runtime - agents, models, tools, skills, memory |
|
|
1137
|
+
| [`@zenera/faker`](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/faker/README.md) | `zen faker` - a mock API from an openapi/swagger document |
|
|
1138
|
+
| [`@zenera/rag`](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/rag/README.md) | `zen rag` - indexing and search for documents and API schemas |
|
|
1139
|
+
| [`@zenera/view`](https://github.com/andreyryabov/ZeneraNeo/blob/main/packages/view/README.md) | `zen view` - a live local viewer for a folder |
|
|
1140
|
+
|
|
1128
1141
|
## License
|
|
1129
1142
|
|
|
1130
1143
|
Early days and moving fast - issues, questions and pull requests are welcome.
|
package/dist/catalog.js
CHANGED
|
@@ -463,10 +463,6 @@ const store = () => new Cache(CATALOG_KIND, { mode: 0o644 });
|
|
|
463
463
|
* to both. A project left to the service-account file is not seen here.
|
|
464
464
|
*/
|
|
465
465
|
function scope(provider) {
|
|
466
|
-
const at = gatewayOf();
|
|
467
|
-
if (at) {
|
|
468
|
-
return cacheKey(GATEWAY_NAME, at.baseURL);
|
|
469
|
-
}
|
|
470
466
|
if (provider !== 'vertex') {
|
|
471
467
|
return undefined;
|
|
472
468
|
}
|
|
@@ -483,6 +479,29 @@ function readCache(provider) {
|
|
|
483
479
|
? file
|
|
484
480
|
: undefined;
|
|
485
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* Through a gateway nothing is cached on disk: the gateway caches its own
|
|
484
|
+
* listing, one request serves every provider, and a stale copy outlives the
|
|
485
|
+
* gateway's providers or the virtual key that was allowed to see them.
|
|
486
|
+
*/
|
|
487
|
+
async function loadGatewayCatalog(provider, at) {
|
|
488
|
+
const via = { via: { name: GATEWAY_NAME, url: at.baseURL } };
|
|
489
|
+
try {
|
|
490
|
+
const entries = await fetchGatewayCatalog(provider, at);
|
|
491
|
+
return { provider, entries, origin: 'live', fetchedAt: new Date().toISOString(), ...via };
|
|
492
|
+
}
|
|
493
|
+
catch (err) {
|
|
494
|
+
// No built-in list: it names vendor models the gateway may not serve at all.
|
|
495
|
+
return {
|
|
496
|
+
provider,
|
|
497
|
+
entries: [],
|
|
498
|
+
origin: 'curated',
|
|
499
|
+
fetchedAt: new Date(0).toISOString(),
|
|
500
|
+
problem: classify(err),
|
|
501
|
+
...via,
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
}
|
|
486
505
|
/**
|
|
487
506
|
* The listing for one provider, from the cheapest source that can answer.
|
|
488
507
|
*
|
|
@@ -494,9 +513,9 @@ function readCache(provider) {
|
|
|
494
513
|
*/
|
|
495
514
|
export async function loadCatalog(provider, opts = {}) {
|
|
496
515
|
const at = gatewayOf();
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
516
|
+
if (at) {
|
|
517
|
+
return loadGatewayCatalog(provider, at);
|
|
518
|
+
}
|
|
500
519
|
const cached = readCache(provider);
|
|
501
520
|
const fresh = cached && Date.now() - new Date(cached.fetchedAt).getTime() < CATALOG_TTL_MS
|
|
502
521
|
? cached
|
|
@@ -507,17 +526,14 @@ export async function loadCatalog(provider, opts = {}) {
|
|
|
507
526
|
entries: fresh.entries,
|
|
508
527
|
origin: 'cache',
|
|
509
528
|
fetchedAt: fresh.fetchedAt,
|
|
510
|
-
...via,
|
|
511
529
|
};
|
|
512
530
|
}
|
|
513
531
|
if (!opts.offline) {
|
|
514
532
|
try {
|
|
515
|
-
const entries =
|
|
516
|
-
? await fetchGatewayCatalog(provider, at)
|
|
517
|
-
: await fetchCatalog(provider);
|
|
533
|
+
const entries = await fetchCatalog(provider);
|
|
518
534
|
const fetchedAt = new Date().toISOString();
|
|
519
535
|
store().put(catalogKey(provider), { provider, fetchedAt, entries });
|
|
520
|
-
return { provider, entries, origin: 'live', fetchedAt
|
|
536
|
+
return { provider, entries, origin: 'live', fetchedAt };
|
|
521
537
|
}
|
|
522
538
|
catch (err) {
|
|
523
539
|
const problem = classify(err);
|
|
@@ -528,16 +544,14 @@ export async function loadCatalog(provider, opts = {}) {
|
|
|
528
544
|
origin: 'stale',
|
|
529
545
|
fetchedAt: cached.fetchedAt,
|
|
530
546
|
problem,
|
|
531
|
-
...via,
|
|
532
547
|
};
|
|
533
548
|
}
|
|
534
549
|
return {
|
|
535
550
|
provider,
|
|
536
|
-
entries:
|
|
551
|
+
entries: curated(provider),
|
|
537
552
|
origin: 'curated',
|
|
538
553
|
fetchedAt: new Date(0).toISOString(),
|
|
539
554
|
problem,
|
|
540
|
-
...via,
|
|
541
555
|
};
|
|
542
556
|
}
|
|
543
557
|
}
|
|
@@ -547,15 +561,13 @@ export async function loadCatalog(provider, opts = {}) {
|
|
|
547
561
|
entries: cached.entries,
|
|
548
562
|
origin: 'stale',
|
|
549
563
|
fetchedAt: cached.fetchedAt,
|
|
550
|
-
...via,
|
|
551
564
|
};
|
|
552
565
|
}
|
|
553
566
|
return {
|
|
554
567
|
provider,
|
|
555
|
-
entries:
|
|
568
|
+
entries: curated(provider),
|
|
556
569
|
origin: 'curated',
|
|
557
570
|
fetchedAt: new Date(0).toISOString(),
|
|
558
|
-
...via,
|
|
559
571
|
};
|
|
560
572
|
}
|
|
561
573
|
// ---------------------------------------------------------------------------
|
package/dist/commands/meta.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readProjectConfig } from '@zenera/neo';
|
|
1
|
+
import { gatewayOf, readProjectConfig } from '@zenera/neo';
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
@@ -11,7 +11,7 @@ import { copilotEventLog } from "../eventlog.js";
|
|
|
11
11
|
import { ensureHome } from "../home.js";
|
|
12
12
|
import { assertOwner, isProvider, KeyStore, PROVIDERS } from "../keys.js";
|
|
13
13
|
import { probeChat, probeModel } from "../liveness.js";
|
|
14
|
-
import { answerBox, chooseModel, DATASET_DETAILS, DATASET_SUMMARY, DATASET_USAGE, datasetProjectFlag, DEFAULT_RESUMES, defaultRef, editorFiles, FINETUNE_DETAILS, FINETUNE_SUMMARY, FINETUNE_USAGE, finetuneProjectFlag, lastSession, launch, listPrompts, loadPrompt, locate, masked, misspelledProvider, MODEL_ENV, openLog, ORDER, PROMPT_DIR, providersWarning, readMeta, recordSession, RESUME_PROMPT, resumeDelayMs, runDataset, runFinetune, sameModel, sessionModel, sessionTotals, SOURCE_LABELS, startVertexRelay, tailSpans, Tally, terminalSink, transient, wire, writeMeta, } from "../meta/index.js";
|
|
14
|
+
import { answerBox, chooseModel, DATASET_DETAILS, DATASET_SUMMARY, DATASET_USAGE, datasetProjectFlag, DEFAULT_RESUMES, defaultRef, editorFiles, FINETUNE_DETAILS, FINETUNE_SUMMARY, FINETUNE_USAGE, finetuneProjectFlag, lastSession, launch, listPrompts, loadPrompt, locate, masked, misspelledProvider, MODEL_ENV, openLog, ORDER, PROMPT_DIR, providersWarning, readMeta, recordSession, RESUME_PROMPT, resumeDelayMs, runDataset, runFinetune, sameModel, sessionModel, sessionTotals, SOURCE_LABELS, startVertexRelay, tailSpans, Tally, terminalSink, transient, wire, wireGateway, writeMeta, } from "../meta/index.js";
|
|
15
15
|
import { splitRef } from "../modelref.js";
|
|
16
16
|
import { duration } from "../narrate.js";
|
|
17
17
|
import * as Projects from "../projects.js";
|
|
@@ -554,6 +554,8 @@ async function go(ctx, values, project, prompt, promptName) {
|
|
|
554
554
|
ensureHome();
|
|
555
555
|
const store = await KeyStore.open();
|
|
556
556
|
store.materialize();
|
|
557
|
+
// After materialize: a keyring in bifrost mode is what sets the url.
|
|
558
|
+
const gateway = gatewayOf();
|
|
557
559
|
const only = values.provider ? asProvider(values.provider) : undefined;
|
|
558
560
|
const chosen = chooseModel({
|
|
559
561
|
flag: values.model,
|
|
@@ -561,7 +563,7 @@ async function go(ctx, values, project, prompt, promptName) {
|
|
|
561
563
|
env: process.env[MODEL_ENV],
|
|
562
564
|
stored: (await readMeta()).model,
|
|
563
565
|
project: projectModel(project.dir),
|
|
564
|
-
fallback: defaultRef(store, only),
|
|
566
|
+
fallback: defaultRef(store, only, gateway !== undefined),
|
|
565
567
|
});
|
|
566
568
|
if (!chosen) {
|
|
567
569
|
if (only) {
|
|
@@ -577,11 +579,11 @@ async function go(ctx, values, project, prompt, promptName) {
|
|
|
577
579
|
if (meant && !only) {
|
|
578
580
|
warn(`${chosen.ref} names no provider — did you mean ${meant}/${id}?`);
|
|
579
581
|
}
|
|
580
|
-
const entry = store.active(owner);
|
|
581
|
-
if (!entry) {
|
|
582
|
+
const entry = gateway ? undefined : store.active(owner);
|
|
583
|
+
if (!gateway && !entry) {
|
|
582
584
|
throw credentialError(`no ${owner} key`, `add one: zen key add ${owner}`);
|
|
583
585
|
}
|
|
584
|
-
const wiring = wire(store, entry, id);
|
|
586
|
+
const wiring = gateway ? wireGateway(gateway, owner, id) : wire(store, entry, id);
|
|
585
587
|
const binary = locate();
|
|
586
588
|
// Copilot cannot carry a session to another model: the resume fails on the first call.
|
|
587
589
|
const ran = values.resume ? sessionModel(values.resume) : undefined;
|
|
@@ -999,10 +1001,10 @@ async function vet(ctx, ref) {
|
|
|
999
1001
|
const { provider, id } = splitRef(ref);
|
|
1000
1002
|
const owner = provider ?? 'openai';
|
|
1001
1003
|
const store = await KeyStore.open();
|
|
1002
|
-
|
|
1004
|
+
store.materialize();
|
|
1005
|
+
if (!gatewayOf() && !store.active(owner)) {
|
|
1003
1006
|
throw credentialError(`no ${owner} key to try ${id} with`, `add one: zen key add ${owner}`);
|
|
1004
1007
|
}
|
|
1005
|
-
store.materialize();
|
|
1006
1008
|
const bar = ctx.json ? undefined : progress();
|
|
1007
1009
|
bar?.update(dim(`asking ${owner} about ${id} …`));
|
|
1008
1010
|
const probe = await probeModel({
|
|
@@ -1058,13 +1060,12 @@ async function pickModel(ctx) {
|
|
|
1058
1060
|
throw usageError('--pick needs a terminal', 'name the model instead');
|
|
1059
1061
|
}
|
|
1060
1062
|
const store = await KeyStore.open();
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
if (known.length === 0) {
|
|
1063
|
+
store.materialize();
|
|
1064
|
+
const known = store.entries.map((e) => e.provider).filter(isProvider);
|
|
1065
|
+
if (known.length === 0 && !gatewayOf()) {
|
|
1065
1066
|
throw credentialError('no keys to choose from', 'add one: zen key add openai');
|
|
1066
1067
|
}
|
|
1067
|
-
const held = [...new Set(known)];
|
|
1068
|
+
const held = gatewayOf() ? [] : [...new Set(known)];
|
|
1068
1069
|
const { browseModels } = await import("./models.js");
|
|
1069
1070
|
const chosen = await browseModels({
|
|
1070
1071
|
initial: held.length === 1 ? held[0] : undefined,
|
package/dist/keys.d.ts
CHANGED
|
@@ -202,7 +202,12 @@ export declare class KeyStore {
|
|
|
202
202
|
* since its url alone is what switches the library over.
|
|
203
203
|
*/
|
|
204
204
|
environment(only?: KeyOwner[]): Record<string, string>;
|
|
205
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* Copies the keyring's active credentials into `process.env`, the only
|
|
207
|
+
* place the library looks. Must run before anything that reads them —
|
|
208
|
+
* in `bifrost` mode this is what sets `BIFROST_BASE_URL`, so `gatewayOf()`
|
|
209
|
+
* returns undefined until it has. Returns what it set.
|
|
210
|
+
*/
|
|
206
211
|
materialize(only?: KeyOwner[]): Record<string, string>;
|
|
207
212
|
}
|
|
208
213
|
/**
|
package/dist/keys.js
CHANGED
|
@@ -482,7 +482,12 @@ export class KeyStore {
|
|
|
482
482
|
}
|
|
483
483
|
return env;
|
|
484
484
|
}
|
|
485
|
-
/**
|
|
485
|
+
/**
|
|
486
|
+
* Copies the keyring's active credentials into `process.env`, the only
|
|
487
|
+
* place the library looks. Must run before anything that reads them —
|
|
488
|
+
* in `bifrost` mode this is what sets `BIFROST_BASE_URL`, so `gatewayOf()`
|
|
489
|
+
* returns undefined until it has. Returns what it set.
|
|
490
|
+
*/
|
|
486
491
|
materialize(only) {
|
|
487
492
|
const env = this.environment(only);
|
|
488
493
|
Object.assign(process.env, env);
|
package/dist/meta/model.d.ts
CHANGED
|
@@ -21,12 +21,21 @@ export interface ModelSources {
|
|
|
21
21
|
}
|
|
22
22
|
/** Where the answer is looked for, best first. */
|
|
23
23
|
export declare const ORDER: readonly ModelSource[];
|
|
24
|
+
/**
|
|
25
|
+
* Decides which model `zen meta` runs copilot on, when it can be named in six
|
|
26
|
+
* places at once. The source comes back too, so a surprising pick can be traced
|
|
27
|
+
* ("from agents.yaml model:") instead of guessed at.
|
|
28
|
+
*/
|
|
24
29
|
export declare function chooseModel(sources: ModelSources): ModelChoice | undefined;
|
|
25
30
|
export declare const SOURCE_LABELS: Record<ModelSource, string>;
|
|
26
31
|
/** First of each row is the default; the rest are the next best. */
|
|
27
32
|
export declare const RECOMMENDED: Partial<Record<Provider, readonly string[]>>;
|
|
28
|
-
/**
|
|
29
|
-
|
|
33
|
+
/**
|
|
34
|
+
* The model `zen meta` falls back to when nothing names one, so a machine with
|
|
35
|
+
* just a key (or just a gateway, which reaches every provider) still runs.
|
|
36
|
+
* `only` is `--provider`: the recommendation for that provider, if it is held.
|
|
37
|
+
*/
|
|
38
|
+
export declare function defaultRef(store: KeyStore, only?: Provider, gateway?: boolean): string | undefined;
|
|
30
39
|
export interface MetaFile {
|
|
31
40
|
version: 1;
|
|
32
41
|
model?: string;
|
package/dist/meta/model.js
CHANGED
|
@@ -13,6 +13,11 @@ export const ORDER = [
|
|
|
13
13
|
'project',
|
|
14
14
|
'default',
|
|
15
15
|
];
|
|
16
|
+
/**
|
|
17
|
+
* Decides which model `zen meta` runs copilot on, when it can be named in six
|
|
18
|
+
* places at once. The source comes back too, so a surprising pick can be traced
|
|
19
|
+
* ("from agents.yaml model:") instead of guessed at.
|
|
20
|
+
*/
|
|
16
21
|
export function chooseModel(sources) {
|
|
17
22
|
const at = {
|
|
18
23
|
flag: sources.flag,
|
|
@@ -57,11 +62,15 @@ export const RECOMMENDED = {
|
|
|
57
62
|
};
|
|
58
63
|
/** Which provider is tried first when several are held. */
|
|
59
64
|
const PREFERENCE = ['anthropic', 'openai', 'vertex', 'google', 'openrouter'];
|
|
60
|
-
/**
|
|
61
|
-
|
|
65
|
+
/**
|
|
66
|
+
* The model `zen meta` falls back to when nothing names one, so a machine with
|
|
67
|
+
* just a key (or just a gateway, which reaches every provider) still runs.
|
|
68
|
+
* `only` is `--provider`: the recommendation for that provider, if it is held.
|
|
69
|
+
*/
|
|
70
|
+
export function defaultRef(store, only, gateway = false) {
|
|
62
71
|
for (const provider of only ? [only] : PREFERENCE) {
|
|
63
72
|
const id = RECOMMENDED[provider]?.[0];
|
|
64
|
-
if (id && store.active(provider)) {
|
|
73
|
+
if (id && (gateway || store.active(provider))) {
|
|
65
74
|
return `${provider}/${id}`;
|
|
66
75
|
}
|
|
67
76
|
}
|
package/dist/meta/wire.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Gateway } from '@zenera/neo';
|
|
1
2
|
import { type KeyEntry, type KeyStore, type Provider } from './host.ts';
|
|
2
3
|
/**
|
|
3
4
|
* Copilot offers its tools as OpenAI *custom* tools, which the completions API
|
|
@@ -35,6 +36,12 @@ export declare const RELAY_URL = "http://127.0.0.1:<relay>";
|
|
|
35
36
|
* through a GitHub account we are deliberately not using.
|
|
36
37
|
*/
|
|
37
38
|
export declare function wire(store: KeyStore, entry: KeyEntry, id: string): Wiring;
|
|
39
|
+
/**
|
|
40
|
+
* Through a gateway: one virtual key, and Bifrost's OpenAI or Anthropic drop-in,
|
|
41
|
+
* which routes on an `<upstream>/<id>` wire model. Claude speaks Anthropic
|
|
42
|
+
* wherever it is hosted; everything else goes through the OpenAI one.
|
|
43
|
+
*/
|
|
44
|
+
export declare function wireGateway(at: Gateway, provider: Provider, id: string): Wiring;
|
|
38
45
|
/** Values a `--dry-run` may print. A key is four characters and an apology. */
|
|
39
46
|
export declare function masked(env: Record<string, string>, secret: readonly string[]): string[];
|
|
40
47
|
/** Non-fatal, said once, because a competing file is a silent override. */
|
package/dist/meta/wire.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GATEWAY_UPSTREAMS } from '@zenera/neo';
|
|
1
2
|
import { randomBytes } from 'node:crypto';
|
|
2
3
|
import { existsSync } from 'node:fs';
|
|
3
4
|
import { credentialError, envOf, invokedAs, yellow, } from "./host.js";
|
|
@@ -112,6 +113,31 @@ export function wire(store, entry, id) {
|
|
|
112
113
|
}
|
|
113
114
|
return { provider, model: env.COPILOT_PROVIDER_WIRE_MODEL ?? id, env, secret, warnings };
|
|
114
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Through a gateway: one virtual key, and Bifrost's OpenAI or Anthropic drop-in,
|
|
118
|
+
* which routes on an `<upstream>/<id>` wire model. Claude speaks Anthropic
|
|
119
|
+
* wherever it is hosted; everything else goes through the OpenAI one.
|
|
120
|
+
*/
|
|
121
|
+
export function wireGateway(at, provider, id) {
|
|
122
|
+
const claude = provider === 'anthropic' || (provider === 'vertex' && vertexClaude(id));
|
|
123
|
+
const model = provider === 'vertex' ? id.replace(/^anthropic\//, '') : id;
|
|
124
|
+
const env = {
|
|
125
|
+
COPILOT_PROVIDER_TYPE: claude ? 'anthropic' : 'openai',
|
|
126
|
+
COPILOT_PROVIDER_BASE_URL: `${at.baseURL}${claude ? '/anthropic' : '/openai/v1'}`,
|
|
127
|
+
COPILOT_PROVIDER_MODEL_ID: model.replace(/^google\//, ''),
|
|
128
|
+
COPILOT_PROVIDER_WIRE_MODEL: `${GATEWAY_UPSTREAMS[provider]}/${model}`,
|
|
129
|
+
};
|
|
130
|
+
const api = wireApi(provider, model);
|
|
131
|
+
if (api) {
|
|
132
|
+
env.COPILOT_PROVIDER_WIRE_API = api;
|
|
133
|
+
}
|
|
134
|
+
const secret = [];
|
|
135
|
+
if (at.apiKey) {
|
|
136
|
+
env.COPILOT_PROVIDER_API_KEY = at.apiKey;
|
|
137
|
+
secret.push('COPILOT_PROVIDER_API_KEY');
|
|
138
|
+
}
|
|
139
|
+
return { provider, model: env.COPILOT_PROVIDER_WIRE_MODEL, env, secret, warnings: [] };
|
|
140
|
+
}
|
|
115
141
|
/** Values a `--dry-run` may print. A key is four characters and an apology. */
|
|
116
142
|
export function masked(env, secret) {
|
|
117
143
|
return Object.entries(env)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenera/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.32",
|
|
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,8 +54,8 @@
|
|
|
54
54
|
"@google/genai": "^2.30.0",
|
|
55
55
|
"@inkjs/ui": "^2.0.0",
|
|
56
56
|
"@openrouter/sdk": "^1.4.25",
|
|
57
|
-
"@zenera/neo": "^1.1.
|
|
58
|
-
"@zenera/view": "^1.1.
|
|
57
|
+
"@zenera/neo": "^1.1.32",
|
|
58
|
+
"@zenera/view": "^1.1.32",
|
|
59
59
|
"google-auth-library": "^10.0.0",
|
|
60
60
|
"ink": "^7.1.1",
|
|
61
61
|
"openai": "^6.0.0",
|