scai 0.1.117 → 0.1.119

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +88 -503
  2. package/dist/agents/MainAgent.js +255 -0
  3. package/dist/agents/contextReviewStep.js +104 -0
  4. package/dist/agents/finalPlanGenStep.js +123 -0
  5. package/dist/agents/infoPlanGenStep.js +126 -0
  6. package/dist/agents/planGeneratorStep.js +118 -0
  7. package/dist/agents/planResolverStep.js +95 -0
  8. package/dist/agents/planTargetFilesStep.js +48 -0
  9. package/dist/agents/preFileSearchCheckStep.js +95 -0
  10. package/dist/agents/selectRelevantSourcesStep.js +100 -0
  11. package/dist/agents/semanticAnalysisStep.js +144 -0
  12. package/dist/agents/structuralAnalysisStep.js +46 -0
  13. package/dist/agents/transformPlanGenStep.js +107 -0
  14. package/dist/agents/understandIntentStep.js +72 -0
  15. package/dist/agents/validationAnalysisStep.js +87 -0
  16. package/dist/commands/AskCmd.js +47 -116
  17. package/dist/commands/ChangeLogUpdateCmd.js +11 -5
  18. package/dist/commands/CommitSuggesterCmd.js +50 -75
  19. package/dist/commands/DaemonCmd.js +119 -29
  20. package/dist/commands/IndexCmd.js +41 -24
  21. package/dist/commands/InspectCmd.js +0 -1
  22. package/dist/commands/ReadlineSingleton.js +18 -0
  23. package/dist/commands/ResetDbCmd.js +20 -21
  24. package/dist/commands/ReviewCmd.js +89 -54
  25. package/dist/commands/SummaryCmd.js +12 -18
  26. package/dist/commands/WorkflowCmd.js +41 -0
  27. package/dist/commands/factory.js +254 -0
  28. package/dist/config.js +67 -15
  29. package/dist/constants.js +20 -4
  30. package/dist/context.js +10 -11
  31. package/dist/daemon/daemonQueues.js +63 -0
  32. package/dist/daemon/daemonWorker.js +40 -63
  33. package/dist/daemon/generateSummaries.js +58 -0
  34. package/dist/daemon/runFolderCapsuleBatch.js +247 -0
  35. package/dist/daemon/runIndexingBatch.js +147 -0
  36. package/dist/daemon/runKgBatch.js +104 -0
  37. package/dist/db/fileIndex.js +168 -63
  38. package/dist/db/functionExtractors/extractFromJava.js +210 -6
  39. package/dist/db/functionExtractors/extractFromJs.js +173 -214
  40. package/dist/db/functionExtractors/extractFromTs.js +159 -160
  41. package/dist/db/functionExtractors/index.js +7 -5
  42. package/dist/db/schema.js +55 -20
  43. package/dist/db/sqlTemplates.js +50 -19
  44. package/dist/fileRules/builtins.js +31 -14
  45. package/dist/fileRules/codeAllowedExtensions.js +4 -0
  46. package/dist/fileRules/fileExceptions.js +0 -13
  47. package/dist/fileRules/ignoredExtensions.js +10 -0
  48. package/dist/index.js +128 -325
  49. package/dist/lib/generate.js +37 -14
  50. package/dist/lib/generateFolderCapsules.js +109 -0
  51. package/dist/lib/spinner.js +12 -5
  52. package/dist/modelSetup.js +1 -11
  53. package/dist/pipeline/modules/changeLogModule.js +16 -19
  54. package/dist/pipeline/modules/chunkManagerModule.js +24 -0
  55. package/dist/pipeline/modules/cleanupModule.js +95 -91
  56. package/dist/pipeline/modules/codeTransformModule.js +208 -0
  57. package/dist/pipeline/modules/commentModule.js +20 -11
  58. package/dist/pipeline/modules/commitSuggesterModule.js +36 -14
  59. package/dist/pipeline/modules/contextReviewModule.js +52 -0
  60. package/dist/pipeline/modules/fileReaderModule.js +72 -0
  61. package/dist/pipeline/modules/fileSearchModule.js +136 -0
  62. package/dist/pipeline/modules/finalAnswerModule.js +53 -0
  63. package/dist/pipeline/modules/gatherInfoModule.js +176 -0
  64. package/dist/pipeline/modules/generateTestsModule.js +63 -54
  65. package/dist/pipeline/modules/kgModule.js +26 -11
  66. package/dist/pipeline/modules/preserveCodeModule.js +91 -49
  67. package/dist/pipeline/modules/refactorModule.js +19 -7
  68. package/dist/pipeline/modules/repairTestsModule.js +44 -36
  69. package/dist/pipeline/modules/reviewModule.js +23 -13
  70. package/dist/pipeline/modules/summaryModule.js +27 -35
  71. package/dist/pipeline/modules/writeFileModule.js +86 -0
  72. package/dist/pipeline/registry/moduleRegistry.js +38 -93
  73. package/dist/pipeline/runModulePipeline.js +22 -19
  74. package/dist/scripts/dbcheck.js +143 -228
  75. package/dist/utils/buildContextualPrompt.js +245 -172
  76. package/dist/utils/debugContext.js +24 -0
  77. package/dist/utils/fileTree.js +16 -6
  78. package/dist/utils/loadRelevantFolderCapsules.js +64 -0
  79. package/dist/utils/log.js +2 -0
  80. package/dist/utils/normalizeData.js +23 -0
  81. package/dist/utils/planActions.js +60 -0
  82. package/dist/utils/promptBuilderHelper.js +67 -0
  83. package/dist/utils/promptLogHelper.js +52 -0
  84. package/dist/utils/sanitizeQuery.js +20 -8
  85. package/dist/utils/sleep.js +3 -0
  86. package/dist/utils/splitCodeIntoChunk.js +65 -32
  87. package/dist/utils/vscode.js +49 -0
  88. package/dist/workflow/workflowResolver.js +14 -0
  89. package/dist/workflow/workflowRunner.js +103 -0
  90. package/package.json +6 -5
  91. package/dist/agent/agentManager.js +0 -39
  92. package/dist/agent/workflowManager.js +0 -95
  93. package/dist/commands/ModulePipelineCmd.js +0 -31
  94. package/dist/daemon/daemonBatch.js +0 -186
  95. package/dist/fileRules/scoreFiles.js +0 -71
  96. package/dist/lib/generateEmbedding.js +0 -22
