ctxloom-pro 1.0.4

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,125 @@
1
+ import {
2
+ logger
3
+ } from "./chunk-IHXVD5SO.js";
4
+
5
+ // src/db/VectorStore.js
6
+ import lancedb from "@lancedb/lancedb";
7
+ import { makeArrowTable } from "@lancedb/lancedb";
8
+ import path from "path";
9
+ import fs from "fs";
10
+ function sanitizeFilterPath(filePath) {
11
+ return filePath.replace(/[^a-zA-Z0-9/._\- ]/g, "_");
12
+ }
13
+ var VectorStore = class {
14
+ dbPath;
15
+ db = null;
16
+ table = null;
17
+ initialized = false;
18
+ constructor(dbPath) {
19
+ this.dbPath = dbPath ?? path.join(process.cwd(), ".ctxloom", "vectors.lancedb");
20
+ }
21
+ async init() {
22
+ if (this.initialized)
23
+ return;
24
+ const dir = path.dirname(this.dbPath);
25
+ if (!fs.existsSync(dir)) {
26
+ fs.mkdirSync(dir, { recursive: true });
27
+ }
28
+ this.db = await lancedb.connect(this.dbPath);
29
+ const existingTables = await this.db.tableNames();
30
+ if (existingTables.includes("code_embeddings")) {
31
+ this.table = await this.db.openTable("code_embeddings");
32
+ } else {
33
+ const seedTable = makeArrowTable([
34
+ {
35
+ id: "__seed__",
36
+ filePath: "__seed__",
37
+ vector: new Array(384).fill(0),
38
+ content: ""
39
+ }
40
+ ]);
41
+ this.table = await this.db.createTable("code_embeddings", seedTable);
42
+ await this.table.delete("id = '__seed__'");
43
+ }
44
+ this.initialized = true;
45
+ }
46
+ /**
47
+ * Insert or update a code record.
48
+ */
49
+ async upsert(filePath, embedding, content) {
50
+ if (!this.table)
51
+ throw new Error("VectorStore not initialized. Call init() first.");
52
+ const safe = sanitizeFilterPath(filePath);
53
+ try {
54
+ await this.table.delete(`filePath = '${safe}'`);
55
+ } catch (err) {
56
+ logger.warn("Delete before upsert failed, continuing", { detail: err instanceof Error ? err.message : String(err) });
57
+ }
58
+ const record = {
59
+ id: filePath,
60
+ filePath,
61
+ vector: embedding,
62
+ content: content.slice(0, 512)
63
+ };
64
+ await this.table.add([record]);
65
+ }
66
+ /**
67
+ * Search for the top-K most similar code records using vector search.
68
+ */
69
+ async search(queryEmbedding, limit = 10) {
70
+ if (!this.table)
71
+ throw new Error("VectorStore not initialized. Call init() first.");
72
+ try {
73
+ const results = await this.table.vectorSearch(queryEmbedding).limit(limit).toArray();
74
+ return results.filter((r) => r.id !== "__seed__").map((r) => ({
75
+ filePath: String(r.filePath ?? r.id),
76
+ content: String(r.content ?? ""),
77
+ score: Number(r._distance ?? 0)
78
+ }));
79
+ } catch (err) {
80
+ logger.warn("Search failed, attempting to create index", { detail: String(err) });
81
+ try {
82
+ await this.table.createIndex("vector");
83
+ const results = await this.table.vectorSearch(queryEmbedding).limit(limit).toArray();
84
+ return results.filter((r) => r.id !== "__seed__").map((r) => ({
85
+ filePath: String(r.filePath ?? r.id),
86
+ content: String(r.content ?? ""),
87
+ score: Number(r._distance ?? 0)
88
+ }));
89
+ } catch {
90
+ return [];
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * Remove a file's embedding from the store.
96
+ */
97
+ async remove(filePath) {
98
+ if (!this.table)
99
+ throw new Error("VectorStore not initialized. Call init() first.");
100
+ const safe = sanitizeFilterPath(filePath);
101
+ try {
102
+ await this.table.delete(`filePath = '${safe}'`);
103
+ } catch (err) {
104
+ logger.error("Remove failed", { detail: err instanceof Error ? err.message : String(err) });
105
+ }
106
+ }
107
+ /**
108
+ * Get the total number of records.
109
+ */
110
+ async count() {
111
+ if (!this.table)
112
+ return 0;
113
+ try {
114
+ return await this.table.countRows();
115
+ } catch (err) {
116
+ logger.error("countRows failed", { detail: err instanceof Error ? err.message : String(err) });
117
+ return 0;
118
+ }
119
+ }
120
+ };
121
+
122
+ export {
123
+ VectorStore
124
+ };
125
+ //# sourceMappingURL=chunk-XNKTZGDX.js.map
@@ -0,0 +1,140 @@
1
+ import {
2
+ logger
3
+ } from "./chunk-IHXVD5SO.js";
4
+
5
+ // src/indexer/embedder.js
6
+ import { pipeline } from "@huggingface/transformers";
7
+ import fs from "fs";
8
+ import path from "path";
9
+ var EMBEDDING_DIMENSION = 384;
10
+ var MODEL_ID = "sentence-transformers/all-MiniLM-L6-v2";
11
+ var CHUNK_SIZE = 4096;
12
+ var embedder = null;
13
+ async function getEmbedder() {
14
+ if (!embedder) {
15
+ embedder = await pipeline("feature-extraction", MODEL_ID, {
16
+ dtype: "fp32"
17
+ });
18
+ }
19
+ return embedder;
20
+ }
21
+ async function generateEmbedding(text) {
22
+ const pipe = await getEmbedder();
23
+ const output = await pipe(text.slice(0, CHUNK_SIZE), {
24
+ pooling: "mean",
25
+ normalize: true
26
+ });
27
+ const data = output.tolist();
28
+ if (Array.isArray(data[0])) {
29
+ return data[0];
30
+ }
31
+ return data;
32
+ }
33
+ function collectFiles(dir, results = []) {
34
+ const IGNORED_DIRS = /* @__PURE__ */ new Set([
35
+ "node_modules",
36
+ ".git",
37
+ "dist",
38
+ "build",
39
+ ".ctxloom",
40
+ "coverage",
41
+ ".next",
42
+ ".nuxt",
43
+ "out",
44
+ ".cache",
45
+ ".turbo"
46
+ ]);
47
+ const SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
48
+ ".ts",
49
+ ".tsx",
50
+ ".js",
51
+ ".jsx",
52
+ ".mjs",
53
+ ".vue",
54
+ ".py",
55
+ ".rs",
56
+ ".go",
57
+ ".java",
58
+ ".cs",
59
+ ".rb",
60
+ ".kt",
61
+ ".kts",
62
+ ".swift",
63
+ ".php",
64
+ ".dart",
65
+ ".c",
66
+ ".cpp",
67
+ ".h",
68
+ ".md",
69
+ ".json",
70
+ ".yaml",
71
+ ".yml",
72
+ ".toml",
73
+ ".ipynb"
74
+ ]);
75
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
76
+ for (const entry of entries) {
77
+ const fullPath = path.join(dir, entry.name);
78
+ if (entry.isDirectory()) {
79
+ if (!IGNORED_DIRS.has(entry.name)) {
80
+ collectFiles(fullPath, results);
81
+ }
82
+ } else if (entry.isFile()) {
83
+ const ext = path.extname(entry.name);
84
+ if (SUPPORTED_EXTENSIONS.has(ext)) {
85
+ results.push(fullPath);
86
+ }
87
+ }
88
+ }
89
+ return results;
90
+ }
91
+ async function indexDirectory(rootDir, onProgress) {
92
+ const { VectorStore } = await import("./VectorStore-UQNBYPBV.js");
93
+ const store = new VectorStore(path.join(rootDir, ".ctxloom", "vectors.lancedb"));
94
+ await store.init();
95
+ const files = collectFiles(rootDir);
96
+ const total = files.length;
97
+ let indexed = 0;
98
+ let errors = 0;
99
+ let processed = 0;
100
+ const CONCURRENCY = 4;
101
+ for (let i = 0; i < files.length; i += CONCURRENCY) {
102
+ const batch = files.slice(i, i + CONCURRENCY);
103
+ const results = await Promise.allSettled(batch.map(async (filePath) => {
104
+ const MAX_INDEX_SIZE = 5 * 1024 * 1024;
105
+ const stat = fs.statSync(filePath);
106
+ if (stat.size > MAX_INDEX_SIZE) {
107
+ logger.warn("Skipping oversized file", { file: filePath, size: stat.size });
108
+ return null;
109
+ }
110
+ const content = fs.readFileSync(filePath, "utf-8");
111
+ if (!content.trim())
112
+ return null;
113
+ const relPath = path.relative(rootDir, filePath);
114
+ const embedding = await generateEmbedding(content);
115
+ await store.upsert(relPath, embedding, content);
116
+ return relPath;
117
+ }));
118
+ for (const result of results) {
119
+ processed++;
120
+ if (result.status === "fulfilled") {
121
+ if (result.value !== null) {
122
+ indexed++;
123
+ onProgress?.(result.value, processed, total);
124
+ }
125
+ } else {
126
+ errors++;
127
+ logger.error("Failed to index file", { detail: result.reason instanceof Error ? result.reason.message : String(result.reason) });
128
+ }
129
+ }
130
+ }
131
+ return { indexed, errors };
132
+ }
133
+
134
+ export {
135
+ EMBEDDING_DIMENSION,
136
+ generateEmbedding,
137
+ collectFiles,
138
+ indexDirectory
139
+ };
140
+ //# sourceMappingURL=chunk-ZYDVY7VZ.js.map
@@ -0,0 +1,13 @@
1
+ // src/dashboard.ts
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
5
+ async function startDashboard(options) {
6
+ const serverPath = path.resolve(__dirname, "../apps/dashboard/server/index.js");
7
+ const mod = await import(serverPath);
8
+ await mod.startDashboard(options);
9
+ }
10
+ export {
11
+ startDashboard
12
+ };
13
+ //# sourceMappingURL=dashboard-LVSRXGZN.js.map
@@ -0,0 +1,14 @@
1
+ import {
2
+ EMBEDDING_DIMENSION,
3
+ collectFiles,
4
+ generateEmbedding,
5
+ indexDirectory
6
+ } from "./chunk-ZYDVY7VZ.js";
7
+ import "./chunk-IHXVD5SO.js";
8
+ export {
9
+ EMBEDDING_DIMENSION,
10
+ collectFiles,
11
+ generateEmbedding,
12
+ indexDirectory
13
+ };
14
+ //# sourceMappingURL=embedder-RECRKXTB.js.map
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node