@colbymchenry/codegraph 0.7.4 → 0.7.9

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.
Files changed (70) hide show
  1. package/README.md +35 -10
  2. package/dist/bin/codegraph.js +72 -4
  3. package/dist/bin/codegraph.js.map +1 -1
  4. package/dist/bin/uninstall.d.ts +7 -7
  5. package/dist/bin/uninstall.d.ts.map +1 -1
  6. package/dist/bin/uninstall.js +23 -135
  7. package/dist/bin/uninstall.js.map +1 -1
  8. package/dist/installer/claude-md-template.d.ts +10 -6
  9. package/dist/installer/claude-md-template.d.ts.map +1 -1
  10. package/dist/installer/claude-md-template.js +15 -40
  11. package/dist/installer/claude-md-template.js.map +1 -1
  12. package/dist/installer/config-writer.d.ts +17 -24
  13. package/dist/installer/config-writer.d.ts.map +1 -1
  14. package/dist/installer/config-writer.js +44 -239
  15. package/dist/installer/config-writer.js.map +1 -1
  16. package/dist/installer/index.d.ts +45 -4
  17. package/dist/installer/index.d.ts.map +1 -1
  18. package/dist/installer/index.js +214 -78
  19. package/dist/installer/index.js.map +1 -1
  20. package/dist/installer/instructions-template.d.ts +28 -0
  21. package/dist/installer/instructions-template.d.ts.map +1 -0
  22. package/dist/installer/instructions-template.js +63 -0
  23. package/dist/installer/instructions-template.js.map +1 -0
  24. package/dist/installer/targets/claude.d.ts +27 -0
  25. package/dist/installer/targets/claude.d.ts.map +1 -0
  26. package/dist/installer/targets/claude.js +246 -0
  27. package/dist/installer/targets/claude.js.map +1 -0
  28. package/dist/installer/targets/codex.d.ts +18 -0
  29. package/dist/installer/targets/codex.d.ts.map +1 -0
  30. package/dist/installer/targets/codex.js +185 -0
  31. package/dist/installer/targets/codex.js.map +1 -0
  32. package/dist/installer/targets/cursor.d.ts +35 -0
  33. package/dist/installer/targets/cursor.d.ts.map +1 -0
  34. package/dist/installer/targets/cursor.js +229 -0
  35. package/dist/installer/targets/cursor.js.map +1 -0
  36. package/dist/installer/targets/opencode.d.ts +30 -0
  37. package/dist/installer/targets/opencode.d.ts.map +1 -0
  38. package/dist/installer/targets/opencode.js +235 -0
  39. package/dist/installer/targets/opencode.js.map +1 -0
  40. package/dist/installer/targets/registry.d.ts +35 -0
  41. package/dist/installer/targets/registry.d.ts.map +1 -0
  42. package/dist/installer/targets/registry.js +83 -0
  43. package/dist/installer/targets/registry.js.map +1 -0
  44. package/dist/installer/targets/shared.d.ts +77 -0
  45. package/dist/installer/targets/shared.d.ts.map +1 -0
  46. package/dist/installer/targets/shared.js +246 -0
  47. package/dist/installer/targets/shared.js.map +1 -0
  48. package/dist/installer/targets/toml.d.ts +52 -0
  49. package/dist/installer/targets/toml.d.ts.map +1 -0
  50. package/dist/installer/targets/toml.js +147 -0
  51. package/dist/installer/targets/toml.js.map +1 -0
  52. package/dist/installer/targets/types.d.ts +116 -0
  53. package/dist/installer/targets/types.d.ts.map +1 -0
  54. package/dist/installer/targets/types.js +16 -0
  55. package/dist/installer/targets/types.js.map +1 -0
  56. package/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
  57. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
  58. package/dist/resolution/frameworks/cargo-workspace.js +225 -0
  59. package/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
  60. package/dist/resolution/frameworks/rust.d.ts.map +1 -1
  61. package/dist/resolution/frameworks/rust.js +35 -17
  62. package/dist/resolution/frameworks/rust.js.map +1 -1
  63. package/dist/resolution/index.d.ts.map +1 -1
  64. package/dist/resolution/index.js +18 -0
  65. package/dist/resolution/index.js.map +1 -1
  66. package/dist/resolution/types.d.ts +9 -0
  67. package/dist/resolution/types.d.ts.map +1 -1
  68. package/package.json +3 -2
  69. package/scripts/local-install.sh +41 -0
  70. package/scripts/release.sh +70 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Helpers shared across `AgentTarget` implementations.
