@vfarcic/dot-ai 0.115.0 → 0.117.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -18
- package/dist/core/ai-provider-factory.d.ts +4 -2
- package/dist/core/ai-provider-factory.d.ts.map +1 -1
- package/dist/core/ai-provider-factory.js +17 -6
- package/dist/core/capability-operations.js +1 -1
- package/dist/core/generic-session-manager.d.ts +67 -0
- package/dist/core/generic-session-manager.d.ts.map +1 -0
- package/dist/core/generic-session-manager.js +192 -0
- package/dist/core/pattern-operations.js +1 -1
- package/dist/core/providers/noop-provider.d.ts +47 -0
- package/dist/core/providers/noop-provider.d.ts.map +1 -0
- package/dist/core/providers/noop-provider.js +63 -0
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +13 -13
- package/dist/core/session-utils.d.ts +3 -6
- package/dist/core/session-utils.d.ts.map +1 -1
- package/dist/core/session-utils.js +5 -13
- package/dist/core/shared-prompt-loader.d.ts +15 -3
- package/dist/core/shared-prompt-loader.d.ts.map +1 -1
- package/dist/core/shared-prompt-loader.js +67 -14
- package/dist/core/unified-creation-session.d.ts +3 -10
- package/dist/core/unified-creation-session.d.ts.map +1 -1
- package/dist/core/unified-creation-session.js +34 -75
- package/dist/core/unified-creation-types.d.ts +31 -22
- package/dist/core/unified-creation-types.d.ts.map +1 -1
- package/dist/evaluation/eval-runner.js +12 -3
- package/dist/evaluation/evaluators/base-comparative.d.ts +2 -0
- package/dist/evaluation/evaluators/base-comparative.d.ts.map +1 -1
- package/dist/evaluation/evaluators/base-comparative.js +13 -1
- package/dist/evaluation/graph-generator.d.ts +56 -0
- package/dist/evaluation/graph-generator.d.ts.map +1 -0
- package/dist/evaluation/graph-generator.js +694 -0
- package/dist/evaluation/metadata-loader.d.ts +39 -0
- package/dist/evaluation/metadata-loader.d.ts.map +1 -0
- package/dist/evaluation/metadata-loader.js +74 -0
- package/dist/evaluation/platform-synthesizer.d.ts +5 -1
- package/dist/evaluation/platform-synthesizer.d.ts.map +1 -1
- package/dist/evaluation/platform-synthesizer.js +65 -23
- package/dist/evaluation/run-platform-synthesis.js +22 -5
- package/dist/interfaces/mcp.d.ts.map +1 -1
- package/dist/interfaces/mcp.js +9 -34
- package/dist/tools/answer-question.d.ts.map +1 -1
- package/dist/tools/answer-question.js +12 -12
- package/dist/tools/choose-solution.js +1 -1
- package/dist/tools/generate-manifests.d.ts.map +1 -1
- package/dist/tools/generate-manifests.js +9 -10
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -6
- package/dist/tools/organizational-data.js +12 -12
- package/dist/tools/project-setup/discovery.d.ts +15 -0
- package/dist/tools/project-setup/discovery.d.ts.map +1 -0
- package/dist/tools/project-setup/discovery.js +104 -0
- package/dist/tools/project-setup/generate-scope.d.ts +15 -0
- package/dist/tools/project-setup/generate-scope.d.ts.map +1 -0
- package/dist/tools/project-setup/generate-scope.js +237 -0
- package/dist/tools/project-setup/report-scan.d.ts +15 -0
- package/dist/tools/project-setup/report-scan.d.ts.map +1 -0
- package/dist/tools/project-setup/report-scan.js +156 -0
- package/dist/tools/project-setup/types.d.ts +111 -0
- package/dist/tools/project-setup/types.d.ts.map +1 -0
- package/dist/tools/project-setup/types.js +8 -0
- package/dist/tools/project-setup.d.ts +28 -0
- package/dist/tools/project-setup.d.ts.map +1 -0
- package/dist/tools/project-setup.js +134 -0
- package/dist/tools/recommend.js +1 -1
- package/dist/tools/remediate.js +1 -1
- package/dist/tools/version.d.ts +0 -7
- package/dist/tools/version.d.ts.map +1 -1
- package/dist/tools/version.js +5 -34
- package/package.json +4 -2
- package/prompts/capability-inference.md +2 -2
- package/prompts/infrastructure-trigger-expansion.md +2 -2
- package/prompts/intent-analysis.md +2 -2
- package/prompts/kyverno-generation.md +14 -14
- package/prompts/manifest-generation.md +5 -5
- package/prompts/map-intent-to-operation.md +2 -2
- package/prompts/pattern-complete-error.md +1 -1
- package/prompts/pattern-complete-success.md +4 -4
- package/prompts/pattern-rationale.md +1 -1
- package/prompts/pattern-resources.md +1 -1
- package/prompts/pattern-review.md +5 -5
- package/prompts/policy-complete-apply.md +4 -4
- package/prompts/policy-complete-discard.md +1 -1
- package/prompts/policy-complete-error.md +1 -1
- package/prompts/policy-complete-save.md +4 -4
- package/prompts/policy-complete-success.md +4 -4
- package/prompts/policy-namespace-scope.md +1 -1
- package/prompts/question-generation.md +5 -5
- package/prompts/resource-analysis.md +3 -3
- package/prompts/resource-selection.md +3 -3
- package/prompts/solution-enhancement.md +4 -4
- package/scripts/anthropic.nu +9 -13
- package/scripts/common.nu +31 -33
- package/scripts/ingress.nu +5 -4
- package/scripts/kubernetes.nu +38 -53
- package/dist/core/doc-discovery.d.ts +0 -38
- package/dist/core/doc-discovery.d.ts.map +0 -1
- package/dist/core/doc-discovery.js +0 -231
- package/dist/core/doc-testing-session.d.ts +0 -109
- package/dist/core/doc-testing-session.d.ts.map +0 -1
- package/dist/core/doc-testing-session.js +0 -696
- package/dist/core/doc-testing-types.d.ts +0 -127
- package/dist/core/doc-testing-types.d.ts.map +0 -1
- package/dist/core/doc-testing-types.js +0 -53
- package/dist/core/nushell-runtime.d.ts +0 -39
- package/dist/core/nushell-runtime.d.ts.map +0 -1
- package/dist/core/nushell-runtime.js +0 -103
- package/dist/core/platform-operations.d.ts +0 -70
- package/dist/core/platform-operations.d.ts.map +0 -1
- package/dist/core/platform-operations.js +0 -294
- package/dist/tools/build-platform.d.ts +0 -25
- package/dist/tools/build-platform.d.ts.map +0 -1
- package/dist/tools/build-platform.js +0 -277
- package/dist/tools/test-docs.d.ts +0 -22
- package/dist/tools/test-docs.d.ts.map +0 -1
- package/dist/tools/test-docs.js +0 -351
- package/prompts/doc-testing-done.md +0 -51
- package/prompts/doc-testing-fix.md +0 -120
- package/prompts/doc-testing-scan.md +0 -140
- package/prompts/doc-testing-test-section.md +0 -169
- package/prompts/platform-operations-parse-script-help.md +0 -68
- package/scripts/ack.nu +0 -195
- package/scripts/argo-workflows.nu +0 -47
- package/scripts/argocd.nu +0 -85
- package/scripts/aso.nu +0 -74
- package/scripts/backstage.nu +0 -349
- package/scripts/cert-manager.nu +0 -13
- package/scripts/cnpg.nu +0 -14
- package/scripts/dot.nu +0 -32
- package/scripts/external-secrets.nu +0 -110
- package/scripts/gatekeeper.nu +0 -19
- package/scripts/github.nu +0 -42
- package/scripts/image.nu +0 -67
- package/scripts/kro.nu +0 -11
- package/scripts/kubevela.nu +0 -22
- package/scripts/port.nu +0 -71
- package/scripts/prometheus.nu +0 -21
- package/scripts/registry.nu +0 -55
- package/scripts/storage.nu +0 -210
- package/scripts/tests.nu +0 -12
- package/scripts/velero.nu +0 -45
- package/shared-prompts/validate-docs.md +0 -22
|
@@ -246,8 +246,8 @@ function parseNumericResponse(response, validOptions) {
|
|
|
246
246
|
/**
|
|
247
247
|
* Get session file path following established pattern
|
|
248
248
|
*/
|
|
249
|
-
function getCapabilitySessionPath(sessionId
|
|
250
|
-
const sessionDir = (0, session_utils_1.getAndValidateSessionDirectory)(
|
|
249
|
+
function getCapabilitySessionPath(sessionId) {
|
|
250
|
+
const sessionDir = (0, session_utils_1.getAndValidateSessionDirectory)(false);
|
|
251
251
|
const sessionSubDir = path.join(sessionDir, 'capability-sessions');
|
|
252
252
|
// Ensure capability-sessions subdirectory exists
|
|
253
253
|
if (!fs.existsSync(sessionSubDir)) {
|
|
@@ -258,9 +258,9 @@ function getCapabilitySessionPath(sessionId, args) {
|
|
|
258
258
|
/**
|
|
259
259
|
* Load session from file system following established pattern
|
|
260
260
|
*/
|
|
261
|
-
function loadCapabilitySession(sessionId
|
|
261
|
+
function loadCapabilitySession(sessionId) {
|
|
262
262
|
try {
|
|
263
|
-
const sessionPath = getCapabilitySessionPath(sessionId
|
|
263
|
+
const sessionPath = getCapabilitySessionPath(sessionId);
|
|
264
264
|
if (!fs.existsSync(sessionPath)) {
|
|
265
265
|
return null;
|
|
266
266
|
}
|
|
@@ -268,7 +268,7 @@ function loadCapabilitySession(sessionId, args) {
|
|
|
268
268
|
const session = JSON.parse(sessionData);
|
|
269
269
|
// Update last activity
|
|
270
270
|
session.lastActivity = new Date().toISOString();
|
|
271
|
-
saveCapabilitySession(session
|
|
271
|
+
saveCapabilitySession(session);
|
|
272
272
|
return session;
|
|
273
273
|
}
|
|
274
274
|
catch (error) {
|
|
@@ -279,9 +279,9 @@ function loadCapabilitySession(sessionId, args) {
|
|
|
279
279
|
/**
|
|
280
280
|
* Save session to file system following established pattern
|
|
281
281
|
*/
|
|
282
|
-
function saveCapabilitySession(session
|
|
282
|
+
function saveCapabilitySession(session) {
|
|
283
283
|
try {
|
|
284
|
-
const sessionPath = getCapabilitySessionPath(session.sessionId
|
|
284
|
+
const sessionPath = getCapabilitySessionPath(session.sessionId);
|
|
285
285
|
fs.writeFileSync(sessionPath, JSON.stringify(session, null, 2), 'utf8');
|
|
286
286
|
}
|
|
287
287
|
catch (error) {
|
|
@@ -294,7 +294,7 @@ function saveCapabilitySession(session, args) {
|
|
|
294
294
|
*/
|
|
295
295
|
function getOrCreateCapabilitySession(sessionId, args, logger, requestId) {
|
|
296
296
|
if (sessionId) {
|
|
297
|
-
const existing = loadCapabilitySession(sessionId
|
|
297
|
+
const existing = loadCapabilitySession(sessionId);
|
|
298
298
|
if (existing) {
|
|
299
299
|
logger.info('Loaded existing capability session', {
|
|
300
300
|
requestId,
|
|
@@ -312,7 +312,7 @@ function getOrCreateCapabilitySession(sessionId, args, logger, requestId) {
|
|
|
312
312
|
startedAt: new Date().toISOString(),
|
|
313
313
|
lastActivity: new Date().toISOString()
|
|
314
314
|
};
|
|
315
|
-
saveCapabilitySession(session
|
|
315
|
+
saveCapabilitySession(session);
|
|
316
316
|
logger.info('Created new capability session', {
|
|
317
317
|
requestId,
|
|
318
318
|
sessionId: newSessionId,
|
|
@@ -341,20 +341,20 @@ function validateCapabilityStep(session, clientStep) {
|
|
|
341
341
|
/**
|
|
342
342
|
* Transition session to next step with proper state updates
|
|
343
343
|
*/
|
|
344
|
-
function transitionCapabilitySession(session, nextStep, updates
|
|
344
|
+
function transitionCapabilitySession(session, nextStep, updates) {
|
|
345
345
|
session.currentStep = nextStep;
|
|
346
346
|
session.lastActivity = new Date().toISOString();
|
|
347
347
|
if (updates) {
|
|
348
348
|
Object.assign(session, updates);
|
|
349
349
|
}
|
|
350
|
-
saveCapabilitySession(session
|
|
350
|
+
saveCapabilitySession(session);
|
|
351
351
|
}
|
|
352
352
|
/**
|
|
353
353
|
* Clean up session file after successful completion
|
|
354
354
|
*/
|
|
355
355
|
function cleanupCapabilitySession(session, args, logger, requestId) {
|
|
356
356
|
try {
|
|
357
|
-
const sessionPath = getCapabilitySessionPath(session.sessionId
|
|
357
|
+
const sessionPath = getCapabilitySessionPath(session.sessionId);
|
|
358
358
|
if (fs.existsSync(sessionPath)) {
|
|
359
359
|
fs.unlinkSync(sessionPath);
|
|
360
360
|
logger.info('Capability session cleaned up after completion', {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery Handler - Project Setup Tool
|
|
3
|
+
* PRD #177 - Milestone 1: Core Tool Infrastructure
|
|
4
|
+
*
|
|
5
|
+
* Step 1 of workflow: Return list of files for client to scan
|
|
6
|
+
*/
|
|
7
|
+
import { Logger } from '../../core/error-handling';
|
|
8
|
+
import { DiscoveryResponse } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Handle discovery stage - Step 1 of project setup workflow
|
|
11
|
+
*
|
|
12
|
+
* Loads ALL files from ALL scopes and returns for client to scan
|
|
13
|
+
*/
|
|
14
|
+
export declare function handleDiscovery(logger: Logger, requestId: string): Promise<DiscoveryResponse>;
|
|
15
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/tools/project-setup/discovery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAgB,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAqC,MAAM,SAAS,CAAC;AAkB/E;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,CAAC,CAiE5B"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Discovery Handler - Project Setup Tool
|
|
4
|
+
* PRD #177 - Milestone 1: Core Tool Infrastructure
|
|
5
|
+
*
|
|
6
|
+
* Step 1 of workflow: Return list of files for client to scan
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.handleDiscovery = handleDiscovery;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const error_handling_1 = require("../../core/error-handling");
|
|
46
|
+
const generic_session_manager_1 = require("../../core/generic-session-manager");
|
|
47
|
+
/**
|
|
48
|
+
* Handle discovery stage - Step 1 of project setup workflow
|
|
49
|
+
*
|
|
50
|
+
* Loads ALL files from ALL scopes and returns for client to scan
|
|
51
|
+
*/
|
|
52
|
+
async function handleDiscovery(logger, requestId) {
|
|
53
|
+
return await error_handling_1.ErrorHandler.withErrorHandling(async () => {
|
|
54
|
+
logger.debug('Starting project setup discovery', { requestId });
|
|
55
|
+
// Load discovery config from source directory
|
|
56
|
+
// From dist/tools/project-setup/ -> ../../../ gets to project root, then src/tools/project-setup/
|
|
57
|
+
const configPath = path.join(__dirname, '..', '..', '..', 'src', 'tools', 'project-setup', 'discovery-config.json');
|
|
58
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
59
|
+
const allConfig = JSON.parse(configContent);
|
|
60
|
+
// Collect all files from all scopes
|
|
61
|
+
const allFiles = [];
|
|
62
|
+
const scopeNames = Object.keys(allConfig);
|
|
63
|
+
for (const scopeName of scopeNames) {
|
|
64
|
+
const scopeConfig = allConfig[scopeName];
|
|
65
|
+
allFiles.push(...scopeConfig.files);
|
|
66
|
+
}
|
|
67
|
+
// Remove duplicates
|
|
68
|
+
const uniqueFiles = Array.from(new Set(allFiles));
|
|
69
|
+
// Initialize session manager with 'proj' prefix
|
|
70
|
+
const sessionManager = new generic_session_manager_1.GenericSessionManager('proj');
|
|
71
|
+
// Create new session with ALL scope configurations
|
|
72
|
+
const session = sessionManager.createSession({
|
|
73
|
+
currentStep: 'discover',
|
|
74
|
+
allScopes: allConfig, // Store all scope configurations
|
|
75
|
+
filesToCheck: uniqueFiles
|
|
76
|
+
});
|
|
77
|
+
logger.info('Project setup session created', {
|
|
78
|
+
requestId,
|
|
79
|
+
sessionId: session.sessionId,
|
|
80
|
+
scopeCount: scopeNames.length,
|
|
81
|
+
fileCount: uniqueFiles.length
|
|
82
|
+
});
|
|
83
|
+
// Return discovery response
|
|
84
|
+
const response = {
|
|
85
|
+
success: true,
|
|
86
|
+
sessionId: session.sessionId,
|
|
87
|
+
filesToCheck: uniqueFiles,
|
|
88
|
+
availableScopes: scopeNames,
|
|
89
|
+
nextStep: 'reportScan',
|
|
90
|
+
instructions: `Scan the repository for these files: ${uniqueFiles.join(', ')}. Check which files exist and build an array of those files. Then call projectSetup tool with step: "reportScan", sessionId: "${session.sessionId}", and existingFiles: [array of files that exist in the repository].`
|
|
91
|
+
};
|
|
92
|
+
logger.debug('Discovery response prepared', {
|
|
93
|
+
requestId,
|
|
94
|
+
sessionId: session.sessionId,
|
|
95
|
+
fileCount: response.filesToCheck.length,
|
|
96
|
+
scopes: scopeNames
|
|
97
|
+
});
|
|
98
|
+
return response;
|
|
99
|
+
}, {
|
|
100
|
+
operation: 'project_setup_discovery',
|
|
101
|
+
component: 'ProjectSetupTool',
|
|
102
|
+
requestId
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate Scope Handler - Project Setup Tool
|
|
3
|
+
* PRD #177 - Scope-based workflow refactoring
|
|
4
|
+
*
|
|
5
|
+
* Step 3 of workflow: Generate ALL files in a scope at once
|
|
6
|
+
*/
|
|
7
|
+
import { Logger } from '../../core/error-handling';
|
|
8
|
+
import { GenerateScopeResponse, ErrorResponse } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Handle generateScope stage - Step 3 of project setup workflow
|
|
11
|
+
*
|
|
12
|
+
* Generates ALL files for a scope at once based on user answers
|
|
13
|
+
*/
|
|
14
|
+
export declare function handleGenerateScope(sessionId: string, scope: string | undefined, answers: Record<string, any> | undefined, logger: Logger, requestId: string): Promise<GenerateScopeResponse | ErrorResponse>;
|
|
15
|
+
//# sourceMappingURL=generate-scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-scope.d.ts","sourceRoot":"","sources":["../../../src/tools/project-setup/generate-scope.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAgB,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,qBAAqB,EAA2B,aAAa,EAAiB,MAAM,SAAS,CAAC;AAGvG;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACxC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,GAAG,aAAa,CAAC,CA8JhD"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generate Scope Handler - Project Setup Tool
|
|
4
|
+
* PRD #177 - Scope-based workflow refactoring
|
|
5
|
+
*
|
|
6
|
+
* Step 3 of workflow: Generate ALL files in a scope at once
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.handleGenerateScope = handleGenerateScope;
|
|
10
|
+
const error_handling_1 = require("../../core/error-handling");
|
|
11
|
+
const generic_session_manager_1 = require("../../core/generic-session-manager");
|
|
12
|
+
const shared_prompt_loader_1 = require("../../core/shared-prompt-loader");
|
|
13
|
+
/**
|
|
14
|
+
* Handle generateScope stage - Step 3 of project setup workflow
|
|
15
|
+
*
|
|
16
|
+
* Generates ALL files for a scope at once based on user answers
|
|
17
|
+
*/
|
|
18
|
+
async function handleGenerateScope(sessionId, scope, answers, logger, requestId) {
|
|
19
|
+
return await error_handling_1.ErrorHandler.withErrorHandling(async () => {
|
|
20
|
+
logger.debug('Starting scope generation', { requestId, sessionId, scope });
|
|
21
|
+
// Initialize session manager
|
|
22
|
+
const sessionManager = new generic_session_manager_1.GenericSessionManager('proj');
|
|
23
|
+
// Load session
|
|
24
|
+
const session = sessionManager.getSession(sessionId);
|
|
25
|
+
if (!session) {
|
|
26
|
+
return {
|
|
27
|
+
success: false,
|
|
28
|
+
error: {
|
|
29
|
+
message: `Session ${sessionId} not found`,
|
|
30
|
+
details: 'Please start a new session with step: "discover"'
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Validate inputs
|
|
35
|
+
if (!scope) {
|
|
36
|
+
return {
|
|
37
|
+
success: false,
|
|
38
|
+
error: {
|
|
39
|
+
message: 'scope is required for generateScope step',
|
|
40
|
+
details: 'Provide the scope name (e.g., "github-community")'
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (!answers) {
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
error: {
|
|
48
|
+
message: 'answers are required for generateScope step',
|
|
49
|
+
details: 'Provide answers to the questions for this scope'
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Validate session state
|
|
54
|
+
if (!session.data.allScopes || !session.data.existingFiles) {
|
|
55
|
+
return {
|
|
56
|
+
success: false,
|
|
57
|
+
error: {
|
|
58
|
+
message: 'Invalid session state',
|
|
59
|
+
details: 'Session does not contain required data'
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const scopeConfig = session.data.allScopes[scope];
|
|
64
|
+
if (!scopeConfig) {
|
|
65
|
+
return {
|
|
66
|
+
success: false,
|
|
67
|
+
error: {
|
|
68
|
+
message: `Invalid scope: ${scope}`,
|
|
69
|
+
details: `Available scopes: ${Object.keys(session.data.allScopes).join(', ')}`
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Get files to generate (excluding existing ones)
|
|
74
|
+
const existingFiles = session.data.existingFiles;
|
|
75
|
+
const baseFiles = scopeConfig.files.filter(file => !existingFiles.includes(file));
|
|
76
|
+
// Add conditional-only files (files that exist ONLY in conditionalFiles, not in main files array)
|
|
77
|
+
const conditionalFiles = scopeConfig.conditionalFiles || {};
|
|
78
|
+
const conditionalOnlyFiles = Object.keys(conditionalFiles).filter(file => !scopeConfig.files.includes(file) && !existingFiles.includes(file));
|
|
79
|
+
// Combine base files and conditional-only files
|
|
80
|
+
const filesToGenerate = [...baseFiles, ...conditionalOnlyFiles];
|
|
81
|
+
// Evaluate conditional files and generate content
|
|
82
|
+
const generatedFiles = [];
|
|
83
|
+
const excludedFiles = [];
|
|
84
|
+
for (const fileName of filesToGenerate) {
|
|
85
|
+
// Check if this file has conditional generation rules
|
|
86
|
+
const conditionalRule = conditionalFiles[fileName];
|
|
87
|
+
if (conditionalRule) {
|
|
88
|
+
const shouldGenerate = evaluateCondition(conditionalRule.condition, answers);
|
|
89
|
+
if (!shouldGenerate) {
|
|
90
|
+
logger.info('File excluded due to conditional rule', {
|
|
91
|
+
requestId,
|
|
92
|
+
fileName,
|
|
93
|
+
scope,
|
|
94
|
+
condition: conditionalRule.condition,
|
|
95
|
+
reason: conditionalRule.reason
|
|
96
|
+
});
|
|
97
|
+
excludedFiles.push(fileName);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Preprocess answers for template (convert comma-separated strings to arrays)
|
|
102
|
+
const processedAnswers = preprocessAnswers(answers);
|
|
103
|
+
// Generate file content
|
|
104
|
+
const content = generateFileContent(fileName, processedAnswers, logger);
|
|
105
|
+
generatedFiles.push({
|
|
106
|
+
path: fileName,
|
|
107
|
+
content,
|
|
108
|
+
reason: conditionalRule ? conditionalRule.reason : undefined
|
|
109
|
+
});
|
|
110
|
+
logger.info('File generated', {
|
|
111
|
+
requestId,
|
|
112
|
+
sessionId,
|
|
113
|
+
fileName,
|
|
114
|
+
scope,
|
|
115
|
+
contentLength: content.length
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// Update session
|
|
119
|
+
session.data.currentStep = 'complete';
|
|
120
|
+
sessionManager.updateSession(sessionId, session.data);
|
|
121
|
+
logger.info('Scope generation complete', {
|
|
122
|
+
requestId,
|
|
123
|
+
sessionId,
|
|
124
|
+
scope,
|
|
125
|
+
generatedCount: generatedFiles.length,
|
|
126
|
+
excludedCount: excludedFiles.length
|
|
127
|
+
});
|
|
128
|
+
// Process additionalInstructions template if present
|
|
129
|
+
let additionalInstructions;
|
|
130
|
+
if (scopeConfig.additionalInstructions) {
|
|
131
|
+
additionalInstructions = replaceTemplateVariables(scopeConfig.additionalInstructions, answers);
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
success: true,
|
|
135
|
+
sessionId,
|
|
136
|
+
scope,
|
|
137
|
+
files: generatedFiles,
|
|
138
|
+
excludedFiles: excludedFiles.length > 0 ? excludedFiles : undefined,
|
|
139
|
+
instructions: `Generated ${generatedFiles.length} file(s) for scope "${scope}".\n\n` +
|
|
140
|
+
`Files:\n${generatedFiles.map(f => `- ${f.path}`).join('\n')}\n\n` +
|
|
141
|
+
(excludedFiles.length > 0 ? `Excluded ${excludedFiles.length} file(s):\n${excludedFiles.map(f => `- ${f}`).join('\n')}\n\n` : '') +
|
|
142
|
+
`Write these files to your repository using the Write tool.`,
|
|
143
|
+
additionalInstructions
|
|
144
|
+
};
|
|
145
|
+
}, {
|
|
146
|
+
operation: 'project_setup_generate_scope',
|
|
147
|
+
component: 'ProjectSetupTool',
|
|
148
|
+
requestId
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Generate file content from template using Handlebars
|
|
153
|
+
*/
|
|
154
|
+
function generateFileContent(fileName, answers, logger) {
|
|
155
|
+
try {
|
|
156
|
+
// Load template using shared prompt loader with Handlebars support
|
|
157
|
+
// Templates use .hbs extension (e.g., README.md -> README.md.hbs)
|
|
158
|
+
const content = (0, shared_prompt_loader_1.loadPrompt)(fileName, answers, 'src/tools/project-setup/templates', '.hbs' // Add .hbs extension to template files
|
|
159
|
+
);
|
|
160
|
+
return content;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
logger.error('Failed to generate file content', error, { fileName });
|
|
164
|
+
return `# ${fileName}\n\nError: Could not generate content for this file.\nTemplate may be missing at: src/tools/project-setup/templates/${fileName}.hbs\n`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Evaluate conditional file generation rule
|
|
169
|
+
*
|
|
170
|
+
* Supports conditions:
|
|
171
|
+
* - "false" -> always false
|
|
172
|
+
* - "true" -> always true
|
|
173
|
+
* - "variableName === 'value'" -> check if answers[variableName] === 'value'
|
|
174
|
+
* - "variableName === true" -> check if answers[variableName] is boolean true or truthy string
|
|
175
|
+
* - OR conditions: "condition1 || condition2 || condition3"
|
|
176
|
+
*/
|
|
177
|
+
function evaluateCondition(condition, answers) {
|
|
178
|
+
const trimmed = condition.trim();
|
|
179
|
+
// Handle literal boolean strings
|
|
180
|
+
if (trimmed === 'false')
|
|
181
|
+
return false;
|
|
182
|
+
if (trimmed === 'true')
|
|
183
|
+
return true;
|
|
184
|
+
// Handle OR conditions: split by || and evaluate each part
|
|
185
|
+
if (trimmed.includes('||')) {
|
|
186
|
+
const conditions = trimmed.split('||').map(c => c.trim());
|
|
187
|
+
return conditions.some(cond => evaluateCondition(cond, answers));
|
|
188
|
+
}
|
|
189
|
+
// Handle equality checks with boolean: "variableName === true"
|
|
190
|
+
const booleanMatch = trimmed.match(/^(\w+)\s*===\s*(true|false)$/);
|
|
191
|
+
if (booleanMatch) {
|
|
192
|
+
const [, variableName, expectedValue] = booleanMatch;
|
|
193
|
+
const actualValue = answers[variableName];
|
|
194
|
+
// Check for truthy values: boolean true, string "yes", string "true"
|
|
195
|
+
if (expectedValue === 'true') {
|
|
196
|
+
return actualValue === true || actualValue === 'true' || actualValue === 'yes';
|
|
197
|
+
}
|
|
198
|
+
// Check for falsy values
|
|
199
|
+
return actualValue === false || actualValue === 'false' || actualValue === 'no';
|
|
200
|
+
}
|
|
201
|
+
// Handle equality checks with strings: "variableName === 'value'"
|
|
202
|
+
const stringMatch = trimmed.match(/^(\w+)\s*===\s*['"]([^'"]+)['"]$/);
|
|
203
|
+
if (stringMatch) {
|
|
204
|
+
const [, variableName, expectedValue] = stringMatch;
|
|
205
|
+
return answers[variableName] === expectedValue;
|
|
206
|
+
}
|
|
207
|
+
// Unknown condition format - default to false for safety
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Preprocess answers for Handlebars templates
|
|
212
|
+
* Converts comma-separated strings to arrays where needed
|
|
213
|
+
*/
|
|
214
|
+
function preprocessAnswers(answers) {
|
|
215
|
+
const processed = { ...answers };
|
|
216
|
+
// Convert maintainerUsernames from comma-separated string to array
|
|
217
|
+
if (processed.maintainerUsernames && typeof processed.maintainerUsernames === 'string') {
|
|
218
|
+
processed.maintainerUsernames = processed.maintainerUsernames
|
|
219
|
+
.split(',')
|
|
220
|
+
.map((username) => username.trim())
|
|
221
|
+
.filter((username) => username.length > 0);
|
|
222
|
+
}
|
|
223
|
+
return processed;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Replace template variables in additionalInstructions
|
|
227
|
+
* Simple replacement for {{variableName}} patterns
|
|
228
|
+
*/
|
|
229
|
+
function replaceTemplateVariables(template, answers) {
|
|
230
|
+
let result = template;
|
|
231
|
+
// Replace all {{variableName}} with actual values
|
|
232
|
+
for (const [key, value] of Object.entries(answers)) {
|
|
233
|
+
const pattern = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
|
|
234
|
+
result = result.replace(pattern, String(value || ''));
|
|
235
|
+
}
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Scan Handler - Project Setup Tool
|
|
3
|
+
* PRD #177 - Scope-based workflow refactoring
|
|
4
|
+
*
|
|
5
|
+
* Step 2 of workflow: Return ALL questions for selected scope
|
|
6
|
+
*/
|
|
7
|
+
import { Logger } from '../../core/error-handling';
|
|
8
|
+
import { ReportScanResponse, ErrorResponse } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Handle reportScan stage - Step 2 of project setup workflow
|
|
11
|
+
*
|
|
12
|
+
* Returns all questions for the selected scope and list of files to generate
|
|
13
|
+
*/
|
|
14
|
+
export declare function handleReportScan(sessionId: string, existingFiles: string[] | undefined, selectedScopes: string[] | undefined, logger: Logger, requestId: string): Promise<ReportScanResponse | ErrorResponse>;
|
|
15
|
+
//# sourceMappingURL=report-scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-scan.d.ts","sourceRoot":"","sources":["../../../src/tools/project-setup/report-scan.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAgB,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAA2B,aAAa,EAAE,MAAM,SAAS,CAAC;AAErF;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EAAE,GAAG,SAAS,EACnC,cAAc,EAAE,MAAM,EAAE,GAAG,SAAS,EACpC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,GAAG,aAAa,CAAC,CA4I7C"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Report Scan Handler - Project Setup Tool
|
|
4
|
+
* PRD #177 - Scope-based workflow refactoring
|
|
5
|
+
*
|
|
6
|
+
* Step 2 of workflow: Return ALL questions for selected scope
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.handleReportScan = handleReportScan;
|
|
10
|
+
const error_handling_1 = require("../../core/error-handling");
|
|
11
|
+
const generic_session_manager_1 = require("../../core/generic-session-manager");
|
|
12
|
+
/**
|
|
13
|
+
* Handle reportScan stage - Step 2 of project setup workflow
|
|
14
|
+
*
|
|
15
|
+
* Returns all questions for the selected scope and list of files to generate
|
|
16
|
+
*/
|
|
17
|
+
async function handleReportScan(sessionId, existingFiles, selectedScopes, logger, requestId) {
|
|
18
|
+
return await error_handling_1.ErrorHandler.withErrorHandling(async () => {
|
|
19
|
+
logger.debug('Starting report scan analysis', { requestId, sessionId });
|
|
20
|
+
// Initialize session manager
|
|
21
|
+
const sessionManager = new generic_session_manager_1.GenericSessionManager('proj');
|
|
22
|
+
// Load session
|
|
23
|
+
const session = sessionManager.getSession(sessionId);
|
|
24
|
+
if (!session) {
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
error: {
|
|
28
|
+
message: `Session ${sessionId} not found`,
|
|
29
|
+
details: 'Please start a new session with step: "discover"'
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Validate session state
|
|
34
|
+
if (!session.data.allScopes || !session.data.filesToCheck) {
|
|
35
|
+
return {
|
|
36
|
+
success: false,
|
|
37
|
+
error: {
|
|
38
|
+
message: 'Invalid session state',
|
|
39
|
+
details: 'Session does not contain scope configuration data'
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const allScopes = session.data.allScopes;
|
|
44
|
+
// Store or retrieve existingFiles
|
|
45
|
+
let filesToUse;
|
|
46
|
+
if (existingFiles !== undefined) {
|
|
47
|
+
filesToUse = existingFiles;
|
|
48
|
+
session.data.existingFiles = existingFiles;
|
|
49
|
+
sessionManager.updateSession(sessionId, session.data);
|
|
50
|
+
logger.debug('Stored existingFiles in session', { requestId, sessionId, count: existingFiles.length });
|
|
51
|
+
}
|
|
52
|
+
else if (session.data.existingFiles !== undefined) {
|
|
53
|
+
filesToUse = session.data.existingFiles;
|
|
54
|
+
logger.debug('Reusing existingFiles from session', { requestId, sessionId, count: filesToUse.length });
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error: {
|
|
60
|
+
message: 'existingFiles is required for first reportScan call',
|
|
61
|
+
details: 'Please provide an array of files that exist in the repository'
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// If no scopes selected, return analysis report
|
|
66
|
+
if (!selectedScopes || selectedScopes.length === 0) {
|
|
67
|
+
// Analyze scope completeness
|
|
68
|
+
const scopeStatus = {};
|
|
69
|
+
for (const [scopeName, scopeConfig] of Object.entries(allScopes)) {
|
|
70
|
+
const missingFiles = scopeConfig.files.filter(file => !filesToUse.includes(file));
|
|
71
|
+
scopeStatus[scopeName] = {
|
|
72
|
+
complete: missingFiles.length === 0,
|
|
73
|
+
missingFiles
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const incompleteScopes = Object.entries(scopeStatus)
|
|
77
|
+
.filter(([_, status]) => !status.complete)
|
|
78
|
+
.map(([scopeName, _]) => scopeName);
|
|
79
|
+
// Generate report for user to review
|
|
80
|
+
const report = generateReport(scopeStatus, allScopes);
|
|
81
|
+
logger.info('Generated scope analysis report', {
|
|
82
|
+
requestId,
|
|
83
|
+
sessionId,
|
|
84
|
+
totalScopes: Object.keys(allScopes).length,
|
|
85
|
+
incompleteScopes: incompleteScopes.length
|
|
86
|
+
});
|
|
87
|
+
const incompleteScopeNames = incompleteScopes.join('", "');
|
|
88
|
+
return {
|
|
89
|
+
success: true,
|
|
90
|
+
sessionId,
|
|
91
|
+
nextStep: 'generateScope',
|
|
92
|
+
scope: '',
|
|
93
|
+
questions: [],
|
|
94
|
+
filesToGenerate: [],
|
|
95
|
+
instructions: `${report}\n\nIncomplete scopes: ${incompleteScopes.join(', ')}\n\n**IMPORTANT**: Present each scope individually to the user. Do NOT combine or group scopes. Use exact scope names.\n\nTo proceed, call projectSetup tool again with:\n- step: "reportScan"\n- sessionId: "${sessionId}"\n- selectedScopes: ["${incompleteScopeNames}"] (Use exact scope names from the list above)`
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// User selected scope(s) - take first scope to generate
|
|
99
|
+
const selectedScope = selectedScopes[0];
|
|
100
|
+
const scopeConfig = allScopes[selectedScope];
|
|
101
|
+
if (!scopeConfig) {
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
error: {
|
|
105
|
+
message: `Invalid scope: ${selectedScope}`,
|
|
106
|
+
details: `Available scopes: ${Object.keys(allScopes).join(', ')}`
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Calculate which files need to be generated
|
|
111
|
+
const filesToGenerate = scopeConfig.files.filter(file => !filesToUse.includes(file));
|
|
112
|
+
// Store selected scopes in session
|
|
113
|
+
session.data.selectedScopes = selectedScopes;
|
|
114
|
+
session.data.currentStep = 'generateScope';
|
|
115
|
+
sessionManager.updateSession(sessionId, session.data);
|
|
116
|
+
logger.info('Ready to generate scope', {
|
|
117
|
+
requestId,
|
|
118
|
+
sessionId,
|
|
119
|
+
scope: selectedScope,
|
|
120
|
+
filesToGenerate: filesToGenerate.length,
|
|
121
|
+
questions: scopeConfig.questions.length
|
|
122
|
+
});
|
|
123
|
+
// Return ALL questions for this scope
|
|
124
|
+
return {
|
|
125
|
+
success: true,
|
|
126
|
+
sessionId,
|
|
127
|
+
nextStep: 'generateScope',
|
|
128
|
+
scope: selectedScope,
|
|
129
|
+
questions: scopeConfig.questions,
|
|
130
|
+
filesToGenerate,
|
|
131
|
+
instructions: `Scope: ${selectedScope}\n\nFiles to generate (${filesToGenerate.length}):\n${filesToGenerate.map(f => `- ${f}`).join('\n')}\n\nQuestions (${scopeConfig.questions.length}):\n${scopeConfig.questions.map((q, i) => `${i + 1}. ${q.question} (ID: ${q.id}${q.required ? ', required' : ''})`).join('\n')}\n\nAnalyze the repository to determine answers for these questions. Present your suggested answers as a numbered list. Once finalized, call projectSetup tool with:\n- step: "generateScope"\n- sessionId: "${sessionId}"\n- scope: "${selectedScope}"\n- answers: {${scopeConfig.questions.slice(0, 2).map(q => `"${q.id}": "value"`).join(', ')}, ...}`
|
|
132
|
+
};
|
|
133
|
+
}, {
|
|
134
|
+
operation: 'project_setup_report_scan',
|
|
135
|
+
component: 'ProjectSetupTool',
|
|
136
|
+
requestId
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Generate human-readable report of scope analysis
|
|
141
|
+
*/
|
|
142
|
+
function generateReport(scopeStatus, allScopes) {
|
|
143
|
+
const lines = ['Repository Analysis:', ''];
|
|
144
|
+
for (const [scopeName, status] of Object.entries(scopeStatus)) {
|
|
145
|
+
const scopeConfig = allScopes[scopeName];
|
|
146
|
+
const totalFiles = scopeConfig.files.length;
|
|
147
|
+
const missingCount = status.missingFiles.length;
|
|
148
|
+
const existingCount = totalFiles - missingCount;
|
|
149
|
+
const statusIcon = status.complete ? '✓' : '○';
|
|
150
|
+
lines.push(`${statusIcon} ${scopeName}: ${existingCount}/${totalFiles} files exist`);
|
|
151
|
+
if (!status.complete) {
|
|
152
|
+
lines.push(` Missing: ${status.missingFiles.join(', ')}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|