openzoo 0.51.4 → 0.51.6

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 (55) hide show
  1. package/README.md +12 -1
  2. package/bin/openzoo.js +21 -46
  3. package/lib/chatgpt-install.js +106 -0
  4. package/lib/chatgpt.js +108 -90
  5. package/lib/config.js +34 -0
  6. package/lib/modelcommand.js +443 -0
  7. package/lib/pay.js +60 -4
  8. package/lib/proxy.js +39 -0
  9. package/package.json +4 -7
  10. package/transmute/README.md +0 -385
  11. package/transmute/bin/openzoo-transmute.js +0 -7
  12. package/transmute/docs/OPENZOO_CLI_PATCH.md +0 -139
  13. package/transmute/docs/VERCEL_TO_SOLANA.md +0 -381
  14. package/transmute/lib/build.js +0 -381
  15. package/transmute/lib/cli.js +0 -293
  16. package/transmute/lib/compile/bytecode.js +0 -591
  17. package/transmute/lib/compile/hostids.js +0 -11
  18. package/transmute/lib/compile/index.js +0 -159
  19. package/transmute/lib/compile/ir.js +0 -1634
  20. package/transmute/lib/compile/parse.js +0 -753
  21. package/transmute/lib/compile/rust.js +0 -781
  22. package/transmute/lib/deploy.js +0 -357
  23. package/transmute/lib/eligibility.js +0 -211
  24. package/transmute/lib/gateway.js +0 -710
  25. package/transmute/lib/hub.js +0 -290
  26. package/transmute/lib/solana.js +0 -387
  27. package/transmute/lib/vercel.js +0 -296
  28. package/transmute/lib/wallet.js +0 -41
  29. package/transmute/lib/wire.js +0 -208
  30. package/transmute/prebuilt/zoo_vm.v0.so +0 -0
  31. package/transmute/runtime/zoo-host/Cargo.lock +0 -588
  32. package/transmute/runtime/zoo-host/Cargo.toml +0 -30
  33. package/transmute/runtime/zoo-host/examples/vmrun.rs +0 -43
  34. package/transmute/runtime/zoo-host/src/assets.rs +0 -214
  35. package/transmute/runtime/zoo-host/src/ctx.rs +0 -350
  36. package/transmute/runtime/zoo-host/src/fmt.rs +0 -188
  37. package/transmute/runtime/zoo-host/src/helpers.rs +0 -245
  38. package/transmute/runtime/zoo-host/src/json.rs +0 -263
  39. package/transmute/runtime/zoo-host/src/kv.rs +0 -206
  40. package/transmute/runtime/zoo-host/src/lib.rs +0 -137
  41. package/transmute/runtime/zoo-host/src/site.rs +0 -94
  42. package/transmute/runtime/zoo-host/src/val.rs +0 -1050
  43. package/transmute/runtime/zoo-host/src/vm.rs +0 -902
  44. package/transmute/runtime/zoo-host/src/wire.rs +0 -239
  45. package/transmute/runtime/zoo-vm/Cargo.lock +0 -596
  46. package/transmute/runtime/zoo-vm/Cargo.toml +0 -23
  47. package/transmute/runtime/zoo-vm/src/lib.rs +0 -92
  48. package/transmute/site/.env.production +0 -2
  49. package/transmute/site/api/echo.js +0 -10
  50. package/transmute/site/api/hello.js +0 -12
  51. package/transmute/site/api/hits.js +0 -13
  52. package/transmute/site/api/time.js +0 -5
  53. package/transmute/site/package.json +0 -6
  54. package/transmute/site/public/app.js +0 -16
  55. package/transmute/site/public/index.html +0 -96
