arceus-s 1.6.4 → 1.6.6
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 +23 -1
- package/dist/cli/index.js +16 -0
- package/dist/cli/serve.js +1 -1
- package/dist/cli/stop.d.ts +3 -0
- package/dist/cli/stop.js +122 -0
- package/dist/core/lbug/lbug-adapter.d.ts +2 -1
- package/dist/core/lbug/lbug-adapter.js +6 -6
- package/dist/server/api.js +28 -12
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -248,6 +248,28 @@ Arceus ships with skill files that teach AI agents how to use the tools effectiv
|
|
|
248
248
|
|
|
249
249
|
Installed automatically by both `arc analyze` (per-repo) and `arc setup` (global).
|
|
250
250
|
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Context Efficiency & Token Optimization (Benchmark)
|
|
254
|
+
|
|
255
|
+
Arceus's semantic graph model drastically reduces token wastage and context pollution for downstream LLMs compared to traditional lexical exploration (e.g., recursive grep and file reading).
|
|
256
|
+
|
|
257
|
+
### Quantitative Efficiency Comparison
|
|
258
|
+
|
|
259
|
+
| Inquiry Scenario | Lexical Method (Grep + Full File Read) | Semantics-Guided (MCP / Cypher Query) | Token Conservation Ratio | Impact & Efficiency Gain |
|
|
260
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
261
|
+
| **1. Call-Site Tracing** <br> Retrieve all calling methods and files invoking `withLbugDb`. | **~21,000 tokens** <br>(Requires scanning grep results, opening and parsing `api.ts` [69.6KB] and `lbug-adapter.ts` [14.4KB] to locate calling signatures). | **~28 tokens** <br>(Cypher execution: returns a targeted JSON array referencing the exact caller `handler` in `api.ts`). | **750x Reduction** <br>(99.87% Saved) | **Critical Path Tracing**: Eliminates ingestion of unrelated implementation details, preserving LLM context window. |
|
|
262
|
+
| **2. API Route Mapping** <br> Discover all registered endpoints and handler files. | **~20,162 tokens** <br>(Requires reading multiple route-registration files, middleware modules, and unit test suites). | **~65 tokens** <br>(Cypher execution: fetches all `Route` nodes containing route paths and source locations). | **310x Reduction** <br>(99.68% Saved) | **Interface Discovery**: Obtains complete routing topography without feeding entire source files to the LLM. |
|
|
263
|
+
| **3. Monorepo Class Indexing** <br> Index all classes and paths in the workspace. | **~87,500 tokens** <br>(Requires reading over 20 files containing class structures to capture inheritance and signatures). | **~1,250 tokens** <br>(Cypher execution: returns a complete node list of all `Class` names and file paths). | **70x Reduction** <br>(98.57% Saved) | **Architecture Mapping**: Instant monorepo-wide indexing with minimal network and computational overhead. |
|
|
264
|
+
|
|
265
|
+
### Architectural Advantages
|
|
266
|
+
|
|
267
|
+
1. **Deterministic Precision (Zero Noise)**: Lexical tools like grep require models to ingest noise (boilerplates, imports, formatting, unrelated logic) to resolve relationships. Arceus returns only the exact requested graph nodes and edges.
|
|
268
|
+
2. **Multi-Hop Traversal**: Tracing transitive chains (e.g., `Class A extends Class B implements Interface C`) normally requires iterative lexical searches. A single Cypher query (e.g., `MATCH (a:Class)-[:EXTENDS]->(b)-[:IMPLEMENTS]->(c) RETURN a, c`) evaluates this instantly on the graph.
|
|
269
|
+
3. **Optimized Concurrency**: Read-only graph locking ensures concurrent MCP context retrieval does not block editor processes, runtime tasks, or local file systems.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
251
273
|
## Requirements
|
|
252
274
|
|
|
253
275
|
- Node.js >= 18
|
|
@@ -384,7 +406,7 @@ For repositories with very large source files, `ARC_WORKER_SUB_BATCH_MAX_BYTES`
|
|
|
384
406
|
|
|
385
407
|
## Web UI
|
|
386
408
|
|
|
387
|
-
Arceus also has a browser-based UI at [arc.vercel.app](https://arc.vercel.app) — 100% client-side, your code never leaves the browser.
|
|
409
|
+
Arceus also has a browser-based UI at [arceus-arc.vercel.app](https://arceus-arc.vercel.app) — 100% client-side, your code never leaves the browser.
|
|
388
410
|
|
|
389
411
|
**Local Backend Mode:** Run `arc serve` and open the web UI locally — it auto-detects the server and shows all your indexed repos, with full AI chat support. No need to re-upload or re-index. The agent's tools (Cypher queries, search, code navigation) route through the backend HTTP API automatically.
|
|
390
412
|
|
package/dist/cli/index.js
CHANGED
|
@@ -99,6 +99,7 @@ Commands:
|
|
|
99
99
|
analyze [path] Index a repository (full analysis)
|
|
100
100
|
index [path...] Register an existing .arc/ folder into the global registry
|
|
101
101
|
serve Start local HTTP server for web UI connection
|
|
102
|
+
stop Stop the local HTTP server on a port (default: 4747)
|
|
102
103
|
mcp Start MCP server (stdio) — serves all indexed repos
|
|
103
104
|
list List all indexed repositories
|
|
104
105
|
status Show index status for current repo
|
|
@@ -175,6 +176,14 @@ Options:
|
|
|
175
176
|
-p, --port <port> Port number (default: 4747)
|
|
176
177
|
--host <host> Bind address (default: 127.0.0.1)`);
|
|
177
178
|
break;
|
|
179
|
+
case 'stop':
|
|
180
|
+
console.log(`Usage: ${binName} stop [options]
|
|
181
|
+
|
|
182
|
+
Stop the local HTTP server on a port
|
|
183
|
+
|
|
184
|
+
Options:
|
|
185
|
+
-p, --port <port> Port number (default: 4747)`);
|
|
186
|
+
break;
|
|
178
187
|
case 'clean':
|
|
179
188
|
console.log(`Usage: ${binName} clean [options]
|
|
180
189
|
|
|
@@ -369,6 +378,13 @@ async function runCLI() {
|
|
|
369
378
|
await serveCommand(options);
|
|
370
379
|
break;
|
|
371
380
|
}
|
|
381
|
+
case 'stop': {
|
|
382
|
+
if (options.port === undefined)
|
|
383
|
+
options.port = '4747';
|
|
384
|
+
const { stopCommand } = await import('./stop.js');
|
|
385
|
+
await stopCommand(options);
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
372
388
|
case 'mcp': {
|
|
373
389
|
const { mcpCommand } = await import('./mcp.js');
|
|
374
390
|
await mcpCommand();
|
package/dist/cli/serve.js
CHANGED
|
@@ -26,7 +26,7 @@ export const serveCommand = async (options) => {
|
|
|
26
26
|
const port = Number(options?.port ?? 4747);
|
|
27
27
|
// Default to 'localhost' so the OS decides whether to bind to 127.0.0.1 or
|
|
28
28
|
// ::1 based on system configuration, avoiding spurious CORS errors when the
|
|
29
|
-
// hosted frontend at arc.vercel.app connects to localhost.
|
|
29
|
+
// hosted frontend at arceus-arc.vercel.app connects to localhost.
|
|
30
30
|
const host = options?.host ?? 'localhost';
|
|
31
31
|
try {
|
|
32
32
|
await createServer(port, host);
|
package/dist/cli/stop.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { exec } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { logger } from '../core/logger.js';
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
export const stopCommand = async (options) => {
|
|
6
|
+
const port = Number(options?.port ?? 4747);
|
|
7
|
+
if (isNaN(port) || port <= 0 || port > 65535) {
|
|
8
|
+
console.error(`Error: Invalid port number: ${options?.port}`);
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
console.log(`Stopping process on port ${port}...`);
|
|
13
|
+
try {
|
|
14
|
+
const pids = await findPidsOnPort(port);
|
|
15
|
+
if (pids.size === 0) {
|
|
16
|
+
console.log(`No active process found using port ${port}.`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const killedPids = [];
|
|
20
|
+
const failedPids = [];
|
|
21
|
+
for (const pid of pids) {
|
|
22
|
+
if (pid === process.pid) {
|
|
23
|
+
// Don't kill ourselves
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
await killPid(pid);
|
|
28
|
+
killedPids.push(pid);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
logger.error({ err, pid }, 'Failed to kill process');
|
|
32
|
+
failedPids.push(pid);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (killedPids.length > 0) {
|
|
36
|
+
console.log(`Successfully stopped process(es) on port ${port} (PID: ${killedPids.join(', ')}).`);
|
|
37
|
+
}
|
|
38
|
+
if (failedPids.length > 0) {
|
|
39
|
+
console.error(`Failed to stop process(es) on port ${port} (PID: ${failedPids.join(', ')}).`);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
console.error(`Error while scanning port ${port}:`, err.message || err);
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
async function findPidsOnPort(port) {
|
|
49
|
+
const pids = new Set();
|
|
50
|
+
if (process.platform === 'win32') {
|
|
51
|
+
try {
|
|
52
|
+
const { stdout } = await execAsync('netstat -ano');
|
|
53
|
+
const lines = stdout.split('\n');
|
|
54
|
+
for (const line of lines) {
|
|
55
|
+
const trimmed = line.trim();
|
|
56
|
+
if (!trimmed)
|
|
57
|
+
continue;
|
|
58
|
+
const parts = trimmed.split(/\s+/);
|
|
59
|
+
if (parts.length < 4)
|
|
60
|
+
continue;
|
|
61
|
+
// Local address is the second column (index 1)
|
|
62
|
+
const localAddress = parts[1];
|
|
63
|
+
if (localAddress &&
|
|
64
|
+
(localAddress.endsWith(`:${port}`) || localAddress.endsWith(`]:${port}`))) {
|
|
65
|
+
const pidStr = parts[parts.length - 1];
|
|
66
|
+
const pid = parseInt(pidStr, 10);
|
|
67
|
+
if (!isNaN(pid) && pid > 0) {
|
|
68
|
+
pids.add(pid);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
logger.debug({ err }, 'netstat execution failed');
|
|
75
|
+
throw new Error(`Failed to list connections via netstat: ${err.message}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// macOS / Linux
|
|
80
|
+
try {
|
|
81
|
+
const { stdout } = await execAsync(`lsof -t -i :${port}`);
|
|
82
|
+
const lines = stdout.trim().split('\n');
|
|
83
|
+
for (const line of lines) {
|
|
84
|
+
const pid = parseInt(line.trim(), 10);
|
|
85
|
+
if (!isNaN(pid) && pid > 0) {
|
|
86
|
+
pids.add(pid);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
// lsof returns exit code 1 if no matches are found, which is not a real failure
|
|
92
|
+
if (err.code !== 1) {
|
|
93
|
+
// Try fallback to fuser
|
|
94
|
+
try {
|
|
95
|
+
const { stdout } = await execAsync(`fuser ${port}/tcp`);
|
|
96
|
+
const lines = stdout.trim().split(/\s+/);
|
|
97
|
+
for (const line of lines) {
|
|
98
|
+
const pid = parseInt(line.trim(), 10);
|
|
99
|
+
if (!isNaN(pid) && pid > 0) {
|
|
100
|
+
pids.add(pid);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (fuserErr) {
|
|
105
|
+
logger.debug({ fuserErr }, 'fuser execution failed');
|
|
106
|
+
if (fuserErr.code !== 1) {
|
|
107
|
+
throw new Error(`Failed to list connections via lsof/fuser: ${err.message}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return pids;
|
|
114
|
+
}
|
|
115
|
+
async function killPid(pid) {
|
|
116
|
+
if (process.platform === 'win32') {
|
|
117
|
+
await execAsync(`taskkill /F /PID ${pid}`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
await execAsync(`kill -9 ${pid}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -2,6 +2,7 @@ import lbug from '@ladybugdb/core';
|
|
|
2
2
|
import { KnowledgeGraph } from '../graph/types.js';
|
|
3
3
|
import type { CachedEmbedding } from '../embeddings/types.js';
|
|
4
4
|
import { type ExtensionEnsureOptions } from './extension-loader.js';
|
|
5
|
+
import { type LbugDatabaseOptions } from './lbug-config.js';
|
|
5
6
|
/** Factory for creating WriteStreams — injectable for testing. */
|
|
6
7
|
export type WriteStreamFactory = (filePath: string) => import('fs').WriteStream;
|
|
7
8
|
/** Result of splitting the relationship CSV into per-label-pair files. */
|
|
@@ -53,7 +54,7 @@ export declare const initLbug: (dbPath: string) => Promise<{
|
|
|
53
54
|
* database is busy (e.g. `arc analyze` holds the write lock).
|
|
54
55
|
* Each retry waits DB_LOCK_RETRY_DELAY_MS * attempt milliseconds.
|
|
55
56
|
*/
|
|
56
|
-
export declare const withLbugDb: <T>(dbPath: string, operation: () => Promise<T
|
|
57
|
+
export declare const withLbugDb: <T>(dbPath: string, operation: () => Promise<T>, options?: LbugDatabaseOptions) => Promise<T>;
|
|
57
58
|
export type LbugProgressCallback = (message: string) => void;
|
|
58
59
|
export declare const loadGraphToLbug: (graph: KnowledgeGraph, repoPath: string, storagePath: string, onProgress?: LbugProgressCallback) => Promise<{
|
|
59
60
|
success: boolean;
|
|
@@ -237,12 +237,12 @@ export const initLbug = async (dbPath) => {
|
|
|
237
237
|
* database is busy (e.g. `arc analyze` holds the write lock).
|
|
238
238
|
* Each retry waits DB_LOCK_RETRY_DELAY_MS * attempt milliseconds.
|
|
239
239
|
*/
|
|
240
|
-
export const withLbugDb = async (dbPath, operation) => {
|
|
240
|
+
export const withLbugDb = async (dbPath, operation, options) => {
|
|
241
241
|
let lastError;
|
|
242
242
|
for (let attempt = 1; attempt <= DB_LOCK_RETRY_ATTEMPTS; attempt++) {
|
|
243
243
|
try {
|
|
244
244
|
return await runWithSessionLock(async () => {
|
|
245
|
-
await ensureLbugInitialized(dbPath);
|
|
245
|
+
await ensureLbugInitialized(dbPath, options);
|
|
246
246
|
return operation();
|
|
247
247
|
});
|
|
248
248
|
}
|
|
@@ -272,14 +272,14 @@ export const withLbugDb = async (dbPath, operation) => {
|
|
|
272
272
|
// but TypeScript needs an explicit throw to satisfy the return type.
|
|
273
273
|
throw lastError;
|
|
274
274
|
};
|
|
275
|
-
const ensureLbugInitialized = async (dbPath) => {
|
|
275
|
+
const ensureLbugInitialized = async (dbPath, options) => {
|
|
276
276
|
if (conn && currentDbPath === dbPath) {
|
|
277
277
|
return { db, conn };
|
|
278
278
|
}
|
|
279
|
-
await doInitLbug(dbPath);
|
|
279
|
+
await doInitLbug(dbPath, options);
|
|
280
280
|
return { db, conn };
|
|
281
281
|
};
|
|
282
|
-
const doInitLbug = async (dbPath) => {
|
|
282
|
+
const doInitLbug = async (dbPath, options) => {
|
|
283
283
|
// Different database requested — close the old one first
|
|
284
284
|
if (conn || db) {
|
|
285
285
|
await safeClose();
|
|
@@ -316,7 +316,7 @@ const doInitLbug = async (dbPath) => {
|
|
|
316
316
|
// Ensure parent directory exists
|
|
317
317
|
const parentDir = path.dirname(dbPath);
|
|
318
318
|
await fs.mkdir(parentDir, { recursive: true });
|
|
319
|
-
const opened = await openLbugConnection(lbug, dbPath);
|
|
319
|
+
const opened = await openLbugConnection(lbug, dbPath, options);
|
|
320
320
|
db = opened.db;
|
|
321
321
|
conn = opened.conn;
|
|
322
322
|
for (const schemaQuery of SCHEMA_QUERIES) {
|
package/dist/server/api.js
CHANGED
|
@@ -56,7 +56,7 @@ export const isAllowedOrigin = (origin) => {
|
|
|
56
56
|
origin === 'http://127.0.0.1' ||
|
|
57
57
|
origin.startsWith('http://[::1]:') ||
|
|
58
58
|
origin === 'http://[::1]' ||
|
|
59
|
-
origin === 'https://arc.vercel.app') {
|
|
59
|
+
origin === 'https://arceus-arc.vercel.app') {
|
|
60
60
|
return true;
|
|
61
61
|
}
|
|
62
62
|
// RFC 1918 private network ranges — allow any port on these hosts.
|
|
@@ -163,7 +163,7 @@ a.ext:hover{text-decoration:underline}
|
|
|
163
163
|
<div class="terminal"><span class="prompt">$ </span><span class="cmd">cd arceus-web && npm run build</span></div>
|
|
164
164
|
<div class="link-row">
|
|
165
165
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
|
|
166
|
-
<a class="ext" href="https://arc.vercel.app" target="_blank" rel="noopener noreferrer">arc.vercel.app</a>
|
|
166
|
+
<a class="ext" href="https://arceus-arc.vercel.app" target="_blank" rel="noopener noreferrer">arceus-arc.vercel.app</a>
|
|
167
167
|
<span style="color:#5a5a70">— connects to this server</span>
|
|
168
168
|
</div>
|
|
169
169
|
</div>
|
|
@@ -852,7 +852,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
852
852
|
res.once('finish', markFinished);
|
|
853
853
|
res.once('close', abortStreaming);
|
|
854
854
|
try {
|
|
855
|
-
await withLbugDb(lbugPath, async () => streamGraphNdjson(res, includeContent, abortController.signal));
|
|
855
|
+
await withLbugDb(lbugPath, async () => streamGraphNdjson(res, includeContent, abortController.signal), { readOnly: true });
|
|
856
856
|
if (!abortController.signal.aborted && !res.writableEnded) {
|
|
857
857
|
res.end();
|
|
858
858
|
}
|
|
@@ -864,7 +864,9 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
864
864
|
}
|
|
865
865
|
return;
|
|
866
866
|
}
|
|
867
|
-
const graph = await withLbugDb(lbugPath, async () => buildGraph(includeContent)
|
|
867
|
+
const graph = await withLbugDb(lbugPath, async () => buildGraph(includeContent), {
|
|
868
|
+
readOnly: true,
|
|
869
|
+
});
|
|
868
870
|
res.json(graph);
|
|
869
871
|
}
|
|
870
872
|
catch (err) {
|
|
@@ -904,7 +906,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
904
906
|
return;
|
|
905
907
|
}
|
|
906
908
|
const lbugPath = path.join(entry.storagePath, 'lbug');
|
|
907
|
-
const result = await withLbugDb(lbugPath, () => executeQuery(cypher));
|
|
909
|
+
const result = await withLbugDb(lbugPath, () => executeQuery(cypher), { readOnly: true });
|
|
908
910
|
res.json({ result });
|
|
909
911
|
}
|
|
910
912
|
catch (err) {
|
|
@@ -1031,7 +1033,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1031
1033
|
return { ...r, ...enrichment };
|
|
1032
1034
|
}));
|
|
1033
1035
|
return { searchResults: enriched, ftsAvailable };
|
|
1034
|
-
});
|
|
1036
|
+
}, { readOnly: true });
|
|
1035
1037
|
const response = { results: results.searchResults ?? results };
|
|
1036
1038
|
if (results.ftsAvailable === false) {
|
|
1037
1039
|
response.warning =
|
|
@@ -1098,7 +1100,7 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1098
1100
|
const results = [];
|
|
1099
1101
|
const repoRoot = path.resolve(entry.path);
|
|
1100
1102
|
const lbugPath = path.join(entry.storagePath, 'lbug');
|
|
1101
|
-
const fileRows = await withLbugDb(lbugPath, () => executeQuery(`MATCH (n:File) WHERE n.content IS NOT NULL RETURN n.filePath AS filePath`));
|
|
1103
|
+
const fileRows = await withLbugDb(lbugPath, () => executeQuery(`MATCH (n:File) WHERE n.content IS NOT NULL RETURN n.filePath AS filePath`), { readOnly: true });
|
|
1102
1104
|
for (const row of fileRows) {
|
|
1103
1105
|
if (results.length >= limit)
|
|
1104
1106
|
break;
|
|
@@ -1139,7 +1141,9 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1139
1141
|
res.json(result);
|
|
1140
1142
|
}
|
|
1141
1143
|
catch (err) {
|
|
1142
|
-
res
|
|
1144
|
+
res
|
|
1145
|
+
.status(statusFromError(err))
|
|
1146
|
+
.json({ error: err.message || 'Failed to query processes' });
|
|
1143
1147
|
}
|
|
1144
1148
|
},
|
|
1145
1149
|
},
|
|
@@ -1176,7 +1180,9 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1176
1180
|
res.json(result);
|
|
1177
1181
|
}
|
|
1178
1182
|
catch (err) {
|
|
1179
|
-
res
|
|
1183
|
+
res
|
|
1184
|
+
.status(statusFromError(err))
|
|
1185
|
+
.json({ error: err.message || 'Failed to query clusters' });
|
|
1180
1186
|
}
|
|
1181
1187
|
},
|
|
1182
1188
|
},
|
|
@@ -1276,7 +1282,9 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1276
1282
|
: [];
|
|
1277
1283
|
const forkWorker = () => {
|
|
1278
1284
|
const currentJob = jobManager.getJob(job.id);
|
|
1279
|
-
if (!currentJob ||
|
|
1285
|
+
if (!currentJob ||
|
|
1286
|
+
currentJob.status === 'complete' ||
|
|
1287
|
+
currentJob.status === 'failed')
|
|
1280
1288
|
return;
|
|
1281
1289
|
const child = fork(workerPath, [], {
|
|
1282
1290
|
execArgv: [...tsxHookArgs, '--max-old-space-size=8192'],
|
|
@@ -1451,7 +1459,11 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1451
1459
|
embedJobManager.updateJob(job.id, {
|
|
1452
1460
|
repoName: entry.name,
|
|
1453
1461
|
status: 'analyzing',
|
|
1454
|
-
progress: {
|
|
1462
|
+
progress: {
|
|
1463
|
+
phase: 'analyzing',
|
|
1464
|
+
percent: 0,
|
|
1465
|
+
message: 'Starting embedding generation...',
|
|
1466
|
+
},
|
|
1455
1467
|
});
|
|
1456
1468
|
const EMBED_TIMEOUT_MS = 30 * 60 * 1000;
|
|
1457
1469
|
const embedTimeout = setTimeout(() => {
|
|
@@ -1477,7 +1489,11 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
1477
1489
|
await runEmbeddingPipeline(executeQuery, executeWithReusedStatement, (p) => {
|
|
1478
1490
|
embedJobManager.updateJob(job.id, {
|
|
1479
1491
|
progress: {
|
|
1480
|
-
phase: p.phase === 'ready'
|
|
1492
|
+
phase: p.phase === 'ready'
|
|
1493
|
+
? 'complete'
|
|
1494
|
+
: p.phase === 'error'
|
|
1495
|
+
? 'failed'
|
|
1496
|
+
: p.phase,
|
|
1481
1497
|
percent: p.percent,
|
|
1482
1498
|
message: p.phase === 'loading-model'
|
|
1483
1499
|
? 'Loading embedding model...'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arceus-s",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.6",
|
|
4
4
|
"description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
|
|
5
5
|
"author": "Chandan Kumar Behera",
|
|
6
6
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
@@ -119,4 +119,4 @@
|
|
|
119
119
|
"engines": {
|
|
120
120
|
"node": ">=22.0.0"
|
|
121
121
|
}
|
|
122
|
-
}
|
|
122
|
+
}
|