jinzd-ai-cli 0.4.74 → 0.4.76
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 +6 -1
- package/dist/{chunk-BT2TCINO.js → chunk-2Q77FT3F.js} +12 -3
- package/dist/{chunk-265H5S5H.js → chunk-34NJTPWZ.js} +12 -3
- package/dist/chunk-6VRJGH25.js +115 -0
- package/dist/chunk-BJAT4GNC.js +113 -0
- package/dist/{chunk-VG3MFZYG.js → chunk-H4DQNZZ6.js} +1 -1
- package/dist/{chunk-FKVJRBPO.js → chunk-K3JJX2Z5.js} +1 -1
- package/dist/{chunk-D5ZDVEJJ.js → chunk-KR4FTJWB.js} +234 -4
- package/dist/chunk-NHNWUBXB.js +431 -0
- package/dist/chunk-RFQVUMDB.js +430 -0
- package/dist/{chunk-PLJUAA3J.js → chunk-XTH7S3AM.js} +2 -2
- package/dist/{hub-ABCHM2OR.js → hub-YPNEYO3Z.js} +1 -1
- package/dist/index.js +93 -14
- package/dist/{run-tests-FMEFXUGO.js → run-tests-2I5S24IH.js} +1 -1
- package/dist/{run-tests-HBLD2R6B.js → run-tests-MKKCDUUV.js} +2 -2
- package/dist/{server-NMMRIWT2.js → server-6MPBAH4K.js} +66 -12
- package/dist/{task-orchestrator-24UUKJW5.js → task-orchestrator-I5HPXTJY.js} +5 -3
- package/dist/wasm/tree-sitter-javascript.wasm +0 -0
- package/dist/wasm/tree-sitter-python.wasm +0 -0
- package/dist/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/wasm/web-tree-sitter.wasm +0 -0
- package/dist/web/client/app.js +142 -0
- package/dist/web/client/index.html +12 -0
- package/dist/web/client/style.css +71 -0
- package/package.json +9 -2
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
detectLanguage,
|
|
4
|
+
emptyIndex,
|
|
5
|
+
loadIndex,
|
|
6
|
+
removeFile,
|
|
7
|
+
saveIndex,
|
|
8
|
+
upsertFileSymbols
|
|
9
|
+
} from "./chunk-6VRJGH25.js";
|
|
10
|
+
|
|
11
|
+
// src/symbols/indexer.ts
|
|
12
|
+
import fs2 from "fs";
|
|
13
|
+
import path3 from "path";
|
|
14
|
+
|
|
15
|
+
// src/symbols/parser.ts
|
|
16
|
+
import path2 from "path";
|
|
17
|
+
|
|
18
|
+
// src/symbols/loader.ts
|
|
19
|
+
import { Parser, Language } from "web-tree-sitter";
|
|
20
|
+
import { createRequire } from "module";
|
|
21
|
+
import path from "path";
|
|
22
|
+
import fs from "fs";
|
|
23
|
+
import { fileURLToPath } from "url";
|
|
24
|
+
var _metaUrl = import.meta?.url;
|
|
25
|
+
var _cjsFilename = globalThis.__filename;
|
|
26
|
+
var __filename_ = _metaUrl ? fileURLToPath(_metaUrl) : _cjsFilename ?? process.execPath;
|
|
27
|
+
var __dirname_ = path.dirname(__filename_);
|
|
28
|
+
var require_ = _metaUrl ? createRequire(_metaUrl) : createRequire(__filename_);
|
|
29
|
+
var GRAMMAR_FILE = {
|
|
30
|
+
typescript: "tree-sitter-typescript.wasm",
|
|
31
|
+
tsx: "tree-sitter-tsx.wasm",
|
|
32
|
+
javascript: "tree-sitter-javascript.wasm",
|
|
33
|
+
python: "tree-sitter-python.wasm"
|
|
34
|
+
};
|
|
35
|
+
var RUNTIME_WASM = "web-tree-sitter.wasm";
|
|
36
|
+
var parserInitPromise = null;
|
|
37
|
+
var languageCache = /* @__PURE__ */ new Map();
|
|
38
|
+
var parserCache = /* @__PURE__ */ new Map();
|
|
39
|
+
function resolveWasmPath(filename) {
|
|
40
|
+
const candidates = [];
|
|
41
|
+
candidates.push(path.join(__dirname_, "wasm", filename));
|
|
42
|
+
candidates.push(path.join(__dirname_, "..", "wasm", filename));
|
|
43
|
+
candidates.push(path.join(__dirname_, "..", "dist", "wasm", filename));
|
|
44
|
+
if (process.pkg) {
|
|
45
|
+
candidates.push(path.join(path.dirname(process.execPath), "dist", "wasm", filename));
|
|
46
|
+
candidates.push(path.join("/snapshot", "ai-cli", "dist", "wasm", filename));
|
|
47
|
+
candidates.push(path.join("/snapshot", "jinzd-ai-cli", "dist", "wasm", filename));
|
|
48
|
+
}
|
|
49
|
+
const resourcesPath = process.resourcesPath;
|
|
50
|
+
if (resourcesPath) {
|
|
51
|
+
candidates.push(path.join(resourcesPath, "app.asar.unpacked", "dist", "wasm", filename));
|
|
52
|
+
candidates.push(path.join(resourcesPath, "app", "dist", "wasm", filename));
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
if (filename === RUNTIME_WASM) {
|
|
56
|
+
const pkgPath = require_.resolve("web-tree-sitter/package.json");
|
|
57
|
+
candidates.push(path.join(path.dirname(pkgPath), filename));
|
|
58
|
+
} else {
|
|
59
|
+
const grammarPkg = filename.replace(/\.wasm$/, "").replace(/^tree-sitter-tsx$/, "tree-sitter-typescript");
|
|
60
|
+
const pkgPath = require_.resolve(`${grammarPkg}/package.json`);
|
|
61
|
+
candidates.push(path.join(path.dirname(pkgPath), filename));
|
|
62
|
+
}
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
candidates.push(path.join(process.cwd(), "dist", "wasm", filename));
|
|
66
|
+
candidates.push(path.join(process.cwd(), "node_modules", "web-tree-sitter", filename));
|
|
67
|
+
for (const p of candidates) {
|
|
68
|
+
try {
|
|
69
|
+
if (fs.existsSync(p)) return p;
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
throw new Error(
|
|
74
|
+
`[symbols/loader] Cannot locate ${filename}. Searched:
|
|
75
|
+
${candidates.join("\n ")}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
async function initRuntime() {
|
|
79
|
+
if (parserInitPromise) return parserInitPromise;
|
|
80
|
+
parserInitPromise = Parser.init({
|
|
81
|
+
locateFile: (name) => resolveWasmPath(name)
|
|
82
|
+
});
|
|
83
|
+
return parserInitPromise;
|
|
84
|
+
}
|
|
85
|
+
async function loadParser(language) {
|
|
86
|
+
const cached = parserCache.get(language);
|
|
87
|
+
if (cached) return cached;
|
|
88
|
+
await initRuntime();
|
|
89
|
+
let lang = languageCache.get(language);
|
|
90
|
+
if (!lang) {
|
|
91
|
+
const wasmPath = resolveWasmPath(GRAMMAR_FILE[language]);
|
|
92
|
+
lang = await Language.load(wasmPath);
|
|
93
|
+
languageCache.set(language, lang);
|
|
94
|
+
}
|
|
95
|
+
const parser = new Parser();
|
|
96
|
+
parser.setLanguage(lang);
|
|
97
|
+
parserCache.set(language, parser);
|
|
98
|
+
return parser;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/symbols/parser.ts
|
|
102
|
+
function locationOf(file, node) {
|
|
103
|
+
return {
|
|
104
|
+
file: path2.resolve(file),
|
|
105
|
+
line: node.startPosition.row + 1,
|
|
106
|
+
column: node.startPosition.column,
|
|
107
|
+
endLine: node.endPosition.row + 1,
|
|
108
|
+
endColumn: node.endPosition.column
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function firstLine(text, max = 200) {
|
|
112
|
+
const line = text.split(/\r?\n/)[0] ?? "";
|
|
113
|
+
return line.length > max ? line.slice(0, max) + "\u2026" : line;
|
|
114
|
+
}
|
|
115
|
+
function childByFieldName(node, field) {
|
|
116
|
+
return node.childForFieldName(field) ?? null;
|
|
117
|
+
}
|
|
118
|
+
function nameOf(node) {
|
|
119
|
+
const n = childByFieldName(node, "name") ?? node.children.find((c) => c?.type === "identifier" || c?.type === "property_identifier" || c?.type === "type_identifier");
|
|
120
|
+
return n?.text ?? null;
|
|
121
|
+
}
|
|
122
|
+
function extractTsJs(root, file, language) {
|
|
123
|
+
const out = [];
|
|
124
|
+
const visit = (node, container, exported) => {
|
|
125
|
+
let childrenContainer = container;
|
|
126
|
+
const kindMap = {
|
|
127
|
+
function_declaration: "function",
|
|
128
|
+
generator_function_declaration: "function",
|
|
129
|
+
class_declaration: "class",
|
|
130
|
+
abstract_class_declaration: "class",
|
|
131
|
+
interface_declaration: "interface",
|
|
132
|
+
type_alias_declaration: "type",
|
|
133
|
+
enum_declaration: "enum",
|
|
134
|
+
method_definition: "method",
|
|
135
|
+
method_signature: "method",
|
|
136
|
+
public_field_definition: "property"
|
|
137
|
+
};
|
|
138
|
+
const kind = kindMap[node.type];
|
|
139
|
+
if (kind) {
|
|
140
|
+
const name = nameOf(node);
|
|
141
|
+
if (name) {
|
|
142
|
+
out.push({
|
|
143
|
+
name,
|
|
144
|
+
kind,
|
|
145
|
+
language,
|
|
146
|
+
location: locationOf(file, node),
|
|
147
|
+
signature: firstLine(node.text),
|
|
148
|
+
container,
|
|
149
|
+
exported
|
|
150
|
+
});
|
|
151
|
+
if (kind === "class" || kind === "interface" || kind === "enum") {
|
|
152
|
+
childrenContainer = name;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
} else if (node.type === "lexical_declaration" || node.type === "variable_declaration") {
|
|
156
|
+
for (const decl of node.children) {
|
|
157
|
+
if (decl?.type !== "variable_declarator") continue;
|
|
158
|
+
const nameNode = childByFieldName(decl, "name");
|
|
159
|
+
if (!nameNode || nameNode.type !== "identifier") continue;
|
|
160
|
+
out.push({
|
|
161
|
+
name: nameNode.text,
|
|
162
|
+
kind: "variable",
|
|
163
|
+
language,
|
|
164
|
+
location: locationOf(file, decl),
|
|
165
|
+
signature: firstLine(decl.text),
|
|
166
|
+
container,
|
|
167
|
+
exported
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
} else if (node.type === "export_statement") {
|
|
171
|
+
for (const c of node.children) {
|
|
172
|
+
if (c) visit(c, container, true);
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const descendInto = /* @__PURE__ */ new Set([
|
|
177
|
+
"program",
|
|
178
|
+
"module",
|
|
179
|
+
"class_body",
|
|
180
|
+
"class_declaration",
|
|
181
|
+
"abstract_class_declaration",
|
|
182
|
+
"interface_body",
|
|
183
|
+
"interface_declaration",
|
|
184
|
+
"enum_body",
|
|
185
|
+
"enum_declaration",
|
|
186
|
+
"export_statement",
|
|
187
|
+
"statement_block",
|
|
188
|
+
// for nested class_declaration inside namespace etc.
|
|
189
|
+
"internal_module",
|
|
190
|
+
"namespace_declaration"
|
|
191
|
+
]);
|
|
192
|
+
if (node === root || descendInto.has(node.type)) {
|
|
193
|
+
for (const c of node.children) {
|
|
194
|
+
if (c) visit(c, childrenContainer, exported);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
visit(root, void 0, false);
|
|
199
|
+
return out;
|
|
200
|
+
}
|
|
201
|
+
function extractPython(root, file) {
|
|
202
|
+
const out = [];
|
|
203
|
+
const visit = (node, container, isModuleLevel) => {
|
|
204
|
+
if (node.type === "decorated_definition") {
|
|
205
|
+
const def = node.children.find(
|
|
206
|
+
(c) => c?.type === "class_definition" || c?.type === "function_definition"
|
|
207
|
+
);
|
|
208
|
+
if (def) visit(def, container, isModuleLevel);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (node.type === "class_definition") {
|
|
212
|
+
const name = nameOf(node);
|
|
213
|
+
if (name) {
|
|
214
|
+
out.push({
|
|
215
|
+
name,
|
|
216
|
+
kind: "class",
|
|
217
|
+
language: "python",
|
|
218
|
+
location: locationOf(file, node),
|
|
219
|
+
signature: firstLine(node.text),
|
|
220
|
+
container,
|
|
221
|
+
exported: isModuleLevel
|
|
222
|
+
});
|
|
223
|
+
const body = childByFieldName(node, "body");
|
|
224
|
+
if (body) {
|
|
225
|
+
for (const c of body.children) {
|
|
226
|
+
if (c) visit(c, name, false);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (node.type === "function_definition") {
|
|
233
|
+
const name = nameOf(node);
|
|
234
|
+
if (name) {
|
|
235
|
+
out.push({
|
|
236
|
+
name,
|
|
237
|
+
kind: container ? "method" : "function",
|
|
238
|
+
language: "python",
|
|
239
|
+
location: locationOf(file, node),
|
|
240
|
+
signature: firstLine(node.text),
|
|
241
|
+
container,
|
|
242
|
+
exported: isModuleLevel && !name.startsWith("_")
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (isModuleLevel && node.type === "expression_statement") {
|
|
248
|
+
const assign = node.children.find((c) => c?.type === "assignment");
|
|
249
|
+
if (assign) {
|
|
250
|
+
const left = childByFieldName(assign, "left");
|
|
251
|
+
if (left && left.type === "identifier") {
|
|
252
|
+
out.push({
|
|
253
|
+
name: left.text,
|
|
254
|
+
kind: "variable",
|
|
255
|
+
language: "python",
|
|
256
|
+
location: locationOf(file, assign),
|
|
257
|
+
signature: firstLine(assign.text),
|
|
258
|
+
container,
|
|
259
|
+
exported: !left.text.startsWith("_")
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (node === root || node.type === "module") {
|
|
266
|
+
for (const c of node.children) {
|
|
267
|
+
if (c) visit(c, container, true);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
visit(root, void 0, true);
|
|
272
|
+
return out;
|
|
273
|
+
}
|
|
274
|
+
async function parseSource(file, source, language) {
|
|
275
|
+
const lang = language ?? detectLanguage(path2.extname(file).slice(1));
|
|
276
|
+
if (!lang) return [];
|
|
277
|
+
try {
|
|
278
|
+
const parser = await loadParser(lang);
|
|
279
|
+
const tree = parser.parse(source);
|
|
280
|
+
if (!tree) return [];
|
|
281
|
+
const root = tree.rootNode;
|
|
282
|
+
if (lang === "python") return extractPython(root, file);
|
|
283
|
+
return extractTsJs(root, file, lang);
|
|
284
|
+
} catch (err) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/symbols/indexer.ts
|
|
290
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
291
|
+
"node_modules",
|
|
292
|
+
".git",
|
|
293
|
+
"dist",
|
|
294
|
+
"dist-cjs",
|
|
295
|
+
"build",
|
|
296
|
+
"out",
|
|
297
|
+
"coverage",
|
|
298
|
+
".next",
|
|
299
|
+
".nuxt",
|
|
300
|
+
".turbo",
|
|
301
|
+
".cache",
|
|
302
|
+
"__pycache__",
|
|
303
|
+
".venv",
|
|
304
|
+
"venv",
|
|
305
|
+
".idea",
|
|
306
|
+
".vscode",
|
|
307
|
+
"release"
|
|
308
|
+
]);
|
|
309
|
+
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
310
|
+
function collectFiles(root, maxFiles) {
|
|
311
|
+
const out = [];
|
|
312
|
+
const stack = [root];
|
|
313
|
+
while (stack.length > 0 && out.length < maxFiles) {
|
|
314
|
+
const dir = stack.pop();
|
|
315
|
+
let entries;
|
|
316
|
+
try {
|
|
317
|
+
entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
318
|
+
} catch {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
for (const e of entries) {
|
|
322
|
+
const full = path3.join(dir, e.name);
|
|
323
|
+
if (e.isDirectory()) {
|
|
324
|
+
if (SKIP_DIRS.has(e.name)) continue;
|
|
325
|
+
if (e.name.startsWith(".") && e.name !== ".") {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
stack.push(full);
|
|
329
|
+
} else if (e.isFile()) {
|
|
330
|
+
const ext = path3.extname(e.name).slice(1);
|
|
331
|
+
if (detectLanguage(ext)) {
|
|
332
|
+
out.push(full);
|
|
333
|
+
if (out.length >= maxFiles) break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return out;
|
|
339
|
+
}
|
|
340
|
+
async function indexProject(root, opts = {}) {
|
|
341
|
+
const start = Date.now();
|
|
342
|
+
const maxFiles = opts.maxFiles ?? 5e3;
|
|
343
|
+
const force = opts.force === true;
|
|
344
|
+
const absRoot = path3.resolve(root);
|
|
345
|
+
let index = force ? emptyIndex(absRoot) : loadIndex(absRoot) ?? emptyIndex(absRoot);
|
|
346
|
+
const files = collectFiles(absRoot, maxFiles);
|
|
347
|
+
const liveSet = new Set(files.map((f) => path3.resolve(f)));
|
|
348
|
+
for (const known of Object.keys(index.files)) {
|
|
349
|
+
if (!liveSet.has(known)) {
|
|
350
|
+
index = removeFile(index, known);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
let parsed = 0;
|
|
354
|
+
let skipped = 0;
|
|
355
|
+
for (let i = 0; i < files.length; i++) {
|
|
356
|
+
const file = path3.resolve(files[i]);
|
|
357
|
+
let stat;
|
|
358
|
+
try {
|
|
359
|
+
stat = fs2.statSync(file);
|
|
360
|
+
} catch {
|
|
361
|
+
skipped++;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (stat.size > MAX_FILE_BYTES) {
|
|
365
|
+
skipped++;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
const prevMtime = index.files[file];
|
|
369
|
+
if (!force && prevMtime !== void 0 && prevMtime === stat.mtimeMs) {
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
let src;
|
|
373
|
+
try {
|
|
374
|
+
src = fs2.readFileSync(file, "utf-8");
|
|
375
|
+
} catch {
|
|
376
|
+
skipped++;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const symbols = await parseSource(file, src);
|
|
380
|
+
index = upsertFileSymbols(index, file, stat.mtimeMs, symbols);
|
|
381
|
+
parsed++;
|
|
382
|
+
if (opts.onProgress && parsed % 50 === 0) {
|
|
383
|
+
opts.onProgress(i + 1, files.length);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
saveIndex(index);
|
|
387
|
+
return {
|
|
388
|
+
index,
|
|
389
|
+
stats: {
|
|
390
|
+
filesScanned: files.length,
|
|
391
|
+
filesParsed: parsed,
|
|
392
|
+
filesSkipped: skipped,
|
|
393
|
+
symbols: index.symbolCount,
|
|
394
|
+
durationMs: Date.now() - start
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
async function updateFile(root, file) {
|
|
399
|
+
const absRoot = path3.resolve(root);
|
|
400
|
+
const absFile = path3.resolve(file);
|
|
401
|
+
let index = loadIndex(absRoot);
|
|
402
|
+
if (!index) return;
|
|
403
|
+
if (!fs2.existsSync(absFile)) {
|
|
404
|
+
index = removeFile(index, absFile);
|
|
405
|
+
saveIndex(index);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const ext = path3.extname(absFile).slice(1);
|
|
409
|
+
if (!detectLanguage(ext)) return;
|
|
410
|
+
let stat;
|
|
411
|
+
try {
|
|
412
|
+
stat = fs2.statSync(absFile);
|
|
413
|
+
} catch {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (stat.size > MAX_FILE_BYTES) return;
|
|
417
|
+
let src;
|
|
418
|
+
try {
|
|
419
|
+
src = fs2.readFileSync(absFile, "utf-8");
|
|
420
|
+
} catch {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
const symbols = await parseSource(absFile, src);
|
|
424
|
+
index = upsertFileSymbols(index, absFile, stat.mtimeMs, symbols);
|
|
425
|
+
saveIndex(index);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export {
|
|
429
|
+
indexProject,
|
|
430
|
+
updateFile
|
|
431
|
+
};
|