scai 0.1.65 ā 0.1.67
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/dist/commands/AskCmd.js +34 -12
- package/dist/constants.js +4 -0
- package/dist/utils/buildContextualPrompt.js +43 -7
- package/package.json +1 -1
package/dist/commands/AskCmd.js
CHANGED
|
@@ -7,7 +7,8 @@ import { generate } from '../lib/generate.js';
|
|
|
7
7
|
import { buildContextualPrompt } from '../utils/buildContextualPrompt.js';
|
|
8
8
|
import { generateFocusedFileTree } from '../utils/fileTree.js';
|
|
9
9
|
import { log } from '../utils/log.js';
|
|
10
|
-
import { PROMPT_LOG_PATH, SCAI_HOME, RELATED_FILES_LIMIT, MAX_SUMMARY_LINES, getIndexDir } from '../constants.js';
|
|
10
|
+
import { PROMPT_LOG_PATH, SCAI_HOME, RELATED_FILES_LIMIT, MAX_SUMMARY_LINES, getIndexDir, MAX_FUNCTION_LINES } from '../constants.js';
|
|
11
|
+
import chalk from 'chalk';
|
|
11
12
|
export async function runAskCommand(query) {
|
|
12
13
|
if (!query) {
|
|
13
14
|
query = await promptOnce('š¬ Ask your question:\n');
|
|
@@ -33,7 +34,7 @@ export async function runAskCommand(query) {
|
|
|
33
34
|
fallbackResults.forEach((file, i) => {
|
|
34
35
|
console.log(` ${i + 1}. š Fallback Match: ${file.path}`);
|
|
35
36
|
});
|
|
36
|
-
// š© STEP 2: Merge results
|
|
37
|
+
// š© STEP 2: Merge results
|
|
37
38
|
const seen = new Set();
|
|
38
39
|
const combinedResults = [];
|
|
39
40
|
for (const file of semanticResults) {
|
|
@@ -71,33 +72,49 @@ export async function runAskCommand(query) {
|
|
|
71
72
|
let code = '';
|
|
72
73
|
let topSummary = topFile.summary || '(No summary available)';
|
|
73
74
|
let topFunctions = [];
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
75
|
+
const fileFunctions = {};
|
|
76
|
+
// Truncate summary
|
|
77
|
+
topSummary = topSummary.split('\n').slice(0, MAX_SUMMARY_LINES).join('\n');
|
|
78
78
|
const allFileIds = combinedResults
|
|
79
79
|
.map(file => file.id)
|
|
80
80
|
.filter((id) => typeof id === 'number');
|
|
81
|
-
const allFunctionsMap = getFunctionsForFiles(allFileIds);
|
|
81
|
+
const allFunctionsMap = getFunctionsForFiles(allFileIds); // Record<number, Function[]>
|
|
82
82
|
try {
|
|
83
83
|
code = fs.readFileSync(filepath, 'utf-8');
|
|
84
84
|
const topFileId = topFile.id;
|
|
85
|
-
topFunctions = allFunctionsMap[topFileId]?.map(fn =>
|
|
85
|
+
topFunctions = allFunctionsMap[topFileId]?.map(fn => {
|
|
86
|
+
const content = fn.content
|
|
87
|
+
? fn.content.split('\n').slice(0, MAX_FUNCTION_LINES).join('\n')
|
|
88
|
+
: '(No content available)';
|
|
89
|
+
return {
|
|
90
|
+
name: fn.name,
|
|
91
|
+
content,
|
|
92
|
+
};
|
|
93
|
+
}) || [];
|
|
86
94
|
}
|
|
87
95
|
catch (err) {
|
|
88
96
|
console.warn(`ā ļø Failed to read or analyze top file (${filepath}):`, err);
|
|
89
97
|
}
|
|
90
|
-
// š© STEP 5: Build relatedFiles with functions
|
|
98
|
+
// š© STEP 5: Build relatedFiles with functions and fileFunctions
|
|
91
99
|
const relatedFiles = combinedResults.slice(0, RELATED_FILES_LIMIT).map(file => {
|
|
92
100
|
const fileId = file.id;
|
|
93
101
|
let summary = file.summary || '(No summary available)';
|
|
94
102
|
if (summary) {
|
|
95
103
|
summary = summary.split('\n').slice(0, MAX_SUMMARY_LINES).join('\n');
|
|
96
104
|
}
|
|
105
|
+
const functions = allFunctionsMap[fileId]?.map(fn => {
|
|
106
|
+
const content = fn.content
|
|
107
|
+
? fn.content.split('\n').slice(0, MAX_FUNCTION_LINES).join('\n')
|
|
108
|
+
: '(No content available)';
|
|
109
|
+
return {
|
|
110
|
+
name: fn.name,
|
|
111
|
+
content,
|
|
112
|
+
};
|
|
113
|
+
}) || [];
|
|
97
114
|
return {
|
|
98
115
|
path: file.path,
|
|
99
116
|
summary,
|
|
100
|
-
functions
|
|
117
|
+
functions,
|
|
101
118
|
};
|
|
102
119
|
});
|
|
103
120
|
// š© STEP 6: Generate file tree
|
|
@@ -109,6 +126,8 @@ export async function runAskCommand(query) {
|
|
|
109
126
|
console.warn('ā ļø Could not generate file tree:', e);
|
|
110
127
|
}
|
|
111
128
|
// š© STEP 7: Build prompt
|
|
129
|
+
console.log(chalk.blueBright('\nš¦ Building contextual prompt...'));
|
|
130
|
+
console.log(chalk.gray(`[runAskCommand] Calling buildContextualPrompt()`));
|
|
112
131
|
const promptContent = buildContextualPrompt({
|
|
113
132
|
baseInstruction: query,
|
|
114
133
|
code,
|
|
@@ -116,8 +135,11 @@ export async function runAskCommand(query) {
|
|
|
116
135
|
functions: topFunctions,
|
|
117
136
|
relatedFiles,
|
|
118
137
|
projectFileTree: fileTree || undefined,
|
|
138
|
+
fileFunctions,
|
|
119
139
|
});
|
|
120
|
-
|
|
140
|
+
console.log(chalk.greenBright('ā
Prompt built successfully.'));
|
|
141
|
+
console.log(chalk.cyan(`[runAskCommand] Prompt token estimate: ~${Math.round(promptContent.length / 4)} tokens`));
|
|
142
|
+
// š© STEP 8: Save prompt
|
|
121
143
|
try {
|
|
122
144
|
if (!fs.existsSync(SCAI_HOME))
|
|
123
145
|
fs.mkdirSync(SCAI_HOME, { recursive: true });
|
|
@@ -144,7 +166,7 @@ export async function runAskCommand(query) {
|
|
|
144
166
|
// š© Helper: Prompt once
|
|
145
167
|
function promptOnce(promptText) {
|
|
146
168
|
return new Promise(resolve => {
|
|
147
|
-
console.log(promptText);
|
|
169
|
+
console.log(promptText);
|
|
148
170
|
const rl = readline.createInterface({
|
|
149
171
|
input: process.stdin,
|
|
150
172
|
output: process.stdout,
|
package/dist/constants.js
CHANGED
|
@@ -1,20 +1,56 @@
|
|
|
1
|
-
|
|
1
|
+
// File: src/utils/buildContextualPrompt.ts
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
function estimateTokenCount(text) {
|
|
4
|
+
return Math.round(text.length / 4); // simple heuristic approximation
|
|
5
|
+
}
|
|
6
|
+
export function buildContextualPrompt({ baseInstruction, code, summary, functions, relatedFiles, projectFileTree, }) {
|
|
2
7
|
const parts = [baseInstruction];
|
|
3
8
|
if (summary) {
|
|
4
9
|
parts.push(`š File Summary:\n${summary}`);
|
|
5
10
|
}
|
|
6
11
|
if (functions?.length) {
|
|
7
|
-
|
|
12
|
+
const formattedFunctions = functions
|
|
13
|
+
.map(fn => `⢠${fn.name}:\n${fn.content}`)
|
|
14
|
+
.join('\n\n');
|
|
15
|
+
parts.push(`š§ Functions:\n${formattedFunctions}`);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
console.log(chalk.gray(`[buildContextualPrompt]`) +
|
|
19
|
+
chalk.yellow(` ā ļø No functions found in top file.`));
|
|
8
20
|
}
|
|
9
21
|
if (relatedFiles?.length) {
|
|
10
|
-
const
|
|
11
|
-
.map(f =>
|
|
12
|
-
.
|
|
13
|
-
|
|
22
|
+
const formattedRelatedFiles = relatedFiles
|
|
23
|
+
.map(f => {
|
|
24
|
+
const relatedFunctions = f.functions
|
|
25
|
+
.map(fn => ` ⢠${fn.name}:\n ${fn.content}`)
|
|
26
|
+
.join('\n\n');
|
|
27
|
+
return `⢠${f.path}: ${f.summary}\n${relatedFunctions}`;
|
|
28
|
+
})
|
|
29
|
+
.join('\n\n');
|
|
30
|
+
parts.push(`š Related Files:\n${formattedRelatedFiles}`);
|
|
14
31
|
}
|
|
15
32
|
if (projectFileTree) {
|
|
16
33
|
parts.push(`š Project File Structure:\n\`\`\`\n${projectFileTree.trim()}\n\`\`\``);
|
|
17
34
|
}
|
|
18
35
|
parts.push(`\n--- CODE START ---\n${code}\n--- CODE END ---`);
|
|
19
|
-
|
|
36
|
+
const prompt = parts.join('\n\n');
|
|
37
|
+
const tokenEstimate = estimateTokenCount(prompt);
|
|
38
|
+
// šµ Colorized diagnostic output
|
|
39
|
+
const header = chalk.bgBlue.white.bold(' [SCAI] Prompt Overview ');
|
|
40
|
+
const labelColor = chalk.cyan;
|
|
41
|
+
const contentColor = chalk.gray;
|
|
42
|
+
console.log('\n' + header);
|
|
43
|
+
console.log(labelColor('š¢ Token Estimate:'), contentColor(`${tokenEstimate.toLocaleString()} tokens`));
|
|
44
|
+
console.log(labelColor('š§© Prompt Sections:'));
|
|
45
|
+
console.log(contentColor([
|
|
46
|
+
summary ? 'š Summary' : null,
|
|
47
|
+
functions?.length ? 'š§ Functions' : null,
|
|
48
|
+
relatedFiles?.length ? 'š Related Files' : null,
|
|
49
|
+
projectFileTree ? 'š File Tree' : null,
|
|
50
|
+
'š¦ Code',
|
|
51
|
+
]
|
|
52
|
+
.filter(Boolean)
|
|
53
|
+
.join(', ')));
|
|
54
|
+
console.log(labelColor('š Key:'), contentColor('[buildContextualPrompt]\n'));
|
|
55
|
+
return prompt;
|
|
20
56
|
}
|