@@ -1,293 +0,0 @@
1
- // The openzoo-transmute command line.
2
- //
3
- // The openzoo package can mount these subcommands in its own bin without
4
- // duplicating anything:
5
- //
6
- // case 'build': case 'deploy': case 'serve':
7
- // await (await import('openzoo-transmute/lib/cli.js')).run(process.argv.slice(2));
8
- //
9
- // `run(argv)` resolves to the exit code (0 = ok) and also sets
10
- // `process.exitCode` when non-zero; it never calls `process.exit` itself so a
11
- // `serve` keeps the event loop (and the http server) alive.
12
- import fs from 'node:fs';
13
- import path from 'node:path';
14
- import { PublicKey } from '@solana/web3.js';
15
- import { readDeployment } from './vercel.js';
16
- import { build } from './build.js';
17
- import { deploy, deployRuntime, resolveOutDir, clusterLabel } from './deploy.js';
18
- import { startGateway, DEFAULT_PORT } from './gateway.js';
19
- import { startHub, DEFAULT_HUB_PORT } from './hub.js';
20
- import { connect, getProgramInfo, getSiteInfo, readManifest } from './solana.js';
21
- import { loadWallet, rpcUrl } from './wallet.js';
22
- import { MANIFEST_PATH } from './wire.js';
23
-
24
- export const USAGE = `openzoo-transmute — Vercel app → Solana program + asset accounts
25
-
26
- usage:
27
- openzoo-transmute build [dir] [--target shared|program] [--out .zoo-out] [--name <crate>] [--arch v0|v3] [--cluster <c>] [--skip-cargo]
28
- --target shared (default): bytecode for the shared zoo-vm runtime — a site is data accounts only (≈0.05–0.1 SOL)
29
- --target program: your own Pinocchio program per site (≈1 SOL+)
30
- openzoo-transmute deploy [dir|outDir] [--cluster mainnet|devnet|localnet|<url>] [--keypair <path>] [--yes] [--runtime <zoo-vm id>]
31
- [--program <id>] [--concurrency 4] [--skip-assets] [--force] [--headroom 1.5]
32
- openzoo-transmute serve <siteId|programId> [--runtime <zoo-vm id>] [--cluster <c>] [--port ${DEFAULT_PORT}] [--keypair <path>] [--host 127.0.0.1] [--quiet]
33
- openzoo-transmute runtime deploy [--cluster <c>] [--keypair <path>] [--yes] [--program-keypair zoo-vm-keypair.json] [--so <path>]
34
- deploy (or upgrade) the shared zoo-vm runtime once per cluster
35
- openzoo-transmute runtime status <zoo-vm id> [--cluster <c>]
36
- openzoo-transmute hub [--cluster mainnet] [--port 8080] [--host 0.0.0.0] [--public-url <https://…>]
37
- hosted explorer for EVERY program on the cluster (/s/<programId>), read-only
38
- openzoo-transmute inspect [dir] print the Vercel model + eligibility report
39
- openzoo-transmute status <programId> [--cluster <c>]
40
- openzoo-transmute help
41
-
42
- clusters: mainnet (default, needs --yes to deploy), devnet, testnet, localnet, or an RPC URL.
43
- env: OPENZOO_CLUSTER, OPENZOO_RPC (mainnet RPC), OPENZOO_KEYPAIR / OPENZOO_WALLET (signer), OPENZOO_VM_PROGRAM (shared runtime id).
44
- `;
45
-
46
- /** `--k v`, `--k=v`, `--flag`, `--no-flag`; everything else is positional. */
47
- export function parseArgs(argv) {
48
- const flags = {};
49
- const positionals = [];
50
- const boolFlags = new Set(['yes', 'skip-cargo', 'skip-assets', 'force', 'quiet', 'help', 'json', 'version']);
51
- for (let i = 0; i < argv.length; i++) {
52
- const a = argv[i];
53
- if (a === '--') { positionals.push(...argv.slice(i + 1)); break; }
54
- if (a.startsWith('--')) {
55
- const eq = a.indexOf('=');
56
- let key = eq >= 0 ? a.slice(2, eq) : a.slice(2);
57
- let val;
58
- if (eq >= 0) val = a.slice(eq + 1);
59
- else if (key.startsWith('no-')) { key = key.slice(3); val = false; }
60
- else if (boolFlags.has(key) || i + 1 >= argv.length || argv[i + 1].startsWith('--')) val = true;
61
- else val = argv[++i];
62
- flags[key] = val;
63
- flags[key.replace(/-([a-z])/g, (_, c) => c.toUpperCase())] = val;
64
- } else if (a === '-h') flags.help = true;
65
- else if (a === '-y') flags.yes = true;
66
- else positionals.push(a);
67
- }
68
- return { cmd: positionals[0] || 'help', positionals: positionals.slice(1), flags };
69
- }
70
-
71
- function fmtBytes(n) { return n == null ? '?' : n.toLocaleString() + ' B'; }
72
-
73
- export function inspectText(deployment, report = null) {
74
- const lines = [];
75
- lines.push(`${deployment.root}`);
76
- lines.push(`source: ${deployment.source}${deployment.framework ? ` · framework: ${deployment.framework}` : ''} · static dir: ${deployment.staticDir ? path.relative(deployment.root, deployment.staticDir) || '.' : '-'}`);
77
- for (const n of deployment.notes) lines.push(`note: ${n}`);
78
- lines.push('');
79
- lines.push(`functions (${deployment.functions.length}):`);
80
- const inel = new Map((report?.ineligible || []).map((i) => [i.name, i]));
81
- const elig = new Set((report?.eligible || []).map((e) => (typeof e === 'string' ? e : e.name)));
82
- for (const f of deployment.functions) {
83
- const mark = report ? (inel.has(f.name) ? '✗' : elig.has(f.name) ? '✓' : '?') : ' ';
84
- const meth = f.methods ? f.methods.join(',') : 'any';
85
- lines.push(` ${mark} ${f.routePath.padEnd(32)} ${f.style.padEnd(12)} ${f.runtime.padEnd(11)} ${String(f.maxDuration + 's').padEnd(5)} ${String(f.memory + 'MB').padEnd(7)} ${meth}${f.params.length ? ` params=${f.params.join(',')}` : ''}${f.middleware ? ' middleware' : ''}${f.prerender ? ' ISR' : ''}`);
86
- lines.push(` ${f.sourceFile ? path.relative(deployment.root, f.sourceFile) : '(no source)'}${Object.keys(f.environment || {}).length ? ` env=${Object.keys(f.environment).join(',')}` : ''}`);
87
- const r = inel.get(f.name);
88
- if (r) lines.push(` ineligible: ${r.reason}${r.line ? ` (line ${r.line})` : ''}`);
89
- }
90
- if (deployment.crons.length) { lines.push(''); lines.push(`crons (${deployment.crons.length}) — not transmuted, Solana has no scheduler:`); for (const c of deployment.crons) lines.push(` ${c.schedule || '?'} ${c.path || ''}`); }
91
- lines.push('');
92
- const total = deployment.staticFiles.reduce((n, f) => n + f.size, 0);
93
- lines.push(`static files (${deployment.staticFiles.length}, ${fmtBytes(total)}):`);
94
- for (const f of deployment.staticFiles.slice(0, 60)) lines.push(` ${f.path.padEnd(48)} ${f.contentType.padEnd(32)} ${fmtBytes(f.size)}`);
95
- if (deployment.staticFiles.length > 60) lines.push(` … ${deployment.staticFiles.length - 60} more`);
96
- if (report) {
97
- lines.push('');
98
- lines.push(`eligibility: ${report.eligible.length} eligible, ${report.ineligible.length} ineligible, ${report.warnings.length} warning(s)`);
99
- for (const w of report.warnings) lines.push(` ! ${typeof w === 'string' ? w : w.message || JSON.stringify(w)}`);
100
- }
101
- const routes = deployment.config?.routes || [];
102
- if (routes.length) {
103
- lines.push('');
104
- lines.push(`routes (${routes.length}):`);
105
- for (const r of routes) lines.push(' ' + (r.handle ? `[handle: ${r.handle}]` : `${r.src} → ${r.dest || (r.status ? `status ${r.status}` : '(headers)')}${r.continue ? ' (continue)' : ''}`));
106
- }
107
- return lines.join('\n');
108
- }
109
-
110
- async function tryTransmute(deployment) {
111
- try {
112
- const mod = await import('./compile/index.js');
113
- if (typeof mod.transmute !== 'function') return null;
114
- const r = await mod.transmute(deployment, { name: 'inspect', dryRun: true });
115
- return r?.report || null;
116
- } catch (e) {
117
- if (e?.code === 'ERR_MODULE_NOT_FOUND') return null;
118
- return { eligible: [], ineligible: [], warnings: [`compiler failed: ${e?.message || e}`] };
119
- }
120
- }
121
-
122
- export const DEFAULT_TARGET = 'shared';
123
-
124
- /** `--runtime` is the zoo-vm program id (shared) — or, for `--target program`, a zoo-host checkout path. */
125
- function runtimeFlag(f) {
126
- const v = f.runtime;
127
- if (typeof v !== 'string') return { runtime: process.env.OPENZOO_VM_PROGRAM || null, runtimePath: f.runtimePath || undefined };
128
- if (fs.existsSync(v) && fs.existsSync(path.join(v, 'Cargo.toml'))) return { runtime: process.env.OPENZOO_VM_PROGRAM || null, runtimePath: v };
129
- new PublicKey(v);
130
- return { runtime: v, runtimePath: f.runtimePath || undefined };
131
- }
132
-
133
- async function cmdBuild(p, f, log) {
134
- const target = f.target || process.env.OPENZOO_TARGET || DEFAULT_TARGET;
135
- if (!['shared', 'program'].includes(target)) throw new Error(`--target must be shared or program (got ${target})`);
136
- const { runtime, runtimePath } = runtimeFlag(f);
137
- const r = await build(p[0] || '.', { out: f.out, name: f.name, arch: f.arch, cluster: f.cluster, target, runtime, runtimePath, skipCargo: !!f.skipCargo, log });
138
- if (f.json) log(JSON.stringify({ outDir: r.outDir, target: r.target || 'program', soPath: r.soPath, codePath: r.codePath || null, codeSize: r.codeSize || null, arch: r.arch, report: r.report, costEstimate: { sol: r.costEstimate.sol, totalSol: r.costEstimate.totalSol, source: r.costEstimate.source } }, null, 2));
139
- return r.report.ineligible.length && !r.report.eligible.length && r.manifest.routes.length === 0 && r.deployment.functions.length ? 2 : 0;
140
- }
141
-
142
- async function cmdDeploy(p, f, log) {
143
- const { runtime } = runtimeFlag(f);
144
- const r = await deploy({ outDir: p[0] || '.', cluster: f.cluster, keypair: f.keypair, programId: f.program, runtime, yes: !!f.yes, concurrency: f.concurrency ? Number(f.concurrency) : undefined, skipAssets: !!f.skipAssets, force: !!f.force, headroom: f.headroom, log });
145
- if (f.json) log(JSON.stringify(r, null, 2));
146
- return 0;
147
- }
148
-
149
- async function cmdServe(p, f, log) {
150
- let programId = p[0];
151
- let { runtime } = runtimeFlag(f);
152
- if (!programId) {
153
- // Fall back to the last deploy in ./ or ./.zoo-out.
154
- try {
155
- const d = JSON.parse(fs.readFileSync(path.join(resolveOutDir('.'), '.zoo', 'deploy.json'), 'utf8'));
156
- programId = d.target === 'shared' ? d.site : d.programId;
157
- if (d.target === 'shared' && !runtime) runtime = d.runtime;
158
- } catch { /* none */ }
159
- if (!programId) throw new Error('usage: serve <siteId|programId> [--runtime <zoo-vm id>] (no .zoo/deploy.json found to infer it from)');
160
- }
161
- new PublicKey(programId); // validate
162
- // Shared runtime: the positional is the site id, the program is zoo-vm.
163
- let site = null;
164
- if (runtime) { site = programId; programId = runtime; }
165
- let keypair = null, walletPath = null;
166
- if (f.keypair !== false) {
167
- try { const w = loadWallet({ keypair: typeof f.keypair === 'string' ? f.keypair : undefined }); keypair = w.keypair; walletPath = w.path; }
168
- catch (e) { if (typeof f.keypair === 'string') throw e; log(`no wallet found (${String(e.message).split(';')[0]}); mutating requests will answer 402`); }
169
- }
170
- const port = f.port != null ? Number(f.port) : DEFAULT_PORT;
171
- const host = f.host || '127.0.0.1';
172
- if (keypair && !/^(127\.0\.0\.1|localhost|::1|\[::1\])$/.test(host)) log(`warning: binding ${host} with a signer: anyone who can reach this gateway can send transactions paid by ${keypair.publicKey.toBase58()}; use --no-keypair unless that is intended`);
173
- const gw = await startGateway({ programId, site, cluster: f.cluster, port, host, keypair, log, quiet: !!f.quiet });
174
- const m = gw.state.manifest;
175
- log(`openzoo-transmute gateway → ${gw.url}/ (explorer ${gw.url}/.zoo/, manifest ${gw.url}${MANIFEST_PATH})`);
176
- log(`${site ? `site ${site} on runtime ${programId}` : `program ${programId}`} on ${gw.state.cluster} · ${m.routes.length} function(s), ${m.static ? m.static.length : '?'} asset(s) · signer ${keypair ? keypair.publicKey.toBase58() + (walletPath ? ` (${walletPath})` : '') : 'none (reads only)'}`);
177
- for (const r of m.routes) log(` ${(r.methods && r.methods.length ? r.methods.join('|') : 'ANY').padEnd(16)} ${r.routePath}`);
178
- const stop = () => gw.close().then(() => process.exit(0));
179
- process.once('SIGINT', stop);
180
- process.once('SIGTERM', stop);
181
- return 0;
182
- }
183
-
184
- async function cmdInspect(p, f, log) {
185
- const deployment = readDeployment(p[0] || '.');
186
- const report = await tryTransmute(deployment);
187
- if (f.json) log(JSON.stringify({ ...deployment, report }, null, 2));
188
- else {
189
- log(inspectText(deployment, report));
190
- if (!report) log('\n(compiler not available: eligibility not checked)');
191
- }
192
- return 0;
193
- }
194
-
195
- async function cmdStatus(p, f, log) {
196
- if (!p[0]) throw new Error('usage: status <siteId|programId> [--runtime <zoo-vm id>] [--cluster <c>]');
197
- const { runtime } = runtimeFlag(f);
198
- const rpc = rpcUrl(f.cluster);
199
- const connection = connect(rpc);
200
- if (runtime) {
201
- const site = new PublicKey(p[0]);
202
- const [info, manifest] = await Promise.all([getSiteInfo(connection, new PublicKey(runtime), site), readManifest(connection, new PublicKey(runtime), site).catch(() => null)]);
203
- const out = { site: site.toBase58(), runtime, cluster: clusterLabel(f.cluster), rpc: rpc.replace(/\?.*$/, ''), exists: info.exists, authority: info.authority ? info.authority.toBase58() : null, account: info.pda.toBase58(), manifest: manifest ? { name: manifest.name, routes: manifest.routes?.length ?? 0, static: manifest.static?.length ?? 0, deployedAt: manifest.deployedAt } : null };
204
- if (f.json) { log(JSON.stringify(out, null, 2)); return info.exists ? 0 : 1; }
205
- log(`site ${out.site} on runtime ${runtime} (${out.cluster})`);
206
- if (!info.exists) { log('status NOT DEPLOYED'); return 1; }
207
- log(`authority ${out.authority}`);
208
- log(`account ${out.account}`);
209
- if (manifest) { log(`manifest ${manifest.name || ''} · ${out.manifest.routes} function(s), ${out.manifest.static} asset(s) · deployed ${manifest.deployedAt || '?'}`); for (const r of manifest.routes || []) log(` ${(r.methods && r.methods.length ? r.methods.join('|') : 'ANY').padEnd(16)} ${r.routePath}`); }
210
- else log(`manifest none at ${MANIFEST_PATH}`);
211
- return 0;
212
- }
213
- const programId = new PublicKey(p[0]);
214
- const [info, slot, manifest] = await Promise.all([getProgramInfo(connection, programId), connection.getSlot('confirmed'), readManifest(connection, programId).catch(() => null)]);
215
- const out = {
216
- programId: programId.toBase58(), cluster: clusterLabel(f.cluster), rpc: rpc.replace(/\?.*$/, ''), slot,
217
- exists: info.exists, executable: info.executable ?? null, authority: info.authority ? info.authority.toBase58() : null,
218
- deploySlot: info.slot, maxDataLen: info.maxDataLen, programData: info.programData.toBase58(),
219
- manifest: manifest ? { name: manifest.name, framework: manifest.framework, routes: manifest.routes?.length ?? 0, static: manifest.static?.length ?? 0, deployedAt: manifest.deployedAt, arch: manifest.arch } : null,
220
- };
221
- if (f.json) { log(JSON.stringify(out, null, 2)); return info.exists ? 0 : 1; }
222
- log(`program ${out.programId} on ${out.cluster} (${out.rpc}) @ slot ${slot}`);
223
- if (!info.exists) { log('status NOT DEPLOYED'); return 1; }
224
- log(`status deployed at slot ${out.deploySlot}${out.executable === false ? ' (not executable!)' : ''}`);
225
- log(`authority ${out.authority || 'none (immutable)'}`);
226
- log(`programData ${out.programData} (max ${out.maxDataLen?.toLocaleString()} B)`);
227
- if (manifest) {
228
- log(`manifest ${manifest.name || ''} ${manifest.framework || ''} · ${out.manifest.routes} function(s), ${out.manifest.static} asset(s) · deployed ${manifest.deployedAt || '?'}${manifest.arch ? ` (${manifest.arch})` : ''}`);
229
- for (const r of manifest.routes || []) log(` ${(r.methods && r.methods.length ? r.methods.join('|') : 'ANY').padEnd(16)} ${r.routePath}`);
230
- } else log(`manifest none at ${MANIFEST_PATH}`);
231
- return 0;
232
- }
233
-
234
- /**
235
- * Run the CLI. Returns the exit code; prints errors to stderr.
236
- * @param {string[]} argv arguments after the program name
237
- * @param {{log?:Function, error?:Function}} io
238
- */
239
- async function cmdHub(p, f, log) {
240
- // The hosted explorer: every program on the cluster from one public host,
241
- // read-only by default (a public signer would be a drain). --keypair opts in.
242
- const cluster = f.cluster || process.env.OPENZOO_CLUSTER || 'mainnet';
243
- // A signer makes the demo real (visitors can POST). It is bounded: a per-IP
244
- // rate limit and a daily SOL budget (OPENZOO_HUB_WRITE_BUDGET_SOL), so a
245
- // public hub can sign without being drained. Keypair from --keypair or the
246
- // OPENZOO_HUB_KEYPAIR secret (JSON byte array).
247
- let keypair = null;
248
- if (typeof f.keypair === 'string') keypair = loadWallet({ keypair: f.keypair }).keypair;
249
- else if (process.env.OPENZOO_HUB_KEYPAIR) { const { Keypair } = await import('@solana/web3.js'); keypair = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(process.env.OPENZOO_HUB_KEYPAIR))); }
250
- if (keypair) log(`hub signs writes with ${keypair.publicKey.toBase58()} (budget ${process.env.OPENZOO_HUB_WRITE_BUDGET_SOL || '0.05'} SOL/day, ${process.env.OPENZOO_HUB_WRITES_PER_MIN || '3'} writes/min/ip)`);
251
- const port = f.port != null ? Number(f.port) : Number(process.env.PORT || DEFAULT_HUB_PORT);
252
- const h = await startHub({ cluster, port, host: f.host || '0.0.0.0', keypair, log, quiet: !!f.quiet, publicUrl: f.publicUrl || process.env.OPENZOO_HUB_URL || null, maxSites: f.maxSites ? Number(f.maxSites) : undefined });
253
- log(`openzoo hub → ${h.url}/.hub (cluster ${cluster}; sites at ${h.url}/s/<programId>)`);
254
- const stop = () => h.close().then(() => process.exit(0));
255
- process.once('SIGINT', stop);
256
- process.once('SIGTERM', stop);
257
- return 0;
258
- }
259
-
260
- async function cmdRuntime(p, f, log) {
261
- const sub = p[0];
262
- if (sub === 'deploy') {
263
- const r = await deployRuntime({ cluster: f.cluster, keypair: f.keypair, yes: !!f.yes, programKeypair: f.programKeypair, so: f.so, headroom: f.headroom, log });
264
- if (f.json) log(JSON.stringify(r, null, 2));
265
- return 0;
266
- }
267
- if (sub === 'status') {
268
- if (!p[1]) throw new Error('usage: runtime status <zoo-vm id> [--cluster <c>]');
269
- return cmdStatus([p[1]], { ...f, runtime: undefined }, log);
270
- }
271
- throw new Error('usage: runtime deploy|status');
272
- }
273
-
274
- export async function run(argv = process.argv.slice(2), io = {}) {
275
- const log = io.log ?? console.log;
276
- const error = io.error ?? console.error;
277
- const { cmd, positionals, flags } = parseArgs(argv);
278
- if (flags.version) { log(JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version); return 0; }
279
- if (flags.help || cmd === 'help' || cmd === '--help') { log(USAGE); return 0; }
280
- const commands = { build: cmdBuild, deploy: cmdDeploy, serve: cmdServe, inspect: cmdInspect, status: cmdStatus, hub: cmdHub, runtime: cmdRuntime };
281
- const fn = commands[cmd];
282
- if (!fn) { error(`unknown command: ${cmd}\n`); error(USAGE); process.exitCode = 1; return 1; }
283
- try {
284
- const code = (await fn(positionals, flags, log)) || 0;
285
- if (code) process.exitCode = code;
286
- return code;
287
- } catch (e) {
288
- error(`error: ${e?.message || e}`);
289
- if (process.env.OPENZOO_DEBUG && e?.stack) error(e.stack);
290
- process.exitCode = 1;
291
- return 1;
292
- }
293
- }