@baselineos/studio 0.1.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.
package/src/system.ts ADDED
@@ -0,0 +1,885 @@
1
+ /**
2
+ * Baseline Studio System
3
+ *
4
+ * The execution and output generation layer of the Baseline Protocol that
5
+ * orchestrates command execution, manages workflows, and generates
6
+ * structured output in multiple formats.
7
+ *
8
+ * @license Apache-2.0
9
+ */
10
+
11
+ import studioSystemConfig from './config/studio-system-config.json' with { type: 'json' };
12
+ import { createHash } from 'crypto';
13
+
14
+ // ─── Types ──────────────────────────────────────────────────────────
15
+
16
+ export interface StudioSystemConfig {
17
+ system: { name: string; version: string; description: string };
18
+ execution: ExecutionConfig;
19
+ output: OutputConfig;
20
+ workflows: WorkflowConfig;
21
+ performance: PerformanceConfig;
22
+ }
23
+
24
+ export interface ExecutionConfig {
25
+ maxConcurrent: number;
26
+ timeout: number;
27
+ retryAttempts: number;
28
+ retryDelay: number;
29
+ }
30
+
31
+ export interface OutputConfig {
32
+ formats: string[];
33
+ defaultFormat: string;
34
+ prettyPrint: boolean;
35
+ includeMetadata: boolean;
36
+ }
37
+
38
+ export interface WorkflowConfig {
39
+ maxSteps: number;
40
+ maxDepth: number;
41
+ enableRollback: boolean;
42
+ enableCheckpoints: boolean;
43
+ }
44
+
45
+ export interface PerformanceConfig {
46
+ enableCaching: boolean;
47
+ cacheSize: number;
48
+ cacheTTL: number;
49
+ enableProfiling: boolean;
50
+ }
51
+
52
+ export interface StudioCommandResult {
53
+ success: boolean;
54
+ command?: string;
55
+ result?: unknown;
56
+ output?: string;
57
+ artifacts?: ArtifactEntry[];
58
+ manifest?: ArtifactManifest;
59
+ performance?: unknown;
60
+ error?: string;
61
+ details?: string | string[];
62
+ timestamp?: string;
63
+ }
64
+
65
+ export interface WorkflowDefinition {
66
+ name: string;
67
+ steps: string[];
68
+ }
69
+
70
+ export interface WorkflowResult {
71
+ success: boolean;
72
+ workflow?: string;
73
+ result?: unknown;
74
+ steps?: unknown[];
75
+ artifacts?: ArtifactEntry[];
76
+ manifest?: ArtifactManifest;
77
+ performance?: unknown;
78
+ error?: string;
79
+ details?: string;
80
+ timestamp?: string;
81
+ }
82
+
83
+ export interface ExecutionStats {
84
+ totalExecuted: number;
85
+ successful: number;
86
+ failed: number;
87
+ averageExecutionTime: number;
88
+ }
89
+
90
+ export interface CacheEntry {
91
+ result: unknown;
92
+ timestamp: number;
93
+ ttl: number;
94
+ }
95
+
96
+ export interface TemplateDefinition {
97
+ id: string;
98
+ name: string;
99
+ format: 'text' | 'html' | 'json';
100
+ template: string;
101
+ variables?: string[];
102
+ }
103
+
104
+ export interface ArtifactProvenance {
105
+ command?: string;
106
+ workflow?: string;
107
+ step?: string;
108
+ context?: Record<string, unknown>;
109
+ templateId?: string;
110
+ generatedAt: string;
111
+ }
112
+
113
+ export interface ArtifactEntry {
114
+ id: string;
115
+ type: 'output' | 'manifest' | 'template' | 'artifact';
116
+ format: string;
117
+ content: string;
118
+ hash: string;
119
+ provenance: ArtifactProvenance;
120
+ }
121
+
122
+ export interface ArtifactManifest {
123
+ id: string;
124
+ createdAt: string;
125
+ artifacts: ArtifactEntry[];
126
+ hash: string;
127
+ }
128
+
129
+ // ─── Execution Engine ───────────────────────────────────────────────
130
+
131
+ export class ExecutionEngine {
132
+ private activeCommands = new Map<string, { command: string; startTime: number; status: string }>();
133
+ private config: ExecutionConfig = { maxConcurrent: 5, timeout: 30000, retryAttempts: 3, retryDelay: 1000 };
134
+ private stats: ExecutionStats = {
135
+ totalExecuted: 0,
136
+ successful: 0,
137
+ failed: 0,
138
+ averageExecutionTime: 0,
139
+ };
140
+
141
+ initialize(config: ExecutionConfig): void {
142
+ this.config = config;
143
+ }
144
+
145
+ async execute(
146
+ command: string,
147
+ options: Record<string, unknown>,
148
+ context: Record<string, unknown>,
149
+ ): Promise<{ success: boolean; commandId: string; result: unknown; performance: unknown; timestamp: string }> {
150
+ const commandId = `cmd-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
151
+
152
+ this.activeCommands.set(commandId, { command, startTime: Date.now(), status: 'executing' });
153
+
154
+ try {
155
+ const result = await this.simulateExecution(command, options, context);
156
+
157
+ const entry = this.activeCommands.get(commandId);
158
+ if (entry) entry.status = 'completed';
159
+
160
+ this.stats.totalExecuted++;
161
+ this.stats.successful++;
162
+
163
+ return {
164
+ success: true,
165
+ commandId,
166
+ result,
167
+ performance: this.calculatePerformance(commandId),
168
+ timestamp: new Date().toISOString(),
169
+ };
170
+ } catch (error) {
171
+ const entry = this.activeCommands.get(commandId);
172
+ if (entry) entry.status = 'failed';
173
+
174
+ this.stats.totalExecuted++;
175
+ this.stats.failed++;
176
+ throw error;
177
+ } finally {
178
+ this.activeCommands.delete(commandId);
179
+ }
180
+ }
181
+
182
+ private async simulateExecution(
183
+ command: string,
184
+ options: Record<string, unknown>,
185
+ context: Record<string, unknown>,
186
+ ): Promise<Record<string, unknown>> {
187
+ return {
188
+ command,
189
+ result: `Executed: ${command}`,
190
+ options,
191
+ context,
192
+ executionTime: 0,
193
+ success: true,
194
+ timestamp: new Date().toISOString(),
195
+ };
196
+ }
197
+
198
+ private calculatePerformance(commandId: string): Record<string, unknown> | null {
199
+ const cmd = this.activeCommands.get(commandId);
200
+ if (!cmd) return null;
201
+
202
+ return {
203
+ executionTime: Date.now() - cmd.startTime,
204
+ };
205
+ }
206
+
207
+ getStatus(): Record<string, unknown> {
208
+ return {
209
+ status: 'operational',
210
+ activeCommands: this.activeCommands.size,
211
+ maxConcurrent: this.config.maxConcurrent,
212
+ timeout: this.config.timeout,
213
+ retryAttempts: this.config.retryAttempts,
214
+ stats: this.stats,
215
+ };
216
+ }
217
+ }
218
+
219
+ // ─── Output Generator ───────────────────────────────────────────────
220
+
221
+ export class OutputGenerator {
222
+ private formatters = new Map<string, (result: Record<string, unknown>) => string>();
223
+ private config: OutputConfig = {
224
+ formats: ['json', 'yaml', 'text', 'table', 'csv'],
225
+ defaultFormat: 'text',
226
+ prettyPrint: true,
227
+ includeMetadata: true,
228
+ };
229
+
230
+ initialize(config: OutputConfig): void {
231
+ this.config = config;
232
+ this.setupFormatters();
233
+ }
234
+
235
+ private setupFormatters(): void {
236
+ this.formatters.set('json', this.formatJSON.bind(this));
237
+ this.formatters.set('yaml', this.formatYAML.bind(this));
238
+ this.formatters.set('text', this.formatText.bind(this));
239
+ this.formatters.set('table', this.formatTable.bind(this));
240
+ this.formatters.set('csv', this.formatCSV.bind(this));
241
+ this.formatters.set('html', this.formatHTML.bind(this));
242
+ }
243
+
244
+ generate(result: Record<string, unknown>, format?: string | null): string {
245
+ const outputFormat = format || this.config.defaultFormat;
246
+ const formatter = this.formatters.get(outputFormat);
247
+
248
+ if (!formatter) {
249
+ throw new Error(`Unsupported output format: ${outputFormat}`);
250
+ }
251
+
252
+ return formatter(result);
253
+ }
254
+
255
+ private formatJSON(result: Record<string, unknown>): string {
256
+ const output: Record<string, unknown> = {
257
+ success: result.success,
258
+ command: result.command,
259
+ result: result.result,
260
+ timestamp: result.timestamp,
261
+ };
262
+
263
+ if (this.config.includeMetadata) {
264
+ output.metadata = {
265
+ format: 'json',
266
+ generated: new Date().toISOString(),
267
+ version: '1.0.0',
268
+ };
269
+ }
270
+
271
+ return this.config.prettyPrint
272
+ ? JSON.stringify(output, null, 2)
273
+ : JSON.stringify(output);
274
+ }
275
+
276
+ private formatYAML(result: Record<string, unknown>): string {
277
+ let output = `success: ${result.success}\n`;
278
+ output += `command: ${result.command}\n`;
279
+ output += `result: ${result.result}\n`;
280
+ output += `timestamp: ${result.timestamp}\n`;
281
+
282
+ if (this.config.includeMetadata) {
283
+ output += `metadata:\n`;
284
+ output += ` format: yaml\n`;
285
+ output += ` generated: ${new Date().toISOString()}\n`;
286
+ output += ` version: 1.0.0\n`;
287
+ }
288
+
289
+ return output;
290
+ }
291
+
292
+ private formatText(result: Record<string, unknown>): string {
293
+ let output = `Command: ${result.command}\n`;
294
+ output += `Status: ${result.success ? 'SUCCESS' : 'FAILED'}\n`;
295
+ output += `Result: ${result.result}\n`;
296
+ output += `Timestamp: ${result.timestamp}\n`;
297
+ return output;
298
+ }
299
+
300
+ private formatTable(result: Record<string, unknown>): string {
301
+ const command = String(result.command || '').padEnd(45);
302
+ const status = (result.success ? 'SUCCESS' : 'FAILED').padEnd(45);
303
+
304
+ let output = '+---------------------------------------------------------+\n';
305
+ output += '| COMMAND EXECUTION RESULT |\n';
306
+ output += '+---------------------------------------------------------+\n';
307
+ output += `| Command | ${command} |\n`;
308
+ output += `| Status | ${status} |\n`;
309
+ output += '+---------------------------------------------------------+\n';
310
+
311
+ return output;
312
+ }
313
+
314
+ private formatCSV(result: Record<string, unknown>): string {
315
+ let output = 'Command,Status,Result,Timestamp\n';
316
+ output += `"${result.command}","${result.success ? 'SUCCESS' : 'FAILED'}","${result.result}","${result.timestamp}"\n`;
317
+ return output;
318
+ }
319
+
320
+ private formatHTML(result: Record<string, unknown>): string {
321
+ const escaped = JSON.stringify(result, null, this.config.prettyPrint ? 2 : 0)
322
+ .replace(/&/g, '&amp;')
323
+ .replace(/</g, '&lt;')
324
+ .replace(/>/g, '&gt;');
325
+ return `<!doctype html>
326
+ <html>
327
+ <head>
328
+ <meta charset="utf-8" />
329
+ <title>Baseline Studio Output</title>
330
+ <style>
331
+ body { font-family: system-ui, sans-serif; margin: 24px; }
332
+ pre { background: #f6f8fa; padding: 16px; border-radius: 8px; }
333
+ </style>
334
+ </head>
335
+ <body>
336
+ <h1>Baseline Studio Output</h1>
337
+ <pre>${escaped}</pre>
338
+ </body>
339
+ </html>`;
340
+ }
341
+
342
+ getStatus(): Record<string, unknown> {
343
+ return {
344
+ status: 'operational',
345
+ supportedFormats: this.config.formats,
346
+ defaultFormat: this.config.defaultFormat,
347
+ prettyPrint: this.config.prettyPrint,
348
+ includeMetadata: this.config.includeMetadata,
349
+ };
350
+ }
351
+ }
352
+
353
+ // ─── Workflow Manager ───────────────────────────────────────────────
354
+
355
+ export class WorkflowManager {
356
+ private activeWorkflows = new Map<string, { workflow: WorkflowDefinition; startTime: number; status: string; currentStep: number }>();
357
+ private config: WorkflowConfig = { maxSteps: 100, maxDepth: 10, enableRollback: true, enableCheckpoints: true };
358
+
359
+ initialize(config: WorkflowConfig): void {
360
+ this.config = config;
361
+ }
362
+
363
+ async execute(
364
+ workflow: WorkflowDefinition,
365
+ _options: Record<string, unknown>,
366
+ ): Promise<{ success: boolean; workflowId: string; steps: unknown[]; performance: unknown; timestamp: string }> {
367
+ const workflowId = `wf-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
368
+
369
+ this.activeWorkflows.set(workflowId, {
370
+ workflow,
371
+ startTime: Date.now(),
372
+ status: 'executing',
373
+ currentStep: 0,
374
+ });
375
+
376
+ try {
377
+ const result = await this.executeWorkflowSteps(workflow, workflowId);
378
+
379
+ const entry = this.activeWorkflows.get(workflowId);
380
+ if (entry) entry.status = 'completed';
381
+
382
+ return {
383
+ success: true,
384
+ workflowId,
385
+ steps: result.steps,
386
+ performance: result.performance,
387
+ timestamp: new Date().toISOString(),
388
+ };
389
+ } catch (error) {
390
+ const entry = this.activeWorkflows.get(workflowId);
391
+ if (entry) entry.status = 'failed';
392
+ throw error;
393
+ } finally {
394
+ this.activeWorkflows.delete(workflowId);
395
+ }
396
+ }
397
+
398
+ private async executeWorkflowSteps(
399
+ workflow: WorkflowDefinition,
400
+ workflowId: string,
401
+ ): Promise<{ steps: unknown[]; performance: { totalTime: number; stepsExecuted: number } }> {
402
+ const steps = workflow.steps || [];
403
+ const results: unknown[] = [];
404
+ const startTime = Date.now();
405
+
406
+ for (let i = 0; i < steps.length && i < this.config.maxSteps; i++) {
407
+ const step = steps[i];
408
+ const stepResult = {
409
+ stepIndex: i,
410
+ step,
411
+ status: 'completed',
412
+ result: `Step ${i + 1} executed: ${step}`,
413
+ };
414
+
415
+ results.push(stepResult);
416
+
417
+ const entry = this.activeWorkflows.get(workflowId);
418
+ if (entry) entry.currentStep = i + 1;
419
+ }
420
+
421
+ return {
422
+ steps: results,
423
+ performance: {
424
+ totalTime: Date.now() - startTime,
425
+ stepsExecuted: results.length,
426
+ },
427
+ };
428
+ }
429
+
430
+ getStatus(): Record<string, unknown> {
431
+ return {
432
+ status: 'operational',
433
+ activeWorkflows: this.activeWorkflows.size,
434
+ maxSteps: this.config.maxSteps,
435
+ maxDepth: this.config.maxDepth,
436
+ enableRollback: this.config.enableRollback,
437
+ enableCheckpoints: this.config.enableCheckpoints,
438
+ };
439
+ }
440
+ }
441
+
442
+ // ─── Template Registry ─────────────────────────────────────────────
443
+
444
+ export class TemplateRegistry {
445
+ private templates = new Map<string, TemplateDefinition>();
446
+
447
+ register(template: TemplateDefinition): void {
448
+ this.templates.set(template.id, template);
449
+ }
450
+
451
+ get(id: string): TemplateDefinition | undefined {
452
+ return this.templates.get(id);
453
+ }
454
+
455
+ list(): TemplateDefinition[] {
456
+ return Array.from(this.templates.values());
457
+ }
458
+
459
+ render(id: string, data: Record<string, unknown>): string {
460
+ const template = this.templates.get(id);
461
+ if (!template) {
462
+ throw new Error(`Template not found: ${id}`);
463
+ }
464
+ return this.renderTemplate(template.template, data);
465
+ }
466
+
467
+ private renderTemplate(template: string, data: Record<string, unknown>): string {
468
+ return template.replace(/\{\{\s*([\w.-]+)\s*\}\}/g, (_match, key: string) => {
469
+ let value: unknown = data;
470
+ for (const part of key.split('.')) {
471
+ if (value && typeof value === 'object') {
472
+ value = (value as Record<string, unknown>)[part];
473
+ continue;
474
+ }
475
+ value = undefined;
476
+ break;
477
+ }
478
+ return value === undefined || value === null ? '' : String(value);
479
+ });
480
+ }
481
+ }
482
+
483
+ // ─── Manifest Builder ──────────────────────────────────────────────
484
+
485
+ export class ArtifactManifestBuilder {
486
+ build(artifacts: ArtifactEntry[]): ArtifactManifest {
487
+ const hash = sha256(stableStringify(artifacts));
488
+ return {
489
+ id: `manifest-${Date.now()}`,
490
+ createdAt: new Date().toISOString(),
491
+ artifacts,
492
+ hash,
493
+ };
494
+ }
495
+ }
496
+
497
+ // ─── Result Processor ───────────────────────────────────────────────
498
+
499
+ export class ResultProcessor {
500
+ initialize(): void {
501
+ // Setup processors
502
+ }
503
+
504
+ process(result: Record<string, unknown>): Record<string, unknown> {
505
+ let processed = this.validateResult(result);
506
+ processed = this.transformResult(processed);
507
+ processed = this.enrichResult(processed);
508
+ return processed;
509
+ }
510
+
511
+ private validateResult(result: Record<string, unknown>): Record<string, unknown> {
512
+ let commandResult = result;
513
+
514
+ if (
515
+ result.result &&
516
+ typeof result.result === 'object' &&
517
+ (result.result as Record<string, unknown>).command
518
+ ) {
519
+ commandResult = result.result as Record<string, unknown>;
520
+ }
521
+
522
+ return commandResult;
523
+ }
524
+
525
+ private transformResult(result: Record<string, unknown>): Record<string, unknown> {
526
+ return {
527
+ ...result,
528
+ processed: true,
529
+ processedAt: new Date().toISOString(),
530
+ };
531
+ }
532
+
533
+ private enrichResult(result: Record<string, unknown>): Record<string, unknown> {
534
+ return {
535
+ ...result,
536
+ metadata: {
537
+ ...(result.metadata as Record<string, unknown> || {}),
538
+ processor: 'Baseline Studio System',
539
+ version: '1.0.0',
540
+ },
541
+ };
542
+ }
543
+ }
544
+
545
+ // ─── Performance Optimizer ──────────────────────────────────────────
546
+
547
+ export class PerformanceOptimizer {
548
+ private cache = new Map<string, CacheEntry>();
549
+ private config: PerformanceConfig = { enableCaching: true, cacheSize: 1000, cacheTTL: 300000, enableProfiling: false };
550
+ private stats = { cacheHits: 0, cacheMisses: 0, optimizationsApplied: 0 };
551
+
552
+ initialize(config: PerformanceConfig): void {
553
+ this.config = config;
554
+ }
555
+
556
+ optimize(result: Record<string, unknown>): Record<string, unknown> {
557
+ if (this.config.enableCaching) {
558
+ this.cacheResult(result);
559
+ }
560
+ this.stats.optimizationsApplied++;
561
+ return result;
562
+ }
563
+
564
+ private cacheResult(result: Record<string, unknown>): void {
565
+ const key = this.generateCacheKey(result);
566
+
567
+ if (this.cache.size >= this.config.cacheSize) {
568
+ const firstKey = this.cache.keys().next().value;
569
+ if (firstKey) this.cache.delete(firstKey);
570
+ }
571
+
572
+ this.cache.set(key, { result, timestamp: Date.now(), ttl: this.config.cacheTTL });
573
+ }
574
+
575
+ private generateCacheKey(result: Record<string, unknown>): string {
576
+ return `${result.command}-${JSON.stringify(result.options)}`;
577
+ }
578
+
579
+ getCachedResult(command: string, options: Record<string, unknown>): unknown | null {
580
+ const key = this.generateCacheKey({ command, options });
581
+ const cached = this.cache.get(key);
582
+
583
+ if (cached && Date.now() - cached.timestamp < cached.ttl) {
584
+ this.stats.cacheHits++;
585
+ return cached.result;
586
+ }
587
+
588
+ this.stats.cacheMisses++;
589
+ return null;
590
+ }
591
+
592
+ getStatus(): Record<string, unknown> {
593
+ return {
594
+ status: 'operational',
595
+ enableCaching: this.config.enableCaching,
596
+ cacheSize: this.cache.size,
597
+ cacheTTL: this.config.cacheTTL,
598
+ enableProfiling: this.config.enableProfiling,
599
+ stats: this.stats,
600
+ };
601
+ }
602
+ }
603
+
604
+ // ─── Baseline Studio System ─────────────────────────────────────────
605
+
606
+ export class BaselineStudioSystem {
607
+ private config: StudioSystemConfig;
608
+ private executionEngine: ExecutionEngine;
609
+ private outputGenerator: OutputGenerator;
610
+ private workflowManager: WorkflowManager;
611
+ private resultProcessor: ResultProcessor;
612
+ private performanceOptimizer: PerformanceOptimizer;
613
+ private templateRegistry: TemplateRegistry;
614
+ private manifestBuilder: ArtifactManifestBuilder;
615
+
616
+ constructor() {
617
+ this.config = this.loadConfiguration();
618
+ this.executionEngine = new ExecutionEngine();
619
+ this.outputGenerator = new OutputGenerator();
620
+ this.workflowManager = new WorkflowManager();
621
+ this.resultProcessor = new ResultProcessor();
622
+ this.performanceOptimizer = new PerformanceOptimizer();
623
+ this.templateRegistry = new TemplateRegistry();
624
+ this.manifestBuilder = new ArtifactManifestBuilder();
625
+ this.initializeSystem();
626
+ }
627
+
628
+ private loadConfiguration(): StudioSystemConfig {
629
+ const cfg = studioSystemConfig as {
630
+ system?: Record<string, string>;
631
+ execution?: Record<string, unknown>;
632
+ output?: Record<string, unknown>;
633
+ workflows?: Record<string, unknown>;
634
+ performance?: Record<string, unknown>;
635
+ };
636
+
637
+ const exec = cfg.execution ?? {};
638
+ const out = cfg.output ?? {};
639
+ const wf = cfg.workflows ?? {};
640
+ const perf = cfg.performance ?? {};
641
+
642
+ return {
643
+ system: {
644
+ name: (cfg.system?.name as string) ?? 'Baseline Studio System',
645
+ version: (cfg.system?.version as string) ?? '1.0.0',
646
+ description: (cfg.system?.description as string) ?? 'Execution and output generation layer for Baseline Protocol',
647
+ },
648
+ execution: {
649
+ maxConcurrent: (exec.maxConcurrent as number) ?? 5,
650
+ timeout: (exec.timeout as number) ?? 30000,
651
+ retryAttempts: (exec.retryAttempts as number) ?? 3,
652
+ retryDelay: (exec.retryDelay as number) ?? 1000,
653
+ },
654
+ output: {
655
+ formats: (out.formats as string[]) ?? ['json', 'yaml', 'text', 'table', 'csv'],
656
+ defaultFormat: (out.defaultFormat as string) ?? 'text',
657
+ prettyPrint: (out.prettyPrint as boolean) ?? true,
658
+ includeMetadata: (out.includeMetadata as boolean) ?? true,
659
+ },
660
+ workflows: {
661
+ maxSteps: (wf.maxSteps as number) ?? 100,
662
+ maxDepth: (wf.maxDepth as number) ?? 10,
663
+ enableRollback: (wf.enableRollback as boolean) ?? true,
664
+ enableCheckpoints: (wf.enableCheckpoints as boolean) ?? true,
665
+ },
666
+ performance: {
667
+ enableCaching: (perf.enableCaching as boolean) ?? true,
668
+ cacheSize: (perf.cacheSize as number) ?? 1000,
669
+ cacheTTL: (perf.cacheTTL as number) ?? 300000,
670
+ enableProfiling: (perf.enableProfiling as boolean) ?? false,
671
+ },
672
+ };
673
+ }
674
+
675
+ private initializeSystem(): void {
676
+ this.executionEngine.initialize(this.config.execution);
677
+ this.outputGenerator.initialize(this.config.output);
678
+ this.workflowManager.initialize(this.config.workflows);
679
+ this.resultProcessor.initialize();
680
+ this.performanceOptimizer.initialize(this.config.performance);
681
+ }
682
+
683
+ async executeCommand(
684
+ command: string,
685
+ options: Record<string, unknown> = {},
686
+ context: Record<string, unknown> = {},
687
+ ): Promise<StudioCommandResult> {
688
+ try {
689
+ const validation = this.validateInput(command, options, context);
690
+ if (!validation.valid) {
691
+ return { success: false, error: 'Input validation failed', details: validation.errors };
692
+ }
693
+
694
+ const executionResult = await this.executionEngine.execute(command, options, context);
695
+ const processedResult = this.resultProcessor.process(executionResult.result as Record<string, unknown>);
696
+ const output = this.outputGenerator.generate(processedResult, (options.format as string) || null);
697
+ this.performanceOptimizer.optimize(executionResult.result as Record<string, unknown>);
698
+
699
+ const artifacts = this.buildArtifacts({
700
+ command,
701
+ output,
702
+ format: (options.format as string) || this.config.output.defaultFormat,
703
+ context,
704
+ });
705
+ const manifest = this.manifestBuilder.build(artifacts);
706
+
707
+ return {
708
+ success: true,
709
+ command,
710
+ result: processedResult,
711
+ output,
712
+ artifacts,
713
+ manifest,
714
+ performance: executionResult.performance,
715
+ timestamp: new Date().toISOString(),
716
+ };
717
+ } catch (error) {
718
+ const msg = error instanceof Error ? error.message : String(error);
719
+ return {
720
+ success: false,
721
+ error: 'Command execution failed',
722
+ details: msg,
723
+ timestamp: new Date().toISOString(),
724
+ };
725
+ }
726
+ }
727
+
728
+ async executeWorkflow(
729
+ workflow: WorkflowDefinition,
730
+ options: Record<string, unknown> = {},
731
+ ): Promise<WorkflowResult> {
732
+ try {
733
+ const workflowResult = await this.workflowManager.execute(workflow, options);
734
+ const artifacts = this.buildArtifacts({
735
+ workflow: workflow.name,
736
+ output: JSON.stringify(workflowResult),
737
+ format: 'json',
738
+ context: options,
739
+ });
740
+ const manifest = this.manifestBuilder.build(artifacts);
741
+
742
+ return {
743
+ success: true,
744
+ workflow: workflow.name,
745
+ result: workflowResult,
746
+ steps: workflowResult.steps,
747
+ artifacts,
748
+ manifest,
749
+ performance: workflowResult.performance,
750
+ timestamp: new Date().toISOString(),
751
+ };
752
+ } catch (error) {
753
+ const msg = error instanceof Error ? error.message : String(error);
754
+ return {
755
+ success: false,
756
+ error: 'Workflow execution failed',
757
+ details: msg,
758
+ workflow: workflow.name,
759
+ };
760
+ }
761
+ }
762
+
763
+ private validateInput(
764
+ command: string,
765
+ options: Record<string, unknown>,
766
+ context: Record<string, unknown>,
767
+ ): { valid: boolean; errors: string[] } {
768
+ const errors: string[] = [];
769
+
770
+ if (!command || typeof command !== 'string') {
771
+ errors.push('Command must be a non-empty string');
772
+ }
773
+
774
+ if (
775
+ options.format &&
776
+ !this.config.output.formats.includes(options.format as string)
777
+ ) {
778
+ errors.push(
779
+ `Invalid output format: ${options.format}. Valid formats: ${this.config.output.formats.join(', ')}`,
780
+ );
781
+ }
782
+
783
+ if (
784
+ context.mode &&
785
+ !['development', 'production', 'testing', 'maintenance'].includes(context.mode as string)
786
+ ) {
787
+ errors.push(`Invalid context mode: ${context.mode}`);
788
+ }
789
+
790
+ return { valid: errors.length === 0, errors };
791
+ }
792
+
793
+ getStatus(): Record<string, unknown> {
794
+ return {
795
+ system: this.config.system.name,
796
+ version: this.config.system.version,
797
+ execution: this.executionEngine.getStatus(),
798
+ output: this.outputGenerator.getStatus(),
799
+ workflows: this.workflowManager.getStatus(),
800
+ performance: this.performanceOptimizer.getStatus(),
801
+ };
802
+ }
803
+
804
+ registerTemplate(template: TemplateDefinition): void {
805
+ this.templateRegistry.register(template);
806
+ }
807
+
808
+ renderTemplate(templateId: string, data: Record<string, unknown>): string {
809
+ return this.templateRegistry.render(templateId, data);
810
+ }
811
+
812
+ preview(templateId: string, data: Record<string, unknown>, format: 'text' | 'html' | 'json' = 'text'): string {
813
+ const rendered = this.renderTemplate(templateId, data);
814
+ if (format === 'json') {
815
+ return JSON.stringify({ rendered, templateId }, null, 2);
816
+ }
817
+ if (format === 'html') {
818
+ return `<!doctype html><html><body><pre>${rendered}</pre></body></html>`;
819
+ }
820
+ return rendered;
821
+ }
822
+
823
+ getExecutionEngine(): ExecutionEngine {
824
+ return this.executionEngine;
825
+ }
826
+
827
+ getOutputGenerator(): OutputGenerator {
828
+ return this.outputGenerator;
829
+ }
830
+
831
+ getWorkflowManager(): WorkflowManager {
832
+ return this.workflowManager;
833
+ }
834
+
835
+ getPerformanceOptimizer(): PerformanceOptimizer {
836
+ return this.performanceOptimizer;
837
+ }
838
+
839
+ getTemplateRegistry(): TemplateRegistry {
840
+ return this.templateRegistry;
841
+ }
842
+
843
+ private buildArtifacts(input: {
844
+ command?: string;
845
+ workflow?: string;
846
+ output: string;
847
+ format: string;
848
+ context: Record<string, unknown>;
849
+ }): ArtifactEntry[] {
850
+ const provenance: ArtifactProvenance = {
851
+ command: input.command,
852
+ workflow: input.workflow,
853
+ context: input.context,
854
+ generatedAt: new Date().toISOString(),
855
+ };
856
+
857
+ const artifact: ArtifactEntry = {
858
+ id: `artifact-${Date.now()}`,
859
+ type: 'output',
860
+ format: input.format,
861
+ content: input.output,
862
+ hash: sha256(stableStringify({ command: input.command, workflow: input.workflow, format: input.format, context: input.context })),
863
+ provenance,
864
+ };
865
+
866
+ return [artifact];
867
+ }
868
+ }
869
+
870
+ // ─── Helpers ───────────────────────────────────────────────────────
871
+
872
+ function sha256(input: string): string {
873
+ return createHash('sha256').update(input).digest('hex');
874
+ }
875
+
876
+ function stableStringify(value: unknown): string {
877
+ if (value === null || typeof value !== 'object') return JSON.stringify(value);
878
+ if (Array.isArray(value)) {
879
+ return `[${value.map(stableStringify).join(',')}]`;
880
+ }
881
+ const obj = value as Record<string, unknown>;
882
+ const keys = Object.keys(obj).sort();
883
+ const entries = keys.map(key => `"${key}":${stableStringify(obj[key])}`);
884
+ return `{${entries.join(',')}}`;
885
+ }