@dcyfr/ai 1.0.1 → 1.0.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 (155) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +19 -22
  3. package/bin/cli.js +12 -0
  4. package/bin/tui/config-wizard.js +107 -0
  5. package/bin/tui/validation-dashboard.js +123 -0
  6. package/bin/tui.js +259 -0
  7. package/dist/ai/agents/agent-loader.d.ts +131 -0
  8. package/dist/ai/agents/agent-loader.d.ts.map +1 -0
  9. package/dist/ai/agents/agent-loader.js +399 -0
  10. package/dist/ai/agents/agent-loader.js.map +1 -0
  11. package/dist/ai/agents/agent-registry.d.ts +120 -0
  12. package/dist/ai/agents/agent-registry.d.ts.map +1 -0
  13. package/dist/ai/agents/agent-registry.js +345 -0
  14. package/dist/ai/agents/agent-registry.js.map +1 -0
  15. package/dist/ai/agents/agent-router.d.ts +97 -0
  16. package/dist/ai/agents/agent-router.d.ts.map +1 -0
  17. package/dist/ai/agents/agent-router.js +375 -0
  18. package/dist/ai/agents/agent-router.js.map +1 -0
  19. package/dist/ai/agents/index.d.ts +10 -0
  20. package/dist/ai/agents/index.d.ts.map +1 -0
  21. package/dist/ai/agents/index.js +12 -0
  22. package/dist/ai/agents/index.js.map +1 -0
  23. package/dist/ai/agents/types.d.ts +264 -0
  24. package/dist/ai/agents/types.d.ts.map +1 -0
  25. package/dist/ai/agents/types.js +10 -0
  26. package/dist/ai/agents/types.js.map +1 -0
  27. package/dist/ai/agents-builtin/architecture/architecture-reviewer.d.ts +12 -0
  28. package/dist/ai/agents-builtin/architecture/architecture-reviewer.d.ts.map +1 -0
  29. package/dist/ai/agents-builtin/architecture/architecture-reviewer.js +92 -0
  30. package/dist/ai/agents-builtin/architecture/architecture-reviewer.js.map +1 -0
  31. package/dist/ai/agents-builtin/architecture/cloud-architect.d.ts +12 -0
  32. package/dist/ai/agents-builtin/architecture/cloud-architect.d.ts.map +1 -0
  33. package/dist/ai/agents-builtin/architecture/cloud-architect.js +103 -0
  34. package/dist/ai/agents-builtin/architecture/cloud-architect.js.map +1 -0
  35. package/dist/ai/agents-builtin/architecture/database-architect.d.ts +12 -0
  36. package/dist/ai/agents-builtin/architecture/database-architect.d.ts.map +1 -0
  37. package/dist/ai/agents-builtin/architecture/database-architect.js +95 -0
  38. package/dist/ai/agents-builtin/architecture/database-architect.js.map +1 -0
  39. package/dist/ai/agents-builtin/architecture/index.d.ts +11 -0
  40. package/dist/ai/agents-builtin/architecture/index.d.ts.map +1 -0
  41. package/dist/ai/agents-builtin/architecture/index.js +11 -0
  42. package/dist/ai/agents-builtin/architecture/index.js.map +1 -0
  43. package/dist/ai/agents-builtin/content/index.d.ts +9 -0
  44. package/dist/ai/agents-builtin/content/index.d.ts.map +1 -0
  45. package/dist/ai/agents-builtin/content/index.js +9 -0
  46. package/dist/ai/agents-builtin/content/index.js.map +1 -0
  47. package/dist/ai/agents-builtin/content/technical-writer.d.ts +12 -0
  48. package/dist/ai/agents-builtin/content/technical-writer.d.ts.map +1 -0
  49. package/dist/ai/agents-builtin/content/technical-writer.js +93 -0
  50. package/dist/ai/agents-builtin/content/technical-writer.js.map +1 -0
  51. package/dist/ai/agents-builtin/data/data-scientist.d.ts +12 -0
  52. package/dist/ai/agents-builtin/data/data-scientist.d.ts.map +1 -0
  53. package/dist/ai/agents-builtin/data/data-scientist.js +92 -0
  54. package/dist/ai/agents-builtin/data/data-scientist.js.map +1 -0
  55. package/dist/ai/agents-builtin/data/index.d.ts +9 -0
  56. package/dist/ai/agents-builtin/data/index.d.ts.map +1 -0
  57. package/dist/ai/agents-builtin/data/index.js +9 -0
  58. package/dist/ai/agents-builtin/data/index.js.map +1 -0
  59. package/dist/ai/agents-builtin/development/backend-architect.d.ts +12 -0
  60. package/dist/ai/agents-builtin/development/backend-architect.d.ts.map +1 -0
  61. package/dist/ai/agents-builtin/development/backend-architect.js +99 -0
  62. package/dist/ai/agents-builtin/development/backend-architect.js.map +1 -0
  63. package/dist/ai/agents-builtin/development/frontend-developer.d.ts +12 -0
  64. package/dist/ai/agents-builtin/development/frontend-developer.d.ts.map +1 -0
  65. package/dist/ai/agents-builtin/development/frontend-developer.js +106 -0
  66. package/dist/ai/agents-builtin/development/frontend-developer.js.map +1 -0
  67. package/dist/ai/agents-builtin/development/fullstack-developer.d.ts +12 -0
  68. package/dist/ai/agents-builtin/development/fullstack-developer.d.ts.map +1 -0
  69. package/dist/ai/agents-builtin/development/fullstack-developer.js +86 -0
  70. package/dist/ai/agents-builtin/development/fullstack-developer.js.map +1 -0
  71. package/dist/ai/agents-builtin/development/index.d.ts +12 -0
  72. package/dist/ai/agents-builtin/development/index.d.ts.map +1 -0
  73. package/dist/ai/agents-builtin/development/index.js +12 -0
  74. package/dist/ai/agents-builtin/development/index.js.map +1 -0
  75. package/dist/ai/agents-builtin/development/typescript-pro.d.ts +12 -0
  76. package/dist/ai/agents-builtin/development/typescript-pro.d.ts.map +1 -0
  77. package/dist/ai/agents-builtin/development/typescript-pro.js +98 -0
  78. package/dist/ai/agents-builtin/development/typescript-pro.js.map +1 -0
  79. package/dist/ai/agents-builtin/devops/devops-engineer.d.ts +12 -0
  80. package/dist/ai/agents-builtin/devops/devops-engineer.d.ts.map +1 -0
  81. package/dist/ai/agents-builtin/devops/devops-engineer.js +98 -0
  82. package/dist/ai/agents-builtin/devops/devops-engineer.js.map +1 -0
  83. package/dist/ai/agents-builtin/devops/index.d.ts +9 -0
  84. package/dist/ai/agents-builtin/devops/index.d.ts.map +1 -0
  85. package/dist/ai/agents-builtin/devops/index.js +9 -0
  86. package/dist/ai/agents-builtin/devops/index.js.map +1 -0
  87. package/dist/ai/agents-builtin/index.d.ts +36 -0
  88. package/dist/ai/agents-builtin/index.d.ts.map +1 -0
  89. package/dist/ai/agents-builtin/index.js +107 -0
  90. package/dist/ai/agents-builtin/index.js.map +1 -0
  91. package/dist/ai/agents-builtin/performance/index.d.ts +9 -0
  92. package/dist/ai/agents-builtin/performance/index.d.ts.map +1 -0
  93. package/dist/ai/agents-builtin/performance/index.js +9 -0
  94. package/dist/ai/agents-builtin/performance/index.js.map +1 -0
  95. package/dist/ai/agents-builtin/performance/performance-profiler.d.ts +12 -0
  96. package/dist/ai/agents-builtin/performance/performance-profiler.d.ts.map +1 -0
  97. package/dist/ai/agents-builtin/performance/performance-profiler.js +89 -0
  98. package/dist/ai/agents-builtin/performance/performance-profiler.js.map +1 -0
  99. package/dist/ai/agents-builtin/research/index.d.ts +9 -0
  100. package/dist/ai/agents-builtin/research/index.d.ts.map +1 -0
  101. package/dist/ai/agents-builtin/research/index.js +9 -0
  102. package/dist/ai/agents-builtin/research/index.js.map +1 -0
  103. package/dist/ai/agents-builtin/research/research-orchestrator.d.ts +12 -0
  104. package/dist/ai/agents-builtin/research/research-orchestrator.d.ts.map +1 -0
  105. package/dist/ai/agents-builtin/research/research-orchestrator.js +83 -0
  106. package/dist/ai/agents-builtin/research/research-orchestrator.js.map +1 -0
  107. package/dist/ai/agents-builtin/security/index.d.ts +9 -0
  108. package/dist/ai/agents-builtin/security/index.d.ts.map +1 -0
  109. package/dist/ai/agents-builtin/security/index.js +9 -0
  110. package/dist/ai/agents-builtin/security/index.js.map +1 -0
  111. package/dist/ai/agents-builtin/security/security-engineer.d.ts +12 -0
  112. package/dist/ai/agents-builtin/security/security-engineer.d.ts.map +1 -0
  113. package/dist/ai/agents-builtin/security/security-engineer.js +90 -0
  114. package/dist/ai/agents-builtin/security/security-engineer.js.map +1 -0
  115. package/dist/ai/agents-builtin/testing/debugger.d.ts +13 -0
  116. package/dist/ai/agents-builtin/testing/debugger.d.ts.map +1 -0
  117. package/dist/ai/agents-builtin/testing/debugger.js +89 -0
  118. package/dist/ai/agents-builtin/testing/debugger.js.map +1 -0
  119. package/dist/ai/agents-builtin/testing/index.d.ts +10 -0
  120. package/dist/ai/agents-builtin/testing/index.d.ts.map +1 -0
  121. package/dist/ai/agents-builtin/testing/index.js +10 -0
  122. package/dist/ai/agents-builtin/testing/index.js.map +1 -0
  123. package/dist/ai/agents-builtin/testing/test-engineer.d.ts +12 -0
  124. package/dist/ai/agents-builtin/testing/test-engineer.d.ts.map +1 -0
  125. package/dist/ai/agents-builtin/testing/test-engineer.js +93 -0
  126. package/dist/ai/agents-builtin/testing/test-engineer.js.map +1 -0
  127. package/dist/ai/config/loader.d.ts +19 -5
  128. package/dist/ai/config/loader.d.ts.map +1 -1
  129. package/dist/ai/config/loader.js +53 -18
  130. package/dist/ai/config/loader.js.map +1 -1
  131. package/dist/ai/config/schema.d.ts +600 -8
  132. package/dist/ai/config/schema.d.ts.map +1 -1
  133. package/dist/ai/config/schema.js +156 -0
  134. package/dist/ai/config/schema.js.map +1 -1
  135. package/dist/ai/index.d.ts +4 -1
  136. package/dist/ai/index.d.ts.map +1 -1
  137. package/dist/ai/index.js +35 -1
  138. package/dist/ai/index.js.map +1 -1
  139. package/dist/ai/mcp/index.d.ts +8 -0
  140. package/dist/ai/mcp/index.d.ts.map +1 -0
  141. package/dist/ai/mcp/index.js +8 -0
  142. package/dist/ai/mcp/index.js.map +1 -0
  143. package/dist/ai/mcp/mcp-registry.d.ts +127 -0
  144. package/dist/ai/mcp/mcp-registry.d.ts.map +1 -0
  145. package/dist/ai/mcp/mcp-registry.js +355 -0
  146. package/dist/ai/mcp/mcp-registry.js.map +1 -0
  147. package/dist/ai/mcp/types.d.ts +126 -0
  148. package/dist/ai/mcp/types.d.ts.map +1 -0
  149. package/dist/ai/mcp/types.js +9 -0
  150. package/dist/ai/mcp/types.js.map +1 -0
  151. package/dist/ai/utils/storage.d.ts +6 -1
  152. package/dist/ai/utils/storage.d.ts.map +1 -1
  153. package/dist/ai/utils/storage.js +57 -22
  154. package/dist/ai/utils/storage.js.map +1 -1
  155. package/package.json +24 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`1d6f12e`](https://github.com/dcyfr/dcyfr-ai/commit/1d6f12ed981054fcb0b26beac4be452926ba793f) Thanks [@dcyfr](https://github.com/dcyfr)! - Automated release management and CI improvements
8
+
9
+ - Added automated release workflows with changesets
10
+ - Fixed glob TypeScript compatibility issues
11
+ - Improved integration test handling for CI environments
12
+ - Added canary release workflow for pre-release testing
13
+ - Comprehensive CI pipeline with type checking, linting, and tests
14
+
3
15
  All notable changes to @dcyfr/ai will be documented in this file.
4
16
 
5
17
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
@@ -10,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
22
  ### Added
11
23
 
12
24
  #### Core Framework
25
+
13
26
  - Configuration system with three-layer merge (defaults → project → env)
14
27
  - Support for YAML, JSON, and package.json configuration formats
15
28
  - Environment variable overrides for all configuration options
@@ -20,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
20
33
  - Validation framework with parallel/serial execution modes
21
34
 
22
35
  #### Plugin System
36
+
23
37
  - Plugin manifest validation
24
38
  - Lifecycle hooks (onLoad, onValidate, onComplete, onUnload)
25
39
  - Error isolation and recovery
@@ -27,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
27
41
  - Plugin timeout support
28
42
 
29
43
  #### Telemetry
44
+
30
45
  - Session management with context tracking
31
46
  - Metric recording (compliance, test pass rate, costs)
32
47
  - Agent statistics aggregation
@@ -35,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
35
50
  - Memory storage adapter for testing
36
51
 
37
52
  #### Provider Support
53
+
38
54
  - Claude (Anthropic)
39
55
  - Groq
40
56
  - Ollama
@@ -43,6 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43
59
  - Generic provider interface
44
60
 
45
61
  #### CLI Tools
62
+
46
63
  - `init` - Initialize new project
47
64
  - `config:init` - Create configuration file
48
65
  - `config:validate` - Validate configuration
@@ -50,6 +67,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
50
67
  - `plugin:create` - Generate plugin template
51
68
 
52
69
  #### Documentation
70
+
53
71
  - Comprehensive getting started guide
54
72
  - Complete API reference
55
73
  - Plugin development guide
@@ -57,6 +75,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
57
75
  - Migration documentation
58
76
 
59
77
  #### Configuration Templates
78
+
60
79
  - Default YAML configuration
61
80
  - Default JSON configuration
62
81
  - Minimal configuration templates
@@ -70,6 +89,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
70
89
  - Zero breaking changes in API surface
71
90
 
72
91
  ### Developer Experience
92
+
73
93
  - Type-safe configuration with Zod
74
94
  - ESM modules with .d.ts declarations
75
95
  - Comprehensive error messages
@@ -79,6 +99,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
79
99
  ## [Unreleased]
80
100
 
81
101
  ### Planned
102
+
82
103
  - Redis storage adapter for telemetry
83
104
  - Database storage adapter
84
105
  - Additional validation gates
package/README.md CHANGED
@@ -187,31 +187,28 @@ See [examples/](./examples/) directory:
187
187
  - [Configuration Guide](./docs/configuration.md)
188
188
  - [Plugin Development](./docs/plugins.md)
189
189
  - [API Reference](./docs/api.md)
190
+ - [Release Management](./docs/RELEASE_MANAGEMENT.md) - Publishing and versioning
191
+ - [Quick Release Guide](./docs/RELEASE_QUICK_START.md) - TL;DR for releases
190
192
 
191
- ## Architecture
193
+ ## Contributing
192
194
 
193
- ```
194
- @dcyfr/ai (Public Framework)
195
- ├── Core
196
- │ ├── TelemetryEngine - Usage tracking
197
- │ └── ProviderRegistry - Multi-provider AI
198
- ├── Plugins
199
- │ ├── PluginLoader - Dynamic loading
200
- │ └── ValidationFramework - Quality gates
201
- ├── Config
202
- │ ├── Schema (Zod) - Validation
203
- │ └── Loader - Three-layer merge
204
- └── CLI
205
- └── Config tools
206
-
207
- @dcyfr/agents (Private Agents)
208
- └── Specialized validators for DCYFR projects
209
- ```
195
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution guidelines.
210
196
 
211
- ## License
197
+ ### Release Process
212
198
 
213
- MIT © DCYFR Labs
199
+ We use [Changesets](https://github.com/changesets/changesets) for automated versioning and publishing.
214
200
 
215
- ## Contributing
201
+ **For contributors:**
202
+ ```bash
203
+ # Add a changeset describing your changes
204
+ npm run changeset
216
205
 
217
- See [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution guidelines.
206
+ # Commit the changeset with your PR
207
+ git add .changeset/*.md
208
+ git commit -m "feat: your feature"
209
+ ```
210
+
211
+ **For maintainers:**
212
+ - Changesets automatically creates Release PRs
213
+ - Merging a Release PR publishes to npm
214
+ - See [Release Management](./docs/RELEASE_MANAGEMENT.md) for full details
package/bin/cli.js CHANGED
@@ -176,6 +176,8 @@ Commands:
176
176
  config:validate Validate configuration file
177
177
  config:init Initialize new configuration file
178
178
  config:schema Show configuration schema
179
+ tui:dashboard Interactive validation dashboard (OpenTUI)
180
+ tui:wizard Interactive configuration wizard (OpenTUI)
179
181
  help Show this help message
180
182
 
181
183
  Options:
@@ -230,6 +232,16 @@ async function main() {
230
232
  await showSchema();
231
233
  break;
232
234
 
235
+ case 'tui:dashboard':
236
+ case 'tui:wizard':
237
+ case 'tui':
238
+ // Delegate to TUI CLI
239
+ console.log('🎨 Launching interactive TUI...\n');
240
+ console.log('Use: npx @dcyfr/ai-tui ' + options.command.replace('tui:', ''));
241
+ console.log('Or run: node bin/tui.js ' + options.command.replace('tui:', ''));
242
+ process.exit(0);
243
+ break;
244
+
233
245
  case 'help':
234
246
  case '--help':
235
247
  case '-h':
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Interactive Configuration Wizard
3
+ * Uses inquirer for interactive prompts
4
+ */
5
+
6
+ import inquirer from 'inquirer';
7
+ import chalk from 'chalk';
8
+
9
+ /**
10
+ * Run configuration wizard
11
+ */
12
+ export async function runConfigWizard() {
13
+ console.log(chalk.cyan.bold('\n⚙️ DCYFR Configuration Wizard\n'));
14
+ console.log(chalk.gray('Configure your AI agent framework\n'));
15
+
16
+ const answers = await inquirer.prompt([
17
+ {
18
+ type: 'input',
19
+ name: 'projectName',
20
+ message: 'Project name:',
21
+ default: 'my-project',
22
+ },
23
+ {
24
+ type: 'list',
25
+ name: 'format',
26
+ message: 'Config format:',
27
+ choices: [
28
+ { name: 'YAML (Recommended)', value: 'yaml' },
29
+ { name: 'JSON', value: 'json' },
30
+ ],
31
+ default: 'yaml',
32
+ },
33
+ {
34
+ type: 'confirm',
35
+ name: 'telemetryEnabled',
36
+ message: 'Enable telemetry?',
37
+ default: true,
38
+ },
39
+ {
40
+ type: 'confirm',
41
+ name: 'validationEnabled',
42
+ message: 'Enable validation?',
43
+ default: true,
44
+ },
45
+ {
46
+ type: 'confirm',
47
+ name: 'parallelExecution',
48
+ message: 'Enable parallel execution?',
49
+ default: true,
50
+ },
51
+ {
52
+ type: 'number',
53
+ name: 'designTokenCompliance',
54
+ message: 'Design token compliance threshold (%):',
55
+ default: 90,
56
+ when: (answers) => answers.validationEnabled,
57
+ },
58
+ {
59
+ type: 'number',
60
+ name: 'pageLayoutUsage',
61
+ message: 'PageLayout usage threshold (%):',
62
+ default: 90,
63
+ when: (answers) => answers.validationEnabled,
64
+ },
65
+ {
66
+ type: 'checkbox',
67
+ name: 'agents',
68
+ message: 'Select agents to enable:',
69
+ choices: [
70
+ { name: 'Design Tokens', value: 'designTokens', checked: true },
71
+ { name: 'Barrel Exports', value: 'barrelExports', checked: true },
72
+ { name: 'Page Layout', value: 'pageLayout', checked: true },
73
+ { name: 'Test Data', value: 'testData', checked: true },
74
+ { name: 'API Pattern', value: 'apiPattern', checked: false },
75
+ ],
76
+ },
77
+ ]);
78
+
79
+ return {
80
+ projectName: answers.projectName,
81
+ format: answers.format,
82
+ telemetryEnabled: answers.telemetryEnabled,
83
+ validationEnabled: answers.validationEnabled,
84
+ parallelExecution: answers.parallelExecution,
85
+ designTokenCompliance: answers.designTokenCompliance || 90,
86
+ pageLayoutUsage: answers.pageLayoutUsage || 90,
87
+ agents: {
88
+ designTokens: {
89
+ enabled: answers.agents.includes('designTokens'),
90
+ compliance: (answers.designTokenCompliance || 90) / 100,
91
+ },
92
+ barrelExports: {
93
+ enabled: answers.agents.includes('barrelExports'),
94
+ },
95
+ pageLayout: {
96
+ enabled: answers.agents.includes('pageLayout'),
97
+ targetUsage: (answers.pageLayoutUsage || 90) / 100,
98
+ },
99
+ testData: {
100
+ enabled: answers.agents.includes('testData'),
101
+ },
102
+ apiPattern: {
103
+ enabled: answers.agents.includes('apiPattern'),
104
+ },
105
+ },
106
+ };
107
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Terminal Validation Dashboard
3
+ * Interactive terminal UI for displaying validation results using chalk and cli-table3
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import Table from 'cli-table3';
8
+
9
+ /**
10
+ * Status icon helper
11
+ */
12
+ export function getStatusIcon(status) {
13
+ const icons = {
14
+ pass: chalk.green.bold('✓'),
15
+ fail: chalk.red.bold('✗'),
16
+ warn: chalk.yellow.bold('⚠'),
17
+ pending: chalk.gray.bold('○'),
18
+ };
19
+
20
+ return icons[status] || icons.pending;
21
+ }
22
+
23
+ /**
24
+ * Progress bar helper
25
+ */
26
+ export function renderProgressBar(value, max = 100, width = 30) {
27
+ const percentage = Math.min(100, (value / max) * 100);
28
+ const filledWidth = Math.floor((percentage / 100) * width);
29
+ const emptyWidth = width - filledWidth;
30
+
31
+ const filled = '█'.repeat(filledWidth);
32
+ const empty = '░'.repeat(emptyWidth);
33
+
34
+ let colorFn = chalk.green;
35
+ if (percentage < 50) colorFn = chalk.red;
36
+ else if (percentage < 90) colorFn = chalk.yellow;
37
+
38
+ return `${colorFn(filled)}${chalk.gray(empty)} ${chalk.cyan(percentage.toFixed(1) + '%')}`;
39
+ }
40
+
41
+ /**
42
+ * Render gate status row
43
+ */
44
+ export function renderGateRow(gate) {
45
+ const status = gate.passed ? 'pass' : 'fail';
46
+ const compliance = gate.compliance || 0;
47
+ const icon = getStatusIcon(status);
48
+ const progressBar = renderProgressBar(compliance, 100, 20);
49
+ const issues = gate.violations > 0 ? chalk.red(`${gate.violations} issues`) : chalk.gray('0 issues');
50
+
51
+ const name = gate.name.padEnd(20);
52
+
53
+ return `${icon} ${name} ${progressBar} ${issues}`;
54
+ }
55
+
56
+ /**
57
+ * Render agent summary
58
+ */
59
+ export function renderAgentSummary(agents) {
60
+ const lines = [chalk.cyan.bold('🤖 Agents'), ''];
61
+
62
+ Object.entries(agents).forEach(([name, config]) => {
63
+ const enabled = 'enabled' in config ? config.enabled : true;
64
+ const icon = enabled ? chalk.green('✓') : chalk.gray('✗');
65
+ const agentName = enabled ? chalk.white(name) : chalk.gray(name);
66
+ lines.push(` ${icon} ${agentName}`);
67
+ });
68
+
69
+ return lines.join('\n');
70
+ }
71
+
72
+ /**
73
+ * Main validation dashboard
74
+ */
75
+ export function renderValidationDashboard(config, report) {
76
+ const hasReport = report && report.gates;
77
+ const passed = report?.valid || false;
78
+
79
+ const lines = [];
80
+
81
+ // Header
82
+ const status = passed ? chalk.green.bold('PASS') : chalk.red.bold('FAIL');
83
+ lines.push('');
84
+ lines.push(chalk.cyan.bold('🔍 DCYFR Validation Dashboard') + ' ' + status);
85
+ lines.push('─'.repeat(80));
86
+ lines.push('');
87
+
88
+ // Project info
89
+ lines.push(`${chalk.gray('📂 Project:')} ${chalk.white(config.projectName || '(unnamed)')}`);
90
+ lines.push(`${chalk.gray('📊 Version:')} ${chalk.white(config.version)}`);
91
+ lines.push('');
92
+
93
+ // Validation gates
94
+ if (hasReport) {
95
+ lines.push(chalk.cyan.bold('🎯 Validation Gates'));
96
+ lines.push('');
97
+ report.gates.forEach((gate) => {
98
+ lines.push(renderGateRow(gate));
99
+ });
100
+ lines.push('');
101
+
102
+ // Overall metrics
103
+ lines.push('─'.repeat(80));
104
+ const gatesPassed = report.gates.filter((g) => g.passed).length;
105
+ const totalViolations = report.gates.reduce((sum, g) => sum + (g.violations || 0), 0);
106
+ const avgCompliance = (report.gates.reduce((sum, g) => sum + (g.compliance || 0), 0) / report.gates.length).toFixed(1);
107
+
108
+ lines.push('');
109
+ lines.push(`${chalk.gray('Gates Passed:')} ${chalk.green.bold(gatesPassed)}/${report.gates.length} ${chalk.gray('Total Violations:')} ${chalk.red.bold(totalViolations)} ${chalk.gray('Avg Compliance:')} ${chalk.cyan.bold(avgCompliance + '%')}`);
110
+ lines.push('');
111
+ }
112
+
113
+ // Agent summary
114
+ lines.push(renderAgentSummary(config.agents));
115
+ lines.push('');
116
+
117
+ // Footer
118
+ lines.push('─'.repeat(80));
119
+ lines.push(chalk.gray.italic('Press Q to quit, R to refresh, V for verbose mode'));
120
+ lines.push('');
121
+
122
+ return lines.join('\n');
123
+ }
package/bin/tui.js ADDED
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * DCYFR AI Framework TUI (Terminal UI)
5
+ * Interactive dashboard using chalk and inquirer
6
+ */
7
+
8
+ import chalk from 'chalk';
9
+ import ora from 'ora';
10
+ import readline from 'readline';
11
+ import { ConfigLoader } from '../dist/ai/config/loader.js';
12
+ import { ValidationFramework } from '../dist/ai/validation/framework.js';
13
+ import { renderValidationDashboard } from './tui/validation-dashboard.js';
14
+ import { runConfigWizard } from './tui/config-wizard.js';
15
+ import { existsSync } from 'fs';
16
+ import { writeFile } from 'fs/promises';
17
+ import { join } from 'path';
18
+
19
+ /**
20
+ * Run interactive validation dashboard
21
+ */
22
+ async function runDashboard(options) {
23
+ const projectRoot = options.root || process.cwd();
24
+ const configFile = options.config;
25
+
26
+ try {
27
+ // Load configuration
28
+ const spinner = ora('Loading configuration...').start();
29
+
30
+ const loader = new ConfigLoader({
31
+ projectRoot,
32
+ configFile,
33
+ validate: true,
34
+ });
35
+
36
+ const config = await loader.load();
37
+ spinner.succeed('Configuration loaded');
38
+
39
+ // Run validation
40
+ spinner.start('Running validation...');
41
+
42
+ const framework = new ValidationFramework({
43
+ gates: config.validation.gates,
44
+ parallel: config.validation.parallel,
45
+ });
46
+
47
+ const report = await framework.validate({
48
+ projectRoot: config.project.root,
49
+ files: config.project.include,
50
+ config: config.agents,
51
+ });
52
+
53
+ spinner.succeed('Validation complete');
54
+
55
+ // Display dashboard
56
+ console.clear();
57
+ console.log(renderValidationDashboard(config, report));
58
+
59
+ // Setup keyboard input for interactive mode
60
+ readline.emitKeypressEvents(process.stdin);
61
+ if (process.stdin.isTTY) {
62
+ process.stdin.setRawMode(true);
63
+ }
64
+
65
+ console.log(chalk.gray('\nPress Q to quit, R to refresh...\n'));
66
+
67
+ process.stdin.on('keypress', async (str, key) => {
68
+ if (key.name === 'q' || (key.ctrl && key.name === 'c')) {
69
+ console.log(chalk.yellow('\n👋 Exiting dashboard...\n'));
70
+ process.exit(0);
71
+ } else if (key.name === 'r') {
72
+ // Refresh
73
+ console.clear();
74
+ const spinner = ora('Refreshing validation...').start();
75
+ const newReport = await framework.validate({
76
+ projectRoot: config.project.root,
77
+ files: config.project.include,
78
+ config: config.agents,
79
+ });
80
+ spinner.succeed('Validation refreshed');
81
+ console.log(renderValidationDashboard(config, newReport));
82
+ console.log(chalk.gray('\nPress Q to quit, R to refresh...\n'));
83
+ }
84
+ });
85
+ } catch (error) {
86
+ console.error(chalk.red('❌ Failed to run dashboard:'), error.message);
87
+ process.exit(1);
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Run interactive configuration wizard
93
+ */
94
+ async function runWizard(options) {
95
+ const projectRoot = options.root || process.cwd();
96
+
97
+ try {
98
+ const config = await runConfigWizard();
99
+
100
+ // Create config file
101
+ await createConfigFile(config, projectRoot);
102
+ } catch (error) {
103
+ if (error.isTTYError) {
104
+ console.error(chalk.red('❌ Prompt couldn\'t be rendered in the current environment'));
105
+ } else {
106
+ console.error(chalk.red('❌ Failed to run wizard:'), error.message);
107
+ }
108
+ process.exit(1);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Create configuration file from wizard state
114
+ */
115
+ async function createConfigFile(state, projectRoot) {
116
+ const configFile = state.format === 'json' ? '.dcyfr.json' : '.dcyfr.yaml';
117
+ const configPath = join(projectRoot, configFile);
118
+
119
+ if (existsSync(configPath)) {
120
+ console.error(chalk.red(`\n❌ Config file already exists: ${configPath}`));
121
+ console.error(chalk.yellow('Delete it first or use --force flag'));
122
+ process.exit(1);
123
+ }
124
+
125
+ // Build config object
126
+ const config = {
127
+ version: '1.0.0',
128
+ projectName: state.projectName || 'my-project',
129
+ telemetry: {
130
+ enabled: state.telemetryEnabled,
131
+ },
132
+ validation: {
133
+ enabled: state.validationEnabled,
134
+ parallel: state.parallelExecution,
135
+ gates: Object.entries(state.agents)
136
+ .filter(([_, cfg]) => cfg.enabled)
137
+ .map(([name]) => name),
138
+ },
139
+ agents: state.agents,
140
+ };
141
+
142
+ // Write file
143
+ const content =
144
+ state.format === 'json'
145
+ ? JSON.stringify(config, null, 2)
146
+ : Object.entries(config)
147
+ .map(([key, val]) => `${key}: ${JSON.stringify(val)}`)
148
+ .join('\n');
149
+
150
+ await writeFile(configPath, content, 'utf-8');
151
+
152
+ console.log(chalk.green(`\n✅ Created ${configPath}`));
153
+ console.log(chalk.cyan('\nNext steps:'));
154
+ console.log(' 1. Review and customize the configuration');
155
+ console.log(' 2. Run ' + chalk.bold('npx @dcyfr/ai tui:dashboard') + ' to test');
156
+ console.log(' 3. Integrate into your CI/CD pipeline\n');
157
+ }
158
+
159
+ /**
160
+ * Show TUI help
161
+ */
162
+ function showHelp() {
163
+ console.log(`
164
+ DCYFR AI Framework - Interactive TUI
165
+
166
+ Usage:
167
+ npx @dcyfr/ai tui:<command> [options]
168
+
169
+ Commands:
170
+ tui:dashboard Interactive validation dashboard
171
+ tui:wizard Interactive configuration wizard
172
+ tui:help Show this help message
173
+
174
+ Options:
175
+ --root <path> Project root directory (default: current directory)
176
+ --config <file> Custom config file path (dashboard only)
177
+ --format <json|yaml> Config format for wizard (default: yaml)
178
+
179
+ Examples:
180
+ # Run interactive validation dashboard
181
+ npx @dcyfr/ai tui:dashboard
182
+
183
+ # Run configuration wizard
184
+ npx @dcyfr/ai tui:wizard
185
+
186
+ # Dashboard with custom config
187
+ npx @dcyfr/ai tui:dashboard --config custom.yaml
188
+
189
+ Keyboard Shortcuts:
190
+ Q Quit
191
+ R Refresh (dashboard)
192
+ V Verbose mode
193
+ Ctrl+C Exit
194
+
195
+ Documentation:
196
+ https://github.com/dcyfr/dcyfr-ai/blob/main/docs/TUI.md
197
+ `);
198
+ process.exit(0);
199
+ }
200
+
201
+ /**
202
+ * Parse command line arguments
203
+ */
204
+ function parseArgs() {
205
+ const args = process.argv.slice(2);
206
+ const command = args[0] || 'help';
207
+ const flags = {};
208
+
209
+ for (let i = 1; i < args.length; i++) {
210
+ const arg = args[i];
211
+
212
+ if (arg.startsWith('--')) {
213
+ const [key, value] = arg.substring(2).split('=');
214
+ if (value !== undefined) {
215
+ flags[key] = value;
216
+ } else {
217
+ flags[key] = args[i + 1]?.startsWith('--') ? true : args[++i] || true;
218
+ }
219
+ }
220
+ }
221
+
222
+ return { command, flags };
223
+ }
224
+
225
+ /**
226
+ * Main CLI entry point
227
+ */
228
+ async function main() {
229
+ const { command, flags } = parseArgs();
230
+
231
+ switch (command) {
232
+ case 'tui:dashboard':
233
+ case 'dashboard':
234
+ await runDashboard(flags);
235
+ break;
236
+
237
+ case 'tui:wizard':
238
+ case 'wizard':
239
+ await runWizard(flags);
240
+ break;
241
+
242
+ case 'tui:help':
243
+ case 'help':
244
+ case '--help':
245
+ case '-h':
246
+ showHelp();
247
+ break;
248
+
249
+ default:
250
+ console.error(`❌ Unknown command: ${command}\n`);
251
+ showHelp();
252
+ }
253
+ }
254
+
255
+ // Run CLI
256
+ main().catch((error) => {
257
+ console.error('❌ Unexpected error:', error);
258
+ process.exit(1);
259
+ });