@principal-ai/principal-view-cli 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/index.cjs +6414 -340
  2. package/dist/index.cjs.map +4 -4
  3. package/package.json +2 -2
  4. package/dist/commands/coverage.d.ts +0 -9
  5. package/dist/commands/coverage.d.ts.map +0 -1
  6. package/dist/commands/coverage.js +0 -158
  7. package/dist/commands/create.d.ts +0 -6
  8. package/dist/commands/create.d.ts.map +0 -1
  9. package/dist/commands/create.js +0 -50
  10. package/dist/commands/doctor.d.ts +0 -10
  11. package/dist/commands/doctor.d.ts.map +0 -1
  12. package/dist/commands/doctor.js +0 -274
  13. package/dist/commands/formats.d.ts +0 -6
  14. package/dist/commands/formats.d.ts.map +0 -1
  15. package/dist/commands/formats.js +0 -475
  16. package/dist/commands/hooks.d.ts +0 -9
  17. package/dist/commands/hooks.d.ts.map +0 -1
  18. package/dist/commands/hooks.js +0 -295
  19. package/dist/commands/init.d.ts +0 -6
  20. package/dist/commands/init.d.ts.map +0 -1
  21. package/dist/commands/init.js +0 -271
  22. package/dist/commands/lint.d.ts +0 -6
  23. package/dist/commands/lint.d.ts.map +0 -1
  24. package/dist/commands/lint.js +0 -506
  25. package/dist/commands/list.d.ts +0 -6
  26. package/dist/commands/list.d.ts.map +0 -1
  27. package/dist/commands/list.js +0 -80
  28. package/dist/commands/narrative/eval.d.ts +0 -3
  29. package/dist/commands/narrative/eval.d.ts.map +0 -1
  30. package/dist/commands/narrative/eval.js +0 -76
  31. package/dist/commands/narrative/index.d.ts +0 -3
  32. package/dist/commands/narrative/index.d.ts.map +0 -1
  33. package/dist/commands/narrative/index.js +0 -19
  34. package/dist/commands/narrative/inspect.d.ts +0 -3
  35. package/dist/commands/narrative/inspect.d.ts.map +0 -1
  36. package/dist/commands/narrative/inspect.js +0 -109
  37. package/dist/commands/narrative/list.d.ts +0 -3
  38. package/dist/commands/narrative/list.d.ts.map +0 -1
  39. package/dist/commands/narrative/list.js +0 -101
  40. package/dist/commands/narrative/render.d.ts +0 -3
  41. package/dist/commands/narrative/render.d.ts.map +0 -1
  42. package/dist/commands/narrative/render.js +0 -99
  43. package/dist/commands/narrative/test.d.ts +0 -3
  44. package/dist/commands/narrative/test.d.ts.map +0 -1
  45. package/dist/commands/narrative/test.js +0 -150
  46. package/dist/commands/narrative/utils.d.ts +0 -69
  47. package/dist/commands/narrative/utils.d.ts.map +0 -1
  48. package/dist/commands/narrative/utils.js +0 -158
  49. package/dist/commands/narrative/validate.d.ts +0 -3
  50. package/dist/commands/narrative/validate.d.ts.map +0 -1
  51. package/dist/commands/narrative/validate.js +0 -149
  52. package/dist/commands/schema.d.ts +0 -6
  53. package/dist/commands/schema.d.ts.map +0 -1
  54. package/dist/commands/schema.js +0 -336
  55. package/dist/commands/validate-execution.d.ts +0 -11
  56. package/dist/commands/validate-execution.d.ts.map +0 -1
  57. package/dist/commands/validate-execution.js +0 -223
  58. package/dist/commands/validate.d.ts +0 -6
  59. package/dist/commands/validate.d.ts.map +0 -1
  60. package/dist/commands/validate.js +0 -1065
  61. package/dist/index.d.ts +0 -8
  62. package/dist/index.d.ts.map +0 -1
  63. package/dist/index.js +0 -45