@@ -0,0 +1,107 @@
1
+ // File: src/agents/transformPlanGenStep.ts
2
+ import { generate } from '../lib/generate.js';
3
+ import { PLAN_ACTIONS } from '../utils/planActions.js';
4
+ import { logInputOutput } from '../utils/promptLogHelper.js';
5
+ import { cleanupModule } from '../pipeline/modules/cleanupModule.js';
6
+ const MAX_STEPS = 100;
7
+ /**
8
+ * TRANSFORM PLAN GENERATOR
9
+ * Generates steps that perform concrete transformations or code changes.
10
+ */
11
+ export const transformPlanGenStep = {
12
+ name: 'transformPlanGen',
13
+ description: 'Generates code transformation / modification steps.',
14
+ requires: ['analysis.intent', 'analysis.focus'],
15
+ produces: ['analysis.planSuggestion'],
16
+ async run(context) {
17
+ var _a, _b;
18
+ context.analysis || (context.analysis = {});
19
+ (_a = context.analysis).planSuggestion || (_a.planSuggestion = {});
20
+ (_b = context.analysis.planSuggestion).plan || (_b.plan = { steps: [] });
21
+ // Restrict actions to TRANSFORM group only
22
+ const effectiveActions = PLAN_ACTIONS.filter(a => a.groups?.includes('transform'));
23
+ const actionsJson = JSON.stringify(effectiveActions, null, 2);
24
+ const intentText = context.analysis.intent?.normalizedQuery ?? '';
25
+ const intentCategory = context.analysis.intent?.intentCategory ?? '';
26
+ const prompt = `
27
+ You are an autonomous coding agent.
28
+ Your task is to produce a structured plan describing how to implement actual code transformations
29
+ or modifications in the system to achieve the intended task.
30
+
31
+ Intent / task description:
32
+ ${intentText}
33
+
34
+ If the intent indicates that this is NOT a coding, refactoring, or inline commenting task,
35
+ then return an empty plan object with an empty "steps" array:
36
+ { "steps": [] }
37
+
38
+ Allowed actions (transformation only):
39
+ ${actionsJson}
40
+
41
+ Task category:
42
+ ${intentCategory}
43
+
44
+ Folder structure:
45
+ ${context.analysis.folderCapsulesHuman ?? ''}
46
+
47
+ Existing relevant files:
48
+ ${JSON.stringify(context.analysis.focus?.relevantFiles ?? {}, null, 2)}
49
+
50
+ Only perform transformations that are safe based on the existing analysis.
51
+
52
+ ⚔ Phase guidance:
53
+ - Actions are grouped into phases: info, transform, finalize.
54
+ - Only include transform steps in this phase.
55
+ - Include a 'writeFile' step for each 'codeTransform' to persist changes to disk.
56
+ - Each step must include: "action", "targetFile" (optional), "description", "metadata"
57
+
58
+ āŒ IMPORTANT: Do NOT include "info" steps here. Only plan actual code transformations.
59
+
60
+ Return a strictly valid JSON plan:
61
+
62
+ {
63
+ "steps": [
64
+ { "action": "stepName", "targetFile": "optional/path.ts", "description": "explanation", "metadata": {} }
65
+ ]
66
+ }
67
+ `.trim();
68
+ try {
69
+ console.log('TransformPlanGenStep prompt', prompt);
70
+ const genInput = { query: intentText, content: prompt };
71
+ const genOutput = await generate(genInput);
72
+ const raw = typeof genOutput.data === 'string'
73
+ ? genOutput.data
74
+ : JSON.stringify(genOutput.data ?? '{}');
75
+ const cleaned = await cleanupModule.run({ query: intentText, content: raw });
76
+ const jsonString = typeof cleaned.content === 'string'
77
+ ? cleaned.content
78
+ : JSON.stringify(cleaned.content ?? '{}');
79
+ let plan = JSON.parse(jsonString);
80
+ if (!plan || !Array.isArray(plan.steps))
81
+ throw new Error('Invalid transform plan structure');
82
+ if (plan.steps.length > MAX_STEPS)
83
+ plan.steps = plan.steps.slice(0, MAX_STEPS);
84
+ // Map groups & metadata
85
+ plan.steps = plan.steps.map(step => {
86
+ const actionDef = PLAN_ACTIONS.find(a => a.action === step.action);
87
+ return {
88
+ ...step,
89
+ metadata: {
90
+ ...step.metadata,
91
+ routingConfidence: context.analysis?.routingDecision?.confidence ?? 0
92
+ },
93
+ groups: actionDef?.groups ?? ['transform']
94
+ };
95
+ });
96
+ // Replace existing transform steps in planSuggestion
97
+ context.analysis.planSuggestion.plan.steps = [
98
+ ...context.analysis.planSuggestion.plan.steps.filter(s => !s.groups?.includes('transform')),
99
+ ...plan.steps
100
+ ];
101
+ logInputOutput('transformPlanGen', 'output', plan);
102
+ }
103
+ catch (err) {
104
+ console.warn('āš ļø Failed to generate transform plan:', err);
105
+ }
106
+ }
107
+ };
@@ -0,0 +1,72 @@
1
+ // File: src/agents/steps/understandIntentStep.ts
2
+ import { generate } from "../lib/generate.js";
3
+ import { logInputOutput } from "../utils/promptLogHelper.js";
4
+ export const understandIntentStep = {
5
+ name: "understandIntent",
6
+ description: "Analyze the user query and determine its intent, type, and the appropriate task category.",
7
+ /**
8
+ * Run the step
9
+ */
10
+ run: async (input) => {
11
+ const { context } = input;
12
+ const prompt = `
13
+ You are an AI assistant whose job is to determine the user's intent.
14
+
15
+ User Query:
16
+ ${context.initContext?.userQuery}
17
+
18
+ Return a STRICT JSON object with the following fields:
19
+ {
20
+ "intent": "short sentence summarizing the user's intent",
21
+ "intentCategory": "one of: question, request, codingTask, refactorTask, explanation, debugging, planning, writing, other",
22
+ "normalizedQuery": "a cleaned and direct restatement of the user query",
23
+ "confidence": 0-1 // float
24
+ }
25
+
26
+ Do not include commentary. Emit ONLY valid JSON.
27
+ `.trim();
28
+ try {
29
+ const genInput = {
30
+ query: context.initContext?.userQuery ?? '',
31
+ content: prompt
32
+ };
33
+ const genOutput = await generate(genInput);
34
+ let raw = genOutput.data;
35
+ if (typeof raw !== "string")
36
+ raw = JSON.stringify(raw ?? "{}");
37
+ logInputOutput("understandIntent", "output", raw);
38
+ let parsed;
39
+ try {
40
+ parsed = JSON.parse(raw);
41
+ }
42
+ catch {
43
+ parsed = {
44
+ intent: "unknown",
45
+ intentCategory: "other",
46
+ normalizedQuery: context.initContext?.userQuery,
47
+ confidence: 0.3
48
+ };
49
+ }
50
+ // Ensure the analysis object exists
51
+ context.analysis ?? (context.analysis = {});
52
+ // Store intent inside a dedicated object
53
+ context.analysis.intent = {
54
+ intent: parsed.intent,
55
+ intentCategory: parsed.intentCategory,
56
+ normalizedQuery: parsed.normalizedQuery,
57
+ confidence: parsed.confidence
58
+ };
59
+ }
60
+ catch (err) {
61
+ console.error("understandIntent error:", err);
62
+ // Ensure the analysis object exists
63
+ context.analysis ?? (context.analysis = {});
64
+ context.analysis.intent = {
65
+ intent: "unknown",
66
+ intentCategory: "other",
67
+ normalizedQuery: context.initContext?.userQuery ?? '',
68
+ confidence: 0.0
69
+ };
70
+ }
71
+ }
72
+ };
@@ -0,0 +1,87 @@
1
+ import { logInputOutput } from "../utils/promptLogHelper.js";
2
+ export const validationAnalysisStep = {
3
+ name: "validationAnalysis",
4
+ description: "Validate semantic analysis results and verify that focused working files were correctly synced into plan.targetFiles.",
5
+ groups: ["analysis"],
6
+ run: async (input) => {
7
+ const ctx = input.context;
8
+ if (!ctx) {
9
+ throw new Error("[validationAnalysisStep] StructuredContext is required but was not provided.");
10
+ }
11
+ const notes = [];
12
+ const warnings = [];
13
+ // -----------------------------
14
+ // Focus validation
15
+ // -----------------------------
16
+ const focusFiles = ctx.analysis?.focus?.relevantFiles ?? [];
17
+ if (!focusFiles.length) {
18
+ warnings.push("No relevant files found in analysis.focus.");
19
+ }
20
+ // -----------------------------
21
+ // Semantic understanding validation
22
+ // -----------------------------
23
+ const understanding = ctx.analysis?.understanding;
24
+ if (!understanding) {
25
+ notes.push("No semantic understanding produced by analysis.");
26
+ }
27
+ else {
28
+ if (!understanding.risks?.length) {
29
+ notes.push("No risks recorded in analysis.understanding.");
30
+ }
31
+ if (!understanding.assumptions?.length) {
32
+ notes.push("No assumptions recorded in analysis.understanding.");
33
+ }
34
+ }
35
+ // -----------------------------
36
+ // Intent presence & shape validation
37
+ // (Produced by understandIntent step)
38
+ // -----------------------------
39
+ const intent = ctx.analysis?.intent;
40
+ if (!intent) {
41
+ warnings.push("No intent found in context (expected from understandIntent step).");
42
+ }
43
+ else {
44
+ if (!intent.intent || !intent.intentCategory) {
45
+ warnings.push("Intent is missing required fields (intent/intentCategory).");
46
+ }
47
+ if (typeof intent.confidence !== "number") {
48
+ warnings.push("Intent confidence not set or invalid.");
49
+ }
50
+ }
51
+ // -----------------------------
52
+ // Plan.targetFiles consistency validation
53
+ // -----------------------------
54
+ const plan = ctx.plan;
55
+ const workingFiles = new Set(ctx.workingFiles?.map(f => f.path) ?? []);
56
+ const targetFiles = new Set(plan?.targetFiles ?? []);
57
+ if (!plan) {
58
+ warnings.push("No plan found in context; target files were not validated.");
59
+ }
60
+ else {
61
+ // Only focused files that are also working files are expected to be in the plan
62
+ const expectedTargetFiles = focusFiles.filter(f => workingFiles.has(f));
63
+ const missing = expectedTargetFiles.filter(f => !targetFiles.has(f));
64
+ if (missing.length > 0) {
65
+ warnings.push(`Some focused working files were not added to plan.targetFiles: ${missing.join(", ")}`);
66
+ }
67
+ }
68
+ const output = {
69
+ query: input.query,
70
+ data: {
71
+ notes,
72
+ warnings,
73
+ summary: {
74
+ focusValid: focusFiles.length > 0,
75
+ semanticValid: !!understanding,
76
+ intentValid: !!intent,
77
+ planFilesValid: !!plan &&
78
+ focusFiles
79
+ .filter(f => workingFiles.has(f))
80
+ .every(f => targetFiles.has(f)),
81
+ },
82
+ },
83
+ };
84
+ logInputOutput("validationAnalysis", "output", output.data);
85
+ return output;
86
+ },
87
+ };
@@ -1,145 +1,76 @@
1
1
  import fs from 'fs';
