@alvera-ai/platform-sdk 0.7.2 → 0.8.0

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.
@@ -0,0 +1,789 @@
1
+ import { Command, Option } from 'commander';
2
+ import { type GlobalOpts, authedApi, bodyOption, readBody, resolveTenant, run } from './helpers.js';
3
+
4
+ export function register(program: Command): void {
5
+ // -- tenants ----------------------------------------------------------------
6
+ const tenants = program.command('tenants').description('Manage tenants');
7
+
8
+ tenants
9
+ .command('list')
10
+ .description('List tenants accessible to the current session')
11
+ .action(async () => {
12
+ await run(async () => {
13
+ const { api } = authedApi(program.opts<GlobalOpts>());
14
+ const { data } = await api.tenants.list();
15
+ return data;
16
+ });
17
+ });
18
+
19
+ // -- datalakes --------------------------------------------------------------
20
+ const datalakes = program.command('datalakes').description('Manage datalakes');
21
+
22
+ datalakes
23
+ .command('list [tenant]')
24
+ .description('List datalakes for a tenant')
25
+ .action(async (tenant: string | undefined) => {
26
+ await run(async () => {
27
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
28
+ const { data } = await api.datalakes.list(resolveTenant(tenant, resolved.tenantSlug));
29
+ return data;
30
+ });
31
+ });
32
+
33
+ datalakes
34
+ .command('get <id> [tenant]')
35
+ .description('Get a datalake by id')
36
+ .action(async (id: string, tenant: string | undefined) => {
37
+ await run(async () => {
38
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
39
+ const { data } = await api.datalakes.get(resolveTenant(tenant, resolved.tenantSlug), id);
40
+ return data;
41
+ });
42
+ });
43
+
44
+ bodyOption(datalakes.command('create [tenant]').description('Create a datalake'))
45
+ .action(async (tenant: string | undefined, opts: Record<string, string>) => {
46
+ await run(async () => {
47
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
48
+ const { data } = await api.datalakes.create(
49
+ resolveTenant(tenant, resolved.tenantSlug),
50
+ readBody(opts.body, opts.bodyFile),
51
+ );
52
+ return data;
53
+ });
54
+ });
55
+
56
+ datalakes
57
+ .command('metadata <datalake> [tenant]')
58
+ .description('Get markdown metadata for a datalake')
59
+ .action(async (datalake: string, tenant: string | undefined) => {
60
+ await run(async () => {
61
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
62
+ const { data } = await api.datalakes.metadata(
63
+ resolveTenant(tenant, resolved.tenantSlug),
64
+ datalake,
65
+ );
66
+ return data;
67
+ });
68
+ });
69
+
70
+ datalakes
71
+ .command('upload-link <datalake> <filename> [tenant]')
72
+ .description('Create a presigned upload link for a datalake')
73
+ .addOption(
74
+ new Option('--content-type <type>', 'MIME type of the file')
75
+ .choices(['application/x-ndjson', 'text/csv'])
76
+ .default('application/x-ndjson'),
77
+ )
78
+ .action(
79
+ async (
80
+ datalake: string,
81
+ filename: string,
82
+ tenant: string | undefined,
83
+ opts: Record<string, string>,
84
+ ) => {
85
+ await run(async () => {
86
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
87
+ const { data } = await api.datalakes.createUploadLink(
88
+ resolveTenant(tenant, resolved.tenantSlug),
89
+ datalake,
90
+ {
91
+ content_type: opts.contentType as 'application/x-ndjson' | 'text/csv',
92
+ filename,
93
+ },
94
+ );
95
+ return data;
96
+ });
97
+ },
98
+ );
99
+
100
+ datalakes
101
+ .command('download-link <datalake> <bucket> <key> [tenant]')
102
+ .description('Create a presigned download URL for a datalake object')
103
+ .action(
104
+ async (
105
+ datalake: string,
106
+ bucket: string,
107
+ key: string,
108
+ tenant: string | undefined,
109
+ ) => {
110
+ await run(async () => {
111
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
112
+ const { data } = await api.datalakes.createDownloadLink(
113
+ resolveTenant(tenant, resolved.tenantSlug),
114
+ datalake,
115
+ { bucket, key },
116
+ );
117
+ return data;
118
+ });
119
+ },
120
+ );
121
+
122
+ // -- data-sources -----------------------------------------------------------
123
+ const dataSources = program.command('data-sources').description('Manage data sources');
124
+
125
+ dataSources
126
+ .command('list <datalake> [tenant]')
127
+ .description('List data sources in a datalake')
128
+ .action(async (datalake: string, tenant: string | undefined) => {
129
+ await run(async () => {
130
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
131
+ const { data } = await api.dataSources.list(resolveTenant(tenant, resolved.tenantSlug), datalake);
132
+ return data;
133
+ });
134
+ });
135
+
136
+ bodyOption(dataSources.command('create <datalake> [tenant]').description('Create a data source'))
137
+ .action(async (datalake: string, tenant: string | undefined, opts: Record<string, string>) => {
138
+ await run(async () => {
139
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
140
+ const { data } = await api.dataSources.create(
141
+ resolveTenant(tenant, resolved.tenantSlug),
142
+ datalake,
143
+ readBody(opts.body, opts.bodyFile),
144
+ );
145
+ return data;
146
+ });
147
+ });
148
+
149
+ bodyOption(dataSources.command('update <datalake> <id> [tenant]').description('Update a data source'))
150
+ .action(async (datalake: string, id: string, tenant: string | undefined, opts: Record<string, string>) => {
151
+ await run(async () => {
152
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
153
+ const { data } = await api.dataSources.update(
154
+ resolveTenant(tenant, resolved.tenantSlug),
155
+ datalake,
156
+ id,
157
+ readBody(opts.body, opts.bodyFile),
158
+ );
159
+ return data;
160
+ });
161
+ });
162
+
163
+ // -- tools ------------------------------------------------------------------
164
+ const tools = program.command('tools').description('Manage tools');
165
+
166
+ tools
167
+ .command('list [tenant]')
168
+ .description('List tools for a tenant')
169
+ .action(async (tenant: string | undefined) => {
170
+ await run(async () => {
171
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
172
+ const { data } = await api.tools.list(resolveTenant(tenant, resolved.tenantSlug));
173
+ return data;
174
+ });
175
+ });
176
+
177
+ tools
178
+ .command('get <id> [tenant]')
179
+ .description('Get a tool by id')
180
+ .action(async (id: string, tenant: string | undefined) => {
181
+ await run(async () => {
182
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
183
+ const { data } = await api.tools.get(resolveTenant(tenant, resolved.tenantSlug), id);
184
+ return data;
185
+ });
186
+ });
187
+
188
+ bodyOption(tools.command('create [tenant]').description('Create a tool'))
189
+ .action(async (tenant: string | undefined, opts: Record<string, string>) => {
190
+ await run(async () => {
191
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
192
+ const { data } = await api.tools.create(
193
+ resolveTenant(tenant, resolved.tenantSlug),
194
+ readBody(opts.body, opts.bodyFile),
195
+ );
196
+ return data;
197
+ });
198
+ });
199
+
200
+ bodyOption(tools.command('update <id> [tenant]').description('Update a tool'))
201
+ .action(async (id: string, tenant: string | undefined, opts: Record<string, string>) => {
202
+ await run(async () => {
203
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
204
+ const { data } = await api.tools.update(
205
+ resolveTenant(tenant, resolved.tenantSlug),
206
+ id,
207
+ readBody(opts.body, opts.bodyFile),
208
+ );
209
+ return data;
210
+ });
211
+ });
212
+
213
+ tools
214
+ .command('delete <id> [tenant]')
215
+ .description('Delete a tool')
216
+ .action(async (id: string, tenant: string | undefined) => {
217
+ await run(async () => {
218
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
219
+ const { data } = await api.tools.delete(resolveTenant(tenant, resolved.tenantSlug), id);
220
+ return data;
221
+ });
222
+ });
223
+
224
+ // -- generic-tables ---------------------------------------------------------
225
+ const genericTables = program.command('generic-tables').description('Manage generic tables');
226
+
227
+ genericTables
228
+ .command('list <datalake> [tenant]')
229
+ .description('List generic tables in a datalake')
230
+ .action(async (datalake: string, tenant: string | undefined) => {
231
+ await run(async () => {
232
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
233
+ const { data } = await api.genericTables.list(resolveTenant(tenant, resolved.tenantSlug), datalake);
234
+ return data;
235
+ });
236
+ });
237
+
238
+ bodyOption(genericTables.command('create <datalake> [tenant]').description('Create a generic table'))
239
+ .action(async (datalake: string, tenant: string | undefined, opts: Record<string, string>) => {
240
+ await run(async () => {
241
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
242
+ const { data } = await api.genericTables.create(
243
+ resolveTenant(tenant, resolved.tenantSlug),
244
+ datalake,
245
+ readBody(opts.body, opts.bodyFile) as never,
246
+ );
247
+ return data;
248
+ });
249
+ });
250
+
251
+ // -- action-status-updaters -------------------------------------------------
252
+ const updaters = program.command('action-status-updaters').description('Manage action status updaters');
253
+
254
+ updaters
255
+ .command('list [tenant]')
256
+ .description('List action status updaters')
257
+ .action(async (tenant: string | undefined) => {
258
+ await run(async () => {
259
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
260
+ const { data } = await api.actionStatusUpdaters.list(resolveTenant(tenant, resolved.tenantSlug));
261
+ return data;
262
+ });
263
+ });
264
+
265
+ bodyOption(updaters.command('create [tenant]').description('Create an action status updater'))
266
+ .action(async (tenant: string | undefined, opts: Record<string, string>) => {
267
+ await run(async () => {
268
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
269
+ const { data } = await api.actionStatusUpdaters.create(
270
+ resolveTenant(tenant, resolved.tenantSlug),
271
+ readBody(opts.body, opts.bodyFile) as never,
272
+ );
273
+ return data;
274
+ });
275
+ });
276
+
277
+ bodyOption(updaters.command('update <id> [tenant]').description('Update an action status updater'))
278
+ .action(async (id: string, tenant: string | undefined, opts: Record<string, string>) => {
279
+ await run(async () => {
280
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
281
+ const { data } = await api.actionStatusUpdaters.update(
282
+ resolveTenant(tenant, resolved.tenantSlug),
283
+ id,
284
+ readBody(opts.body, opts.bodyFile) as never,
285
+ );
286
+ return data;
287
+ });
288
+ });
289
+
290
+ // -- ai-agents --------------------------------------------------------------
291
+ const aiAgents = program.command('ai-agents').description('Manage AI agents');
292
+
293
+ aiAgents
294
+ .command('list <datalake> [tenant]')
295
+ .description('List AI agents in a datalake')
296
+ .action(async (datalake: string, tenant: string | undefined) => {
297
+ await run(async () => {
298
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
299
+ const { data } = await api.aiAgents.list(resolveTenant(tenant, resolved.tenantSlug), datalake);
300
+ return data;
301
+ });
302
+ });
303
+
304
+ aiAgents
305
+ .command('get <datalake> <id> [tenant]')
306
+ .description('Get an AI agent by id')
307
+ .action(async (datalake: string, id: string, tenant: string | undefined) => {
308
+ await run(async () => {
309
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
310
+ const { data } = await api.aiAgents.get(resolveTenant(tenant, resolved.tenantSlug), datalake, id);
311
+ return data;
312
+ });
313
+ });
314
+
315
+ bodyOption(aiAgents.command('create <datalake> [tenant]').description('Create an AI agent'))
316
+ .action(async (datalake: string, tenant: string | undefined, opts: Record<string, string>) => {
317
+ await run(async () => {
318
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
319
+ const { data } = await api.aiAgents.create(
320
+ resolveTenant(tenant, resolved.tenantSlug),
321
+ datalake,
322
+ readBody(opts.body, opts.bodyFile) as never,
323
+ );
324
+ return data;
325
+ });
326
+ });
327
+
328
+ bodyOption(aiAgents.command('update <datalake> <id> [tenant]').description('Update an AI agent'))
329
+ .action(async (datalake: string, id: string, tenant: string | undefined, opts: Record<string, string>) => {
330
+ await run(async () => {
331
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
332
+ const { data } = await api.aiAgents.update(
333
+ resolveTenant(tenant, resolved.tenantSlug),
334
+ datalake,
335
+ id,
336
+ readBody(opts.body, opts.bodyFile) as never,
337
+ );
338
+ return data;
339
+ });
340
+ });
341
+
342
+ aiAgents
343
+ .command('delete <datalake> <id> [tenant]')
344
+ .description('Delete an AI agent')
345
+ .action(async (datalake: string, id: string, tenant: string | undefined) => {
346
+ await run(async () => {
347
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
348
+ const { data } = await api.aiAgents.delete(resolveTenant(tenant, resolved.tenantSlug), datalake, id);
349
+ return data;
350
+ });
351
+ });
352
+
353
+ // -- datasets ---------------------------------------------------------------
354
+ const datasets = program.command('datasets').description('Search datasets');
355
+
356
+ datasets
357
+ .command('search <dataset>')
358
+ .description('Search a dataset (e.g. patient, member)')
359
+ .option('--datalake-id <id>', 'restrict to a specific datalake')
360
+ .option('--data-access-mode <mode>', 'regulated or unregulated')
361
+ .option('--page <n>', 'page number', (v: string) => Number(v))
362
+ .option('--page-size <n>', 'results per page (max 100)', (v: string) => Number(v))
363
+ .action(async (dataset: string, opts: Record<string, unknown>) => {
364
+ await run(async () => {
365
+ const { api } = authedApi(program.opts<GlobalOpts>());
366
+ const { data } = await api.datasets.search(dataset, {
367
+ datalakeId: opts.datalakeId as string | undefined,
368
+ dataAccessMode: opts.dataAccessMode as 'regulated' | 'unregulated' | undefined,
369
+ page: opts.page as number | undefined,
370
+ pageSize: opts.pageSize as number | undefined,
371
+ });
372
+ return data;
373
+ });
374
+ });
375
+
376
+ datasets
377
+ .command('metadata <dataset-type>')
378
+ .description('Get markdown schema metadata for a dataset type')
379
+ .option('--datalake-id <id>', 'restrict to a specific datalake')
380
+ .option('--generic-table-id <id>', 'required when dataset-type is generic_table')
381
+ .action(async (datasetType: string, opts: Record<string, string>) => {
382
+ await run(async () => {
383
+ const { api } = authedApi(program.opts<GlobalOpts>());
384
+ const { data } = await api.datasets.metadata(datasetType, {
385
+ datalakeId: opts.datalakeId,
386
+ genericTableId: opts.genericTableId,
387
+ });
388
+ return data;
389
+ });
390
+ });
391
+
392
+ // -- mdm --------------------------------------------------------------------
393
+ const mdm = program.command('mdm').description('Master data management');
394
+
395
+ bodyOption(
396
+ mdm.command('verify <datalake> [tenant]').description('Fuzzy-verify an identity against MDM'),
397
+ )
398
+ .action(async (datalake: string, tenant: string | undefined, opts: Record<string, string>) => {
399
+ await run(async () => {
400
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
401
+ const { data } = await api.mdm.verify(
402
+ resolveTenant(tenant, resolved.tenantSlug),
403
+ datalake,
404
+ readBody(opts.body, opts.bodyFile),
405
+ );
406
+ return data;
407
+ });
408
+ });
409
+
410
+ // -- interoperability-contracts --------------------------------------------
411
+ const interop = program
412
+ .command('interoperability-contracts')
413
+ .alias('interop')
414
+ .description('Manage interoperability contracts');
415
+
416
+ interop
417
+ .command('list <datalake> [tenant]')
418
+ .description('List interoperability contracts in a datalake')
419
+ .action(async (datalake: string, tenant: string | undefined) => {
420
+ await run(async () => {
421
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
422
+ const { data } = await api.interoperabilityContracts.list(
423
+ resolveTenant(tenant, resolved.tenantSlug),
424
+ datalake,
425
+ );
426
+ return data;
427
+ });
428
+ });
429
+
430
+ interop
431
+ .command('get <datalake> <slug> [tenant]')
432
+ .description('Get a contract by slug')
433
+ .action(async (datalake: string, slug: string, tenant: string | undefined) => {
434
+ await run(async () => {
435
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
436
+ const { data } = await api.interoperabilityContracts.get(
437
+ resolveTenant(tenant, resolved.tenantSlug),
438
+ datalake,
439
+ slug,
440
+ );
441
+ return data;
442
+ });
443
+ });
444
+
445
+ bodyOption(interop.command('create <datalake> [tenant]').description('Create a contract'))
446
+ .action(async (datalake: string, tenant: string | undefined, opts: Record<string, string>) => {
447
+ await run(async () => {
448
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
449
+ const { data } = await api.interoperabilityContracts.create(
450
+ resolveTenant(tenant, resolved.tenantSlug),
451
+ datalake,
452
+ readBody(opts.body, opts.bodyFile),
453
+ );
454
+ return data;
455
+ });
456
+ });
457
+
458
+ bodyOption(interop.command('update <datalake> <slug> [tenant]').description('Update a contract'))
459
+ .action(async (datalake: string, slug: string, tenant: string | undefined, opts: Record<string, string>) => {
460
+ await run(async () => {
461
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
462
+ const { data } = await api.interoperabilityContracts.update(
463
+ resolveTenant(tenant, resolved.tenantSlug),
464
+ datalake,
465
+ slug,
466
+ readBody(opts.body, opts.bodyFile),
467
+ );
468
+ return data;
469
+ });
470
+ });
471
+
472
+ interop
473
+ .command('delete <datalake> <slug> [tenant]')
474
+ .description('Delete a contract')
475
+ .action(async (datalake: string, slug: string, tenant: string | undefined) => {
476
+ await run(async () => {
477
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
478
+ const { data } = await api.interoperabilityContracts.delete(
479
+ resolveTenant(tenant, resolved.tenantSlug),
480
+ datalake,
481
+ slug,
482
+ );
483
+ return data;
484
+ });
485
+ });
486
+
487
+ interop
488
+ .command('metadata <datalake> <slug> [tenant]')
489
+ .description('Get markdown metadata for a contract')
490
+ .action(async (datalake: string, slug: string, tenant: string | undefined) => {
491
+ await run(async () => {
492
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
493
+ const { data } = await api.interoperabilityContracts.metadata(
494
+ resolveTenant(tenant, resolved.tenantSlug),
495
+ datalake,
496
+ slug,
497
+ );
498
+ return data;
499
+ });
500
+ });
501
+
502
+ bodyOption(
503
+ interop
504
+ .command('run <datalake> <slug> [tenant]')
505
+ .description('Execute a contract against a raw source row'),
506
+ )
507
+ .action(async (datalake: string, slug: string, tenant: string | undefined, opts: Record<string, string>) => {
508
+ await run(async () => {
509
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
510
+ const { data } = await api.interoperabilityContracts.run(
511
+ resolveTenant(tenant, resolved.tenantSlug),
512
+ datalake,
513
+ slug,
514
+ readBody(opts.body, opts.bodyFile),
515
+ );
516
+ return data;
517
+ });
518
+ });
519
+
520
+ // -- connected-apps ---------------------------------------------------------
521
+ const connectedApps = program.command('connected-apps').description('Manage connected apps');
522
+
523
+ connectedApps
524
+ .command('list <datalake> [tenant]')
525
+ .description('List connected apps in a datalake')
526
+ .action(async (datalake: string, tenant: string | undefined) => {
527
+ await run(async () => {
528
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
529
+ const { data } = await api.connectedApps.list(resolveTenant(tenant, resolved.tenantSlug), datalake);
530
+ return data;
531
+ });
532
+ });
533
+
534
+ connectedApps
535
+ .command('get <datalake> <id> [tenant]')
536
+ .description('Get a connected app by id')
537
+ .action(async (datalake: string, id: string, tenant: string | undefined) => {
538
+ await run(async () => {
539
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
540
+ const { data } = await api.connectedApps.get(resolveTenant(tenant, resolved.tenantSlug), datalake, id);
541
+ return data;
542
+ });
543
+ });
544
+
545
+ bodyOption(connectedApps.command('create <datalake> [tenant]').description('Create a connected app'))
546
+ .action(async (datalake: string, tenant: string | undefined, opts: Record<string, string>) => {
547
+ await run(async () => {
548
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
549
+ const { data } = await api.connectedApps.create(
550
+ resolveTenant(tenant, resolved.tenantSlug),
551
+ datalake,
552
+ readBody(opts.body, opts.bodyFile),
553
+ );
554
+ return data;
555
+ });
556
+ });
557
+
558
+ bodyOption(connectedApps.command('update <datalake> <id> [tenant]').description('Update a connected app'))
559
+ .action(async (datalake: string, id: string, tenant: string | undefined, opts: Record<string, string>) => {
560
+ await run(async () => {
561
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
562
+ const { data } = await api.connectedApps.update(
563
+ resolveTenant(tenant, resolved.tenantSlug),
564
+ datalake,
565
+ id,
566
+ readBody(opts.body, opts.bodyFile),
567
+ );
568
+ return data;
569
+ });
570
+ });
571
+
572
+ connectedApps
573
+ .command('sync-routes <datalake> <id> [tenant]')
574
+ .description('Trigger a sync of routes for a connected app')
575
+ .action(async (datalake: string, id: string, tenant: string | undefined) => {
576
+ await run(async () => {
577
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
578
+ const { data } = await api.connectedApps.syncRoutes(
579
+ resolveTenant(tenant, resolved.tenantSlug),
580
+ datalake,
581
+ id,
582
+ );
583
+ return data;
584
+ });
585
+ });
586
+
587
+ bodyOption(
588
+ connectedApps
589
+ .command('resolve-page <slug> [tenant]')
590
+ .description('Resolve a connected app page (tenant-scoped, by slug)'),
591
+ )
592
+ .action(async (slug: string, tenant: string | undefined, opts: Record<string, string>) => {
593
+ await run(async () => {
594
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
595
+ const { data } = await api.connectedApps.resolvePage(
596
+ resolveTenant(tenant, resolved.tenantSlug),
597
+ slug,
598
+ readBody(opts.body, opts.bodyFile),
599
+ );
600
+ return data;
601
+ });
602
+ });
603
+
604
+ bodyOption(
605
+ connectedApps
606
+ .command('update-message-tracking <slug> [tenant]')
607
+ .description('Update page message tracking for a connected app'),
608
+ )
609
+ .action(async (slug: string, tenant: string | undefined, opts: Record<string, string>) => {
610
+ await run(async () => {
611
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
612
+ const { data } = await api.connectedApps.updateMessageTracking(
613
+ resolveTenant(tenant, resolved.tenantSlug),
614
+ slug,
615
+ readBody(opts.body, opts.bodyFile),
616
+ );
617
+ return data;
618
+ });
619
+ });
620
+
621
+ // -- data-activation-clients -----------------------------------------------
622
+ const dac = program.command('data-activation-clients').description('Manage data activation clients');
623
+
624
+ dac
625
+ .command('list <datalake> [tenant]')
626
+ .description('List data activation clients in a datalake')
627
+ .action(async (datalake: string, tenant: string | undefined) => {
628
+ await run(async () => {
629
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
630
+ const { data } = await api.dataActivationClients.list(
631
+ resolveTenant(tenant, resolved.tenantSlug),
632
+ datalake,
633
+ );
634
+ return data;
635
+ });
636
+ });
637
+
638
+ dac
639
+ .command('get <datalake> <slug> [tenant]')
640
+ .description('Get a data activation client by slug')
641
+ .action(async (datalake: string, slug: string, tenant: string | undefined) => {
642
+ await run(async () => {
643
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
644
+ const { data } = await api.dataActivationClients.get(
645
+ resolveTenant(tenant, resolved.tenantSlug),
646
+ datalake,
647
+ slug,
648
+ );
649
+ return data;
650
+ });
651
+ });
652
+
653
+ bodyOption(dac.command('create <datalake> [tenant]').description('Create a data activation client'))
654
+ .action(async (datalake: string, tenant: string | undefined, opts: Record<string, string>) => {
655
+ await run(async () => {
656
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
657
+ const { data } = await api.dataActivationClients.create(
658
+ resolveTenant(tenant, resolved.tenantSlug),
659
+ datalake,
660
+ readBody(opts.body, opts.bodyFile),
661
+ );
662
+ return data;
663
+ });
664
+ });
665
+
666
+ bodyOption(dac.command('update <datalake> <slug> [tenant]').description('Update a data activation client'))
667
+ .action(async (datalake: string, slug: string, tenant: string | undefined, opts: Record<string, string>) => {
668
+ await run(async () => {
669
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
670
+ const { data } = await api.dataActivationClients.update(
671
+ resolveTenant(tenant, resolved.tenantSlug),
672
+ datalake,
673
+ slug,
674
+ readBody(opts.body, opts.bodyFile),
675
+ );
676
+ return data;
677
+ });
678
+ });
679
+
680
+ dac
681
+ .command('delete <datalake> <slug> [tenant]')
682
+ .description('Delete a data activation client')
683
+ .action(async (datalake: string, slug: string, tenant: string | undefined) => {
684
+ await run(async () => {
685
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
686
+ const { data } = await api.dataActivationClients.delete(
687
+ resolveTenant(tenant, resolved.tenantSlug),
688
+ datalake,
689
+ slug,
690
+ );
691
+ return data;
692
+ });
693
+ });
694
+
695
+ dac
696
+ .command('metadata <datalake> <slug> [tenant]')
697
+ .description('Get markdown metadata for a data activation client')
698
+ .action(async (datalake: string, slug: string, tenant: string | undefined) => {
699
+ await run(async () => {
700
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
701
+ const { data } = await api.dataActivationClients.metadata(
702
+ resolveTenant(tenant, resolved.tenantSlug),
703
+ datalake,
704
+ slug,
705
+ );
706
+ return data;
707
+ });
708
+ });
709
+
710
+ bodyOption(
711
+ dac
712
+ .command('run-manually <datalake> <slug> [tenant]')
713
+ .description('Trigger a manual run (optional --body for tool_call override)'),
714
+ )
715
+ .action(async (datalake: string, slug: string, tenant: string | undefined, opts: Record<string, string>) => {
716
+ await run(async () => {
717
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
718
+ const body = opts.body || opts.bodyFile ? readBody(opts.body, opts.bodyFile) : undefined;
719
+ const { data } = await api.dataActivationClients.runManually(
720
+ resolveTenant(tenant, resolved.tenantSlug),
721
+ datalake,
722
+ slug,
723
+ body,
724
+ );
725
+ return data;
726
+ });
727
+ });
728
+
729
+ bodyOption(dac.command('ingest <datalake> <slug> [tenant]').description('Ingest a JSON payload'))
730
+ .action(async (datalake: string, slug: string, tenant: string | undefined, opts: Record<string, string>) => {
731
+ await run(async () => {
732
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
733
+ const { data } = await api.dataActivationClients.ingest(
734
+ resolveTenant(tenant, resolved.tenantSlug),
735
+ datalake,
736
+ slug,
737
+ readBody(opts.body, opts.bodyFile),
738
+ );
739
+ return data;
740
+ });
741
+ });
742
+
743
+ dac
744
+ .command('ingest-file <datalake> <slug> <key> [tenant]')
745
+ .description('Ingest a previously uploaded file (key from upload-link)')
746
+ .action(async (datalake: string, slug: string, key: string, tenant: string | undefined) => {
747
+ await run(async () => {
748
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
749
+ const { data } = await api.dataActivationClients.ingestFile(
750
+ resolveTenant(tenant, resolved.tenantSlug),
751
+ datalake,
752
+ slug,
753
+ { key },
754
+ );
755
+ return data;
756
+ });
757
+ });
758
+
759
+ dac
760
+ .command('logs <datalake> <slug> [tenant]')
761
+ .description('List execution logs for a data activation client')
762
+ .action(async (datalake: string, slug: string, tenant: string | undefined) => {
763
+ await run(async () => {
764
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
765
+ const { data } = await api.dataActivationClients.logs.list(
766
+ resolveTenant(tenant, resolved.tenantSlug),
767
+ datalake,
768
+ slug,
769
+ );
770
+ return data;
771
+ });
772
+ });
773
+
774
+ dac
775
+ .command('log-get <datalake> <slug> <id> [tenant]')
776
+ .description('Get a single execution log by id')
777
+ .action(async (datalake: string, slug: string, id: string, tenant: string | undefined) => {
778
+ await run(async () => {
779
+ const { api, resolved } = authedApi(program.opts<GlobalOpts>());
780
+ const { data } = await api.dataActivationClients.logs.get(
781
+ resolveTenant(tenant, resolved.tenantSlug),
782
+ datalake,
783
+ slug,
784
+ id,
785
+ );
786
+ return data;
787
+ });
788
+ });
789
+ }