3
+ *
4
+ * Lifted from the original `config-writer.ts` so each target can
5
+ * compose them without inheritance. Kept deliberately small — the
6
+ * targets are different enough (JSON vs TOML vs Markdown, varying
7
+ * idempotency markers) that a base class would force the awkward
8
+ * shape onto everyone.
9
+ */
10
+ /**
11
+ * The MCP-server config block codegraph injects. Same shape across
12
+ * all JSON-shaped agent configs (Claude, Cursor, opencode), only the
13
+ * surrounding wrapper differs. Codex (TOML) builds its own block.
14
+ */
15
+ export declare function getMcpServerConfig(): {
16
+ type: string;
17
+ command: string;
18
+ args: string[];
19
+ };
20
+ /**
21
+ * Permissions list for Claude `settings.json`. Other targets that
22
+ * have a permissions concept can compose this list directly. The
23
+ * permission strings follow Claude's `mcp__<server>__<tool>` format.
24
+ */
25
+ export declare function getCodeGraphPermissions(): string[];
26
+ /**
27
+ * Read a JSON file, returning `{}` when missing or unparseable.
28
+ *
29
+ * Unparseable files are backed up to `<path>.backup` BEFORE we return
30
+ * `{}` — so an idempotent re-run never silently deletes a user's
31
+ * existing config that happened to break JSON parse temporarily.
32
+ */
33
+ export declare function readJsonFile(filePath: string): Record<string, any>;
34
+ /**
35
+ * Write a file atomically: write to `<path>.tmp.<pid>`, then rename.
36
+ *
37
+ * Prevents corruption if the process crashes mid-write. The temp
38
+ * file is cleaned up on rename failure.
39
+ */
40
+ export declare function atomicWriteFileSync(filePath: string, content: string): void;
41
+ /**
42
+ * Atomic JSON write. Trailing newline matches the convention every
43
+ * existing target had — preserves diff-friendly file shape.
44
+ */
45
+ export declare function writeJsonFile(filePath: string, data: Record<string, any>): void;
46
+ /**
47
+ * Compare two JSON values for deep equality, ignoring key order.
48
+ *
49
+ * Used for idempotency: when the on-disk config already exactly
50
+ * matches what we'd write, return action=`unchanged` instead of
51
+ * re-writing (and emitting a confusing "Updated" log line).
52
+ */
53
+ export declare function jsonDeepEqual(a: unknown, b: unknown): boolean;
54
+ /**
55
+ * Replace or append a marker-delimited section in a markdown-ish file.
56
+ *
57
+ * Used by Claude / Codex for the `<!-- CODEGRAPH_START --> ... <!--
58
+ * CODEGRAPH_END -->` block. Preserves all content outside the
59
+ * markers verbatim.
60
+ *
61
+ * Returns `created` when the file didn't exist; `updated` when
62
+ * markers were found and content swapped; `appended` when markers
63
+ * weren't found and section was added at end. `unchanged` when the
64
+ * existing block already matches `body`.
65
+ */
66
+ export declare function replaceOrAppendMarkedSection(filePath: string, body: string, startMarker: string, endMarker: string): 'created' | 'updated' | 'appended' | 'unchanged';
67
+ /**
68
+ * Inverse of `replaceOrAppendMarkedSection`. Strips the marker
69
+ * block from `filePath` if present. If the file becomes empty after
70
+ * removal, deletes the file entirely (matches the existing Claude
71
+ * uninstall behavior).
72
+ *
73
+ * Returns `removed` when content was stripped, `not-found` when
74
+ * the markers weren't present, `kept` when the file didn't exist.
75
+ */
76
+ export declare function removeMarkedSection(filePath: string, startMarker: string, endMarker: string): 'removed' | 'not-found' | 'kept';
77
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/installer/targets/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAMtF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,EAAE,CAUlD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAelE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAa3E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAE/E;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAiB7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CA2BlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,SAAS,GAAG,WAAW,GAAG,MAAM,CAwBlC"}
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ /**
3
+ * Helpers shared across `AgentTarget` implementations.
4
+ *
5
+ * Lifted from the original `config-writer.ts` so each target can
6
+ * compose them without inheritance. Kept deliberately small — the
7
+ * targets are different enough (JSON vs TOML vs Markdown, varying
8
+ * idempotency markers) that a base class would force the awkward
9
+ * shape onto everyone.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.getMcpServerConfig = getMcpServerConfig;
46
+ exports.getCodeGraphPermissions = getCodeGraphPermissions;
47
+ exports.readJsonFile = readJsonFile;
48
+ exports.atomicWriteFileSync = atomicWriteFileSync;
49
+ exports.writeJsonFile = writeJsonFile;
50
+ exports.jsonDeepEqual = jsonDeepEqual;
51
+ exports.replaceOrAppendMarkedSection = replaceOrAppendMarkedSection;
52
+ exports.removeMarkedSection = removeMarkedSection;
53
+ const fs = __importStar(require("fs"));
54
+ const path = __importStar(require("path"));
55
+ /**
56
+ * The MCP-server config block codegraph injects. Same shape across
57
+ * all JSON-shaped agent configs (Claude, Cursor, opencode), only the
58
+ * surrounding wrapper differs. Codex (TOML) builds its own block.
59
+ */
60
+ function getMcpServerConfig() {
61
+ return {
62
+ type: 'stdio',
63
+ command: 'codegraph',
64
+ args: ['serve', '--mcp'],
65
+ };
66
+ }
67
+ /**
68
+ * Permissions list for Claude `settings.json`. Other targets that
69
+ * have a permissions concept can compose this list directly. The
70
+ * permission strings follow Claude's `mcp__<server>__<tool>` format.
71
+ */
72
+ function getCodeGraphPermissions() {
73
+ return [
74
+ 'mcp__codegraph__codegraph_search',
75
+ 'mcp__codegraph__codegraph_context',
76
+ 'mcp__codegraph__codegraph_callers',
77
+ 'mcp__codegraph__codegraph_callees',
78
+ 'mcp__codegraph__codegraph_impact',
79
+ 'mcp__codegraph__codegraph_node',
80
+ 'mcp__codegraph__codegraph_status',
81
+ ];
82
+ }
83
+ /**
84
+ * Read a JSON file, returning `{}` when missing or unparseable.
85
+ *
86
+ * Unparseable files are backed up to `<path>.backup` BEFORE we return
87
+ * `{}` — so an idempotent re-run never silently deletes a user's
88
+ * existing config that happened to break JSON parse temporarily.
89
+ */
90
+ function readJsonFile(filePath) {
91
+ if (!fs.existsSync(filePath)) {
92
+ return {};
93
+ }
94
+ try {
95
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
96
+ }
97
+ catch (err) {
98
+ const msg = err instanceof Error ? err.message : String(err);
99
+ console.warn(` Warning: Could not parse ${path.basename(filePath)}: ${msg}`);
100
+ console.warn(` A backup will be created before overwriting.`);
101
+ try {
102
+ fs.copyFileSync(filePath, filePath + '.backup');
103
+ }
104
+ catch { /* ignore backup failure */ }
105
+ return {};
106
+ }
107
+ }
108
+ /**
109
+ * Write a file atomically: write to `<path>.tmp.<pid>`, then rename.
110
+ *
111
+ * Prevents corruption if the process crashes mid-write. The temp
112
+ * file is cleaned up on rename failure.
113
+ */
114
+ function atomicWriteFileSync(filePath, content) {
115
+ const dir = path.dirname(filePath);
116
+ if (!fs.existsSync(dir)) {
117
+ fs.mkdirSync(dir, { recursive: true });
118
+ }
119
+ const tmpPath = filePath + '.tmp.' + process.pid;
120
+ try {
121
+ fs.writeFileSync(tmpPath, content);
122
+ fs.renameSync(tmpPath, filePath);
123
+ }
124
+ catch (err) {
125
+ try {
126
+ fs.unlinkSync(tmpPath);
127
+ }
128
+ catch { /* ignore */ }
129
+ throw err;
130
+ }
131
+ }
132
+ /**
133
+ * Atomic JSON write. Trailing newline matches the convention every
134
+ * existing target had — preserves diff-friendly file shape.
135
+ */
136
+ function writeJsonFile(filePath, data) {
137
+ atomicWriteFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
138
+ }
139
+ /**
140
+ * Compare two JSON values for deep equality, ignoring key order.
141
+ *
142
+ * Used for idempotency: when the on-disk config already exactly
143
+ * matches what we'd write, return action=`unchanged` instead of
144
+ * re-writing (and emitting a confusing "Updated" log line).
145
+ */
146
+ function jsonDeepEqual(a, b) {
147
+ if (a === b)
148
+ return true;
149
+ if (typeof a !== typeof b)
150
+ return false;
151
+ if (a === null || b === null)
152
+ return a === b;
153
+ if (typeof a !== 'object')
154
+ return false;
155
+ if (Array.isArray(a) !== Array.isArray(b))
156
+ return false;
157
+ if (Array.isArray(a) && Array.isArray(b)) {
158
+ if (a.length !== b.length)
159
+ return false;
160
+ return a.every((v, i) => jsonDeepEqual(v, b[i]));
161
+ }
162
+ const ao = a;
163
+ const bo = b;
164
+ const ak = Object.keys(ao).sort();
165
+ const bk = Object.keys(bo).sort();
166
+ if (ak.length !== bk.length)
167
+ return false;
168
+ if (!ak.every((k, i) => k === bk[i]))
169
+ return false;
170
+ return ak.every((k) => jsonDeepEqual(ao[k], bo[k]));
171
+ }
172
+ /**
173
+ * Replace or append a marker-delimited section in a markdown-ish file.
174
+ *
175
+ * Used by Claude / Codex for the `<!-- CODEGRAPH_START --> ... <!--
176
+ * CODEGRAPH_END -->` block. Preserves all content outside the
177
+ * markers verbatim.
178
+ *
179
+ * Returns `created` when the file didn't exist; `updated` when
180
+ * markers were found and content swapped; `appended` when markers
181
+ * weren't found and section was added at end. `unchanged` when the
182
+ * existing block already matches `body`.
183
+ */
184
+ function replaceOrAppendMarkedSection(filePath, body, startMarker, endMarker) {
185
+ if (!fs.existsSync(filePath)) {
186
+ atomicWriteFileSync(filePath, body + '\n');
187
+ return 'created';
188
+ }
189
+ const content = fs.readFileSync(filePath, 'utf-8');
190
+ const startIdx = content.indexOf(startMarker);
191
+ const endIdx = content.indexOf(endMarker);
192
+ if (startIdx !== -1 && endIdx > startIdx) {
193
+ const existingBlock = content.substring(startIdx, endIdx + endMarker.length);
194
+ if (existingBlock === body) {
195
+ return 'unchanged';
196
+ }
197
+ const before = content.substring(0, startIdx);
198
+ const after = content.substring(endIdx + endMarker.length);
199
+ atomicWriteFileSync(filePath, before + body + after);
200
+ return 'updated';
201
+ }
202
+ // No markers — append. Preserve existing content with a separating
203
+ // blank line.
204
+ const trimmed = content.trimEnd();
205
+ const sep = trimmed.length > 0 ? '\n\n' : '';
206
+ atomicWriteFileSync(filePath, trimmed + sep + body + '\n');
207
+ return 'appended';
208
+ }
209
+ /**
210
+ * Inverse of `replaceOrAppendMarkedSection`. Strips the marker
211
+ * block from `filePath` if present. If the file becomes empty after
212
+ * removal, deletes the file entirely (matches the existing Claude
213
+ * uninstall behavior).
214
+ *
215
+ * Returns `removed` when content was stripped, `not-found` when
216
+ * the markers weren't present, `kept` when the file didn't exist.
217
+ */
218
+ function removeMarkedSection(filePath, startMarker, endMarker) {
219
+ if (!fs.existsSync(filePath))
220
+ return 'kept';
221
+ let content;
222
+ try {
223
+ content = fs.readFileSync(filePath, 'utf-8');
224
+ }
225
+ catch {
226
+ return 'kept';
227
+ }
228
+ const startIdx = content.indexOf(startMarker);
229
+ const endIdx = content.indexOf(endMarker);
230
+ if (startIdx === -1 || endIdx <= startIdx)
231
+ return 'not-found';
232
+ const before = content.substring(0, startIdx).trimEnd();
233
+ const after = content.substring(endIdx + endMarker.length).trimStart();
234
+ const joined = before + (before && after ? '\n\n' : '') + after;
235
+ if (joined.trim() === '') {
236
+ try {
237
+ fs.unlinkSync(filePath);
238
+ }
239
+ catch { /* ignore */ }
240
+ }
241
+ else {
242
+ atomicWriteFileSync(filePath, joined.trim() + '\n');
243
+ }
244
+ return 'removed';
245
+ }
246
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/installer/targets/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Tiny TOML helpers — just enough to inject / replace / remove a
3
+ * single dotted-key table block (`[mcp_servers.codegraph]`) inside an
4
+ * existing `~/.codex/config.toml`. We deliberately do NOT try to be a
5
+ * general TOML parser/serializer; that would mean pulling in a
6
+ * dependency (~50KB) for ~6 lines of output.
7
+ *
8
+ * Strategy: treat the file as text. Find the `[mcp_servers.codegraph]`
9
+ * header line, splice it (and the lines that follow it until the next
10
+ * `[...]` header or EOF) in or out. Everything outside that block is
11
+ * preserved verbatim, byte-for-byte.
12
+ *
13
+ * Limitations (acceptable for our narrow use):
14
+ * - Only handles top-level table headers; not array-of-tables or
15
+ * subtables nested inside `[mcp_servers]` itself (we always write
16
+ * the full dotted key `[mcp_servers.codegraph]`).
17
+ * - Doesn't validate sibling TOML — if the file is malformed
18
+ * elsewhere, our injection won't fix it but won't make it worse.
19
+ * - Quotes string values with double quotes; escapes `\` and `"`.
20
+ */
21
+ /**
22
+ * Serialize a record into the body lines of a TOML table. Values
23
+ * supported: string, string[]. Other types throw — the codex MCP
24
+ * config only needs these two.
25
+ */
26
+ export declare function serializeTomlTableBody(values: Record<string, string | string[]>): string;
27
+ /**
28
+ * Build a full table block: header line + body. Suitable for direct
29
+ * insertion into a TOML file.
30
+ */
31
+ export declare function buildTomlTable(header: string, values: Record<string, string | string[]>): string;
32
+ /**
33
+ * Insert or replace a top-level dotted-key TOML table block in the
34
+ * given file content. Preserves all other content verbatim.
35
+ *
36
+ * Returns `'inserted'` when the table was newly added, `'replaced'`
37
+ * when an existing one was rewritten, `'unchanged'` when the
38
+ * existing block already matches `block` byte-for-byte.
39
+ */
40
+ export declare function upsertTomlTable(fileContent: string, header: string, block: string): {
41
+ content: string;
42
+ action: 'inserted' | 'replaced' | 'unchanged';
43
+ };
44
+ /**
45
+ * Remove a top-level dotted-key TOML table block. Returns the
46
+ * possibly-empty new content + an action flag.
47
+ */
48
+ export declare function removeTomlTable(fileContent: string, header: string): {
49
+ content: string;
50
+ action: 'removed' | 'not-found';
51
+ };
52
+ //# sourceMappingURL=toml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toml.d.ts","sourceRoot":"","sources":["../../../src/installer/targets/toml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM,CAaxF;AAQD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM,CAEhG;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,CAAA;CAAE,CAkCpE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,WAAW,CAAA;CAAE,CAUtD"}
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ /**
3
+ * Tiny TOML helpers — just enough to inject / replace / remove a
4
+ * single dotted-key table block (`[mcp_servers.codegraph]`) inside an
5
+ * existing `~/.codex/config.toml`. We deliberately do NOT try to be a
6
+ * general TOML parser/serializer; that would mean pulling in a
7
+ * dependency (~50KB) for ~6 lines of output.
8
+ *
9
+ * Strategy: treat the file as text. Find the `[mcp_servers.codegraph]`
10
+ * header line, splice it (and the lines that follow it until the next
11
+ * `[...]` header or EOF) in or out. Everything outside that block is
12
+ * preserved verbatim, byte-for-byte.
13
+ *
14
+ * Limitations (acceptable for our narrow use):
15
+ * - Only handles top-level table headers; not array-of-tables or
16
+ * subtables nested inside `[mcp_servers]` itself (we always write
17
+ * the full dotted key `[mcp_servers.codegraph]`).
18
+ * - Doesn't validate sibling TOML — if the file is malformed
19
+ * elsewhere, our injection won't fix it but won't make it worse.
20
+ * - Quotes string values with double quotes; escapes `\` and `"`.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.serializeTomlTableBody = serializeTomlTableBody;
24
+ exports.buildTomlTable = buildTomlTable;
25
+ exports.upsertTomlTable = upsertTomlTable;
26
+ exports.removeTomlTable = removeTomlTable;
27
+ /**
28
+ * Serialize a record into the body lines of a TOML table. Values
29
+ * supported: string, string[]. Other types throw — the codex MCP
30
+ * config only needs these two.
31
+ */
32
+ function serializeTomlTableBody(values) {
33
+ const lines = [];
34
+ for (const [key, value] of Object.entries(values)) {
35
+ if (typeof value === 'string') {
36
+ lines.push(`${key} = ${quoteString(value)}`);
37
+ }
38
+ else if (Array.isArray(value) && value.every((v) => typeof v === 'string')) {
39
+ const parts = value.map(quoteString).join(', ');
40
+ lines.push(`${key} = [${parts}]`);
41
+ }
42
+ else {
43
+ throw new Error(`Unsupported TOML value type for key "${key}"`);
44
+ }
45
+ }
46
+ return lines.join('\n');
47
+ }
48
+ function quoteString(s) {
49
+ // TOML basic strings: backslash and double-quote escapes; control
50
+ // chars not expected in our payload (paths/args).
51
+ return '"' + s.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
52
+ }
53
+ /**
54
+ * Build a full table block: header line + body. Suitable for direct
55
+ * insertion into a TOML file.
56
+ */
57
+ function buildTomlTable(header, values) {
58
+ return `[${header}]\n${serializeTomlTableBody(values)}`;
59
+ }
60
+ /**
61
+ * Insert or replace a top-level dotted-key TOML table block in the
62
+ * given file content. Preserves all other content verbatim.
63
+ *
64
+ * Returns `'inserted'` when the table was newly added, `'replaced'`
65
+ * when an existing one was rewritten, `'unchanged'` when the
66
+ * existing block already matches `block` byte-for-byte.
67
+ */
68
+ function upsertTomlTable(fileContent, header, block) {
69
+ const headerLine = `[${header}]`;
70
+ const headerIdx = findHeaderIndex(fileContent, headerLine);
71
+ if (headerIdx === -1) {
72
+ // Insert at end with separating blank line if there's existing content.
73
+ const trimmed = fileContent.trimEnd();
74
+ const sep = trimmed.length > 0 ? '\n\n' : '';
75
+ return {
76
+ content: trimmed + sep + block + '\n',
77
+ action: 'inserted',
78
+ };
79
+ }
80
+ // Find the end of this block: next `[...]` header (at line start) or EOF.
81
+ const blockEnd = findNextTableHeader(fileContent, headerIdx + headerLine.length);
82
+ const existingBlock = fileContent.substring(headerIdx, blockEnd).replace(/\n+$/, '');
83
+ if (existingBlock === block) {
84
+ return { content: fileContent, action: 'unchanged' };
85
+ }
86
+ const before = fileContent.substring(0, headerIdx);
87
+ const after = fileContent.substring(blockEnd);
88
+ // Trim trailing blank lines from `before` (we'll re-add one) and
89
+ // leading blank lines from `after` so the file shape stays clean.
90
+ const beforeClean = before.replace(/\n+$/, '');
91
+ const afterClean = after.replace(/^\n+/, '');
92
+ const sepBefore = beforeClean.length > 0 ? '\n\n' : '';
93
+ const sepAfter = afterClean.length > 0 ? '\n\n' : '\n';
94
+ return {
95
+ content: beforeClean + sepBefore + block + sepAfter + afterClean,
96
+ action: 'replaced',
97
+ };
98
+ }
99
+ /**
100
+ * Remove a top-level dotted-key TOML table block. Returns the
101
+ * possibly-empty new content + an action flag.
102
+ */
103
+ function removeTomlTable(fileContent, header) {
104
+ const headerLine = `[${header}]`;
105
+ const headerIdx = findHeaderIndex(fileContent, headerLine);
106
+ if (headerIdx === -1)
107
+ return { content: fileContent, action: 'not-found' };
108
+ const blockEnd = findNextTableHeader(fileContent, headerIdx + headerLine.length);
109
+ const before = fileContent.substring(0, headerIdx).replace(/\n+$/, '');
110
+ const after = fileContent.substring(blockEnd).replace(/^\n+/, '');
111
+ const joined = before + (before && after ? '\n\n' : '') + after;
112
+ return { content: joined, action: 'removed' };
113
+ }
114
+ /**
115
+ * Locate the byte index of a header line (`[foo.bar]`) when it
116
+ * appears at the start of a line. Returns -1 if not found.
117
+ */
118
+ function findHeaderIndex(content, headerLine) {
119
+ // Search BOL or right after a newline.
120
+ if (content.startsWith(headerLine))
121
+ return 0;
122
+ const needle = '\n' + headerLine;
123
+ const idx = content.indexOf(needle);
124
+ return idx === -1 ? -1 : idx + 1;
125
+ }
126
+ /**
127
+ * Find the byte index of the next top-level `[...]` table header
128
+ * (excluding array-of-tables `[[...]]`) starting from `from`, or
129
+ * return content length when none.
130
+ */
131
+ function findNextTableHeader(content, from) {
132
+ // Look for "\n[" but skip "\n[[" (array of tables).
133
+ let i = from;
134
+ while (i < content.length) {
135
+ const nlIdx = content.indexOf('\n[', i);
136
+ if (nlIdx === -1)
137
+ return content.length;
138
+ if (content[nlIdx + 2] === '[') {
139
+ // [[...]] — keep searching past it.
140
+ i = nlIdx + 2;
141
+ continue;
142
+ }
143
+ return nlIdx + 1;
144
+ }
145
+ return content.length;
146
+ }
147
+ //# sourceMappingURL=toml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toml.js","sourceRoot":"","sources":["../../../src/installer/targets/toml.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Agent target abstraction for the installer.
3
+ *
4
+ * Each MCP-capable agent (Claude Code, Cursor, Codex CLI, opencode, ...)
5
+ * implements this interface so the installer orchestrator can write the
6
+ * right MCP-server config + instructions file + permissions for that
7
+ * agent without baking client-specific paths into core code. Adding a
8
+ * new agent = one new file in `targets/` + one entry in `registry.ts`.
9
+ *
10
+ * Closes the Claude-locked installer issue (upstream #137). The
11
+ * runtime MCP server is already agent-agnostic; this brings the
12
+ * installer to the same surface.
13
+ */
14
+ export type Location = 'global' | 'local';
15
+ /**
16
+ * Stable string id used in the `--target` CLI flag and the registry
17
+ * lookup. New targets add a value here when they're added to the
18
+ * registry. Keep these short and lowercase.
19
+ */
20
+ export type TargetId = 'claude' | 'cursor' | 'codex' | 'opencode';
21
+ /**
22
+ * Result of `target.detect(location)`.
23
+ *
24
+ * `installed` is a best-effort heuristic that the agent's CLI / app /
25
+ * config dir is present on this system — used to default the
26
+ * multiselect prompt to "what's actually here." False positives are
27
+ * acceptable (we still write); false negatives just mean the user
28
+ * has to opt in manually.
29
+ *
30
+ * `alreadyConfigured` reports whether codegraph has already been
31
+ * wired into this target at this location — drives the
32
+ * "Updated"-vs-"Added" log line and lets `--check` exit 0/1.
33
+ */
34
+ export interface DetectionResult {
35
+ installed: boolean;
36
+ alreadyConfigured: boolean;
37
+ /** Path inspected; surfaced in diagnostic / dry-run output. */
38
+ configPath?: string;
39
+ }
40
+ /**
41
+ * What `target.install(location)` actually changed on disk. The
42
+ * orchestrator renders one log line per file using `action`.
43
+ *
44
+ * `unchanged` means we touched the file but its contents were already
45
+ * what we'd write — used for byte-identical idempotent re-runs.
46
+ */
47
+ export interface WriteResult {
48
+ files: Array<{
49
+ path: string;
50
+ action: 'created' | 'updated' | 'unchanged' | 'removed' | 'not-found' | 'kept';
51
+ }>;
52
+ /**
53
+ * Optional one-line notes the orchestrator surfaces verbatim — e.g.
54
+ * "Restart Cursor to apply." Keep these short; multi-line goes in
55
+ * the README.
56
+ */
57
+ notes?: string[];
58
+ }
59
+ export interface InstallOptions {
60
+ /**
61
+ * Whether to write the agent's permissions / auto-allow surface
62
+ * (Claude `settings.json`, others where applicable). When the
63
+ * target has no permissions concept this option is a no-op.
64
+ */
65
+ autoAllow: boolean;
66
+ }
67
+ export interface AgentTarget {
68
+ /** Stable id; matches the `TargetId` union. */
69
+ readonly id: TargetId;
70
+ /** Human-readable name shown in clack prompts and log lines. */
71
+ readonly displayName: string;
72
+ /** Optional URL for "where do I learn more about this agent." */
73
+ readonly docsUrl?: string;
74
+ /**
75
+ * Whether this target supports the given install location.
76
+ *
77
+ * Some agents (Codex CLI as of 2026-05) have no project-local
78
+ * config concept — only a single `~/.codex/` dir. Returning false
79
+ * for an unsupported (target, location) pair lets the orchestrator
80
+ * skip cleanly with a clear message.
81
+ */
82
+ supportsLocation(loc: Location): boolean;
83
+ detect(loc: Location): DetectionResult;
84
+ install(loc: Location, opts: InstallOptions): WriteResult;
85
+ /**
86
+ * Inverse of install. Removes only what install would have written;
87
+ * preserves sibling MCP servers, sibling permissions, and unrelated
88
+ * markdown sections. Must be safe to call when nothing was ever
89
+ * installed (returns `not-found` actions).
90
+ */
91
+ uninstall(loc: Location): WriteResult;
92
+ /**
93
+ * Print the MCP-server snippet a user would paste manually for this
94
+ * target. Used by `codegraph install --print-config <id>` and by
95
+ * the README. Must NOT touch the filesystem.
96
+ */
97
+ printConfig(loc: Location): string;
98
+ /** Filesystem paths this target would write to at this location. */
99
+ describePaths(loc: Location): string[];
100
+ /**
101
+ * Optional. Write any project-local surfaces this target needs in
102
+ * order to work fully when its MCP config is configured globally.
103
+ * Called by `codegraph init` to bootstrap new projects without
104
+ * forcing the user to re-run `codegraph install` per project.
105
+ *
106
+ * Most targets need nothing here — their global config is complete.
107
+ * Cursor is the notable exception: its rules system
108
+ * (`.cursor/rules/*.mdc`) is project-scoped only, and is what makes
109
+ * Cursor's agent prefer codegraph over its built-in grep.
110
+ *
111
+ * Must be idempotent. Targets that have nothing project-local omit
112
+ * the method entirely.
113
+ */
114
+ wireProjectSurfaces?(): WriteResult;
115
+ }
116
+ //# sourceMappingURL=types.d.ts.map