2
- import path from 'path';
3
2
  import readline from 'readline';
4
- import { searchFiles, queryFiles } from '../db/fileIndex.js';
5
- import { sanitizeQueryForFts } from '../utils/sanitizeQuery.js';
6
- import { generate } from '../lib/generate.js';
7
- import { buildContextualPrompt } from '../utils/buildContextualPrompt.js';
8
- import { log } from '../utils/log.js';
9
- import { PROMPT_LOG_PATH, SCAI_HOME, RELATED_FILES_LIMIT, getIndexDir } from '../constants.js';
10
3
  import chalk from 'chalk';
4
+ import { searchFiles } from '../db/fileIndex.js';
5
+ import { sanitizeQueryForFts } from '../utils/sanitizeQuery.js';
6
+ import { NUM_TOPFILES, RELATED_FILES_LIMIT, getIndexDir } from '../constants.js';
7
+ import { MainAgent } from '../agents/MainAgent.js';
8
+ import { buildLightContext } from '../utils/buildContextualPrompt.js';
11
9
  export async function runAskCommand(query) {
12
- if (!query) {
10
+ // STEP 0: Get user query
11
+ if (!query)
13
12
  query = await promptOnce('šŸ’¬ Ask your question:\n');
14
- }
15
13
  query = query.trim();
16
14
  if (!query) {
17
15
  console.error('āŒ No question provided.\nšŸ‘‰ Usage: scai ask "your question"');
18
16
  return;
19
17
  }
20
18
  console.log(`šŸ“ Using index root: ${getIndexDir()}`);
21
- // Semantic Search
22
- const start = Date.now();
23
- const semanticResults = await searchFiles(query, RELATED_FILES_LIMIT);
24
- const duration = Date.now() - start;
25
- console.log(`ā±ļø searchFiles took ${duration}ms and returned ${semanticResults.length} result(s)`);
26
- semanticResults.forEach((file, i) => {
27
- console.log(` ${i + 1}. šŸ“„ Path: ${file.path} | Score: ${file.score?.toFixed(3) ?? 'n/a'}`);
28
- });
29
- // Fallback FTS search
19
+ // STEP 1: FTS Search
30
20
  const safeQuery = sanitizeQueryForFts(query);
31
- const fallbackResults = queryFiles(safeQuery, 10);
32
- fallbackResults.forEach((file, i) => {
33
- console.log(` ${i + 1}. šŸ”Ž Fallback Match: ${file.path}`);
34
- });
35
- // Merge results
36
- const seen = new Set();
37
- const combinedResults = [];
38
- for (const file of semanticResults) {
39
- const resolved = path.resolve(file.path);
40
- seen.add(resolved);
41
- combinedResults.push(file);
21
+ const start = Date.now();
22
+ const results = await searchFiles(safeQuery, RELATED_FILES_LIMIT);
23
+ console.log(`ā±ļø searchFiles took ${Date.now() - start}ms and returned ${results.length} result(s)`);
24
+ if (results.length === 0) {
25
+ console.log(chalk.redBright('āŒ No results found.'));
26
+ return;
42
27
  }
43
- for (const file of fallbackResults) {
44
- const resolved = path.resolve(file.path);
45
- if (!seen.has(resolved)) {
46
- seen.add(resolved);
47
- combinedResults.push({
48
- id: file.id,
49
- path: file.path,
50
- summary: file.summary || '',
51
- score: 0.0,
52
- sim: 0,
53
- bm25: 0
54
- });
28
+ // STEP 2: Build topFiles (with code)
29
+ const topResults = results.slice(0, NUM_TOPFILES);
30
+ const topFiles = topResults.map(r => {
31
+ let code = '';
32
+ try {
33
+ code = fs.readFileSync(r.path, 'utf-8');
55
34
  }
56
- }
57
- // Exact match prioritization
58
- const queryFilenameRaw = path.basename(query).toLowerCase();
59
- const queryFilenameNoExt = queryFilenameRaw.replace(/\.[^/.]+$/, '');
60
- const exactMatchIndex = combinedResults.findIndex(f => {
61
- const base = path.basename(f.path).toLowerCase();
62
- const baseNoExt = base.replace(/\.[^/.]+$/, '');
63
- return base === queryFilenameRaw || baseNoExt === queryFilenameNoExt;
64
- });
65
- if (exactMatchIndex !== -1) {
66
- const [exactMatch] = combinedResults.splice(exactMatchIndex, 1);
67
- combinedResults.unshift(exactMatch);
68
- console.log(`šŸŽÆ Exact match prioritized: ${exactMatch.path}`);
69
- }
70
- // Log combined results
71
- if (combinedResults.length) {
72
- console.log('\nšŸ“Š Final Related Files:');
73
- combinedResults.forEach((f, i) => {
74
- console.log(` ${i + 1}. ${f.path} (${f.score?.toFixed(3) ?? 'fallback'})`);
75
- });
76
- }
77
- else {
78
- console.log('āš ļø No similar files found. Using query only.');
79
- }
80
- // STEP 4+: Build contextual prompt using topFile + combinedResults
81
- if (combinedResults.length === 0) {
82
- throw new Error('āŒ No search results found. Cannot build contextual prompt.');
83
- }
84
- const file = combinedResults[0];
85
- let code = "";
86
- // STEP 4++: Add code to params
87
- try {
88
- code = fs.readFileSync(file.path, 'utf-8');
89
- if (!code) {
90
- console.warn(`āš ļø No code loaded for top file: ${file.path}`);
35
+ catch (err) {
36
+ console.warn(`āš ļø Failed to read file: ${r.path}`);
91
37
  }
92
- }
93
- catch (e) {
94
- console.log("Error reading code from selected file: ", e instanceof Error ? e.message : e);
95
- }
96
- const topFile = {
97
- id: file.id,
98
- path: file.path,
99
- summary: file.summary ?? "",
100
- code,
101
- };
38
+ return {
39
+ path: r.path,
40
+ summary: r.summary ?? undefined,
41
+ code,
42
+ };
43
+ });
44
+ console.log(chalk.greenBright(`šŸŽÆ Selected top ${topFiles.length} file(s):`));
45
+ topFiles.forEach(f => console.log(` → ${f.path}`));
46
+ // STEP 3: Related files (all results except topFiles)
47
+ const relatedFiles = results.slice(NUM_TOPFILES).map(f => ({
48
+ id: f.id,
49
+ path: f.path,
50
+ summary: f.summary ?? undefined,
51
+ }));
52
+ // STEP 4: Build context prompt
102
53
  const promptArgs = {
103
- topFile,
104
- relatedFiles: combinedResults,
54
+ topFiles,
55
+ relatedFiles,
105
56
  query,
106
57
  };
107
- console.log(chalk.blueBright('\nšŸ“¦ Building contextual prompt...'));
108
- const promptContent = await buildContextualPrompt(promptArgs);
109
- console.log(chalk.greenBright('āœ… Prompt built successfully.'));
110
- console.log(chalk.cyan(`[runAskCommand] Prompt token estimate: ~${Math.round(promptContent.length / 4)} tokens`));
111
- // STEP 5: Save prompt
58
+ const context = await buildLightContext(promptArgs);
59
+ // STEP 5: Run agent
112
60
  try {
113
- if (!fs.existsSync(SCAI_HOME))
114
- fs.mkdirSync(SCAI_HOME, { recursive: true });
115
- fs.writeFileSync(PROMPT_LOG_PATH, promptContent, 'utf-8');
116
- log(`šŸ“ Prompt saved to ${PROMPT_LOG_PATH}`);
61
+ console.log('\nšŸ¤– Launching autonomous agent...');
62
+ const agent = new MainAgent(context);
63
+ await agent.run();
117
64
  }
118
65
  catch (err) {
119
- log('āŒ Failed to write prompt log:', err);
120
- }
121
- // STEP 6: Ask model
122
- try {
123
- console.log('\nšŸ¤– Asking the model...');
124
- const input = {
125
- content: promptContent,
126
- filepath: topFile.path,
127
- };
128
- const modelResponse = await generate(input);
129
- console.log(`\n🧠 Model Response:\n${modelResponse.content}`);
130
- }
131
- catch (err) {
132
- console.error('āŒ Model request failed:', err);
66
+ console.error('āŒ Autonomous agent run failed:', err);
133
67
  }
134
68
  }
135
- // Helper: Prompt once
69
+ // helper
136
70
  function promptOnce(promptText) {
137
71
  return new Promise(resolve => {
138
72
  console.log(promptText);
139
- const rl = readline.createInterface({
140
- input: process.stdin,
141
- output: process.stdout,
142
- });
73
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
143
74
  rl.question('> ', answer => {
144
75
  rl.close();
145
76
  resolve(answer.trim());
@@ -7,7 +7,6 @@ import { changelogModule } from '../pipeline/modules/changeLogModule.js';
7
7
  import { askChangelogApproval } from '../utils/changeLogPrompt.js';
8
8
  import { openTextEditor } from '../utils/editor.js';
9
9
  export async function handleStandaloneChangelogUpdate() {
10
- // Don't bother with diffs at all here
11
10
  let entry = await generateChangelogEntry();
12
11
  if (!entry) {
13
12
  console.log('āš ļø No significant changes found.');
@@ -51,8 +50,16 @@ export async function generateChangelogEntry(currentCommitMsg) {
51
50
  console.log("āš ļø No commits found since last release.");
52
51
  return null;
53
52
  }
54
- const result = await runModulePipeline([changelogModule], { content: commits });
55
- const output = result?.summary?.trim();
53
+ // --- ModuleIO usage ---
54
+ const result = await runModulePipeline([changelogModule], {
55
+ query: 'generate changelog entry',
56
+ content: commits
57
+ });
58
+ const output = result?.data
59
+ ? typeof result.data === 'string'
60
+ ? result.data.trim()
61
+ : JSON.stringify(result.data, null, 2)
62
+ : null;
56
63
  if (!output || output === 'NO UPDATE') {
57
64
  console.log('āš ļø No significant changes detected for changelog.');
58
65
  return null;
@@ -69,11 +76,10 @@ function getLastGitTag() {
69
76
  return execSync('git describe --tags --abbrev=0', { encoding: 'utf-8' }).trim();
70
77
  }
71
78
  catch {
72
- return null; // no tags found
79
+ return null;
73
80
  }
74
81
  }
75
82
  function getCommitsSinceTag(tag) {
76
- // Get commit messages in a simple format, e.g. only commit messages
77
83
  return execSync(`git log ${tag}..HEAD --pretty=format:%s`, { encoding: 'utf-8' }).trim();
78
84
  }
79
85
  export async function updateChangelogFile(entry) {