@lifesi/genesis-cli 0.1.4 → 0.1.7

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.
@@ -49,15 +49,19 @@ export function registerHivesResources(hives, deps) {
49
49
  objects.command('download <project_id> <bucket_id> <key>').requiredOption('--output-file <path>', 'Create a new file; existing files are never overwritten').action(async (project, id, key, o) => { const response = await (await deps.client()).hives.cells.objects.download(project, id, key); const data = new Uint8Array(await response.arrayBuffer()); await writeFile(o.outputFile, data, { flag: 'wx', mode: 0o600 }); output({ saved: true, bytes: data.byteLength }); });
50
50
  cells.command('presign <project_id> <bucket_id>').requiredOption('--request-file <path>', 'Explicit GET/PUT capability request; PUT requires exact content_length').action(async (project, id, o) => output(await (await deps.client()).hives.cells.presign(project, id, await read(o.requestFile, 64 * 1024))));
51
51
  const queues = hives.command('queues').description('Buzz durable messages and possessed temporary delivery receipts');
52
+ const consumer = queues.command('consumer').description('Persisted standard-queue function binding; inspect state after an unknown mutation outcome');
53
+ for (const action of ['get', 'remove'])
54
+ consumer.command(`${action} <project_id> <queue_id>`).action(async (project, id) => output(await (await deps.client()).hives.queues.consumer[action](project, id)));
55
+ consumer.command('configure <project_id> <queue_id>').requiredOption('--request-file <path>', 'Exact existing queue delivery settings and owned active function').action(async (project, id, o) => output(await (await deps.client()).hives.queues.consumer.configure(project, id, await read(o.requestFile, 4096))));
52
56
  for (const action of ['list'])
53
57
  queues.command(`${action} <project_id>`).action(async (project) => output(await (await deps.client()).hives.queues[action](project)));
54
58
  for (const action of ['get', 'stats', 'consumers', 'pause', 'resume', 'purge', 'remove', 'dead-letter-stats', 'purge-dead-letters']) {
55
59
  const names = { 'dead-letter-stats': 'deadLetterStats', 'purge-dead-letters': 'purgeDeadLetters' };
56
60
  queues.command(`${action} <project_id> <queue_id>`).action(async (project, id) => { const client = await deps.client(); const method = action in names ? names[action] : action; output(await client.hives.queues[method](project, id)); });
57
61
  }
58
- queues.command('create <project_id>').requiredOption('--request-file <path>').action(async (project, o) => output(await (await deps.client()).hives.queues.create(project, await read(o.requestFile, 512 * 1024))));
62
+ queues.command('create <project_id>').requiredOption('--request-file <path>', 'Queue name, standard/dead_letter/fifo type and optional delivery settings').action(async (project, o) => output(await (await deps.client()).hives.queues.create(project, await read(o.requestFile, 512 * 1024))));
59
63
  queues.command('configure <project_id> <queue_id>').requiredOption('--request-file <path>').action(async (project, id, o) => output(await (await deps.client()).hives.queues.configure(project, id, await read(o.requestFile, 512 * 1024))));
60
- queues.command('send <project_id> <queue_id>').requiredOption('--request-file <path>', 'Exactly body or body_base64; decoded body 256 KiB').action(async (project, id, o) => output(await (await deps.client()).hives.queues.send(project, id, await read(o.requestFile, 512 * 1024))));
64
+ queues.command('send <project_id> <queue_id>').requiredOption('--request-file <path>', 'Exactly body or body_base64; decoded body 256 KiB. FIFO also requires message_group_id and deduplication_id').action(async (project, id, o) => output(await (await deps.client()).hives.queues.send(project, id, await read(o.requestFile, 512 * 1024))));
61
65
  queues.command('receive <project_id> <queue_id>').option('--max-messages <number>').option('--wait-seconds <number>').action(async (project, id, o) => output(await (await deps.client()).hives.queues.receive(project, id, { maxMessages: number(o.maxMessages, 1, 10), waitSeconds: number(o.waitSeconds, 0, 10) })));
62
66
  for (const action of ['ack', 'nack'])
63
67
  queues.command(`${action} <project_id> <queue_id> <message_id>`).requiredOption('--receipt-file <path>', 'JSON receiptHandle; not a credential/header/query').action(async (project, id, message, o) => { const body = await read(o.receiptFile, 4096); if (typeof body.receiptHandle !== 'string')
@@ -65,6 +69,16 @@ export function registerHivesResources(hives, deps) {
65
69
  queues.command('dead-letters <project_id> <queue_id>').option('--limit <number>').option('--offset <number>').action(async (project, id, o) => output(await (await deps.client()).hives.queues.deadLetters(project, id, { limit: number(o.limit, 1, 10), offset: number(o.offset, 0, 8192) })));
66
70
  for (const action of ['replay', 'delete-dead-letter'])
67
71
  queues.command(`${action} <project_id> <queue_id> <message_id>`).action(async (project, id, message) => output(await (await deps.client()).hives.queues[action === 'replay' ? 'replay' : 'deleteDeadLetter'](project, id, message)));
72
+ const topics = hives.command('topics').description('Owned Buzz topics; publication persists deliveries, never retries an unknown outcome');
73
+ topics.command('list <project_id>').action(async (project) => output(await (await deps.client()).hives.topics.list(project)));
74
+ for (const action of ['get', 'remove'])
75
+ topics.command(`${action} <project_id> <topic_id>`).action(async (project, id) => output(await (await deps.client()).hives.topics[action](project, id)));
76
+ topics.command('create <project_id>').requiredOption('--request-file <path>', 'JSON topic name').action(async (project, o) => output(await (await deps.client()).hives.topics.create(project, await read(o.requestFile, 4096))));
77
+ topics.command('publish <project_id> <topic_id>').requiredOption('--request-file <path>', 'Exactly body or body_base64 plus optional string attributes; no automatic retry').action(async (project, id, o) => output(await (await deps.client()).hives.topics.publish(project, id, await read(o.requestFile, 512 * 1024))));
78
+ const subscriptions = topics.command('subscriptions').description('Same-project standard queue destinations; removing a subscription retains queued messages');
79
+ subscriptions.command('list <project_id> <topic_id>').action(async (project, id) => output(await (await deps.client()).hives.topics.subscriptions.list(project, id)));
80
+ subscriptions.command('add <project_id> <topic_id> <queue_id>').action(async (project, id, queue) => output(await (await deps.client()).hives.topics.subscriptions.add(project, id, queue)));
81
+ subscriptions.command('remove <project_id> <topic_id> <subscription_id>').action(async (project, id, subscription) => output(await (await deps.client()).hives.topics.subscriptions.remove(project, id, subscription)));
68
82
  const volumes = hives.command('volumes').description('Persistent local storage; refresh saved state after an uncertain acknowledgement');
69
83
  volumes.command('list <project_id>').option('--page <number>').option('--per-page <number>').action(async (project, o) => output(await (await deps.client()).hives.volumes.list(project, { page: number(o.page, 1, 10000), per_page: number(o.perPage, 1, 100) })));
70
84
  for (const action of ['get', 'unmount', 'remove'])
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { registerRelaysEnrollment } from './relays-enrollment.js';
1
2
  import { registerBeacons } from './beacons.js';
2
3
  import { registerDials } from './dials.js';
3
4
  import { Command, CommanderError } from 'commander';
@@ -32,7 +33,7 @@ export function buildProgram(deps = {}) {
32
33
  const auth = { ...authConfig(env, f), sleep: deps.sleep };
33
34
  const program = new Command('genesis')
34
35
  .description('One CLI for every Genesis service.')
35
- .version('0.1.4')
36
+ .version('0.1.7')
36
37
  .option('--json', 'machine-readable JSON output')
37
38
  .option('--api-key <key>', 'use this API key (default: GENESIS_API_KEY, then your `genesis login`)')
38
39
  .option('--base-url <url>', 'gateway URL (default: GENESIS_BASE_URL or https://console.life.one/api)')
@@ -48,7 +49,7 @@ export function buildProgram(deps = {}) {
48
49
  const opts = {
49
50
  apiKey: o.apiKey ?? env.GENESIS_API_KEY, token: env.GENESIS_TOKEN,
50
51
  baseUrl: o.baseUrl ?? env.GENESIS_BASE_URL, routing: o.direct || env.GENESIS_ROUTING === 'direct' ? 'direct' : 'gateway',
51
- fetch: f, userAgent: 'genesis-cli/0.1.4',
52
+ fetch: f, userAgent: 'genesis-cli/0.1.7',
52
53
  credentials: store ? savedLoginProvider(auth, store) : undefined,
53
54
  };
54
55
  return new Genesis(hivesTransport ? { ...opts, fetch: createHivesNodeTransport(opts, deps.signal) } : opts);
@@ -83,6 +84,16 @@ export function buildProgram(deps = {}) {
83
84
  silosProjects.command('get <project_id>').action(async (id) => out.log(JSON.stringify(await (await client()).silos.projects.get(id), null, 2)));
84
85
  silosProjects.command('create').requiredOption('--name <name>', 'Project name').requiredOption('--slug <slug>', 'Unique project slug')
85
86
  .action(async (options) => out.log(JSON.stringify(await (await client()).silos.projects.create({ name: options.name, slug: options.slug }), null, 2)));
87
+ const owner = program.command('blinds').description('Blinds credential custody').command('owner-enrollment')
88
+ .description('Original-human enrollment only; preserve operation and locator IDs after unknown outcomes');
89
+ for (const [action, operation] of Object.entries({ reserve: 'blinds_ownerReserve', sign: 'blinds_ownerSign', attach: 'blinds_ownerAttach', 'p256-ensure': 'blinds_ownerP256Ensure' })) {
90
+ owner.command(action).requiredOption('--body-file <path>', 'Closed JSON request, up to 2 KiB; original human login required')
91
+ .action(async (options) => {
92
+ const body = await readFunctionJson(options.bodyFile, 2048);
93
+ const result = await (await client()).request(operation, { body }, { signal: deps.signal });
94
+ out.log(JSON.stringify(result, null, 2));
95
+ });
96
+ }
86
97
  registerDials(program, { client, orgId, emit });
87
98
  // ---- auth ------------------------------------------------------------
88
99
  program.command('login').description('Sign in with LifeID in your browser').option('--no-browser', 'just print the link')
@@ -168,6 +179,11 @@ export function buildProgram(deps = {}) {
168
179
  });
169
180
  // ---- foundry ---------------------------------------------------------
170
181
  const foundry = program.command('foundry').description('Foundry: models and inference');
182
+ const foundryBilling = foundry.command('billing').description('Current organization’s native TEST billing; original LifeID human login required');
183
+ foundryBilling.command('profile').action(async () => out.log(JSON.stringify(await (await client()).foundry.billing.profile({ signal: deps.signal }), null, 2)));
184
+ foundryBilling.command('ensure').requiredOption('--operation-key <key>', 'Persisted operation key; reconcile unknown outcomes before retrying').action(async (o) => out.log(JSON.stringify(await (await client()).foundry.billing.ensureProfile(o.operationKey, { signal: deps.signal }), null, 2)));
185
+ foundryBilling.command('checkout').requiredOption('--purchase-key <key>', 'Persisted purchase key; server controls the TEST amount').action(async (o) => out.log(JSON.stringify(await (await client()).foundry.billing.checkoutCredits(o.purchaseKey, { signal: deps.signal }), null, 2)));
186
+ foundryBilling.command('balance').action(async () => out.log(JSON.stringify(await (await client()).foundry.billing.creditBalance({ signal: deps.signal }), null, 2)));
171
187
  foundry.command('models').action(async () => {
172
188
  const r = await (await client()).foundry.models.list();
173
189
  const rows = listOf(r).map((m) => ({ id: m.id, owned_by: m.owned_by ?? m.provider ?? '' }));
@@ -440,6 +456,7 @@ export function buildProgram(deps = {}) {
440
456
  });
441
457
  // ---- relays ----------------------------------------------------------
442
458
  const relays = program.command('relays').description('Relays: DNS zones and records');
459
+ registerRelaysEnrollment(relays, client, emit);
443
460
  relays.command('zones').description('List DNS zones').option('--search <q>').action(async (o) => {
444
461
  const r = await (await client()).relays.zones.list(o.search ? { search: o.search } : {});
445
462
  emit(r, () => table((r.zones ?? []), ['name', 'type', 'record_count', 'dnssec_enabled', 'status']));
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import type { Genesis } from '@lifesi/genesis';
3
+ export declare function registerRelaysEnrollment(relays: Command, client: () => Promise<Genesis>, emit: (value: unknown, pretty: () => string) => void): void;
@@ -0,0 +1,7 @@
1
+ export function registerRelaysEnrollment(relays, client, emit) {
2
+ const enrollment = relays.command('enrollment').description('Explicit empty Relays account for the current verified human selection');
3
+ for (const action of ['get', 'activate'])
4
+ enrollment.command(action).allowExcessArguments(false)
5
+ .description(action === 'get' ? 'Read status without creating an account' : 'Activate once; read status after any unconfirmed response')
6
+ .action(async () => { const value = await (await client()).relays.enrollment[action](); emit(value, () => JSON.stringify(value, null, 2)); });
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifesi/genesis-cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/l1felabs/genesis-api.git",
@@ -18,7 +18,7 @@
18
18
  "dependencies": {
19
19
  "commander": "^14.0.0",
20
20
  "undici": "6.29.0",
21
- "@lifesi/genesis": "0.1.4"
21
+ "@lifesi/genesis": "0.1.7"
22
22
  },
23
23
  "optionalDependencies": {
24
24
  "@napi-rs/keyring": "^1.2.0"