coaiajs 0.3.2 → 0.4.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.
Files changed (48) hide show
  1. package/README.md +12 -4
  2. package/agents/custom_gpt/ceremony.yml +3341 -0
  3. package/dist/mcp/config.d.ts.map +1 -1
  4. package/dist/mcp/config.js +0 -2
  5. package/dist/mcp/config.js.map +1 -1
  6. package/dist/mcp/server.js +3 -8
  7. package/dist/mcp/server.js.map +1 -1
  8. package/dist/mcp/tools/coaiapy-tools.d.ts.map +1 -1
  9. package/dist/mcp/tools/coaiapy-tools.js +3 -18
  10. package/dist/mcp/tools/coaiapy-tools.js.map +1 -1
  11. package/dist/src/cli.js +169 -98
  12. package/dist/src/cli.js.map +1 -1
  13. package/dist/src/langfuse/client.d.ts +44 -11
  14. package/dist/src/langfuse/client.d.ts.map +1 -1
  15. package/dist/src/langfuse/client.js +171 -8
  16. package/dist/src/langfuse/client.js.map +1 -1
  17. package/dist/src/langfuse/comments.js +2 -2
  18. package/dist/src/langfuse/comments.js.map +1 -1
  19. package/dist/src/langfuse/index.d.ts +5 -3
  20. package/dist/src/langfuse/index.d.ts.map +1 -1
  21. package/dist/src/langfuse/index.js +3 -2
  22. package/dist/src/langfuse/index.js.map +1 -1
  23. package/dist/src/langfuse/observations.d.ts +37 -2
  24. package/dist/src/langfuse/observations.d.ts.map +1 -1
  25. package/dist/src/langfuse/observations.js +132 -61
  26. package/dist/src/langfuse/observations.js.map +1 -1
  27. package/dist/src/langfuse/projects.d.ts +2 -0
  28. package/dist/src/langfuse/projects.d.ts.map +1 -0
  29. package/dist/src/langfuse/projects.js +8 -0
  30. package/dist/src/langfuse/projects.js.map +1 -0
  31. package/dist/src/langfuse/prompts.d.ts +1 -0
  32. package/dist/src/langfuse/prompts.d.ts.map +1 -1
  33. package/dist/src/langfuse/prompts.js +53 -0
  34. package/dist/src/langfuse/prompts.js.map +1 -1
  35. package/dist/src/langfuse/scores.d.ts +9 -3
  36. package/dist/src/langfuse/scores.d.ts.map +1 -1
  37. package/dist/src/langfuse/scores.js +33 -22
  38. package/dist/src/langfuse/scores.js.map +1 -1
  39. package/dist/src/langfuse/traces.d.ts +16 -5
  40. package/dist/src/langfuse/traces.d.ts.map +1 -1
  41. package/dist/src/langfuse/traces.js +112 -105
  42. package/dist/src/langfuse/traces.js.map +1 -1
  43. package/llms-full.txt +9 -6
  44. package/llms.txt +3 -3
  45. package/package.json +7 -2
  46. package/rispecs/03-langfuse-module.spec.md +5 -0
  47. package/rispecs/08-cli-interface.spec.md +8 -5
  48. package/rispecs/09-mcp-server.spec.md +2 -2
package/dist/src/cli.js CHANGED
@@ -44,6 +44,15 @@ function globals(cmd) {
44
44
  }
