@flyingrobots/graft 0.7.0 → 0.7.1
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/CHANGELOG.md +13 -0
- package/README.md +0 -1
- package/bin/graft.js +26 -26
- package/dist/cli/init-client-config.d.ts.map +1 -1
- package/dist/cli/init-client-config.js +40 -4
- package/dist/cli/init-client-config.js.map +1 -1
- package/dist/cli/init-model.js +2 -2
- package/dist/cli/init-model.js.map +1 -1
- package/dist/cli/json-document.d.ts +1 -0
- package/dist/cli/json-document.d.ts.map +1 -1
- package/dist/cli/json-document.js +3 -0
- package/dist/cli/json-document.js.map +1 -1
- package/dist/hooks/posttooluse-read.js +1 -1
- package/dist/hooks/posttooluse-read.js.map +1 -1
- package/dist/hooks/pretooluse-read.js +1 -1
- package/dist/hooks/pretooluse-read.js.map +1 -1
- package/dist/mcp/daemon-worker-child-pool.d.ts +2 -0
- package/dist/mcp/daemon-worker-child-pool.d.ts.map +1 -1
- package/dist/mcp/daemon-worker-child-pool.js +10 -3
- package/dist/mcp/daemon-worker-child-pool.js.map +1 -1
- package/dist/mcp/daemon-worker-pool.d.ts +1 -1
- package/dist/mcp/daemon-worker-pool.d.ts.map +1 -1
- package/dist/mcp/daemon-worker-pool.js +1 -1
- package/dist/mcp/daemon-worker-pool.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +3 -1
- package/dist/version.js.map +1 -1
- package/docs/SETUP.md +11 -7
- package/package.json +9 -4
- package/src/adapters/canonical-json.ts +0 -56
- package/src/adapters/json-text-decoder.ts +0 -11
- package/src/adapters/node-fs.ts +0 -43
- package/src/adapters/node-git.ts +0 -47
- package/src/adapters/node-paths.ts +0 -35
- package/src/adapters/node-process-runner.ts +0 -27
- package/src/adapters/repo-paths.ts +0 -63
- package/src/adapters/rotating-ndjson-log.ts +0 -66
- package/src/api/index.ts +0 -107
- package/src/api/repo-local-graft.ts +0 -21
- package/src/api/repo-workspace.ts +0 -34
- package/src/api/tool-bridge.ts +0 -22
- package/src/cli/activity-render.ts +0 -112
- package/src/cli/cli-error.ts +0 -192
- package/src/cli/command-parser.ts +0 -484
- package/src/cli/daemon-status-model.ts +0 -238
- package/src/cli/daemon-status-render.ts +0 -102
- package/src/cli/daemon-status.ts +0 -100
- package/src/cli/entrypoint.ts +0 -18
- package/src/cli/git-graft-enhance-model.ts +0 -131
- package/src/cli/git-graft-enhance-render.ts +0 -33
- package/src/cli/git-graft-enhance.ts +0 -54
- package/src/cli/index-cmd.ts +0 -90
- package/src/cli/index-model.ts +0 -75
- package/src/cli/init-bootstrap.ts +0 -47
- package/src/cli/init-client-config.ts +0 -428
- package/src/cli/init-model.ts +0 -284
- package/src/cli/init-render.ts +0 -54
- package/src/cli/init-target-hooks.ts +0 -93
- package/src/cli/init.ts +0 -124
- package/src/cli/json-document.ts +0 -155
- package/src/cli/local-history-dag-model.ts +0 -437
- package/src/cli/local-history-dag-render.ts +0 -133
- package/src/cli/local-history-dag.ts +0 -103
- package/src/cli/main.ts +0 -197
- package/src/cli/migrate-local-history.ts +0 -119
- package/src/cli/peer-command.ts +0 -60
- package/src/contracts/capabilities.ts +0 -540
- package/src/contracts/causal-ontology.ts +0 -627
- package/src/contracts/causal-surface-next-action.ts +0 -18
- package/src/contracts/json-object.ts +0 -18
- package/src/contracts/mcp-runtime.ts +0 -16
- package/src/contracts/output-schema-cli.ts +0 -103
- package/src/contracts/output-schema-fragments.ts +0 -881
- package/src/contracts/output-schema-mcp.ts +0 -501
- package/src/contracts/output-schema-meta.ts +0 -119
- package/src/contracts/output-schemas.ts +0 -1524
- package/src/git/diff.ts +0 -161
- package/src/git/target-git-hook-bootstrap.ts +0 -56
- package/src/guards/stream-boundary.ts +0 -110
- package/src/hooks/posttooluse-read.ts +0 -54
- package/src/hooks/pretooluse-read.ts +0 -52
- package/src/hooks/read-governor.ts +0 -95
- package/src/hooks/read-messages.ts +0 -53
- package/src/hooks/shared.ts +0 -168
- package/src/index.ts +0 -1
- package/src/mcp/burden.ts +0 -132
- package/src/mcp/cache.ts +0 -7
- package/src/mcp/cached-file.ts +0 -1
- package/src/mcp/context.ts +0 -150
- package/src/mcp/control-plane/authz-storage.ts +0 -129
- package/src/mcp/control-plane/session-registry.ts +0 -115
- package/src/mcp/control-plane/status-projection.ts +0 -76
- package/src/mcp/control-plane/types.ts +0 -144
- package/src/mcp/daemon-bootstrap.ts +0 -100
- package/src/mcp/daemon-control-plane.ts +0 -310
- package/src/mcp/daemon-job-scheduler.ts +0 -279
- package/src/mcp/daemon-repos.ts +0 -99
- package/src/mcp/daemon-server.ts +0 -172
- package/src/mcp/daemon-session-host.ts +0 -234
- package/src/mcp/daemon-stdio-bridge.ts +0 -262
- package/src/mcp/daemon-worker-child-pool.ts +0 -213
- package/src/mcp/daemon-worker-inline-pool.ts +0 -46
- package/src/mcp/daemon-worker-pool.ts +0 -7
- package/src/mcp/daemon-worker-process.ts +0 -52
- package/src/mcp/daemon-worker-types.ts +0 -66
- package/src/mcp/metrics.ts +0 -176
- package/src/mcp/monitor-health.ts +0 -83
- package/src/mcp/monitor-persistence.ts +0 -54
- package/src/mcp/monitor-tick-job.ts +0 -153
- package/src/mcp/monitor-types.ts +0 -103
- package/src/mcp/persisted-local-history-graph.ts +0 -592
- package/src/mcp/persisted-local-history-policy.ts +0 -501
- package/src/mcp/persisted-local-history-views.ts +0 -250
- package/src/mcp/persisted-local-history.ts +0 -1621
- package/src/mcp/persistent-monitor-runtime.ts +0 -482
- package/src/mcp/policy.ts +0 -75
- package/src/mcp/receipt.ts +0 -201
- package/src/mcp/repo-concurrency.ts +0 -392
- package/src/mcp/repo-overview/filter.ts +0 -44
- package/src/mcp/repo-overview/types.ts +0 -63
- package/src/mcp/repo-overview/view-projection.ts +0 -90
- package/src/mcp/repo-state-git.ts +0 -247
- package/src/mcp/repo-state-observation.ts +0 -203
- package/src/mcp/repo-state-transition.ts +0 -151
- package/src/mcp/repo-state-types.ts +0 -107
- package/src/mcp/repo-state.ts +0 -146
- package/src/mcp/repo-tool-job.ts +0 -102
- package/src/mcp/repo-tool-worker-context.ts +0 -215
- package/src/mcp/repo-workspace.ts +0 -21
- package/src/mcp/run-capture-config.ts +0 -33
- package/src/mcp/runtime-causal-context.ts +0 -72
- package/src/mcp/runtime-observability.ts +0 -217
- package/src/mcp/runtime-staged-target.ts +0 -161
- package/src/mcp/runtime-workspace-overlay.ts +0 -255
- package/src/mcp/secret-scrub.ts +0 -89
- package/src/mcp/semantic-transition-guidance.ts +0 -60
- package/src/mcp/semantic-transition-summary.ts +0 -130
- package/src/mcp/server-context.ts +0 -236
- package/src/mcp/server-invocation.ts +0 -388
- package/src/mcp/server-tool-access.ts +0 -148
- package/src/mcp/server.ts +0 -270
- package/src/mcp/stdio-server.ts +0 -26
- package/src/mcp/stdio.ts +0 -3
- package/src/mcp/tool-registry.ts +0 -98
- package/src/mcp/tools/activity-view.ts +0 -325
- package/src/mcp/tools/budget.ts +0 -23
- package/src/mcp/tools/causal-attach.ts +0 -67
- package/src/mcp/tools/causal-status.ts +0 -58
- package/src/mcp/tools/changed-since.ts +0 -71
- package/src/mcp/tools/code-find.ts +0 -192
- package/src/mcp/tools/code-refs.ts +0 -470
- package/src/mcp/tools/code-show.ts +0 -289
- package/src/mcp/tools/daemon-monitors.ts +0 -14
- package/src/mcp/tools/daemon-repos.ts +0 -22
- package/src/mcp/tools/daemon-sessions.ts +0 -14
- package/src/mcp/tools/daemon-status.ts +0 -12
- package/src/mcp/tools/diagnostic-models.ts +0 -97
- package/src/mcp/tools/doctor.ts +0 -83
- package/src/mcp/tools/explain.ts +0 -84
- package/src/mcp/tools/export-surface-diff.ts +0 -26
- package/src/mcp/tools/file-outline.ts +0 -67
- package/src/mcp/tools/git-files.ts +0 -73
- package/src/mcp/tools/graft-diff.ts +0 -35
- package/src/mcp/tools/graft-edit.ts +0 -276
- package/src/mcp/tools/knowledge-map.ts +0 -34
- package/src/mcp/tools/map-collector.ts +0 -338
- package/src/mcp/tools/map.ts +0 -185
- package/src/mcp/tools/monitor-nudge.ts +0 -19
- package/src/mcp/tools/monitor-pause.ts +0 -18
- package/src/mcp/tools/monitor-resume.ts +0 -18
- package/src/mcp/tools/monitor-start.ts +0 -20
- package/src/mcp/tools/monitor-stop.ts +0 -18
- package/src/mcp/tools/precision-live.ts +0 -158
- package/src/mcp/tools/precision-match.ts +0 -54
- package/src/mcp/tools/precision-paths.ts +0 -59
- package/src/mcp/tools/precision-query.ts +0 -127
- package/src/mcp/tools/precision-show.ts +0 -86
- package/src/mcp/tools/precision-visibility.ts +0 -44
- package/src/mcp/tools/precision-warp.ts +0 -101
- package/src/mcp/tools/precision.ts +0 -21
- package/src/mcp/tools/read-range.ts +0 -28
- package/src/mcp/tools/refactor-difficulty.ts +0 -42
- package/src/mcp/tools/run-capture.ts +0 -149
- package/src/mcp/tools/safe-read.ts +0 -148
- package/src/mcp/tools/since.ts +0 -53
- package/src/mcp/tools/state.ts +0 -39
- package/src/mcp/tools/stats.ts +0 -24
- package/src/mcp/tools/structural-blame.ts +0 -55
- package/src/mcp/tools/structural-churn.ts +0 -28
- package/src/mcp/tools/structural-log.ts +0 -41
- package/src/mcp/tools/structural-review.ts +0 -63
- package/src/mcp/tools/workspace-authorizations.ts +0 -14
- package/src/mcp/tools/workspace-authorize.ts +0 -20
- package/src/mcp/tools/workspace-bind.ts +0 -25
- package/src/mcp/tools/workspace-rebind.ts +0 -25
- package/src/mcp/tools/workspace-revoke.ts +0 -18
- package/src/mcp/tools/workspace-status.ts +0 -12
- package/src/mcp/warp-pool.ts +0 -36
- package/src/mcp/workspace-read-observation-model.ts +0 -48
- package/src/mcp/workspace-read-observation.ts +0 -103
- package/src/mcp/workspace-router-capability.ts +0 -32
- package/src/mcp/workspace-router-history.ts +0 -233
- package/src/mcp/workspace-router-model.ts +0 -131
- package/src/mcp/workspace-router-resolution.ts +0 -71
- package/src/mcp/workspace-router-runtime.ts +0 -246
- package/src/mcp/workspace-router.ts +0 -688
- package/src/metrics/logger.ts +0 -40
- package/src/metrics/types.ts +0 -40
- package/src/operations/adaptive-projection.ts +0 -54
- package/src/operations/agent-handoff.ts +0 -59
- package/src/operations/cached-file.ts +0 -40
- package/src/operations/capture-range.ts +0 -64
- package/src/operations/conversation-primer.ts +0 -82
- package/src/operations/cross-session-resume.ts +0 -104
- package/src/operations/deterministic-replay.ts +0 -143
- package/src/operations/diff-identity.ts +0 -127
- package/src/operations/export-surface-diff.ts +0 -355
- package/src/operations/file-outline.ts +0 -48
- package/src/operations/footprint-parallelism.ts +0 -98
- package/src/operations/graft-diff.ts +0 -169
- package/src/operations/horizon-of-readability.ts +0 -60
- package/src/operations/import-reference-impact.ts +0 -143
- package/src/operations/knowledge-map.ts +0 -96
- package/src/operations/observation-cache.ts +0 -165
- package/src/operations/projection-safety.ts +0 -111
- package/src/operations/read-range.ts +0 -64
- package/src/operations/repo-workspace.ts +0 -339
- package/src/operations/result-dto.ts +0 -23
- package/src/operations/safe-read.ts +0 -118
- package/src/operations/semantic-drift.ts +0 -70
- package/src/operations/session-filtration.ts +0 -76
- package/src/operations/session-replay.ts +0 -73
- package/src/operations/sludge-detector.ts +0 -356
- package/src/operations/state.ts +0 -66
- package/src/operations/structural-blame.ts +0 -197
- package/src/operations/structural-review.ts +0 -317
- package/src/operations/structured-buffer-compare.ts +0 -429
- package/src/operations/structured-buffer-model.ts +0 -456
- package/src/operations/structured-buffer-query.ts +0 -794
- package/src/operations/structured-buffer.ts +0 -181
- package/src/operations/teaching-hints.ts +0 -52
- package/src/parser/diff.ts +0 -320
- package/src/parser/lang.ts +0 -71
- package/src/parser/markdown.ts +0 -197
- package/src/parser/outline.ts +0 -316
- package/src/parser/runtime.ts +0 -71
- package/src/parser/types.ts +0 -75
- package/src/policy/evaluate.ts +0 -178
- package/src/policy/graftignore.ts +0 -6
- package/src/policy/types.ts +0 -87
- package/src/ports/codec.ts +0 -13
- package/src/ports/filesystem.ts +0 -18
- package/src/ports/git.ts +0 -16
- package/src/ports/guards.ts +0 -68
- package/src/ports/paths.ts +0 -22
- package/src/ports/process-runner.ts +0 -22
- package/src/release/security-gate.ts +0 -102
- package/src/session/tracker.ts +0 -145
- package/src/session/types.ts +0 -23
- package/src/version.ts +0 -3
- package/src/warp/ast-emitter.ts +0 -133
- package/src/warp/ast-import-resolver.ts +0 -333
- package/src/warp/commit-meta.ts +0 -19
- package/src/warp/context.ts +0 -48
- package/src/warp/dead-symbols.ts +0 -174
- package/src/warp/drift-sentinel.ts +0 -101
- package/src/warp/index-head.ts +0 -348
- package/src/warp/observers.ts +0 -101
- package/src/warp/open.ts +0 -67
- package/src/warp/outline-diff-trailer.ts +0 -100
- package/src/warp/plumbing.d.ts +0 -24
- package/src/warp/refactor-difficulty.ts +0 -257
- package/src/warp/references.ts +0 -77
- package/src/warp/stale-docs.ts +0 -210
- package/src/warp/structural-drift-detection.ts +0 -97
- package/src/warp/structural-queries.ts +0 -258
- package/src/warp/symbol-timeline.ts +0 -209
- package/src/warp/traverse-hydrate.ts +0 -61
- package/src/warp/warp-reference-count.ts +0 -47
- package/src/warp/warp-structural-blame.ts +0 -65
- package/src/warp/warp-structural-churn.ts +0 -309
- package/src/warp/warp-structural-log.ts +0 -149
- package/src/warp/writer-id.ts +0 -30
package/src/cli/index-cmd.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { CanonicalJsonCodec } from "../adapters/canonical-json.js";
|
|
2
|
-
import { nodeGit } from "../adapters/node-git.js";
|
|
3
|
-
import { nodePathOps } from "../adapters/node-paths.js";
|
|
4
|
-
import { attachCliSchemaMeta, validateCliOutput } from "../contracts/output-schemas.js";
|
|
5
|
-
import { indexHead } from "../warp/index-head.js";
|
|
6
|
-
import { openWarp } from "../warp/open.js";
|
|
7
|
-
import { writeCliError } from "./cli-error.js";
|
|
8
|
-
import {
|
|
9
|
-
buildIndexCliFailure,
|
|
10
|
-
buildIndexCliSuccess,
|
|
11
|
-
parseIndexCommandArgs,
|
|
12
|
-
type IndexCliResult,
|
|
13
|
-
} from "./index-model.js";
|
|
14
|
-
|
|
15
|
-
const codec = new CanonicalJsonCodec();
|
|
16
|
-
|
|
17
|
-
interface Writer {
|
|
18
|
-
write(chunk: string): unknown;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface RunIndexOptions {
|
|
22
|
-
cwd?: string | undefined;
|
|
23
|
-
args?: readonly string[] | undefined;
|
|
24
|
-
stdout?: Writer | undefined;
|
|
25
|
-
stderr?: Writer | undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function writeLine(writer: Writer, line = ""): void {
|
|
29
|
-
writer.write(`${line}\n`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function emitIndexJson(result: IndexCliResult, writer: Writer): void {
|
|
33
|
-
writer.write(`${codec.encode(validateCliOutput("index", attachCliSchemaMeta("index", result)))}\n`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function runIndex(options: RunIndexOptions = {}): Promise<void> {
|
|
37
|
-
const cwd = options.cwd ?? process.cwd();
|
|
38
|
-
const args = options.args ?? process.argv.slice(3);
|
|
39
|
-
const stdout = options.stdout ?? process.stdout;
|
|
40
|
-
const stderr = options.stderr ?? process.stderr;
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const { json, paths } = parseIndexCommandArgs(args);
|
|
44
|
-
const app = await openWarp({ cwd });
|
|
45
|
-
const ctx = { app, strandId: null };
|
|
46
|
-
const result = await indexHead({
|
|
47
|
-
cwd,
|
|
48
|
-
git: nodeGit,
|
|
49
|
-
pathOps: nodePathOps,
|
|
50
|
-
ctx,
|
|
51
|
-
...(paths.length > 0 ? { paths } : {}),
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
if (json) {
|
|
55
|
-
emitIndexJson(buildIndexCliSuccess({
|
|
56
|
-
cwd,
|
|
57
|
-
filesIndexed: result.filesIndexed,
|
|
58
|
-
nodesEmitted: result.nodesEmitted,
|
|
59
|
-
}), stdout);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
writeLine(stdout);
|
|
64
|
-
writeLine(stdout, `Indexing HEAD in ${cwd}`);
|
|
65
|
-
writeLine(stdout);
|
|
66
|
-
writeLine(stdout, ` files indexed: ${String(result.filesIndexed)}`);
|
|
67
|
-
writeLine(stdout, ` nodes emitted: ${String(result.nodesEmitted)}`);
|
|
68
|
-
writeLine(stdout);
|
|
69
|
-
writeLine(stdout, "Done.");
|
|
70
|
-
writeLine(stdout);
|
|
71
|
-
} catch (err: unknown) {
|
|
72
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
73
|
-
process.exitCode = 1;
|
|
74
|
-
const parsed = (() => {
|
|
75
|
-
try {
|
|
76
|
-
return parseIndexCommandArgs(args);
|
|
77
|
-
} catch {
|
|
78
|
-
return { json: args.includes("--json") };
|
|
79
|
-
}
|
|
80
|
-
})();
|
|
81
|
-
if (parsed.json) {
|
|
82
|
-
emitIndexJson(buildIndexCliFailure({ cwd, error: message }), stdout);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
writeCliError(stderr, message, {
|
|
86
|
-
usage: "graft index [--path <path>] [--json]",
|
|
87
|
-
nextSteps: ["Use `--path <path>` for lazy per-file indexing and `--json` for machine-readable output."],
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
package/src/cli/index-model.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
const indexCommandArgsSchema = z.object({
|
|
4
|
-
json: z.boolean(),
|
|
5
|
-
paths: z.array(z.string()),
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
export type IndexCommandArgs = z.infer<typeof indexCommandArgsSchema>;
|
|
9
|
-
|
|
10
|
-
const indexSuccessSchema = z.object({
|
|
11
|
-
ok: z.literal(true),
|
|
12
|
-
cwd: z.string(),
|
|
13
|
-
filesIndexed: z.number().int().nonnegative(),
|
|
14
|
-
nodesEmitted: z.number().int().nonnegative(),
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const indexFailureSchema = z.object({
|
|
18
|
-
ok: z.literal(false),
|
|
19
|
-
cwd: z.string(),
|
|
20
|
-
error: z.string(),
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
export const indexCliResultSchema = z.union([indexSuccessSchema, indexFailureSchema]);
|
|
24
|
-
|
|
25
|
-
export type IndexCliResult = z.infer<typeof indexCliResultSchema>;
|
|
26
|
-
|
|
27
|
-
export function parseIndexCommandArgs(args: readonly string[]): IndexCommandArgs {
|
|
28
|
-
let json = false;
|
|
29
|
-
const paths: string[] = [];
|
|
30
|
-
|
|
31
|
-
for (let index = 0; index < args.length; index++) {
|
|
32
|
-
const arg = args[index];
|
|
33
|
-
if (arg === undefined) continue;
|
|
34
|
-
if (arg === "--json") {
|
|
35
|
-
json = true;
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
if (arg === "--path") {
|
|
39
|
-
const value = args[index + 1];
|
|
40
|
-
if (value === undefined) {
|
|
41
|
-
throw new Error("Missing value for --path");
|
|
42
|
-
}
|
|
43
|
-
paths.push(value);
|
|
44
|
-
index++;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
throw new Error(`Unknown index arguments: ${arg}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return indexCommandArgsSchema.parse({ json, paths });
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function buildIndexCliSuccess(input: {
|
|
54
|
-
readonly cwd: string;
|
|
55
|
-
readonly filesIndexed: number;
|
|
56
|
-
readonly nodesEmitted: number;
|
|
57
|
-
}): IndexCliResult {
|
|
58
|
-
return indexSuccessSchema.parse({
|
|
59
|
-
ok: true,
|
|
60
|
-
cwd: input.cwd,
|
|
61
|
-
filesIndexed: input.filesIndexed,
|
|
62
|
-
nodesEmitted: input.nodesEmitted,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function buildIndexCliFailure(input: {
|
|
67
|
-
readonly cwd: string;
|
|
68
|
-
readonly error: string;
|
|
69
|
-
}): IndexCliResult {
|
|
70
|
-
return indexFailureSchema.parse({
|
|
71
|
-
ok: false,
|
|
72
|
-
cwd: input.cwd,
|
|
73
|
-
error: input.error,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import { InitAction } from "./init-model.js";
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
ensureCodexStartupTimeout,
|
|
7
|
-
mergeClaudeHooksConfig,
|
|
8
|
-
mergeClaudeMcpConfig,
|
|
9
|
-
mergeClineMcpConfig,
|
|
10
|
-
mergeCodexMcpConfig,
|
|
11
|
-
mergeContinueMcpConfig,
|
|
12
|
-
mergeCursorMcpConfig,
|
|
13
|
-
mergeWindsurfMcpConfig,
|
|
14
|
-
} from "./init-client-config.js";
|
|
15
|
-
export { ensureTargetGitHooks } from "./init-target-hooks.js";
|
|
16
|
-
|
|
17
|
-
export function writeIfMissing(
|
|
18
|
-
filePath: string,
|
|
19
|
-
content: string,
|
|
20
|
-
label: string,
|
|
21
|
-
): InitAction {
|
|
22
|
-
if (fs.existsSync(filePath)) {
|
|
23
|
-
return InitAction.exists(label);
|
|
24
|
-
}
|
|
25
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
26
|
-
fs.writeFileSync(filePath, content);
|
|
27
|
-
return InitAction.create(label);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function appendIfMissing(
|
|
31
|
-
filePath: string,
|
|
32
|
-
marker: string,
|
|
33
|
-
content: string,
|
|
34
|
-
label: string,
|
|
35
|
-
): InitAction {
|
|
36
|
-
if (fs.existsSync(filePath)) {
|
|
37
|
-
const existing = fs.readFileSync(filePath, "utf-8");
|
|
38
|
-
if (existing.includes(marker)) {
|
|
39
|
-
return InitAction.exists(label, "already has graft entry");
|
|
40
|
-
}
|
|
41
|
-
fs.appendFileSync(filePath, content);
|
|
42
|
-
return InitAction.append(label);
|
|
43
|
-
}
|
|
44
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
45
|
-
fs.writeFileSync(filePath, content.trimStart());
|
|
46
|
-
return InitAction.create(label);
|
|
47
|
-
}
|
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
GRAFT_HOOKS_CONFIG,
|
|
5
|
-
GRAFT_MCP_SERVER,
|
|
6
|
-
GraftMcpServer,
|
|
7
|
-
InitAction,
|
|
8
|
-
isGraftMcpServerEntryForRuntime,
|
|
9
|
-
type GraftHookMatcher,
|
|
10
|
-
type JsonObjectValue,
|
|
11
|
-
type JsonValue,
|
|
12
|
-
} from "./init-model.js";
|
|
13
|
-
import {
|
|
14
|
-
JsonArrayNode,
|
|
15
|
-
JsonObjectDocument,
|
|
16
|
-
} from "./json-document.js";
|
|
17
|
-
|
|
18
|
-
class JsonMcpConfigDocument {
|
|
19
|
-
constructor(
|
|
20
|
-
private readonly document: JsonObjectDocument,
|
|
21
|
-
private readonly server: GraftMcpServer,
|
|
22
|
-
private readonly updateExisting: boolean,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
static create(
|
|
26
|
-
filePath: string,
|
|
27
|
-
label: string,
|
|
28
|
-
server: GraftMcpServer,
|
|
29
|
-
updateExisting: boolean,
|
|
30
|
-
): JsonMcpConfigDocument {
|
|
31
|
-
return new JsonMcpConfigDocument(
|
|
32
|
-
JsonObjectDocument.create(filePath, label, server.toJsonMcpConfig()),
|
|
33
|
-
server,
|
|
34
|
-
updateExisting,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
static open(
|
|
39
|
-
filePath: string,
|
|
40
|
-
label: string,
|
|
41
|
-
server: GraftMcpServer,
|
|
42
|
-
updateExisting: boolean,
|
|
43
|
-
): JsonMcpConfigDocument {
|
|
44
|
-
return new JsonMcpConfigDocument(
|
|
45
|
-
JsonObjectDocument.open(filePath, label),
|
|
46
|
-
server,
|
|
47
|
-
updateExisting,
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
write(): void {
|
|
52
|
-
this.document.write();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
ensureGraftServer(): InitAction {
|
|
56
|
-
const root = this.document.root();
|
|
57
|
-
const servers = root.ensureObject("mcpServers");
|
|
58
|
-
const existing = servers.toJsonValue()[this.server.name];
|
|
59
|
-
if (existing !== undefined) {
|
|
60
|
-
if (isGraftMcpServerEntryForRuntime(existing, this.server.runtime) || !this.updateExisting) {
|
|
61
|
-
return InitAction.exists(this.document.label, "already has graft mcp server");
|
|
62
|
-
}
|
|
63
|
-
servers.set(this.server.name, this.server.toJsonServerEntry());
|
|
64
|
-
this.document.write();
|
|
65
|
-
return InitAction.append(this.document.label, `updated graft mcp server runtime to ${this.server.runtime}`);
|
|
66
|
-
}
|
|
67
|
-
if (servers.has(this.server.name)) {
|
|
68
|
-
return InitAction.exists(this.document.label, "already has graft mcp server");
|
|
69
|
-
}
|
|
70
|
-
servers.set(this.server.name, this.server.toJsonServerEntry());
|
|
71
|
-
this.document.write();
|
|
72
|
-
return InitAction.append(this.document.label, "added graft mcp server");
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
class ContinueMcpConfigDocument {
|
|
77
|
-
constructor(
|
|
78
|
-
private readonly document: JsonObjectDocument,
|
|
79
|
-
private readonly server: GraftMcpServer,
|
|
80
|
-
private readonly updateExisting: boolean,
|
|
81
|
-
) {}
|
|
82
|
-
|
|
83
|
-
static create(
|
|
84
|
-
filePath: string,
|
|
85
|
-
label: string,
|
|
86
|
-
server: GraftMcpServer,
|
|
87
|
-
updateExisting: boolean,
|
|
88
|
-
): ContinueMcpConfigDocument {
|
|
89
|
-
return new ContinueMcpConfigDocument(
|
|
90
|
-
JsonObjectDocument.create(filePath, label, server.toContinueConfig()),
|
|
91
|
-
server,
|
|
92
|
-
updateExisting,
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
static open(
|
|
97
|
-
filePath: string,
|
|
98
|
-
label: string,
|
|
99
|
-
server: GraftMcpServer,
|
|
100
|
-
updateExisting: boolean,
|
|
101
|
-
): ContinueMcpConfigDocument {
|
|
102
|
-
return new ContinueMcpConfigDocument(
|
|
103
|
-
JsonObjectDocument.open(filePath, label),
|
|
104
|
-
server,
|
|
105
|
-
updateExisting,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
write(): void {
|
|
110
|
-
this.document.write();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
ensureGraftServer(): InitAction {
|
|
114
|
-
const root = this.document.root();
|
|
115
|
-
const servers = root.ensureArray("mcpServers");
|
|
116
|
-
const existingEntries = servers.objectEntries();
|
|
117
|
-
const existing = existingEntries
|
|
118
|
-
.find((entry) => entry.node.stringValue("name") === this.server.name);
|
|
119
|
-
if (existing !== undefined) {
|
|
120
|
-
if (isContinueServerEntryForRuntime(existing.node.toJsonValue(), this.server.runtime) || !this.updateExisting) {
|
|
121
|
-
return InitAction.exists(this.document.label, "already has graft mcp server");
|
|
122
|
-
}
|
|
123
|
-
servers.set(existing.index, this.server.toContinueServerEntry());
|
|
124
|
-
this.document.write();
|
|
125
|
-
return InitAction.append(this.document.label, `updated graft mcp server runtime to ${this.server.runtime}`);
|
|
126
|
-
}
|
|
127
|
-
servers.push(this.server.toContinueServerEntry());
|
|
128
|
-
this.document.write();
|
|
129
|
-
return InitAction.append(this.document.label, "added graft mcp server");
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
class ClaudeHooksDocument {
|
|
134
|
-
constructor(
|
|
135
|
-
private readonly document: JsonObjectDocument,
|
|
136
|
-
private readonly hooksConfig: typeof GRAFT_HOOKS_CONFIG,
|
|
137
|
-
) {}
|
|
138
|
-
|
|
139
|
-
static create(
|
|
140
|
-
filePath: string,
|
|
141
|
-
label: string,
|
|
142
|
-
hooksConfig: typeof GRAFT_HOOKS_CONFIG,
|
|
143
|
-
): ClaudeHooksDocument {
|
|
144
|
-
return new ClaudeHooksDocument(
|
|
145
|
-
JsonObjectDocument.create(filePath, label, hooksConfig.toJsonValue()),
|
|
146
|
-
hooksConfig,
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
static open(
|
|
151
|
-
filePath: string,
|
|
152
|
-
label: string,
|
|
153
|
-
hooksConfig: typeof GRAFT_HOOKS_CONFIG,
|
|
154
|
-
): ClaudeHooksDocument {
|
|
155
|
-
return new ClaudeHooksDocument(
|
|
156
|
-
JsonObjectDocument.open(filePath, label),
|
|
157
|
-
hooksConfig,
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
write(): void {
|
|
162
|
-
this.document.write();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
ensureGraftHooks(): InitAction {
|
|
166
|
-
const root = this.document.root();
|
|
167
|
-
const hooksRoot = root.ensureObject("hooks");
|
|
168
|
-
const preToolUse = hooksRoot.ensureArray("PreToolUse");
|
|
169
|
-
const postToolUse = hooksRoot.ensureArray("PostToolUse");
|
|
170
|
-
const changed = this.mergeHookPhase(preToolUse, this.hooksConfig.preToolUse)
|
|
171
|
-
|| this.mergeHookPhase(postToolUse, this.hooksConfig.postToolUse);
|
|
172
|
-
if (!changed) {
|
|
173
|
-
return InitAction.exists(this.document.label, "already has graft hooks");
|
|
174
|
-
}
|
|
175
|
-
this.document.write();
|
|
176
|
-
return InitAction.append(this.document.label, "added graft hooks");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
private mergeHookPhase(
|
|
180
|
-
phases: JsonArrayNode,
|
|
181
|
-
entry: GraftHookMatcher,
|
|
182
|
-
): boolean {
|
|
183
|
-
const existing = phases
|
|
184
|
-
.objectItems()
|
|
185
|
-
.find((candidate) => candidate.stringValue("matcher") === entry.matcher);
|
|
186
|
-
if (existing === undefined) {
|
|
187
|
-
phases.push(entry.toJsonValue());
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const hooks = existing.requireArray("hooks");
|
|
192
|
-
let changed = false;
|
|
193
|
-
for (const graftHook of entry.hooks) {
|
|
194
|
-
const alreadyPresent = hooks.objectItems().some((candidate) =>
|
|
195
|
-
candidate.stringValue("type") === "command"
|
|
196
|
-
&& candidate.stringValue("command") === graftHook.command,
|
|
197
|
-
);
|
|
198
|
-
if (alreadyPresent) {
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
hooks.push(graftHook.toJsonValue());
|
|
202
|
-
changed = true;
|
|
203
|
-
}
|
|
204
|
-
return changed;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export function ensureCodexStartupTimeout(
|
|
209
|
-
existing: string,
|
|
210
|
-
): { content: string; changed: boolean } {
|
|
211
|
-
const ensured = ensureCodexMcpServerBlock(existing, GRAFT_MCP_SERVER, false);
|
|
212
|
-
return { content: ensured.content, changed: ensured.changed };
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function codexBlockBounds(lines: readonly string[]): { start: number; end: number } | undefined {
|
|
216
|
-
const marker = "[mcp_servers.graft]";
|
|
217
|
-
const blockStart = lines.findIndex((line) => line.trim() === marker);
|
|
218
|
-
if (blockStart === -1) {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
let blockEnd = lines.length;
|
|
223
|
-
for (let index = blockStart + 1; index < lines.length; index++) {
|
|
224
|
-
const line = lines[index];
|
|
225
|
-
if (line !== undefined && line.trim().startsWith("[") && line.trim().endsWith("]")) {
|
|
226
|
-
blockEnd = index;
|
|
227
|
-
break;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return { start: blockStart, end: blockEnd };
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function replaceOrInsertLine(
|
|
235
|
-
lines: string[],
|
|
236
|
-
bounds: { readonly start: number; readonly end: number },
|
|
237
|
-
predicate: (line: string) => boolean,
|
|
238
|
-
value: string,
|
|
239
|
-
): { end: number; changed: boolean } {
|
|
240
|
-
const index = lines
|
|
241
|
-
.slice(bounds.start + 1, bounds.end)
|
|
242
|
-
.findIndex(predicate);
|
|
243
|
-
if (index === -1) {
|
|
244
|
-
lines.splice(bounds.end, 0, value);
|
|
245
|
-
return { end: bounds.end + 1, changed: true };
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const absoluteIndex = bounds.start + 1 + index;
|
|
249
|
-
if (lines[absoluteIndex] === value) {
|
|
250
|
-
return { end: bounds.end, changed: false };
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
lines[absoluteIndex] = value;
|
|
254
|
-
return { end: bounds.end, changed: true };
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export function ensureCodexMcpServerBlock(
|
|
258
|
-
existing: string,
|
|
259
|
-
server: GraftMcpServer,
|
|
260
|
-
updateExisting: boolean,
|
|
261
|
-
): { content: string; changed: boolean; detail?: string | undefined } {
|
|
262
|
-
const lines = existing.split("\n");
|
|
263
|
-
const bounds = codexBlockBounds(lines);
|
|
264
|
-
if (bounds === undefined) {
|
|
265
|
-
return { content: existing, changed: false };
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
let changed = false;
|
|
269
|
-
let runtimeChanged = false;
|
|
270
|
-
let blockEnd = bounds.end;
|
|
271
|
-
if (updateExisting) {
|
|
272
|
-
const command = replaceOrInsertLine(
|
|
273
|
-
lines,
|
|
274
|
-
{ start: bounds.start, end: blockEnd },
|
|
275
|
-
(line) => line.trim().startsWith("command"),
|
|
276
|
-
`command = "${server.command}"`,
|
|
277
|
-
);
|
|
278
|
-
runtimeChanged = command.changed;
|
|
279
|
-
changed = command.changed;
|
|
280
|
-
blockEnd = command.end;
|
|
281
|
-
|
|
282
|
-
const args = replaceOrInsertLine(
|
|
283
|
-
lines,
|
|
284
|
-
{ start: bounds.start, end: blockEnd },
|
|
285
|
-
(line) => line.trim().startsWith("args"),
|
|
286
|
-
server.toCodexTomlArgsLine(),
|
|
287
|
-
);
|
|
288
|
-
runtimeChanged = runtimeChanged || args.changed;
|
|
289
|
-
changed = changed || args.changed;
|
|
290
|
-
blockEnd = args.end;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const hasTimeout = lines
|
|
294
|
-
.slice(bounds.start + 1, blockEnd)
|
|
295
|
-
.some((line) => line.trim().startsWith("startup_timeout_sec"));
|
|
296
|
-
if (!hasTimeout) {
|
|
297
|
-
lines.splice(blockEnd, 0, `startup_timeout_sec = ${String(server.codexStartupTimeoutSec)}`);
|
|
298
|
-
changed = true;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return {
|
|
302
|
-
content: lines.join("\n"),
|
|
303
|
-
changed,
|
|
304
|
-
...(runtimeChanged ? { detail: `updated graft mcp server runtime to ${server.runtime}` } : {}),
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function isContinueServerEntryForRuntime(value: JsonObjectValue, runtime: GraftMcpServer["runtime"]): boolean {
|
|
309
|
-
const { name, ...entry } = value;
|
|
310
|
-
void name;
|
|
311
|
-
return isGraftMcpServerEntryForRuntime(entry as JsonValue, runtime);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
function ensureJsonMcpConfig(
|
|
315
|
-
filePath: string,
|
|
316
|
-
label: string,
|
|
317
|
-
server: GraftMcpServer,
|
|
318
|
-
updateExisting: boolean,
|
|
319
|
-
): InitAction {
|
|
320
|
-
if (!fs.existsSync(filePath)) {
|
|
321
|
-
const created = JsonMcpConfigDocument.create(filePath, label, server, updateExisting);
|
|
322
|
-
created.write();
|
|
323
|
-
return InitAction.create(label, "wrote graft mcp server");
|
|
324
|
-
}
|
|
325
|
-
return JsonMcpConfigDocument
|
|
326
|
-
.open(filePath, label, server, updateExisting)
|
|
327
|
-
.ensureGraftServer();
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
export function mergeClaudeMcpConfig(
|
|
331
|
-
cwd: string,
|
|
332
|
-
server = GRAFT_MCP_SERVER,
|
|
333
|
-
updateExisting = false,
|
|
334
|
-
): InitAction {
|
|
335
|
-
const label = ".mcp.json";
|
|
336
|
-
const filePath = path.join(cwd, label);
|
|
337
|
-
return ensureJsonMcpConfig(filePath, label, server, updateExisting);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export function mergeCursorMcpConfig(
|
|
341
|
-
cwd: string,
|
|
342
|
-
server = GRAFT_MCP_SERVER,
|
|
343
|
-
updateExisting = false,
|
|
344
|
-
): InitAction {
|
|
345
|
-
const label = ".cursor/mcp.json";
|
|
346
|
-
const filePath = path.join(cwd, ".cursor", "mcp.json");
|
|
347
|
-
return ensureJsonMcpConfig(filePath, label, server, updateExisting);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
export function mergeWindsurfMcpConfig(
|
|
351
|
-
cwd: string,
|
|
352
|
-
server = GRAFT_MCP_SERVER,
|
|
353
|
-
updateExisting = false,
|
|
354
|
-
): InitAction {
|
|
355
|
-
const label = ".codeium/windsurf/mcp_config.json";
|
|
356
|
-
const filePath = path.join(cwd, ".codeium", "windsurf", "mcp_config.json");
|
|
357
|
-
return ensureJsonMcpConfig(filePath, label, server, updateExisting);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
export function mergeClineMcpConfig(
|
|
361
|
-
cwd: string,
|
|
362
|
-
server = GRAFT_MCP_SERVER,
|
|
363
|
-
updateExisting = false,
|
|
364
|
-
): InitAction {
|
|
365
|
-
const label = ".vscode/cline_mcp_settings.json";
|
|
366
|
-
const filePath = path.join(cwd, ".vscode", "cline_mcp_settings.json");
|
|
367
|
-
return ensureJsonMcpConfig(filePath, label, server, updateExisting);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
export function mergeClaudeHooksConfig(cwd: string): InitAction {
|
|
371
|
-
const label = ".claude/settings.json";
|
|
372
|
-
const filePath = path.join(cwd, ".claude", "settings.json");
|
|
373
|
-
if (!fs.existsSync(filePath)) {
|
|
374
|
-
const created = ClaudeHooksDocument.create(filePath, label, GRAFT_HOOKS_CONFIG);
|
|
375
|
-
created.write();
|
|
376
|
-
return InitAction.create(label, "wrote graft hooks");
|
|
377
|
-
}
|
|
378
|
-
return ClaudeHooksDocument.open(filePath, label, GRAFT_HOOKS_CONFIG).ensureGraftHooks();
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
export function mergeContinueMcpConfig(
|
|
382
|
-
cwd: string,
|
|
383
|
-
server = GRAFT_MCP_SERVER,
|
|
384
|
-
updateExisting = false,
|
|
385
|
-
): InitAction {
|
|
386
|
-
const label = ".continue/config.json";
|
|
387
|
-
const filePath = path.join(cwd, ".continue", "config.json");
|
|
388
|
-
if (!fs.existsSync(filePath)) {
|
|
389
|
-
const created = ContinueMcpConfigDocument.create(filePath, label, server, updateExisting);
|
|
390
|
-
created.write();
|
|
391
|
-
return InitAction.create(label, "wrote graft mcp server");
|
|
392
|
-
}
|
|
393
|
-
return ContinueMcpConfigDocument
|
|
394
|
-
.open(filePath, label, server, updateExisting)
|
|
395
|
-
.ensureGraftServer();
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
export function mergeCodexMcpConfig(
|
|
399
|
-
cwd: string,
|
|
400
|
-
server = GRAFT_MCP_SERVER,
|
|
401
|
-
updateExisting = false,
|
|
402
|
-
): InitAction {
|
|
403
|
-
const label = ".codex/config.toml";
|
|
404
|
-
const filePath = path.join(cwd, ".codex", "config.toml");
|
|
405
|
-
const marker = "[mcp_servers.graft]";
|
|
406
|
-
if (!fs.existsSync(filePath)) {
|
|
407
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
408
|
-
fs.writeFileSync(filePath, server.toCodexTomlBlock());
|
|
409
|
-
return InitAction.create(label, "wrote graft mcp server");
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const existing = fs.readFileSync(filePath, "utf-8");
|
|
413
|
-
if (existing.includes(marker)) {
|
|
414
|
-
const ensured = ensureCodexMcpServerBlock(existing, server, updateExisting);
|
|
415
|
-
if (ensured.changed) {
|
|
416
|
-
fs.writeFileSync(filePath, ensured.content);
|
|
417
|
-
return InitAction.append(label, ensured.detail ?? "added graft startup timeout");
|
|
418
|
-
}
|
|
419
|
-
return InitAction.exists(label, "already has graft mcp server");
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
423
|
-
fs.writeFileSync(
|
|
424
|
-
filePath,
|
|
425
|
-
`${existing}${separator}${server.toCodexTomlBlock()}`,
|
|
426
|
-
);
|
|
427
|
-
return InitAction.append(label, "appended graft mcp server");
|
|
428
|
-
}
|