@principal-ai/principal-view-core 0.6.3 → 0.7.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 (92) hide show
  1. package/dist/ConfigurationLoader.js +2 -1
  2. package/dist/ConfigurationLoader.js.map +1 -1
  3. package/dist/ConfigurationValidator.js.map +1 -1
  4. package/dist/EventProcessor.js.map +1 -1
  5. package/dist/EventRecorderService.js.map +1 -1
  6. package/dist/LibraryLoader.js.map +1 -1
  7. package/dist/PathBasedEventProcessor.js.map +1 -1
  8. package/dist/SessionManager.js +1 -1
  9. package/dist/SessionManager.js.map +1 -1
  10. package/dist/ValidationEngine.js.map +1 -1
  11. package/dist/cli/codegen.js.map +1 -1
  12. package/dist/codegen/type-generator.js.map +1 -1
  13. package/dist/codegen/usage-example.js.map +1 -1
  14. package/dist/helpers/GraphInstrumentationHelper.js +2 -2
  15. package/dist/helpers/GraphInstrumentationHelper.js.map +1 -1
  16. package/dist/index.d.ts +2 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +2 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/narrative/example.d.ts +11 -0
  21. package/dist/narrative/example.d.ts.map +1 -0
  22. package/dist/narrative/example.js +331 -0
  23. package/dist/narrative/example.js.map +1 -0
  24. package/dist/narrative/index.d.ts +12 -0
  25. package/dist/narrative/index.d.ts.map +1 -0
  26. package/dist/narrative/index.js +14 -0
  27. package/dist/narrative/index.js.map +1 -0
  28. package/dist/narrative/scenario-matcher.d.ts +87 -0
  29. package/dist/narrative/scenario-matcher.d.ts.map +1 -0
  30. package/dist/narrative/scenario-matcher.js +269 -0
  31. package/dist/narrative/scenario-matcher.js.map +1 -0
  32. package/dist/narrative/template-parser.d.ts +33 -0
  33. package/dist/narrative/template-parser.d.ts.map +1 -0
  34. package/dist/narrative/template-parser.js +288 -0
  35. package/dist/narrative/template-parser.js.map +1 -0
  36. package/dist/narrative/template-renderer.d.ts +18 -0
  37. package/dist/narrative/template-renderer.d.ts.map +1 -0
  38. package/dist/narrative/template-renderer.js +367 -0
  39. package/dist/narrative/template-renderer.js.map +1 -0
  40. package/dist/narrative/types.d.ts +268 -0
  41. package/dist/narrative/types.d.ts.map +1 -0
  42. package/dist/narrative/types.js +10 -0
  43. package/dist/narrative/types.js.map +1 -0
  44. package/dist/rules/config.js.map +1 -1
  45. package/dist/rules/engine.js.map +1 -1
  46. package/dist/rules/implementations/connection-type-references.js.map +1 -1
  47. package/dist/rules/implementations/dead-end-states.js.map +1 -1
  48. package/dist/rules/implementations/library-node-type-match.js.map +1 -1
  49. package/dist/rules/implementations/minimum-node-sources.js.map +1 -1
  50. package/dist/rules/implementations/no-unknown-fields.js.map +1 -1
  51. package/dist/rules/implementations/orphaned-edge-types.js.map +1 -1
  52. package/dist/rules/implementations/orphaned-node-types.js.map +1 -1
  53. package/dist/rules/implementations/required-metadata.js.map +1 -1
  54. package/dist/rules/implementations/state-transition-references.js.map +1 -1
  55. package/dist/rules/implementations/unreachable-states.js.map +1 -1
  56. package/dist/rules/implementations/valid-action-patterns.js.map +1 -1
  57. package/dist/rules/implementations/valid-color-format.js.map +1 -1
  58. package/dist/rules/implementations/valid-edge-types.js.map +1 -1
  59. package/dist/rules/implementations/valid-node-types.js.map +1 -1
  60. package/dist/rules/types.js.map +1 -1
  61. package/dist/telemetry/coverage.js.map +1 -1
  62. package/dist/telemetry/event-validator.js.map +1 -1
  63. package/dist/types/audit.js.map +1 -1
  64. package/dist/types/canvas.js +5 -5
  65. package/dist/types/canvas.js.map +1 -1
  66. package/dist/types/otel.js.map +1 -1
  67. package/dist/types/resource-match.js.map +1 -1
  68. package/dist/utils/CanvasConverter.js.map +1 -1
  69. package/dist/utils/GraphConverter.js.map +1 -1
  70. package/dist/utils/LibraryConverter.js.map +1 -1
  71. package/dist/utils/PathMatcher.js.map +1 -1
  72. package/dist/utils/TraceToCanvas.js +7 -7
  73. package/dist/utils/TraceToCanvas.js.map +1 -1
  74. package/dist/utils/YamlParser.js.map +1 -1
  75. package/package.json +15 -15
  76. package/src/index.ts +31 -13
  77. package/src/narrative/README.md +381 -0
  78. package/src/narrative/__tests__/scenario-matcher.test.ts +368 -0
  79. package/src/narrative/__tests__/template-parser.test.ts +235 -0
  80. package/src/narrative/__tests__/template-renderer.test.ts +377 -0
  81. package/src/narrative/example.ts +349 -0
  82. package/src/narrative/index.ts +35 -0
  83. package/src/narrative/scenario-matcher.ts +331 -0
  84. package/src/narrative/template-parser.ts +298 -0
  85. package/src/narrative/template-renderer.ts +423 -0
  86. package/src/narrative/types.ts +368 -0
  87. package/src/utils/GraphConverter.test.ts +0 -79
  88. package/dist/utils/ExecutionFileDiscovery.d.ts +0 -206
  89. package/dist/utils/ExecutionFileDiscovery.d.ts.map +0 -1
  90. package/dist/utils/ExecutionFileDiscovery.js +0 -340
  91. package/dist/utils/ExecutionFileDiscovery.js.map +0 -1
  92. package/src/utils/ExecutionFileDiscovery.ts +0 -522
