@ai-coders/context 0.5.2 → 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/README.md +247 -12
- package/dist/generators/agents/agentGenerator.d.ts +3 -0
- package/dist/generators/agents/agentGenerator.d.ts.map +1 -1
- package/dist/generators/agents/agentGenerator.js +13 -7
- package/dist/generators/agents/agentGenerator.js.map +1 -1
- package/dist/generators/agents/templates/playbookTemplate.d.ts.map +1 -1
- package/dist/generators/agents/templates/playbookTemplate.js +3 -1
- package/dist/generators/agents/templates/playbookTemplate.js.map +1 -1
- package/dist/generators/documentation/codebaseMapGenerator.d.ts +98 -0
- package/dist/generators/documentation/codebaseMapGenerator.d.ts.map +1 -0
- package/dist/generators/documentation/codebaseMapGenerator.js +247 -0
- package/dist/generators/documentation/codebaseMapGenerator.js.map +1 -0
- package/dist/generators/documentation/documentationGenerator.d.ts +2 -0
- package/dist/generators/documentation/documentationGenerator.d.ts.map +1 -1
- package/dist/generators/documentation/documentationGenerator.js +20 -1
- package/dist/generators/documentation/documentationGenerator.js.map +1 -1
- package/dist/generators/documentation/index.d.ts +2 -0
- package/dist/generators/documentation/index.d.ts.map +1 -1
- package/dist/generators/documentation/index.js +3 -1
- package/dist/generators/documentation/index.js.map +1 -1
- package/dist/generators/documentation/templates/architectureTemplate.d.ts.map +1 -1
- package/dist/generators/documentation/templates/architectureTemplate.js +2 -31
- package/dist/generators/documentation/templates/architectureTemplate.js.map +1 -1
- package/dist/generators/documentation/templates/common.d.ts +4 -1
- package/dist/generators/documentation/templates/common.d.ts.map +1 -1
- package/dist/generators/documentation/templates/common.js +4 -2
- package/dist/generators/documentation/templates/common.js.map +1 -1
- package/dist/generators/plans/templates/planTemplate.d.ts.map +1 -1
- package/dist/generators/plans/templates/planTemplate.js +46 -2
- package/dist/generators/plans/templates/planTemplate.js.map +1 -1
- package/dist/generators/skills/index.d.ts +7 -0
- package/dist/generators/skills/index.d.ts.map +1 -0
- package/dist/generators/skills/index.js +15 -0
- package/dist/generators/skills/index.js.map +1 -0
- package/dist/generators/skills/skillGenerator.d.ts +53 -0
- package/dist/generators/skills/skillGenerator.d.ts.map +1 -0
- package/dist/generators/skills/skillGenerator.js +149 -0
- package/dist/generators/skills/skillGenerator.js.map +1 -0
- package/dist/generators/skills/templates/indexTemplate.d.ts +13 -0
- package/dist/generators/skills/templates/indexTemplate.d.ts.map +1 -0
- package/dist/generators/skills/templates/indexTemplate.js +102 -0
- package/dist/generators/skills/templates/indexTemplate.js.map +1 -0
- package/dist/generators/skills/templates/skillTemplate.d.ts +20 -0
- package/dist/generators/skills/templates/skillTemplate.d.ts.map +1 -0
- package/dist/generators/skills/templates/skillTemplate.js +85 -0
- package/dist/generators/skills/templates/skillTemplate.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1315 -43
- package/dist/index.js.map +1 -1
- package/dist/services/ai/agentEvents.d.ts +1 -1
- package/dist/services/ai/agentEvents.d.ts.map +1 -1
- package/dist/services/ai/agents/index.d.ts +2 -0
- package/dist/services/ai/agents/index.d.ts.map +1 -1
- package/dist/services/ai/agents/index.js +3 -1
- package/dist/services/ai/agents/index.js.map +1 -1
- package/dist/services/ai/agents/skillAgent.d.ts +49 -0
- package/dist/services/ai/agents/skillAgent.d.ts.map +1 -0
- package/dist/services/ai/agents/skillAgent.js +179 -0
- package/dist/services/ai/agents/skillAgent.js.map +1 -0
- package/dist/services/ai/prompts/index.d.ts +1 -1
- package/dist/services/ai/prompts/index.d.ts.map +1 -1
- package/dist/services/ai/prompts/index.js +2 -1
- package/dist/services/ai/prompts/index.js.map +1 -1
- package/dist/services/ai/prompts/sharedPrompts.d.ts +4 -0
- package/dist/services/ai/prompts/sharedPrompts.d.ts.map +1 -1
- package/dist/services/ai/prompts/sharedPrompts.js +33 -0
- package/dist/services/ai/prompts/sharedPrompts.js.map +1 -1
- package/dist/services/ai/schemas.d.ts +98 -1
- package/dist/services/ai/schemas.d.ts.map +1 -1
- package/dist/services/ai/schemas.js +61 -3
- package/dist/services/ai/schemas.js.map +1 -1
- package/dist/services/ai/toolRegistry.d.ts.map +1 -1
- package/dist/services/ai/toolRegistry.js +17 -0
- package/dist/services/ai/toolRegistry.js.map +1 -1
- package/dist/services/ai/tools/fillScaffoldingTool.d.ts +21 -4
- package/dist/services/ai/tools/fillScaffoldingTool.d.ts.map +1 -1
- package/dist/services/ai/tools/fillScaffoldingTool.js +17 -0
- package/dist/services/ai/tools/fillScaffoldingTool.js.map +1 -1
- package/dist/services/ai/tools/getCodebaseMapTool.d.ts +17 -0
- package/dist/services/ai/tools/getCodebaseMapTool.d.ts.map +1 -0
- package/dist/services/ai/tools/getCodebaseMapTool.js +115 -0
- package/dist/services/ai/tools/getCodebaseMapTool.js.map +1 -0
- package/dist/services/ai/tools/index.d.ts +3 -2
- package/dist/services/ai/tools/index.d.ts.map +1 -1
- package/dist/services/ai/tools/index.js +12 -3
- package/dist/services/ai/tools/index.js.map +1 -1
- package/dist/services/ai/tools/initializeContextTool.d.ts +22 -4
- package/dist/services/ai/tools/initializeContextTool.d.ts.map +1 -1
- package/dist/services/ai/tools/initializeContextTool.js +201 -16
- package/dist/services/ai/tools/initializeContextTool.js.map +1 -1
- package/dist/services/ai/tools/scaffoldPlanTool.d.ts +11 -0
- package/dist/services/ai/tools/scaffoldPlanTool.d.ts.map +1 -1
- package/dist/services/ai/tools/scaffoldPlanTool.js +79 -7
- package/dist/services/ai/tools/scaffoldPlanTool.js.map +1 -1
- package/dist/services/export/exportRulesService.d.ts +62 -0
- package/dist/services/export/exportRulesService.d.ts.map +1 -0
- package/dist/services/export/exportRulesService.js +242 -0
- package/dist/services/export/exportRulesService.js.map +1 -0
- package/dist/services/export/index.d.ts +5 -0
- package/dist/services/export/index.d.ts.map +1 -0
- package/dist/services/export/index.js +10 -0
- package/dist/services/export/index.js.map +1 -0
- package/dist/services/export/skillExportService.d.ts +64 -0
- package/dist/services/export/skillExportService.d.ts.map +1 -0
- package/dist/services/export/skillExportService.js +238 -0
- package/dist/services/export/skillExportService.js.map +1 -0
- package/dist/services/fill/skillFillService.d.ts +50 -0
- package/dist/services/fill/skillFillService.d.ts.map +1 -0
- package/dist/services/fill/skillFillService.js +254 -0
- package/dist/services/fill/skillFillService.js.map +1 -0
- package/dist/services/import/agentsDetector.d.ts +12 -0
- package/dist/services/import/agentsDetector.d.ts.map +1 -0
- package/dist/services/import/agentsDetector.js +183 -0
- package/dist/services/import/agentsDetector.js.map +1 -0
- package/dist/services/import/importAgentsService.d.ts +14 -0
- package/dist/services/import/importAgentsService.d.ts.map +1 -0
- package/dist/services/import/importAgentsService.js +195 -0
- package/dist/services/import/importAgentsService.js.map +1 -0
- package/dist/services/import/importRulesService.d.ts +17 -0
- package/dist/services/import/importRulesService.d.ts.map +1 -0
- package/dist/services/import/importRulesService.js +222 -0
- package/dist/services/import/importRulesService.js.map +1 -0
- package/dist/services/import/index.d.ts +7 -0
- package/dist/services/import/index.d.ts.map +1 -0
- package/dist/services/import/index.js +28 -0
- package/dist/services/import/index.js.map +1 -0
- package/dist/services/import/presets.d.ts +8 -0
- package/dist/services/import/presets.d.ts.map +1 -0
- package/dist/services/import/presets.js +176 -0
- package/dist/services/import/presets.js.map +1 -0
- package/dist/services/import/rulesDetector.d.ts +16 -0
- package/dist/services/import/rulesDetector.d.ts.map +1 -0
- package/dist/services/import/rulesDetector.js +278 -0
- package/dist/services/import/rulesDetector.js.map +1 -0
- package/dist/services/import/types.d.ts +72 -0
- package/dist/services/import/types.d.ts.map +1 -0
- package/dist/services/import/types.js +3 -0
- package/dist/services/import/types.js.map +1 -0
- package/dist/services/mcp/mcpServer.d.ts +24 -0
- package/dist/services/mcp/mcpServer.d.ts.map +1 -1
- package/dist/services/mcp/mcpServer.js +1651 -7
- package/dist/services/mcp/mcpServer.js.map +1 -1
- package/dist/services/quickSync/index.d.ts +3 -0
- package/dist/services/quickSync/index.d.ts.map +1 -0
- package/dist/services/quickSync/index.js +7 -0
- package/dist/services/quickSync/index.js.map +1 -0
- package/dist/services/quickSync/quickSyncService.d.ts +72 -0
- package/dist/services/quickSync/quickSyncService.d.ts.map +1 -0
- package/dist/services/quickSync/quickSyncService.js +268 -0
- package/dist/services/quickSync/quickSyncService.js.map +1 -0
- package/dist/services/report/index.d.ts +3 -0
- package/dist/services/report/index.d.ts.map +1 -0
- package/dist/services/report/index.js +6 -0
- package/dist/services/report/index.js.map +1 -0
- package/dist/services/report/reportService.d.ts +131 -0
- package/dist/services/report/reportService.d.ts.map +1 -0
- package/dist/services/report/reportService.js +372 -0
- package/dist/services/report/reportService.js.map +1 -0
- package/dist/services/semantic/contextBuilder.d.ts +8 -1
- package/dist/services/semantic/contextBuilder.d.ts.map +1 -1
- package/dist/services/semantic/contextBuilder.js +107 -20
- package/dist/services/semantic/contextBuilder.js.map +1 -1
- package/dist/services/shared/globPatterns.d.ts +48 -0
- package/dist/services/shared/globPatterns.d.ts.map +1 -0
- package/dist/services/shared/globPatterns.js +110 -0
- package/dist/services/shared/globPatterns.js.map +1 -0
- package/dist/services/shared/index.d.ts +10 -0
- package/dist/services/shared/index.d.ts.map +1 -0
- package/dist/services/shared/index.js +46 -0
- package/dist/services/shared/index.js.map +1 -0
- package/dist/services/shared/pathHelpers.d.ts +71 -0
- package/dist/services/shared/pathHelpers.d.ts.map +1 -0
- package/dist/services/shared/pathHelpers.js +162 -0
- package/dist/services/shared/pathHelpers.js.map +1 -0
- package/dist/services/shared/types.d.ts +74 -0
- package/dist/services/shared/types.d.ts.map +1 -0
- package/dist/services/shared/types.js +44 -0
- package/dist/services/shared/types.js.map +1 -0
- package/dist/services/shared/uiHelpers.d.ts +70 -0
- package/dist/services/shared/uiHelpers.d.ts.map +1 -0
- package/dist/services/shared/uiHelpers.js +131 -0
- package/dist/services/shared/uiHelpers.js.map +1 -0
- package/dist/services/stack/index.d.ts +6 -0
- package/dist/services/stack/index.d.ts.map +1 -0
- package/dist/services/stack/index.js +25 -0
- package/dist/services/stack/index.js.map +1 -0
- package/dist/services/stack/projectTypeClassifier.d.ts +59 -0
- package/dist/services/stack/projectTypeClassifier.d.ts.map +1 -0
- package/dist/services/stack/projectTypeClassifier.js +242 -0
- package/dist/services/stack/projectTypeClassifier.js.map +1 -0
- package/dist/services/stack/scaffoldFilter.d.ts +75 -0
- package/dist/services/stack/scaffoldFilter.d.ts.map +1 -0
- package/dist/services/stack/scaffoldFilter.js +222 -0
- package/dist/services/stack/scaffoldFilter.js.map +1 -0
- package/dist/services/stack/stackDetector.d.ts +43 -0
- package/dist/services/stack/stackDetector.d.ts.map +1 -0
- package/dist/services/stack/stackDetector.js +406 -0
- package/dist/services/stack/stackDetector.js.map +1 -0
- package/dist/services/start/index.d.ts +3 -0
- package/dist/services/start/index.d.ts.map +1 -0
- package/dist/services/start/index.js +6 -0
- package/dist/services/start/index.js.map +1 -0
- package/dist/services/start/startService.d.ts +64 -0
- package/dist/services/start/startService.d.ts.map +1 -0
- package/dist/services/start/startService.js +180 -0
- package/dist/services/start/startService.js.map +1 -0
- package/dist/services/sync/presets.d.ts.map +1 -1
- package/dist/services/sync/presets.js +16 -1
- package/dist/services/sync/presets.js.map +1 -1
- package/dist/services/sync/types.d.ts +1 -1
- package/dist/services/sync/types.d.ts.map +1 -1
- package/dist/services/workflow/autoAdvance.d.ts +38 -0
- package/dist/services/workflow/autoAdvance.d.ts.map +1 -0
- package/dist/services/workflow/autoAdvance.js +219 -0
- package/dist/services/workflow/autoAdvance.js.map +1 -0
- package/dist/services/workflow/index.d.ts +6 -0
- package/dist/services/workflow/index.d.ts.map +1 -0
- package/dist/services/workflow/index.js +11 -0
- package/dist/services/workflow/index.js.map +1 -0
- package/dist/services/workflow/workflowService.d.ts +98 -0
- package/dist/services/workflow/workflowService.d.ts.map +1 -0
- package/dist/services/workflow/workflowService.js +210 -0
- package/dist/services/workflow/workflowService.js.map +1 -0
- package/dist/utils/cliUI.d.ts +4 -0
- package/dist/utils/cliUI.d.ts.map +1 -1
- package/dist/utils/cliUI.js +31 -1
- package/dist/utils/cliUI.js.map +1 -1
- package/dist/utils/i18n.d.ts +202 -0
- package/dist/utils/i18n.d.ts.map +1 -1
- package/dist/utils/i18n.js +438 -2
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/theme.d.ts +1 -0
- package/dist/utils/theme.d.ts.map +1 -1
- package/dist/utils/theme.js +1 -0
- package/dist/utils/theme.js.map +1 -1
- package/dist/workflow/agents/agentRegistry.d.ts +82 -0
- package/dist/workflow/agents/agentRegistry.d.ts.map +1 -0
- package/dist/workflow/agents/agentRegistry.js +205 -0
- package/dist/workflow/agents/agentRegistry.js.map +1 -0
- package/dist/workflow/agents/index.d.ts +7 -0
- package/dist/workflow/agents/index.d.ts.map +1 -0
- package/dist/workflow/agents/index.js +14 -0
- package/dist/workflow/agents/index.js.map +1 -0
- package/dist/workflow/collaboration.d.ts +110 -0
- package/dist/workflow/collaboration.d.ts.map +1 -0
- package/dist/workflow/collaboration.js +301 -0
- package/dist/workflow/collaboration.js.map +1 -0
- package/dist/workflow/index.d.ts +25 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +124 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/orchestration/agentOrchestrator.d.ts +68 -0
- package/dist/workflow/orchestration/agentOrchestrator.d.ts.map +1 -0
- package/dist/workflow/orchestration/agentOrchestrator.js +280 -0
- package/dist/workflow/orchestration/agentOrchestrator.js.map +1 -0
- package/dist/workflow/orchestration/documentLinker.d.ts +100 -0
- package/dist/workflow/orchestration/documentLinker.d.ts.map +1 -0
- package/dist/workflow/orchestration/documentLinker.js +266 -0
- package/dist/workflow/orchestration/documentLinker.js.map +1 -0
- package/dist/workflow/orchestration/index.d.ts +9 -0
- package/dist/workflow/orchestration/index.d.ts.map +1 -0
- package/dist/workflow/orchestration/index.js +25 -0
- package/dist/workflow/orchestration/index.js.map +1 -0
- package/dist/workflow/orchestrator.d.ts +99 -0
- package/dist/workflow/orchestrator.d.ts.map +1 -0
- package/dist/workflow/orchestrator.js +217 -0
- package/dist/workflow/orchestrator.js.map +1 -0
- package/dist/workflow/phases.d.ts +64 -0
- package/dist/workflow/phases.d.ts.map +1 -0
- package/dist/workflow/phases.js +151 -0
- package/dist/workflow/phases.js.map +1 -0
- package/dist/workflow/plans/index.d.ts +8 -0
- package/dist/workflow/plans/index.d.ts.map +1 -0
- package/dist/workflow/plans/index.js +27 -0
- package/dist/workflow/plans/index.js.map +1 -0
- package/dist/workflow/plans/planLinker.d.ts +119 -0
- package/dist/workflow/plans/planLinker.d.ts.map +1 -0
- package/dist/workflow/plans/planLinker.js +499 -0
- package/dist/workflow/plans/planLinker.js.map +1 -0
- package/dist/workflow/plans/types.d.ts +167 -0
- package/dist/workflow/plans/types.d.ts.map +1 -0
- package/dist/workflow/plans/types.js +25 -0
- package/dist/workflow/plans/types.js.map +1 -0
- package/dist/workflow/prevcConfig.d.ts +27 -0
- package/dist/workflow/prevcConfig.d.ts.map +1 -0
- package/dist/workflow/prevcConfig.js +153 -0
- package/dist/workflow/prevcConfig.js.map +1 -0
- package/dist/workflow/roles.d.ts +44 -0
- package/dist/workflow/roles.d.ts.map +1 -0
- package/dist/workflow/roles.js +112 -0
- package/dist/workflow/roles.js.map +1 -0
- package/dist/workflow/scaling.d.ts +44 -0
- package/dist/workflow/scaling.d.ts.map +1 -0
- package/dist/workflow/scaling.js +224 -0
- package/dist/workflow/scaling.js.map +1 -0
- package/dist/workflow/skills/frontmatter.d.ts +23 -0
- package/dist/workflow/skills/frontmatter.d.ts.map +1 -0
- package/dist/workflow/skills/frontmatter.js +100 -0
- package/dist/workflow/skills/frontmatter.js.map +1 -0
- package/dist/workflow/skills/index.d.ts +10 -0
- package/dist/workflow/skills/index.d.ts.map +1 -0
- package/dist/workflow/skills/index.js +22 -0
- package/dist/workflow/skills/index.js.map +1 -0
- package/dist/workflow/skills/skillRegistry.d.ts +60 -0
- package/dist/workflow/skills/skillRegistry.d.ts.map +1 -0
- package/dist/workflow/skills/skillRegistry.js +257 -0
- package/dist/workflow/skills/skillRegistry.js.map +1 -0
- package/dist/workflow/skills/skillTemplates.d.ts +16 -0
- package/dist/workflow/skills/skillTemplates.d.ts.map +1 -0
- package/dist/workflow/skills/skillTemplates.js +610 -0
- package/dist/workflow/skills/skillTemplates.js.map +1 -0
- package/dist/workflow/skills/types.d.ts +72 -0
- package/dist/workflow/skills/types.d.ts.map +1 -0
- package/dist/workflow/skills/types.js +48 -0
- package/dist/workflow/skills/types.js.map +1 -0
- package/dist/workflow/status/statusManager.d.ts +84 -0
- package/dist/workflow/status/statusManager.d.ts.map +1 -0
- package/dist/workflow/status/statusManager.js +402 -0
- package/dist/workflow/status/statusManager.js.map +1 -0
- package/dist/workflow/status/templates.d.ts +40 -0
- package/dist/workflow/status/templates.d.ts.map +1 -0
- package/dist/workflow/status/templates.js +148 -0
- package/dist/workflow/status/templates.js.map +1 -0
- package/dist/workflow/types.d.ts +178 -0
- package/dist/workflow/types.d.ts.map +1 -0
- package/dist/workflow/types.js +25 -0
- package/dist/workflow/types.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -57,10 +57,18 @@ const initService_1 = require("./services/init/initService");
|
|
|
57
57
|
const fillService_1 = require("./services/fill/fillService");
|
|
58
58
|
const planService_1 = require("./services/plan/planService");
|
|
59
59
|
const syncService_1 = require("./services/sync/syncService");
|
|
60
|
+
const import_1 = require("./services/import");
|
|
60
61
|
const serve_1 = require("./services/serve");
|
|
61
62
|
const mcp_1 = require("./services/mcp");
|
|
62
63
|
const state_1 = require("./services/state");
|
|
63
64
|
const update_1 = require("./services/update");
|
|
65
|
+
const workflow_1 = require("./services/workflow");
|
|
66
|
+
const start_1 = require("./services/start");
|
|
67
|
+
const export_1 = require("./services/export");
|
|
68
|
+
const report_1 = require("./services/report");
|
|
69
|
+
const quickSync_1 = require("./services/quickSync");
|
|
70
|
+
const workflow_2 = require("./workflow");
|
|
71
|
+
const providerFactory_1 = require("./services/ai/providerFactory");
|
|
64
72
|
const prompts_1 = require("./utils/prompts");
|
|
65
73
|
const version_1 = require("./version");
|
|
66
74
|
const rawArgs = process.argv.slice(2);
|
|
@@ -101,6 +109,16 @@ const syncService = new syncService_1.SyncService({
|
|
|
101
109
|
t,
|
|
102
110
|
version: version_1.VERSION
|
|
103
111
|
});
|
|
112
|
+
const importRulesService = new import_1.ImportRulesService({
|
|
113
|
+
ui,
|
|
114
|
+
t,
|
|
115
|
+
version: version_1.VERSION
|
|
116
|
+
});
|
|
117
|
+
const importAgentsService = new import_1.ImportAgentsService({
|
|
118
|
+
ui,
|
|
119
|
+
t,
|
|
120
|
+
version: version_1.VERSION
|
|
121
|
+
});
|
|
104
122
|
const updateService = new update_1.UpdateService({
|
|
105
123
|
ui,
|
|
106
124
|
t
|
|
@@ -312,6 +330,60 @@ program
|
|
|
312
330
|
process.exit(1);
|
|
313
331
|
}
|
|
314
332
|
});
|
|
333
|
+
program
|
|
334
|
+
.command('import-rules')
|
|
335
|
+
.description(t('commands.importRules.description'))
|
|
336
|
+
.argument('[repo-path]', 'Repository path to scan', process.cwd())
|
|
337
|
+
.option('-s, --source <paths...>', t('commands.importRules.options.source'))
|
|
338
|
+
.option('-t, --target <dir>', t('commands.importRules.options.target'))
|
|
339
|
+
.option('-f, --format <format>', t('commands.importRules.options.format'), 'markdown')
|
|
340
|
+
.option('--force', t('commands.importRules.options.force'))
|
|
341
|
+
.option('--dry-run', t('commands.importRules.options.dryRun'))
|
|
342
|
+
.option('-v, --verbose', t('commands.importRules.options.verbose'))
|
|
343
|
+
.option('--no-auto-detect', 'Disable auto-detection')
|
|
344
|
+
.action(async (repoPath, options) => {
|
|
345
|
+
try {
|
|
346
|
+
await importRulesService.run({
|
|
347
|
+
source: options.source,
|
|
348
|
+
target: options.target,
|
|
349
|
+
format: options.format,
|
|
350
|
+
force: options.force,
|
|
351
|
+
dryRun: options.dryRun,
|
|
352
|
+
verbose: options.verbose,
|
|
353
|
+
autoDetect: options.autoDetect !== false
|
|
354
|
+
}, repoPath);
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
ui.displayError(t('errors.import.failed'), error);
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
program
|
|
362
|
+
.command('import-agents')
|
|
363
|
+
.description(t('commands.importAgents.description'))
|
|
364
|
+
.argument('[repo-path]', 'Repository path to scan', process.cwd())
|
|
365
|
+
.option('-s, --source <paths...>', t('commands.importAgents.options.source'))
|
|
366
|
+
.option('-t, --target <dir>', t('commands.importAgents.options.target'))
|
|
367
|
+
.option('--force', t('commands.importAgents.options.force'))
|
|
368
|
+
.option('--dry-run', t('commands.importAgents.options.dryRun'))
|
|
369
|
+
.option('-v, --verbose', t('commands.importAgents.options.verbose'))
|
|
370
|
+
.option('--no-auto-detect', 'Disable auto-detection')
|
|
371
|
+
.action(async (repoPath, options) => {
|
|
372
|
+
try {
|
|
373
|
+
await importAgentsService.run({
|
|
374
|
+
source: options.source,
|
|
375
|
+
target: options.target,
|
|
376
|
+
force: options.force,
|
|
377
|
+
dryRun: options.dryRun,
|
|
378
|
+
verbose: options.verbose,
|
|
379
|
+
autoDetect: options.autoDetect !== false
|
|
380
|
+
}, repoPath);
|
|
381
|
+
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
ui.displayError(t('errors.import.failed'), error);
|
|
384
|
+
process.exit(1);
|
|
385
|
+
}
|
|
386
|
+
});
|
|
315
387
|
program
|
|
316
388
|
.command('serve')
|
|
317
389
|
.description('Start passthrough server for external AI agents (stdin/stdout JSON)')
|
|
@@ -362,6 +434,441 @@ program
|
|
|
362
434
|
process.exit(1);
|
|
363
435
|
}
|
|
364
436
|
});
|
|
437
|
+
// Smart Start Command
|
|
438
|
+
program
|
|
439
|
+
.command('start')
|
|
440
|
+
.description(t('commands.start.description'))
|
|
441
|
+
.argument('[feature-name]', t('commands.start.arguments.featureName'))
|
|
442
|
+
.option('-t, --template <template>', t('commands.start.options.template'), 'auto')
|
|
443
|
+
.option('--skip-fill', t('commands.start.options.skipFill'))
|
|
444
|
+
.option('--skip-workflow', t('commands.start.options.skipWorkflow'))
|
|
445
|
+
.option('-k, --api-key <key>', t('commands.fill.options.apiKey'))
|
|
446
|
+
.option('-m, --model <model>', t('commands.fill.options.model'), DEFAULT_MODEL)
|
|
447
|
+
.option('-p, --provider <provider>', t('commands.fill.options.provider'))
|
|
448
|
+
.option('-v, --verbose', t('commands.fill.options.verbose'))
|
|
449
|
+
.action(async (featureName, options) => {
|
|
450
|
+
try {
|
|
451
|
+
const startService = new start_1.StartService({
|
|
452
|
+
ui,
|
|
453
|
+
t,
|
|
454
|
+
version: version_1.VERSION,
|
|
455
|
+
defaultModel: DEFAULT_MODEL,
|
|
456
|
+
});
|
|
457
|
+
const result = await startService.run(process.cwd(), {
|
|
458
|
+
featureName,
|
|
459
|
+
template: options.template,
|
|
460
|
+
skipFill: options.skipFill,
|
|
461
|
+
skipWorkflow: options.skipWorkflow,
|
|
462
|
+
apiKey: options.apiKey,
|
|
463
|
+
model: options.model,
|
|
464
|
+
provider: options.provider,
|
|
465
|
+
verbose: options.verbose,
|
|
466
|
+
});
|
|
467
|
+
// Display summary
|
|
468
|
+
const details = [];
|
|
469
|
+
if (result.initialized)
|
|
470
|
+
details.push('context initialized');
|
|
471
|
+
if (result.filled)
|
|
472
|
+
details.push('docs filled');
|
|
473
|
+
if (result.workflowStarted)
|
|
474
|
+
details.push(`workflow started (${(0, workflow_2.getScaleName)(result.scale)})`);
|
|
475
|
+
if (result.stackDetected?.primaryLanguage) {
|
|
476
|
+
details.push(`stack: ${result.stackDetected.primaryLanguage}`);
|
|
477
|
+
}
|
|
478
|
+
ui.displaySuccess(t('success.start.complete', { details: details.join(', ') }));
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
ui.displayError(t('errors.cli.executionFailed'), error);
|
|
482
|
+
process.exit(1);
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
// Export Rules Command
|
|
486
|
+
program
|
|
487
|
+
.command('export-rules')
|
|
488
|
+
.description(t('commands.export.description'))
|
|
489
|
+
.argument('[repo-path]', 'Repository path', process.cwd())
|
|
490
|
+
.option('-s, --source <dir>', t('commands.export.options.source'), '.context/docs')
|
|
491
|
+
.option('-t, --targets <paths...>', t('commands.export.options.targets'))
|
|
492
|
+
.option('--preset <name>', t('commands.export.options.preset'))
|
|
493
|
+
.option('--force', t('commands.export.options.force'))
|
|
494
|
+
.option('--dry-run', t('commands.export.options.dryRun'))
|
|
495
|
+
.option('-v, --verbose', t('commands.fill.options.verbose'))
|
|
496
|
+
.action(async (repoPath, options) => {
|
|
497
|
+
try {
|
|
498
|
+
const exportService = new export_1.ExportRulesService({
|
|
499
|
+
ui,
|
|
500
|
+
t,
|
|
501
|
+
version: version_1.VERSION,
|
|
502
|
+
});
|
|
503
|
+
await exportService.run(repoPath, {
|
|
504
|
+
source: options.source,
|
|
505
|
+
targets: options.targets,
|
|
506
|
+
preset: options.preset,
|
|
507
|
+
force: options.force,
|
|
508
|
+
dryRun: options.dryRun,
|
|
509
|
+
verbose: options.verbose,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
catch (error) {
|
|
513
|
+
ui.displayError(t('errors.cli.executionFailed'), error);
|
|
514
|
+
process.exit(1);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
// Report Command
|
|
518
|
+
program
|
|
519
|
+
.command('report')
|
|
520
|
+
.description(t('commands.report.description'))
|
|
521
|
+
.argument('[repo-path]', 'Repository path', process.cwd())
|
|
522
|
+
.option('-f, --format <format>', t('commands.report.options.format'), 'console')
|
|
523
|
+
.option('-o, --output <path>', t('commands.report.options.output'))
|
|
524
|
+
.option('--include-stack', t('commands.report.options.includeStack'))
|
|
525
|
+
.option('-v, --verbose', t('commands.fill.options.verbose'))
|
|
526
|
+
.action(async (repoPath, options) => {
|
|
527
|
+
try {
|
|
528
|
+
const reportService = new report_1.ReportService({
|
|
529
|
+
ui,
|
|
530
|
+
t,
|
|
531
|
+
version: version_1.VERSION,
|
|
532
|
+
});
|
|
533
|
+
const report = await reportService.generate(repoPath, {
|
|
534
|
+
format: options.format,
|
|
535
|
+
output: options.output,
|
|
536
|
+
includeStack: options.includeStack,
|
|
537
|
+
verbose: options.verbose,
|
|
538
|
+
});
|
|
539
|
+
await reportService.output(report, options);
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
ui.displayError(t('errors.cli.executionFailed'), error);
|
|
543
|
+
process.exit(1);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
// Skill Commands
|
|
547
|
+
const skillCommand = program
|
|
548
|
+
.command('skill')
|
|
549
|
+
.description(t('commands.skill.description'));
|
|
550
|
+
skillCommand
|
|
551
|
+
.command('init')
|
|
552
|
+
.description(t('commands.skill.init.description'))
|
|
553
|
+
.argument('[repo-path]', 'Repository path', process.cwd())
|
|
554
|
+
.option('-f, --force', 'Overwrite existing files')
|
|
555
|
+
.option('--skills <skills...>', 'Specific skills to scaffold')
|
|
556
|
+
.action(async (repoPath, options) => {
|
|
557
|
+
try {
|
|
558
|
+
const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
|
|
559
|
+
const generator = createSkillGenerator({ repoPath });
|
|
560
|
+
const result = await generator.generate({
|
|
561
|
+
skills: options.skills,
|
|
562
|
+
force: options.force,
|
|
563
|
+
});
|
|
564
|
+
ui.displaySuccess(`Skills initialized in ${result.skillsDir}`);
|
|
565
|
+
ui.displayInfo('Generated', result.generatedSkills.join(', ') || 'none');
|
|
566
|
+
if (result.skippedSkills.length > 0) {
|
|
567
|
+
ui.displayInfo('Skipped (already exist)', result.skippedSkills.join(', '));
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
ui.displayError('Failed to initialize skills', error);
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
skillCommand
|
|
576
|
+
.command('fill')
|
|
577
|
+
.description(t('commands.skill.fill.description'))
|
|
578
|
+
.argument('[repo-path]', 'Repository path', process.cwd())
|
|
579
|
+
.option('-o, --output <dir>', 'Output directory', '.context')
|
|
580
|
+
.option('-f, --force', 'Overwrite existing content')
|
|
581
|
+
.option('--skills <skills...>', 'Specific skills to fill')
|
|
582
|
+
.option('--model <model>', 'LLM model to use')
|
|
583
|
+
.option('--provider <provider>', 'LLM provider (anthropic, openai, google, openrouter)')
|
|
584
|
+
.option('--api-key <key>', 'API key for LLM provider')
|
|
585
|
+
.option('--base-url <url>', 'Base URL for custom LLM endpoint')
|
|
586
|
+
.option('--no-semantic', 'Disable semantic context mode')
|
|
587
|
+
.option('--use-lsp', 'Enable LSP for deeper analysis')
|
|
588
|
+
.option('-v, --verbose', 'Show detailed progress')
|
|
589
|
+
.option('--limit <number>', 'Limit number of skills to fill', parseInt)
|
|
590
|
+
.action(async (repoPath, options) => {
|
|
591
|
+
try {
|
|
592
|
+
const { SkillFillService } = await Promise.resolve().then(() => __importStar(require('./services/fill/skillFillService')));
|
|
593
|
+
const skillFillService = new SkillFillService({
|
|
594
|
+
ui,
|
|
595
|
+
t,
|
|
596
|
+
version: version_1.VERSION,
|
|
597
|
+
defaultModel: DEFAULT_MODEL,
|
|
598
|
+
});
|
|
599
|
+
const result = await skillFillService.run(repoPath, {
|
|
600
|
+
output: options.output,
|
|
601
|
+
skills: options.skills,
|
|
602
|
+
force: options.force,
|
|
603
|
+
model: options.model,
|
|
604
|
+
provider: options.provider,
|
|
605
|
+
apiKey: options.apiKey,
|
|
606
|
+
baseUrl: options.baseUrl,
|
|
607
|
+
semantic: options.semantic,
|
|
608
|
+
useLsp: options.useLsp,
|
|
609
|
+
verbose: options.verbose,
|
|
610
|
+
limit: options.limit,
|
|
611
|
+
});
|
|
612
|
+
if (result.filled.length > 0) {
|
|
613
|
+
ui.displaySuccess(t('success.skill.filled', { count: result.filled.length }));
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
ui.displayError(t('errors.skill.fillFailed'), error);
|
|
618
|
+
process.exit(1);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
skillCommand
|
|
622
|
+
.command('list')
|
|
623
|
+
.description(t('commands.skill.list.description'))
|
|
624
|
+
.argument('[repo-path]', 'Repository path', process.cwd())
|
|
625
|
+
.option('--json', 'Output as JSON')
|
|
626
|
+
.action(async (repoPath, options) => {
|
|
627
|
+
try {
|
|
628
|
+
const { createSkillRegistry, BUILT_IN_SKILLS } = await Promise.resolve().then(() => __importStar(require('./workflow/skills')));
|
|
629
|
+
const registry = createSkillRegistry(repoPath);
|
|
630
|
+
const discovered = await registry.discoverAll();
|
|
631
|
+
if (options.json) {
|
|
632
|
+
console.log(JSON.stringify({
|
|
633
|
+
builtIn: discovered.builtIn.map(s => s.slug),
|
|
634
|
+
custom: discovered.custom.map(s => s.slug),
|
|
635
|
+
total: discovered.all.length,
|
|
636
|
+
}, null, 2));
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
console.log('\nBuilt-in Skills:');
|
|
640
|
+
for (const skill of discovered.builtIn) {
|
|
641
|
+
const scaffolded = discovered.all.find(s => s.slug === skill.slug && s.path.includes('.context'));
|
|
642
|
+
const status = scaffolded ? '[scaffolded]' : '[available]';
|
|
643
|
+
console.log(` ${skill.slug} ${status}`);
|
|
644
|
+
console.log(` ${skill.metadata.description}`);
|
|
645
|
+
}
|
|
646
|
+
if (discovered.custom.length > 0) {
|
|
647
|
+
console.log('\nCustom Skills:');
|
|
648
|
+
for (const skill of discovered.custom) {
|
|
649
|
+
console.log(` ${skill.slug}`);
|
|
650
|
+
console.log(` ${skill.metadata.description}`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
console.log(`\nTotal: ${discovered.all.length} skills (${discovered.builtIn.length} built-in, ${discovered.custom.length} custom)`);
|
|
654
|
+
}
|
|
655
|
+
catch (error) {
|
|
656
|
+
ui.displayError('Failed to list skills', error);
|
|
657
|
+
process.exit(1);
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
skillCommand
|
|
661
|
+
.command('export')
|
|
662
|
+
.description(t('commands.skill.export.description'))
|
|
663
|
+
.argument('[repo-path]', 'Repository path', process.cwd())
|
|
664
|
+
.option('-p, --preset <preset>', 'Export preset: claude, gemini, codex, all', 'all')
|
|
665
|
+
.option('-f, --force', 'Overwrite existing files')
|
|
666
|
+
.option('--include-builtin', 'Include built-in skills even if not scaffolded')
|
|
667
|
+
.option('--dry-run', 'Preview changes without writing')
|
|
668
|
+
.action(async (repoPath, options) => {
|
|
669
|
+
try {
|
|
670
|
+
const { SkillExportService } = await Promise.resolve().then(() => __importStar(require('./services/export/skillExportService')));
|
|
671
|
+
const exportService = new SkillExportService({
|
|
672
|
+
ui,
|
|
673
|
+
t,
|
|
674
|
+
version: version_1.VERSION,
|
|
675
|
+
});
|
|
676
|
+
const result = await exportService.run(repoPath, {
|
|
677
|
+
preset: options.preset,
|
|
678
|
+
force: options.force,
|
|
679
|
+
includeBuiltIn: options.includeBuiltin,
|
|
680
|
+
dryRun: options.dryRun,
|
|
681
|
+
});
|
|
682
|
+
if (options.dryRun) {
|
|
683
|
+
ui.displayInfo('Dry run', 'No files were written');
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
ui.displaySuccess(`Exported ${result.skillsExported.length} skills to ${result.targets.length} targets`);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
catch (error) {
|
|
690
|
+
ui.displayError('Failed to export skills', error);
|
|
691
|
+
process.exit(1);
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
skillCommand
|
|
695
|
+
.command('create <name>')
|
|
696
|
+
.description(t('commands.skill.create.description'))
|
|
697
|
+
.argument('[repo-path]', 'Repository path', process.cwd())
|
|
698
|
+
.option('-d, --description <text>', 'Skill description')
|
|
699
|
+
.option('--phases <phases...>', 'PREVC phases (P, R, E, V, C)')
|
|
700
|
+
.option('-f, --force', 'Overwrite if exists')
|
|
701
|
+
.action(async (name, repoPath, options) => {
|
|
702
|
+
try {
|
|
703
|
+
const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
|
|
704
|
+
const generator = createSkillGenerator({ repoPath });
|
|
705
|
+
const skillPath = await generator.generateCustomSkill({
|
|
706
|
+
name,
|
|
707
|
+
description: options.description || `TODO: Describe when to use ${name}`,
|
|
708
|
+
phases: options.phases,
|
|
709
|
+
force: options.force,
|
|
710
|
+
});
|
|
711
|
+
ui.displaySuccess(`Created skill: ${name}`);
|
|
712
|
+
ui.displayInfo('Path', skillPath);
|
|
713
|
+
}
|
|
714
|
+
catch (error) {
|
|
715
|
+
ui.displayError('Failed to create skill', error);
|
|
716
|
+
process.exit(1);
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
// PREVC Workflow Commands
|
|
720
|
+
const workflowCommand = program
|
|
721
|
+
.command('workflow')
|
|
722
|
+
.description('PREVC workflow management (Planning, Review, Execution, Validation, Confirmation)');
|
|
723
|
+
// Helper to create workflow service dependencies
|
|
724
|
+
const getWorkflowDeps = () => ({
|
|
725
|
+
ui: {
|
|
726
|
+
displaySuccess: (msg) => ui.displaySuccess(msg),
|
|
727
|
+
displayError: (msg, err) => ui.displayError(msg, err),
|
|
728
|
+
displayInfo: (title, detail) => ui.displayInfo(title, detail || '')
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
workflowCommand
|
|
732
|
+
.command('init <name>')
|
|
733
|
+
.description('Initialize a new PREVC workflow')
|
|
734
|
+
.option('-d, --description <text>', 'Project description for scale detection')
|
|
735
|
+
.option('-s, --scale <scale>', 'Project scale: QUICK, SMALL, MEDIUM, LARGE, ENTERPRISE')
|
|
736
|
+
.option('-r, --repo-path <path>', 'Repository path', process.cwd())
|
|
737
|
+
.action(async (name, options) => {
|
|
738
|
+
try {
|
|
739
|
+
const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
|
|
740
|
+
const status = await workflowService.init({
|
|
741
|
+
name,
|
|
742
|
+
description: options.description,
|
|
743
|
+
scale: options.scale
|
|
744
|
+
});
|
|
745
|
+
ui.displaySuccess(`Workflow PREVC initialized: ${name}`);
|
|
746
|
+
ui.displayInfo('Scale', (0, workflow_2.getScaleName)(status.project.scale));
|
|
747
|
+
ui.displayInfo('Current Phase', `${status.project.current_phase} - ${workflow_2.PHASE_NAMES_PT[status.project.current_phase]}`);
|
|
748
|
+
}
|
|
749
|
+
catch (error) {
|
|
750
|
+
ui.displayError('Failed to initialize workflow', error);
|
|
751
|
+
process.exit(1);
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
workflowCommand
|
|
755
|
+
.command('status')
|
|
756
|
+
.description('Show current workflow status')
|
|
757
|
+
.option('-r, --repo-path <path>', 'Repository path', process.cwd())
|
|
758
|
+
.action(async (options) => {
|
|
759
|
+
try {
|
|
760
|
+
const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
|
|
761
|
+
if (!await workflowService.hasWorkflow()) {
|
|
762
|
+
ui.displayError('No workflow found. Run "workflow init <name>" first.');
|
|
763
|
+
process.exit(1);
|
|
764
|
+
}
|
|
765
|
+
const formattedStatus = await workflowService.getFormattedStatus();
|
|
766
|
+
console.log(formattedStatus);
|
|
767
|
+
const actions = await workflowService.getRecommendedActions();
|
|
768
|
+
if (actions.length > 0) {
|
|
769
|
+
console.log('\nRecommended actions:');
|
|
770
|
+
actions.forEach((action, i) => console.log(` ${i + 1}. ${action}`));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
catch (error) {
|
|
774
|
+
ui.displayError('Failed to get workflow status', error);
|
|
775
|
+
process.exit(1);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
workflowCommand
|
|
779
|
+
.command('advance')
|
|
780
|
+
.description('Complete current phase and advance to next')
|
|
781
|
+
.option('-r, --repo-path <path>', 'Repository path', process.cwd())
|
|
782
|
+
.option('-o, --outputs <files...>', 'Output files generated in current phase')
|
|
783
|
+
.action(async (options) => {
|
|
784
|
+
try {
|
|
785
|
+
const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
|
|
786
|
+
if (!await workflowService.hasWorkflow()) {
|
|
787
|
+
ui.displayError('No workflow found. Run "workflow init <name>" first.');
|
|
788
|
+
process.exit(1);
|
|
789
|
+
}
|
|
790
|
+
const nextPhase = await workflowService.advance(options.outputs);
|
|
791
|
+
if (nextPhase) {
|
|
792
|
+
ui.displaySuccess(`Advanced to phase: ${nextPhase} - ${workflow_2.PHASE_NAMES_PT[nextPhase]}`);
|
|
793
|
+
}
|
|
794
|
+
else {
|
|
795
|
+
ui.displaySuccess('Workflow completed!');
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
ui.displayError('Failed to advance workflow', error);
|
|
800
|
+
process.exit(1);
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
workflowCommand
|
|
804
|
+
.command('handoff <from> <to>')
|
|
805
|
+
.description('Perform handoff between roles')
|
|
806
|
+
.option('-r, --repo-path <path>', 'Repository path', process.cwd())
|
|
807
|
+
.option('-a, --artifacts <files...>', 'Artifacts to hand off')
|
|
808
|
+
.action(async (from, to, options) => {
|
|
809
|
+
try {
|
|
810
|
+
const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
|
|
811
|
+
if (!await workflowService.hasWorkflow()) {
|
|
812
|
+
ui.displayError('No workflow found. Run "workflow init <name>" first.');
|
|
813
|
+
process.exit(1);
|
|
814
|
+
}
|
|
815
|
+
await workflowService.handoff(from, to, options.artifacts || []);
|
|
816
|
+
ui.displaySuccess(`Handoff: ${workflow_2.ROLE_DISPLAY_NAMES[from]} → ${workflow_2.ROLE_DISPLAY_NAMES[to]}`);
|
|
817
|
+
}
|
|
818
|
+
catch (error) {
|
|
819
|
+
ui.displayError('Failed to perform handoff', error);
|
|
820
|
+
process.exit(1);
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
workflowCommand
|
|
824
|
+
.command('collaborate <topic>')
|
|
825
|
+
.description('Start a collaboration session between roles')
|
|
826
|
+
.option('-r, --repo-path <path>', 'Repository path', process.cwd())
|
|
827
|
+
.option('-p, --participants <roles...>', 'Participating roles')
|
|
828
|
+
.action(async (topic, options) => {
|
|
829
|
+
try {
|
|
830
|
+
const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
|
|
831
|
+
const session = await workflowService.startCollaboration(topic, options.participants);
|
|
832
|
+
ui.displaySuccess(`Collaboration started: ${topic}`);
|
|
833
|
+
ui.displayInfo('Session ID', session.getId());
|
|
834
|
+
ui.displayInfo('Participants', session.getParticipantNames().join(', '));
|
|
835
|
+
console.log('\nUse MCP tools to contribute and synthesize the collaboration.');
|
|
836
|
+
}
|
|
837
|
+
catch (error) {
|
|
838
|
+
ui.displayError('Failed to start collaboration', error);
|
|
839
|
+
process.exit(1);
|
|
840
|
+
}
|
|
841
|
+
});
|
|
842
|
+
workflowCommand
|
|
843
|
+
.command('role <action> <role>')
|
|
844
|
+
.description('Manage role status (start/complete)')
|
|
845
|
+
.option('-r, --repo-path <path>', 'Repository path', process.cwd())
|
|
846
|
+
.option('-o, --outputs <files...>', 'Output files (for complete action)')
|
|
847
|
+
.action(async (action, role, options) => {
|
|
848
|
+
try {
|
|
849
|
+
const workflowService = new workflow_1.WorkflowService(options.repoPath, getWorkflowDeps());
|
|
850
|
+
if (!await workflowService.hasWorkflow()) {
|
|
851
|
+
ui.displayError('No workflow found. Run "workflow init <name>" first.');
|
|
852
|
+
process.exit(1);
|
|
853
|
+
}
|
|
854
|
+
if (action === 'start') {
|
|
855
|
+
await workflowService.startRole(role);
|
|
856
|
+
ui.displaySuccess(`Started role: ${workflow_2.ROLE_DISPLAY_NAMES[role]}`);
|
|
857
|
+
}
|
|
858
|
+
else if (action === 'complete') {
|
|
859
|
+
await workflowService.completeRole(role, options.outputs || []);
|
|
860
|
+
ui.displaySuccess(`Completed role: ${workflow_2.ROLE_DISPLAY_NAMES[role]}`);
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
ui.displayError(`Unknown action: ${action}. Use 'start' or 'complete'.`);
|
|
864
|
+
process.exit(1);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
catch (error) {
|
|
868
|
+
ui.displayError('Failed to manage role', error);
|
|
869
|
+
process.exit(1);
|
|
870
|
+
}
|
|
871
|
+
});
|
|
365
872
|
async function runInit(repoPath, type, rawOptions) {
|
|
366
873
|
await initService.run(repoPath, type, rawOptions);
|
|
367
874
|
}
|
|
@@ -409,31 +916,63 @@ async function selectLocale(showWelcome) {
|
|
|
409
916
|
translateFn = (0, i18n_1.createTranslator)(normalizedLocale);
|
|
410
917
|
if (showWelcome) {
|
|
411
918
|
ui.displayWelcome(version_1.VERSION);
|
|
919
|
+
ui.displayPrevcExplanation();
|
|
412
920
|
}
|
|
413
921
|
}
|
|
414
922
|
async function runInteractive() {
|
|
415
|
-
await selectLocale(
|
|
923
|
+
await selectLocale(false); // Don't show welcome yet
|
|
924
|
+
// Show welcome screen with PREVC explanation
|
|
925
|
+
ui.displayWelcome(version_1.VERSION);
|
|
926
|
+
ui.displayPrevcExplanation();
|
|
927
|
+
// Wait for user to press Enter
|
|
928
|
+
await inquirer_1.default.prompt([
|
|
929
|
+
{
|
|
930
|
+
type: 'input',
|
|
931
|
+
name: 'continue',
|
|
932
|
+
message: t('prompts.pressEnter'),
|
|
933
|
+
},
|
|
934
|
+
]);
|
|
935
|
+
console.log('\n');
|
|
416
936
|
const projectPath = process.cwd();
|
|
417
937
|
const detector = new state_1.StateDetector({ projectPath });
|
|
418
938
|
const result = await detector.detect();
|
|
419
|
-
//
|
|
939
|
+
// Get quick stats for compact status
|
|
940
|
+
const quickSyncService = new quickSync_1.QuickSyncService({
|
|
941
|
+
ui,
|
|
942
|
+
t,
|
|
943
|
+
version: version_1.VERSION,
|
|
944
|
+
defaultModel: DEFAULT_MODEL,
|
|
945
|
+
});
|
|
946
|
+
const stats = await quickSyncService.getStats(projectPath);
|
|
947
|
+
// Display compact header
|
|
420
948
|
console.log('');
|
|
421
|
-
|
|
422
|
-
|
|
949
|
+
console.log(`${theme_1.colors.primaryBold(`${version_1.PACKAGE_NAME}`)} ${theme_1.colors.secondary(`v${version_1.VERSION}`)}`);
|
|
950
|
+
console.log(`${theme_1.colors.secondary('Project:')} ${projectPath}`);
|
|
951
|
+
// Show compact status line based on state
|
|
423
952
|
switch (result.state) {
|
|
424
953
|
case 'new':
|
|
425
|
-
console.log(theme_1.colors.secondaryDim('
|
|
954
|
+
console.log(theme_1.colors.secondaryDim(t('status.new')));
|
|
426
955
|
break;
|
|
427
956
|
case 'unfilled':
|
|
428
|
-
console.log(theme_1.colors.secondaryDim(
|
|
957
|
+
console.log(theme_1.colors.secondaryDim(t('status.unfilled', { count: result.details.unfilledFiles })));
|
|
429
958
|
break;
|
|
430
959
|
case 'outdated':
|
|
431
|
-
console.log(theme_1.colors.warning(
|
|
960
|
+
console.log(theme_1.colors.warning(t('status.outdated', {
|
|
961
|
+
docs: stats.docs,
|
|
962
|
+
days: result.details.daysBehind || 0,
|
|
963
|
+
agents: stats.agents,
|
|
964
|
+
skills: stats.skills
|
|
965
|
+
})));
|
|
432
966
|
break;
|
|
433
967
|
case 'ready':
|
|
434
|
-
console.log(theme_1.colors.success(
|
|
968
|
+
console.log(theme_1.colors.success(t('status.compact', {
|
|
969
|
+
docs: stats.docs,
|
|
970
|
+
agents: stats.agents,
|
|
971
|
+
skills: stats.skills
|
|
972
|
+
})));
|
|
435
973
|
break;
|
|
436
974
|
}
|
|
975
|
+
console.log('');
|
|
437
976
|
// Handle state-based flow
|
|
438
977
|
if (result.state === 'new') {
|
|
439
978
|
const { action } = await inquirer_1.default.prompt([
|
|
@@ -442,15 +981,20 @@ async function runInteractive() {
|
|
|
442
981
|
name: 'action',
|
|
443
982
|
message: t('prompts.main.action'),
|
|
444
983
|
choices: [
|
|
445
|
-
{ name: t('prompts.main.choice.
|
|
984
|
+
{ name: t('prompts.main.choice.quickSetup'), value: 'create' },
|
|
985
|
+
{ name: t('prompts.main.choice.scaffoldOnly'), value: 'scaffold' },
|
|
446
986
|
{ name: t('prompts.main.choice.exit'), value: 'exit' }
|
|
447
987
|
]
|
|
448
988
|
}
|
|
449
989
|
]);
|
|
450
990
|
if (action === 'create') {
|
|
451
|
-
// Run init + fill automatically
|
|
991
|
+
// Run init + fill with AI + LSP automatically
|
|
452
992
|
await runQuickSetup(projectPath);
|
|
453
993
|
}
|
|
994
|
+
else if (action === 'scaffold') {
|
|
995
|
+
// Scaffold only without AI fill
|
|
996
|
+
await runInteractiveScaffold();
|
|
997
|
+
}
|
|
454
998
|
return;
|
|
455
999
|
}
|
|
456
1000
|
if (result.state === 'unfilled') {
|
|
@@ -479,6 +1023,27 @@ async function runInteractive() {
|
|
|
479
1023
|
await runFullMenu(result.state === 'outdated' ? result.details.daysBehind : undefined);
|
|
480
1024
|
}
|
|
481
1025
|
async function runQuickSetup(projectPath) {
|
|
1026
|
+
// AI-first: Detect smart defaults automatically
|
|
1027
|
+
const defaults = await (0, prompts_1.detectSmartDefaults)();
|
|
1028
|
+
// If no API key found, prompt for one
|
|
1029
|
+
let llmConfig = null;
|
|
1030
|
+
if (defaults.apiKeyConfigured && defaults.provider) {
|
|
1031
|
+
// Auto-detected config
|
|
1032
|
+
llmConfig = {
|
|
1033
|
+
provider: defaults.provider,
|
|
1034
|
+
model: DEFAULT_MODEL,
|
|
1035
|
+
apiKey: (0, providerFactory_1.getApiKeyFromEnv)(defaults.provider),
|
|
1036
|
+
};
|
|
1037
|
+
console.log(theme_1.colors.secondary(` Auto-detected: ${defaults.provider} API key found`));
|
|
1038
|
+
}
|
|
1039
|
+
else {
|
|
1040
|
+
// Need to get API key from user
|
|
1041
|
+
llmConfig = await (0, prompts_1.promptLLMConfig)(t);
|
|
1042
|
+
if (!llmConfig) {
|
|
1043
|
+
ui.displayInfo(t('info.setup.incomplete.title'), t('info.setup.incomplete.detail'));
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
482
1047
|
const { confirm } = await inquirer_1.default.prompt([
|
|
483
1048
|
{
|
|
484
1049
|
type: 'confirm',
|
|
@@ -490,11 +1055,11 @@ async function runQuickSetup(projectPath) {
|
|
|
490
1055
|
if (!confirm) {
|
|
491
1056
|
return;
|
|
492
1057
|
}
|
|
493
|
-
// Run init
|
|
1058
|
+
// Run init with semantic analysis
|
|
494
1059
|
ui.startSpinner(t('spinner.setup.creatingStructure'));
|
|
495
1060
|
try {
|
|
496
|
-
const
|
|
497
|
-
await
|
|
1061
|
+
const localInitService = new initService_1.InitService({ ui, t, version: version_1.VERSION });
|
|
1062
|
+
await localInitService.run(projectPath, 'both', {
|
|
498
1063
|
semantic: true
|
|
499
1064
|
});
|
|
500
1065
|
ui.stopSpinner();
|
|
@@ -504,22 +1069,27 @@ async function runQuickSetup(projectPath) {
|
|
|
504
1069
|
ui.displayError('Failed to create structure', error);
|
|
505
1070
|
return;
|
|
506
1071
|
}
|
|
507
|
-
//
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
1072
|
+
// Initialize skills too (AI-first)
|
|
1073
|
+
try {
|
|
1074
|
+
const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
|
|
1075
|
+
const skillGenerator = createSkillGenerator({ repoPath: projectPath });
|
|
1076
|
+
await skillGenerator.generate({});
|
|
512
1077
|
}
|
|
1078
|
+
catch {
|
|
1079
|
+
// Skills init failure is not critical
|
|
1080
|
+
}
|
|
1081
|
+
// Fill with AI + LSP (default behavior)
|
|
513
1082
|
ui.startSpinner(t('spinner.setup.fillingDocs'));
|
|
514
1083
|
try {
|
|
515
|
-
const
|
|
516
|
-
await
|
|
1084
|
+
const localFillService = new fillService_1.FillService({ ui, t, version: version_1.VERSION, defaultModel: DEFAULT_MODEL });
|
|
1085
|
+
await localFillService.run(projectPath, {
|
|
517
1086
|
model: llmConfig.model,
|
|
518
1087
|
provider: llmConfig.provider,
|
|
519
1088
|
apiKey: llmConfig.apiKey,
|
|
520
1089
|
baseUrl: llmConfig.baseUrl,
|
|
521
1090
|
verbose: false,
|
|
522
|
-
semantic: true
|
|
1091
|
+
semantic: true,
|
|
1092
|
+
useLsp: true // LSP enabled by default
|
|
523
1093
|
});
|
|
524
1094
|
ui.stopSpinner();
|
|
525
1095
|
ui.displaySuccess(t('success.setup.docsCreated'));
|
|
@@ -536,12 +1106,21 @@ async function runFullMenu(daysBehind) {
|
|
|
536
1106
|
const updateLabel = daysBehind
|
|
537
1107
|
? t('prompts.main.choice.updateDocsBehind', { daysBehind })
|
|
538
1108
|
: t('prompts.main.choice.updateDocs');
|
|
1109
|
+
// New menu structure with separators - organized by frequency of use
|
|
539
1110
|
const choices = [
|
|
540
|
-
|
|
1111
|
+
// Quick Actions (most used)
|
|
1112
|
+
{ name: t('prompts.main.choice.quickSync'), value: 'quickSync' },
|
|
1113
|
+
{ name: t('prompts.main.choice.startWorkflow'), value: 'workflow' },
|
|
1114
|
+
{ name: t('prompts.main.choice.createPlan'), value: 'plan' },
|
|
1115
|
+
new inquirer_1.default.Separator(),
|
|
1116
|
+
// Manage
|
|
541
1117
|
{ name: updateLabel, value: 'fill' },
|
|
542
|
-
{ name: t('prompts.main.choice.
|
|
1118
|
+
{ name: t('prompts.main.choice.manageSkills'), value: 'skills' },
|
|
1119
|
+
{ name: t('prompts.main.choice.manageAgents'), value: 'agents' },
|
|
1120
|
+
new inquirer_1.default.Separator(),
|
|
1121
|
+
// Config
|
|
543
1122
|
{ name: t('prompts.main.choice.rescaffold'), value: 'scaffold' },
|
|
544
|
-
{ name: t('prompts.main.choice.
|
|
1123
|
+
{ name: t('prompts.main.choice.settings'), value: 'settings' },
|
|
545
1124
|
{ name: t('prompts.main.choice.exit'), value: 'exit' }
|
|
546
1125
|
];
|
|
547
1126
|
const { action } = await inquirer_1.default.prompt([
|
|
@@ -552,15 +1131,18 @@ async function runFullMenu(daysBehind) {
|
|
|
552
1131
|
choices
|
|
553
1132
|
}
|
|
554
1133
|
]);
|
|
555
|
-
if (action === '
|
|
556
|
-
await
|
|
1134
|
+
if (action === 'settings') {
|
|
1135
|
+
await runSettings();
|
|
557
1136
|
continue;
|
|
558
1137
|
}
|
|
559
1138
|
if (action === 'exit') {
|
|
560
1139
|
exitRequested = true;
|
|
561
1140
|
break;
|
|
562
1141
|
}
|
|
563
|
-
if (action === '
|
|
1142
|
+
if (action === 'quickSync') {
|
|
1143
|
+
await runQuickSync();
|
|
1144
|
+
}
|
|
1145
|
+
else if (action === 'scaffold') {
|
|
564
1146
|
await runInteractiveScaffold();
|
|
565
1147
|
}
|
|
566
1148
|
else if (action === 'fill') {
|
|
@@ -569,8 +1151,14 @@ async function runFullMenu(daysBehind) {
|
|
|
569
1151
|
else if (action === 'plan') {
|
|
570
1152
|
await runInteractivePlan();
|
|
571
1153
|
}
|
|
572
|
-
else if (action === '
|
|
573
|
-
await
|
|
1154
|
+
else if (action === 'agents') {
|
|
1155
|
+
await runManageAgents();
|
|
1156
|
+
}
|
|
1157
|
+
else if (action === 'workflow') {
|
|
1158
|
+
await runInteractiveWorkflow();
|
|
1159
|
+
}
|
|
1160
|
+
else if (action === 'skills') {
|
|
1161
|
+
await runInteractiveSkills();
|
|
574
1162
|
}
|
|
575
1163
|
ui.displayInfo(t('info.interactive.returning.title'), t('info.interactive.returning.detail'));
|
|
576
1164
|
}
|
|
@@ -595,19 +1183,24 @@ async function runInteractiveScaffold() {
|
|
|
595
1183
|
default: defaultOutput
|
|
596
1184
|
}
|
|
597
1185
|
]);
|
|
598
|
-
|
|
1186
|
+
// Multi-select checkbox for scaffold components
|
|
1187
|
+
const { scaffoldComponents } = await inquirer_1.default.prompt([
|
|
599
1188
|
{
|
|
600
|
-
type: '
|
|
601
|
-
name: '
|
|
602
|
-
message: t('prompts.scaffold.
|
|
1189
|
+
type: 'checkbox',
|
|
1190
|
+
name: 'scaffoldComponents',
|
|
1191
|
+
message: t('prompts.scaffold.selectComponents'),
|
|
603
1192
|
choices: [
|
|
604
|
-
{ name: t('prompts.scaffold.
|
|
605
|
-
{ name: t('prompts.scaffold.
|
|
606
|
-
{ name: t('prompts.scaffold.
|
|
607
|
-
]
|
|
608
|
-
default: 'both'
|
|
1193
|
+
{ name: t('prompts.scaffold.componentDocs'), value: 'docs', checked: true },
|
|
1194
|
+
{ name: t('prompts.scaffold.componentAgents'), value: 'agents', checked: true },
|
|
1195
|
+
{ name: t('prompts.scaffold.componentSkills'), value: 'skills', checked: false }
|
|
1196
|
+
]
|
|
609
1197
|
}
|
|
610
1198
|
]);
|
|
1199
|
+
// Validate: at least one component must be selected
|
|
1200
|
+
if (scaffoldComponents.length === 0) {
|
|
1201
|
+
ui.displayWarning(t('warnings.scaffold.noneSelected'));
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
611
1204
|
const { verbose } = await inquirer_1.default.prompt([
|
|
612
1205
|
{
|
|
613
1206
|
type: 'confirm',
|
|
@@ -616,11 +1209,58 @@ async function runInteractiveScaffold() {
|
|
|
616
1209
|
default: false
|
|
617
1210
|
}
|
|
618
1211
|
]);
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
1212
|
+
// Determine what to scaffold
|
|
1213
|
+
const scaffoldDocs = scaffoldComponents.includes('docs');
|
|
1214
|
+
const scaffoldAgents = scaffoldComponents.includes('agents');
|
|
1215
|
+
const scaffoldSkills = scaffoldComponents.includes('skills');
|
|
1216
|
+
// Scaffold docs and/or agents if selected
|
|
1217
|
+
if (scaffoldDocs || scaffoldAgents) {
|
|
1218
|
+
let scaffoldType;
|
|
1219
|
+
if (scaffoldDocs && scaffoldAgents) {
|
|
1220
|
+
scaffoldType = 'both';
|
|
1221
|
+
}
|
|
1222
|
+
else if (scaffoldDocs) {
|
|
1223
|
+
scaffoldType = 'docs';
|
|
1224
|
+
}
|
|
1225
|
+
else {
|
|
1226
|
+
scaffoldType = 'agents';
|
|
1227
|
+
}
|
|
1228
|
+
await runInit(resolvedRepo, scaffoldType, {
|
|
1229
|
+
output: outputDir,
|
|
1230
|
+
verbose,
|
|
1231
|
+
semantic: true
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
// Scaffold skills if selected
|
|
1235
|
+
if (scaffoldSkills) {
|
|
1236
|
+
try {
|
|
1237
|
+
const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
|
|
1238
|
+
const generator = createSkillGenerator({
|
|
1239
|
+
repoPath: resolvedRepo,
|
|
1240
|
+
outputDir
|
|
1241
|
+
});
|
|
1242
|
+
// Display step for skills scaffolding
|
|
1243
|
+
const stepNumber = (scaffoldDocs || scaffoldAgents) ? 4 : 1;
|
|
1244
|
+
const totalSteps = (scaffoldDocs || scaffoldAgents) ? 4 : 1;
|
|
1245
|
+
ui.displayStep(stepNumber, totalSteps, t('steps.init.skills'));
|
|
1246
|
+
ui.startSpinner(t('spinner.skills.creating'));
|
|
1247
|
+
const result = await generator.generate({});
|
|
1248
|
+
ui.updateSpinner(t('spinner.skills.created', { count: result.generatedSkills.length }), 'success');
|
|
1249
|
+
// If only skills were selected, show success message
|
|
1250
|
+
if (!scaffoldDocs && !scaffoldAgents) {
|
|
1251
|
+
ui.displaySuccess(t('success.skill.initialized', { path: result.skillsDir }));
|
|
1252
|
+
}
|
|
1253
|
+
if (result.generatedSkills.length > 0) {
|
|
1254
|
+
ui.displayInfo(t('info.skill.generated'), result.generatedSkills.join(', '));
|
|
1255
|
+
}
|
|
1256
|
+
if (result.skippedSkills.length > 0) {
|
|
1257
|
+
ui.displayInfo(t('info.skill.skipped'), result.skippedSkills.join(', '));
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
catch (error) {
|
|
1261
|
+
ui.displayError(t('errors.skill.initFailed'), error);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
624
1264
|
}
|
|
625
1265
|
async function runInteractiveLlmFill() {
|
|
626
1266
|
const defaults = await (0, prompts_1.detectSmartDefaults)();
|
|
@@ -1040,6 +1680,638 @@ async function runInteractiveSync() {
|
|
|
1040
1680
|
}
|
|
1041
1681
|
}
|
|
1042
1682
|
}
|
|
1683
|
+
async function createNewWorkflow(workflowService) {
|
|
1684
|
+
const { name, description, scale } = await inquirer_1.default.prompt([
|
|
1685
|
+
{
|
|
1686
|
+
type: 'input',
|
|
1687
|
+
name: 'name',
|
|
1688
|
+
message: t('prompts.workflow.projectName'),
|
|
1689
|
+
validate: (input) => input.trim().length > 0 || t('prompts.workflow.projectNameRequired')
|
|
1690
|
+
},
|
|
1691
|
+
{
|
|
1692
|
+
type: 'input',
|
|
1693
|
+
name: 'description',
|
|
1694
|
+
message: t('prompts.workflow.description'),
|
|
1695
|
+
default: ''
|
|
1696
|
+
},
|
|
1697
|
+
{
|
|
1698
|
+
type: 'list',
|
|
1699
|
+
name: 'scale',
|
|
1700
|
+
message: t('prompts.workflow.scale'),
|
|
1701
|
+
choices: [
|
|
1702
|
+
{ name: t('prompts.workflow.scale.auto'), value: '' },
|
|
1703
|
+
{ name: t('prompts.workflow.scale.quick'), value: 'QUICK' },
|
|
1704
|
+
{ name: t('prompts.workflow.scale.small'), value: 'SMALL' },
|
|
1705
|
+
{ name: t('prompts.workflow.scale.medium'), value: 'MEDIUM' },
|
|
1706
|
+
{ name: t('prompts.workflow.scale.large'), value: 'LARGE' },
|
|
1707
|
+
{ name: t('prompts.workflow.scale.enterprise'), value: 'ENTERPRISE' }
|
|
1708
|
+
],
|
|
1709
|
+
default: ''
|
|
1710
|
+
}
|
|
1711
|
+
]);
|
|
1712
|
+
try {
|
|
1713
|
+
const status = await workflowService.init({
|
|
1714
|
+
name: name.trim(),
|
|
1715
|
+
description: description.trim() || undefined,
|
|
1716
|
+
scale: scale || undefined
|
|
1717
|
+
});
|
|
1718
|
+
ui.displaySuccess(t('success.workflow.initialized', { name }));
|
|
1719
|
+
ui.displayInfo(t('info.workflow.scale'), (0, workflow_2.getScaleName)(status.project.scale));
|
|
1720
|
+
ui.displayInfo(t('info.workflow.currentPhase'), `${status.project.current_phase} - ${workflow_2.PHASE_NAMES_PT[status.project.current_phase]}`);
|
|
1721
|
+
return true;
|
|
1722
|
+
}
|
|
1723
|
+
catch (error) {
|
|
1724
|
+
ui.displayError(t('errors.workflow.initFailed'), error);
|
|
1725
|
+
return false;
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
async function runInteractiveWorkflow() {
|
|
1729
|
+
const projectPath = process.cwd();
|
|
1730
|
+
const workflowService = new workflow_1.WorkflowService(projectPath, getWorkflowDeps());
|
|
1731
|
+
const hasWorkflow = await workflowService.hasWorkflow();
|
|
1732
|
+
if (!hasWorkflow) {
|
|
1733
|
+
// No workflow exists - offer to create one
|
|
1734
|
+
const { createNew } = await inquirer_1.default.prompt([
|
|
1735
|
+
{
|
|
1736
|
+
type: 'confirm',
|
|
1737
|
+
name: 'createNew',
|
|
1738
|
+
message: t('prompts.workflow.noWorkflowFound'),
|
|
1739
|
+
default: true
|
|
1740
|
+
}
|
|
1741
|
+
]);
|
|
1742
|
+
if (!createNew) {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
await createNewWorkflow(workflowService);
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
// Workflow exists - check if complete
|
|
1749
|
+
const isComplete = await workflowService.isComplete();
|
|
1750
|
+
if (isComplete) {
|
|
1751
|
+
// Workflow is complete - offer to start a new one or view status
|
|
1752
|
+
console.log('');
|
|
1753
|
+
const formattedStatus = await workflowService.getFormattedStatus();
|
|
1754
|
+
console.log(formattedStatus);
|
|
1755
|
+
const { completeAction } = await inquirer_1.default.prompt([
|
|
1756
|
+
{
|
|
1757
|
+
type: 'list',
|
|
1758
|
+
name: 'completeAction',
|
|
1759
|
+
message: t('prompts.workflow.workflowComplete'),
|
|
1760
|
+
choices: [
|
|
1761
|
+
{ name: t('prompts.workflow.action.newWorkflow'), value: 'newWorkflow' },
|
|
1762
|
+
{ name: t('prompts.workflow.action.viewStatus'), value: 'viewStatus' },
|
|
1763
|
+
{ name: t('prompts.workflow.action.back'), value: 'back' }
|
|
1764
|
+
]
|
|
1765
|
+
}
|
|
1766
|
+
]);
|
|
1767
|
+
if (completeAction === 'newWorkflow') {
|
|
1768
|
+
const { confirmNew } = await inquirer_1.default.prompt([
|
|
1769
|
+
{
|
|
1770
|
+
type: 'confirm',
|
|
1771
|
+
name: 'confirmNew',
|
|
1772
|
+
message: t('prompts.workflow.confirmNewWorkflow'),
|
|
1773
|
+
default: true
|
|
1774
|
+
}
|
|
1775
|
+
]);
|
|
1776
|
+
if (confirmNew) {
|
|
1777
|
+
await createNewWorkflow(workflowService);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
// 'viewStatus' and 'back' just return
|
|
1781
|
+
return;
|
|
1782
|
+
}
|
|
1783
|
+
// Workflow exists and is not complete - show status and actions
|
|
1784
|
+
let continueMenu = true;
|
|
1785
|
+
while (continueMenu) {
|
|
1786
|
+
console.log('');
|
|
1787
|
+
const formattedStatus = await workflowService.getFormattedStatus();
|
|
1788
|
+
console.log(formattedStatus);
|
|
1789
|
+
const choices = [];
|
|
1790
|
+
choices.push({ name: t('prompts.workflow.action.advance'), value: 'advance' });
|
|
1791
|
+
choices.push({ name: t('prompts.workflow.action.newWorkflow'), value: 'newWorkflow' });
|
|
1792
|
+
choices.push({ name: t('prompts.workflow.action.refresh'), value: 'status' });
|
|
1793
|
+
choices.push({ name: t('prompts.workflow.action.back'), value: 'back' });
|
|
1794
|
+
const { action } = await inquirer_1.default.prompt([
|
|
1795
|
+
{
|
|
1796
|
+
type: 'list',
|
|
1797
|
+
name: 'action',
|
|
1798
|
+
message: t('prompts.workflow.action'),
|
|
1799
|
+
choices
|
|
1800
|
+
}
|
|
1801
|
+
]);
|
|
1802
|
+
if (action === 'back') {
|
|
1803
|
+
continueMenu = false;
|
|
1804
|
+
}
|
|
1805
|
+
else if (action === 'newWorkflow') {
|
|
1806
|
+
const { confirmNew } = await inquirer_1.default.prompt([
|
|
1807
|
+
{
|
|
1808
|
+
type: 'confirm',
|
|
1809
|
+
name: 'confirmNew',
|
|
1810
|
+
message: t('prompts.workflow.confirmNewWorkflow'),
|
|
1811
|
+
default: false
|
|
1812
|
+
}
|
|
1813
|
+
]);
|
|
1814
|
+
if (confirmNew) {
|
|
1815
|
+
const created = await createNewWorkflow(workflowService);
|
|
1816
|
+
if (created) {
|
|
1817
|
+
// Continue with the new workflow
|
|
1818
|
+
continue;
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
else if (action === 'advance') {
|
|
1823
|
+
try {
|
|
1824
|
+
const nextPhase = await workflowService.advance();
|
|
1825
|
+
if (nextPhase) {
|
|
1826
|
+
ui.displaySuccess(t('success.workflow.advanced', { phase: nextPhase, phaseName: workflow_2.PHASE_NAMES_PT[nextPhase] }));
|
|
1827
|
+
}
|
|
1828
|
+
else {
|
|
1829
|
+
ui.displaySuccess(t('success.workflow.completed'));
|
|
1830
|
+
// Workflow completed - ask if they want to start a new one
|
|
1831
|
+
const { startNew } = await inquirer_1.default.prompt([
|
|
1832
|
+
{
|
|
1833
|
+
type: 'confirm',
|
|
1834
|
+
name: 'startNew',
|
|
1835
|
+
message: t('prompts.workflow.noWorkflowFound'),
|
|
1836
|
+
default: true
|
|
1837
|
+
}
|
|
1838
|
+
]);
|
|
1839
|
+
if (startNew) {
|
|
1840
|
+
await createNewWorkflow(workflowService);
|
|
1841
|
+
}
|
|
1842
|
+
continueMenu = false;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
catch (error) {
|
|
1846
|
+
ui.displayError(t('errors.workflow.advanceFailed'), error);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
// 'status' just loops and refreshes
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
async function runInteractiveSkills() {
|
|
1853
|
+
const projectPath = process.cwd();
|
|
1854
|
+
let continueMenu = true;
|
|
1855
|
+
while (continueMenu) {
|
|
1856
|
+
const { action } = await inquirer_1.default.prompt([
|
|
1857
|
+
{
|
|
1858
|
+
type: 'list',
|
|
1859
|
+
name: 'action',
|
|
1860
|
+
message: t('prompts.skill.action'),
|
|
1861
|
+
choices: [
|
|
1862
|
+
{ name: t('prompts.skill.action.init'), value: 'init' },
|
|
1863
|
+
{ name: t('prompts.skill.action.list'), value: 'list' },
|
|
1864
|
+
{ name: t('prompts.skill.action.export'), value: 'export' },
|
|
1865
|
+
{ name: t('prompts.skill.action.create'), value: 'create' },
|
|
1866
|
+
{ name: t('prompts.skill.action.back'), value: 'back' }
|
|
1867
|
+
]
|
|
1868
|
+
}
|
|
1869
|
+
]);
|
|
1870
|
+
if (action === 'back') {
|
|
1871
|
+
continueMenu = false;
|
|
1872
|
+
break;
|
|
1873
|
+
}
|
|
1874
|
+
if (action === 'init') {
|
|
1875
|
+
try {
|
|
1876
|
+
const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
|
|
1877
|
+
const generator = createSkillGenerator({ repoPath: projectPath });
|
|
1878
|
+
const result = await generator.generate({});
|
|
1879
|
+
ui.displaySuccess(t('success.skill.initialized', { path: result.skillsDir }));
|
|
1880
|
+
ui.displayInfo(t('info.skill.generated'), result.generatedSkills.join(', ') || 'none');
|
|
1881
|
+
if (result.skippedSkills.length > 0) {
|
|
1882
|
+
ui.displayInfo(t('info.skill.skipped'), result.skippedSkills.join(', '));
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
catch (error) {
|
|
1886
|
+
ui.displayError(t('errors.skill.initFailed'), error);
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
else if (action === 'list') {
|
|
1890
|
+
try {
|
|
1891
|
+
const { createSkillRegistry, BUILT_IN_SKILLS } = await Promise.resolve().then(() => __importStar(require('./workflow/skills')));
|
|
1892
|
+
const registry = createSkillRegistry(projectPath);
|
|
1893
|
+
const discovered = await registry.discoverAll();
|
|
1894
|
+
console.log('\nBuilt-in Skills:');
|
|
1895
|
+
for (const skill of discovered.builtIn) {
|
|
1896
|
+
const scaffolded = discovered.all.find(s => s.slug === skill.slug && s.path.includes('.context'));
|
|
1897
|
+
const status = scaffolded ? '[scaffolded]' : '[available]';
|
|
1898
|
+
console.log(` ${skill.slug} ${status}`);
|
|
1899
|
+
console.log(` ${skill.metadata.description}`);
|
|
1900
|
+
}
|
|
1901
|
+
if (discovered.custom.length > 0) {
|
|
1902
|
+
console.log('\nCustom Skills:');
|
|
1903
|
+
for (const skill of discovered.custom) {
|
|
1904
|
+
console.log(` ${skill.slug}`);
|
|
1905
|
+
console.log(` ${skill.metadata.description}`);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
console.log(`\nTotal: ${discovered.all.length} skills (${discovered.builtIn.length} built-in, ${discovered.custom.length} custom)\n`);
|
|
1909
|
+
}
|
|
1910
|
+
catch (error) {
|
|
1911
|
+
ui.displayError(t('errors.skill.listFailed'), error);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
else if (action === 'export') {
|
|
1915
|
+
try {
|
|
1916
|
+
const { preset } = await inquirer_1.default.prompt([
|
|
1917
|
+
{
|
|
1918
|
+
type: 'list',
|
|
1919
|
+
name: 'preset',
|
|
1920
|
+
message: t('prompts.skill.exportPreset'),
|
|
1921
|
+
choices: [
|
|
1922
|
+
{ name: t('prompts.skill.exportPreset.all'), value: 'all' },
|
|
1923
|
+
{ name: t('prompts.skill.exportPreset.claude'), value: 'claude' },
|
|
1924
|
+
{ name: t('prompts.skill.exportPreset.gemini'), value: 'gemini' },
|
|
1925
|
+
{ name: t('prompts.skill.exportPreset.codex'), value: 'codex' }
|
|
1926
|
+
],
|
|
1927
|
+
default: 'all'
|
|
1928
|
+
}
|
|
1929
|
+
]);
|
|
1930
|
+
const { SkillExportService } = await Promise.resolve().then(() => __importStar(require('./services/export/skillExportService')));
|
|
1931
|
+
const exportService = new SkillExportService({
|
|
1932
|
+
ui,
|
|
1933
|
+
t,
|
|
1934
|
+
version: version_1.VERSION,
|
|
1935
|
+
});
|
|
1936
|
+
const result = await exportService.run(projectPath, {
|
|
1937
|
+
preset,
|
|
1938
|
+
includeBuiltIn: true,
|
|
1939
|
+
});
|
|
1940
|
+
ui.displaySuccess(t('success.skill.exported', {
|
|
1941
|
+
count: String(result.skillsExported.length),
|
|
1942
|
+
targets: String(result.targets.length)
|
|
1943
|
+
}));
|
|
1944
|
+
}
|
|
1945
|
+
catch (error) {
|
|
1946
|
+
ui.displayError(t('errors.skill.exportFailed'), error);
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
else if (action === 'create') {
|
|
1950
|
+
try {
|
|
1951
|
+
const { name, description, phases } = await inquirer_1.default.prompt([
|
|
1952
|
+
{
|
|
1953
|
+
type: 'input',
|
|
1954
|
+
name: 'name',
|
|
1955
|
+
message: t('prompts.skill.name'),
|
|
1956
|
+
validate: (input) => input.trim().length > 0 || 'Name is required'
|
|
1957
|
+
},
|
|
1958
|
+
{
|
|
1959
|
+
type: 'input',
|
|
1960
|
+
name: 'description',
|
|
1961
|
+
message: t('prompts.skill.description'),
|
|
1962
|
+
default: ''
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
type: 'input',
|
|
1966
|
+
name: 'phases',
|
|
1967
|
+
message: t('prompts.skill.phases'),
|
|
1968
|
+
default: 'E,V' // Default to Execution + Validation
|
|
1969
|
+
}
|
|
1970
|
+
]);
|
|
1971
|
+
const phaseArray = phases.split(',').map(p => p.trim().toUpperCase()).filter(p => ['P', 'R', 'E', 'V', 'C'].includes(p));
|
|
1972
|
+
ui.startSpinner('Creating skill...');
|
|
1973
|
+
const { createSkillGenerator } = await Promise.resolve().then(() => __importStar(require('./generators/skills')));
|
|
1974
|
+
const generator = createSkillGenerator({ repoPath: projectPath });
|
|
1975
|
+
const skillPath = await generator.generateCustomSkill({
|
|
1976
|
+
name: name.trim(),
|
|
1977
|
+
description: description.trim() || `TODO: Describe when to use ${name}`,
|
|
1978
|
+
phases: phaseArray,
|
|
1979
|
+
});
|
|
1980
|
+
// AI-first: Try to fill skill with AI + LSP
|
|
1981
|
+
const defaults = await (0, prompts_1.detectSmartDefaults)();
|
|
1982
|
+
if (defaults.apiKeyConfigured && defaults.provider) {
|
|
1983
|
+
ui.updateSpinner('Enhancing skill with AI...', 'info');
|
|
1984
|
+
try {
|
|
1985
|
+
const { SkillFillService } = await Promise.resolve().then(() => __importStar(require('./services/fill/skillFillService')));
|
|
1986
|
+
const skillFillService = new SkillFillService({ ui, t, version: version_1.VERSION, defaultModel: DEFAULT_MODEL });
|
|
1987
|
+
await skillFillService.run(projectPath, {
|
|
1988
|
+
provider: defaults.provider,
|
|
1989
|
+
model: DEFAULT_MODEL,
|
|
1990
|
+
apiKey: (0, providerFactory_1.getApiKeyFromEnv)(defaults.provider),
|
|
1991
|
+
skills: [name.trim()],
|
|
1992
|
+
semantic: true,
|
|
1993
|
+
useLsp: true,
|
|
1994
|
+
});
|
|
1995
|
+
}
|
|
1996
|
+
catch {
|
|
1997
|
+
// Fill failure is not critical - template is already created
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
ui.updateSpinner('Skill created', 'success');
|
|
2001
|
+
ui.stopSpinner();
|
|
2002
|
+
ui.displaySuccess(t('success.skill.created', { name }));
|
|
2003
|
+
ui.displayInfo(t('info.skill.path'), skillPath);
|
|
2004
|
+
}
|
|
2005
|
+
catch (error) {
|
|
2006
|
+
ui.stopSpinner();
|
|
2007
|
+
ui.displayError(t('errors.skill.createFailed'), error);
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
// ============================================================================
|
|
2013
|
+
// Quick Sync - Unified sync for agents, skills, and docs
|
|
2014
|
+
// ============================================================================
|
|
2015
|
+
async function runQuickSync() {
|
|
2016
|
+
const projectPath = process.cwd();
|
|
2017
|
+
// Step 1: Select components to sync
|
|
2018
|
+
const { components } = await inquirer_1.default.prompt([
|
|
2019
|
+
{
|
|
2020
|
+
type: 'checkbox',
|
|
2021
|
+
name: 'components',
|
|
2022
|
+
message: t('prompts.quickSync.selectComponents'),
|
|
2023
|
+
choices: [
|
|
2024
|
+
{ name: t('prompts.quickSync.components.agents'), value: 'agents', checked: true },
|
|
2025
|
+
{ name: t('prompts.quickSync.components.skills'), value: 'skills', checked: true },
|
|
2026
|
+
{ name: t('prompts.quickSync.components.docs'), value: 'docs', checked: true },
|
|
2027
|
+
],
|
|
2028
|
+
},
|
|
2029
|
+
]);
|
|
2030
|
+
if (components.length === 0) {
|
|
2031
|
+
ui.displayWarning(t('prompts.quickSync.noComponentsSelected'));
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
let agentTargets;
|
|
2035
|
+
let skillTargets;
|
|
2036
|
+
let docTargets;
|
|
2037
|
+
// Step 2: If agents selected, choose targets
|
|
2038
|
+
if (components.includes('agents')) {
|
|
2039
|
+
const { targets } = await inquirer_1.default.prompt([
|
|
2040
|
+
{
|
|
2041
|
+
type: 'checkbox',
|
|
2042
|
+
name: 'targets',
|
|
2043
|
+
message: t('prompts.quickSync.selectAgentTargets'),
|
|
2044
|
+
choices: [
|
|
2045
|
+
{ name: '.claude/agents (Claude Code)', value: 'claude', checked: true },
|
|
2046
|
+
{ name: '.github/agents (GitHub Copilot)', value: 'github', checked: true },
|
|
2047
|
+
{ name: '.cursor/agents (Cursor AI)', value: 'cursor', checked: false },
|
|
2048
|
+
{ name: '.windsurf/agents (Windsurf/Codeium)', value: 'windsurf', checked: false },
|
|
2049
|
+
{ name: '.cline/agents (Cline)', value: 'cline', checked: false },
|
|
2050
|
+
{ name: '.continue/agents (Continue.dev)', value: 'continue', checked: false },
|
|
2051
|
+
],
|
|
2052
|
+
},
|
|
2053
|
+
]);
|
|
2054
|
+
agentTargets = targets.length > 0 ? targets : undefined;
|
|
2055
|
+
}
|
|
2056
|
+
// Step 3: If skills selected, choose targets
|
|
2057
|
+
if (components.includes('skills')) {
|
|
2058
|
+
const { targets } = await inquirer_1.default.prompt([
|
|
2059
|
+
{
|
|
2060
|
+
type: 'checkbox',
|
|
2061
|
+
name: 'targets',
|
|
2062
|
+
message: t('prompts.quickSync.selectSkillTargets'),
|
|
2063
|
+
choices: [
|
|
2064
|
+
{ name: '.claude/skills (Claude Code)', value: 'claude', checked: true },
|
|
2065
|
+
{ name: '.gemini/skills (Gemini CLI)', value: 'gemini', checked: true },
|
|
2066
|
+
{ name: '.codex/skills (Codex CLI)', value: 'codex', checked: true },
|
|
2067
|
+
],
|
|
2068
|
+
},
|
|
2069
|
+
]);
|
|
2070
|
+
skillTargets = targets.length > 0 ? targets : undefined;
|
|
2071
|
+
}
|
|
2072
|
+
// Step 4: If docs selected, choose targets
|
|
2073
|
+
if (components.includes('docs')) {
|
|
2074
|
+
const { targets } = await inquirer_1.default.prompt([
|
|
2075
|
+
{
|
|
2076
|
+
type: 'checkbox',
|
|
2077
|
+
name: 'targets',
|
|
2078
|
+
message: t('prompts.quickSync.selectDocTargets'),
|
|
2079
|
+
choices: [
|
|
2080
|
+
{ name: '.cursorrules (Cursor AI)', value: 'cursor', checked: true },
|
|
2081
|
+
{ name: 'CLAUDE.md (Claude Code)', value: 'claude', checked: true },
|
|
2082
|
+
{ name: 'AGENTS.md (Universal)', value: 'agents', checked: true },
|
|
2083
|
+
{ name: '.windsurfrules (Windsurf)', value: 'windsurf', checked: false },
|
|
2084
|
+
{ name: '.clinerules (Cline)', value: 'cline', checked: false },
|
|
2085
|
+
{ name: 'CONVENTIONS.md (Aider)', value: 'aider', checked: false },
|
|
2086
|
+
],
|
|
2087
|
+
},
|
|
2088
|
+
]);
|
|
2089
|
+
docTargets = targets.length > 0 ? targets : undefined;
|
|
2090
|
+
}
|
|
2091
|
+
// Build options based on selections
|
|
2092
|
+
const options = {
|
|
2093
|
+
skipAgents: !components.includes('agents'),
|
|
2094
|
+
skipSkills: !components.includes('skills'),
|
|
2095
|
+
skipDocs: !components.includes('docs'),
|
|
2096
|
+
agentTargets,
|
|
2097
|
+
skillTargets,
|
|
2098
|
+
docTargets,
|
|
2099
|
+
force: false,
|
|
2100
|
+
dryRun: false,
|
|
2101
|
+
verbose: false,
|
|
2102
|
+
};
|
|
2103
|
+
const quickSyncService = new quickSync_1.QuickSyncService({
|
|
2104
|
+
ui,
|
|
2105
|
+
t,
|
|
2106
|
+
version: version_1.VERSION,
|
|
2107
|
+
defaultModel: DEFAULT_MODEL,
|
|
2108
|
+
});
|
|
2109
|
+
const result = await quickSyncService.run(projectPath, options);
|
|
2110
|
+
// If docs are outdated, ask if user wants to update
|
|
2111
|
+
if (!result.docsUpdated) {
|
|
2112
|
+
const stats = await quickSyncService.getStats(projectPath);
|
|
2113
|
+
if (stats.daysOld) {
|
|
2114
|
+
const { updateDocs } = await inquirer_1.default.prompt([
|
|
2115
|
+
{
|
|
2116
|
+
type: 'confirm',
|
|
2117
|
+
name: 'updateDocs',
|
|
2118
|
+
message: t('prompts.quickSync.updateDocs'),
|
|
2119
|
+
default: true,
|
|
2120
|
+
},
|
|
2121
|
+
]);
|
|
2122
|
+
if (updateDocs) {
|
|
2123
|
+
// Trigger fill with AI + LSP
|
|
2124
|
+
await runInteractiveLlmFill();
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
ui.displaySuccess(t('success.quickSync.complete'));
|
|
2129
|
+
}
|
|
2130
|
+
async function runManageAgents() {
|
|
2131
|
+
const projectPath = process.cwd();
|
|
2132
|
+
let continueMenu = true;
|
|
2133
|
+
while (continueMenu) {
|
|
2134
|
+
const { action } = await inquirer_1.default.prompt([
|
|
2135
|
+
{
|
|
2136
|
+
type: 'list',
|
|
2137
|
+
name: 'action',
|
|
2138
|
+
message: t('prompts.agents.action'),
|
|
2139
|
+
choices: [
|
|
2140
|
+
{ name: t('prompts.agents.choice.sync'), value: 'sync' },
|
|
2141
|
+
{ name: t('prompts.agents.choice.create'), value: 'create' },
|
|
2142
|
+
{ name: t('prompts.agents.choice.list'), value: 'list' },
|
|
2143
|
+
{ name: t('prompts.agents.choice.back'), value: 'back' },
|
|
2144
|
+
],
|
|
2145
|
+
},
|
|
2146
|
+
]);
|
|
2147
|
+
if (action === 'back') {
|
|
2148
|
+
continueMenu = false;
|
|
2149
|
+
break;
|
|
2150
|
+
}
|
|
2151
|
+
if (action === 'sync') {
|
|
2152
|
+
await runInteractiveSync();
|
|
2153
|
+
}
|
|
2154
|
+
else if (action === 'list') {
|
|
2155
|
+
await listAgents(projectPath);
|
|
2156
|
+
}
|
|
2157
|
+
else if (action === 'create') {
|
|
2158
|
+
await createCustomAgent(projectPath);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
async function listAgents(projectPath) {
|
|
2163
|
+
const agentsPath = path.join(projectPath, '.context', 'agents');
|
|
2164
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs-extra')));
|
|
2165
|
+
if (!(await fs.pathExists(agentsPath))) {
|
|
2166
|
+
ui.displayWarning('No agents directory found. Run scaffold first.');
|
|
2167
|
+
return;
|
|
2168
|
+
}
|
|
2169
|
+
const files = await fs.readdir(agentsPath);
|
|
2170
|
+
const agents = files.filter(f => f.endsWith('.md') && f !== 'README.md');
|
|
2171
|
+
console.log('\nAgents:');
|
|
2172
|
+
for (const agent of agents) {
|
|
2173
|
+
const name = agent.replace('.md', '');
|
|
2174
|
+
console.log(` ${theme_1.colors.primary(name)}`);
|
|
2175
|
+
}
|
|
2176
|
+
console.log(`\nTotal: ${agents.length} agents\n`);
|
|
2177
|
+
}
|
|
2178
|
+
async function createCustomAgent(projectPath) {
|
|
2179
|
+
const { name, description, role } = await inquirer_1.default.prompt([
|
|
2180
|
+
{
|
|
2181
|
+
type: 'input',
|
|
2182
|
+
name: 'name',
|
|
2183
|
+
message: t('prompts.agent.name'),
|
|
2184
|
+
validate: (input) => input.trim().length > 0 || 'Name is required',
|
|
2185
|
+
},
|
|
2186
|
+
{
|
|
2187
|
+
type: 'input',
|
|
2188
|
+
name: 'description',
|
|
2189
|
+
message: t('prompts.agent.description'),
|
|
2190
|
+
},
|
|
2191
|
+
{
|
|
2192
|
+
type: 'list',
|
|
2193
|
+
name: 'role',
|
|
2194
|
+
message: t('prompts.agent.role'),
|
|
2195
|
+
choices: [
|
|
2196
|
+
{ name: 'Code Reviewer', value: 'code-reviewer' },
|
|
2197
|
+
{ name: 'Bug Fixer', value: 'bug-fixer' },
|
|
2198
|
+
{ name: 'Feature Developer', value: 'feature-developer' },
|
|
2199
|
+
{ name: 'Test Writer', value: 'test-writer' },
|
|
2200
|
+
{ name: 'Documentation Writer', value: 'documentation-writer' },
|
|
2201
|
+
{ name: 'Security Auditor', value: 'security-auditor' },
|
|
2202
|
+
{ name: 'Performance Optimizer', value: 'performance-optimizer' },
|
|
2203
|
+
{ name: 'Custom...', value: 'custom' },
|
|
2204
|
+
],
|
|
2205
|
+
},
|
|
2206
|
+
]);
|
|
2207
|
+
let finalRole = role;
|
|
2208
|
+
if (role === 'custom') {
|
|
2209
|
+
const { customRole } = await inquirer_1.default.prompt([
|
|
2210
|
+
{
|
|
2211
|
+
type: 'input',
|
|
2212
|
+
name: 'customRole',
|
|
2213
|
+
message: 'Enter custom role:',
|
|
2214
|
+
validate: (input) => input.trim().length > 0 || 'Role is required',
|
|
2215
|
+
},
|
|
2216
|
+
]);
|
|
2217
|
+
finalRole = customRole.trim();
|
|
2218
|
+
}
|
|
2219
|
+
ui.startSpinner(t('spinner.agent.creating'));
|
|
2220
|
+
try {
|
|
2221
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs-extra')));
|
|
2222
|
+
const agentsDir = path.join(projectPath, '.context', 'agents');
|
|
2223
|
+
await fs.ensureDir(agentsDir);
|
|
2224
|
+
const slug = name.trim().toLowerCase().replace(/\s+/g, '-');
|
|
2225
|
+
const agentPath = path.join(agentsDir, `${slug}.md`);
|
|
2226
|
+
// Generate template content
|
|
2227
|
+
const template = `---
|
|
2228
|
+
name: ${name.trim()}
|
|
2229
|
+
description: ${description.trim() || `Custom agent: ${name.trim()}`}
|
|
2230
|
+
role: ${finalRole}
|
|
2231
|
+
custom: true
|
|
2232
|
+
---
|
|
2233
|
+
|
|
2234
|
+
# ${name.trim()} Agent
|
|
2235
|
+
|
|
2236
|
+
## Role
|
|
2237
|
+
${description.trim() || `Custom agent specialized in ${finalRole}`}
|
|
2238
|
+
|
|
2239
|
+
## Responsibilities
|
|
2240
|
+
- Review and analyze code related to ${finalRole}
|
|
2241
|
+
- Provide recommendations based on best practices
|
|
2242
|
+
- Help maintain code quality and standards
|
|
2243
|
+
|
|
2244
|
+
## Guidelines
|
|
2245
|
+
- Follow project conventions and patterns
|
|
2246
|
+
- Consider performance and maintainability
|
|
2247
|
+
- Document decisions and rationale
|
|
2248
|
+
|
|
2249
|
+
## Context
|
|
2250
|
+
This agent should be invoked when working on tasks related to ${finalRole}.
|
|
2251
|
+
`;
|
|
2252
|
+
// Write the agent file
|
|
2253
|
+
await fs.writeFile(agentPath, template, 'utf-8');
|
|
2254
|
+
// Try to fill with AI if API key is available
|
|
2255
|
+
const defaults = await (0, prompts_1.detectSmartDefaults)();
|
|
2256
|
+
if (defaults.apiKeyConfigured && defaults.provider) {
|
|
2257
|
+
ui.updateSpinner('Enhancing agent with AI...', 'info');
|
|
2258
|
+
try {
|
|
2259
|
+
// Run fill on just this agent
|
|
2260
|
+
const singleFillService = new fillService_1.FillService({
|
|
2261
|
+
ui,
|
|
2262
|
+
t,
|
|
2263
|
+
version: version_1.VERSION,
|
|
2264
|
+
defaultModel: DEFAULT_MODEL,
|
|
2265
|
+
});
|
|
2266
|
+
await singleFillService.run(projectPath, {
|
|
2267
|
+
model: DEFAULT_MODEL,
|
|
2268
|
+
provider: defaults.provider,
|
|
2269
|
+
apiKey: (0, providerFactory_1.getApiKeyFromEnv)(defaults.provider),
|
|
2270
|
+
verbose: false,
|
|
2271
|
+
semantic: true,
|
|
2272
|
+
useLsp: true,
|
|
2273
|
+
limit: 1,
|
|
2274
|
+
include: [agentPath],
|
|
2275
|
+
});
|
|
2276
|
+
}
|
|
2277
|
+
catch {
|
|
2278
|
+
// Ignore fill errors - template is already saved
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
ui.updateSpinner(t('spinner.agent.created'), 'success');
|
|
2282
|
+
ui.stopSpinner();
|
|
2283
|
+
ui.displaySuccess(t('success.agent.created', { name: name.trim() }));
|
|
2284
|
+
console.log(` Path: ${agentPath}\n`);
|
|
2285
|
+
}
|
|
2286
|
+
catch (error) {
|
|
2287
|
+
ui.updateSpinner('Failed to create agent', 'fail');
|
|
2288
|
+
ui.stopSpinner();
|
|
2289
|
+
ui.displayError('Failed to create agent', error);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
async function runSettings() {
|
|
2293
|
+
let continueMenu = true;
|
|
2294
|
+
while (continueMenu) {
|
|
2295
|
+
const { action } = await inquirer_1.default.prompt([
|
|
2296
|
+
{
|
|
2297
|
+
type: 'list',
|
|
2298
|
+
name: 'action',
|
|
2299
|
+
message: t('prompts.settings.action'),
|
|
2300
|
+
choices: [
|
|
2301
|
+
{ name: t('prompts.settings.choice.language'), value: 'language' },
|
|
2302
|
+
{ name: t('prompts.settings.choice.back'), value: 'back' },
|
|
2303
|
+
],
|
|
2304
|
+
},
|
|
2305
|
+
]);
|
|
2306
|
+
if (action === 'back') {
|
|
2307
|
+
continueMenu = false;
|
|
2308
|
+
break;
|
|
2309
|
+
}
|
|
2310
|
+
if (action === 'language') {
|
|
2311
|
+
await selectLocale(true);
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
1043
2315
|
function filterOutLocaleArgs(args) {
|
|
1044
2316
|
const filtered = [];
|
|
1045
2317
|
for (let index = 0; index < args.length; index += 1) {
|