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
@@ -1,41 +1,33 @@
1
- import { Config } from '../../config.js';
2
- import { generate } from '../../lib/generate.js';
3
- import path from 'path';
1
+ import { generate } from "../../lib/generate.js";
2
+ import { logInputOutput } from "../../utils/promptLogHelper.js";
4
3
  export const summaryModule = {
5
- name: 'summary',
6
- description: 'Generates a general summary of any file content.',
7
- run: async ({ content, filepath }) => {
8
- const model = Config.getModel();
9
- const ext = filepath ? path.extname(filepath).toLowerCase() : '';
10
- const filename = filepath ? path.basename(filepath) : '';
4
+ name: "summary",
5
+ description: "Generates a general summary of any file content.",
6
+ groups: ["analysis"],
7
+ run: async (input) => {
8
+ // Only care about content now
9
+ const contentStr = typeof input.content === "string"
10
+ ? input.content
11
+ : JSON.stringify(input.content ?? "", null, 2);
12
+ // ❌ Removed filepath/ext/filename extraction
11
13
  const prompt = `
12
14
  You are an assistant specialized in summarizing files.
13
15
 
14
- Your task is to summarize the contents of the following file as clearly and concisely as possible.
16
+ Your task is to summarize the following content as clearly and concisely as possible:
15
17
 
16
- File: ${filename}
17
- Extension: ${ext}
18
-
19
- 📋 Instructions:
20
- - Identify the main topic and purpose of the file
21
- - Summarize key content and sections
22
- - Mention any technical, legal, or structural info if relevant
23
- - Do NOT include the raw content or repeat lines from it
24
- - Return a human-readable bullet-point summary
25
-
26
- --- FILE CONTENT START ---
27
- ${content}
28
- --- FILE CONTENT END ---
29
- `.trim();
30
- const response = await generate({ content: prompt, filepath });
31
- if (response.content) {
32
- response.summary = response.content;
33
- console.log('\n📝 Summary:\n');
34
- console.log(response.summary);
35
- }
36
- else {
37
- console.warn('⚠️ No summary generated.');
38
- }
39
- return response;
40
- }
18
+ ${contentStr}
19
+ `.trim();
20
+ const response = await generate({
21
+ content: prompt,
22
+ query: ""
23
+ });
24
+ const summary = response.data ?? "⚠️ No summary generated.";
25
+ const output = {
26
+ query: input.query, // keep query for context
27
+ content: '',
28
+ data: { summary }, // ❌ no filepath
29
+ };
30
+ logInputOutput("summary", "output", output.data);
31
+ return output;
32
+ },
41
33
  };
@@ -0,0 +1,86 @@
1
+ // File: src/modules/writeFileModule.ts
2
+ import fs from "fs/promises";
3
+ import chalk from "chalk";
4
+ import { normalizePath } from "../../utils/contentUtils.js";
5
+ import { logInputOutput } from "../../utils/promptLogHelper.js";
6
+ export const writeFileModule = {
7
+ name: "writeFile",
8
+ description: "Writes materialized file outputs from codeTransformModule to disk. " +
9
+ "Only writes files specified in the current plan step.",
10
+ groups: ["finalize"],
11
+ run: async (input) => {
12
+ var _a;
13
+ const context = input.context;
14
+ const mode = input.data?.mode ?? "overwrite";
15
+ if (!context) {
16
+ return {
17
+ query: input.query,
18
+ data: { writeMode: mode, writtenFiles: [], errors: ["Missing execution context"] },
19
+ };
20
+ }
21
+ const step = context.currentStep;
22
+ if (!step) {
23
+ return {
24
+ query: input.query,
25
+ data: { writeMode: mode, writtenFiles: [], errors: ["No current step in context"] },
26
+ };
27
+ }
28
+ // Determine target file(s) from the current step
29
+ const targetFiles = [];
30
+ if (step.targetFile)
31
+ targetFiles.push(step.targetFile);
32
+ if (Array.isArray(step.targetFiles))
33
+ targetFiles.push(...step.targetFiles);
34
+ if (!targetFiles.length) {
35
+ return {
36
+ query: input.query,
37
+ data: { writeMode: mode, writtenFiles: [], errors: ["No targetFile(s) specified in current step"] },
38
+ };
39
+ }
40
+ // Filter codeTransformArtifacts to only the target file(s)
41
+ const allFiles = context.execution?.codeTransformArtifacts?.files ?? [];
42
+ const filesToWrite = allFiles.filter(f => targetFiles.includes(f.filePath));
43
+ if (!filesToWrite.length) {
44
+ return {
45
+ query: input.query,
46
+ data: { writeMode: mode, writtenFiles: [], errors: ["No transformed files found for targetFile(s)"] },
47
+ };
48
+ }
49
+ const writtenFiles = [];
50
+ const errors = [];
51
+ for (const f of filesToWrite) {
52
+ const filePath = normalizePath(f.filePath);
53
+ if (!filePath) {
54
+ errors.push(`Invalid filePath: ${f.filePath}`);
55
+ continue;
56
+ }
57
+ if (typeof f.content !== "string" || !f.content.trim()) {
58
+ errors.push(`No content to write for ${filePath}`);
59
+ continue;
60
+ }
61
+ try {
62
+ await fs.writeFile(filePath, f.content, "utf-8");
63
+ console.log(chalk.green(`✅ Written: ${filePath}`));
64
+ writtenFiles.push(filePath);
65
+ }
66
+ catch (err) {
67
+ console.error(chalk.red(`❌ Failed writing ${filePath}:`), err);
68
+ errors.push(`${filePath}: ${err.message}`);
69
+ }
70
+ }
71
+ // Mark only the files we just wrote as touched
72
+ context.plan ?? (context.plan = {});
73
+ (_a = context.plan).touchedFiles ?? (_a.touchedFiles = []);
74
+ for (const file of writtenFiles) {
75
+ if (!context.plan.touchedFiles.includes(file)) {
76
+ context.plan.touchedFiles.push(file);
77
+ }
78
+ }
79
+ const output = {
80
+ query: input.query,
81
+ data: { writeMode: mode, writtenFiles, errors },
82
+ };
83
+ logInputOutput("writeFile", "output", output.data);
84
+ return output;
85
+ },
86
+ };
@@ -1,110 +1,55 @@
1
- import { addCommentsModule } from '../modules/commentModule.js';
2
- import { cleanupModule } from '../modules/cleanupModule.js';
3
- import { summaryModule } from '../modules/summaryModule.js';
4
- import { generateTestsModule } from '../modules/generateTestsModule.js';
5
- import { commitSuggesterModule } from '../modules/commitSuggesterModule.js';
6
- import { changelogModule } from '../modules/changeLogModule.js';
7
- import { cleanGeneratedTestsModule } from '../modules/cleanGeneratedTestsModule.js';
8
- import { preserveCodeModule } from '../modules/preserveCodeModule.js';
9
- import { runTestsModule } from '../modules/runTestsModule.js';
10
- import { repairTestsModule } from '../modules/repairTestsModule.js';
11
- // Built-in modules with metadata
1
+ import { contextReviewModule } from "../modules/contextReviewModule.js";
2
+ import { finalAnswerModule } from "../modules/finalAnswerModule.js";
3
+ import { writeFileModule } from "../modules/writeFileModule.js";
4
+ import { fileSearchModule } from "../modules/fileSearchModule.js";
5
+ import { cleanupModule } from "../modules/cleanupModule.js";
6
+ import { summaryModule } from "../modules/summaryModule.js";
7
+ import { addCommentsModule } from "../modules/commentModule.js";
8
+ import { codeTransformModule } from "../modules/codeTransformModule.js";
9
+ /**
10
+ * Active built-in modules — all use ModuleIO for input/output.
11
+ */
12
12
  export const builtInModules = {
13
- comments: {
14
- ...addCommentsModule,
15
- group: 'documentation',
16
- dependencies: {
17
- after: ['cleanComments'], // run cleanComments after comments
18
- },
19
- },
20
- cleanComments: {
21
- ...preserveCodeModule,
22
- group: 'documentation',
23
- },
24
- cleanup: {
25
- ...cleanupModule,
26
- group: 'maintenance',
27
- },
28
- summary: {
29
- ...summaryModule,
30
- group: 'documentation',
31
- },
32
- tests: {
33
- ...generateTestsModule,
34
- group: 'testing',
35
- dependencies: {
36
- after: ['cleanTests'], // run cleanTests after tests
37
- },
38
- },
39
- cleanTests: {
40
- ...cleanGeneratedTestsModule,
41
- group: 'testing',
42
- },
43
- runTests: {
44
- ...runTestsModule,
45
- group: 'testing',
46
- dependencies: {
47
- before: ['tests'], // must exist after tests are generated
48
- after: ['cleanTests'], // run after cleaning
49
- },
50
- },
51
- repairTests: {
52
- ...repairTestsModule,
53
- group: 'testing',
54
- dependencies: {
55
- after: ['runTests'], // repair runs after tests have been executed
56
- },
57
- },
58
- suggest: {
59
- ...commitSuggesterModule,
60
- group: 'git',
61
- },
62
- changelog: {
63
- ...changelogModule,
64
- group: 'git',
65
- },
13
+ fileSearch: fileSearchModule,
14
+ summary: summaryModule,
15
+ contextReview: contextReviewModule,
16
+ // analysis (as agent options?)
17
+ codeTransform: codeTransformModule,
18
+ cleanup: cleanupModule,
19
+ comments: addCommentsModule,
20
+ writeFile: writeFileModule,
21
+ finalAnswer: finalAnswerModule,
66
22
  };
67
- // Get module by name
23
+ /**
24
+ * Get module by name.
25
+ */
68
26
  export function getModuleByName(name) {
69
27
  return builtInModules[name];
70
28
  }
71
- // Return module metadata for CLI or UI
29
+ /**
30
+ * List available modules for CLI or UI display.
31
+ */
72
32
  export function listAvailableModules() {
73
- return Object.values(builtInModules).map(({ name, description, group, dependencies }) => ({
33
+ return Object.entries(builtInModules).map(([name, mod]) => ({
74
34
  name,
75
- description: description || 'No description available',
76
- group,
77
- dependencies,
35
+ description: mod.description ?? "No description available",
78
36
  }));
79
37
  }
80
38
  /**
81
- * Resolve module execution order including before/after dependencies.
82
- * Returns a unique ordered array of PromptModuleMeta.
39
+ * Resolve modules from a list of names.
40
+ * Returns a unique ordered array of modules.
83
41
  */
84
- export function resolveModuleOrder(moduleNames) {
42
+ export function resolveModulesByNames(names) {
43
+ const seen = new Set();
85
44
  const resolved = [];
86
- const visited = new Set();
87
- function visit(name) {
88
- if (visited.has(name))
89
- return;
45
+ for (const name of names) {
46
+ if (seen.has(name))
47
+ continue;
90
48
  const mod = getModuleByName(name);
91
- if (!mod)
92
- return;
93
- // Handle before dependencies first
94
- if (mod.dependencies?.before) {
95
- for (const dep of mod.dependencies.before)
96
- visit(dep);
97
- }
98
- // Add the module itself
99
- resolved.push(mod);
100
- visited.add(name);
101
- // Handle after dependencies
102
- if (mod.dependencies?.after) {
103
- for (const dep of mod.dependencies.after)
104
- visit(dep);
49
+ if (mod) {
50
+ resolved.push(mod);
51
+ seen.add(name);
105
52
  }
106
53
  }
107
- for (const name of moduleNames)
108
- visit(name);
109
54
  return resolved;
110
55
  }
@@ -1,27 +1,30 @@
1
- import chalk from 'chalk';
2
- export async function runModulePipeline(modules, input) {
3
- let current = input;
4
- const isDebug = false;
1
+ export async function runModulePipeline(modules, initialInput) {
2
+ const logPrefix = `[runModulePipeline]`;
3
+ console.log(`${logPrefix} 🚀 Starting pipeline with ${modules.length} module(s)`);
4
+ // Copy initial input
5
+ let currentIO = { ...initialInput };
5
6
  for (const mod of modules) {
6
7
  try {
7
- if (isDebug)
8
- console.log(current.filepath);
9
- const response = await mod.run(current);
10
- console.log(`⚙️ Running: ${mod.name}`);
11
- if (isDebug) {
12
- console.log(chalk.yellow('➡️ Output:', response.content));
8
+ const output = await mod.run(currentIO);
9
+ // Validate shape
10
+ if (!output) {
11
+ throw new Error(`Module '${mod.name}' returned empty output`);
13
12
  }
14
- // Safeguard to preserve filepath + originalContent
15
- current = {
16
- ...response,
17
- originalContent: current.originalContent,
18
- filepath: current.filepath,
13
+ // --- FIX: Pipeline semantics ---
14
+ // Next module receives:
15
+ // - same query
16
+ // - content = previous module's data
17
+ // - (data is the last produced data only, never merged)
18
+ currentIO = {
19
+ query: currentIO.query,
20
+ content: output.data, // data -> content handoff
21
+ data: '',
19
22
  };
23
+ console.log(`${logPrefix} 🔁 '${mod.name}' → content replaced with data`);
20
24
  }
21
- catch (error) {
22
- console.error(`❌ Error in ${mod.name}:`, error instanceof Error ? error.message : error);
23
- throw new Error(`Pipeline failed at module ${mod.name}`);
25
+ catch (err) {
26
+ console.error(`${logPrefix} Module '${mod.name}' failed:`, err instanceof Error ? err.message : err);
24
27
  }
25
28
  }
26
- return current;
29
+ return currentIO;
27
30
  }