@codragraph/cli 2.1.4 → 2.1.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 +36 -7
- package/dist/cli/ai-context.js +297 -0
- package/dist/cli/analyze.d.ts +9 -4
- package/dist/cli/analyze.js +37 -13
- package/dist/cli/index.js +40 -14
- package/dist/cli/status.d.ts +1 -1
- package/dist/cli/status.js +8 -0
- package/dist/cli/tool.d.ts +10 -2
- package/dist/cli/tool.js +100 -39
- package/dist/config/ignore-service.js +1 -0
- package/dist/core/adaptive-profile.d.ts +52 -0
- package/dist/core/adaptive-profile.js +180 -0
- package/dist/core/cgdb/cgdb-adapter.d.ts +34 -5
- package/dist/core/cgdb/cgdb-adapter.js +418 -5
- package/dist/core/cgdb/pool-adapter.js +130 -20
- package/dist/core/ingestion/parsing-processor.js +7 -1
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +7 -1
- package/dist/core/ingestion/pipeline-phases/structure.js +19 -3
- package/dist/core/ingestion/pipeline.d.ts +10 -0
- package/dist/core/ingestion/workers/parse-worker.js +1 -1
- package/dist/core/ingestion/workers/worker-pool.d.ts +14 -1
- package/dist/core/ingestion/workers/worker-pool.js +33 -17
- package/dist/core/run-analyze.d.ts +27 -2
- package/dist/core/run-analyze.js +626 -32
- package/dist/core/search/bm25-index.d.ts +16 -8
- package/dist/core/search/bm25-index.js +72 -110
- package/dist/mcp/local/local-backend.d.ts +2 -0
- package/dist/mcp/local/local-backend.js +241 -21
- package/dist/storage/repo-manager.d.ts +29 -0
- package/dist/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/dist/web/assets/agent-DcdaQnmu.js +1104 -0
- package/dist/web/assets/architectureDiagram-UL44E2DR-DFSpa3Hb.js +36 -0
- package/dist/web/assets/blockDiagram-7IZFK4PR-DlFaxH1b.js +132 -0
- package/dist/web/assets/{c4Diagram-DFAF54RM-C4Hl3J2U.js → c4Diagram-Y2BXMSZH-BjJ_Yrim.js} +1 -1
- package/dist/web/assets/{chunk-7RZVMHOQ-BitYcNVR.js → chunk-3SSMPTDK-KGZSzG3Y.js} +1 -1
- package/dist/web/assets/{chunk-TBF5ZNIQ-DL5stGM1.js → chunk-6764PJDD-p1sGJgVm.js} +1 -1
- package/dist/web/assets/{chunk-KSICW3F5-BYzvDLNI.js → chunk-AZZRMDJM-DIDkQA4V.js} +1 -1
- package/dist/web/assets/{chunk-AEOMTBSW-BgTIXPsY.js → chunk-JQRUD6KW-DAwg-yCU.js} +1 -1
- package/dist/web/assets/chunk-KRXBNO2N-ChVO_XdS.js +1 -0
- package/dist/web/assets/chunk-LCXTWHL2-DGYdb_Eh.js +231 -0
- package/dist/web/assets/{chunk-O5ABG6QK-dHwHzA6n.js → chunk-LII3EMHJ-Bzh9SNgD.js} +1 -1
- package/dist/web/assets/chunk-RG4AUYOV-Bcl7U_IV.js +206 -0
- package/dist/web/assets/{chunk-TU3PZOEN-RLyvLcv-.js → chunk-T5OCTHI4-CZYMg5sc.js} +1 -1
- package/dist/web/assets/chunk-W44A43WB-REOI67PN.js +13 -0
- package/dist/web/assets/{chunk-RWUO3TPN-BgRTY0_k.js → chunk-ZXARS5L4-BfFdV1tf.js} +1 -1
- package/dist/web/assets/classDiagram-KGZ6W3CR-B-qkKMYi.js +1 -0
- package/dist/web/assets/classDiagram-v2-72OJOZXJ-B-qkKMYi.js +1 -0
- package/dist/web/assets/{cose-bilkent-PNC4W37J-DVhePRYg.js → cose-bilkent-UX7MHV2Q-D6vANJGG.js} +1 -1
- package/dist/web/assets/dagre-ND4H6XIP-BiHe5Lal.js +4 -0
- package/dist/web/assets/diagram-3NCE3AQN-CEutBCOW.js +43 -0
- package/dist/web/assets/diagram-GF46GFSD-CZns6HPQ.js +24 -0
- package/dist/web/assets/diagram-HNR7UZ2L-Vz8fE5of.js +3 -0
- package/dist/web/assets/diagram-QXG6HAR7-D60HKZ_y.js +24 -0
- package/dist/web/assets/diagram-WEQXMOUZ-vGAf1p3E.js +10 -0
- package/dist/web/assets/{erDiagram-GCSMX5X6-C3dhDFA8.js → erDiagram-L5TCEMPS-DZaplJA6.js} +5 -5
- package/dist/web/assets/{flowDiagram-OTCZ4VVT-CWSFWmhr.js → flowDiagram-H6V6AXG4-BqUqeAsI.js} +9 -9
- package/dist/web/assets/ganttDiagram-JCBTUEKG-XEB6H-0G.js +292 -0
- package/dist/web/assets/gitGraphDiagram-S2ZK5IYY-7G50u1Cd.js +106 -0
- package/dist/web/assets/index-B5WxtMpv.js +1415 -0
- package/dist/web/assets/infoDiagram-3YFTVSEB-Cut_rzaf.js +2 -0
- package/dist/web/assets/{ishikawaDiagram-YMYX4NHK-DUoJvNP2.js → ishikawaDiagram-BNXS4ZKH-B4DGfGi3.js} +3 -3
- package/dist/web/assets/{journeyDiagram-SO5T7YLQ-RMFPNNqz.js → journeyDiagram-M6C3CM3L-BBFhsL3E.js} +1 -1
- package/dist/web/assets/{kanban-definition-LJHFXRCJ-BzpDs1K9.js → kanban-definition-75IXJCU3-DarGRyn3.js} +4 -4
- package/dist/web/assets/{katex-GD7MH7QM-DBQvrix-.js → katex-K3KEBU37-W5XTYMhr.js} +1 -1
- package/dist/web/assets/mindmap-definition-2TDM6QVE-BgeczIJM.js +96 -0
- package/dist/web/assets/pieDiagram-CU6KROY3-Kkoo-Noq.js +30 -0
- package/dist/web/assets/quadrantDiagram-VICAPDV7-CDQFeRWN.js +7 -0
- package/dist/web/assets/{requirementDiagram-M5DCFWZL-DLHOVTSv.js → requirementDiagram-JXO7QTGE-Cz9-XnkA.js} +2 -2
- package/dist/web/assets/sankeyDiagram-URQDO5SZ-CU26z0n7.js +40 -0
- package/dist/web/assets/sequenceDiagram-VS2MUI6T-OGK1FLOt.js +162 -0
- package/dist/web/assets/stateDiagram-7D4R322I-DJ9brq0U.js +1 -0
- package/dist/web/assets/stateDiagram-v2-36443NZ5-DhJ4Ky-7.js +1 -0
- package/dist/web/assets/{timeline-definition-5SPVSISX-TRSDRgPw.js → timeline-definition-O6YCAMPW-XZvnjqTT.js} +4 -4
- package/dist/web/assets/{vennDiagram-IE5QUKF5-DNy7HRBM.js → vennDiagram-MWXL3ELB-CJUssEjA.js} +6 -6
- package/dist/web/assets/wardley-L42UT6IY-5TKZOOLJ-DZr11zBG.js +173 -0
- package/dist/web/assets/wardleyDiagram-CUQ6CDDI-C276iqrN.js +78 -0
- package/dist/web/assets/{xychartDiagram-ZHJ5623Y-Dr9r7a35.js → xychartDiagram-N2JHSOCM-B9-uCZyP.js} +4 -4
- package/dist/web/index.html +1 -1
- package/hooks/claude/codragraph-hook.cjs +15 -122
- package/package.json +1 -1
- package/vendor/node_modules/node-addon-api/node_addon_api_except.stamp +0 -0
- package/dist/web/assets/agent-D5lb0zXz.js +0 -1089
- package/dist/web/assets/architectureDiagram-EMZXCZ2Q-CZtc99v_.js +0 -36
- package/dist/web/assets/blockDiagram-IGV67L2C-BtoUp-6Y.js +0 -132
- package/dist/web/assets/chunk-3GS5O3IE-DkUjU0WD.js +0 -231
- package/dist/web/assets/chunk-3YCYZ6SJ-CQkVgT_z.js +0 -1
- package/dist/web/assets/chunk-H3VCZNTA-Cx5XV_aC.js +0 -13
- package/dist/web/assets/chunk-HN6EAY2L-BBnyTNdB.js +0 -1
- package/dist/web/assets/chunk-PK6DOVAG-CvsEnugt.js +0 -206
- package/dist/web/assets/classDiagram-PPOCWD7C-DTr8QIOf.js +0 -1
- package/dist/web/assets/classDiagram-v2-23LJLIIU-DTr8QIOf.js +0 -1
- package/dist/web/assets/dagre-E77IOHMT-Dzx0A6ZU.js +0 -4
- package/dist/web/assets/diagram-H7BISOXX-CC9pRew1.js +0 -43
- package/dist/web/assets/diagram-JC5VWROH-Bau_i9tf.js +0 -24
- package/dist/web/assets/diagram-LXUTUG65-D9_FM2Gt.js +0 -10
- package/dist/web/assets/diagram-WEHSV5V5-BMlayouL.js +0 -24
- package/dist/web/assets/ganttDiagram-MUNLMDZQ-D3a67Yol.js +0 -292
- package/dist/web/assets/gitGraphDiagram-3HKGZ4G3-7jmry-vM.js +0 -106
- package/dist/web/assets/index-BgeqpYgd.js +0 -1415
- package/dist/web/assets/infoDiagram-MN7RKWGX-G7lhP0Ib.js +0 -2
- package/dist/web/assets/mindmap-definition-2EUWGEK5-Bk0O4roa.js +0 -96
- package/dist/web/assets/pieDiagram-3IATQBI2-DKU7kpgS.js +0 -30
- package/dist/web/assets/quadrantDiagram-E256RVCF-BY0TGWCS.js +0 -7
- package/dist/web/assets/sankeyDiagram-L3NBLAOT-DVMj5rX2.js +0 -10
- package/dist/web/assets/sequenceDiagram-ZOUHS735-CJC73bV-.js +0 -157
- package/dist/web/assets/stateDiagram-MLPALWAM-BCFyESls.js +0 -1
- package/dist/web/assets/stateDiagram-v2-B5LQ5ZB2-DahzzIca.js +0 -1
- package/dist/web/assets/wardley-RL74JXVD-BCRCBASE-B-eZEzf9.js +0 -161
- package/dist/web/assets/wardleyDiagram-XU3VSMPF-BP-r1xzR.js +0 -20
package/dist/cli/index.js
CHANGED
|
@@ -8,6 +8,26 @@ import { registerGroupCommands } from './group.js';
|
|
|
8
8
|
const _require = createRequire(import.meta.url);
|
|
9
9
|
const pkg = _require('../../package.json');
|
|
10
10
|
const program = new Command();
|
|
11
|
+
const exitOneShot = (code) => {
|
|
12
|
+
const reallyExit = process
|
|
13
|
+
.reallyExit;
|
|
14
|
+
if (typeof reallyExit === 'function') {
|
|
15
|
+
reallyExit(code);
|
|
16
|
+
}
|
|
17
|
+
process.exit(code);
|
|
18
|
+
};
|
|
19
|
+
const createOneShotLazyAction = (loader, exportName) => {
|
|
20
|
+
const action = createLazyAction(loader, exportName);
|
|
21
|
+
return async (...args) => {
|
|
22
|
+
await action(...args);
|
|
23
|
+
const code = typeof process.exitCode === 'number'
|
|
24
|
+
? process.exitCode
|
|
25
|
+
: process.exitCode
|
|
26
|
+
? Number(process.exitCode) || 1
|
|
27
|
+
: 0;
|
|
28
|
+
exitOneShot(code);
|
|
29
|
+
};
|
|
30
|
+
};
|
|
11
31
|
program.name('codragraph').description('CodraGraph local CLI and MCP server').version(pkg.version);
|
|
12
32
|
program
|
|
13
33
|
.command('setup')
|
|
@@ -17,7 +37,9 @@ program
|
|
|
17
37
|
.command('analyze [path]')
|
|
18
38
|
.description('Index a repository (full analysis)')
|
|
19
39
|
.option('-f, --force', 'Force full re-index even if up to date')
|
|
20
|
-
.option('--
|
|
40
|
+
.option('--profile <mode>', 'Adaptive runtime profile: auto, lean, balanced, power', 'auto')
|
|
41
|
+
.option('--embedding-mode <mode>', 'Embedding policy: auto, off, on', 'auto')
|
|
42
|
+
.option('--embeddings', 'Enable embedding generation for semantic search (same as --embedding-mode on)')
|
|
21
43
|
.option('--skills', 'Generate repo-specific skill files from detected communities')
|
|
22
44
|
.option('--skill-targets <list>', 'CSV of editor targets for --skills (claude, cursor, opencode, codex). Default: claude.')
|
|
23
45
|
.option('--skip-agents-md', 'Skip updating the codragraph section in AGENTS.md and CLAUDE.md')
|
|
@@ -30,7 +52,7 @@ program
|
|
|
30
52
|
.option('-v, --verbose', 'Enable verbose ingestion warnings (default: false)')
|
|
31
53
|
.option('--max-file-size <kb>', 'Skip files larger than this (KB). Default: 512. Hard cap: 32768 (tree-sitter limit).')
|
|
32
54
|
.option('--no-setup', 'Skip the first-run editor setup (auto-runs once when ~/.codragraph/registry.json is missing)')
|
|
33
|
-
.option('--compress <encoding>', 'Compress per-row content
|
|
55
|
+
.option('--compress <encoding>', 'Compress per-row content. One of: auto (default), none, brotli, zstd. zstd requires Node >= 22.15.', 'auto')
|
|
34
56
|
.addHelpText('after', '\nEnvironment variables:\n' +
|
|
35
57
|
' CODRAGRAPH_NO_GITIGNORE=1 Skip .gitignore parsing (still reads .codragraphignore)\n' +
|
|
36
58
|
' CODRAGRAPH_MAX_FILE_SIZE=N Override large-file skip threshold (KB). Default 512, max 32768.\n' +
|
|
@@ -114,65 +136,69 @@ program
|
|
|
114
136
|
.option('-g, --goal <text>', 'What you want to find')
|
|
115
137
|
.option('-l, --limit <n>', 'Max processes to return (default: 5)')
|
|
116
138
|
.option('--content', 'Include full symbol source code')
|
|
117
|
-
.action(
|
|
139
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'queryCommand'));
|
|
118
140
|
program
|
|
119
141
|
.command('context [name]')
|
|
120
142
|
.description('360-degree view of a code symbol: callers, callees, processes')
|
|
121
143
|
.option('-r, --repo <name>', 'Target repository')
|
|
122
144
|
.option('-u, --uid <uid>', 'Direct symbol UID (zero-ambiguity lookup)')
|
|
123
145
|
.option('-f, --file <path>', 'File path to disambiguate common names')
|
|
146
|
+
.option('-k, --kind <kind>', 'Symbol kind to disambiguate common names')
|
|
124
147
|
.option('--content', 'Include full symbol source code')
|
|
125
|
-
.action(
|
|
148
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'contextCommand'));
|
|
126
149
|
program
|
|
127
|
-
.command('impact
|
|
150
|
+
.command('impact [target]')
|
|
128
151
|
.description('Blast radius analysis: what breaks if you change a symbol')
|
|
129
152
|
.option('-d, --direction <dir>', 'upstream (dependants) or downstream (dependencies)', 'upstream')
|
|
130
153
|
.option('-r, --repo <name>', 'Target repository')
|
|
154
|
+
.option('-u, --uid <uid>', 'Direct target symbol UID (zero-ambiguity lookup)')
|
|
155
|
+
.option('-f, --file <path>', 'File path to disambiguate common names')
|
|
156
|
+
.option('-k, --kind <kind>', 'Symbol kind to disambiguate common names')
|
|
131
157
|
.option('--depth <n>', 'Max relationship depth (default: 3)')
|
|
132
158
|
.option('--include-tests', 'Include test files in results')
|
|
133
|
-
.action(
|
|
159
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'impactCommand'));
|
|
134
160
|
program
|
|
135
161
|
.command('cypher <query>')
|
|
136
162
|
.description('Execute raw Cypher query against the knowledge graph')
|
|
137
163
|
.option('-r, --repo <name>', 'Target repository')
|
|
138
|
-
.action(
|
|
164
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'cypherCommand'));
|
|
139
165
|
program
|
|
140
166
|
.command('feature-clusters')
|
|
141
167
|
.description('List human-facing feature clusters for targeted context building')
|
|
142
168
|
.option('-r, --repo <name>', 'Target repository')
|
|
143
169
|
.option('-l, --limit <n>', 'Max feature clusters to return (default: 100)')
|
|
144
|
-
.action(
|
|
170
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'featureClustersCommand'));
|
|
145
171
|
program
|
|
146
172
|
.command('cluster-query [query]')
|
|
147
173
|
.description('Alias for feature-clusters: list product/domain clusters')
|
|
148
174
|
.option('-r, --repo <name>', 'Target repository')
|
|
149
175
|
.option('-l, --limit <n>', 'Max feature clusters to return (default: 100)')
|
|
150
|
-
.action(
|
|
176
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'clusterQueryCommand'));
|
|
151
177
|
program
|
|
152
178
|
.command('feature-context <name>')
|
|
153
179
|
.description('Show members, line ranges, and dependencies for a feature cluster')
|
|
154
180
|
.option('-r, --repo <name>', 'Target repository')
|
|
155
181
|
.option('-l, --limit <n>', 'Max members to return (default: 100)')
|
|
156
|
-
.action(
|
|
182
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'featureContextCommand'));
|
|
157
183
|
program
|
|
158
184
|
.command('cluster-context <name>')
|
|
159
185
|
.description('Alias for feature-context: show a feature cluster context pack')
|
|
160
186
|
.option('-r, --repo <name>', 'Target repository')
|
|
161
187
|
.option('-l, --limit <n>', 'Max members to return (default: 100)')
|
|
162
|
-
.action(
|
|
188
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'clusterContextCommand'));
|
|
163
189
|
program
|
|
164
190
|
.command('context-pack <name>')
|
|
165
191
|
.description('Generate the compact agent context pack for a feature cluster')
|
|
166
192
|
.option('-r, --repo <name>', 'Target repository')
|
|
167
193
|
.option('-l, --limit <n>', 'Max members to return (default: 100)')
|
|
168
|
-
.action(
|
|
194
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'contextPackCommand'));
|
|
169
195
|
program
|
|
170
196
|
.command('cluster-impact <name>')
|
|
171
197
|
.description('Feature-level blast radius analysis for a cluster')
|
|
172
198
|
.option('-d, --direction <dir>', 'upstream, downstream, or both', 'upstream')
|
|
173
199
|
.option('-r, --repo <name>', 'Target repository')
|
|
174
200
|
.option('-l, --limit <n>', 'Max context-pack members to include (default: 100)')
|
|
175
|
-
.action(
|
|
201
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'clusterImpactCommand'));
|
|
176
202
|
program
|
|
177
203
|
.command('detect-changes')
|
|
178
204
|
.alias('detect_changes')
|
|
@@ -180,7 +206,7 @@ program
|
|
|
180
206
|
.option('-s, --scope <scope>', 'What to analyze: unstaged, staged, all, or compare', 'unstaged')
|
|
181
207
|
.option('-b, --base-ref <ref>', 'Branch/commit for compare scope (e.g. main)')
|
|
182
208
|
.option('-r, --repo <name>', 'Target repository')
|
|
183
|
-
.action(
|
|
209
|
+
.action(createOneShotLazyAction(() => import('./tool.js'), 'detectChangesCommand'));
|
|
184
210
|
// ─── Eval Server (persistent daemon for SWE-bench) ─────────────────
|
|
185
211
|
program
|
|
186
212
|
.command('eval-server')
|
package/dist/cli/status.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface IndexStorageSummary {
|
|
|
13
13
|
}
|
|
14
14
|
export declare const formatBytes: (bytes: number) => string;
|
|
15
15
|
export declare const summarizeIndexStorage: (storagePath: string) => Promise<IndexStorageSummary | null>;
|
|
16
|
-
export declare const formatIndexStatusLines: (summary: IndexStorageSummary | null, meta: Pick<RepoMeta, "stats" | "compress">, options?: {
|
|
16
|
+
export declare const formatIndexStatusLines: (summary: IndexStorageSummary | null, meta: Pick<RepoMeta, "stats" | "compress" | "adaptiveProfile">, options?: {
|
|
17
17
|
largeIndexWarningBytes?: number;
|
|
18
18
|
}) => string[];
|
|
19
19
|
export declare const statusCommand: () => Promise<void>;
|
package/dist/cli/status.js
CHANGED
|
@@ -94,6 +94,14 @@ export const formatIndexStatusLines = (summary, meta, options = {}) => {
|
|
|
94
94
|
const embeddings = meta.stats?.embeddings;
|
|
95
95
|
lines.push(`Embeddings: ${typeof embeddings === 'number' ? embeddings.toLocaleString('en-US') : 'unknown'}`);
|
|
96
96
|
lines.push(`Compression: ${meta.compress ?? 'none'}`);
|
|
97
|
+
if (meta.adaptiveProfile?.resolved) {
|
|
98
|
+
const profile = meta.adaptiveProfile;
|
|
99
|
+
const workerText = typeof profile.workerPoolSize === 'number' ? `, workers ${profile.workerPoolSize}` : '';
|
|
100
|
+
const embeddingText = profile.embeddingDecision
|
|
101
|
+
? `, embeddings ${profile.embeddingDecision}`
|
|
102
|
+
: '';
|
|
103
|
+
lines.push(`Adaptive profile: ${profile.resolved}${workerText}${embeddingText}`);
|
|
104
|
+
}
|
|
97
105
|
return lines;
|
|
98
106
|
};
|
|
99
107
|
export const statusCommand = async () => {
|
package/dist/cli/tool.d.ts
CHANGED
|
@@ -21,15 +21,23 @@ export declare function queryCommand(queryText: string, options?: {
|
|
|
21
21
|
limit?: string;
|
|
22
22
|
content?: boolean;
|
|
23
23
|
}): Promise<void>;
|
|
24
|
-
export declare function contextCommand(name: string
|
|
24
|
+
export declare function contextCommand(name: string | undefined | {
|
|
25
|
+
opts?: () => Record<string, unknown>;
|
|
26
|
+
}, options?: {
|
|
25
27
|
repo?: string;
|
|
26
28
|
file?: string;
|
|
27
29
|
uid?: string;
|
|
30
|
+
kind?: string;
|
|
28
31
|
content?: boolean;
|
|
29
32
|
}): Promise<void>;
|
|
30
|
-
export declare function impactCommand(target: string
|
|
33
|
+
export declare function impactCommand(target: string | undefined | {
|
|
34
|
+
opts?: () => Record<string, unknown>;
|
|
35
|
+
}, options?: {
|
|
31
36
|
direction?: string;
|
|
32
37
|
repo?: string;
|
|
38
|
+
uid?: string;
|
|
39
|
+
file?: string;
|
|
40
|
+
kind?: string;
|
|
33
41
|
depth?: string;
|
|
34
42
|
includeTests?: boolean;
|
|
35
43
|
}): Promise<void>;
|
package/dist/cli/tool.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import { writeSync } from 'node:fs';
|
|
18
18
|
import { LocalBackend } from '../mcp/local/local-backend.js';
|
|
19
19
|
import { emitTokenStats } from './compress-stats.js';
|
|
20
|
+
import { findRepo } from '../storage/repo-manager.js';
|
|
20
21
|
let _backend = null;
|
|
21
22
|
async function getBackend() {
|
|
22
23
|
if (_backend)
|
|
@@ -29,6 +30,27 @@ async function getBackend() {
|
|
|
29
30
|
}
|
|
30
31
|
return _backend;
|
|
31
32
|
}
|
|
33
|
+
async function callToolOnce(toolName, params) {
|
|
34
|
+
const backend = await getBackend();
|
|
35
|
+
return backend.callTool(toolName, params);
|
|
36
|
+
}
|
|
37
|
+
async function resolveCliRepoParam(repoParam) {
|
|
38
|
+
if (repoParam)
|
|
39
|
+
return repoParam;
|
|
40
|
+
const currentRepo = await findRepo(process.cwd());
|
|
41
|
+
if (currentRepo)
|
|
42
|
+
return currentRepo.repoPath;
|
|
43
|
+
output(`Error: Current repository is not indexed: ${process.cwd()}\n` +
|
|
44
|
+
'Run: npx @codragraph/cli analyze');
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
function unwrapCommanderOptions(value) {
|
|
49
|
+
if (!value || typeof value !== 'object')
|
|
50
|
+
return value;
|
|
51
|
+
const maybeCommand = value;
|
|
52
|
+
return typeof maybeCommand.opts === 'function' ? maybeCommand.opts() : value;
|
|
53
|
+
}
|
|
32
54
|
/**
|
|
33
55
|
* Write tool output to stdout using low-level fd write.
|
|
34
56
|
*
|
|
@@ -59,47 +81,67 @@ export async function queryCommand(queryText, options) {
|
|
|
59
81
|
console.error('Usage: codragraph query <search_query>');
|
|
60
82
|
process.exit(1);
|
|
61
83
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
84
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
85
|
+
if (!repo)
|
|
86
|
+
return;
|
|
87
|
+
const result = await callToolOnce('query', {
|
|
64
88
|
query: queryText,
|
|
65
89
|
task_context: options?.context,
|
|
66
90
|
goal: options?.goal,
|
|
67
91
|
limit: options?.limit ? parseInt(options.limit) : undefined,
|
|
68
92
|
include_content: options?.content ?? false,
|
|
69
|
-
repo
|
|
93
|
+
repo,
|
|
70
94
|
});
|
|
71
95
|
output(result);
|
|
72
96
|
emitTokenStats(result);
|
|
73
97
|
}
|
|
74
98
|
export async function contextCommand(name, options) {
|
|
75
|
-
|
|
99
|
+
let symbolName = typeof name === 'string' ? name : undefined;
|
|
100
|
+
if (typeof name !== 'string' && name && !options) {
|
|
101
|
+
options = unwrapCommanderOptions(name);
|
|
102
|
+
symbolName = undefined;
|
|
103
|
+
}
|
|
104
|
+
if (!symbolName?.trim() && !options?.uid) {
|
|
76
105
|
console.error('Usage: codragraph context <symbol_name> [--uid <uid>] [--file <path>]');
|
|
77
106
|
process.exit(1);
|
|
78
107
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
108
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
109
|
+
if (!repo)
|
|
110
|
+
return;
|
|
111
|
+
const result = await callToolOnce('context', {
|
|
112
|
+
name: symbolName || undefined,
|
|
82
113
|
uid: options?.uid,
|
|
83
114
|
file_path: options?.file,
|
|
115
|
+
kind: options?.kind,
|
|
84
116
|
include_content: options?.content ?? false,
|
|
85
|
-
repo
|
|
117
|
+
repo,
|
|
86
118
|
});
|
|
87
119
|
output(result);
|
|
88
120
|
emitTokenStats(result);
|
|
89
121
|
}
|
|
90
122
|
export async function impactCommand(target, options) {
|
|
91
|
-
|
|
92
|
-
|
|
123
|
+
let targetName = typeof target === 'string' ? target : undefined;
|
|
124
|
+
if (typeof target !== 'string' && target && !options) {
|
|
125
|
+
options = unwrapCommanderOptions(target);
|
|
126
|
+
targetName = undefined;
|
|
127
|
+
}
|
|
128
|
+
if (!targetName?.trim() && !options?.uid) {
|
|
129
|
+
console.error('Usage: codragraph impact <symbol_name> [--uid <uid>] [--direction upstream|downstream]');
|
|
93
130
|
process.exit(1);
|
|
94
131
|
}
|
|
95
132
|
try {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
133
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
134
|
+
if (!repo)
|
|
135
|
+
return;
|
|
136
|
+
const result = await callToolOnce('impact', {
|
|
137
|
+
target: targetName || undefined,
|
|
138
|
+
target_uid: options?.uid,
|
|
139
|
+
file_path: options?.file,
|
|
140
|
+
kind: options?.kind,
|
|
99
141
|
direction: options?.direction || 'upstream',
|
|
100
142
|
maxDepth: options?.depth ? parseInt(options.depth, 10) : undefined,
|
|
101
143
|
includeTests: options?.includeTests ?? false,
|
|
102
|
-
repo
|
|
144
|
+
repo,
|
|
103
145
|
});
|
|
104
146
|
output(result);
|
|
105
147
|
emitTokenStats(result);
|
|
@@ -109,7 +151,7 @@ export async function impactCommand(target, options) {
|
|
|
109
151
|
// The backend's impact() already returns structured errors for graph query failures
|
|
110
152
|
output({
|
|
111
153
|
error: (err instanceof Error ? err.message : String(err)) || 'Impact analysis failed unexpectedly',
|
|
112
|
-
target: { name:
|
|
154
|
+
target: { name: targetName || options?.uid },
|
|
113
155
|
direction: options?.direction || 'upstream',
|
|
114
156
|
suggestion: 'Try reducing --depth or using codragraph context <symbol> as a fallback',
|
|
115
157
|
});
|
|
@@ -121,26 +163,32 @@ export async function cypherCommand(query, options) {
|
|
|
121
163
|
console.error('Usage: codragraph cypher <cypher_query>');
|
|
122
164
|
process.exit(1);
|
|
123
165
|
}
|
|
124
|
-
const
|
|
125
|
-
|
|
166
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
167
|
+
if (!repo)
|
|
168
|
+
return;
|
|
169
|
+
const result = await callToolOnce('cypher', {
|
|
126
170
|
query,
|
|
127
|
-
repo
|
|
171
|
+
repo,
|
|
128
172
|
});
|
|
129
173
|
output(result);
|
|
130
174
|
}
|
|
131
175
|
export async function featureClustersCommand(options) {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
176
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
177
|
+
if (!repo)
|
|
178
|
+
return;
|
|
179
|
+
const result = await callToolOnce('feature_clusters', {
|
|
180
|
+
repo,
|
|
135
181
|
limit: options?.limit ? parseInt(options.limit, 10) : undefined,
|
|
136
182
|
});
|
|
137
183
|
output(result);
|
|
138
184
|
}
|
|
139
185
|
export async function clusterQueryCommand(query, options) {
|
|
140
|
-
const
|
|
141
|
-
|
|
186
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
187
|
+
if (!repo)
|
|
188
|
+
return;
|
|
189
|
+
const result = await callToolOnce('cluster_query', {
|
|
142
190
|
query,
|
|
143
|
-
repo
|
|
191
|
+
repo,
|
|
144
192
|
limit: options?.limit ? parseInt(options.limit, 10) : undefined,
|
|
145
193
|
});
|
|
146
194
|
output(result);
|
|
@@ -150,10 +198,12 @@ export async function featureContextCommand(name, options) {
|
|
|
150
198
|
console.error('Usage: codragraph feature-context <name>');
|
|
151
199
|
process.exit(1);
|
|
152
200
|
}
|
|
153
|
-
const
|
|
154
|
-
|
|
201
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
202
|
+
if (!repo)
|
|
203
|
+
return;
|
|
204
|
+
const result = await callToolOnce('feature_context', {
|
|
155
205
|
name,
|
|
156
|
-
repo
|
|
206
|
+
repo,
|
|
157
207
|
limit: options?.limit ? parseInt(options.limit, 10) : undefined,
|
|
158
208
|
});
|
|
159
209
|
output(result);
|
|
@@ -164,10 +214,12 @@ export async function clusterContextCommand(name, options) {
|
|
|
164
214
|
console.error('Usage: codragraph cluster-context <name>');
|
|
165
215
|
process.exit(1);
|
|
166
216
|
}
|
|
167
|
-
const
|
|
168
|
-
|
|
217
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
218
|
+
if (!repo)
|
|
219
|
+
return;
|
|
220
|
+
const result = await callToolOnce('cluster_context', {
|
|
169
221
|
name,
|
|
170
|
-
repo
|
|
222
|
+
repo,
|
|
171
223
|
limit: options?.limit ? parseInt(options.limit, 10) : undefined,
|
|
172
224
|
});
|
|
173
225
|
output(result);
|
|
@@ -178,10 +230,12 @@ export async function contextPackCommand(name, options) {
|
|
|
178
230
|
console.error('Usage: codragraph context-pack <name>');
|
|
179
231
|
process.exit(1);
|
|
180
232
|
}
|
|
181
|
-
const
|
|
182
|
-
|
|
233
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
234
|
+
if (!repo)
|
|
235
|
+
return;
|
|
236
|
+
const result = await callToolOnce('context_pack', {
|
|
183
237
|
name,
|
|
184
|
-
repo
|
|
238
|
+
repo,
|
|
185
239
|
limit: options?.limit ? parseInt(options.limit, 10) : undefined,
|
|
186
240
|
});
|
|
187
241
|
output(result);
|
|
@@ -192,11 +246,13 @@ export async function clusterImpactCommand(name, options) {
|
|
|
192
246
|
console.error('Usage: codragraph cluster-impact <name>');
|
|
193
247
|
process.exit(1);
|
|
194
248
|
}
|
|
195
|
-
const
|
|
196
|
-
|
|
249
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
250
|
+
if (!repo)
|
|
251
|
+
return;
|
|
252
|
+
const result = await callToolOnce('cluster_impact', {
|
|
197
253
|
name,
|
|
198
254
|
direction: options?.direction,
|
|
199
|
-
repo
|
|
255
|
+
repo,
|
|
200
256
|
limit: options?.limit ? parseInt(options.limit, 10) : undefined,
|
|
201
257
|
});
|
|
202
258
|
output(result);
|
|
@@ -236,11 +292,16 @@ function formatDetectChangesResult(result) {
|
|
|
236
292
|
return lines.join('\n').trim();
|
|
237
293
|
}
|
|
238
294
|
export async function detectChangesCommand(options) {
|
|
239
|
-
|
|
240
|
-
const
|
|
295
|
+
options = unwrapCommanderOptions(options);
|
|
296
|
+
const repo = await resolveCliRepoParam(options?.repo);
|
|
297
|
+
if (!repo)
|
|
298
|
+
return;
|
|
299
|
+
const result = await callToolOnce('detect_changes', {
|
|
241
300
|
scope: options?.scope || 'unstaged',
|
|
242
301
|
base_ref: options?.baseRef,
|
|
243
|
-
repo
|
|
302
|
+
repo,
|
|
244
303
|
});
|
|
245
304
|
output(formatDetectChangesResult(result));
|
|
305
|
+
if (result?.error)
|
|
306
|
+
process.exitCode = 1;
|
|
246
307
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ContentEncoding } from '@codragraph/graphstore';
|
|
2
|
+
import type { RepoMeta } from '../storage/repo-manager.js';
|
|
3
|
+
export type AnalyzeProfileOption = 'auto' | 'lean' | 'balanced' | 'power';
|
|
4
|
+
export type ResolvedAnalyzeProfile = Exclude<AnalyzeProfileOption, 'auto'>;
|
|
5
|
+
export type EmbeddingMode = 'auto' | 'off' | 'on';
|
|
6
|
+
export type CompressionOption = ContentEncoding | 'auto';
|
|
7
|
+
export interface MachineSnapshot {
|
|
8
|
+
platform: NodeJS.Platform;
|
|
9
|
+
arch: NodeJS.Architecture;
|
|
10
|
+
logicalCpus: number;
|
|
11
|
+
availableParallelism: number;
|
|
12
|
+
totalMemoryBytes: number;
|
|
13
|
+
freeMemoryBytes: number;
|
|
14
|
+
heapLimitBytes: number;
|
|
15
|
+
nodeVersion: string;
|
|
16
|
+
httpEmbeddingsConfigured: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface AdaptiveAnalyzePlan {
|
|
19
|
+
requestedProfile: AnalyzeProfileOption;
|
|
20
|
+
profile: ResolvedAnalyzeProfile;
|
|
21
|
+
machine: MachineSnapshot;
|
|
22
|
+
compress: ContentEncoding;
|
|
23
|
+
embeddingMode: EmbeddingMode;
|
|
24
|
+
embeddingNodeLimit: number;
|
|
25
|
+
workerPoolSize: number;
|
|
26
|
+
workerSubBatchSize: number;
|
|
27
|
+
reasons: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface EmbeddingDecision {
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
reason: string;
|
|
32
|
+
limit: number;
|
|
33
|
+
}
|
|
34
|
+
export declare const parseAnalyzeProfile: (value?: string) => AnalyzeProfileOption;
|
|
35
|
+
export declare const parseEmbeddingMode: (value?: string) => EmbeddingMode;
|
|
36
|
+
export declare const parseCompressionOption: (value?: string) => CompressionOption;
|
|
37
|
+
export declare const detectMachineSnapshot: () => MachineSnapshot;
|
|
38
|
+
export declare const resolveAnalyzeProfile: (requested: AnalyzeProfileOption, machine: MachineSnapshot) => ResolvedAnalyzeProfile;
|
|
39
|
+
export declare const resolveEmbeddingMode: (embeddingsFlag: boolean | undefined, requestedMode: string | undefined) => EmbeddingMode;
|
|
40
|
+
export declare const resolveCompression: (requested: CompressionOption, profile: ResolvedAnalyzeProfile, existingMeta?: Pick<RepoMeta, "compress"> | null) => ContentEncoding;
|
|
41
|
+
export declare const embeddingLimitForProfile: (profile: ResolvedAnalyzeProfile, httpEmbeddingsConfigured: boolean) => number;
|
|
42
|
+
export declare const workerPlanForProfile: (profile: ResolvedAnalyzeProfile, machine: Pick<MachineSnapshot, "availableParallelism">) => Pick<AdaptiveAnalyzePlan, "workerPoolSize" | "workerSubBatchSize">;
|
|
43
|
+
export declare const resolveAdaptiveAnalyzePlan: (input: {
|
|
44
|
+
profile?: string;
|
|
45
|
+
embeddingMode?: string;
|
|
46
|
+
embeddings?: boolean;
|
|
47
|
+
compress?: string;
|
|
48
|
+
existingMeta?: Pick<RepoMeta, "compress"> | null;
|
|
49
|
+
machine?: MachineSnapshot;
|
|
50
|
+
}) => AdaptiveAnalyzePlan;
|
|
51
|
+
export declare const decideEmbeddingRun: (plan: Pick<AdaptiveAnalyzePlan, "embeddingMode" | "embeddingNodeLimit" | "profile" | "machine">, stats?: Pick<NonNullable<RepoMeta["stats"]>, "nodes" | "embeddings">) => EmbeddingDecision;
|
|
52
|
+
export declare const formatAdaptiveAnalyzePlan: (plan: AdaptiveAnalyzePlan) => string;
|