@principal-ai/principal-view-core 0.5.17 → 0.6.1
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.
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/ExecutionFileDiscovery.d.ts +206 -0
- package/dist/utils/ExecutionFileDiscovery.d.ts.map +1 -0
- package/dist/utils/ExecutionFileDiscovery.js +340 -0
- package/dist/utils/ExecutionFileDiscovery.js.map +1 -0
- package/package.json +2 -1
- package/src/index.ts +13 -0
- package/src/utils/ExecutionFileDiscovery.ts +522 -0
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export { PathBasedEventProcessor } from './PathBasedEventProcessor';
|
|
|
13
13
|
export type { LogEntry } from './PathBasedEventProcessor';
|
|
14
14
|
export { PathMatcher } from './utils/PathMatcher';
|
|
15
15
|
export { GraphConverter } from './utils/GraphConverter';
|
|
16
|
+
export { ExecutionFileDiscovery } from './utils/ExecutionFileDiscovery';
|
|
17
|
+
export type { ExecutionFile, CanvasFile, PackageContext, ExecutionMetadata, ExecutionSpan, ExecutionArtifact, FileTreeEntry, DiscoveryOptions, } from './utils/ExecutionFileDiscovery';
|
|
16
18
|
export * from './types/canvas';
|
|
17
19
|
export { CanvasConverter } from './utils/CanvasConverter';
|
|
18
20
|
export type { ReactFlowNode, ReactFlowEdge } from './utils/CanvasConverter';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EACV,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAGlF,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,YAAY,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG5E,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAC3G,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAGpE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG5G,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjG,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG7F,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACzE,YAAY,EACV,SAAS,EACT,WAAW,EACX,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EACV,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,UAAU,EACV,eAAe,EACf,eAAe,EACf,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AACtF,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGrF,YAAY,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,8 @@ export { PathBasedEventProcessor } from './PathBasedEventProcessor';
|
|
|
15
15
|
// Export path utilities
|
|
16
16
|
export { PathMatcher } from './utils/PathMatcher';
|
|
17
17
|
export { GraphConverter } from './utils/GraphConverter';
|
|
18
|
+
// Export execution file discovery
|
|
19
|
+
export { ExecutionFileDiscovery } from './utils/ExecutionFileDiscovery';
|
|
18
20
|
// Export Canvas types and converter
|
|
19
21
|
export * from './types/canvas';
|
|
20
22
|
export { CanvasConverter } from './utils/CanvasConverter';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mBAAmB;AACnB,cAAc,SAAS,CAAC;AAExB,sBAAsB;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAMlE,iBAAiB;AACjB,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAElF,iDAAiD;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,wBAAwB;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,oCAAoC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,oCAAoC;AACpC,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAG3G,qCAAqC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,yBAAyB;AACzB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGjG,oCAAoC;AACpC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAQzE,qDAAqD;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAYlD,gCAAgC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAqB9D,+DAA+D;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGtF,mCAAmC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAK5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,sBAAsB;AACtB,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mBAAmB;AACnB,cAAc,SAAS,CAAC;AAExB,sBAAsB;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAMlE,iBAAiB;AACjB,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAElF,iDAAiD;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,wBAAwB;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,kCAAkC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAYxE,oCAAoC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,oCAAoC;AACpC,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAG3G,qCAAqC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,yBAAyB;AACzB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGjG,oCAAoC;AACpC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAQzE,qDAAqD;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAYlD,gCAAgC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAqB9D,+DAA+D;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGtF,mCAAmC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAK5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,sBAAsB;AACtB,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,206 @@
|
|
|
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
|
+
* Represents a discovered execution artifact file
|
|
10
|
+
*/
|
|
11
|
+
export interface ExecutionFile {
|
|
12
|
+
/** Unique identifier for this execution */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Display name for this execution */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Full file path (relative to repository root) */
|
|
17
|
+
path: string;
|
|
18
|
+
/** Canvas basename (without extension) that this execution is linked to */
|
|
19
|
+
canvasBasename: string;
|
|
20
|
+
/** Package context if this execution belongs to a specific package */
|
|
21
|
+
packageContext?: PackageContext;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Represents a discovered canvas file
|
|
25
|
+
*/
|
|
26
|
+
export interface CanvasFile {
|
|
27
|
+
/** Unique identifier for this canvas */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Display name for this canvas */
|
|
30
|
+
name: string;
|
|
31
|
+
/** Full file path (relative to repository root) */
|
|
32
|
+
path: string;
|
|
33
|
+
/** Canvas basename (without .otel.canvas or .canvas extension) */
|
|
34
|
+
basename: string;
|
|
35
|
+
/** Package context if this canvas belongs to a specific package */
|
|
36
|
+
packageContext?: PackageContext;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Package context for execution/canvas files
|
|
40
|
+
*/
|
|
41
|
+
export interface PackageContext {
|
|
42
|
+
/** Package name (from package.json, Cargo.toml, etc.) */
|
|
43
|
+
name: string;
|
|
44
|
+
/** Package directory path (relative to repository root) */
|
|
45
|
+
packagePath: string;
|
|
46
|
+
/** Package type (npm, cargo, go, etc.) */
|
|
47
|
+
packageType?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Execution artifact metadata
|
|
51
|
+
*/
|
|
52
|
+
export interface ExecutionMetadata {
|
|
53
|
+
name: string;
|
|
54
|
+
canvasName?: string;
|
|
55
|
+
exportedAt?: string;
|
|
56
|
+
source?: string;
|
|
57
|
+
framework?: string;
|
|
58
|
+
status?: 'success' | 'error' | 'OK';
|
|
59
|
+
spanCount: number;
|
|
60
|
+
eventCount: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Execution span structure
|
|
64
|
+
*/
|
|
65
|
+
export interface ExecutionSpan {
|
|
66
|
+
id: string;
|
|
67
|
+
name: string;
|
|
68
|
+
startTime: number;
|
|
69
|
+
endTime?: number;
|
|
70
|
+
duration?: number;
|
|
71
|
+
status?: string;
|
|
72
|
+
attributes?: Record<string, any>;
|
|
73
|
+
events: Array<{
|
|
74
|
+
time: number;
|
|
75
|
+
name: string;
|
|
76
|
+
attributes?: Record<string, any>;
|
|
77
|
+
}>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Execution artifact file structure
|
|
81
|
+
*/
|
|
82
|
+
export interface ExecutionArtifact {
|
|
83
|
+
metadata?: {
|
|
84
|
+
canvasName?: string;
|
|
85
|
+
exportedAt?: string;
|
|
86
|
+
source?: string;
|
|
87
|
+
framework?: string;
|
|
88
|
+
status?: 'success' | 'error';
|
|
89
|
+
};
|
|
90
|
+
spans: ExecutionSpan[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* File tree entry for discovery
|
|
94
|
+
*/
|
|
95
|
+
export interface FileTreeEntry {
|
|
96
|
+
path?: string;
|
|
97
|
+
relativePath?: string;
|
|
98
|
+
name?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Options for execution file discovery
|
|
102
|
+
*/
|
|
103
|
+
export interface DiscoveryOptions {
|
|
104
|
+
/** Whether to include package-level .principal-views folders */
|
|
105
|
+
includePackagePrincipalViews?: boolean;
|
|
106
|
+
/** Custom execution folder names (defaults to ['__executions__']) */
|
|
107
|
+
executionFolders?: string[];
|
|
108
|
+
/** Custom canvas extensions (defaults to ['.otel.canvas']) */
|
|
109
|
+
canvasExtensions?: string[];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Execution File Discovery Engine
|
|
113
|
+
*
|
|
114
|
+
* Discovers execution artifacts and canvas files using monorepo-aware logic.
|
|
115
|
+
*/
|
|
116
|
+
export declare class ExecutionFileDiscovery {
|
|
117
|
+
private packageLayerModule;
|
|
118
|
+
private options;
|
|
119
|
+
constructor(options?: DiscoveryOptions);
|
|
120
|
+
/**
|
|
121
|
+
* Find all execution artifact files in the repository
|
|
122
|
+
*/
|
|
123
|
+
findExecutionFiles(files: FileTreeEntry[]): Promise<ExecutionFile[]>;
|
|
124
|
+
/**
|
|
125
|
+
* Find all canvas files in the repository
|
|
126
|
+
*/
|
|
127
|
+
findCanvasFiles(files: FileTreeEntry[]): Promise<CanvasFile[]>;
|
|
128
|
+
/**
|
|
129
|
+
* Find execution artifact for a given canvas
|
|
130
|
+
* Now package-aware - can disambiguate between packages
|
|
131
|
+
*/
|
|
132
|
+
findExecutionForCanvas(canvas: CanvasFile, executionFiles: ExecutionFile[]): ExecutionFile | null;
|
|
133
|
+
/**
|
|
134
|
+
* Find canvas file for a given execution
|
|
135
|
+
*/
|
|
136
|
+
findCanvasForExecution(execution: ExecutionFile, canvasFiles: CanvasFile[]): CanvasFile | null;
|
|
137
|
+
/**
|
|
138
|
+
* Parse execution artifact JSON
|
|
139
|
+
*/
|
|
140
|
+
static parseExecutionArtifact(content: string): ExecutionArtifact;
|
|
141
|
+
/**
|
|
142
|
+
* Get spans from an artifact
|
|
143
|
+
*/
|
|
144
|
+
static getSpans(artifact: ExecutionArtifact): ExecutionSpan[];
|
|
145
|
+
/**
|
|
146
|
+
* Extract metadata from an execution artifact
|
|
147
|
+
*/
|
|
148
|
+
static getExecutionMetadata(artifact: ExecutionArtifact): ExecutionMetadata;
|
|
149
|
+
/**
|
|
150
|
+
* Detect packages using codebase-composition
|
|
151
|
+
*/
|
|
152
|
+
private detectPackages;
|
|
153
|
+
/**
|
|
154
|
+
* Convert file entries to file tree format for codebase-composition
|
|
155
|
+
*/
|
|
156
|
+
private convertToFileTree;
|
|
157
|
+
/**
|
|
158
|
+
* Find executions in a specific package
|
|
159
|
+
*/
|
|
160
|
+
private findExecutionsInPackage;
|
|
161
|
+
/**
|
|
162
|
+
* Find executions in root-level locations
|
|
163
|
+
*/
|
|
164
|
+
private findExecutionsInRoot;
|
|
165
|
+
/**
|
|
166
|
+
* Find canvas files in a specific directory
|
|
167
|
+
*/
|
|
168
|
+
private findCanvasesInDirectory;
|
|
169
|
+
/**
|
|
170
|
+
* Create package context from PackageLayer
|
|
171
|
+
*/
|
|
172
|
+
private createPackageContext;
|
|
173
|
+
/**
|
|
174
|
+
* Check if filename is an execution file
|
|
175
|
+
*/
|
|
176
|
+
private isExecutionFile;
|
|
177
|
+
/**
|
|
178
|
+
* Check if filename is a canvas file
|
|
179
|
+
*/
|
|
180
|
+
private isCanvasFile;
|
|
181
|
+
/**
|
|
182
|
+
* Extract basename from execution filename
|
|
183
|
+
*/
|
|
184
|
+
private extractExecutionBasename;
|
|
185
|
+
/**
|
|
186
|
+
* Extract basename from canvas filename
|
|
187
|
+
*/
|
|
188
|
+
private extractCanvasBasename;
|
|
189
|
+
/**
|
|
190
|
+
* Format display name from basename (kebab-case to Title Case)
|
|
191
|
+
*/
|
|
192
|
+
private formatDisplayName;
|
|
193
|
+
/**
|
|
194
|
+
* Generate unique ID for execution file
|
|
195
|
+
*/
|
|
196
|
+
private generateExecutionId;
|
|
197
|
+
/**
|
|
198
|
+
* Generate unique ID for canvas file
|
|
199
|
+
*/
|
|
200
|
+
private generateCanvasId;
|
|
201
|
+
/**
|
|
202
|
+
* Sort execution files by package name, then by basename
|
|
203
|
+
*/
|
|
204
|
+
private sortExecutionFiles;
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=ExecutionFileDiscovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecutionFileDiscovery.d.ts","sourceRoot":"","sources":["../../src/utils/ExecutionFileDiscovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,340 @@
|
|
|
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
|
+
import { PackageLayerModule } from '@principal-ai/codebase-composition/browser';
|
|
9
|
+
/**
|
|
10
|
+
* Execution File Discovery Engine
|
|
11
|
+
*
|
|
12
|
+
* Discovers execution artifacts and canvas files using monorepo-aware logic.
|
|
13
|
+
*/
|
|
14
|
+
export class ExecutionFileDiscovery {
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
this.packageLayerModule = new PackageLayerModule();
|
|
17
|
+
this.options = {
|
|
18
|
+
includePackagePrincipalViews: options.includePackagePrincipalViews ?? true,
|
|
19
|
+
executionFolders: options.executionFolders ?? ['__executions__'],
|
|
20
|
+
canvasExtensions: options.canvasExtensions ?? ['.otel.canvas'],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Find all execution artifact files in the repository
|
|
25
|
+
*/
|
|
26
|
+
async findExecutionFiles(files) {
|
|
27
|
+
const executionFiles = [];
|
|
28
|
+
// Detect packages in the repository
|
|
29
|
+
const packages = await this.detectPackages(files);
|
|
30
|
+
// Search for execution files in each package
|
|
31
|
+
for (const pkg of packages) {
|
|
32
|
+
const pkgExecutions = this.findExecutionsInPackage(pkg, files);
|
|
33
|
+
executionFiles.push(...pkgExecutions);
|
|
34
|
+
}
|
|
35
|
+
// Search in root-level locations
|
|
36
|
+
const rootExecutions = this.findExecutionsInRoot(files);
|
|
37
|
+
executionFiles.push(...rootExecutions);
|
|
38
|
+
// Sort by package name, then by basename
|
|
39
|
+
return this.sortExecutionFiles(executionFiles);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Find all canvas files in the repository
|
|
43
|
+
*/
|
|
44
|
+
async findCanvasFiles(files) {
|
|
45
|
+
const canvasFiles = [];
|
|
46
|
+
// Detect packages in the repository
|
|
47
|
+
const packages = await this.detectPackages(files);
|
|
48
|
+
// Search for canvas files in root .principal-views/
|
|
49
|
+
const rootCanvases = this.findCanvasesInDirectory('.principal-views', files);
|
|
50
|
+
canvasFiles.push(...rootCanvases);
|
|
51
|
+
// Search for canvas files in package-level .principal-views/ if enabled
|
|
52
|
+
if (this.options.includePackagePrincipalViews) {
|
|
53
|
+
for (const pkg of packages) {
|
|
54
|
+
const pkgCanvases = this.findCanvasesInDirectory(`${pkg.packageData.path}/.principal-views`, files, this.createPackageContext(pkg));
|
|
55
|
+
canvasFiles.push(...pkgCanvases);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Sort by name
|
|
59
|
+
return canvasFiles.sort((a, b) => a.name.localeCompare(b.name));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Find execution artifact for a given canvas
|
|
63
|
+
* Now package-aware - can disambiguate between packages
|
|
64
|
+
*/
|
|
65
|
+
findExecutionForCanvas(canvas, executionFiles) {
|
|
66
|
+
// First, try exact package match if canvas has package context
|
|
67
|
+
if (canvas.packageContext) {
|
|
68
|
+
const exactMatch = executionFiles.find(exec => exec.canvasBasename === canvas.basename &&
|
|
69
|
+
exec.packageContext?.name === canvas.packageContext?.name);
|
|
70
|
+
if (exactMatch)
|
|
71
|
+
return exactMatch;
|
|
72
|
+
}
|
|
73
|
+
// Fallback to basename-only match (for root-level canvases)
|
|
74
|
+
return executionFiles.find(exec => exec.canvasBasename === canvas.basename) || null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Find canvas file for a given execution
|
|
78
|
+
*/
|
|
79
|
+
findCanvasForExecution(execution, canvasFiles) {
|
|
80
|
+
// First, try exact package match if execution has package context
|
|
81
|
+
if (execution.packageContext) {
|
|
82
|
+
const exactMatch = canvasFiles.find(canvas => canvas.basename === execution.canvasBasename &&
|
|
83
|
+
canvas.packageContext?.name === execution.packageContext?.name);
|
|
84
|
+
if (exactMatch)
|
|
85
|
+
return exactMatch;
|
|
86
|
+
}
|
|
87
|
+
// Fallback to basename-only match (for root-level executions)
|
|
88
|
+
return canvasFiles.find(canvas => canvas.basename === execution.canvasBasename) || null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parse execution artifact JSON
|
|
92
|
+
*/
|
|
93
|
+
static parseExecutionArtifact(content) {
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(content);
|
|
96
|
+
return parsed;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw new Error(`Failed to parse execution artifact JSON: ${error.message}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get spans from an artifact
|
|
104
|
+
*/
|
|
105
|
+
static getSpans(artifact) {
|
|
106
|
+
return artifact.spans || [];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Extract metadata from an execution artifact
|
|
110
|
+
*/
|
|
111
|
+
static getExecutionMetadata(artifact) {
|
|
112
|
+
const spans = ExecutionFileDiscovery.getSpans(artifact);
|
|
113
|
+
const spanCount = spans.length;
|
|
114
|
+
const eventCount = spans.reduce((total, span) => {
|
|
115
|
+
return total + (span.events?.length || 0);
|
|
116
|
+
}, 0);
|
|
117
|
+
const metadata = artifact.metadata;
|
|
118
|
+
let status = 'success';
|
|
119
|
+
if (metadata?.status) {
|
|
120
|
+
status = metadata.status;
|
|
121
|
+
}
|
|
122
|
+
else if (spans.length > 0) {
|
|
123
|
+
const hasError = spans.some(s => s.status === 'ERROR' || s.status === 'error' || s.status === 'FAILED');
|
|
124
|
+
status = hasError ? 'error' : 'OK';
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
name: metadata?.canvasName || 'Untitled Execution',
|
|
128
|
+
canvasName: metadata?.canvasName,
|
|
129
|
+
exportedAt: metadata?.exportedAt,
|
|
130
|
+
source: metadata?.source,
|
|
131
|
+
framework: metadata?.framework,
|
|
132
|
+
status,
|
|
133
|
+
spanCount,
|
|
134
|
+
eventCount,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// Private helper methods
|
|
138
|
+
/**
|
|
139
|
+
* Detect packages using codebase-composition
|
|
140
|
+
*/
|
|
141
|
+
async detectPackages(files) {
|
|
142
|
+
try {
|
|
143
|
+
// Convert files to the format expected by codebase-composition
|
|
144
|
+
const fileTree = this.convertToFileTree(files);
|
|
145
|
+
const packages = await this.packageLayerModule.discoverPackages(fileTree);
|
|
146
|
+
return packages || [];
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
// If package detection fails, continue with fallback patterns
|
|
150
|
+
console.warn('Package detection failed, using fallback patterns:', error);
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Convert file entries to file tree format for codebase-composition
|
|
156
|
+
*/
|
|
157
|
+
convertToFileTree(files) {
|
|
158
|
+
// This is a simplified conversion - codebase-composition expects a specific format
|
|
159
|
+
// In practice, the caller should provide a proper FileTree from repository-abstraction
|
|
160
|
+
return {
|
|
161
|
+
files: files.map(f => ({
|
|
162
|
+
path: f.relativePath || f.path || '',
|
|
163
|
+
name: f.name || (f.relativePath || f.path || '').split('/').pop() || '',
|
|
164
|
+
})),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Find executions in a specific package
|
|
169
|
+
*/
|
|
170
|
+
findExecutionsInPackage(pkg, files) {
|
|
171
|
+
const executions = [];
|
|
172
|
+
const pkgPath = pkg.packageData.path || '';
|
|
173
|
+
const packageContext = this.createPackageContext(pkg);
|
|
174
|
+
for (const execFolder of this.options.executionFolders) {
|
|
175
|
+
const execPath = pkgPath ? `${pkgPath}/${execFolder}` : execFolder;
|
|
176
|
+
for (const file of files) {
|
|
177
|
+
const filePath = file.relativePath || file.path || '';
|
|
178
|
+
const fileName = file.name || filePath.split('/').pop() || '';
|
|
179
|
+
if (filePath.startsWith(execPath + '/') && this.isExecutionFile(fileName)) {
|
|
180
|
+
const basename = this.extractExecutionBasename(fileName);
|
|
181
|
+
executions.push({
|
|
182
|
+
id: this.generateExecutionId(basename, packageContext),
|
|
183
|
+
name: this.formatDisplayName(basename),
|
|
184
|
+
path: filePath,
|
|
185
|
+
canvasBasename: basename,
|
|
186
|
+
packageContext,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return executions;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Find executions in root-level locations
|
|
195
|
+
*/
|
|
196
|
+
findExecutionsInRoot(files) {
|
|
197
|
+
const executions = [];
|
|
198
|
+
// Root __executions__/
|
|
199
|
+
for (const execFolder of this.options.executionFolders) {
|
|
200
|
+
for (const file of files) {
|
|
201
|
+
const filePath = file.relativePath || file.path || '';
|
|
202
|
+
const fileName = file.name || filePath.split('/').pop() || '';
|
|
203
|
+
if (filePath.startsWith(`${execFolder}/`) && this.isExecutionFile(fileName)) {
|
|
204
|
+
const basename = this.extractExecutionBasename(fileName);
|
|
205
|
+
executions.push({
|
|
206
|
+
id: `root-${basename}`,
|
|
207
|
+
name: this.formatDisplayName(basename),
|
|
208
|
+
path: filePath,
|
|
209
|
+
canvasBasename: basename,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// .principal-views/__executions__/
|
|
215
|
+
const pvExecPath = '.principal-views/__executions__';
|
|
216
|
+
for (const file of files) {
|
|
217
|
+
const filePath = file.relativePath || file.path || '';
|
|
218
|
+
const fileName = file.name || filePath.split('/').pop() || '';
|
|
219
|
+
if (filePath.startsWith(pvExecPath + '/') && this.isExecutionFile(fileName)) {
|
|
220
|
+
const basename = this.extractExecutionBasename(fileName);
|
|
221
|
+
executions.push({
|
|
222
|
+
id: `pv-${basename}`,
|
|
223
|
+
name: this.formatDisplayName(basename),
|
|
224
|
+
path: filePath,
|
|
225
|
+
canvasBasename: basename,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return executions;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Find canvas files in a specific directory
|
|
233
|
+
*/
|
|
234
|
+
findCanvasesInDirectory(directory, files, packageContext) {
|
|
235
|
+
const canvases = [];
|
|
236
|
+
for (const file of files) {
|
|
237
|
+
const filePath = file.relativePath || file.path || '';
|
|
238
|
+
const fileName = file.name || filePath.split('/').pop() || '';
|
|
239
|
+
if (filePath.startsWith(directory + '/') && this.isCanvasFile(fileName)) {
|
|
240
|
+
const basename = this.extractCanvasBasename(fileName);
|
|
241
|
+
canvases.push({
|
|
242
|
+
id: this.generateCanvasId(basename, packageContext),
|
|
243
|
+
name: this.formatDisplayName(basename),
|
|
244
|
+
path: filePath,
|
|
245
|
+
basename,
|
|
246
|
+
packageContext,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return canvases;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Create package context from PackageLayer
|
|
254
|
+
*/
|
|
255
|
+
createPackageContext(pkg) {
|
|
256
|
+
return {
|
|
257
|
+
name: pkg.packageData.name || 'unknown',
|
|
258
|
+
packagePath: pkg.packageData.path || '',
|
|
259
|
+
packageType: pkg.type,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Check if filename is an execution file
|
|
264
|
+
*/
|
|
265
|
+
isExecutionFile(filename) {
|
|
266
|
+
return /\.(spans|execution|events)\.json$/.test(filename);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Check if filename is a canvas file
|
|
270
|
+
*/
|
|
271
|
+
isCanvasFile(filename) {
|
|
272
|
+
return this.options.canvasExtensions.some(ext => filename.endsWith(ext));
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Extract basename from execution filename
|
|
276
|
+
*/
|
|
277
|
+
extractExecutionBasename(filename) {
|
|
278
|
+
return filename.replace(/\.(spans|execution|events)\.json$/, '');
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Extract basename from canvas filename
|
|
282
|
+
*/
|
|
283
|
+
extractCanvasBasename(filename) {
|
|
284
|
+
for (const ext of this.options.canvasExtensions) {
|
|
285
|
+
if (filename.endsWith(ext)) {
|
|
286
|
+
return filename.slice(0, -ext.length);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return filename;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Format display name from basename (kebab-case to Title Case)
|
|
293
|
+
*/
|
|
294
|
+
formatDisplayName(basename) {
|
|
295
|
+
return basename
|
|
296
|
+
.split('-')
|
|
297
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
298
|
+
.join(' ');
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Generate unique ID for execution file
|
|
302
|
+
*/
|
|
303
|
+
generateExecutionId(basename, packageContext) {
|
|
304
|
+
if (packageContext) {
|
|
305
|
+
return `${packageContext.name}-${basename}`;
|
|
306
|
+
}
|
|
307
|
+
return basename;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Generate unique ID for canvas file
|
|
311
|
+
*/
|
|
312
|
+
generateCanvasId(basename, packageContext) {
|
|
313
|
+
if (packageContext) {
|
|
314
|
+
return `${packageContext.name}-${basename}`;
|
|
315
|
+
}
|
|
316
|
+
return basename;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Sort execution files by package name, then by basename
|
|
320
|
+
*/
|
|
321
|
+
sortExecutionFiles(files) {
|
|
322
|
+
return files.sort((a, b) => {
|
|
323
|
+
// Sort by package name first
|
|
324
|
+
if (a.packageContext && b.packageContext) {
|
|
325
|
+
const pkgCompare = a.packageContext.name.localeCompare(b.packageContext.name);
|
|
326
|
+
if (pkgCompare !== 0)
|
|
327
|
+
return pkgCompare;
|
|
328
|
+
}
|
|
329
|
+
else if (a.packageContext) {
|
|
330
|
+
return -1;
|
|
331
|
+
}
|
|
332
|
+
else if (b.packageContext) {
|
|
333
|
+
return 1;
|
|
334
|
+
}
|
|
335
|
+
// Then by basename
|
|
336
|
+
return a.canvasBasename.localeCompare(b.canvasBasename);
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=ExecutionFileDiscovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExecutionFileDiscovery.js","sourceRoot":"","sources":["../../src/utils/ExecutionFileDiscovery.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principal-ai/principal-view-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Core logic and types for graph-based principal view framework",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"zod": "^3.22.0",
|
|
29
29
|
"date-fns": "^3.0.0",
|
|
30
30
|
"@principal-ai/repository-abstraction": "^0.2.5",
|
|
31
|
+
"@principal-ai/codebase-composition": "^0.2.32",
|
|
31
32
|
"js-yaml": "^4.1.0"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,19 @@ export type { LogEntry } from './PathBasedEventProcessor';
|
|
|
29
29
|
export { PathMatcher } from './utils/PathMatcher';
|
|
30
30
|
export { GraphConverter } from './utils/GraphConverter';
|
|
31
31
|
|
|
32
|
+
// Export execution file discovery
|
|
33
|
+
export { ExecutionFileDiscovery } from './utils/ExecutionFileDiscovery';
|
|
34
|
+
export type {
|
|
35
|
+
ExecutionFile,
|
|
36
|
+
CanvasFile,
|
|
37
|
+
PackageContext,
|
|
38
|
+
ExecutionMetadata,
|
|
39
|
+
ExecutionSpan,
|
|
40
|
+
ExecutionArtifact,
|
|
41
|
+
FileTreeEntry,
|
|
42
|
+
DiscoveryOptions,
|
|
43
|
+
} from './utils/ExecutionFileDiscovery';
|
|
44
|
+
|
|
32
45
|
// Export Canvas types and converter
|
|
33
46
|
export * from './types/canvas';
|
|
34
47
|
export { CanvasConverter } from './utils/CanvasConverter';
|
|
@@ -0,0 +1,522 @@
|
|
|
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
|
+
}
|