@principal-ai/principal-studio-cli 0.35.3

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 (184) hide show
  1. package/README.md +172 -0
  2. package/dist/commands/agent-session.d.ts +3 -0
  3. package/dist/commands/agent-session.d.ts.map +1 -0
  4. package/dist/commands/agent-session.js +67 -0
  5. package/dist/commands/agent-sessions.d.ts +11 -0
  6. package/dist/commands/agent-sessions.d.ts.map +1 -0
  7. package/dist/commands/agent-sessions.js +39 -0
  8. package/dist/commands/auxiliary/index.d.ts +3 -0
  9. package/dist/commands/auxiliary/index.d.ts.map +1 -0
  10. package/dist/commands/auxiliary/index.js +9 -0
  11. package/dist/commands/auxiliary/validate.d.ts +3 -0
  12. package/dist/commands/auxiliary/validate.d.ts.map +1 -0
  13. package/dist/commands/auxiliary/validate.js +123 -0
  14. package/dist/commands/collector/check.d.ts +6 -0
  15. package/dist/commands/collector/check.d.ts.map +1 -0
  16. package/dist/commands/collector/check.js +153 -0
  17. package/dist/commands/collector/diagnose.d.ts +6 -0
  18. package/dist/commands/collector/diagnose.d.ts.map +1 -0
  19. package/dist/commands/collector/diagnose.js +229 -0
  20. package/dist/commands/collector/index.d.ts +6 -0
  21. package/dist/commands/collector/index.d.ts.map +1 -0
  22. package/dist/commands/collector/index.js +16 -0
  23. package/dist/commands/collector/status.d.ts +6 -0
  24. package/dist/commands/collector/status.d.ts.map +1 -0
  25. package/dist/commands/collector/status.js +77 -0
  26. package/dist/commands/collector/utils.d.ts +92 -0
  27. package/dist/commands/collector/utils.d.ts.map +1 -0
  28. package/dist/commands/collector/utils.js +154 -0
  29. package/dist/commands/coverage.d.ts +9 -0
  30. package/dist/commands/coverage.d.ts.map +1 -0
  31. package/dist/commands/coverage.js +252 -0
  32. package/dist/commands/create.d.ts +6 -0
  33. package/dist/commands/create.d.ts.map +1 -0
  34. package/dist/commands/create.js +50 -0
  35. package/dist/commands/events/index.d.ts +3 -0
  36. package/dist/commands/events/index.d.ts.map +1 -0
  37. package/dist/commands/events/index.js +9 -0
  38. package/dist/commands/events/validate.d.ts +3 -0
  39. package/dist/commands/events/validate.d.ts.map +1 -0
  40. package/dist/commands/events/validate.js +124 -0
  41. package/dist/commands/formats.d.ts +6 -0
  42. package/dist/commands/formats.d.ts.map +1 -0
  43. package/dist/commands/formats.js +1118 -0
  44. package/dist/commands/hooks.d.ts +9 -0
  45. package/dist/commands/hooks.d.ts.map +1 -0
  46. package/dist/commands/hooks.js +295 -0
  47. package/dist/commands/inbox.d.ts +13 -0
  48. package/dist/commands/inbox.d.ts.map +1 -0
  49. package/dist/commands/inbox.js +179 -0
  50. package/dist/commands/init.d.ts +6 -0
  51. package/dist/commands/init.d.ts.map +1 -0
  52. package/dist/commands/init.js +220 -0
  53. package/dist/commands/lint.d.ts +11 -0
  54. package/dist/commands/lint.d.ts.map +1 -0
  55. package/dist/commands/lint.js +71 -0
  56. package/dist/commands/list.d.ts +6 -0
  57. package/dist/commands/list.d.ts.map +1 -0
  58. package/dist/commands/list.js +78 -0
  59. package/dist/commands/migrate-nodes.d.ts +9 -0
  60. package/dist/commands/migrate-nodes.d.ts.map +1 -0
  61. package/dist/commands/migrate-nodes.js +363 -0
  62. package/dist/commands/migrate-scopes-to-canvas.d.ts +3 -0
  63. package/dist/commands/migrate-scopes-to-canvas.d.ts.map +1 -0
  64. package/dist/commands/migrate-scopes-to-canvas.js +143 -0
  65. package/dist/commands/migration.d.ts +6 -0
  66. package/dist/commands/migration.d.ts.map +1 -0
  67. package/dist/commands/migration.js +247 -0
  68. package/dist/commands/open-studio.d.ts +10 -0
  69. package/dist/commands/open-studio.d.ts.map +1 -0
  70. package/dist/commands/open-studio.js +32 -0
  71. package/dist/commands/opencode/fetch.d.ts +3 -0
  72. package/dist/commands/opencode/fetch.d.ts.map +1 -0
  73. package/dist/commands/opencode/fetch.js +25 -0
  74. package/dist/commands/opencode/index.d.ts +3 -0
  75. package/dist/commands/opencode/index.d.ts.map +1 -0
  76. package/dist/commands/opencode/index.js +11 -0
  77. package/dist/commands/opencode/list-sessions.d.ts +3 -0
  78. package/dist/commands/opencode/list-sessions.d.ts.map +1 -0
  79. package/dist/commands/opencode/list-sessions.js +20 -0
  80. package/dist/commands/repo.d.ts +18 -0
  81. package/dist/commands/repo.d.ts.map +1 -0
  82. package/dist/commands/repo.js +233 -0
  83. package/dist/commands/schema.d.ts +6 -0
  84. package/dist/commands/schema.d.ts.map +1 -0
  85. package/dist/commands/schema.js +367 -0
  86. package/dist/commands/scopes/index.d.ts +3 -0
  87. package/dist/commands/scopes/index.d.ts.map +1 -0
  88. package/dist/commands/scopes/index.js +9 -0
  89. package/dist/commands/scopes/validate.d.ts +3 -0
  90. package/dist/commands/scopes/validate.d.ts.map +1 -0
  91. package/dist/commands/scopes/validate.js +187 -0
  92. package/dist/commands/setup.d.ts +6 -0
  93. package/dist/commands/setup.d.ts.map +1 -0
  94. package/dist/commands/setup.js +406 -0
  95. package/dist/commands/starred-collections.d.ts +12 -0
  96. package/dist/commands/starred-collections.d.ts.map +1 -0
  97. package/dist/commands/starred-collections.js +310 -0
  98. package/dist/commands/subsystem-model.d.ts +11 -0
  99. package/dist/commands/subsystem-model.d.ts.map +1 -0
  100. package/dist/commands/subsystem-model.js +249 -0
  101. package/dist/commands/topic.d.ts +15 -0
  102. package/dist/commands/topic.d.ts.map +1 -0
  103. package/dist/commands/topic.js +683 -0
  104. package/dist/commands/tour.d.ts +23 -0
  105. package/dist/commands/tour.d.ts.map +1 -0
  106. package/dist/commands/tour.js +783 -0
  107. package/dist/commands/trace/flow.d.ts +6 -0
  108. package/dist/commands/trace/flow.d.ts.map +1 -0
  109. package/dist/commands/trace/flow.js +158 -0
  110. package/dist/commands/trace/index.d.ts +6 -0
  111. package/dist/commands/trace/index.d.ts.map +1 -0
  112. package/dist/commands/trace/index.js +20 -0
  113. package/dist/commands/trace/inspect.d.ts +6 -0
  114. package/dist/commands/trace/inspect.d.ts.map +1 -0
  115. package/dist/commands/trace/inspect.js +187 -0
  116. package/dist/commands/trace/list.d.ts +6 -0
  117. package/dist/commands/trace/list.d.ts.map +1 -0
  118. package/dist/commands/trace/list.js +145 -0
  119. package/dist/commands/trace/registrations.d.ts +6 -0
  120. package/dist/commands/trace/registrations.d.ts.map +1 -0
  121. package/dist/commands/trace/registrations.js +81 -0
  122. package/dist/commands/trace/validate.d.ts +6 -0
  123. package/dist/commands/trace/validate.d.ts.map +1 -0
  124. package/dist/commands/trace/validate.js +276 -0
  125. package/dist/commands/trail.d.ts +36 -0
  126. package/dist/commands/trail.d.ts.map +1 -0
  127. package/dist/commands/trail.js +622 -0
  128. package/dist/commands/validate.d.ts +12 -0
  129. package/dist/commands/validate.d.ts.map +1 -0
  130. package/dist/commands/validate.js +3334 -0
  131. package/dist/commands/workflow/implementation.d.ts +3 -0
  132. package/dist/commands/workflow/implementation.d.ts.map +1 -0
  133. package/dist/commands/workflow/implementation.js +51 -0
  134. package/dist/commands/workflow/index.d.ts +3 -0
  135. package/dist/commands/workflow/index.d.ts.map +1 -0
  136. package/dist/commands/workflow/index.js +19 -0
  137. package/dist/commands/workflow/inspect.d.ts +3 -0
  138. package/dist/commands/workflow/inspect.d.ts.map +1 -0
  139. package/dist/commands/workflow/inspect.js +123 -0
  140. package/dist/commands/workflow/list.d.ts +3 -0
  141. package/dist/commands/workflow/list.d.ts.map +1 -0
  142. package/dist/commands/workflow/list.js +95 -0
  143. package/dist/commands/workflow/render.d.ts +3 -0
  144. package/dist/commands/workflow/render.d.ts.map +1 -0
  145. package/dist/commands/workflow/render.js +88 -0
  146. package/dist/commands/workflow/test.d.ts +3 -0
  147. package/dist/commands/workflow/test.d.ts.map +1 -0
  148. package/dist/commands/workflow/test.js +141 -0
  149. package/dist/commands/workflow/utils.d.ts +49 -0
  150. package/dist/commands/workflow/utils.d.ts.map +1 -0
  151. package/dist/commands/workflow/utils.js +164 -0
  152. package/dist/commands/workflow/validate.d.ts +3 -0
  153. package/dist/commands/workflow/validate.d.ts.map +1 -0
  154. package/dist/commands/workflow/validate.js +344 -0
  155. package/dist/file-utils.d.ts +15 -0
  156. package/dist/file-utils.d.ts.map +1 -0
  157. package/dist/file-utils.js +29 -0
  158. package/dist/index.cjs +285718 -0
  159. package/dist/index.cjs.map +7 -0
  160. package/dist/index.d.ts +8 -0
  161. package/dist/index.d.ts.map +1 -0
  162. package/dist/index.js +81 -0
  163. package/dist/lib/bridge-ipc.d.ts +29 -0
  164. package/dist/lib/bridge-ipc.d.ts.map +1 -0
  165. package/dist/lib/bridge-ipc.js +128 -0
  166. package/dist/lib/github-user.d.ts +17 -0
  167. package/dist/lib/github-user.d.ts.map +1 -0
  168. package/dist/lib/github-user.js +53 -0
  169. package/dist/lib/open-url.d.ts +11 -0
  170. package/dist/lib/open-url.d.ts.map +1 -0
  171. package/dist/lib/open-url.js +45 -0
  172. package/dist/lib/subsystem-model-store.d.ts +74 -0
  173. package/dist/lib/subsystem-model-store.d.ts.map +1 -0
  174. package/dist/lib/subsystem-model-store.js +292 -0
  175. package/dist/lib/tour-cache.d.ts +26 -0
  176. package/dist/lib/tour-cache.d.ts.map +1 -0
  177. package/dist/lib/tour-cache.js +46 -0
  178. package/dist/lib/trail-cache.d.ts +40 -0
  179. package/dist/lib/trail-cache.d.ts.map +1 -0
  180. package/dist/lib/trail-cache.js +97 -0
  181. package/dist/lib/viewer-ipc.d.ts +44 -0
  182. package/dist/lib/viewer-ipc.d.ts.map +1 -0
  183. package/dist/lib/viewer-ipc.js +68 -0
  184. package/package.json +68 -0
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createImplementationCommand(): Command;
3
+ //# sourceMappingURL=implementation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"implementation.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/implementation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,2BAA2B,IAAI,OAAO,CAyDrD"}
@@ -0,0 +1,51 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ export function createImplementationCommand() {
4
+ const command = new Command('implementation');
5
+ command
6
+ .description('Guide for implementing telemetry from workflow definitions')
7
+ .action(() => {
8
+ console.log(chalk.bold('\nWorkflow Implementation Guide'));
9
+ console.log(chalk.bold('=============================\n'));
10
+ console.log('A workflow.json defines how to instrument a single operation (span) in your code.\n');
11
+ console.log(chalk.cyan.bold('SPAN (Workflow Level)'));
12
+ console.log(' The workflow itself represents one span - the traced operation.');
13
+ console.log(' - workflow.name → span name');
14
+ console.log(' - workflow.canvas → the architectural context\n');
15
+ console.log(chalk.cyan.bold('EVENTS (Scenario Level)'));
16
+ console.log(' Each scenario represents an event that can occur during the span.');
17
+ console.log(' - scenario.name → event name');
18
+ console.log(' - scenario.template.events → attributes to capture\n');
19
+ console.log(chalk.dim('Example mapping:'));
20
+ console.log(chalk.dim(' workflow: "user-checkout" → span: "user-checkout"'));
21
+ console.log(chalk.dim(' scenario: "payment-processed" → event on that span'));
22
+ console.log(chalk.dim(' scenario: "payment-failed" → event on that span\n'));
23
+ console.log(chalk.yellow.bold('In your code:'));
24
+ console.log(' 1. Start the span when the operation begins');
25
+ console.log(' 2. Add events as scenarios occur');
26
+ console.log(' 3. End the span when the operation completes\n');
27
+ console.log(chalk.green.bold('Example (OpenTelemetry JS):'));
28
+ console.log(chalk.dim(`
29
+ const span = tracer.startSpan('user-checkout');
30
+
31
+ // When payment succeeds:
32
+ span.addEvent('payment-processed', {
33
+ 'payment.amount': amount,
34
+ 'payment.method': method,
35
+ });
36
+
37
+ // When payment fails:
38
+ span.addEvent('payment-failed', {
39
+ 'error.message': error.message,
40
+ });
41
+
42
+ span.end();
43
+ `));
44
+ console.log(chalk.bold('Key Concepts:'));
45
+ console.log(' - One workflow = one span (the operation being traced)');
46
+ console.log(' - Multiple scenarios = multiple possible events on that span');
47
+ console.log(' - Event attributes come from scenario.template.events');
48
+ console.log(' - Node pv.status tracks implementation progress (draft → approved → implemented)\n');
49
+ });
50
+ return command;
51
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createWorkflowCommand(): Command;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,qBAAqB,IAAI,OAAO,CAa/C"}
@@ -0,0 +1,19 @@
1
+ import { Command } from 'commander';
2
+ import { createValidateCommand } from './validate.js';
3
+ import { createInspectCommand } from './inspect.js';
4
+ import { createRenderCommand } from './render.js';
5
+ import { createTestCommand } from './test.js';
6
+ import { createListCommand } from './list.js';
7
+ import { createImplementationCommand } from './implementation.js';
8
+ export function createWorkflowCommand() {
9
+ const command = new Command('workflow');
10
+ command
11
+ .description('Validate, test, and debug workflow templates')
12
+ .addCommand(createValidateCommand())
13
+ .addCommand(createInspectCommand())
14
+ .addCommand(createRenderCommand())
15
+ .addCommand(createTestCommand())
16
+ .addCommand(createListCommand())
17
+ .addCommand(createImplementationCommand());
18
+ return command;
19
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createInspectCommand(): Command;
3
+ //# sourceMappingURL=inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,oBAAoB,IAAI,OAAO,CAiJ9C"}
@@ -0,0 +1,123 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { computeAggregates } from '@principal-ai/subsystems-core';
4
+ import { loadExecution, executionToEvents, resolvePath, formatTimestamp, formatDuration, groupAttributesByPrefix, filterAttributes, countEventsByType, formatValue, capitalize, } from './utils.js';
5
+ export function createInspectCommand() {
6
+ const command = new Command('inspect');
7
+ command
8
+ .description('Inspect execution file and show available attributes for templates')
9
+ .argument('<execution>', 'Path to .otel.json execution file')
10
+ .option('--events', 'Show all events')
11
+ .option('--aggregates', 'Show computed aggregates (default)', true)
12
+ .option('--json', 'Output as JSON')
13
+ .option('--filter <pattern>', 'Filter attributes by pattern (e.g., auth.*)')
14
+ .action(async (execution, options) => {
15
+ try {
16
+ const executionPath = resolvePath(execution);
17
+ // Load execution
18
+ const executionData = await loadExecution(executionPath);
19
+ const events = executionToEvents(executionData);
20
+ // Compute aggregates
21
+ const aggregates = computeAggregates(events);
22
+ // Apply filter if provided
23
+ const filteredAggregates = options.filter
24
+ ? filterAttributes(aggregates, options.filter)
25
+ : aggregates;
26
+ // Count events by type
27
+ const eventCounts = countEventsByType(events);
28
+ // Calculate time range
29
+ const timestamps = events.map((e) => typeof e.timestamp === 'string' ? parseInt(e.timestamp, 10) : e.timestamp);
30
+ const minTime = Math.min(...timestamps);
31
+ const maxTime = Math.max(...timestamps);
32
+ const duration = maxTime - minTime;
33
+ if (options.json) {
34
+ const output = {
35
+ file: execution,
36
+ summary: {
37
+ eventCount: events.length,
38
+ spanCount: executionData.spans.length,
39
+ timeRange: {
40
+ start: minTime,
41
+ end: maxTime,
42
+ duration: duration,
43
+ },
44
+ status: executionData.metadata?.status || 'UNKNOWN',
45
+ scope: executionData.metadata?.scopeName || null,
46
+ scopeVersion: executionData.metadata?.scopeVersion || null,
47
+ serviceName: executionData.metadata?.serviceName || null,
48
+ },
49
+ eventTypes: Array.from(eventCounts.entries()).map(([name, count]) => ({
50
+ name,
51
+ count,
52
+ })),
53
+ attributes: filteredAggregates,
54
+ };
55
+ if (options.events) {
56
+ output.events = events.map((e) => ({
57
+ name: e.name,
58
+ timestamp: e.timestamp,
59
+ attributes: e.attributes,
60
+ }));
61
+ }
62
+ console.log(JSON.stringify(output, null, 2));
63
+ }
64
+ else {
65
+ // Text output
66
+ console.log(chalk.bold(`\nInspecting: ${execution}\n`));
67
+ // Execution Summary
68
+ console.log(chalk.bold('Execution Summary:'));
69
+ console.log('━'.repeat(60));
70
+ console.log(chalk.gray(' • Total Events:'), events.length);
71
+ console.log(chalk.gray(' • Total Spans:'), executionData.spans.length);
72
+ console.log(chalk.gray(' • Time Range:'), `${formatTimestamp(minTime)} → ${formatTimestamp(maxTime)} (${formatDuration(duration)})`);
73
+ const status = executionData.metadata?.status || 'UNKNOWN';
74
+ const statusColor = status === 'OK' ? chalk.green : chalk.red;
75
+ console.log(chalk.gray(' • Status:'), statusColor(status));
76
+ // Show scope information
77
+ const scopeName = executionData.metadata?.scopeName;
78
+ const scopeVersion = executionData.metadata?.scopeVersion;
79
+ const serviceName = executionData.metadata?.serviceName;
80
+ if (serviceName) {
81
+ console.log(chalk.gray(' • Service:'), serviceName);
82
+ }
83
+ if (scopeName) {
84
+ const scopeDisplay = scopeVersion ? `${scopeName}@${scopeVersion}` : scopeName;
85
+ console.log(chalk.gray(' • Scope:'), scopeDisplay);
86
+ }
87
+ // Event Types
88
+ console.log(chalk.bold('\nEvent Types:'));
89
+ console.log('━'.repeat(60));
90
+ for (const [name, count] of eventCounts) {
91
+ console.log(chalk.gray(' •'), `${name} (${count})`);
92
+ }
93
+ // Available Attributes
94
+ console.log(chalk.bold('\nAvailable Attributes (for templates):'));
95
+ console.log('━'.repeat(60));
96
+ const grouped = groupAttributesByPrefix(filteredAggregates);
97
+ for (const [prefix, attrs] of Object.entries(grouped)) {
98
+ console.log(chalk.bold(`\n${capitalize(prefix)}:`));
99
+ for (const [key, value] of Object.entries(attrs)) {
100
+ console.log(chalk.gray(' •'), `${key}: ${formatValue(value)}`);
101
+ }
102
+ }
103
+ // Show events if requested
104
+ if (options.events) {
105
+ console.log(chalk.bold('\nEvents:'));
106
+ console.log('━'.repeat(60));
107
+ for (const event of events) {
108
+ console.log(chalk.cyan(`\n[${formatTimestamp(typeof event.timestamp === 'string' ? parseInt(event.timestamp, 10) : event.timestamp)}]`), chalk.bold(event.name));
109
+ for (const [key, value] of Object.entries(event.attributes || {})) {
110
+ console.log(chalk.gray(' •'), `${key}: ${formatValue(value)}`);
111
+ }
112
+ }
113
+ }
114
+ console.log();
115
+ }
116
+ }
117
+ catch (error) {
118
+ console.error(chalk.red('Error:'), error.message);
119
+ process.exit(1);
120
+ }
121
+ });
122
+ return command;
123
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createListCommand(): Command;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,iBAAiB,IAAI,OAAO,CAsG3C"}
@@ -0,0 +1,95 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { access } from 'node:fs/promises';
4
+ import { resolve, dirname, join } from 'node:path';
5
+ import { globby } from 'globby';
6
+ import { loadWorkflow } from './utils.js';
7
+ export function createListCommand() {
8
+ const command = new Command('list');
9
+ command
10
+ .description('List all workflow files in project')
11
+ .argument('[dir]', 'Directory to search (default: .principal-views/)')
12
+ .option('--json', 'Output as JSON')
13
+ .option('--show-canvas', 'Show linked canvas files')
14
+ .action(async (dir, options) => {
15
+ try {
16
+ const searchDir = dir || '.principal-views';
17
+ const searchPath = resolve(process.cwd(), searchDir);
18
+ // Find all .workflow.json files
19
+ const files = await globby('**/*.workflow.json', {
20
+ cwd: searchPath,
21
+ ignore: ['node_modules/**', '.git/**', '__executions__/**'],
22
+ });
23
+ // Load each workflow and check canvas existence
24
+ const workflows = await Promise.all(files.map(async (file) => {
25
+ const fullPath = join(searchPath, file);
26
+ const workflow = await loadWorkflow(fullPath);
27
+ let canvasExists;
28
+ if (options.showCanvas && workflow.canvas) {
29
+ const workflowDir = dirname(fullPath);
30
+ const canvasPath = resolve(workflowDir, workflow.canvas);
31
+ try {
32
+ await access(canvasPath);
33
+ canvasExists = true;
34
+ }
35
+ catch {
36
+ canvasExists = false;
37
+ }
38
+ }
39
+ return {
40
+ file: join(searchDir, file),
41
+ canvas: workflow.canvas,
42
+ canvasExists,
43
+ scenarioCount: workflow.scenarios.length,
44
+ name: workflow.name,
45
+ };
46
+ }));
47
+ if (options.json) {
48
+ const output = {
49
+ searchDir,
50
+ count: workflows.length,
51
+ workflows: workflows.map((n) => ({
52
+ file: n.file,
53
+ name: n.name,
54
+ canvas: n.canvas,
55
+ canvasExists: n.canvasExists,
56
+ scenarios: n.scenarioCount,
57
+ })),
58
+ };
59
+ console.log(JSON.stringify(output, null, 2));
60
+ }
61
+ else {
62
+ console.log(chalk.bold('\nWorkflow Templates:'));
63
+ console.log('━'.repeat(60));
64
+ if (workflows.length === 0) {
65
+ console.log(chalk.yellow(`\nNo workflow templates found in ${searchDir}`));
66
+ console.log();
67
+ return;
68
+ }
69
+ for (const workflow of workflows) {
70
+ console.log(chalk.bold(`\n${workflow.file}`));
71
+ if (workflow.name) {
72
+ console.log(chalk.gray(` Name: ${workflow.name}`));
73
+ }
74
+ if (options.showCanvas && workflow.canvas) {
75
+ const status = workflow.canvasExists
76
+ ? chalk.green('✓')
77
+ : chalk.red('✗');
78
+ console.log(chalk.gray(` Canvas: ${workflow.canvas} ${status}`));
79
+ }
80
+ else if (workflow.canvas) {
81
+ console.log(chalk.gray(` Canvas: ${workflow.canvas}`));
82
+ }
83
+ console.log(chalk.gray(` Scenarios: ${workflow.scenarioCount}`));
84
+ }
85
+ console.log(chalk.bold(`\nFound ${workflows.length} workflow template(s)`));
86
+ console.log();
87
+ }
88
+ }
89
+ catch (error) {
90
+ console.error(chalk.red('Error:'), error.message);
91
+ process.exit(1);
92
+ }
93
+ });
94
+ return command;
95
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createRenderCommand(): Command;
3
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,wBAAgB,mBAAmB,IAAI,OAAO,CAqG7C"}
@@ -0,0 +1,88 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { renderWorkflow } from '@principal-ai/subsystems-core';
4
+ import { loadWorkflow, loadExecution, executionToEvents, resolvePath, } from './utils.js';
5
+ export function createRenderCommand() {
6
+ const command = new Command('render');
7
+ command
8
+ .description('Render workflow template using execution data')
9
+ .argument('<workflow>', 'Path to .workflow.json file')
10
+ .argument('<execution>', 'Path to .otel.json execution file')
11
+ .option('--scenario <id>', 'Force specific scenario (skip auto-selection)')
12
+ .option('--json', 'Output structured result as JSON')
13
+ .option('--format <format>', 'Output format: text (default), markdown, json', 'text')
14
+ .option('--show-metadata', 'Include rendering metadata in output')
15
+ .action(async (workflowPath, executionPath, options) => {
16
+ try {
17
+ const workflow = await loadWorkflow(resolvePath(workflowPath));
18
+ const executionData = await loadExecution(resolvePath(executionPath));
19
+ const events = executionToEvents(executionData);
20
+ // Render workflow
21
+ const result = renderWorkflow(workflow, events);
22
+ // Get the selected scenario from the result
23
+ const selectedScenario = workflow.scenarios.find((s) => s.id === result.scenarioId);
24
+ // Force scenario if specified
25
+ if (options.scenario) {
26
+ const scenario = workflow.scenarios.find((s) => s.id === options.scenario);
27
+ if (!scenario) {
28
+ throw new Error(`Scenario not found: ${options.scenario}`);
29
+ }
30
+ // Note: This would require a way to force scenario in renderWorkflow API
31
+ // For now, we'll just validate the scenario exists
32
+ }
33
+ if (options.json) {
34
+ const output = {
35
+ workflow: workflowPath,
36
+ execution: executionPath,
37
+ scenario: {
38
+ id: selectedScenario?.id,
39
+ priority: selectedScenario?.priority,
40
+ matched: true,
41
+ },
42
+ text: result.text,
43
+ };
44
+ if (options.showMetadata) {
45
+ output.metadata = result.metadata;
46
+ }
47
+ console.log(JSON.stringify(output, null, 2));
48
+ }
49
+ else {
50
+ // Text output
51
+ if (!options.format || options.format === 'text') {
52
+ console.log(chalk.gray(`Rendering: ${workflowPath}`));
53
+ console.log(chalk.gray(`Execution: ${executionPath}`));
54
+ if (selectedScenario) {
55
+ console.log(chalk.gray(`Scenario: ${selectedScenario.id} (priority: ${selectedScenario.priority})`));
56
+ }
57
+ console.log();
58
+ console.log('━'.repeat(60));
59
+ console.log();
60
+ console.log(result.text);
61
+ console.log();
62
+ console.log('━'.repeat(60));
63
+ if (options.showMetadata && result.metadata) {
64
+ console.log();
65
+ console.log(chalk.bold('Metadata:'));
66
+ console.log(chalk.gray(' • Event Count:'), result.metadata.eventCount);
67
+ console.log(chalk.gray(' • Span Count:'), result.metadata.spanCount);
68
+ if (result.metadata.timeRange) {
69
+ console.log(chalk.gray(' • Time Range:'), `${result.metadata.timeRange.start} → ${result.metadata.timeRange.end}`);
70
+ }
71
+ }
72
+ console.log();
73
+ }
74
+ else if (options.format === 'markdown') {
75
+ console.log(result.text);
76
+ }
77
+ else if (options.format === 'json') {
78
+ console.log(JSON.stringify({ text: result.text }, null, 2));
79
+ }
80
+ }
81
+ }
82
+ catch (error) {
83
+ console.error(chalk.red('Error:'), error.message);
84
+ process.exit(1);
85
+ }
86
+ });
87
+ return command;
88
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createTestCommand(): Command;
3
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,wBAAgB,iBAAiB,IAAI,OAAO,CA+K3C"}
@@ -0,0 +1,141 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { selectScenario, computeAggregates } from '@principal-ai/subsystems-core';
4
+ import { loadWorkflow, loadExecution, executionToEvents, resolvePath, formatValue, } from './utils.js';
5
+ export function createTestCommand() {
6
+ const command = new Command('test');
7
+ command
8
+ .description('Test scenario matching and show why scenarios match or don\'t match')
9
+ .argument('<workflow>', 'Path to .workflow.json file')
10
+ .argument('<execution>', 'Path to .otel.json execution file')
11
+ .option('--show-all', 'Show all scenarios (not just matches)')
12
+ .option('--show-aggregates', 'Display computed aggregates')
13
+ .option('--json', 'Output as JSON')
14
+ .action(async (workflowPath, executionPath, options) => {
15
+ try {
16
+ const workflow = await loadWorkflow(resolvePath(workflowPath));
17
+ const executionData = await loadExecution(resolvePath(executionPath));
18
+ const events = executionToEvents(executionData);
19
+ // Compute aggregates
20
+ const aggregates = computeAggregates(events);
21
+ // Select the winning scenario using enhanced matching
22
+ const matchResult = selectScenario(workflow, events);
23
+ if (options.json) {
24
+ const output = {
25
+ workflow: workflowPath,
26
+ execution: executionPath,
27
+ fullMatches: matchResult.fullMatches.map((m) => ({
28
+ id: m.scenario.id,
29
+ priority: m.scenario.priority,
30
+ matchPercentage: m.matchPercentage,
31
+ matchedEventCount: m.matchedEventCount,
32
+ totalRequiredEvents: m.totalRequiredEvents,
33
+ matchedEventNames: m.matchedEventNames,
34
+ missingEventNames: m.missingEventNames,
35
+ })),
36
+ partialMatches: matchResult.partialMatches.map((m) => ({
37
+ id: m.scenario.id,
38
+ priority: m.scenario.priority,
39
+ matchPercentage: m.matchPercentage,
40
+ matchedEventCount: m.matchedEventCount,
41
+ totalRequiredEvents: m.totalRequiredEvents,
42
+ matchedEventNames: m.matchedEventNames,
43
+ missingEventNames: m.missingEventNames,
44
+ })),
45
+ recommendedScenario: matchResult.recommendedScenario
46
+ ? {
47
+ id: matchResult.recommendedScenario.scenario.id,
48
+ priority: matchResult.recommendedScenario.scenario.priority,
49
+ matchPercentage: matchResult.recommendedScenario.matchPercentage,
50
+ isFullMatch: matchResult.recommendedScenario.isFullMatch,
51
+ }
52
+ : null,
53
+ totalTraceEvents: matchResult.totalTraceEvents,
54
+ totalScenariosEvaluated: matchResult.totalScenariosEvaluated,
55
+ aggregates: options.showAggregates ? aggregates : undefined,
56
+ };
57
+ console.log(JSON.stringify(output, null, 2));
58
+ }
59
+ else {
60
+ // Text output
61
+ console.log(chalk.bold(`\nTesting: ${workflowPath}`));
62
+ console.log(chalk.gray(`Execution: ${executionPath}`));
63
+ console.log(chalk.gray(`Total Events: ${matchResult.totalTraceEvents}, Scenarios Evaluated: ${matchResult.totalScenariosEvaluated}\n`));
64
+ console.log(chalk.bold('Scenario Matching Results:'));
65
+ console.log('━'.repeat(60));
66
+ // Show full matches
67
+ if (matchResult.fullMatches.length > 0) {
68
+ console.log(chalk.green.bold('\n✓ FULL MATCHES (100% coverage):'));
69
+ for (const match of matchResult.fullMatches) {
70
+ console.log(`\n ${chalk.bold(match.scenario.id)} ${chalk.gray(`(priority: ${match.scenario.priority})`)}`);
71
+ console.log(` • Matched: ${match.matchedEventCount}/${match.totalRequiredEvents} events`);
72
+ for (const eventName of match.matchedEventNames) {
73
+ console.log(` ${chalk.green('✓')} ${eventName}`);
74
+ }
75
+ }
76
+ }
77
+ else if (matchResult.partialMatches.length > 0) {
78
+ console.log(chalk.yellow.bold('\n⚠ PARTIAL MATCHES:'));
79
+ // Show top 5 partial matches
80
+ const displayCount = options.showAll
81
+ ? matchResult.partialMatches.length
82
+ : Math.min(5, matchResult.partialMatches.length);
83
+ for (const match of matchResult.partialMatches.slice(0, displayCount)) {
84
+ const percentColor = match.matchPercentage >= 75
85
+ ? chalk.yellow
86
+ : match.matchPercentage >= 50
87
+ ? chalk.yellowBright
88
+ : chalk.gray;
89
+ console.log(`\n ${chalk.bold(match.scenario.id)} ${percentColor(`(${match.matchPercentage.toFixed(1)}%)`)} ${chalk.gray(`priority: ${match.scenario.priority}`)}`);
90
+ console.log(` • Matched: ${match.matchedEventCount}/${match.totalRequiredEvents}`);
91
+ if (match.matchedEventNames.length > 0) {
92
+ console.log(chalk.gray(' Matched:'));
93
+ for (const eventName of match.matchedEventNames) {
94
+ console.log(` ${chalk.green('✓')} ${eventName}`);
95
+ }
96
+ }
97
+ if (match.missingEventNames.length > 0) {
98
+ console.log(chalk.gray(' Missing:'));
99
+ for (const eventName of match.missingEventNames) {
100
+ console.log(` ${chalk.red('✗')} ${eventName}`);
101
+ }
102
+ }
103
+ }
104
+ if (!options.showAll &&
105
+ matchResult.partialMatches.length > displayCount) {
106
+ console.log(chalk.gray(`\n ... and ${matchResult.partialMatches.length - displayCount} more partial matches (use --show-all to see all)`));
107
+ }
108
+ }
109
+ else {
110
+ console.log(chalk.red('\n✗ No scenarios matched'));
111
+ }
112
+ console.log('\n' + '━'.repeat(60));
113
+ if (matchResult.recommendedScenario) {
114
+ const isFullMatch = matchResult.recommendedScenario.isFullMatch;
115
+ const matchType = isFullMatch ? 'Full Match' : 'Partial Match';
116
+ const percentage = matchResult.recommendedScenario.matchPercentage.toFixed(1);
117
+ console.log(chalk.bold('\nRecommended Scenario:'), chalk.cyan(`${matchResult.recommendedScenario.scenario.id} (${matchType}, ${percentage}%)`));
118
+ }
119
+ else {
120
+ console.log(chalk.yellow('\nNo scenario selected'));
121
+ }
122
+ if (options.showAggregates) {
123
+ console.log(chalk.bold('\nComputed Aggregates:'));
124
+ for (const [key, value] of Object.entries(aggregates)) {
125
+ console.log(chalk.gray(' •'), `${key}: ${formatValue(value)}`);
126
+ }
127
+ }
128
+ console.log();
129
+ }
130
+ // Exit with error if no scenario matched
131
+ if (!matchResult.recommendedScenario) {
132
+ process.exit(1);
133
+ }
134
+ }
135
+ catch (error) {
136
+ console.error(chalk.red('Error:'), error.message);
137
+ process.exit(1);
138
+ }
139
+ });
140
+ return command;
141
+ }
@@ -0,0 +1,49 @@
1
+ import type { WorkflowTemplate, OtelEvent } from '@principal-ai/subsystems-core';
2
+ import { type ExecutionData } from '@principal-ai/subsystems-core';
3
+ /**
4
+ * Load a workflow template from a file
5
+ */
6
+ export declare function loadWorkflow(filePath: string): Promise<WorkflowTemplate>;
7
+ /**
8
+ * Load execution data from a .otel.json file
9
+ *
10
+ * Automatically handles OTLP standard format conversion via ExecutionValidator.
11
+ */
12
+ export declare function loadExecution(filePath: string): Promise<ExecutionData>;
13
+ /**
14
+ * Convert execution data to OtelEvent array format expected by workflow APIs
15
+ */
16
+ export declare function executionToEvents(execution: ExecutionData): OtelEvent[];
17
+ /**
18
+ * Resolve a file path relative to a base directory
19
+ */
20
+ export declare function resolvePath(filePath: string, baseDir?: string): string;
21
+ /**
22
+ * Format a timestamp as human-readable date/time
23
+ */
24
+ export declare function formatTimestamp(timestamp: number): string;
25
+ /**
26
+ * Format duration in milliseconds
27
+ */
28
+ export declare function formatDuration(ms: number): string;
29
+ /**
30
+ * Group attributes by prefix (e.g., 'auth.method' -> 'auth')
31
+ */
32
+ export declare function groupAttributesByPrefix(attributes: Record<string, unknown>): Record<string, Record<string, unknown>>;
33
+ /**
34
+ * Filter attributes by pattern (supports glob-like patterns)
35
+ */
36
+ export declare function filterAttributes(attributes: Record<string, unknown>, pattern: string): Record<string, unknown>;
37
+ /**
38
+ * Count events by type/name
39
+ */
40
+ export declare function countEventsByType(events: OtelEvent[]): Map<string, number>;
41
+ /**
42
+ * Format attribute value for display
43
+ */
44
+ export declare function formatValue(value: unknown): string;
45
+ /**
46
+ * Capitalize first letter of a string
47
+ */
48
+ export declare function capitalize(str: string): string;
49
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AACjF,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEvF;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU9E;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAc5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,EAAE,CAmBvE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAWzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoBzC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAS1E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAclD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C"}