@@ -1,522 +0,0 @@
1
- /**
2
- * Execution File Discovery
3
- *
4
- * Discovers execution artifacts and canvas files in a repository with monorepo awareness.
5
- * Uses codebase-composition (browser-safe export) to intelligently detect package boundaries
6
- * and workspace patterns.
7
- */
8
-
9
- import { PackageLayerModule } from '@principal-ai/codebase-composition/browser';
10
- import type { PackageLayer } from '@principal-ai/codebase-composition/browser';
11
-
12
- /**
13
- * Represents a discovered execution artifact file
14
- */
15
- export interface ExecutionFile {
16
- /** Unique identifier for this execution */
17
- id: string;
18
- /** Display name for this execution */
19
- name: string;
20
- /** Full file path (relative to repository root) */
21
- path: string;
22
- /** Canvas basename (without extension) that this execution is linked to */
23
- canvasBasename: string;
24
- /** Package context if this execution belongs to a specific package */
25
- packageContext?: PackageContext;
26
- }
27
-
28
- /**
29
- * Represents a discovered canvas file
30
- */
31
- export interface CanvasFile {
32
- /** Unique identifier for this canvas */
33
- id: string;
34
- /** Display name for this canvas */
35
- name: string;
36
- /** Full file path (relative to repository root) */
37
- path: string;
38
- /** Canvas basename (without .otel.canvas or .canvas extension) */
39
- basename: string;
40
- /** Package context if this canvas belongs to a specific package */
41
- packageContext?: PackageContext;
42
- }
43
-
44
- /**
45
- * Package context for execution/canvas files
46
- */
47
- export interface PackageContext {
48
- /** Package name (from package.json, Cargo.toml, etc.) */
49
- name: string;
50
- /** Package directory path (relative to repository root) */
51
- packagePath: string;
52
- /** Package type (npm, cargo, go, etc.) */
53
- packageType?: string;
54
- }
55
-
56
- /**
57
- * Execution artifact metadata
58
- */
59
- export interface ExecutionMetadata {
60
- name: string;
61
- canvasName?: string;
62
- exportedAt?: string;
63
- source?: string;
64
- framework?: string;
65
- status?: 'success' | 'error' | 'OK';
66
- spanCount: number;
67
- eventCount: number;
68
- }
69
-
70
- /**
71
- * Execution span structure
72
- */
73
- export interface ExecutionSpan {
74
- id: string;
75
- name: string;
76
- startTime: number;
77
- endTime?: number;
78
- duration?: number;
79
- status?: string;
80
- attributes?: Record<string, any>;
81
- events: Array<{
82
- time: number;
83
- name: string;
84
- attributes?: Record<string, any>;
85
- }>;
86
- }
87
-
88
- /**
89
- * Execution artifact file structure
90
- */
91
- export interface ExecutionArtifact {
92
- metadata?: {
93
- canvasName?: string;
94
- exportedAt?: string;
95
- source?: string;
96
- framework?: string;
97
- status?: 'success' | 'error';
98
- };
99
- spans: ExecutionSpan[];
100
- }
101
-
102
- /**
103
- * File tree entry for discovery
104
- */
105
- export interface FileTreeEntry {
106
- path?: string;
107
- relativePath?: string;
108
- name?: string;
109
- }
110
-
111
- /**
112
- * Options for execution file discovery
113
- */
114
- export interface DiscoveryOptions {
115
- /** Whether to include package-level .principal-views folders */
116
- includePackagePrincipalViews?: boolean;
117
- /** Custom execution folder names (defaults to ['__executions__']) */
118
- executionFolders?: string[];
119
- /** Custom canvas extensions (defaults to ['.otel.canvas']) */
120
- canvasExtensions?: string[];
121
- }
122
-
123
- /**
124
- * Execution File Discovery Engine
125
- *
126
- * Discovers execution artifacts and canvas files using monorepo-aware logic.
127
- */
128
- export class ExecutionFileDiscovery {
129
- private packageLayerModule: PackageLayerModule;
130
- private options: Required<DiscoveryOptions>;
131
-
132
- constructor(options: DiscoveryOptions = {}) {
133
- this.packageLayerModule = new PackageLayerModule();
134
- this.options = {
135
- includePackagePrincipalViews: options.includePackagePrincipalViews ?? true,
136
- executionFolders: options.executionFolders ?? ['__executions__'],
137
- canvasExtensions: options.canvasExtensions ?? ['.otel.canvas'],
138
- };
139
- }
140
-
141
- /**
142
- * Find all execution artifact files in the repository
143
- */
144
- async findExecutionFiles(files: FileTreeEntry[]): Promise<ExecutionFile[]> {
145
- const executionFiles: ExecutionFile[] = [];
146
-
147
- // Detect packages in the repository
148
- const packages = await this.detectPackages(files);
149
-
150
- // Search for execution files in each package
151
- for (const pkg of packages) {
152
- const pkgExecutions = this.findExecutionsInPackage(pkg, files);
153
- executionFiles.push(...pkgExecutions);
154
- }
155
-
156
- // Search in root-level locations
157
- const rootExecutions = this.findExecutionsInRoot(files);
158
- executionFiles.push(...rootExecutions);
159
-
160
- // Sort by package name, then by basename
161
- return this.sortExecutionFiles(executionFiles);
162
- }
163
-
164
- /**
165
- * Find all canvas files in the repository
166
- */
167
- async findCanvasFiles(files: FileTreeEntry[]): Promise<CanvasFile[]> {
168
- const canvasFiles: CanvasFile[] = [];
169
-
170
- // Detect packages in the repository
171
- const packages = await this.detectPackages(files);
172
-
173
- // Search for canvas files in root .principal-views/
174
- const rootCanvases = this.findCanvasesInDirectory('.principal-views', files);
175
- canvasFiles.push(...rootCanvases);
176
-
177
- // Search for canvas files in package-level .principal-views/ if enabled
178
- if (this.options.includePackagePrincipalViews) {
179
- for (const pkg of packages) {
180
- const pkgCanvases = this.findCanvasesInDirectory(
181
- `${pkg.packageData.path}/.principal-views`,
182
- files,
183
- this.createPackageContext(pkg)
184
- );
185
- canvasFiles.push(...pkgCanvases);
186
- }
187
- }
188
-
189
- // Sort by name
190
- return canvasFiles.sort((a, b) => a.name.localeCompare(b.name));
191
- }
192
-
193
- /**
194
- * Find execution artifact for a given canvas
195
- * Now package-aware - can disambiguate between packages
196
- */
197
- findExecutionForCanvas(
198
- canvas: CanvasFile,
199
- executionFiles: ExecutionFile[]
200
- ): ExecutionFile | null {
201
- // First, try exact package match if canvas has package context
202
- if (canvas.packageContext) {
203
- const exactMatch = executionFiles.find(
204
- exec =>
205
- exec.canvasBasename === canvas.basename &&
206
- exec.packageContext?.name === canvas.packageContext?.name
207
- );
208
- if (exactMatch) return exactMatch;
209
- }
210
-
211
- // Fallback to basename-only match (for root-level canvases)
212
- return executionFiles.find(exec => exec.canvasBasename === canvas.basename) || null;
213
- }
214
-
215
- /**
216
- * Find canvas file for a given execution
217
- */
218
- findCanvasForExecution(
219
- execution: ExecutionFile,
220
- canvasFiles: CanvasFile[]
221
- ): CanvasFile | null {
222
- // First, try exact package match if execution has package context
223
- if (execution.packageContext) {
224
- const exactMatch = canvasFiles.find(
225
- canvas =>
226
- canvas.basename === execution.canvasBasename &&
227
- canvas.packageContext?.name === execution.packageContext?.name
228
- );
229
- if (exactMatch) return exactMatch;
230
- }
231
-
232
- // Fallback to basename-only match (for root-level executions)
233
- return canvasFiles.find(canvas => canvas.basename === execution.canvasBasename) || null;
234
- }
235
-
236
- /**
237
- * Parse execution artifact JSON
238
- */
239
- static parseExecutionArtifact(content: string): ExecutionArtifact {
240
- try {
241
- const parsed = JSON.parse(content);
242
- return parsed as ExecutionArtifact;
243
- } catch (error) {
244
- throw new Error(`Failed to parse execution artifact JSON: ${(error as Error).message}`);
245
- }
246
- }
247
-
248
- /**
249
- * Get spans from an artifact
250
- */
251
- static getSpans(artifact: ExecutionArtifact): ExecutionSpan[] {
252
- return artifact.spans || [];
253
- }
254
-
255
- /**
256
- * Extract metadata from an execution artifact
257
- */
258
- static getExecutionMetadata(artifact: ExecutionArtifact): ExecutionMetadata {
259
- const spans = ExecutionFileDiscovery.getSpans(artifact);
260
- const spanCount = spans.length;
261
-
262
- const eventCount = spans.reduce((total, span) => {
263
- return total + (span.events?.length || 0);
264
- }, 0);
265
-
266
- const metadata = artifact.metadata;
267
-
268
- let status: 'success' | 'error' | 'OK' = 'success';
269
- if (metadata?.status) {
270
- status = metadata.status;
271
- } else if (spans.length > 0) {
272
- const hasError = spans.some(
273
- s => s.status === 'ERROR' || s.status === 'error' || s.status === 'FAILED'
274
- );
275
- status = hasError ? 'error' : 'OK';
276
- }
277
-
278
- return {
279
- name: metadata?.canvasName || 'Untitled Execution',
280
- canvasName: metadata?.canvasName,
281
- exportedAt: metadata?.exportedAt,
282
- source: metadata?.source,
283
- framework: metadata?.framework,
284
- status,
285
- spanCount,
286
- eventCount,
287
- };
288
- }
289
-
290
- // Private helper methods
291
-
292
- /**
293
- * Detect packages using codebase-composition
294
- */
295
- private async detectPackages(files: FileTreeEntry[]): Promise<PackageLayer[]> {
296
- try {
297
- // Convert files to the format expected by codebase-composition
298
- const fileTree = this.convertToFileTree(files);
299
- const packages = await this.packageLayerModule.discoverPackages(fileTree);
300
- return packages || [];
301
- } catch (error) {
302
- // If package detection fails, continue with fallback patterns
303
- console.warn('Package detection failed, using fallback patterns:', error);
304
- return [];
305
- }
306
- }
307
-
308
- /**
309
- * Convert file entries to file tree format for codebase-composition
310
- */
311
- private convertToFileTree(files: FileTreeEntry[]): any {
312
- // This is a simplified conversion - codebase-composition expects a specific format
313
- // In practice, the caller should provide a proper FileTree from repository-abstraction
314
- return {
315
- files: files.map(f => ({
316
- path: f.relativePath || f.path || '',
317
- name: f.name || (f.relativePath || f.path || '').split('/').pop() || '',
318
- })),
319
- };
320
- }
321
-
322
- /**
323
- * Find executions in a specific package
324
- */
325
- private findExecutionsInPackage(
326
- pkg: PackageLayer,
327
- files: FileTreeEntry[]
328
- ): ExecutionFile[] {
329
- const executions: ExecutionFile[] = [];
330
- const pkgPath = pkg.packageData.path || '';
331
- const packageContext = this.createPackageContext(pkg);
332
-
333
- for (const execFolder of this.options.executionFolders) {
334
- const execPath = pkgPath ? `${pkgPath}/${execFolder}` : execFolder;
335
-
336
- for (const file of files) {
337
- const filePath = file.relativePath || file.path || '';
338
- const fileName = file.name || filePath.split('/').pop() || '';
339
-
340
- if (filePath.startsWith(execPath + '/') && this.isExecutionFile(fileName)) {
341
- const basename = this.extractExecutionBasename(fileName);
342
- executions.push({
343
- id: this.generateExecutionId(basename, packageContext),
344
- name: this.formatDisplayName(basename),
345
- path: filePath,
346
- canvasBasename: basename,
347
- packageContext,
348
- });
349
- }
350
- }
351
- }
352
-
353
- return executions;
354
- }
355
-
356
- /**
357
- * Find executions in root-level locations
358
- */
359
- private findExecutionsInRoot(files: FileTreeEntry[]): ExecutionFile[] {
360
- const executions: ExecutionFile[] = [];
361
-
362
- // Root __executions__/
363
- for (const execFolder of this.options.executionFolders) {
364
- for (const file of files) {
365
- const filePath = file.relativePath || file.path || '';
366
- const fileName = file.name || filePath.split('/').pop() || '';
367
-
368
- if (filePath.startsWith(`${execFolder}/`) && this.isExecutionFile(fileName)) {
369
- const basename = this.extractExecutionBasename(fileName);
370
- executions.push({
371
- id: `root-${basename}`,
372
- name: this.formatDisplayName(basename),
373
- path: filePath,
374
- canvasBasename: basename,
375
- });
376
- }
377
- }
378
- }
379
-
380
- // .principal-views/__executions__/
381
- const pvExecPath = '.principal-views/__executions__';
382
- for (const file of files) {
383
- const filePath = file.relativePath || file.path || '';
384
- const fileName = file.name || filePath.split('/').pop() || '';
385
-
386
- if (filePath.startsWith(pvExecPath + '/') && this.isExecutionFile(fileName)) {
387
- const basename = this.extractExecutionBasename(fileName);
388
- executions.push({
389
- id: `pv-${basename}`,
390
- name: this.formatDisplayName(basename),
391
- path: filePath,
392
- canvasBasename: basename,
393
- });
394
- }
395
- }
396
-
397
- return executions;
398
- }
399
-
400
- /**
401
- * Find canvas files in a specific directory
402
- */
403
- private findCanvasesInDirectory(
404
- directory: string,
405
- files: FileTreeEntry[],
406
- packageContext?: PackageContext
407
- ): CanvasFile[] {
408
- const canvases: CanvasFile[] = [];
409
-
410
- for (const file of files) {
411
- const filePath = file.relativePath || file.path || '';
412
- const fileName = file.name || filePath.split('/').pop() || '';
413
-
414
- if (filePath.startsWith(directory + '/') && this.isCanvasFile(fileName)) {
415
- const basename = this.extractCanvasBasename(fileName);
416
- canvases.push({
417
- id: this.generateCanvasId(basename, packageContext),
418
- name: this.formatDisplayName(basename),
419
- path: filePath,
420
- basename,
421
- packageContext,
422
- });
423
- }
424
- }
425
-
426
- return canvases;
427
- }
428
-
429
- /**
430
- * Create package context from PackageLayer
431
- */
432
- private createPackageContext(pkg: PackageLayer): PackageContext {
433
- return {
434
- name: pkg.packageData.name || 'unknown',
435
- packagePath: pkg.packageData.path || '',
436
- packageType: pkg.type,
437
- };
438
- }
439
-
440
- /**
441
- * Check if filename is an execution file
442
- */
443
- private isExecutionFile(filename: string): boolean {
444
- return /\.(spans|execution|events)\.json$/.test(filename);
445
- }
446
-
447
- /**
448
- * Check if filename is a canvas file
449
- */
450
- private isCanvasFile(filename: string): boolean {
451
- return this.options.canvasExtensions.some(ext => filename.endsWith(ext));
452
- }
453
-
454
- /**
455
- * Extract basename from execution filename
456
- */
457
- private extractExecutionBasename(filename: string): string {
458
- return filename.replace(/\.(spans|execution|events)\.json$/, '');
459
- }
460
-
461
- /**
462
- * Extract basename from canvas filename
463
- */
464
- private extractCanvasBasename(filename: string): string {
465
- for (const ext of this.options.canvasExtensions) {
466
- if (filename.endsWith(ext)) {
467
- return filename.slice(0, -ext.length);
468
- }
469
- }
470
- return filename;
471
- }
472
-
473
- /**
474
- * Format display name from basename (kebab-case to Title Case)
475
- */
476
- private formatDisplayName(basename: string): string {
477
- return basename
478
- .split('-')
479
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
480
- .join(' ');
481
- }
482
-
483
- /**
484
- * Generate unique ID for execution file
485
- */
486
- private generateExecutionId(basename: string, packageContext?: PackageContext): string {
487
- if (packageContext) {
488
- return `${packageContext.name}-${basename}`;
489
- }
490
- return basename;
491
- }
492
-
493
- /**
494
- * Generate unique ID for canvas file
495
- */
496
- private generateCanvasId(basename: string, packageContext?: PackageContext): string {
497
- if (packageContext) {
498
- return `${packageContext.name}-${basename}`;
499
- }
500
- return basename;
501
- }
502
-
503
- /**
504
- * Sort execution files by package name, then by basename
505
- */
506
- private sortExecutionFiles(files: ExecutionFile[]): ExecutionFile[] {
507
- return files.sort((a, b) => {
508
- // Sort by package name first
509
- if (a.packageContext && b.packageContext) {
510
- const pkgCompare = a.packageContext.name.localeCompare(b.packageContext.name);
511
- if (pkgCompare !== 0) return pkgCompare;
512
- } else if (a.packageContext) {
513
- return -1;
514
- } else if (b.packageContext) {
515
- return 1;
516
- }
517
-
518
- // Then by basename
519
- return a.canvasBasename.localeCompare(b.canvasBasename);
520
- });
521
- }
522
- }