@openez-graph/cli 0.3.2 → 0.4.0
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 +11 -3
- package/dist/cli.cjs +597 -174
- package/dist/web/assets/{WorkspaceGraph-CyIfL-tO.js → WorkspaceGraph-C2EeqZCG.js} +1 -1
- package/dist/web/assets/index-4j3-JbXm.css +1 -0
- package/dist/web/assets/index-BrXKvH08.js +332 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/index-C3yC9A2l.css +0 -1
- package/dist/web/assets/index-CDXvHMX8.js +0 -312
package/dist/cli.cjs
CHANGED
|
@@ -11564,6 +11564,15 @@ var init_schema = __esm({
|
|
|
11564
11564
|
});
|
|
11565
11565
|
|
|
11566
11566
|
// ../../packages/db/src/sqlite/database-loader.ts
|
|
11567
|
+
function getRequireUrl() {
|
|
11568
|
+
try {
|
|
11569
|
+
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
11570
|
+
return import_meta.url;
|
|
11571
|
+
}
|
|
11572
|
+
} catch {
|
|
11573
|
+
}
|
|
11574
|
+
return `file://${__filename}`;
|
|
11575
|
+
}
|
|
11567
11576
|
function tryResolveAddon() {
|
|
11568
11577
|
if (resolvedAddon !== void 0) return resolvedAddon;
|
|
11569
11578
|
try {
|
|
@@ -11600,9 +11609,7 @@ var init_database_loader = __esm({
|
|
|
11600
11609
|
import_node_fs = __toESM(require("fs"), 1);
|
|
11601
11610
|
import_node_module = __toESM(require("module"), 1);
|
|
11602
11611
|
import_meta = {};
|
|
11603
|
-
_require = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : import_node_module.default.createRequire(
|
|
11604
|
-
typeof import_meta !== "undefined" && import_meta.url ? import_meta.url : `file://${__filename}`
|
|
11605
|
-
);
|
|
11612
|
+
_require = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : import_node_module.default.createRequire(getRequireUrl());
|
|
11606
11613
|
}
|
|
11607
11614
|
});
|
|
11608
11615
|
|
|
@@ -11722,6 +11729,68 @@ function initializeWorkspaceSchema(sqlite) {
|
|
|
11722
11729
|
CREATE INDEX IF NOT EXISTS idx_graph_edges_type ON graph_edges(type);
|
|
11723
11730
|
CREATE INDEX IF NOT EXISTS idx_embeddings_chunk_id ON embeddings(chunk_id);
|
|
11724
11731
|
`);
|
|
11732
|
+
sqlite.exec(`
|
|
11733
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(
|
|
11734
|
+
chunk_id UNINDEXED,
|
|
11735
|
+
path,
|
|
11736
|
+
heading,
|
|
11737
|
+
language,
|
|
11738
|
+
search_text,
|
|
11739
|
+
content,
|
|
11740
|
+
tokenize = 'porter unicode61'
|
|
11741
|
+
);
|
|
11742
|
+
`);
|
|
11743
|
+
const ftsColumns = sqlite.prepare("PRAGMA table_info(chunks_fts)").all();
|
|
11744
|
+
if (!ftsColumns.some((column) => column.name === "search_text")) {
|
|
11745
|
+
sqlite.exec(`
|
|
11746
|
+
DROP TRIGGER IF EXISTS chunks_fts_insert;
|
|
11747
|
+
DROP TRIGGER IF EXISTS chunks_fts_delete;
|
|
11748
|
+
DROP TRIGGER IF EXISTS chunks_fts_update;
|
|
11749
|
+
DROP TABLE chunks_fts;
|
|
11750
|
+
CREATE VIRTUAL TABLE chunks_fts USING fts5(
|
|
11751
|
+
chunk_id UNINDEXED,
|
|
11752
|
+
path,
|
|
11753
|
+
heading,
|
|
11754
|
+
language,
|
|
11755
|
+
search_text,
|
|
11756
|
+
content,
|
|
11757
|
+
tokenize = 'porter unicode61'
|
|
11758
|
+
);
|
|
11759
|
+
`);
|
|
11760
|
+
}
|
|
11761
|
+
sqlite.exec(`
|
|
11762
|
+
CREATE TRIGGER IF NOT EXISTS chunks_fts_insert AFTER INSERT ON chunks
|
|
11763
|
+
BEGIN
|
|
11764
|
+
INSERT INTO chunks_fts (chunk_id, path, heading, language, search_text, content)
|
|
11765
|
+
SELECT new.id, documents.path, coalesce(new.heading, ''),
|
|
11766
|
+
coalesce(documents.language, ''), coalesce(json_extract(new.metadata, '$.searchText'), ''), new.content
|
|
11767
|
+
FROM documents WHERE documents.id = new.document_id;
|
|
11768
|
+
END;
|
|
11769
|
+
|
|
11770
|
+
CREATE TRIGGER IF NOT EXISTS chunks_fts_delete AFTER DELETE ON chunks
|
|
11771
|
+
BEGIN
|
|
11772
|
+
DELETE FROM chunks_fts WHERE chunk_id = old.id;
|
|
11773
|
+
END;
|
|
11774
|
+
|
|
11775
|
+
CREATE TRIGGER IF NOT EXISTS chunks_fts_update AFTER UPDATE ON chunks
|
|
11776
|
+
BEGIN
|
|
11777
|
+
DELETE FROM chunks_fts WHERE chunk_id = old.id;
|
|
11778
|
+
INSERT INTO chunks_fts (chunk_id, path, heading, language, search_text, content)
|
|
11779
|
+
SELECT new.id, documents.path, coalesce(new.heading, ''),
|
|
11780
|
+
coalesce(documents.language, ''), coalesce(json_extract(new.metadata, '$.searchText'), ''), new.content
|
|
11781
|
+
FROM documents WHERE documents.id = new.document_id;
|
|
11782
|
+
END;
|
|
11783
|
+
`);
|
|
11784
|
+
sqlite.exec(`
|
|
11785
|
+
INSERT INTO chunks_fts (chunk_id, path, heading, language, search_text, content)
|
|
11786
|
+
SELECT chunks.id, documents.path, coalesce(chunks.heading, ''),
|
|
11787
|
+
coalesce(documents.language, ''), coalesce(json_extract(chunks.metadata, '$.searchText'), ''), chunks.content
|
|
11788
|
+
FROM chunks
|
|
11789
|
+
INNER JOIN documents ON documents.id = chunks.document_id
|
|
11790
|
+
WHERE NOT EXISTS (
|
|
11791
|
+
SELECT 1 FROM chunks_fts WHERE chunks_fts.chunk_id = chunks.id
|
|
11792
|
+
);
|
|
11793
|
+
`);
|
|
11725
11794
|
}
|
|
11726
11795
|
function getWorkspaceTableDefinitions() {
|
|
11727
11796
|
return [
|
|
@@ -12081,8 +12150,9 @@ function createWorkspaceRepository(rootPath) {
|
|
|
12081
12150
|
const existing = native.prepare("SELECT * FROM graph_nodes WHERE type = ? AND label = ?").get(input.type, input.label);
|
|
12082
12151
|
if (existing) {
|
|
12083
12152
|
const nextMetadata = input.metadata ?? String(existing.metadata ?? "{}");
|
|
12084
|
-
const
|
|
12085
|
-
|
|
12153
|
+
const existingRefId = existing.ref_id ?? null;
|
|
12154
|
+
const nextRefId = input.refId ?? existingRefId;
|
|
12155
|
+
if (nextRefId !== existingRefId || nextMetadata !== existing.metadata) {
|
|
12086
12156
|
native.prepare("UPDATE graph_nodes SET ref_id = ?, metadata = ?, updated_at = ? WHERE id = ?").run(nextRefId, nextMetadata, (/* @__PURE__ */ new Date()).toISOString(), existing.id);
|
|
12087
12157
|
}
|
|
12088
12158
|
return String(existing.id);
|
|
@@ -12133,36 +12203,59 @@ function createWorkspaceRepository(rootPath) {
|
|
|
12133
12203
|
},
|
|
12134
12204
|
// ── Full-Text Search ──
|
|
12135
12205
|
async fullTextSearch(query, limit2) {
|
|
12136
|
-
const
|
|
12206
|
+
const ftsQuery = sanitizeFtsQuery(query);
|
|
12207
|
+
if (!ftsQuery) return [];
|
|
12137
12208
|
const rows = native.prepare(
|
|
12138
|
-
`SELECT
|
|
12139
|
-
|
|
12209
|
+
`SELECT
|
|
12210
|
+
chunks.id, chunks.content, chunks.heading, chunks.metadata,
|
|
12211
|
+
documents.path,
|
|
12212
|
+
bm25(chunks_fts, 0, 4, 3, 1.5, 2, 1)
|
|
12213
|
+
* CASE
|
|
12214
|
+
WHEN documents.path LIKE 'tests/%' OR documents.path LIKE '%/__tests__/%' OR documents.path GLOB '*.test.*' THEN 0.8
|
|
12215
|
+
WHEN documents.kind = 'code' THEN 1.35
|
|
12216
|
+
ELSE 1
|
|
12217
|
+
END AS bm25_score
|
|
12218
|
+
FROM chunks_fts
|
|
12219
|
+
INNER JOIN chunks ON chunks.id = chunks_fts.chunk_id
|
|
12140
12220
|
INNER JOIN documents ON documents.id = chunks.document_id
|
|
12141
|
-
WHERE
|
|
12221
|
+
WHERE chunks_fts MATCH ?
|
|
12222
|
+
ORDER BY bm25_score ASC
|
|
12142
12223
|
LIMIT ?`
|
|
12143
|
-
).all(
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12224
|
+
).all(ftsQuery, limit2 * 5);
|
|
12225
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
12226
|
+
return rows.map((row) => {
|
|
12227
|
+
const bm25 = Number(row.bm25_score ?? 0);
|
|
12228
|
+
const score = -bm25;
|
|
12229
|
+
return {
|
|
12230
|
+
id: String(row.id),
|
|
12231
|
+
path: String(row.path),
|
|
12232
|
+
content: String(row.content),
|
|
12233
|
+
score,
|
|
12234
|
+
heading: row.heading ? String(row.heading) : null,
|
|
12235
|
+
metadata: safeParseJson(String(row.metadata ?? ""), {})
|
|
12236
|
+
};
|
|
12237
|
+
}).filter((row) => {
|
|
12238
|
+
if (seenPaths.has(row.path)) return false;
|
|
12239
|
+
seenPaths.add(row.path);
|
|
12240
|
+
return true;
|
|
12241
|
+
}).slice(0, limit2);
|
|
12152
12242
|
},
|
|
12153
12243
|
// ── Graph Traversal ──
|
|
12154
|
-
async graphNeighbors(
|
|
12155
|
-
const seedNodes = native.prepare("SELECT * FROM graph_nodes WHERE label = ? LIMIT 1").all(
|
|
12244
|
+
async graphNeighbors(labelOrId, depth) {
|
|
12245
|
+
const seedNodes = native.prepare("SELECT * FROM graph_nodes WHERE id = ? OR label = ? ORDER BY id = ? DESC LIMIT 1").all(labelOrId, labelOrId, labelOrId);
|
|
12156
12246
|
if (seedNodes.length === 0) {
|
|
12157
12247
|
return { nodes: [], edges: [] };
|
|
12158
12248
|
}
|
|
12159
12249
|
const seedId = String(seedNodes[0].id);
|
|
12160
12250
|
const visited = /* @__PURE__ */ new Set();
|
|
12161
|
-
const resultNodes = [
|
|
12251
|
+
const resultNodes = [
|
|
12252
|
+
{ ...seedNodes[0], metadata: safeParseJson(String(seedNodes[0].metadata ?? ""), {}) }
|
|
12253
|
+
];
|
|
12162
12254
|
const resultEdges = [];
|
|
12255
|
+
const resultEdgeIds = /* @__PURE__ */ new Set();
|
|
12163
12256
|
let currentBatch = [seedId];
|
|
12164
12257
|
visited.add(seedId);
|
|
12165
|
-
for (let hop = 0; hop
|
|
12258
|
+
for (let hop = 0; hop < Math.max(0, depth); hop++) {
|
|
12166
12259
|
if (currentBatch.length === 0) break;
|
|
12167
12260
|
const placeholders = currentBatch.map(() => "?").join(",");
|
|
12168
12261
|
const edges = native.prepare(`SELECT * FROM graph_edges WHERE (from_node_id IN (${placeholders}) OR to_node_id IN (${placeholders}))`).all(...currentBatch, ...currentBatch);
|
|
@@ -12170,15 +12263,19 @@ function createWorkspaceRepository(rootPath) {
|
|
|
12170
12263
|
for (const edge of edges) {
|
|
12171
12264
|
const fromId = String(edge.from_node_id);
|
|
12172
12265
|
const toId = String(edge.to_node_id);
|
|
12173
|
-
if (!visited.has(fromId)) {
|
|
12266
|
+
if (!visited.has(fromId) && visited.size < 200) {
|
|
12174
12267
|
nextBatch.push(fromId);
|
|
12175
12268
|
visited.add(fromId);
|
|
12176
12269
|
}
|
|
12177
|
-
if (!visited.has(toId)) {
|
|
12270
|
+
if (!visited.has(toId) && visited.size < 200) {
|
|
12178
12271
|
nextBatch.push(toId);
|
|
12179
12272
|
visited.add(toId);
|
|
12180
12273
|
}
|
|
12181
|
-
|
|
12274
|
+
const edgeId = String(edge.id);
|
|
12275
|
+
if (!resultEdgeIds.has(edgeId)) {
|
|
12276
|
+
resultEdgeIds.add(edgeId);
|
|
12277
|
+
resultEdges.push(edge);
|
|
12278
|
+
}
|
|
12182
12279
|
}
|
|
12183
12280
|
for (const nodeId of nextBatch) {
|
|
12184
12281
|
const node = native.prepare("SELECT * FROM graph_nodes WHERE id = ?").get(nodeId);
|
|
@@ -12188,9 +12285,6 @@ function createWorkspaceRepository(rootPath) {
|
|
|
12188
12285
|
}
|
|
12189
12286
|
currentBatch = nextBatch;
|
|
12190
12287
|
}
|
|
12191
|
-
if (seedNodes[0]) {
|
|
12192
|
-
resultNodes.push({ ...seedNodes[0], metadata: safeParseJson(String(seedNodes[0].metadata ?? ""), {}) });
|
|
12193
|
-
}
|
|
12194
12288
|
return { nodes: resultNodes, edges: resultEdges };
|
|
12195
12289
|
},
|
|
12196
12290
|
// ── Memory Operations ──
|
|
@@ -12317,6 +12411,38 @@ function safeParseJson(value, fallback) {
|
|
|
12317
12411
|
return fallback;
|
|
12318
12412
|
}
|
|
12319
12413
|
}
|
|
12414
|
+
function sanitizeFtsQuery(query) {
|
|
12415
|
+
const stopwords = /* @__PURE__ */ new Set([
|
|
12416
|
+
"a",
|
|
12417
|
+
"an",
|
|
12418
|
+
"are",
|
|
12419
|
+
"does",
|
|
12420
|
+
"extracted",
|
|
12421
|
+
"how",
|
|
12422
|
+
"implement",
|
|
12423
|
+
"implementation",
|
|
12424
|
+
"implemented",
|
|
12425
|
+
"in",
|
|
12426
|
+
"is",
|
|
12427
|
+
"of",
|
|
12428
|
+
"the",
|
|
12429
|
+
"to",
|
|
12430
|
+
"what",
|
|
12431
|
+
"where",
|
|
12432
|
+
"work"
|
|
12433
|
+
]);
|
|
12434
|
+
const codeVerbs = {
|
|
12435
|
+
created: "create",
|
|
12436
|
+
generated: "generate",
|
|
12437
|
+
indexing: "index",
|
|
12438
|
+
selected: "select",
|
|
12439
|
+
stored: "store",
|
|
12440
|
+
written: "write"
|
|
12441
|
+
};
|
|
12442
|
+
const terms = (query.match(/[\p{L}\p{N}$]+/gu) ?? []).filter((t) => t.length > 1 && !stopwords.has(t.toLowerCase()));
|
|
12443
|
+
if (terms.length === 0) return "";
|
|
12444
|
+
return [...new Set(terms.map((term) => codeVerbs[term.toLowerCase()] ?? term))].map((term) => `"${term}"*`).join(" OR ");
|
|
12445
|
+
}
|
|
12320
12446
|
var import_node_crypto;
|
|
12321
12447
|
var init_repository = __esm({
|
|
12322
12448
|
"../../packages/db/src/sqlite/repository.ts"() {
|
|
@@ -27434,6 +27560,27 @@ function truncateToTokenLimit(value, maxTokens) {
|
|
|
27434
27560
|
return value.slice(0, approximateMaxChars);
|
|
27435
27561
|
}
|
|
27436
27562
|
}
|
|
27563
|
+
function splitToTokenLimit(value, maxTokens, overlapTokens = 0) {
|
|
27564
|
+
if (!value || maxTokens <= 0) return [];
|
|
27565
|
+
const overlap = Math.min(Math.max(0, overlapTokens), maxTokens - 1);
|
|
27566
|
+
try {
|
|
27567
|
+
const tokens = encode2(value);
|
|
27568
|
+
if (tokens.length <= maxTokens) return [value];
|
|
27569
|
+
const chunks2 = [];
|
|
27570
|
+
for (let start = 0; start < tokens.length; start += maxTokens - overlap) {
|
|
27571
|
+
chunks2.push(decode2(tokens.slice(start, start + maxTokens)));
|
|
27572
|
+
}
|
|
27573
|
+
return chunks2;
|
|
27574
|
+
} catch {
|
|
27575
|
+
const maxChars = maxTokens * 4;
|
|
27576
|
+
const overlapChars = overlap * 4;
|
|
27577
|
+
const chunks2 = [];
|
|
27578
|
+
for (let start = 0; start < value.length; start += maxChars - overlapChars) {
|
|
27579
|
+
chunks2.push(value.slice(start, start + maxChars));
|
|
27580
|
+
}
|
|
27581
|
+
return chunks2;
|
|
27582
|
+
}
|
|
27583
|
+
}
|
|
27437
27584
|
var init_tokenizer = __esm({
|
|
27438
27585
|
"../../packages/core/src/tokenizer.ts"() {
|
|
27439
27586
|
"use strict";
|
|
@@ -27442,6 +27589,14 @@ var init_tokenizer = __esm({
|
|
|
27442
27589
|
});
|
|
27443
27590
|
|
|
27444
27591
|
// ../../packages/core/src/embeddings.ts
|
|
27592
|
+
function embeddingStorageModel(provider) {
|
|
27593
|
+
return `${provider.model}:openez-code-v1`;
|
|
27594
|
+
}
|
|
27595
|
+
function formatEmbeddingInput(provider, input, task) {
|
|
27596
|
+
const text2 = task === "query" ? input.content : [`path: ${input.path ?? ""}`, input.heading ? `heading: ${input.heading}` : "", input.content].filter(Boolean).join("\n");
|
|
27597
|
+
const nomicPrefix = provider.provider === "ollama" && provider.model.includes("nomic-embed-text") ? task === "query" ? "search_query: " : "search_document: " : "";
|
|
27598
|
+
return `${nomicPrefix}${text2}`;
|
|
27599
|
+
}
|
|
27445
27600
|
function getEmbeddingProvider() {
|
|
27446
27601
|
const env = loadEnv();
|
|
27447
27602
|
if (env.EMBEDDING_PROVIDER === "none" || !env.EMBEDDING_PROVIDER) {
|
|
@@ -27548,13 +27703,14 @@ async function codeContext(input) {
|
|
|
27548
27703
|
const edges = neighbors.edges.filter((edge) => edge.type === "calls");
|
|
27549
27704
|
const relatedChunks = neighbors.nodes.filter((node) => node.type === "chunk");
|
|
27550
27705
|
const symbol = neighbors.nodes.find(
|
|
27551
|
-
(node) => node.type === "symbol"
|
|
27706
|
+
(node) => node.type === "symbol" && (node.label === input.symbolOrPath || node.id === input.symbolOrPath)
|
|
27552
27707
|
);
|
|
27708
|
+
const symbolId = symbol ? String(symbol.id) : "";
|
|
27553
27709
|
return {
|
|
27554
27710
|
symbol,
|
|
27555
27711
|
files,
|
|
27556
|
-
callers: edges,
|
|
27557
|
-
callees: edges,
|
|
27712
|
+
callers: edges.filter((edge) => String(edge.to_node_id) === symbolId),
|
|
27713
|
+
callees: edges.filter((edge) => String(edge.from_node_id) === symbolId),
|
|
27558
27714
|
relatedChunks
|
|
27559
27715
|
};
|
|
27560
27716
|
}
|
|
@@ -27590,12 +27746,12 @@ var init_memory = __esm({
|
|
|
27590
27746
|
});
|
|
27591
27747
|
|
|
27592
27748
|
// ../../packages/core/src/rrf.ts
|
|
27593
|
-
function reciprocalRankFusion(resultSets, k = 60) {
|
|
27749
|
+
function reciprocalRankFusion(resultSets, k = 60, weights = []) {
|
|
27594
27750
|
const map = /* @__PURE__ */ new Map();
|
|
27595
|
-
resultSets.forEach((resultSet) => {
|
|
27751
|
+
resultSets.forEach((resultSet, resultSetIndex) => {
|
|
27596
27752
|
resultSet.forEach((entry, index2) => {
|
|
27597
27753
|
const existing = map.get(entry.item.id);
|
|
27598
|
-
const score = 1 / (k + index2 + 1);
|
|
27754
|
+
const score = (weights[resultSetIndex] ?? 1) / (k + index2 + 1);
|
|
27599
27755
|
if (existing) {
|
|
27600
27756
|
existing.score += score;
|
|
27601
27757
|
} else {
|
|
@@ -27634,77 +27790,116 @@ function formatContextBlock(chunk) {
|
|
|
27634
27790
|
return `[source: ${chunk.path}:${startLine}-${endLine} | score: ${chunk.score.toFixed(3)}]
|
|
27635
27791
|
${chunk.content}`;
|
|
27636
27792
|
}
|
|
27637
|
-
|
|
27638
|
-
|
|
27639
|
-
|
|
27640
|
-
|
|
27641
|
-
|
|
27642
|
-
|
|
27793
|
+
function cosineSimilarity(left, right) {
|
|
27794
|
+
if (left.length === 0 || left.length !== right.length) return 0;
|
|
27795
|
+
let dot = 0;
|
|
27796
|
+
let leftNorm = 0;
|
|
27797
|
+
let rightNorm = 0;
|
|
27798
|
+
for (let index2 = 0; index2 < left.length; index2 += 1) {
|
|
27799
|
+
dot += left[index2] * right[index2];
|
|
27800
|
+
leftNorm += left[index2] * left[index2];
|
|
27801
|
+
rightNorm += right[index2] * right[index2];
|
|
27802
|
+
}
|
|
27803
|
+
return leftNorm === 0 || rightNorm === 0 ? 0 : dot / Math.sqrt(leftNorm * rightNorm);
|
|
27804
|
+
}
|
|
27805
|
+
function parseEmbedding(value) {
|
|
27806
|
+
try {
|
|
27807
|
+
const parsed = JSON.parse(String(value));
|
|
27808
|
+
return Array.isArray(parsed) && parsed.every((item) => typeof item === "number") ? parsed : [];
|
|
27809
|
+
} catch {
|
|
27810
|
+
return [];
|
|
27811
|
+
}
|
|
27812
|
+
}
|
|
27813
|
+
async function rankStoredEmbeddings(rootPath, provider, queryEmbedding, limit2) {
|
|
27814
|
+
if (queryEmbedding.length === 0) return [];
|
|
27643
27815
|
const repo = createWorkspaceRepository(rootPath);
|
|
27644
27816
|
const results = await repo.queryRaw(
|
|
27645
27817
|
`SELECT
|
|
27646
27818
|
chunks.id, chunks.content, chunks.heading, chunks.metadata,
|
|
27647
|
-
documents.path
|
|
27819
|
+
documents.path, embeddings.embedding
|
|
27648
27820
|
FROM embeddings
|
|
27649
27821
|
INNER JOIN chunks ON chunks.id = embeddings.chunk_id
|
|
27650
27822
|
INNER JOIN documents ON documents.id = chunks.document_id
|
|
27651
|
-
WHERE embeddings.
|
|
27652
|
-
AND embeddings.
|
|
27653
|
-
|
|
27654
|
-
|
|
27655
|
-
[provider.model, queryDimensions, embeddingJson.length, limit2]
|
|
27823
|
+
WHERE embeddings.provider = ?
|
|
27824
|
+
AND embeddings.model = ?
|
|
27825
|
+
AND embeddings.dimensions = ?`,
|
|
27826
|
+
[provider.provider, embeddingStorageModel(provider), queryEmbedding.length]
|
|
27656
27827
|
);
|
|
27657
27828
|
return results.map((row) => ({
|
|
27658
27829
|
id: String(row.id),
|
|
27659
27830
|
path: String(row.path),
|
|
27660
27831
|
content: String(row.content),
|
|
27661
|
-
score:
|
|
27832
|
+
score: cosineSimilarity(queryEmbedding, parseEmbedding(row.embedding)),
|
|
27662
27833
|
heading: row.heading ? String(row.heading) : null,
|
|
27663
27834
|
metadata: safeParseJson2(String(row.metadata ?? "{}"), {})
|
|
27664
|
-
}));
|
|
27835
|
+
})).sort((left, right) => right.score - left.score).slice(0, limit2);
|
|
27836
|
+
}
|
|
27837
|
+
async function vectorSearch(rootPath, query, limit2) {
|
|
27838
|
+
const provider = getEmbeddingProvider();
|
|
27839
|
+
if (!provider) return [];
|
|
27840
|
+
const [queryEmbedding] = await provider.embed([
|
|
27841
|
+
formatEmbeddingInput(provider, { content: query }, "query")
|
|
27842
|
+
]);
|
|
27843
|
+
return rankStoredEmbeddings(rootPath, provider, queryEmbedding ?? [], limit2);
|
|
27665
27844
|
}
|
|
27666
|
-
async function graphExpand(rootPath, seedIds, limit2) {
|
|
27845
|
+
async function graphExpand(rootPath, seedIds, depth, limit2) {
|
|
27667
27846
|
if (seedIds.length === 0) return [];
|
|
27668
27847
|
const repo = createWorkspaceRepository(rootPath);
|
|
27669
27848
|
const placeholders = seedIds.map(() => "?").join(",");
|
|
27670
27849
|
const results = await repo.queryRaw(
|
|
27671
|
-
`WITH
|
|
27672
|
-
SELECT id,
|
|
27850
|
+
`WITH RECURSIVE walk(node_id, depth) AS (
|
|
27851
|
+
SELECT id, 0
|
|
27673
27852
|
FROM graph_nodes
|
|
27674
27853
|
WHERE type = 'chunk'
|
|
27675
27854
|
AND ref_id IN (${placeholders})
|
|
27676
|
-
|
|
27677
|
-
|
|
27678
|
-
SELECT DISTINCT
|
|
27855
|
+
UNION
|
|
27856
|
+
SELECT
|
|
27679
27857
|
CASE
|
|
27680
|
-
WHEN graph_edges.from_node_id =
|
|
27858
|
+
WHEN graph_edges.from_node_id = walk.node_id THEN graph_edges.to_node_id
|
|
27681
27859
|
ELSE graph_edges.from_node_id
|
|
27682
|
-
END
|
|
27683
|
-
|
|
27684
|
-
|
|
27685
|
-
|
|
27686
|
-
|
|
27860
|
+
END,
|
|
27861
|
+
walk.depth + 1
|
|
27862
|
+
FROM walk
|
|
27863
|
+
INNER JOIN graph_edges
|
|
27864
|
+
ON graph_edges.from_node_id = walk.node_id
|
|
27865
|
+
OR graph_edges.to_node_id = walk.node_id
|
|
27866
|
+
WHERE walk.depth < ?
|
|
27867
|
+
),
|
|
27868
|
+
candidate_chunks AS (
|
|
27869
|
+
SELECT chunks.id, MIN(walk.depth) AS distance
|
|
27870
|
+
FROM walk
|
|
27871
|
+
INNER JOIN graph_nodes ON graph_nodes.id = walk.node_id
|
|
27872
|
+
INNER JOIN chunks ON chunks.id = graph_nodes.ref_id
|
|
27873
|
+
WHERE graph_nodes.type = 'chunk'
|
|
27874
|
+
AND walk.depth > 0
|
|
27875
|
+
AND chunks.id NOT IN (${placeholders})
|
|
27876
|
+
GROUP BY chunks.id
|
|
27877
|
+
ORDER BY distance
|
|
27687
27878
|
LIMIT ?
|
|
27688
27879
|
)
|
|
27689
27880
|
SELECT
|
|
27690
27881
|
chunks.id, chunks.content, chunks.heading, chunks.metadata,
|
|
27691
27882
|
documents.path,
|
|
27692
|
-
0.
|
|
27693
|
-
FROM
|
|
27694
|
-
INNER JOIN
|
|
27695
|
-
INNER JOIN chunks ON chunks.id = graph_nodes.ref_id
|
|
27883
|
+
1.0 / (candidate_chunks.distance + 1) AS score
|
|
27884
|
+
FROM candidate_chunks
|
|
27885
|
+
INNER JOIN chunks ON chunks.id = candidate_chunks.id
|
|
27696
27886
|
INNER JOIN documents ON documents.id = chunks.document_id
|
|
27697
|
-
|
|
27698
|
-
[...seedIds, limit2]
|
|
27887
|
+
ORDER BY candidate_chunks.distance, documents.path`,
|
|
27888
|
+
[...seedIds, depth, ...seedIds, limit2 * 5]
|
|
27699
27889
|
);
|
|
27890
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
27700
27891
|
return results.map((row) => ({
|
|
27701
27892
|
id: String(row.id),
|
|
27702
27893
|
path: String(row.path),
|
|
27703
27894
|
content: String(row.content),
|
|
27704
|
-
score: Number(row.score ?? 0
|
|
27895
|
+
score: Number(row.score ?? 0),
|
|
27705
27896
|
heading: row.heading ? String(row.heading) : null,
|
|
27706
27897
|
metadata: safeParseJson2(String(row.metadata ?? "{}"), {})
|
|
27707
|
-
}))
|
|
27898
|
+
})).filter((row) => {
|
|
27899
|
+
if (seenPaths.has(row.path)) return false;
|
|
27900
|
+
seenPaths.add(row.path);
|
|
27901
|
+
return true;
|
|
27902
|
+
}).slice(0, limit2);
|
|
27708
27903
|
}
|
|
27709
27904
|
async function memoryQuery(input) {
|
|
27710
27905
|
const registry2 = createRegistryRepository();
|
|
@@ -27721,29 +27916,34 @@ async function memoryQuery(input) {
|
|
|
27721
27916
|
repo.fullTextSearch(input.query, retrieval.textLimit),
|
|
27722
27917
|
vectorSearch(workspace.rootPath, input.query, retrieval.vectorLimit)
|
|
27723
27918
|
]);
|
|
27919
|
+
const primaryResults = ftsResults.length > 0 ? ftsResults : vectorResults;
|
|
27724
27920
|
let fused = reciprocalRankFusion([
|
|
27725
|
-
|
|
27726
|
-
vectorResults.map((item) => ({ item, score: item.score }))
|
|
27921
|
+
primaryResults.map((item) => ({ item, score: item.score }))
|
|
27727
27922
|
]);
|
|
27728
27923
|
if (!input.skipGraphExpand) {
|
|
27729
27924
|
const graphResults = await graphExpand(
|
|
27730
27925
|
workspace.rootPath,
|
|
27731
|
-
fused.slice(0, finalLimit).map((entry) => entry.item.id),
|
|
27926
|
+
fused.slice(0, Math.min(finalLimit, 5)).map((entry) => entry.item.id),
|
|
27927
|
+
retrieval.graphHops,
|
|
27732
27928
|
retrieval.maxGraphNeighbors
|
|
27733
27929
|
);
|
|
27930
|
+
const fusedItemsByPath = new Map(fused.map((entry) => [entry.item.path, entry.item]));
|
|
27734
27931
|
fused = reciprocalRankFusion([
|
|
27735
27932
|
fused,
|
|
27736
|
-
graphResults.map((item) => ({ item, score: item.score }))
|
|
27737
|
-
]);
|
|
27933
|
+
graphResults.map((item) => ({ item: fusedItemsByPath.get(item.path) ?? item, score: item.score }))
|
|
27934
|
+
], 60, [1, 0.25]);
|
|
27738
27935
|
}
|
|
27739
27936
|
const selected = [];
|
|
27740
27937
|
let usedTokens = 0;
|
|
27938
|
+
const chunksPerPath = /* @__PURE__ */ new Map();
|
|
27741
27939
|
for (const entry of fused) {
|
|
27742
27940
|
if (selected.length >= finalLimit) break;
|
|
27743
27941
|
const tokenCount = countTokens2(entry.item.content);
|
|
27744
27942
|
if (usedTokens + tokenCount > maxTokens) continue;
|
|
27745
|
-
|
|
27943
|
+
if (chunksPerPath.has(entry.item.path)) continue;
|
|
27944
|
+
selected.push({ ...entry.item, score: entry.score });
|
|
27746
27945
|
usedTokens += tokenCount;
|
|
27946
|
+
chunksPerPath.set(entry.item.path, (chunksPerPath.get(entry.item.path) ?? 0) + 1);
|
|
27747
27947
|
}
|
|
27748
27948
|
const sources = selected.map((chunk) => sourceFromChunk(chunk, "retrieved-context"));
|
|
27749
27949
|
await repo.insertQueryLog({
|
|
@@ -302258,6 +302458,10 @@ function getLineRange(node) {
|
|
|
302258
302458
|
endLine: node.getEndLineNumber()
|
|
302259
302459
|
};
|
|
302260
302460
|
}
|
|
302461
|
+
function codeSearchText(text2) {
|
|
302462
|
+
const identifiers = text2.match(/[A-Za-z_$][A-Za-z0-9_$]*/g) ?? [];
|
|
302463
|
+
return [...new Set(identifiers.flatMap((identifier) => identifier.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(" ").filter((term) => term.length > 1)))].slice(0, 256).join(" ");
|
|
302464
|
+
}
|
|
302261
302465
|
function indexCode(content, filePath) {
|
|
302262
302466
|
const project = new import_ts_morph.Project({
|
|
302263
302467
|
useInMemoryFileSystem: true,
|
|
@@ -302269,6 +302473,7 @@ function indexCode(content, filePath) {
|
|
|
302269
302473
|
const chunks2 = [];
|
|
302270
302474
|
const definedSymbols = [];
|
|
302271
302475
|
const calledIdentifiers = /* @__PURE__ */ new Set();
|
|
302476
|
+
const callExpressions = [];
|
|
302272
302477
|
sourceFile.getImportDeclarations().forEach((declaration) => {
|
|
302273
302478
|
declaration.getDescendantsOfKind(import_ts_morph.SyntaxKind.Identifier).forEach((identifier) => {
|
|
302274
302479
|
if (identifier.getText()) {
|
|
@@ -302308,6 +302513,7 @@ function indexCode(content, filePath) {
|
|
|
302308
302513
|
symbolType: symbolType2,
|
|
302309
302514
|
metadata: {
|
|
302310
302515
|
kind: "code",
|
|
302516
|
+
searchText: codeSearchText(text2),
|
|
302311
302517
|
symbolName: name,
|
|
302312
302518
|
symbolType: symbolType2,
|
|
302313
302519
|
exported,
|
|
@@ -302319,6 +302525,7 @@ function indexCode(content, filePath) {
|
|
|
302319
302525
|
const calledName = expression.getText();
|
|
302320
302526
|
if (calledName) {
|
|
302321
302527
|
calledIdentifiers.add(calledName);
|
|
302528
|
+
callExpressions.push({ callerName: name, calleeName: calledName.split(".").pop() ?? calledName });
|
|
302322
302529
|
}
|
|
302323
302530
|
});
|
|
302324
302531
|
});
|
|
@@ -302339,6 +302546,7 @@ function indexCode(content, filePath) {
|
|
|
302339
302546
|
symbolType: "variable",
|
|
302340
302547
|
metadata: {
|
|
302341
302548
|
kind: "code",
|
|
302549
|
+
searchText: codeSearchText(text2),
|
|
302342
302550
|
symbolName: name,
|
|
302343
302551
|
symbolType: "variable",
|
|
302344
302552
|
exported,
|
|
@@ -302359,6 +302567,7 @@ function indexCode(content, filePath) {
|
|
|
302359
302567
|
contentHash: hashContent(slice),
|
|
302360
302568
|
metadata: {
|
|
302361
302569
|
kind: "code",
|
|
302570
|
+
searchText: codeSearchText(slice),
|
|
302362
302571
|
fallback: true,
|
|
302363
302572
|
startLine: index2 + 1,
|
|
302364
302573
|
endLine: Math.min(index2 + 80, lines.length)
|
|
@@ -302370,7 +302579,8 @@ function indexCode(content, filePath) {
|
|
|
302370
302579
|
chunks: chunks2,
|
|
302371
302580
|
importPaths: sourceFile.getImportDeclarations().map((declaration) => declaration.getModuleSpecifierValue()),
|
|
302372
302581
|
definedSymbols,
|
|
302373
|
-
calledIdentifiers: [...calledIdentifiers]
|
|
302582
|
+
calledIdentifiers: [...calledIdentifiers],
|
|
302583
|
+
callExpressions
|
|
302374
302584
|
};
|
|
302375
302585
|
}
|
|
302376
302586
|
var import_ts_morph;
|
|
@@ -302572,13 +302782,37 @@ function inferDocumentKind(filePath) {
|
|
|
302572
302782
|
}
|
|
302573
302783
|
return { kind: "text", language: extension.slice(1) || null, extension };
|
|
302574
302784
|
}
|
|
302785
|
+
function stripPythonAlias(value) {
|
|
302786
|
+
return value.trim().replace(/^\(+|\)+$/g, "").split(/\s+as\s+/i)[0]?.trim() ?? "";
|
|
302787
|
+
}
|
|
302788
|
+
function parsePythonImportLine(line) {
|
|
302789
|
+
const trimmed = line.trim().replace(/\s+#.*$/, "");
|
|
302790
|
+
const fromMatch = /^from\s+([.\w]+)\s+import\s+(.+)$/.exec(trimmed);
|
|
302791
|
+
if (fromMatch) {
|
|
302792
|
+
const modulePath = fromMatch[1];
|
|
302793
|
+
const importedNames = fromMatch[2].split(",").map(stripPythonAlias).filter((name) => name && name !== "*");
|
|
302794
|
+
return [
|
|
302795
|
+
modulePath,
|
|
302796
|
+
...importedNames.map((name) => modulePath.endsWith(".") ? `${modulePath}${name}` : `${modulePath}.${name}`)
|
|
302797
|
+
];
|
|
302798
|
+
}
|
|
302799
|
+
const importMatch = /^import\s+(.+)$/.exec(trimmed);
|
|
302800
|
+
if (!importMatch) return [];
|
|
302801
|
+
return importMatch[1].split(",").map(stripPythonAlias).filter(Boolean);
|
|
302802
|
+
}
|
|
302803
|
+
function normalizePythonCallName(value) {
|
|
302804
|
+
const parts = value.split(".").filter(Boolean);
|
|
302805
|
+
return parts[parts.length - 1] ?? value;
|
|
302806
|
+
}
|
|
302575
302807
|
function parsePython(content) {
|
|
302576
302808
|
const lines = content.split("\n");
|
|
302577
302809
|
const definedSymbols = [];
|
|
302578
302810
|
const importPaths = [];
|
|
302811
|
+
const calledIdentifiers = /* @__PURE__ */ new Set();
|
|
302812
|
+
const callExpressions = [];
|
|
302579
302813
|
const symbolRegex = /^(?:async\s+)?(?:def|class)\s+(\w+)/;
|
|
302580
|
-
const importRegex = /^(?:from\s+(\S+)\s+)?import\s+(\S+)/;
|
|
302581
302814
|
const moduleDocstring = /^"""/;
|
|
302815
|
+
const callRegex = /(\w+(?:\.\w+)*)\s*\(/g;
|
|
302582
302816
|
let inMultilineString = false;
|
|
302583
302817
|
for (let i = 0; i < lines.length; i++) {
|
|
302584
302818
|
const line = lines[i];
|
|
@@ -302594,29 +302828,37 @@ function parsePython(content) {
|
|
|
302594
302828
|
}
|
|
302595
302829
|
continue;
|
|
302596
302830
|
}
|
|
302597
|
-
const
|
|
302598
|
-
|
|
302831
|
+
const trimmed = line.trim();
|
|
302832
|
+
const symbolMatch = symbolRegex.exec(trimmed);
|
|
302833
|
+
if (symbolMatch) {
|
|
302599
302834
|
const name = symbolMatch[1];
|
|
302600
|
-
const isAsync2 =
|
|
302601
|
-
const stripped = isAsync2 ?
|
|
302835
|
+
const isAsync2 = trimmed.startsWith("async");
|
|
302836
|
+
const stripped = isAsync2 ? trimmed.slice(6) : trimmed;
|
|
302602
302837
|
const symbolType2 = stripped.startsWith("def") ? "function" : "class";
|
|
302603
302838
|
const exported = !name.startsWith("_");
|
|
302604
302839
|
const startLine = i + 1;
|
|
302605
302840
|
const endLine = findBlockEnd(lines, i);
|
|
302606
302841
|
const content2 = lines.slice(i, endLine).join("\n");
|
|
302607
302842
|
definedSymbols.push({ name, symbolType: symbolType2, type: symbolType2, exported, startLine, endLine });
|
|
302843
|
+
const bodyContent = lines.slice(i, endLine).join("\n");
|
|
302844
|
+
let callMatch;
|
|
302845
|
+
const localCallRegex = new RegExp(callRegex);
|
|
302846
|
+
while ((callMatch = localCallRegex.exec(bodyContent)) !== null) {
|
|
302847
|
+
const rawCalledName = callMatch[1];
|
|
302848
|
+
const calledName = normalizePythonCallName(rawCalledName);
|
|
302849
|
+
if (!PYTHON_CALL_IGNORES.has(rawCalledName) && !PYTHON_CALL_IGNORES.has(calledName) && calledName !== name) {
|
|
302850
|
+
calledIdentifiers.add(calledName);
|
|
302851
|
+
callExpressions.push({ callerName: name, calleeName: calledName });
|
|
302852
|
+
}
|
|
302853
|
+
}
|
|
302608
302854
|
}
|
|
302609
|
-
|
|
302610
|
-
if (importMatch) {
|
|
302611
|
-
const modulePath = importMatch[1] || importMatch[2];
|
|
302612
|
-
importPaths.push(modulePath);
|
|
302613
|
-
}
|
|
302855
|
+
importPaths.push(...parsePythonImportLine(line));
|
|
302614
302856
|
}
|
|
302615
302857
|
const chunks2 = createSymbolChunks(definedSymbols, lines, "python");
|
|
302616
302858
|
if (chunks2.length === 0) {
|
|
302617
|
-
return makeFallbackChunks(content, lines);
|
|
302859
|
+
return { ...makeFallbackChunks(content, lines), callExpressions: [] };
|
|
302618
302860
|
}
|
|
302619
|
-
return { chunks: chunks2, importPaths, definedSymbols, calledIdentifiers: [] };
|
|
302861
|
+
return { chunks: chunks2, importPaths: [...new Set(importPaths)], definedSymbols, calledIdentifiers: [...calledIdentifiers], callExpressions };
|
|
302620
302862
|
}
|
|
302621
302863
|
function parseGo(content) {
|
|
302622
302864
|
const lines = content.split("\n");
|
|
@@ -302683,7 +302925,7 @@ function parseGo(content) {
|
|
|
302683
302925
|
if (chunks2.length === 0) {
|
|
302684
302926
|
return makeFallbackChunks(content, lines);
|
|
302685
302927
|
}
|
|
302686
|
-
return { chunks: chunks2, importPaths, definedSymbols, calledIdentifiers: [] };
|
|
302928
|
+
return { chunks: chunks2, importPaths, definedSymbols, calledIdentifiers: [], callExpressions: [] };
|
|
302687
302929
|
}
|
|
302688
302930
|
function parseRust(content) {
|
|
302689
302931
|
const lines = content.split("\n");
|
|
@@ -302781,7 +303023,7 @@ function parseRust(content) {
|
|
|
302781
303023
|
if (chunks2.length === 0) {
|
|
302782
303024
|
return makeFallbackChunks(content, lines);
|
|
302783
303025
|
}
|
|
302784
|
-
return { chunks: chunks2, importPaths, definedSymbols, calledIdentifiers: [] };
|
|
303026
|
+
return { chunks: chunks2, importPaths, definedSymbols, calledIdentifiers: [], callExpressions: [] };
|
|
302785
303027
|
}
|
|
302786
303028
|
function indexConfig(content, language) {
|
|
302787
303029
|
switch (language) {
|
|
@@ -303003,9 +303245,9 @@ function makeFallbackChunks(content, lines) {
|
|
|
303003
303245
|
}
|
|
303004
303246
|
});
|
|
303005
303247
|
}
|
|
303006
|
-
return { chunks: chunks2, importPaths: [], definedSymbols: [], calledIdentifiers: [] };
|
|
303248
|
+
return { chunks: chunks2, importPaths: [], definedSymbols: [], calledIdentifiers: [], callExpressions: [] };
|
|
303007
303249
|
}
|
|
303008
|
-
var import_node_path9, codeExtensions, configExtensions, markdownExtensions;
|
|
303250
|
+
var import_node_path9, codeExtensions, configExtensions, markdownExtensions, PYTHON_CALL_IGNORES;
|
|
303009
303251
|
var init_languages = __esm({
|
|
303010
303252
|
"../../packages/indexer/src/languages.ts"() {
|
|
303011
303253
|
"use strict";
|
|
@@ -303032,6 +303274,30 @@ var init_languages = __esm({
|
|
|
303032
303274
|
[".toml", "toml"]
|
|
303033
303275
|
]);
|
|
303034
303276
|
markdownExtensions = /* @__PURE__ */ new Set([".md", ".mdx"]);
|
|
303277
|
+
PYTHON_CALL_IGNORES = /* @__PURE__ */ new Set([
|
|
303278
|
+
"if",
|
|
303279
|
+
"for",
|
|
303280
|
+
"while",
|
|
303281
|
+
"with",
|
|
303282
|
+
"return",
|
|
303283
|
+
"yield",
|
|
303284
|
+
"print",
|
|
303285
|
+
"len",
|
|
303286
|
+
"range",
|
|
303287
|
+
"str",
|
|
303288
|
+
"int",
|
|
303289
|
+
"float",
|
|
303290
|
+
"list",
|
|
303291
|
+
"dict",
|
|
303292
|
+
"set",
|
|
303293
|
+
"tuple",
|
|
303294
|
+
"bool",
|
|
303295
|
+
"isinstance",
|
|
303296
|
+
"issubclass",
|
|
303297
|
+
"super",
|
|
303298
|
+
"self",
|
|
303299
|
+
"cls"
|
|
303300
|
+
]);
|
|
303035
303301
|
}
|
|
303036
303302
|
});
|
|
303037
303303
|
|
|
@@ -303104,7 +303370,10 @@ var init_scanner = __esm({
|
|
|
303104
303370
|
"**/build/**",
|
|
303105
303371
|
"**/coverage/**",
|
|
303106
303372
|
"**/.turbo/**",
|
|
303107
|
-
"**/.openez/**"
|
|
303373
|
+
"**/.openez/**",
|
|
303374
|
+
"**/pnpm-lock.yaml",
|
|
303375
|
+
"**/package-lock.json",
|
|
303376
|
+
"**/yarn.lock"
|
|
303108
303377
|
];
|
|
303109
303378
|
}
|
|
303110
303379
|
});
|
|
@@ -303141,24 +303410,68 @@ function createWorkspaceFileResolver(workspaceRoot, files) {
|
|
|
303141
303410
|
}
|
|
303142
303411
|
return null;
|
|
303143
303412
|
}
|
|
303413
|
+
function resolvePythonModulePath(modulePath) {
|
|
303414
|
+
const basePath = normalizeRelativePath(modulePath.replace(/\./g, "/"));
|
|
303415
|
+
const directPath = `${basePath}.py`;
|
|
303416
|
+
if (knownRelativePaths.has(directPath)) return directPath;
|
|
303417
|
+
const initPath = `${basePath}/__init__.py`;
|
|
303418
|
+
if (knownRelativePaths.has(initPath)) return initPath;
|
|
303419
|
+
return null;
|
|
303420
|
+
}
|
|
303421
|
+
function resolvePythonRelativeImport(importerRelativePath, importPath) {
|
|
303422
|
+
const dotMatch = /^(\.+)(.*)$/.exec(importPath);
|
|
303423
|
+
if (!dotMatch) return null;
|
|
303424
|
+
const level = dotMatch[1].length;
|
|
303425
|
+
const remainder = dotMatch[2].replace(/^\./, "");
|
|
303426
|
+
let baseDirectory = normalizeRelativePath(import_node_path11.default.dirname(importerRelativePath));
|
|
303427
|
+
for (let index2 = 1; index2 < level; index2++) {
|
|
303428
|
+
baseDirectory = normalizeRelativePath(import_node_path11.default.dirname(baseDirectory));
|
|
303429
|
+
}
|
|
303430
|
+
const modulePath = remainder ? normalizeRelativePath(import_node_path11.default.join(baseDirectory, remainder.replace(/\./g, "/"))) : baseDirectory;
|
|
303431
|
+
return resolvePythonModulePath(modulePath);
|
|
303432
|
+
}
|
|
303433
|
+
function resolvePythonImport(importerRelativePath, importPath) {
|
|
303434
|
+
if (importPath.startsWith(".")) {
|
|
303435
|
+
const resolved = resolvePythonRelativeImport(importerRelativePath, importPath);
|
|
303436
|
+
if (resolved) return resolved;
|
|
303437
|
+
}
|
|
303438
|
+
return resolvePythonModulePath(importPath);
|
|
303439
|
+
}
|
|
303144
303440
|
return {
|
|
303145
|
-
resolveImport(importerRelativePath, importPath) {
|
|
303146
|
-
if (
|
|
303147
|
-
|
|
303441
|
+
resolveImport(importerRelativePath, importPath, language) {
|
|
303442
|
+
if (language === "python") {
|
|
303443
|
+
const resolved = resolvePythonImport(importerRelativePath, importPath);
|
|
303444
|
+
if (resolved) return resolved;
|
|
303445
|
+
}
|
|
303446
|
+
if (importPath.startsWith(".")) {
|
|
303447
|
+
return resolveRelativeImport(importerRelativePath, importPath);
|
|
303448
|
+
}
|
|
303449
|
+
return null;
|
|
303148
303450
|
}
|
|
303149
303451
|
};
|
|
303150
303452
|
}
|
|
303151
303453
|
async function resetDocumentArtifacts(repo, documentId) {
|
|
303152
303454
|
const chunks2 = await repo.getChunksByDocument(documentId);
|
|
303153
303455
|
const chunkIds = chunks2.map((c) => c.id);
|
|
303154
|
-
const allNodeIds = [documentId, ...chunkIds];
|
|
303155
303456
|
if (chunkIds.length > 0) {
|
|
303156
303457
|
await repo.deleteEmbeddingsByChunkIds(chunkIds);
|
|
303157
303458
|
}
|
|
303158
|
-
await repo.deleteEdgesByNodeIds(allNodeIds);
|
|
303159
303459
|
await repo.deleteGraphNodesByRefId(documentId);
|
|
303160
303460
|
await repo.deleteChunksByDocument(documentId);
|
|
303161
303461
|
}
|
|
303462
|
+
function boundChunks(chunks2, targetTokens, overlapTokens) {
|
|
303463
|
+
return chunks2.flatMap((chunk) => {
|
|
303464
|
+
const parts = splitToTokenLimit(chunk.content, targetTokens, overlapTokens);
|
|
303465
|
+
if (parts.length <= 1) return chunk;
|
|
303466
|
+
return parts.map((content, splitIndex) => ({
|
|
303467
|
+
...chunk,
|
|
303468
|
+
content,
|
|
303469
|
+
tokenCount: countTokens2(content),
|
|
303470
|
+
contentHash: hashContent(content),
|
|
303471
|
+
metadata: { ...chunk.metadata, splitIndex, splitCount: parts.length }
|
|
303472
|
+
}));
|
|
303473
|
+
});
|
|
303474
|
+
}
|
|
303162
303475
|
async function chunkDocument(input) {
|
|
303163
303476
|
const info = inferDocumentKind(input.relativePath);
|
|
303164
303477
|
if (info.kind === "markdown") {
|
|
@@ -303174,7 +303487,8 @@ async function chunkDocument(input) {
|
|
|
303174
303487
|
importPaths: [],
|
|
303175
303488
|
wikilinks: result.wikilinks,
|
|
303176
303489
|
definedSymbols: [],
|
|
303177
|
-
calledIdentifiers: []
|
|
303490
|
+
calledIdentifiers: [],
|
|
303491
|
+
callExpressions: []
|
|
303178
303492
|
};
|
|
303179
303493
|
}
|
|
303180
303494
|
if (info.kind === "config") {
|
|
@@ -303186,7 +303500,8 @@ async function chunkDocument(input) {
|
|
|
303186
303500
|
importPaths: [],
|
|
303187
303501
|
wikilinks: [],
|
|
303188
303502
|
definedSymbols: [],
|
|
303189
|
-
calledIdentifiers: []
|
|
303503
|
+
calledIdentifiers: [],
|
|
303504
|
+
callExpressions: []
|
|
303190
303505
|
};
|
|
303191
303506
|
}
|
|
303192
303507
|
if (info.kind === "code") {
|
|
@@ -303199,7 +303514,8 @@ async function chunkDocument(input) {
|
|
|
303199
303514
|
importPaths: result.importPaths,
|
|
303200
303515
|
wikilinks: [],
|
|
303201
303516
|
definedSymbols: result.definedSymbols,
|
|
303202
|
-
calledIdentifiers: result.calledIdentifiers
|
|
303517
|
+
calledIdentifiers: result.calledIdentifiers,
|
|
303518
|
+
callExpressions: result.callExpressions
|
|
303203
303519
|
};
|
|
303204
303520
|
}
|
|
303205
303521
|
if (info.language === "python") {
|
|
@@ -303211,7 +303527,8 @@ async function chunkDocument(input) {
|
|
|
303211
303527
|
importPaths: result.importPaths,
|
|
303212
303528
|
wikilinks: [],
|
|
303213
303529
|
definedSymbols: result.definedSymbols,
|
|
303214
|
-
calledIdentifiers: result.calledIdentifiers
|
|
303530
|
+
calledIdentifiers: result.calledIdentifiers,
|
|
303531
|
+
callExpressions: result.callExpressions
|
|
303215
303532
|
};
|
|
303216
303533
|
}
|
|
303217
303534
|
if (info.language === "go") {
|
|
@@ -303223,7 +303540,8 @@ async function chunkDocument(input) {
|
|
|
303223
303540
|
importPaths: result.importPaths,
|
|
303224
303541
|
wikilinks: [],
|
|
303225
303542
|
definedSymbols: result.definedSymbols,
|
|
303226
|
-
calledIdentifiers: result.calledIdentifiers
|
|
303543
|
+
calledIdentifiers: result.calledIdentifiers,
|
|
303544
|
+
callExpressions: result.callExpressions
|
|
303227
303545
|
};
|
|
303228
303546
|
}
|
|
303229
303547
|
if (info.language === "rust") {
|
|
@@ -303235,7 +303553,8 @@ async function chunkDocument(input) {
|
|
|
303235
303553
|
importPaths: result.importPaths,
|
|
303236
303554
|
wikilinks: [],
|
|
303237
303555
|
definedSymbols: result.definedSymbols,
|
|
303238
|
-
calledIdentifiers: result.calledIdentifiers
|
|
303556
|
+
calledIdentifiers: result.calledIdentifiers,
|
|
303557
|
+
callExpressions: result.callExpressions
|
|
303239
303558
|
};
|
|
303240
303559
|
}
|
|
303241
303560
|
const fallbackChunk2 = {
|
|
@@ -303256,7 +303575,8 @@ async function chunkDocument(input) {
|
|
|
303256
303575
|
importPaths: [],
|
|
303257
303576
|
wikilinks: [],
|
|
303258
303577
|
definedSymbols: [],
|
|
303259
|
-
calledIdentifiers: []
|
|
303578
|
+
calledIdentifiers: [],
|
|
303579
|
+
callExpressions: []
|
|
303260
303580
|
};
|
|
303261
303581
|
}
|
|
303262
303582
|
const fallbackChunk = {
|
|
@@ -303276,19 +303596,33 @@ async function chunkDocument(input) {
|
|
|
303276
303596
|
importPaths: [],
|
|
303277
303597
|
wikilinks: [],
|
|
303278
303598
|
definedSymbols: [],
|
|
303279
|
-
calledIdentifiers: []
|
|
303599
|
+
calledIdentifiers: [],
|
|
303600
|
+
callExpressions: []
|
|
303280
303601
|
};
|
|
303281
303602
|
}
|
|
303282
|
-
async function writeEmbeddingsToRepo(repo, chunkRows) {
|
|
303283
|
-
const provider = getEmbeddingProvider();
|
|
303603
|
+
async function writeEmbeddingsToRepo(repo, chunkRows, provider) {
|
|
303284
303604
|
if (!provider || chunkRows.length === 0) {
|
|
303285
303605
|
return 0;
|
|
303286
303606
|
}
|
|
303607
|
+
const existing = await repo.queryRaw(
|
|
303608
|
+
`SELECT chunk_id FROM embeddings
|
|
303609
|
+
WHERE provider = ? AND model = ? AND chunk_id IN (${chunkRows.map(() => "?").join(",")})`,
|
|
303610
|
+
[provider.provider, embeddingStorageModel(provider), ...chunkRows.map((chunk) => chunk.id)]
|
|
303611
|
+
);
|
|
303612
|
+
const existingIds = new Set(existing.map((row) => String(row.chunk_id)));
|
|
303613
|
+
const missingRows = chunkRows.filter((chunk) => !existingIds.has(chunk.id));
|
|
303614
|
+
if (missingRows.length === 0) return 0;
|
|
303287
303615
|
try {
|
|
303288
|
-
const vectors = await provider.embed(
|
|
303616
|
+
const vectors = await provider.embed(
|
|
303617
|
+
missingRows.map((chunk) => formatEmbeddingInput(provider, chunk, "document"))
|
|
303618
|
+
);
|
|
303619
|
+
if (vectors.length !== missingRows.length) {
|
|
303620
|
+
console.error(`Embedding provider returned ${vectors.length} vectors for ${missingRows.length} chunks`);
|
|
303621
|
+
return 0;
|
|
303622
|
+
}
|
|
303289
303623
|
const invalidEmbeddingIndex = vectors.findIndex((embedding) => embedding.length === 0);
|
|
303290
303624
|
if (invalidEmbeddingIndex !== -1) {
|
|
303291
|
-
console.error(`Embedding provider returned empty vector for chunk ${
|
|
303625
|
+
console.error(`Embedding provider returned empty vector for chunk ${missingRows[invalidEmbeddingIndex].id}`);
|
|
303292
303626
|
return 0;
|
|
303293
303627
|
}
|
|
303294
303628
|
const dimensions = vectors[0]?.length ?? 0;
|
|
@@ -303298,9 +303632,9 @@ async function writeEmbeddingsToRepo(repo, chunkRows) {
|
|
|
303298
303632
|
}
|
|
303299
303633
|
await repo.insertEmbeddings(
|
|
303300
303634
|
vectors.map((embedding, index2) => ({
|
|
303301
|
-
chunkId:
|
|
303635
|
+
chunkId: missingRows[index2].id,
|
|
303302
303636
|
provider: provider.provider,
|
|
303303
|
-
model: provider
|
|
303637
|
+
model: embeddingStorageModel(provider),
|
|
303304
303638
|
dimensions,
|
|
303305
303639
|
embedding: JSON.stringify(embedding)
|
|
303306
303640
|
}))
|
|
@@ -303328,20 +303662,36 @@ async function indexWorkspace(input) {
|
|
|
303328
303662
|
await writeLocalWorkspaceConfig(workspace);
|
|
303329
303663
|
const repo = createWorkspaceRepository(workspace.rootPath);
|
|
303330
303664
|
const settings = await getBrainSettings();
|
|
303665
|
+
const config2 = await loadBrainConfig(workspace.rootPath);
|
|
303666
|
+
const configuredWorkspace = config2.workspaces?.find(
|
|
303667
|
+
(candidate) => candidate.id === workspace.id || import_node_path11.default.resolve(candidate.root) === import_node_path11.default.resolve(workspace.rootPath)
|
|
303668
|
+
);
|
|
303669
|
+
const includeGlobs = workspace.includeGlobs || configuredWorkspace?.include.join("\n") || "";
|
|
303670
|
+
const excludeGlobs = workspace.excludeGlobs || configuredWorkspace?.exclude.join("\n") || "";
|
|
303671
|
+
const embeddingProvider = getEmbeddingProvider();
|
|
303331
303672
|
const runMode = input.mode ?? "incremental";
|
|
303332
303673
|
const reportProgress = async (message, progress) => {
|
|
303333
303674
|
await input.onProgress?.({ message, progress });
|
|
303334
303675
|
};
|
|
303335
|
-
const runId = await repo.createIndexRun({ mode: runMode });
|
|
303336
303676
|
if (runMode === "full") {
|
|
303337
303677
|
await repo.resetAll();
|
|
303338
303678
|
}
|
|
303679
|
+
const runId = await repo.createIndexRun({ mode: runMode });
|
|
303339
303680
|
await reportProgress("Scanning workspace files...", 5);
|
|
303340
303681
|
const files = await scanWorkspaceFiles({
|
|
303341
303682
|
rootPath: workspace.rootPath,
|
|
303342
|
-
include:
|
|
303343
|
-
exclude:
|
|
303683
|
+
include: includeGlobs,
|
|
303684
|
+
exclude: excludeGlobs
|
|
303344
303685
|
});
|
|
303686
|
+
if (runMode === "incremental") {
|
|
303687
|
+
const scannedPaths = new Set(files.map((file) => file.relativePath));
|
|
303688
|
+
for (const document of await repo.listDocuments()) {
|
|
303689
|
+
if (!scannedPaths.has(document.path)) {
|
|
303690
|
+
await resetDocumentArtifacts(repo, document.id);
|
|
303691
|
+
await repo.deleteDocument(document.id);
|
|
303692
|
+
}
|
|
303693
|
+
}
|
|
303694
|
+
}
|
|
303345
303695
|
const workspaceFileResolver = createWorkspaceFileResolver(
|
|
303346
303696
|
workspace.rootPath,
|
|
303347
303697
|
files.map((file) => ({
|
|
@@ -303352,6 +303702,8 @@ async function indexWorkspace(input) {
|
|
|
303352
303702
|
let filesUpdated = 0;
|
|
303353
303703
|
let chunksWritten = 0;
|
|
303354
303704
|
let embeddingsWritten = 0;
|
|
303705
|
+
const symbolNodeIdsByName = /* @__PURE__ */ new Map();
|
|
303706
|
+
const pendingCallEdges = [];
|
|
303355
303707
|
try {
|
|
303356
303708
|
await reportProgress(
|
|
303357
303709
|
files.length === 0 ? "No files matched the workspace filters" : `Queued ${files.length} file(s) for indexing`,
|
|
@@ -303363,7 +303715,19 @@ async function indexWorkspace(input) {
|
|
|
303363
303715
|
const content = await import_promises7.default.readFile(file.absolutePath, "utf8");
|
|
303364
303716
|
const contentHash = hashContent(content);
|
|
303365
303717
|
const existingDocument = await repo.getDocumentByPath(file.relativePath);
|
|
303366
|
-
|
|
303718
|
+
const existingChunks = existingDocument ? await repo.getChunksByDocument(existingDocument.id) : [];
|
|
303719
|
+
const unchanged = runMode === "incremental" && existingDocument && existingDocument.contentHash === contentHash && existingDocument.mtimeMs === file.mtimeMs;
|
|
303720
|
+
if (unchanged) {
|
|
303721
|
+
embeddingsWritten += await writeEmbeddingsToRepo(
|
|
303722
|
+
repo,
|
|
303723
|
+
existingChunks.map((chunk) => ({
|
|
303724
|
+
id: chunk.id,
|
|
303725
|
+
content: chunk.content,
|
|
303726
|
+
path: existingDocument.path,
|
|
303727
|
+
heading: chunk.heading
|
|
303728
|
+
})),
|
|
303729
|
+
embeddingProvider
|
|
303730
|
+
);
|
|
303367
303731
|
continue;
|
|
303368
303732
|
}
|
|
303369
303733
|
const indexed = await chunkDocument({
|
|
@@ -303373,6 +303737,7 @@ async function indexWorkspace(input) {
|
|
|
303373
303737
|
targetTokens: settings.chunking.targetTokens,
|
|
303374
303738
|
overlapTokens: settings.chunking.overlapTokens
|
|
303375
303739
|
});
|
|
303740
|
+
indexed.chunks = boundChunks(indexed.chunks, settings.chunking.targetTokens, settings.chunking.overlapTokens);
|
|
303376
303741
|
let documentId;
|
|
303377
303742
|
if (existingDocument) {
|
|
303378
303743
|
await resetDocumentArtifacts(repo, existingDocument.id);
|
|
@@ -303450,10 +303815,11 @@ async function indexWorkspace(input) {
|
|
|
303450
303815
|
toNodeId: chunkNodeId,
|
|
303451
303816
|
type: "represented_by"
|
|
303452
303817
|
});
|
|
303818
|
+
symbolNodeIdsByName.set(symbolName, symbolNodeId);
|
|
303453
303819
|
}
|
|
303454
303820
|
}
|
|
303455
303821
|
for (const importPath of indexed.importPaths) {
|
|
303456
|
-
const resolvedImportPath = workspaceFileResolver
|
|
303822
|
+
const resolvedImportPath = workspaceFileResolver?.resolveImport(file.relativePath, importPath, indexed.language ?? void 0);
|
|
303457
303823
|
if (!resolvedImportPath) continue;
|
|
303458
303824
|
const targetNodeId = await repo.upsertGraphNode({
|
|
303459
303825
|
type: "file",
|
|
@@ -303479,43 +303845,33 @@ async function indexWorkspace(input) {
|
|
|
303479
303845
|
type: "mentions"
|
|
303480
303846
|
});
|
|
303481
303847
|
}
|
|
303482
|
-
|
|
303483
|
-
const symbolNodeIds = await Promise.all(
|
|
303484
|
-
indexed.definedSymbols.map(
|
|
303485
|
-
(symbol) => repo.upsertGraphNode({
|
|
303486
|
-
type: "symbol",
|
|
303487
|
-
label: symbol.name,
|
|
303488
|
-
metadata: JSON.stringify({
|
|
303489
|
-
symbolType: symbol.type,
|
|
303490
|
-
exported: symbol.exported,
|
|
303491
|
-
filePath: file.relativePath
|
|
303492
|
-
})
|
|
303493
|
-
})
|
|
303494
|
-
)
|
|
303495
|
-
);
|
|
303496
|
-
for (const caller of indexed.calledIdentifiers) {
|
|
303497
|
-
const callerIndex = indexed.definedSymbols.findIndex((s) => s.name === caller);
|
|
303498
|
-
if (callerIndex === -1) continue;
|
|
303499
|
-
const calleeNode = await repo.findGraphNode("symbol", caller);
|
|
303500
|
-
if (calleeNode && symbolNodeIds[callerIndex] !== calleeNode.id) {
|
|
303501
|
-
await repo.insertEdge({
|
|
303502
|
-
fromNodeId: symbolNodeIds[callerIndex],
|
|
303503
|
-
toNodeId: calleeNode.id,
|
|
303504
|
-
type: "calls",
|
|
303505
|
-
weight: 0.35,
|
|
303506
|
-
metadata: JSON.stringify({ heuristic: true })
|
|
303507
|
-
});
|
|
303508
|
-
}
|
|
303509
|
-
}
|
|
303510
|
-
}
|
|
303848
|
+
pendingCallEdges.push(...indexed.callExpressions);
|
|
303511
303849
|
const chunkRows = chunkIds.map((id, i) => ({
|
|
303512
303850
|
id,
|
|
303513
|
-
content: indexed.chunks[i].content
|
|
303851
|
+
content: indexed.chunks[i].content,
|
|
303852
|
+
path: file.relativePath,
|
|
303853
|
+
heading: indexed.chunks[i].heading
|
|
303514
303854
|
}));
|
|
303515
|
-
embeddingsWritten += await writeEmbeddingsToRepo(repo, chunkRows);
|
|
303855
|
+
embeddingsWritten += await writeEmbeddingsToRepo(repo, chunkRows, embeddingProvider);
|
|
303516
303856
|
chunksWritten += chunkIds.length;
|
|
303517
303857
|
filesUpdated += 1;
|
|
303518
303858
|
}
|
|
303859
|
+
const insertedCallEdges = /* @__PURE__ */ new Set();
|
|
303860
|
+
for (const callExpression of pendingCallEdges) {
|
|
303861
|
+
const callerNodeId = symbolNodeIdsByName.get(callExpression.callerName) ?? (await repo.findGraphNode("symbol", callExpression.callerName))?.id;
|
|
303862
|
+
const calleeNodeId = symbolNodeIdsByName.get(callExpression.calleeName) ?? (await repo.findGraphNode("symbol", callExpression.calleeName))?.id;
|
|
303863
|
+
if (!callerNodeId || !calleeNodeId || callerNodeId === calleeNodeId) continue;
|
|
303864
|
+
const edgeKey = `${callerNodeId}:${calleeNodeId}:calls`;
|
|
303865
|
+
if (insertedCallEdges.has(edgeKey)) continue;
|
|
303866
|
+
insertedCallEdges.add(edgeKey);
|
|
303867
|
+
await repo.insertEdge({
|
|
303868
|
+
fromNodeId: callerNodeId,
|
|
303869
|
+
toNodeId: calleeNodeId,
|
|
303870
|
+
type: "calls",
|
|
303871
|
+
weight: 0.35,
|
|
303872
|
+
metadata: JSON.stringify({ heuristic: true, callee: callExpression.calleeName })
|
|
303873
|
+
});
|
|
303874
|
+
}
|
|
303519
303875
|
await reportProgress("Finalizing index run...", 98);
|
|
303520
303876
|
await repo.completeIndexRun(runId, {
|
|
303521
303877
|
status: "completed",
|
|
@@ -303588,7 +303944,8 @@ var init_index_workspace = __esm({
|
|
|
303588
303944
|
".mts",
|
|
303589
303945
|
".cts",
|
|
303590
303946
|
".md",
|
|
303591
|
-
".mdx"
|
|
303947
|
+
".mdx",
|
|
303948
|
+
".py"
|
|
303592
303949
|
];
|
|
303593
303950
|
}
|
|
303594
303951
|
});
|
|
@@ -318760,6 +319117,15 @@ var init_mcp_bridge = __esm({
|
|
|
318760
319117
|
});
|
|
318761
319118
|
|
|
318762
319119
|
// ../web/src/server/sqlite.ts
|
|
319120
|
+
function getRequireUrl2() {
|
|
319121
|
+
try {
|
|
319122
|
+
if (typeof import_meta3 !== "undefined" && import_meta3.url) {
|
|
319123
|
+
return import_meta3.url;
|
|
319124
|
+
}
|
|
319125
|
+
} catch {
|
|
319126
|
+
}
|
|
319127
|
+
return `file://${__filename}`;
|
|
319128
|
+
}
|
|
318763
319129
|
function safeParseJson3(value, fallback) {
|
|
318764
319130
|
if (!value) return fallback;
|
|
318765
319131
|
try {
|
|
@@ -319165,9 +319531,7 @@ var init_sqlite2 = __esm({
|
|
|
319165
319531
|
import_node_path13 = __toESM(require("path"), 1);
|
|
319166
319532
|
import_node_module2 = require("module");
|
|
319167
319533
|
import_meta3 = {};
|
|
319168
|
-
require2 = (0, import_node_module2.createRequire)(
|
|
319169
|
-
typeof import_meta3 !== "undefined" && import_meta3.url ? import_meta3.url : `file://${__filename}`
|
|
319170
|
-
);
|
|
319534
|
+
require2 = (0, import_node_module2.createRequire)(getRequireUrl2());
|
|
319171
319535
|
Database = require2("better-sqlite3");
|
|
319172
319536
|
registryDb2 = null;
|
|
319173
319537
|
workspaceDbs = /* @__PURE__ */ new Map();
|
|
@@ -319188,6 +319552,15 @@ var init_sqlite2 = __esm({
|
|
|
319188
319552
|
});
|
|
319189
319553
|
|
|
319190
319554
|
// ../web/src/server/index.ts
|
|
319555
|
+
function getDirname() {
|
|
319556
|
+
try {
|
|
319557
|
+
if (typeof import_meta4 !== "undefined" && import_meta4.url) {
|
|
319558
|
+
return import_node_path14.default.dirname(new URL(import_meta4.url).pathname);
|
|
319559
|
+
}
|
|
319560
|
+
} catch {
|
|
319561
|
+
}
|
|
319562
|
+
return typeof __dirname2 !== "undefined" ? __dirname2 : process.cwd();
|
|
319563
|
+
}
|
|
319191
319564
|
function mapWorkspace2(ws) {
|
|
319192
319565
|
return {
|
|
319193
319566
|
id: ws.id,
|
|
@@ -319210,9 +319583,9 @@ function mapWorkspace2(ws) {
|
|
|
319210
319583
|
};
|
|
319211
319584
|
}
|
|
319212
319585
|
function resolveWebDist() {
|
|
319213
|
-
const sourceDist = import_node_path14.default.resolve(
|
|
319586
|
+
const sourceDist = import_node_path14.default.resolve(__dirname2, "..", "dist");
|
|
319214
319587
|
if ((0, import_node_fs10.existsSync)(import_node_path14.default.join(sourceDist, "index.html"))) return sourceDist;
|
|
319215
|
-
const cliDist = import_node_path14.default.resolve(
|
|
319588
|
+
const cliDist = import_node_path14.default.resolve(__dirname2, "web");
|
|
319216
319589
|
if ((0, import_node_fs10.existsSync)(import_node_path14.default.join(cliDist, "index.html"))) return cliDist;
|
|
319217
319590
|
return null;
|
|
319218
319591
|
}
|
|
@@ -319228,7 +319601,7 @@ function createWebServer() {
|
|
|
319228
319601
|
}
|
|
319229
319602
|
return app;
|
|
319230
319603
|
}
|
|
319231
|
-
var import_serve_static, import_hono, import_cors, import_node_crypto3, import_node_fs10, import_node_path14, app, DEFAULT_INCLUDE_GLOBS, DEFAULT_EXCLUDE_GLOBS;
|
|
319604
|
+
var import_serve_static, import_hono, import_cors, import_node_crypto3, import_node_fs10, import_node_path14, import_meta4, __dirname2, app, DEFAULT_INCLUDE_GLOBS, DEFAULT_EXCLUDE_GLOBS;
|
|
319232
319605
|
var init_server3 = __esm({
|
|
319233
319606
|
"../web/src/server/index.ts"() {
|
|
319234
319607
|
"use strict";
|
|
@@ -319241,11 +319614,21 @@ var init_server3 = __esm({
|
|
|
319241
319614
|
init_sqlite2();
|
|
319242
319615
|
init_src3();
|
|
319243
319616
|
init_src();
|
|
319617
|
+
import_meta4 = {};
|
|
319618
|
+
__dirname2 = getDirname();
|
|
319244
319619
|
app = new import_hono.Hono();
|
|
319245
|
-
app.use(
|
|
319246
|
-
|
|
319247
|
-
|
|
319248
|
-
|
|
319620
|
+
app.use(
|
|
319621
|
+
"/*",
|
|
319622
|
+
(0, import_cors.cors)({
|
|
319623
|
+
origin: [
|
|
319624
|
+
"http://localhost:5173",
|
|
319625
|
+
"http://127.0.0.1:5173",
|
|
319626
|
+
"http://localhost:11368",
|
|
319627
|
+
"http://127.0.0.1:11368"
|
|
319628
|
+
],
|
|
319629
|
+
credentials: true
|
|
319630
|
+
})
|
|
319631
|
+
);
|
|
319249
319632
|
DEFAULT_INCLUDE_GLOBS = [
|
|
319250
319633
|
"src/**/*.{ts,tsx,js,jsx}",
|
|
319251
319634
|
"app/**/*.{ts,tsx}",
|
|
@@ -319276,7 +319659,13 @@ var init_server3 = __esm({
|
|
|
319276
319659
|
if (!target) {
|
|
319277
319660
|
return c.json({
|
|
319278
319661
|
workspace: { id: "", name: "No workspace", root: "" },
|
|
319279
|
-
stats: {
|
|
319662
|
+
stats: {
|
|
319663
|
+
documents: 0,
|
|
319664
|
+
chunks: 0,
|
|
319665
|
+
graphNodes: 0,
|
|
319666
|
+
graphEdges: 0,
|
|
319667
|
+
memories: 0
|
|
319668
|
+
},
|
|
319280
319669
|
recentRuns: [],
|
|
319281
319670
|
recentDocuments: [],
|
|
319282
319671
|
recentMemories: [],
|
|
@@ -319303,7 +319692,13 @@ var init_server3 = __esm({
|
|
|
319303
319692
|
console.error("Dashboard error:", err);
|
|
319304
319693
|
return c.json({
|
|
319305
319694
|
workspace: { id: "", name: "No workspace", root: "" },
|
|
319306
|
-
stats: {
|
|
319695
|
+
stats: {
|
|
319696
|
+
documents: 0,
|
|
319697
|
+
chunks: 0,
|
|
319698
|
+
graphNodes: 0,
|
|
319699
|
+
graphEdges: 0,
|
|
319700
|
+
memories: 0
|
|
319701
|
+
},
|
|
319307
319702
|
recentRuns: [],
|
|
319308
319703
|
recentDocuments: [],
|
|
319309
319704
|
recentMemories: [],
|
|
@@ -319343,10 +319738,14 @@ var init_server3 = __esm({
|
|
|
319343
319738
|
if (!rootPath) return c.json({ valid: false, error: "Path is required" });
|
|
319344
319739
|
try {
|
|
319345
319740
|
const stats = await import_node_fs10.promises.stat(rootPath);
|
|
319346
|
-
if (!stats.isDirectory())
|
|
319741
|
+
if (!stats.isDirectory())
|
|
319742
|
+
return c.json({ valid: false, error: "Path is not a directory" });
|
|
319347
319743
|
return c.json({ valid: true });
|
|
319348
319744
|
} catch {
|
|
319349
|
-
return c.json({
|
|
319745
|
+
return c.json({
|
|
319746
|
+
valid: false,
|
|
319747
|
+
error: "Directory does not exist or is not accessible"
|
|
319748
|
+
});
|
|
319350
319749
|
}
|
|
319351
319750
|
});
|
|
319352
319751
|
app.get("/api/workspaces", (c) => {
|
|
@@ -319370,7 +319769,11 @@ var init_server3 = __esm({
|
|
|
319370
319769
|
return c.json({ ok: true, data });
|
|
319371
319770
|
} catch (err) {
|
|
319372
319771
|
const message = err instanceof Error ? err.message : String(err);
|
|
319373
|
-
return c.json({
|
|
319772
|
+
return c.json({
|
|
319773
|
+
ok: false,
|
|
319774
|
+
error: message,
|
|
319775
|
+
dbPath: resolveRegistryDbPath2()
|
|
319776
|
+
});
|
|
319374
319777
|
}
|
|
319375
319778
|
});
|
|
319376
319779
|
app.get("/api/workspaces/:id", (c) => {
|
|
@@ -319388,19 +319791,28 @@ var init_server3 = __esm({
|
|
|
319388
319791
|
return c.json({ ok: true, data });
|
|
319389
319792
|
} catch (err) {
|
|
319390
319793
|
const message = err instanceof Error ? err.message : String(err);
|
|
319391
|
-
return c.json({
|
|
319794
|
+
return c.json({
|
|
319795
|
+
ok: false,
|
|
319796
|
+
error: message,
|
|
319797
|
+
dbPath: resolveRegistryDbPath2()
|
|
319798
|
+
});
|
|
319392
319799
|
}
|
|
319393
319800
|
});
|
|
319394
319801
|
app.post("/api/workspaces", async (c) => {
|
|
319395
319802
|
try {
|
|
319396
319803
|
const body = await c.req.json();
|
|
319397
319804
|
const rootPath = body.rootPath;
|
|
319398
|
-
if (!rootPath)
|
|
319805
|
+
if (!rootPath)
|
|
319806
|
+
return c.json({ success: false, error: "rootPath is required" });
|
|
319399
319807
|
try {
|
|
319400
319808
|
const stats = await import_node_fs10.promises.stat(rootPath);
|
|
319401
|
-
if (!stats.isDirectory())
|
|
319809
|
+
if (!stats.isDirectory())
|
|
319810
|
+
return c.json({ success: false, error: "Path is not a directory" });
|
|
319402
319811
|
} catch {
|
|
319403
|
-
return c.json({
|
|
319812
|
+
return c.json({
|
|
319813
|
+
success: false,
|
|
319814
|
+
error: "Directory does not exist or is not accessible"
|
|
319815
|
+
});
|
|
319404
319816
|
}
|
|
319405
319817
|
const ws = ensureRegistryWorkspace({
|
|
319406
319818
|
name: body.name?.trim() || import_node_path14.default.basename(rootPath),
|
|
@@ -319410,7 +319822,11 @@ var init_server3 = __esm({
|
|
|
319410
319822
|
});
|
|
319411
319823
|
return c.json({
|
|
319412
319824
|
success: true,
|
|
319413
|
-
workspace: {
|
|
319825
|
+
workspace: {
|
|
319826
|
+
...mapWorkspace2(ws),
|
|
319827
|
+
latestIndexRun: null,
|
|
319828
|
+
latestGraphRun: null
|
|
319829
|
+
}
|
|
319414
319830
|
});
|
|
319415
319831
|
} catch (err) {
|
|
319416
319832
|
console.error("Failed to create workspace:", err);
|
|
@@ -319436,7 +319852,11 @@ var init_server3 = __esm({
|
|
|
319436
319852
|
app.post("/api/workspaces/:id/index", async (c) => {
|
|
319437
319853
|
const id = c.req.param("id");
|
|
319438
319854
|
const ws = getRegistryWorkspace(id);
|
|
319439
|
-
if (!ws)
|
|
319855
|
+
if (!ws)
|
|
319856
|
+
return c.json(
|
|
319857
|
+
{ jobId: null, status: "error", error: "Workspace not found" },
|
|
319858
|
+
404
|
|
319859
|
+
);
|
|
319440
319860
|
const body = await c.req.json().catch(() => ({ mode: "incremental" }));
|
|
319441
319861
|
updateRegistryWorkspace(id, {
|
|
319442
319862
|
indexingStatus: "running",
|
|
@@ -319610,8 +320030,11 @@ function getThisDir() {
|
|
|
319610
320030
|
if (typeof __dirname !== "undefined") {
|
|
319611
320031
|
return __dirname;
|
|
319612
320032
|
}
|
|
319613
|
-
|
|
319614
|
-
|
|
320033
|
+
try {
|
|
320034
|
+
if (typeof import_meta5 !== "undefined" && import_meta5.dirname) {
|
|
320035
|
+
return import_meta5.dirname;
|
|
320036
|
+
}
|
|
320037
|
+
} catch {
|
|
319615
320038
|
}
|
|
319616
320039
|
return process.cwd();
|
|
319617
320040
|
}
|
|
@@ -319643,13 +320066,13 @@ function resolveCliInvocation() {
|
|
|
319643
320066
|
repoRoot
|
|
319644
320067
|
};
|
|
319645
320068
|
}
|
|
319646
|
-
var import_node_fs11, import_node_path15,
|
|
320069
|
+
var import_node_fs11, import_node_path15, import_meta5;
|
|
319647
320070
|
var init_resolve_cli = __esm({
|
|
319648
320071
|
"src/resolve-cli.ts"() {
|
|
319649
320072
|
"use strict";
|
|
319650
320073
|
import_node_fs11 = __toESM(require("fs"), 1);
|
|
319651
320074
|
import_node_path15 = __toESM(require("path"), 1);
|
|
319652
|
-
|
|
320075
|
+
import_meta5 = {};
|
|
319653
320076
|
}
|
|
319654
320077
|
});
|
|
319655
320078
|
|
|
@@ -320773,7 +321196,7 @@ var {
|
|
|
320773
321196
|
init_src();
|
|
320774
321197
|
init_src4();
|
|
320775
321198
|
var program2 = new Command();
|
|
320776
|
-
program2.name("openez").description("OpenEZ Graph - Local-first knowledge retrieval system").version("0.
|
|
321199
|
+
program2.name("openez").description("OpenEZ Graph - Local-first knowledge retrieval system").version("0.4.0");
|
|
320777
321200
|
program2.command("init").description("Initialize a workspace at the given path and run initial index").argument("[path]", "path to the project directory", process.cwd()).option("--no-index", "skip initial indexing").action(async (targetPath, options) => {
|
|
320778
321201
|
const resolvedPath = import_node_path19.default.resolve(targetPath);
|
|
320779
321202
|
if (!import_node_fs15.default.existsSync(resolvedPath)) {
|