@codragraph/cli 2.1.6 → 2.2.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 +7 -7
- package/dist/cli/graphpack.d.ts +48 -0
- package/dist/cli/graphpack.js +217 -0
- package/dist/cli/index.js +72 -0
- package/dist/cli/tool.d.ts +1 -0
- package/dist/cli/tool.js +111 -2
- package/dist/core/graphpack/index.d.ts +14 -0
- package/dist/core/graphpack/index.js +474 -0
- package/dist/core/graphpack/types.d.ts +129 -0
- package/dist/core/graphpack/types.js +4 -0
- package/dist/core/semantic/relationships.d.ts +36 -0
- package/dist/core/semantic/relationships.js +261 -0
- package/dist/mcp/local/local-backend.js +42 -0
- package/dist/mcp/resources.js +125 -0
- package/dist/mcp/tools.js +105 -0
- package/dist/server/api.js +112 -0
- package/dist/web/assets/agent-CQNZQ-hg.js +1139 -0
- package/dist/web/assets/{architectureDiagram-UL44E2DR-DFSpa3Hb.js → architectureDiagram-UL44E2DR-B5_goS_i.js} +1 -1
- package/dist/web/assets/{blockDiagram-7IZFK4PR-DlFaxH1b.js → blockDiagram-7IZFK4PR-D7ZAlDyv.js} +1 -1
- package/dist/web/assets/{c4Diagram-Y2BXMSZH-BjJ_Yrim.js → c4Diagram-Y2BXMSZH-Djcgm_54.js} +1 -1
- package/dist/web/assets/{chunk-3SSMPTDK-KGZSzG3Y.js → chunk-3SSMPTDK-Cv2Zy2FO.js} +1 -1
- package/dist/web/assets/{chunk-6764PJDD-p1sGJgVm.js → chunk-6764PJDD-Cppb-jH-.js} +1 -1
- package/dist/web/assets/{chunk-AZZRMDJM-DIDkQA4V.js → chunk-AZZRMDJM-BHlLC7p3.js} +1 -1
- package/dist/web/assets/{chunk-JQRUD6KW-DAwg-yCU.js → chunk-JQRUD6KW-3F8Zg-1N.js} +1 -1
- package/dist/web/assets/{chunk-KRXBNO2N-ChVO_XdS.js → chunk-KRXBNO2N-C0mbN9a7.js} +1 -1
- package/dist/web/assets/{chunk-LCXTWHL2-DGYdb_Eh.js → chunk-LCXTWHL2-BoiuJpIF.js} +1 -1
- package/dist/web/assets/{chunk-LII3EMHJ-Bzh9SNgD.js → chunk-LII3EMHJ-Dqq0Qguw.js} +1 -1
- package/dist/web/assets/{chunk-RG4AUYOV-Bcl7U_IV.js → chunk-RG4AUYOV-Bl5F_gDs.js} +1 -1
- package/dist/web/assets/{chunk-T5OCTHI4-CZYMg5sc.js → chunk-T5OCTHI4-B2tIcggA.js} +1 -1
- package/dist/web/assets/{chunk-W44A43WB-REOI67PN.js → chunk-W44A43WB-BHe37iN7.js} +1 -1
- package/dist/web/assets/{chunk-ZXARS5L4-BfFdV1tf.js → chunk-ZXARS5L4-wcrIaQvY.js} +1 -1
- package/dist/web/assets/classDiagram-KGZ6W3CR-IbI6v_24.js +1 -0
- package/dist/web/assets/classDiagram-v2-72OJOZXJ-IbI6v_24.js +1 -0
- package/dist/web/assets/{cose-bilkent-UX7MHV2Q-D6vANJGG.js → cose-bilkent-UX7MHV2Q-BWr7v0Wr.js} +1 -1
- package/dist/web/assets/{dagre-ND4H6XIP-BiHe5Lal.js → dagre-ND4H6XIP-De5LIh1B.js} +1 -1
- package/dist/web/assets/{diagram-3NCE3AQN-CEutBCOW.js → diagram-3NCE3AQN-Dd22FSHy.js} +1 -1
- package/dist/web/assets/{diagram-GF46GFSD-CZns6HPQ.js → diagram-GF46GFSD-Cev3THY8.js} +1 -1
- package/dist/web/assets/{diagram-HNR7UZ2L-Vz8fE5of.js → diagram-HNR7UZ2L-D8Z8RQGs.js} +1 -1
- package/dist/web/assets/{diagram-QXG6HAR7-D60HKZ_y.js → diagram-QXG6HAR7-B8VOJOiE.js} +1 -1
- package/dist/web/assets/{diagram-WEQXMOUZ-vGAf1p3E.js → diagram-WEQXMOUZ-va1bLoMD.js} +1 -1
- package/dist/web/assets/{erDiagram-L5TCEMPS-DZaplJA6.js → erDiagram-L5TCEMPS-B3_9uAoP.js} +1 -1
- package/dist/web/assets/{flowDiagram-H6V6AXG4-BqUqeAsI.js → flowDiagram-H6V6AXG4-98m6maI1.js} +1 -1
- package/dist/web/assets/{ganttDiagram-JCBTUEKG-XEB6H-0G.js → ganttDiagram-JCBTUEKG-vE2nzETb.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-S2ZK5IYY-7G50u1Cd.js → gitGraphDiagram-S2ZK5IYY-DKc8uUg_.js} +1 -1
- package/dist/web/assets/index-BAhe1HSk.css +1 -0
- package/dist/web/assets/{index-B5WxtMpv.js → index-VTKdaklA.js} +230 -230
- package/dist/web/assets/{infoDiagram-3YFTVSEB-Cut_rzaf.js → infoDiagram-3YFTVSEB-DYP-Srzx.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-BNXS4ZKH-B4DGfGi3.js → ishikawaDiagram-BNXS4ZKH-QZnkpmmb.js} +1 -1
- package/dist/web/assets/{journeyDiagram-M6C3CM3L-BBFhsL3E.js → journeyDiagram-M6C3CM3L-B5ojIuqu.js} +1 -1
- package/dist/web/assets/{kanban-definition-75IXJCU3-DarGRyn3.js → kanban-definition-75IXJCU3-BJA8liRR.js} +1 -1
- package/dist/web/assets/{katex-K3KEBU37-W5XTYMhr.js → katex-K3KEBU37-DUqZiCRL.js} +1 -1
- package/dist/web/assets/{mindmap-definition-2TDM6QVE-BgeczIJM.js → mindmap-definition-2TDM6QVE-BQj5yylD.js} +1 -1
- package/dist/web/assets/{pieDiagram-CU6KROY3-Kkoo-Noq.js → pieDiagram-CU6KROY3-4eSrPiQz.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-VICAPDV7-CDQFeRWN.js → quadrantDiagram-VICAPDV7-PzxN8j55.js} +1 -1
- package/dist/web/assets/{requirementDiagram-JXO7QTGE-Cz9-XnkA.js → requirementDiagram-JXO7QTGE-CtplTc5y.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-URQDO5SZ-CU26z0n7.js → sankeyDiagram-URQDO5SZ-CoSgvkxv.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-VS2MUI6T-OGK1FLOt.js → sequenceDiagram-VS2MUI6T-D7ygyXvJ.js} +1 -1
- package/dist/web/assets/{stateDiagram-7D4R322I-DJ9brq0U.js → stateDiagram-7D4R322I-v01gvwji.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-36443NZ5-DFD2b8_x.js +1 -0
- package/dist/web/assets/{timeline-definition-O6YCAMPW-XZvnjqTT.js → timeline-definition-O6YCAMPW-CTI3M65J.js} +1 -1
- package/dist/web/assets/{vennDiagram-MWXL3ELB-CJUssEjA.js → vennDiagram-MWXL3ELB-RnB0XMP7.js} +1 -1
- package/dist/web/assets/{wardley-L42UT6IY-5TKZOOLJ-DZr11zBG.js → wardley-L42UT6IY-5TKZOOLJ-C-ZcgEBb.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-CUQ6CDDI-C276iqrN.js → wardleyDiagram-CUQ6CDDI-EwRi4kwo.js} +1 -1
- package/dist/web/assets/{xychartDiagram-N2JHSOCM-B9-uCZyP.js → xychartDiagram-N2JHSOCM-DA38II6y.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +2 -2
- package/dist/web/assets/__vite-browser-external-BIHI7g3E.js +0 -1
- package/dist/web/assets/agent-DcdaQnmu.js +0 -1104
- package/dist/web/assets/classDiagram-KGZ6W3CR-B-qkKMYi.js +0 -1
- package/dist/web/assets/classDiagram-v2-72OJOZXJ-B-qkKMYi.js +0 -1
- package/dist/web/assets/index-CT0GtFLZ.css +0 -1
- package/dist/web/assets/stateDiagram-v2-36443NZ5-DhJ4Ky-7.js +0 -1
package/README.md
CHANGED
|
@@ -65,16 +65,16 @@ If you prefer to configure manually instead of using `codragraph setup`:
|
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
# macOS / Linux
|
|
68
|
-
claude mcp add codragraph -- npx -y @codragraph/cli@2.
|
|
68
|
+
claude mcp add codragraph -- npx -y @codragraph/cli@2.2.0 mcp
|
|
69
69
|
|
|
70
70
|
# Windows
|
|
71
|
-
claude mcp add codragraph -- cmd /c npx -y @codragraph/cli@2.
|
|
71
|
+
claude mcp add codragraph -- cmd /c npx -y @codragraph/cli@2.2.0 mcp
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
### Codex (full support — MCP + skills)
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
|
-
codex mcp add codragraph -- npx -y @codragraph/cli@2.
|
|
77
|
+
codex mcp add codragraph -- npx -y @codragraph/cli@2.2.0 mcp
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
### Cursor / Windsurf
|
|
@@ -86,7 +86,7 @@ Add to `~/.cursor/mcp.json` (global — works for all projects):
|
|
|
86
86
|
"mcpServers": {
|
|
87
87
|
"codragraph": {
|
|
88
88
|
"command": "npx",
|
|
89
|
-
"args": ["-y", "@codragraph/cli@2.
|
|
89
|
+
"args": ["-y", "@codragraph/cli@2.2.0", "mcp"]
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -101,7 +101,7 @@ Add to `~/.config/opencode/config.json`:
|
|
|
101
101
|
"mcp": {
|
|
102
102
|
"codragraph": {
|
|
103
103
|
"command": "npx",
|
|
104
|
-
"args": ["-y", "@codragraph/cli@2.
|
|
104
|
+
"args": ["-y", "@codragraph/cli@2.2.0", "mcp"]
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -309,9 +309,9 @@ It is fixed in **codragraph v1.6.2+**. Upgrade to the current workspace
|
|
|
309
309
|
version, or pin the version your team has validated:
|
|
310
310
|
|
|
311
311
|
```bash
|
|
312
|
-
npx @codragraph/cli@2.
|
|
312
|
+
npx @codragraph/cli@2.2.0 analyze # no global install
|
|
313
313
|
# or
|
|
314
|
-
npm install -g @codragraph/cli@2.
|
|
314
|
+
npm install -g @codragraph/cli@2.2.0 # upgrade a global install
|
|
315
315
|
```
|
|
316
316
|
|
|
317
317
|
If you still hit npm install issues after upgrading, these generic workarounds
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type GraphpackTarget } from '../core/graphpack/index.js';
|
|
2
|
+
export declare const bootstrapCommand: (opts?: {
|
|
3
|
+
lock?: string;
|
|
4
|
+
artifactDir?: string;
|
|
5
|
+
materialize?: boolean;
|
|
6
|
+
json?: boolean;
|
|
7
|
+
}) => Promise<void>;
|
|
8
|
+
export declare const graphpackPublishCommand: (opts?: {
|
|
9
|
+
target?: GraphpackTarget;
|
|
10
|
+
repo?: string;
|
|
11
|
+
artifactDir?: string;
|
|
12
|
+
artifactUrl?: string;
|
|
13
|
+
baseSnapshot?: string;
|
|
14
|
+
headSnapshot?: string;
|
|
15
|
+
pr?: string;
|
|
16
|
+
json?: boolean;
|
|
17
|
+
}) => Promise<void>;
|
|
18
|
+
export declare const graphpackPullCommand: (opts?: {
|
|
19
|
+
lock?: string;
|
|
20
|
+
artifactDir?: string;
|
|
21
|
+
materialize?: boolean;
|
|
22
|
+
json?: boolean;
|
|
23
|
+
}) => Promise<void>;
|
|
24
|
+
export declare const graphpackStatusCommand: (opts?: {
|
|
25
|
+
lock?: string;
|
|
26
|
+
strict?: boolean;
|
|
27
|
+
json?: boolean;
|
|
28
|
+
}) => Promise<void>;
|
|
29
|
+
export declare const semanticAnalyzeCommand: (opts?: {
|
|
30
|
+
llm?: boolean;
|
|
31
|
+
limit?: string;
|
|
32
|
+
write?: boolean;
|
|
33
|
+
json?: boolean;
|
|
34
|
+
}) => Promise<void>;
|
|
35
|
+
export declare const recipesLookupCommand: (opts?: {
|
|
36
|
+
taskFamily?: string;
|
|
37
|
+
snapshotId?: string;
|
|
38
|
+
recipeStore?: string;
|
|
39
|
+
requiredSubgraphSignature?: string;
|
|
40
|
+
limit?: string;
|
|
41
|
+
json?: boolean;
|
|
42
|
+
}) => Promise<void>;
|
|
43
|
+
export declare const teamServeCommand: (opts?: {
|
|
44
|
+
graphpack?: string;
|
|
45
|
+
port?: string;
|
|
46
|
+
host?: string;
|
|
47
|
+
web?: string;
|
|
48
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { bootstrapGraphpack, getGraphpackStatus, publishGraphpack, pullGraphpack, } from '../core/graphpack/index.js';
|
|
4
|
+
import { analyzeSemanticRelationships } from '../core/semantic/relationships.js';
|
|
5
|
+
import { findRepo, getStoragePaths, registerRepo } from '../storage/repo-manager.js';
|
|
6
|
+
import { getGitRoot, getInferredRepoName } from '../storage/git.js';
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const pkg = require('../../package.json');
|
|
9
|
+
const resolveRepoForGraphpack = async () => {
|
|
10
|
+
const indexed = await findRepo(process.cwd());
|
|
11
|
+
if (indexed) {
|
|
12
|
+
return {
|
|
13
|
+
repoPath: indexed.repoPath,
|
|
14
|
+
storagePath: indexed.storagePath,
|
|
15
|
+
repoName: getInferredRepoName(indexed.repoPath) ?? path.basename(indexed.repoPath),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const gitRoot = getGitRoot(process.cwd());
|
|
19
|
+
if (!gitRoot) {
|
|
20
|
+
throw new Error('Not inside a git repository and no CodraGraph index was found.');
|
|
21
|
+
}
|
|
22
|
+
const paths = getStoragePaths(gitRoot);
|
|
23
|
+
return {
|
|
24
|
+
repoPath: gitRoot,
|
|
25
|
+
storagePath: paths.storagePath,
|
|
26
|
+
repoName: getInferredRepoName(gitRoot) ?? path.basename(gitRoot),
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export const bootstrapCommand = async (opts = {}) => {
|
|
30
|
+
const repo = await resolveRepoForGraphpack();
|
|
31
|
+
const result = await bootstrapGraphpack({
|
|
32
|
+
repoPath: repo.repoPath,
|
|
33
|
+
storagePath: repo.storagePath,
|
|
34
|
+
lockPath: opts.lock ? path.resolve(opts.lock) : undefined,
|
|
35
|
+
artifactDir: opts.artifactDir ? path.resolve(opts.artifactDir) : undefined,
|
|
36
|
+
});
|
|
37
|
+
await maybeRegisterRepo(repo);
|
|
38
|
+
if (opts.materialize !== false && result.materializable) {
|
|
39
|
+
await materializeGraphpackHead(result.status.lock?.graphpack.graphstoreHeadCommit);
|
|
40
|
+
}
|
|
41
|
+
if (opts.json) {
|
|
42
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
printPullLikeResult('bootstrap', result);
|
|
46
|
+
};
|
|
47
|
+
export const graphpackPublishCommand = async (opts = {}) => {
|
|
48
|
+
const repo = await resolveRepoForGraphpack();
|
|
49
|
+
const result = await publishGraphpack({
|
|
50
|
+
repoPath: repo.repoPath,
|
|
51
|
+
storagePath: repo.storagePath,
|
|
52
|
+
repoName: opts.repo ?? repo.repoName,
|
|
53
|
+
analyzerVersion: pkg.version,
|
|
54
|
+
target: opts.target ?? 'main',
|
|
55
|
+
artifactDir: opts.artifactDir ? path.resolve(opts.artifactDir) : undefined,
|
|
56
|
+
artifactUrl: opts.artifactUrl,
|
|
57
|
+
baseSnapshotId: opts.baseSnapshot,
|
|
58
|
+
headSnapshotId: opts.headSnapshot,
|
|
59
|
+
pullRequest: opts.pr,
|
|
60
|
+
});
|
|
61
|
+
if (opts.json) {
|
|
62
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
process.stdout.write([
|
|
66
|
+
`graphpack: ${result.lock.graphpack.id}`,
|
|
67
|
+
`target: ${result.lock.graphpack.target}`,
|
|
68
|
+
`lock: ${result.lockPath}`,
|
|
69
|
+
`manifest: ${result.manifestPath}`,
|
|
70
|
+
`snapshot: ${result.lock.graphpack.graphstoreSnapshot ?? '(unknown)'}`,
|
|
71
|
+
`chunks: ${result.lock.chunks.length}`,
|
|
72
|
+
].join('\n') + '\n');
|
|
73
|
+
};
|
|
74
|
+
export const graphpackPullCommand = async (opts = {}) => {
|
|
75
|
+
const repo = await resolveRepoForGraphpack();
|
|
76
|
+
const result = await pullGraphpack({
|
|
77
|
+
repoPath: repo.repoPath,
|
|
78
|
+
storagePath: repo.storagePath,
|
|
79
|
+
lockPath: opts.lock ? path.resolve(opts.lock) : undefined,
|
|
80
|
+
artifactDir: opts.artifactDir ? path.resolve(opts.artifactDir) : undefined,
|
|
81
|
+
});
|
|
82
|
+
await maybeRegisterRepo(repo);
|
|
83
|
+
if (opts.materialize !== false && result.materializable) {
|
|
84
|
+
await materializeGraphpackHead(result.status.lock?.graphpack.graphstoreHeadCommit);
|
|
85
|
+
}
|
|
86
|
+
if (opts.json) {
|
|
87
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
printPullLikeResult('pull', result);
|
|
91
|
+
};
|
|
92
|
+
export const graphpackStatusCommand = async (opts = {}) => {
|
|
93
|
+
const repo = await resolveRepoForGraphpack();
|
|
94
|
+
const status = await getGraphpackStatus({
|
|
95
|
+
repoPath: repo.repoPath,
|
|
96
|
+
storagePath: repo.storagePath,
|
|
97
|
+
lockPath: opts.lock ? path.resolve(opts.lock) : undefined,
|
|
98
|
+
strict: opts.strict,
|
|
99
|
+
});
|
|
100
|
+
if (opts.json) {
|
|
101
|
+
process.stdout.write(`${JSON.stringify(status, null, 2)}\n`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const lines = [
|
|
105
|
+
`source: ${status.source}`,
|
|
106
|
+
`lock: ${status.lockPresent ? status.lockPath : 'missing'}`,
|
|
107
|
+
`local_graphstore: ${status.local.graphstorePresent ? 'present' : 'missing'}`,
|
|
108
|
+
status.local.headCommit ? `local_head: ${status.local.headCommit}` : undefined,
|
|
109
|
+
status.lock?.graphpack.graphstoreSnapshot
|
|
110
|
+
? `lock_snapshot: ${status.lock.graphpack.graphstoreSnapshot}`
|
|
111
|
+
: undefined,
|
|
112
|
+
`chunks: ${status.chunks.verified}/${status.chunks.expected} verified`,
|
|
113
|
+
`compatible: ${status.compatibility.ok ? 'yes' : 'no'}`,
|
|
114
|
+
].filter(Boolean);
|
|
115
|
+
if (status.compatibility.reasons.length > 0) {
|
|
116
|
+
lines.push('reasons:');
|
|
117
|
+
for (const reason of status.compatibility.reasons)
|
|
118
|
+
lines.push(` - ${reason}`);
|
|
119
|
+
}
|
|
120
|
+
if (status.chunks.missing.length > 0) {
|
|
121
|
+
lines.push('missing:');
|
|
122
|
+
for (const chunk of status.chunks.missing)
|
|
123
|
+
lines.push(` - ${chunk}`);
|
|
124
|
+
}
|
|
125
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
126
|
+
};
|
|
127
|
+
export const semanticAnalyzeCommand = async (opts = {}) => {
|
|
128
|
+
const repo = await resolveRepoForGraphpack();
|
|
129
|
+
const report = await analyzeSemanticRelationships({
|
|
130
|
+
storagePath: repo.storagePath,
|
|
131
|
+
llm: opts.llm,
|
|
132
|
+
write: opts.write !== false,
|
|
133
|
+
limit: opts.limit ? Number.parseInt(opts.limit, 10) : undefined,
|
|
134
|
+
});
|
|
135
|
+
if (opts.json) {
|
|
136
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const lines = [
|
|
140
|
+
`snapshot: ${report.snapshotId ?? '(unknown)'}`,
|
|
141
|
+
`extractor: ${report.extractorVersion}`,
|
|
142
|
+
`llm: ${report.llmEnabled ? 'enabled' : 'disabled'}`,
|
|
143
|
+
`relationships: ${report.relationships.length}`,
|
|
144
|
+
];
|
|
145
|
+
for (const [family, count] of Object.entries(report.summary)) {
|
|
146
|
+
if (count > 0)
|
|
147
|
+
lines.push(` ${family}: ${count}`);
|
|
148
|
+
}
|
|
149
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
150
|
+
};
|
|
151
|
+
export const recipesLookupCommand = async (opts = {}) => {
|
|
152
|
+
if (!opts.taskFamily)
|
|
153
|
+
throw new Error('recipes lookup requires --task-family <name>');
|
|
154
|
+
const repo = await resolveRepoForGraphpack();
|
|
155
|
+
const snapshotId = opts.snapshotId ??
|
|
156
|
+
(await getGraphpackStatus({ repoPath: repo.repoPath, storagePath: repo.storagePath })).lock
|
|
157
|
+
?.graphpack.graphstoreSnapshot;
|
|
158
|
+
if (!snapshotId) {
|
|
159
|
+
throw new Error('recipes lookup requires --snapshot-id when no graphpack lock is available.');
|
|
160
|
+
}
|
|
161
|
+
const moduleId = '@codragraph/harness/mcp/handler';
|
|
162
|
+
const mod = (await import(/* @vite-ignore */ moduleId));
|
|
163
|
+
if (!mod.handleHarnessRecipesLookup) {
|
|
164
|
+
throw new Error('@codragraph/harness/mcp/handler does not export handleHarnessRecipesLookup');
|
|
165
|
+
}
|
|
166
|
+
const result = await mod.handleHarnessRecipesLookup({
|
|
167
|
+
task_family: opts.taskFamily,
|
|
168
|
+
snapshot_id: snapshotId,
|
|
169
|
+
recipe_store: opts.recipeStore ?? path.join(repo.storagePath, 'recipes'),
|
|
170
|
+
required_subgraph_signature: opts.requiredSubgraphSignature,
|
|
171
|
+
limit: opts.limit ? Number.parseInt(opts.limit, 10) : undefined,
|
|
172
|
+
});
|
|
173
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
174
|
+
};
|
|
175
|
+
export const teamServeCommand = async (opts = {}) => {
|
|
176
|
+
const repo = await resolveRepoForGraphpack();
|
|
177
|
+
const status = await getGraphpackStatus({
|
|
178
|
+
repoPath: repo.repoPath,
|
|
179
|
+
storagePath: repo.storagePath,
|
|
180
|
+
});
|
|
181
|
+
if (opts.graphpack && status.lock?.graphpack.id !== opts.graphpack) {
|
|
182
|
+
throw new Error(`Requested graphpack ${opts.graphpack}, but lock points at ${status.lock?.graphpack.id ?? '(none)'}. Run graphpack pull or pass the matching id.`);
|
|
183
|
+
}
|
|
184
|
+
process.env.CODRAGRAPH_TEAM_GRAPH_MODE = '1';
|
|
185
|
+
process.env.CODRAGRAPH_ACTIVE_GRAPHPACK = opts.graphpack ?? status.lock?.graphpack.id ?? '';
|
|
186
|
+
const { serveCommand } = await import('./serve.js');
|
|
187
|
+
await serveCommand({ port: opts.port, host: opts.host, web: opts.web ?? 'hosted' });
|
|
188
|
+
};
|
|
189
|
+
const maybeRegisterRepo = async (repo) => {
|
|
190
|
+
const indexed = await findRepo(repo.repoPath);
|
|
191
|
+
if (!indexed?.meta)
|
|
192
|
+
return;
|
|
193
|
+
await registerRepo(repo.repoPath, indexed.meta);
|
|
194
|
+
};
|
|
195
|
+
const materializeGraphpackHead = async (headCommit) => {
|
|
196
|
+
if (!headCommit)
|
|
197
|
+
return;
|
|
198
|
+
const { checkoutCommand } = await import('./graphstore.js');
|
|
199
|
+
await checkoutCommand(headCommit, { materialize: true });
|
|
200
|
+
};
|
|
201
|
+
const printPullLikeResult = (label, result) => {
|
|
202
|
+
if (result.fallbackRequired) {
|
|
203
|
+
process.stdout.write([
|
|
204
|
+
`${label}: fallback required`,
|
|
205
|
+
`reason: ${result.reason ?? 'graphpack is not available locally'}`,
|
|
206
|
+
`fallback: ${result.fallbackCommand ?? 'codragraph analyze --skip-agents-md --no-setup'}`,
|
|
207
|
+
].join('\n') + '\n');
|
|
208
|
+
process.exitCode = 1;
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
process.stdout.write([
|
|
212
|
+
`${label}: ok`,
|
|
213
|
+
`source: ${result.status.source}`,
|
|
214
|
+
`graphpack: ${result.status.lock?.graphpack.id ?? '(none)'}`,
|
|
215
|
+
`materializable: ${result.materializable ? 'yes' : 'no'}`,
|
|
216
|
+
].join('\n') + '\n');
|
|
217
|
+
};
|
package/dist/cli/index.js
CHANGED
|
@@ -94,6 +94,14 @@ program
|
|
|
94
94
|
.command('status')
|
|
95
95
|
.description('Show index status for current repo')
|
|
96
96
|
.action(createLazyAction(() => import('./status.js'), 'statusCommand'));
|
|
97
|
+
program
|
|
98
|
+
.command('bootstrap')
|
|
99
|
+
.description('Bootstrap a local graph from .codragraph/index.lock.json when available')
|
|
100
|
+
.option('--lock <path>', 'Path to graphpack lock file')
|
|
101
|
+
.option('--artifact-dir <path>', 'Local graphpack artifact directory to pull from')
|
|
102
|
+
.option('--no-materialize', 'Validate/pull graphpack chunks without rebuilding the local cgdb')
|
|
103
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
104
|
+
.action(createLazyAction(() => import('./graphpack.js'), 'bootstrapCommand'));
|
|
97
105
|
program
|
|
98
106
|
.command('clean')
|
|
99
107
|
.description('Delete CodraGraph index for current repo')
|
|
@@ -191,6 +199,7 @@ program
|
|
|
191
199
|
.description('Generate the compact agent context pack for a feature cluster')
|
|
192
200
|
.option('-r, --repo <name>', 'Target repository')
|
|
193
201
|
.option('-l, --limit <n>', 'Max members to return (default: 100)')
|
|
202
|
+
.option('--compress <level>', 'Compression level: balanced, lean, or max')
|
|
194
203
|
.action(createOneShotLazyAction(() => import('./tool.js'), 'contextPackCommand'));
|
|
195
204
|
program
|
|
196
205
|
.command('cluster-impact <name>')
|
|
@@ -215,6 +224,69 @@ program
|
|
|
215
224
|
.option('--idle-timeout <seconds>', 'Auto-shutdown after N seconds idle (0 = disabled)', '0')
|
|
216
225
|
.action(createLazyAction(() => import('./eval-server.js'), 'evalServerCommand'));
|
|
217
226
|
registerGroupCommands(program);
|
|
227
|
+
const graphpackCmd = program
|
|
228
|
+
.command('graphpack')
|
|
229
|
+
.description('Publish, pull, and inspect team graphpack artifacts');
|
|
230
|
+
graphpackCmd
|
|
231
|
+
.command('publish')
|
|
232
|
+
.description('Publish a graphpack lock/manifest for main or PR artifact workflows')
|
|
233
|
+
.option('--target <target>', 'Graphpack target: main or pr', 'main')
|
|
234
|
+
.option('--repo <name>', 'Repository identity stored in the lock')
|
|
235
|
+
.option('--artifact-dir <path>', 'Local artifact staging directory')
|
|
236
|
+
.option('--artifact-url <url>', 'Remote artifact URL recorded in the lock')
|
|
237
|
+
.option('--base-snapshot <id>', 'PR overlay base snapshot id')
|
|
238
|
+
.option('--head-snapshot <id>', 'PR overlay head snapshot id')
|
|
239
|
+
.option('--pr <ref>', 'Pull request number or URL for overlay graphpacks')
|
|
240
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
241
|
+
.action(createLazyAction(() => import('./graphpack.js'), 'graphpackPublishCommand'));
|
|
242
|
+
graphpackCmd
|
|
243
|
+
.command('pull')
|
|
244
|
+
.description('Pull graphpack chunks and prepare local materialization')
|
|
245
|
+
.option('--lock <path>', 'Path to graphpack lock file')
|
|
246
|
+
.option('--artifact-dir <path>', 'Local graphpack artifact directory to pull from')
|
|
247
|
+
.option('--no-materialize', 'Pull/validate without rebuilding the local cgdb')
|
|
248
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
249
|
+
.action(createLazyAction(() => import('./graphpack.js'), 'graphpackPullCommand'));
|
|
250
|
+
graphpackCmd
|
|
251
|
+
.command('status', { isDefault: true })
|
|
252
|
+
.description('Show graphpack lock, chunk, and local materialization status')
|
|
253
|
+
.option('--lock <path>', 'Path to graphpack lock file')
|
|
254
|
+
.option('--strict', 'Recompute graphstore CAS digest instead of trusting local presence')
|
|
255
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
256
|
+
.action(createLazyAction(() => import('./graphpack.js'), 'graphpackStatusCommand'));
|
|
257
|
+
const semanticCmd = program
|
|
258
|
+
.command('semantic')
|
|
259
|
+
.description('Analyze developer-intent semantic relationships above raw graph edges');
|
|
260
|
+
semanticCmd
|
|
261
|
+
.command('analyze', { isDefault: true })
|
|
262
|
+
.description('Extract semantic relationship families with confidence and evidence')
|
|
263
|
+
.option('--llm', 'Allow optional LLM-inferred semantic edges when provider support is configured')
|
|
264
|
+
.option('--limit <n>', 'Maximum semantic relationships to return', '1000')
|
|
265
|
+
.option('--no-write', 'Do not write .codragraph/semantic-relationships.json')
|
|
266
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
267
|
+
.action(createLazyAction(() => import('./graphpack.js'), 'semanticAnalyzeCommand'));
|
|
268
|
+
const recipesCmd = program
|
|
269
|
+
.command('recipes')
|
|
270
|
+
.description('Lookup graph-snapshot keyed harness recipes');
|
|
271
|
+
recipesCmd
|
|
272
|
+
.command('lookup')
|
|
273
|
+
.description('Find reusable harness recipes for a task family and graph snapshot')
|
|
274
|
+
.requiredOption('--task-family <name>', 'Task family identifier')
|
|
275
|
+
.option('--snapshot-id <id>', 'Graph snapshot id. Defaults to graphpack lock snapshot.')
|
|
276
|
+
.option('--required-subgraph-signature <sig>', 'Subgraph signature needed by the task')
|
|
277
|
+
.option('--recipe-store <path>', 'Recipe store root')
|
|
278
|
+
.option('--limit <n>', 'Max entries per match kind', '10')
|
|
279
|
+
.option('--json', 'Emit machine-readable JSON')
|
|
280
|
+
.action(createLazyAction(() => import('./graphpack.js'), 'recipesLookupCommand'));
|
|
281
|
+
const teamCmd = program.command('team').description('Team graph server commands');
|
|
282
|
+
teamCmd
|
|
283
|
+
.command('serve')
|
|
284
|
+
.description('Start hosted/team MCP-compatible HTTP mode for a graphpack')
|
|
285
|
+
.option('--graphpack <id>', 'Graphpack id to serve')
|
|
286
|
+
.option('-p, --port <port>', 'Port number', '4747')
|
|
287
|
+
.option('--host <host>', 'Bind address')
|
|
288
|
+
.option('--web <mode>', 'Dashboard mode: hosted, local, or off', 'hosted')
|
|
289
|
+
.action(createLazyAction(() => import('./graphpack.js'), 'teamServeCommand'));
|
|
218
290
|
// ─── Config: unified API-key model (~/.codragraph/config.json) ─────
|
|
219
291
|
const configCmd = program
|
|
220
292
|
.command('config')
|
package/dist/cli/tool.d.ts
CHANGED
|
@@ -63,6 +63,7 @@ export declare function clusterContextCommand(name: string, options?: {
|
|
|
63
63
|
export declare function contextPackCommand(name: string, options?: {
|
|
64
64
|
repo?: string;
|
|
65
65
|
limit?: string;
|
|
66
|
+
compress?: string;
|
|
66
67
|
}): Promise<void>;
|
|
67
68
|
export declare function clusterImpactCommand(name: string, options?: {
|
|
68
69
|
direction?: string;
|
package/dist/cli/tool.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* native module which captures the Node.js process.stdout stream during init.
|
|
15
15
|
* See the output() function for details (#324).
|
|
16
16
|
*/
|
|
17
|
+
import crypto from 'node:crypto';
|
|
17
18
|
import { writeSync } from 'node:fs';
|
|
18
19
|
import { LocalBackend } from '../mcp/local/local-backend.js';
|
|
19
20
|
import { emitTokenStats } from './compress-stats.js';
|
|
@@ -238,8 +239,116 @@ export async function contextPackCommand(name, options) {
|
|
|
238
239
|
repo,
|
|
239
240
|
limit: options?.limit ? parseInt(options.limit, 10) : undefined,
|
|
240
241
|
});
|
|
241
|
-
|
|
242
|
-
|
|
242
|
+
const maybeCompressed = options?.compress
|
|
243
|
+
? compressContextPackForCli(result, name, options.compress)
|
|
244
|
+
: result;
|
|
245
|
+
output(maybeCompressed);
|
|
246
|
+
emitTokenStats(maybeCompressed);
|
|
247
|
+
}
|
|
248
|
+
function compressContextPackForCli(result, featureName, rawLevel) {
|
|
249
|
+
const level = normalizeCliCompressionLevel(rawLevel);
|
|
250
|
+
const originalText = JSON.stringify(result);
|
|
251
|
+
const compressed = pruneContextPack(result, level);
|
|
252
|
+
const compressedText = JSON.stringify(compressed);
|
|
253
|
+
const originalTokens = estimateJsonTokens(originalText);
|
|
254
|
+
const compressedTokens = estimateJsonTokens(compressedText);
|
|
255
|
+
const snapshotId = result?.snapshotId ??
|
|
256
|
+
result?.snapshot_id ??
|
|
257
|
+
result?.cluster?.lastIndexedCommit ??
|
|
258
|
+
result?.cluster?.snapshotId ??
|
|
259
|
+
'unknown';
|
|
260
|
+
const clusterId = result?.cluster?.id ?? result?.cluster?.slug ?? featureName;
|
|
261
|
+
const cacheKey = crypto
|
|
262
|
+
.createHash('sha256')
|
|
263
|
+
.update(`${snapshotId}\n${clusterId}\n${level}\ncli-context-pack-compressor-v1`)
|
|
264
|
+
.digest('hex');
|
|
265
|
+
return {
|
|
266
|
+
...compressed,
|
|
267
|
+
compression: {
|
|
268
|
+
level,
|
|
269
|
+
compressorVersion: 'cli-context-pack-compressor-v1',
|
|
270
|
+
cacheKey: `ctxpack:${cacheKey.slice(0, 32)}`,
|
|
271
|
+
originalTokens,
|
|
272
|
+
compressedTokens,
|
|
273
|
+
tokenSavingsPct: originalTokens > 0
|
|
274
|
+
? Number((((originalTokens - compressedTokens) / originalTokens) * 100).toFixed(1))
|
|
275
|
+
: 0,
|
|
276
|
+
preserved: [
|
|
277
|
+
'feature cluster',
|
|
278
|
+
'files',
|
|
279
|
+
'line ranges',
|
|
280
|
+
'symbols',
|
|
281
|
+
'tests',
|
|
282
|
+
'routes',
|
|
283
|
+
'tools',
|
|
284
|
+
'dependencies',
|
|
285
|
+
'warnings',
|
|
286
|
+
],
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function normalizeCliCompressionLevel(raw) {
|
|
291
|
+
if (raw === 'balanced' || raw === 'lean' || raw === 'max')
|
|
292
|
+
return raw;
|
|
293
|
+
throw new Error('context-pack --compress must be one of: balanced, lean, max');
|
|
294
|
+
}
|
|
295
|
+
function pruneContextPack(value, level) {
|
|
296
|
+
if (!value || typeof value !== 'object')
|
|
297
|
+
return value;
|
|
298
|
+
const memberLimit = level === 'max' ? 20 : level === 'lean' ? 40 : 80;
|
|
299
|
+
const processLimit = level === 'max' ? 5 : level === 'lean' ? 8 : 15;
|
|
300
|
+
const supportLimit = level === 'max' ? 5 : level === 'lean' ? 10 : 20;
|
|
301
|
+
return {
|
|
302
|
+
cluster: value.cluster,
|
|
303
|
+
members: Array.isArray(value.members)
|
|
304
|
+
? value.members.slice(0, memberLimit).map(compactContextPackItem)
|
|
305
|
+
: value.members,
|
|
306
|
+
entryPoints: Array.isArray(value.entryPoints)
|
|
307
|
+
? value.entryPoints.slice(0, supportLimit).map(compactContextPackItem)
|
|
308
|
+
: value.entryPoints,
|
|
309
|
+
routes: value.routes,
|
|
310
|
+
tools: value.tools,
|
|
311
|
+
dependencies: value.dependencies,
|
|
312
|
+
processes: Array.isArray(value.processes)
|
|
313
|
+
? value.processes.slice(0, processLimit).map(compactContextPackItem)
|
|
314
|
+
: value.processes,
|
|
315
|
+
tests: Array.isArray(value.tests)
|
|
316
|
+
? value.tests.slice(0, supportLimit).map(compactContextPackItem)
|
|
317
|
+
: value.tests,
|
|
318
|
+
docs: Array.isArray(value.docs)
|
|
319
|
+
? value.docs.slice(0, supportLimit).map(compactContextPackItem)
|
|
320
|
+
: value.docs,
|
|
321
|
+
warnings: value.warnings ?? value.safeEditSurface?.warnings,
|
|
322
|
+
safeEditSurface: value.safeEditSurface,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function compactContextPackItem(item) {
|
|
326
|
+
if (!item || typeof item !== 'object')
|
|
327
|
+
return item;
|
|
328
|
+
const keys = [
|
|
329
|
+
'id',
|
|
330
|
+
'uid',
|
|
331
|
+
'name',
|
|
332
|
+
'type',
|
|
333
|
+
'kind',
|
|
334
|
+
'filePath',
|
|
335
|
+
'file',
|
|
336
|
+
'startLine',
|
|
337
|
+
'endLine',
|
|
338
|
+
'route',
|
|
339
|
+
'method',
|
|
340
|
+
'summary',
|
|
341
|
+
'confidence',
|
|
342
|
+
];
|
|
343
|
+
const compact = {};
|
|
344
|
+
for (const key of keys) {
|
|
345
|
+
if (item[key] !== undefined)
|
|
346
|
+
compact[key] = item[key];
|
|
347
|
+
}
|
|
348
|
+
return compact;
|
|
349
|
+
}
|
|
350
|
+
function estimateJsonTokens(text) {
|
|
351
|
+
return Math.ceil(text.length / 4);
|
|
243
352
|
}
|
|
244
353
|
export async function clusterImpactCommand(name, options) {
|
|
245
354
|
if (!name?.trim()) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type GraphpackBootstrapResult, type GraphpackPublishOptions, type GraphpackPublishResult, type GraphpackPullOptions, type GraphpackPullResult, type GraphpackStatus, type GraphpackLock } from './types.js';
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export declare const defaultLockPath: (repoPath: string) => string;
|
|
4
|
+
export declare const readGraphpackLock: (lockPath: string) => Promise<GraphpackLock | null>;
|
|
5
|
+
export declare const writeGraphpackLock: (lockPath: string, lock: GraphpackLock) => Promise<void>;
|
|
6
|
+
export declare const publishGraphpack: (opts: GraphpackPublishOptions) => Promise<GraphpackPublishResult>;
|
|
7
|
+
export declare const getGraphpackStatus: (opts: {
|
|
8
|
+
repoPath: string;
|
|
9
|
+
storagePath: string;
|
|
10
|
+
lockPath?: string;
|
|
11
|
+
strict?: boolean;
|
|
12
|
+
}) => Promise<GraphpackStatus>;
|
|
13
|
+
export declare const pullGraphpack: (opts: GraphpackPullOptions) => Promise<GraphpackPullResult>;
|
|
14
|
+
export declare const bootstrapGraphpack: (opts: GraphpackPullOptions) => Promise<GraphpackBootstrapResult>;
|