@@ -1,506 +0,0 @@
1
- /**
2
- * Lint command - Lint graph configuration files using the rules engine
3
- */
4
- import { Command } from 'commander';
5
- import { existsSync, readFileSync } from 'node:fs';
6
- import { resolve, relative, dirname, basename } from 'node:path';
7
- import chalk from 'chalk';
8
- import { globby } from 'globby';
9
- import yaml from 'js-yaml';
10
- import { createDefaultRulesEngine, validatePrivuConfig, mergeConfigs, getDefaultConfig, createNarrativeValidator, } from '@principal-ai/principal-view-core';
11
- // ============================================================================
12
- // Config File Loading
13
- // ============================================================================
14
- /**
15
- * Config file names in resolution order
16
- */
17
- const CONFIG_FILE_NAMES = ['.privurc.yaml', '.privurc.yml', '.privurc.json'];
18
- /**
19
- * Find and load privurc config file
20
- */
21
- function findConfig(startDir) {
22
- let currentDir = resolve(startDir);
23
- // eslint-disable-next-line no-constant-condition
24
- while (true) {
25
- // Check for config files
26
- for (const fileName of CONFIG_FILE_NAMES) {
27
- const configPath = resolve(currentDir, fileName);
28
- if (existsSync(configPath)) {
29
- const config = loadConfigFile(configPath);
30
- if (config) {
31
- return { config, path: configPath };
32
- }
33
- }
34
- }
35
- // Check package.json for "privu" key
36
- const packageJsonPath = resolve(currentDir, 'package.json');
37
- if (existsSync(packageJsonPath)) {
38
- try {
39
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
40
- if (packageJson.privu && typeof packageJson.privu === 'object') {
41
- return { config: packageJson.privu, path: packageJsonPath };
42
- }
43
- }
44
- catch {
45
- // Ignore parse errors
46
- }
47
- }
48
- // Check for root flag or filesystem root
49
- const parentDir = dirname(currentDir);
50
- if (parentDir === currentDir) {
51
- break; // Reached filesystem root
52
- }
53
- currentDir = parentDir;
54
- }
55
- return null;
56
- }
57
- /**
58
- * Load a config file (JSON or YAML)
59
- */
60
- function loadConfigFile(filePath) {
61
- try {
62
- const content = readFileSync(filePath, 'utf8');
63
- const ext = filePath.toLowerCase();
64
- if (ext.endsWith('.json')) {
65
- return JSON.parse(content);
66
- }
67
- else {
68
- return yaml.load(content);
69
- }
70
- }
71
- catch {
72
- return null;
73
- }
74
- }
75
- /**
76
- * Load a component library file
77
- */
78
- function loadLibrary(libraryPath) {
79
- if (!existsSync(libraryPath)) {
80
- return null;
81
- }
82
- try {
83
- const content = readFileSync(libraryPath, 'utf8');
84
- const ext = libraryPath.toLowerCase();
85
- if (ext.endsWith('.json')) {
86
- return JSON.parse(content);
87
- }
88
- else {
89
- return yaml.load(content);
90
- }
91
- }
92
- catch {
93
- return null;
94
- }
95
- }
96
- /**
97
- * Load a graph configuration file (YAML or JSON)
98
- */
99
- function loadGraphConfig(filePath) {
100
- if (!existsSync(filePath)) {
101
- return null;
102
- }
103
- try {
104
- const raw = readFileSync(filePath, 'utf8');
105
- const ext = filePath.toLowerCase();
106
- let config;
107
- if (ext.endsWith('.json')) {
108
- config = JSON.parse(raw);
109
- }
110
- else {
111
- config = yaml.load(raw);
112
- }
113
- return { config, raw };
114
- }
115
- catch {
116
- return null;
117
- }
118
- }
119
- /**
120
- * Load a narrative template file
121
- */
122
- function loadNarrativeTemplate(filePath) {
123
- if (!existsSync(filePath)) {
124
- return null;
125
- }
126
- try {
127
- const raw = readFileSync(filePath, 'utf8');
128
- const narrative = JSON.parse(raw);
129
- return { narrative, raw };
130
- }
131
- catch {
132
- return null;
133
- }
134
- }
135
- /**
136
- * Load a canvas file for narrative validation
137
- */
138
- function loadCanvas(filePath) {
139
- if (!existsSync(filePath)) {
140
- return null;
141
- }
142
- try {
143
- const content = readFileSync(filePath, 'utf8');
144
- const ext = filePath.toLowerCase();
145
- if (ext.endsWith('.json')) {
146
- return JSON.parse(content);
147
- }
148
- else {
149
- return yaml.load(content);
150
- }
151
- }
152
- catch {
153
- return null;
154
- }
155
- }
156
- /**
157
- * Determine file type
158
- */
159
- function getFileType(filePath) {
160
- const name = basename(filePath).toLowerCase();
161
- if (name.endsWith('.narrative.json')) {
162
- return 'narrative';
163
- }
164
- if (name.endsWith('.canvas') || name.endsWith('.otel.canvas')) {
165
- return 'canvas';
166
- }
167
- return 'config';
168
- }
169
- // ============================================================================
170
- // Output Formatting
171
- // ============================================================================
172
- /**
173
- * Format violations for pretty console output
174
- */
175
- function formatPrettyOutput(results, quiet) {
176
- const lines = [];
177
- let totalErrors = 0;
178
- let totalWarnings = 0;
179
- let totalFixable = 0;
180
- for (const [filePath, result] of results) {
181
- totalErrors += result.errorCount;
182
- totalWarnings += result.warningCount;
183
- totalFixable += result.fixableCount;
184
- if (result.violations.length === 0) {
185
- if (!quiet) {
186
- lines.push(chalk.green(`✓ ${filePath}`));
187
- }
188
- continue;
189
- }
190
- lines.push('');
191
- lines.push(chalk.cyan(filePath));
192
- lines.push('');
193
- for (const violation of result.violations) {
194
- const severityColor = violation.severity === 'error' ? chalk.red : chalk.yellow;
195
- const severityLabel = violation.severity === 'error' ? 'error' : 'warn ';
196
- // Format: " error rule-id message"
197
- const ruleId = chalk.dim(violation.ruleId.padEnd(30));
198
- lines.push(` ${severityColor(severityLabel)} ${ruleId} ${violation.message}`);
199
- if (violation.suggestion) {
200
- lines.push(chalk.dim(` ${''.padEnd(30)} → ${violation.suggestion}`));
201
- }
202
- }
203
- }
204
- // Summary
205
- lines.push('');
206
- if (totalErrors === 0 && totalWarnings === 0) {
207
- lines.push(chalk.green(`✓ All files passed linting`));
208
- }
209
- else {
210
- const parts = [];
211
- if (totalErrors > 0) {
212
- parts.push(chalk.red(`${totalErrors} error${totalErrors === 1 ? '' : 's'}`));
213
- }
214
- if (totalWarnings > 0) {
215
- parts.push(chalk.yellow(`${totalWarnings} warning${totalWarnings === 1 ? '' : 's'}`));
216
- }
217
- lines.push(`✖ ${parts.join(', ')}`);
218
- if (totalFixable > 0) {
219
- lines.push(chalk.dim(` ${totalFixable} fixable with --fix (coming soon)`));
220
- }
221
- }
222
- return {
223
- output: lines.join('\n'),
224
- hasErrors: totalErrors > 0,
225
- };
226
- }
227
- /**
228
- * Format violations for JSON output
229
- */
230
- function formatJsonOutput(results) {
231
- const files = [];
232
- let totalErrors = 0;
233
- let totalWarnings = 0;
234
- let totalFixable = 0;
235
- for (const [filePath, result] of results) {
236
- totalErrors += result.errorCount;
237
- totalWarnings += result.warningCount;
238
- totalFixable += result.fixableCount;
239
- files.push({
240
- file: filePath,
241
- errorCount: result.errorCount,
242
- warningCount: result.warningCount,
243
- fixableCount: result.fixableCount,
244
- violations: result.violations,
245
- });
246
- }
247
- return {
248
- files,
249
- summary: {
250
- totalFiles: files.length,
251
- totalErrors,
252
- totalWarnings,
253
- totalFixable,
254
- },
255
- };
256
- }
257
- // ============================================================================
258
- // Helper Functions
259
- // ============================================================================
260
- /**
261
- * Count violations by rule ID
262
- */
263
- function countByRule(violations) {
264
- const counts = {};
265
- for (const v of violations) {
266
- counts[v.ruleId] = (counts[v.ruleId] || 0) + 1;
267
- }
268
- return counts;
269
- }
270
- // ============================================================================
271
- // Command Implementation
272
- // ============================================================================
273
- export function createLintCommand() {
274
- const command = new Command('lint');
275
- command
276
- .description('Lint graph configuration files')
277
- .argument('[files...]', 'Files or glob patterns to lint (defaults to .principal-views/**/*.yaml)')
278
- .option('-c, --config <path>', 'Path to config file')
279
- .option('--library <path>', 'Path to component library file')
280
- .option('-q, --quiet', 'Only output errors')
281
- .option('--json', 'Output results as JSON')
282
- .option('--rule <rules...>', 'Only run specific rules')
283
- .option('--ignore-rule <rules...>', 'Skip specific rules')
284
- .action(async (files, options) => {
285
- try {
286
- const cwd = process.cwd();
287
- // Load privurc config
288
- let privuConfig = getDefaultConfig();
289
- if (options.config) {
290
- // Use specified config file
291
- const loadedConfig = loadConfigFile(resolve(cwd, options.config));
292
- if (!loadedConfig) {
293
- console.error(chalk.red(`Error: Could not load config file: ${options.config}`));
294
- process.exit(1);
295
- }
296
- // Validate config
297
- const validation = validatePrivuConfig(loadedConfig);
298
- if (!validation.valid) {
299
- console.error(chalk.red('Configuration Error:'), options.config);
300
- for (const error of validation.errors) {
301
- console.error(chalk.red(` ${error.path}: ${error.message}`));
302
- if (error.suggestion) {
303
- console.error(chalk.dim(` → ${error.suggestion}`));
304
- }
305
- }
306
- process.exit(1);
307
- }
308
- privuConfig = mergeConfigs(privuConfig, loadedConfig);
309
- }
310
- else {
311
- // Search for config file
312
- const found = findConfig(cwd);
313
- if (found) {
314
- const validation = validatePrivuConfig(found.config);
315
- if (!validation.valid) {
316
- console.error(chalk.red('Configuration Error:'), found.path);
317
- for (const error of validation.errors) {
318
- console.error(chalk.red(` ${error.path}: ${error.message}`));
319
- if (error.suggestion) {
320
- console.error(chalk.dim(` → ${error.suggestion}`));
321
- }
322
- }
323
- process.exit(1);
324
- }
325
- privuConfig = mergeConfigs(privuConfig, found.config);
326
- }
327
- }
328
- // Determine files to lint
329
- let patterns;
330
- if (files.length > 0) {
331
- patterns = files;
332
- }
333
- else if (privuConfig.include && privuConfig.include.length > 0) {
334
- patterns = privuConfig.include;
335
- }
336
- else {
337
- patterns = [
338
- '.principal-views/**/*.yaml',
339
- '.principal-views/**/*.yml',
340
- '.principal-views/**/*.json',
341
- ];
342
- }
343
- // Find matching files
344
- const matchedFiles = await globby(patterns, {
345
- ignore: privuConfig.exclude || ['**/node_modules/**'],
346
- expandDirectories: false,
347
- });
348
- // Filter out library files, config files, and execution artifacts
349
- // INCLUDE both canvas files and narrative templates for linting
350
- const configFiles = matchedFiles.filter((f) => {
351
- const name = basename(f).toLowerCase();
352
- const isLibraryFile = name.startsWith('library.');
353
- const isConfigFile = name.startsWith('.privurc');
354
- const isExecutionArtifact = f.includes('__executions__/');
355
- return !isLibraryFile && !isConfigFile && !isExecutionArtifact;
356
- });
357
- if (configFiles.length === 0) {
358
- if (options.json) {
359
- console.log(JSON.stringify({
360
- files: [],
361
- summary: { totalFiles: 0, totalErrors: 0, totalWarnings: 0, totalFixable: 0 },
362
- }));
363
- }
364
- else {
365
- console.log(chalk.yellow('No configuration files found matching the specified patterns.'));
366
- console.log(chalk.dim(`Patterns searched: ${patterns.join(', ')}`));
367
- }
368
- return;
369
- }
370
- // Load library if specified
371
- let library;
372
- const libraryPath = options.library || privuConfig.library;
373
- if (libraryPath) {
374
- const resolvedLibraryPath = resolve(cwd, libraryPath);
375
- library = loadLibrary(resolvedLibraryPath) ?? undefined;
376
- if (!library && !options.quiet) {
377
- console.log(chalk.yellow(`Warning: Could not load library from ${libraryPath}`));
378
- }
379
- }
380
- // Create validators
381
- const engine = createDefaultRulesEngine();
382
- const narrativeValidator = createNarrativeValidator();
383
- // Lint each file
384
- const results = new Map();
385
- for (const filePath of configFiles) {
386
- const absolutePath = resolve(cwd, filePath);
387
- const relativePath = relative(cwd, absolutePath);
388
- const fileType = getFileType(absolutePath);
389
- if (fileType === 'narrative') {
390
- // Validate narrative template
391
- const loaded = loadNarrativeTemplate(absolutePath);
392
- if (!loaded) {
393
- // File couldn't be loaded - report as error
394
- results.set(relativePath, {
395
- violations: [
396
- {
397
- ruleId: 'parse-error',
398
- severity: 'error',
399
- file: relativePath,
400
- message: `Could not parse narrative file: ${filePath}`,
401
- impact: 'File cannot be validated',
402
- fixable: false,
403
- },
404
- ],
405
- errorCount: 1,
406
- warningCount: 0,
407
- fixableCount: 0,
408
- byCategory: { schema: 1, reference: 0, structure: 0, pattern: 0, library: 0 },
409
- byRule: { 'parse-error': 1 },
410
- });
411
- continue;
412
- }
413
- // Load the referenced canvas if it exists
414
- const canvasPath = loaded.narrative.canvas
415
- ? resolve(dirname(absolutePath), loaded.narrative.canvas)
416
- : undefined;
417
- const canvas = canvasPath ? loadCanvas(canvasPath) : undefined;
418
- // Run narrative validation
419
- const narrativeResult = await narrativeValidator.validate({
420
- narrative: loaded.narrative,
421
- narrativePath: relativePath,
422
- canvas: canvas ?? undefined,
423
- canvasPath: canvasPath ? relative(cwd, canvasPath) : undefined,
424
- basePath: dirname(absolutePath),
425
- rawContent: loaded.raw,
426
- });
427
- // Convert narrative violations to graph violations format
428
- const violations = narrativeResult.violations.map((v) => ({
429
- ruleId: v.ruleId,
430
- severity: v.severity,
431
- file: v.file,
432
- line: v.line,
433
- path: v.path,
434
- message: v.message,
435
- impact: v.impact,
436
- suggestion: v.suggestion,
437
- fixable: v.fixable,
438
- }));
439
- results.set(relativePath, {
440
- violations,
441
- errorCount: narrativeResult.errorCount,
442
- warningCount: narrativeResult.warningCount,
443
- fixableCount: narrativeResult.fixableCount,
444
- byCategory: { schema: 0, reference: 0, structure: 0, pattern: 0, library: 0 }, // Could categorize narrative rules
445
- byRule: countByRule(violations),
446
- });
447
- }
448
- else {
449
- // Validate canvas/graph configuration
450
- const loaded = loadGraphConfig(absolutePath);
451
- if (!loaded) {
452
- // File couldn't be loaded - report as error
453
- results.set(relativePath, {
454
- violations: [
455
- {
456
- ruleId: 'parse-error',
457
- severity: 'error',
458
- file: relativePath,
459
- message: `Could not parse file: ${filePath}`,
460
- impact: 'File cannot be validated',
461
- fixable: false,
462
- },
463
- ],
464
- errorCount: 1,
465
- warningCount: 0,
466
- fixableCount: 0,
467
- byCategory: { schema: 1, reference: 0, structure: 0, pattern: 0, library: 0 },
468
- byRule: { 'parse-error': 1 },
469
- });
470
- continue;
471
- }
472
- // Run linting
473
- const result = await engine.lintWithConfig(loaded.config, privuConfig, {
474
- library,
475
- configPath: relativePath,
476
- rawContent: loaded.raw,
477
- enabledRules: options.rule,
478
- disabledRules: options.ignoreRule,
479
- });
480
- results.set(relativePath, result);
481
- }
482
- }
483
- // Output results
484
- if (options.json) {
485
- console.log(JSON.stringify(formatJsonOutput(results), null, 2));
486
- }
487
- else {
488
- const { output, hasErrors } = formatPrettyOutput(results, options.quiet);
489
- console.log(output);
490
- if (hasErrors) {
491
- process.exit(1);
492
- }
493
- }
494
- }
495
- catch (error) {
496
- if (options.json) {
497
- console.log(JSON.stringify({ error: error.message }));
498
- }
499
- else {
500
- console.error(chalk.red('Error:'), error.message);
501
- }
502
- process.exit(1);
503
- }
504
- });
505
- return command;
506
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * List command - List all .canvas files in a project
3
- */
4
- import { Command } from 'commander';
5
- export declare function createListCommand(): Command;
6
- //# sourceMappingURL=list.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC,wBAAgB,iBAAiB,IAAI,OAAO,CAwD3C"}
@@ -1,80 +0,0 @@
1
- /**
2
- * List command - List all .canvas files in a project
3
- */
4
- import { Command } from 'commander';
5
- import { readFileSync, statSync } from 'node:fs';
6
- import { resolve, relative } from 'node:path';
7
- import chalk from 'chalk';
8
- import { globby } from 'globby';
9
- function getCanvasInfo(filePath) {
10
- try {
11
- const absolutePath = resolve(filePath);
12
- const content = readFileSync(absolutePath, 'utf8');
13
- const canvas = JSON.parse(content);
14
- const stats = statSync(absolutePath);
15
- return {
16
- file: relative(process.cwd(), absolutePath),
17
- name: canvas.pv?.name || 'Untitled',
18
- version: canvas.pv?.version,
19
- nodeCount: Array.isArray(canvas.nodes) ? canvas.nodes.length : 0,
20
- edgeCount: Array.isArray(canvas.edges) ? canvas.edges.length : 0,
21
- modified: stats.mtime,
22
- };
23
- }
24
- catch {
25
- return null;
26
- }
27
- }
28
- export function createListCommand() {
29
- const command = new Command('list');
30
- command
31
- .alias('ls')
32
- .description('List all .canvas files in the project')
33
- .option('-a, --all', 'Search all directories (not just .principal-views)')
34
- .option('--json', 'Output as JSON')
35
- .action(async (options) => {
36
- try {
37
- const patterns = options.all
38
- ? ['**/*.canvas', '!node_modules/**']
39
- : ['.principal-views/*.canvas'];
40
- const files = await globby(patterns, {
41
- expandDirectories: false,
42
- });
43
- if (files.length === 0) {
44
- if (options.json) {
45
- console.log(JSON.stringify({ files: [] }));
46
- }
47
- else {
48
- console.log(chalk.yellow('No .canvas files found.'));
49
- if (!options.all) {
50
- console.log(chalk.dim('Run with --all to search all directories'));
51
- }
52
- console.log(chalk.dim('\nTo create a new canvas, run: npx @principal-ai/principal-view-cli init'));
53
- }
54
- return;
55
- }
56
- const canvasInfos = files
57
- .map(getCanvasInfo)
58
- .filter((info) => info !== null)
59
- .sort((a, b) => b.modified.getTime() - a.modified.getTime());
60
- if (options.json) {
61
- console.log(JSON.stringify({ files: canvasInfos }, null, 2));
62
- }
63
- else {
64
- console.log(chalk.bold(`\nFound ${canvasInfos.length} canvas file(s):\n`));
65
- for (const info of canvasInfos) {
66
- const version = info.version ? chalk.dim(` v${info.version}`) : '';
67
- console.log(` ${chalk.cyan(info.file)}`);
68
- console.log(` ${chalk.bold(info.name)}${version}`);
69
- console.log(chalk.dim(` ${info.nodeCount} nodes, ${info.edgeCount} edges`));
70
- console.log('');
71
- }
72
- }
73
- }
74
- catch (error) {
75
- console.error(chalk.red('Error:'), error.message);
76
- process.exit(1);
77
- }
78
- });
79
- return command;
80
- }
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createEvalCommand(): Command;
3
- //# sourceMappingURL=eval.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../../src/commands/narrative/eval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,iBAAiB,IAAI,OAAO,CA2E3C"}
@@ -1,76 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import { readFile } from 'node:fs/promises';
4
- import { evaluateExpression } from '@principal-ai/principal-view-core';
5
- import { resolvePath, formatValue } from './utils.js';
6
- export function createEvalCommand() {
7
- const command = new Command('eval');
8
- command
9
- .description('Evaluate template expression with context')
10
- .argument('<expression>', 'Template expression to evaluate (e.g., {count > 5 ? \'many\' : \'few\'})')
11
- .argument('[context]', 'Optional path to JSON context file')
12
- .option('--context <json>', 'Inline JSON context as string')
13
- .option('--json', 'Output result as JSON')
14
- .action(async (expression, contextPath, options) => {
15
- try {
16
- let context = {};
17
- // Load context from file or inline option
18
- if (contextPath) {
19
- const content = await readFile(resolvePath(contextPath), 'utf-8');
20
- context = JSON.parse(content);
21
- }
22
- else if (options.context) {
23
- context = JSON.parse(options.context);
24
- }
25
- // Remove curly braces if user included them
26
- let cleanExpression = expression.trim();
27
- if (cleanExpression.startsWith('{') && cleanExpression.endsWith('}')) {
28
- cleanExpression = cleanExpression.slice(1, -1).trim();
29
- }
30
- // Evaluate expression
31
- const result = evaluateExpression(cleanExpression, context);
32
- if (options.json) {
33
- const output = {
34
- expression: cleanExpression,
35
- context,
36
- result,
37
- type: typeof result,
38
- };
39
- console.log(JSON.stringify(output, null, 2));
40
- }
41
- else {
42
- console.log(chalk.bold('\nExpression:'), chalk.cyan(`{${cleanExpression}}`));
43
- if (Object.keys(context).length > 0) {
44
- console.log(chalk.bold('\nContext:'));
45
- for (const [key, value] of Object.entries(context)) {
46
- console.log(chalk.gray(' •'), `${key} = ${formatValue(value)}`);
47
- }
48
- }
49
- else {
50
- console.log(chalk.yellow('\nNo context provided'));
51
- }
52
- console.log(chalk.bold('\nResult:'), formatValue(result));
53
- console.log(chalk.gray('Type:'), typeof result);
54
- console.log();
55
- }
56
- }
57
- catch (error) {
58
- const errorMessage = error.message;
59
- if (options.json) {
60
- const output = {
61
- error: true,
62
- message: errorMessage,
63
- expression: expression,
64
- };
65
- console.log(JSON.stringify(output, null, 2));
66
- }
67
- else {
68
- console.error(chalk.red('\nEvaluation Error:'), errorMessage);
69
- console.error(chalk.gray('\nExpression:'), expression);
70
- console.log();
71
- }
72
- process.exit(1);
73
- }
74
- });
75
- return command;
76
- }
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createNarrativeCommand(): Command;
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/narrative/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,sBAAsB,IAAI,OAAO,CAahD"}