scai 0.1.57 → 0.1.58
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.
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Project, SyntaxKind } from 'ts-morph';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { generateEmbedding } from '../../lib/generateEmbedding.js';
|
|
4
|
+
import { log } from '../../utils/log.js';
|
|
5
|
+
import { getDbForRepo } from '../client.js';
|
|
6
|
+
import { markFileAsSkippedTemplate, markFileAsExtractedTemplate, markFileAsFailedTemplate } from '../sqlTemplates.js';
|
|
7
|
+
export async function extractFromTS(filePath, content, fileId) {
|
|
8
|
+
const db = getDbForRepo();
|
|
9
|
+
try {
|
|
10
|
+
const project = new Project({ useInMemoryFileSystem: true });
|
|
11
|
+
const sourceFile = project.createSourceFile(filePath, content);
|
|
12
|
+
const functions = [];
|
|
13
|
+
const allFuncs = [
|
|
14
|
+
...sourceFile.getDescendantsOfKind(SyntaxKind.FunctionDeclaration),
|
|
15
|
+
...sourceFile.getDescendantsOfKind(SyntaxKind.FunctionExpression),
|
|
16
|
+
...sourceFile.getDescendantsOfKind(SyntaxKind.ArrowFunction),
|
|
17
|
+
];
|
|
18
|
+
for (const fn of allFuncs) {
|
|
19
|
+
const name = fn.getSymbol()?.getName() ?? `${path.basename(filePath)}:<anon>`;
|
|
20
|
+
const start = fn.getStartLineNumber();
|
|
21
|
+
const end = fn.getEndLineNumber();
|
|
22
|
+
const code = fn.getText();
|
|
23
|
+
functions.push({ name, start_line: start, end_line: end, content: code });
|
|
24
|
+
}
|
|
25
|
+
if (functions.length === 0) {
|
|
26
|
+
log(`⚠️ No functions found in TS file: ${filePath}`);
|
|
27
|
+
db.prepare(markFileAsSkippedTemplate).run({ id: fileId });
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
log(`🔍 Found ${functions.length} TypeScript functions in ${filePath}`);
|
|
31
|
+
for (const fn of functions) {
|
|
32
|
+
const embedding = await generateEmbedding(fn.content);
|
|
33
|
+
const result = db.prepare(`
|
|
34
|
+
INSERT INTO functions (
|
|
35
|
+
file_id, name, start_line, end_line, content, embedding, lang
|
|
36
|
+
) VALUES (
|
|
37
|
+
@file_id, @name, @start_line, @end_line, @content, @embedding, @lang
|
|
38
|
+
)
|
|
39
|
+
`).run({
|
|
40
|
+
file_id: fileId,
|
|
41
|
+
name: fn.name,
|
|
42
|
+
start_line: fn.start_line,
|
|
43
|
+
end_line: fn.end_line,
|
|
44
|
+
content: fn.content,
|
|
45
|
+
embedding: JSON.stringify(embedding),
|
|
46
|
+
lang: 'ts'
|
|
47
|
+
});
|
|
48
|
+
const callerId = result.lastInsertRowid;
|
|
49
|
+
// Simplified call detection (no walking for now)
|
|
50
|
+
const callMatches = fn.content.matchAll(/(\w+)\s*\(/g);
|
|
51
|
+
for (const match of callMatches) {
|
|
52
|
+
db.prepare(`
|
|
53
|
+
INSERT INTO function_calls (caller_id, callee_name)
|
|
54
|
+
VALUES (@caller_id, @callee_name)
|
|
55
|
+
`).run({
|
|
56
|
+
caller_id: callerId,
|
|
57
|
+
callee_name: match[1],
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
log(`📌 Indexed TS function: ${fn.name}`);
|
|
61
|
+
}
|
|
62
|
+
db.prepare(markFileAsExtractedTemplate).run({ id: fileId });
|
|
63
|
+
log(`✅ Marked TS functions as extracted for ${filePath}`);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
log(`❌ Failed to extract from TS file: ${filePath}`);
|
|
68
|
+
log(` ↳ ${String(err.message)}`);
|
|
69
|
+
db.prepare(markFileAsFailedTemplate).run({ id: fileId });
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -5,6 +5,7 @@ import { extractFromJS } from './extractFromJs.js';
|
|
|
5
5
|
import { extractFromXML } from './extractFromXML.js';
|
|
6
6
|
import { getDbForRepo } from '../client.js';
|
|
7
7
|
import { markFileAsFailedTemplate, markFileAsSkippedByPath } from '../sqlTemplates.js';
|
|
8
|
+
import { extractFromTS } from './extractFromTs.js';
|
|
8
9
|
/**
|
|
9
10
|
* Detects file type and delegates to the appropriate extractor.
|
|
10
11
|
*/
|
|
@@ -12,10 +13,14 @@ export async function extractFunctionsFromFile(filePath, content, fileId) {
|
|
|
12
13
|
const type = detectFileType(filePath).trim().toLowerCase();
|
|
13
14
|
const db = getDbForRepo();
|
|
14
15
|
try {
|
|
15
|
-
if (type === 'js' || type === '
|
|
16
|
+
if (type === 'js' || type === 'javascript') {
|
|
16
17
|
log(`✅ Attempting to extract JS functions from ${filePath}`);
|
|
17
18
|
return await extractFromJS(filePath, content, fileId);
|
|
18
19
|
}
|
|
20
|
+
if (type === 'ts' || type === 'typescript') {
|
|
21
|
+
log(`📘 Extracting TS functions from ${filePath}`);
|
|
22
|
+
return await extractFromTS(filePath, content, fileId);
|
|
23
|
+
}
|
|
19
24
|
if (type === 'java') {
|
|
20
25
|
log(`❌ Nothing extracted for ${filePath} due to missing implementation`);
|
|
21
26
|
await extractFromJava(filePath, content, fileId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.58",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"scai": "./dist/index.js"
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"commander": "^11.0.0",
|
|
45
45
|
"fast-glob": "^3.3.3",
|
|
46
46
|
"proper-lockfile": "^4.1.2",
|
|
47
|
-
"string-similarity-js": "^2.1.4"
|
|
47
|
+
"string-similarity-js": "^2.1.4",
|
|
48
|
+
"ts-morph": "^26.0.0"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@types/better-sqlite3": "^7.6.13",
|