45
45
  function output(data, cmd) {
46
46
  if (globals(cmd).json) {
47
+ if (typeof data === 'string') {
48
+ try {
49
+ console.log(formatJson(JSON.parse(data)));
50
+ return;
51
+ }
52
+ catch {
53
+ // Non-JSON strings are valid command results.
54
+ }
55
+ }
47
56
  console.log(formatJson(data));
48
57
  }
49
58
  else if (typeof data === 'string') {
@@ -53,6 +62,16 @@ function output(data, cmd) {
53
62
  console.log(formatJson(data));
54
63
  }
55
64
  }
65
+ function parseJsonValue(value) {
66
+ if (typeof value !== 'string')
67
+ return value;
68
+ try {
69
+ return JSON.parse(value);
70
+ }
71
+ catch {
72
+ return value;
73
+ }
74
+ }
56
75
  async function readStdin() {
57
76
  if (process.stdin.isTTY)
58
77
  return '';
@@ -242,21 +261,36 @@ function registerFuseCommands(program) {
242
261
  comments
243
262
  .command('list')
244
263
  .description('List comments')
264
+ .option('--object-type <type>', 'Filter by object type')
265
+ .option('--object-id <id>', 'Filter by object ID')
245
266
  .option('--trace-id <id>', 'Filter by trace ID')
267
+ .option('--author-user-id <id>', 'Filter by author user ID')
246
268
  .option('--page <n>', 'Page number', parseInt)
247
269
  .option('--limit <n>', 'Results per page', parseInt)
248
270
  .action(actionHandler(async (opts, cmd) => {
249
- const result = await callModule('langfuse', 'listComments', opts);
271
+ const result = await callModule('langfuse', 'listComments', {
272
+ objectType: opts.objectType ?? (opts.traceId ? 'TRACE' : undefined),
273
+ objectId: opts.objectId ?? opts.traceId,
274
+ authorUserId: opts.authorUserId,
275
+ page: opts.page,
276
+ limit: opts.limit,
277
+ });
250
278
  output(result, cmd);
251
279
  }));
252
280
  comments
253
281
  .command('post')
254
282
  .description('Post a comment')
255
- .option('--trace-id <id>', 'Trace ID')
256
- .option('--content <text>', 'Comment content')
257
- .option('--author <name>', 'Author name')
283
+ .requiredOption('--content <text>', 'Comment content')
284
+ .requiredOption('--object-type <type>', 'Object type')
285
+ .requiredOption('--object-id <id>', 'Object ID')
286
+ .option('--author-user-id <id>', 'Author user ID')
258
287
  .action(actionHandler(async (opts, cmd) => {
259
- const result = await callModule('langfuse', 'postComment', opts);
288
+ const result = await callModule('langfuse', 'createComment', {
289
+ text: opts.content,
290
+ objectType: opts.objectType,
291
+ objectId: opts.objectId,
292
+ authorUserId: opts.authorUserId,
293
+ });
260
294
  output(result, cmd);
261
295
  }));
262
296
  // ── prompts ──────────────────────────────────────────────────────────
@@ -276,19 +310,40 @@ function registerFuseCommands(program) {
276
310
  .argument('<name>', 'Prompt name')
277
311
  .option('--version <n>', 'Prompt version', parseInt)
278
312
  .option('--label <label>', 'Prompt deployment label')
313
+ .option('--md', 'Markdown output (default)')
279
314
  .action(actionHandler(async (name, opts, cmd) => {
280
- const result = await callModule('langfuse', 'getPrompt', name, opts);
281
- output(result, cmd);
315
+ const result = await callModule('langfuse', 'getPrompt', name, {
316
+ version: opts.version,
317
+ label: opts.label,
318
+ });
319
+ if (globals(cmd).json) {
320
+ console.log(formatJson(typeof result === 'string' ? JSON.parse(result) : result));
321
+ }
322
+ else {
323
+ const markdown = await callModule('langfuse', 'formatPromptMarkdown', result);
324
+ console.log(markdown);
325
+ }
282
326
  }));
283
327
  prompts
284
328
  .command('create')
285
329
  .description('Create a prompt')
286
- .option('--name <name>', 'Prompt name')
287
- .option('--prompt <text>', 'Prompt text')
288
- .option('--model <model>', 'Model name')
330
+ .requiredOption('--name <name>', 'Prompt name')
331
+ .requiredOption('--prompt <text>', 'Prompt text')
332
+ .option('--type <type>', 'Prompt type (text|chat)', 'text')
333
+ .option('--labels <labels>', 'Comma-separated labels')
334
+ .option('--tags <tags>', 'Comma-separated tags')
335
+ .option('--commit-message <text>', 'Commit message')
289
336
  .option('--config <json>', 'Config JSON')
290
337
  .action(actionHandler(async (opts, cmd) => {
291
- const result = await callModule('langfuse', 'createPrompt', opts);
338
+ const result = await callModule('langfuse', 'createPrompt', {
339
+ name: opts.name,
340
+ content: opts.type === 'chat' ? parseJsonValue(opts.prompt) : opts.prompt,
341
+ promptType: opts.type,
342
+ labels: opts.labels ? String(opts.labels).split(',').map((v) => v.trim()) : undefined,
343
+ tags: opts.tags ? String(opts.tags).split(',').map((v) => v.trim()) : undefined,
344
+ commitMessage: opts.commitMessage,
345
+ config: parseJsonValue(opts.config),
346
+ });
292
347
  output(result, cmd);
293
348
  }));
294
349
  // ── datasets ─────────────────────────────────────────────────────────
@@ -313,38 +368,26 @@ function registerFuseCommands(program) {
313
368
  datasets
314
369
  .command('create')
315
370
  .description('Create a dataset')
316
- .option('--name <name>', 'Dataset name')
371
+ .requiredOption('--name <name>', 'Dataset name')
317
372
  .option('--description <text>', 'Description')
373
+ .option('--metadata <json>', 'Metadata JSON')
318
374
  .action(actionHandler(async (opts, cmd) => {
319
- const result = await callModule('langfuse', 'createDataset', opts);
375
+ const result = await callModule('langfuse', 'createDataset', {
376
+ ...opts,
377
+ metadata: parseJsonValue(opts.metadata),
378
+ });
320
379
  output(result, cmd);
321
380
  }));
322
381
  // ── sessions ─────────────────────────────────────────────────────────
323
- const sessions = fuse.command('sessions').description('Session management');
324
- sessions
325
- .command('create')
326
- .description('Create a session')
327
- .option('--id <id>', 'Session ID')
328
- .option('--project-id <id>', 'Project ID')
329
- .action(actionHandler(async (opts, cmd) => {
330
- const result = await callModule('langfuse', 'createSession', opts);
331
- output(result, cmd);
332
- }));
333
- sessions
334
- .command('addnode')
335
- .description('Add a node to a session')
336
- .option('--session-id <id>', 'Session ID')
337
- .option('--trace-id <id>', 'Trace ID')
338
- .action(actionHandler(async (opts, cmd) => {
339
- const result = await callModule('langfuse', 'addSessionNode', opts);
340
- output(result, cmd);
341
- }));
382
+ // Langfuse v4 has no session entity endpoint. Sessions are reconstructed
383
+ // from observations sharing a sessionId.
384
+ const sessions = fuse.command('sessions').description('Session observation views');
342
385
  sessions
343
386
  .command('view')
344
- .description('View a session')
387
+ .description('View traces reconstructed from observations in a session')
345
388
  .argument('<sessionId>', 'Session ID')
346
389
  .action(actionHandler(async (sessionId, opts, cmd) => {
347
- const result = await callModule('langfuse', 'viewSession', sessionId);
390
+ const result = await callModule('langfuse', 'sessionView', sessionId);
348
391
  output(result, cmd);
349
392
  }));
350
393
  // ── scores ───────────────────────────────────────────────────────────
@@ -352,11 +395,11 @@ function registerFuseCommands(program) {
352
395
  scores
353
396
  .command('create')
354
397
  .description('Create a score')
355
- .option('--name <name>', 'Score name')
398
+ .requiredOption('--name <name>', 'Score name')
356
399
  .option('--trace-id <id>', 'Trace ID')
357
400
  .option('--observation-id <id>', 'Observation ID')
358
- .option('--value <n>', 'Score value', parseFloat)
359
- .option('--data-type <type>', 'Data type (NUMERIC|CATEGORICAL|BOOLEAN)')
401
+ .requiredOption('--value <n>', 'Score value', parseFloat)
402
+ .option('--config-id <id>', 'Score config ID')
360
403
  .option('--comment <text>', 'Comment')
361
404
  .action(actionHandler(async (opts, cmd) => {
362
405
  const result = await callModule('langfuse', 'createScore', opts);
@@ -365,22 +408,32 @@ function registerFuseCommands(program) {
365
408
  scores
366
409
  .command('apply')
367
410
  .description('Apply a score config')
368
- .option('--config <name>', 'Score config name')
369
- .option('--trace-id <id>', 'Trace ID')
370
- .option('--value <n>', 'Score value', parseFloat)
411
+ .requiredOption('--config <name>', 'Score config name or ID')
412
+ .requiredOption('--trace-id <id>', 'Trace ID')
413
+ .requiredOption('--value <n>', 'Score value', parseFloat)
414
+ .option('--observation-id <id>', 'Observation ID')
415
+ .option('--comment <text>', 'Comment')
371
416
  .action(actionHandler(async (opts, cmd) => {
372
- const result = await callModule('langfuse', 'applyScore', opts);
417
+ const result = await callModule('langfuse', 'applyScoreConfig', opts.config, 'trace', opts.traceId, opts.value, opts.observationId, opts.comment);
373
418
  output(result, cmd);
374
419
  }));
375
420
  scores
376
421
  .command('list')
377
- .description('List scores')
422
+ .description('List scores through Scores API v3')
378
423
  .option('--trace-id <id>', 'Filter by trace ID')
424
+ .option('--observation-id <id>', 'Filter by observation ID (requires trace ID)')
425
+ .option('--session-id <id>', 'Filter by session ID')
379
426
  .option('--name <name>', 'Filter by name')
380
- .option('--page <n>', 'Page number', parseInt)
381
- .option('--limit <n>', 'Results per page', parseInt)
427
+ .option('--from <timestamp>', 'Inclusive score timestamp')
428
+ .option('--to <timestamp>', 'Exclusive score timestamp')
429
+ .option('--cursor <cursor>', 'Cursor from a prior response')
430
+ .option('--limit <n>', 'Results per request (max 100)', parseInt)
382
431
  .action(actionHandler(async (opts, cmd) => {
383
- const result = await callModule('langfuse', 'listScores', opts);
432
+ const result = await callModule('langfuse', 'listScores', {
433
+ ...opts,
434
+ fromTimestamp: opts.from,
435
+ toTimestamp: opts.to,
436
+ });
384
437
  output(result, cmd);
385
438
  }));
386
439
  // ── score-configs ────────────────────────────────────────────────────
@@ -405,14 +458,21 @@ function registerFuseCommands(program) {
405
458
  scc
406
459
  .command('create')
407
460
  .description('Create a score config')
408
- .option('--name <name>', 'Config name')
409
- .option('--data-type <type>', 'NUMERIC | CATEGORICAL | BOOLEAN')
461
+ .requiredOption('--name <name>', 'Config name')
462
+ .requiredOption('--data-type <type>', 'NUMERIC | CATEGORICAL | BOOLEAN')
410
463
  .option('--description <text>', 'Description')
411
464
  .option('--min <n>', 'Min value (NUMERIC)', parseFloat)
412
465
  .option('--max <n>', 'Max value (NUMERIC)', parseFloat)
413
466
  .option('--categories <json>', 'Categories JSON (CATEGORICAL)')
414
467
  .action(actionHandler(async (opts, cmd) => {
415
- const result = await callModule('langfuse', 'createScoreConfig', opts);
468
+ const result = await callModule('langfuse', 'createScoreConfig', {
469
+ name: opts.name,
470
+ dataType: opts.dataType,
471
+ description: opts.description,
472
+ minValue: opts.min,
473
+ maxValue: opts.max,
474
+ categories: parseJsonValue(opts.categories),
475
+ });
416
476
  output(result, cmd);
417
477
  }));
418
478
  scc
@@ -420,7 +480,7 @@ function registerFuseCommands(program) {
420
480
  .description('Export score configs')
421
481
  .option('--output <path>', 'Output file path')
422
482
  .action(actionHandler(async (opts, cmd) => {
423
- const result = await callModule('langfuse', 'exportScoreConfigs', opts);
483
+ const result = await callModule('langfuse', 'exportScoreConfigs', opts.output);
424
484
  output(result, cmd);
425
485
  }));
426
486
  scc
@@ -435,46 +495,30 @@ function registerFuseCommands(program) {
435
495
  .command('presets')
436
496
  .description('List available presets')
437
497
  .action(actionHandler(async (opts, cmd) => {
438
- const result = await callModule('langfuse', 'listScoreConfigPresets');
498
+ const result = await callModule('langfuse', 'getBuiltInPresets');
439
499
  output(result, cmd);
440
500
  }));
441
501
  scc
442
502
  .command('apply')
443
- .description('Apply a preset')
503
+ .description('Install a preset')
444
504
  .argument('<preset>', 'Preset name')
445
505
  .action(actionHandler(async (preset, opts, cmd) => {
446
- const result = await callModule('langfuse', 'applyScoreConfigPreset', preset);
447
- output(result, cmd);
448
- }));
449
- scc
450
- .command('available')
451
- .description('Show available score types')
452
- .action(actionHandler(async (opts, cmd) => {
453
- const result = await callModule('langfuse', 'availableScoreTypes');
454
- output(result, cmd);
455
- }));
456
- scc
457
- .command('show')
458
- .description('Show a score config in detail')
459
- .argument('<name>', 'Config name')
460
- .action(actionHandler(async (name, opts, cmd) => {
461
- const result = await callModule('langfuse', 'showScoreConfig', name);
506
+ const result = await callModule('langfuse', 'installPreset', preset);
462
507
  output(result, cmd);
463
508
  }));
464
509
  // ── traces ───────────────────────────────────────────────────────────
465
510
  const traces = fuse.command('traces').description('Trace operations');
466
511
  traces
467
512
  .command('list')
468
- .description('List traces with optional filters')
513
+ .description('List traces reconstructed from Langfuse v4 observations')
469
514
  .option('--session-id <id>', 'Filter by session ID')
470
515
  .option('--user-id <id>', 'Filter by user ID')
471
516
  .option('--name <name>', 'Filter by trace name')
472
517
  .option('--tags <tags>', 'Comma-separated tags to filter by')
473
- .option('--from <timestamp>', 'From timestamp (ISO 8601)')
474
- .option('--to <timestamp>', 'To timestamp (ISO 8601)')
475
- .option('--order-by <field>', 'Order by field')
476
- .option('--page <n>', 'Page number', parseInt)
477
- .option('--limit <n>', 'Items per page (default 50)', parseInt)
518
+ .option('--from <timestamp>', 'Observation start time from (ISO 8601)')
519
+ .option('--to <timestamp>', 'Observation start time to (ISO 8601)')
520
+ .option('--cursor <cursor>', 'Cursor from a prior response')
521
+ .option('--limit <n>', 'Items per request (default 50)', parseInt)
478
522
  .action(actionHandler(async (opts, cmd) => {
479
523
  const filters = {
480
524
  sessionId: opts.sessionId,
@@ -483,8 +527,7 @@ function registerFuseCommands(program) {
483
527
  tags: opts.tags ? opts.tags.split(',').map((t) => t.trim()) : undefined,
484
528
  fromTimestamp: opts.from,
485
529
  toTimestamp: opts.to,
486
- orderBy: opts.orderBy,
487
- page: opts.page,
530
+ cursor: opts.cursor,
488
531
  limit: opts.limit,
489
532
  };
490
533
  const raw = await callModule('langfuse', 'listTraces', filters);
@@ -498,25 +541,44 @@ function registerFuseCommands(program) {
498
541
  }));
499
542
  traces
500
543
  .command('create')
501
- .description('Create a trace')
502
- .option('--name <name>', 'Trace name')
544
+ .description('Create a complete root observation through OpenTelemetry')
545
+ .requiredOption('--name <name>', 'Trace and root observation name')
546
+ .option('--trace-id <id>', 'Trace ID (UUID or 32 hexadecimal characters)')
503
547
  .option('--session-id <id>', 'Session ID')
504
- .option('--input <json>', 'Input JSON')
548
+ .option('--user-id <id>', 'User ID')
549
+ .option('--input <json>', 'Root observation input JSON')
550
+ .option('--output <json>', 'Root observation output JSON')
505
551
  .option('--metadata <json>', 'Metadata JSON')
552
+ .option('--tags <tags>', 'Comma-separated tags')
553
+ .option('--version <version>', 'Version')
554
+ .option('--environment <environment>', 'Environment')
506
555
  .action(actionHandler(async (opts, cmd) => {
507
- const result = await callModule('langfuse', 'createTrace', opts);
556
+ const result = await callModule('langfuse', 'createTrace', {
557
+ ...opts,
558
+ tags: opts.tags ? String(opts.tags).split(',').map((v) => v.trim()) : undefined,
559
+ });
508
560
  output(result, cmd);
509
561
  }));
510
562
  traces
511
563
  .command('add-observation')
512
- .description('Add an observation to a trace')
513
- .option('--trace-id <id>', 'Trace ID')
514
- .option('--name <name>', 'Observation name')
515
- .option('--type <type>', 'Type: generation | span | event')
564
+ .description('Export a complete immutable observation through OpenTelemetry')
565
+ .requiredOption('--trace-id <id>', 'Trace ID')
566
+ .requiredOption('--name <name>', 'Observation name')
567
+ .option('--type <type>', 'Type: generation | span | event', 'event')
568
+ .option('--parent-id <id>', 'Parent observation ID')
516
569
  .option('--input <json>', 'Input JSON')
517
570
  .option('--output <json>', 'Output JSON')
571
+ .option('--metadata <json>', 'Metadata JSON')
572
+ .option('--trace-name <name>', 'Propagated trace name')
573
+ .option('--session-id <id>', 'Propagated session ID')
574
+ .option('--user-id <id>', 'Propagated user ID')
575
+ .option('--tags <tags>', 'Comma-separated propagated tags')
576
+ .option('--model <model>', 'Model name for generation observations')
518
577
  .action(actionHandler(async (opts, cmd) => {
519
- const result = await callModule('langfuse', 'addObservation', opts);
578
+ const result = await callModule('langfuse', 'addObservation', {
579
+ ...opts,
580
+ tags: opts.tags ? String(opts.tags).split(',').map((v) => v.trim()) : undefined,
581
+ });
520
582
  output(result, cmd);
521
583
  }));
522
584
  traces
@@ -533,15 +595,6 @@ function registerFuseCommands(program) {
533
595
  const result = await callModule('langfuse', 'addObservations', data);
534
596
  output(result, cmd);
535
597
  }));
536
- traces
537
- .command('patch-output')
538
- .description('Patch trace output')
539
- .option('--trace-id <id>', 'Trace ID')
540
- .option('--output <json>', 'Output JSON')
541
- .action(actionHandler(async (opts, cmd) => {
542
- const result = await callModule('langfuse', 'patchTraceOutput', opts);
543
- output(result, cmd);
544
- }));
545
598
  traces
546
599
  .command('session-view')
547
600
  .description('View traces by session')
@@ -580,9 +633,18 @@ function registerFuseCommands(program) {
580
633
  .command('upload')
581
634
  .description('Upload a media file')
582
635
  .argument('<file>', 'File path')
583
- .option('--trace-id <id>', 'Associate with trace')
636
+ .requiredOption('--trace-id <id>', 'Associate with trace')
637
+ .option('--observation-id <id>', 'Associate with observation')
638
+ .option('--field <field>', 'Attach to input, output, or metadata', 'input')
639
+ .option('--content-type <type>', 'MIME type override')
584
640
  .action(actionHandler(async (file, opts, cmd) => {
585
- const result = await callModule('langfuse', 'uploadMedia', resolve(file), opts);
641
+ const result = await callModule('langfuse', 'uploadAndAttachMedia', {
642
+ filePath: resolve(file),
643
+ traceId: opts.traceId,
644
+ observationId: opts.observationId,
645
+ field: opts.field,
646
+ contentType: opts.contentType,
647
+ });
586
648
  output(result, cmd);
587
649
  }));
588
650
  media
@@ -598,12 +660,21 @@ function registerFuseCommands(program) {
598
660
  datasetItems
599
661
  .command('create')
600
662
  .description('Create a dataset item')
601
- .option('--dataset <name>', 'Dataset name')
602
- .option('--input <json>', 'Input JSON')
663
+ .requiredOption('--dataset <name>', 'Dataset name')
664
+ .requiredOption('--input <json>', 'Input JSON')
603
665
  .option('--expected <json>', 'Expected output JSON')
604
666
  .option('--metadata <json>', 'Metadata JSON')
667
+ .option('--source-trace-id <id>', 'Source trace ID')
668
+ .option('--source-observation-id <id>', 'Source observation ID')
605
669
  .action(actionHandler(async (opts, cmd) => {
606
- const result = await callModule('langfuse', 'createDatasetItem', opts);
670
+ const result = await callModule('langfuse', 'createDatasetItem', {
671
+ datasetName: opts.dataset,
672
+ input: parseJsonValue(opts.input),
673
+ expectedOutput: parseJsonValue(opts.expected),
674
+ metadata: parseJsonValue(opts.metadata),
675
+ sourceTraceId: opts.sourceTraceId,
676
+ sourceObservationId: opts.sourceObservationId,
677
+ });
607
678
  output(result, cmd);
608
679
  }));
609
680
  }