oh-my-opencode 5.0.0-beta.33 → 5.0.0-beta.35
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/.agents/skills/codex-qa/scripts/lsp-e2e.sh +1 -3
- package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +1 -1
- package/.agents/skills/tech-debt-audit/SKILL.md +6 -76
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.ru.md +1 -1
- package/README.zh-cn.md +1 -1
- package/THIRD-PARTY-NOTICES.md +27 -99
- package/dist/cli/index.js +48350 -48559
- package/dist/cli-node/index.js +48480 -48689
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schema/hooks.d.ts +0 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +0 -10
- package/dist/config/schema.d.ts +0 -1
- package/dist/create-hooks.d.ts +0 -1
- package/dist/hooks/index.d.ts +0 -1
- package/dist/index.js +11675 -13742
- package/dist/mcp/index.d.ts +0 -4
- package/dist/mcp/types.d.ts +0 -1
- package/dist/oh-my-opencode.schema.json +1 -45
- package/dist/plugin/hooks/create-core-hooks.d.ts +0 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +1 -2
- package/dist/shared/omo-process-sweep.d.ts +2 -4
- package/dist/skills/init-deep/SKILL.md +13 -13
- package/dist/skills/ulw-plan/SKILL.md +0 -1
- package/dist/tui.js +44809 -44910
- package/package.json +16 -18
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +0 -17
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -3
- package/packages/omo-codex/plugin/.mcp.json +0 -6
- package/packages/omo-codex/plugin/AGENTS.md +5 -5
- package/packages/omo-codex/plugin/README.md +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +1 -15
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +0 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +11 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +45 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +10 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +35 -38
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +278 -193
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +7 -51
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +39 -22
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +64 -8
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +37 -18
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +10 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +32 -63
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +7 -53
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +50 -31
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +67 -14
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +36 -17
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +26 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +47 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -146
- package/packages/omo-codex/plugin/package.json +1 -2
- package/packages/omo-codex/plugin/scripts/AGENTS.md +0 -1
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +0 -1
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
- package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
- package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +2 -8
- package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
- package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +13 -13
- package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +0 -1
- package/packages/omo-codex/plugin/test/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +2 -21
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -2
- package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +0 -25
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
- package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +0 -50
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +0 -1
- package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
- package/packages/omo-codex/scripts/install-cache-copy.test.mjs +27 -1
- package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +0 -23
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +238 -431
- package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +1 -25
- package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +0 -36
- package/packages/shared-skills/skills/init-deep/SKILL.md +13 -13
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +0 -1
- package/dist/config/schema/codegraph.d.ts +0 -12
- package/dist/hooks/codegraph-bootstrap/command-runner.d.ts +0 -17
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +0 -35
- package/dist/hooks/codegraph-bootstrap/index.d.ts +0 -1
- package/dist/hooks/codegraph-bootstrap/project-root.d.ts +0 -1
- package/dist/hooks/codegraph-bootstrap/status.d.ts +0 -11
- package/dist/mcp/codegraph.d.ts +0 -16
- package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
- package/packages/omo-codex/plugin/components/codegraph/LICENSE +0 -21
- package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
- package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12326
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9908
- package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
- package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -310
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -92
- package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -22
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
- package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
- package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
- package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
- package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
- package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
- package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +0 -47
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate.test.ts +0 -101
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
- package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
- package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { dirname, join, resolve } from "node:path";
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
-
|
|
8
|
-
const componentRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
9
|
-
|
|
10
|
-
describe("built CodeGraph serve wrappers", () => {
|
|
11
|
-
it("#given built serve entry #when invoked with a fake CodeGraph binary #then it runs serve mcp exactly once", () => {
|
|
12
|
-
// given
|
|
13
|
-
const tempRoot = createFakeCodegraphRoot();
|
|
14
|
-
try {
|
|
15
|
-
// when
|
|
16
|
-
const result = runBuiltWrapper("dist/serve.js", tempRoot);
|
|
17
|
-
|
|
18
|
-
// then
|
|
19
|
-
expect(result.status).toBe(0);
|
|
20
|
-
expect(result.stderr).toBe("");
|
|
21
|
-
expect(readInvocations(tempRoot)).toEqual(['["serve","--mcp"]']);
|
|
22
|
-
} finally {
|
|
23
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("#given built cli entry #when invoked with a fake CodeGraph binary #then it runs serve mcp exactly once", () => {
|
|
28
|
-
// given
|
|
29
|
-
const tempRoot = createFakeCodegraphRoot();
|
|
30
|
-
try {
|
|
31
|
-
// when
|
|
32
|
-
const result = runBuiltWrapper("dist/cli.js", tempRoot);
|
|
33
|
-
|
|
34
|
-
// then
|
|
35
|
-
expect(result.status).toBe(0);
|
|
36
|
-
expect(result.stderr).toBe("");
|
|
37
|
-
expect(readInvocations(tempRoot)).toEqual(['["serve","--mcp"]']);
|
|
38
|
-
} finally {
|
|
39
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
function createFakeCodegraphRoot(): string {
|
|
45
|
-
const tempRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-wrapper-"));
|
|
46
|
-
const fakeBinaryPath = join(tempRoot, "codegraph-fake.cjs");
|
|
47
|
-
writeFileSync(
|
|
48
|
-
fakeBinaryPath,
|
|
49
|
-
[
|
|
50
|
-
"#!/usr/bin/env node",
|
|
51
|
-
"const fs = require('node:fs');",
|
|
52
|
-
"fs.appendFileSync(process.env.CODEGRAPH_FAKE_LOG, JSON.stringify(process.argv.slice(2)) + '\\n');",
|
|
53
|
-
"",
|
|
54
|
-
].join("\n"),
|
|
55
|
-
);
|
|
56
|
-
chmodSync(fakeBinaryPath, 0o755);
|
|
57
|
-
return tempRoot;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function runBuiltWrapper(entryPath: string, tempRoot: string): ReturnType<typeof spawnSync> {
|
|
61
|
-
return spawnSync(process.execPath, [join(componentRoot, entryPath)], {
|
|
62
|
-
cwd: componentRoot,
|
|
63
|
-
encoding: "utf8",
|
|
64
|
-
env: {
|
|
65
|
-
...process.env,
|
|
66
|
-
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
67
|
-
CODEGRAPH_FAKE_LOG: join(tempRoot, "invocations.log"),
|
|
68
|
-
OMO_CODEGRAPH_BIN: join(tempRoot, "codegraph-fake.cjs"),
|
|
69
|
-
},
|
|
70
|
-
timeout: 5000,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function readInvocations(tempRoot: string): readonly string[] {
|
|
75
|
-
return readFileSync(join(tempRoot, "invocations.log"), "utf8").trim().split("\n");
|
|
76
|
-
}
|
package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { PassThrough, Writable } from "node:stream";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
|
|
7
|
-
import { isProcessAlive } from "../../../../../mcp-stdio-core/src/index.ts";
|
|
8
|
-
import { runCodegraphServe } from "../src/serve.ts";
|
|
9
|
-
import {
|
|
10
|
-
frameMcpRequest,
|
|
11
|
-
writeFakeExitingCodegraph,
|
|
12
|
-
writeFakeHeldOpenCodegraph,
|
|
13
|
-
} from "./mcp-bridge-fixtures.ts";
|
|
14
|
-
|
|
15
|
-
const componentRoot = realpathSync(
|
|
16
|
-
fileURLToPath(new URL("..", import.meta.url)),
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
describe("runCodegraphServe MCP bridge lifecycle", () => {
|
|
20
|
-
it("#given an exiting Codegraph child and delayed closed parent output #when the final response write fails #then the output error is preserved", async () => {
|
|
21
|
-
const tempRoot = mkdtempSync(
|
|
22
|
-
join(componentRoot, ".tmp-codegraph-exit-output-failure-"),
|
|
23
|
-
);
|
|
24
|
-
const projectRoot = join(tempRoot, "project");
|
|
25
|
-
const fakeCodegraph = join(tempRoot, "codegraph-exiting.cjs");
|
|
26
|
-
const input = new PassThrough();
|
|
27
|
-
const outputError = Object.assign(
|
|
28
|
-
new Error("parent output closed after child exit"),
|
|
29
|
-
{ code: "EPIPE" },
|
|
30
|
-
);
|
|
31
|
-
const writeStarted = Promise.withResolvers<void>();
|
|
32
|
-
const output = new Writable({
|
|
33
|
-
write(_chunk, _encoding, callback) {
|
|
34
|
-
writeStarted.resolve();
|
|
35
|
-
setTimeout(() => callback(outputError), 150);
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
mkdirSync(projectRoot, { recursive: true });
|
|
41
|
-
writeFakeExitingCodegraph(fakeCodegraph);
|
|
42
|
-
const run = runCodegraphServe({
|
|
43
|
-
cwd: tempRoot,
|
|
44
|
-
env: {
|
|
45
|
-
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
46
|
-
OMO_CODEGRAPH_BIN: fakeCodegraph,
|
|
47
|
-
OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
|
|
48
|
-
PATH: process.env["PATH"],
|
|
49
|
-
},
|
|
50
|
-
nodeVersion: "22.14.0",
|
|
51
|
-
buildEnv: () => ({}),
|
|
52
|
-
resolve: () => ({
|
|
53
|
-
argsPrefix: [],
|
|
54
|
-
command: fakeCodegraph,
|
|
55
|
-
exists: true,
|
|
56
|
-
source: "env",
|
|
57
|
-
}),
|
|
58
|
-
stderr: { write: () => undefined },
|
|
59
|
-
stdin: input,
|
|
60
|
-
stdout: output,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
input.end(frameMcpRequest({ id: 1, method: "tools/list", params: {} }));
|
|
64
|
-
|
|
65
|
-
await writeStarted.promise;
|
|
66
|
-
await expect(run).rejects.toBe(outputError);
|
|
67
|
-
} finally {
|
|
68
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("#given a held-open Codegraph child and a dead parent #when the bridge watchdog polls #then the child is terminated and the bridge settles through the child-exit path", async () => {
|
|
73
|
-
// given
|
|
74
|
-
const tempRoot = mkdtempSync(
|
|
75
|
-
join(componentRoot, ".tmp-codegraph-orphan-"),
|
|
76
|
-
);
|
|
77
|
-
const projectRoot = join(tempRoot, "project");
|
|
78
|
-
const fakeCodegraph = join(tempRoot, "codegraph-held-open.cjs");
|
|
79
|
-
const childPidFile = join(tempRoot, "child.pid");
|
|
80
|
-
// Client stdio is held open and never sees EOF, so the parent-liveness
|
|
81
|
-
// watchdog is the only settle path. The probe reports the parent alive
|
|
82
|
-
// until the child has started, making the poll fire deterministically.
|
|
83
|
-
const input = new PassThrough();
|
|
84
|
-
const output = new PassThrough();
|
|
85
|
-
output.resume();
|
|
86
|
-
let childPid: number | undefined;
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
mkdirSync(projectRoot, { recursive: true });
|
|
90
|
-
writeFakeHeldOpenCodegraph(fakeCodegraph);
|
|
91
|
-
const run = runCodegraphServe({
|
|
92
|
-
cwd: tempRoot,
|
|
93
|
-
env: {
|
|
94
|
-
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
95
|
-
CODEGRAPH_FAKE_LOG: childPidFile,
|
|
96
|
-
OMO_CODEGRAPH_BIN: fakeCodegraph,
|
|
97
|
-
OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
|
|
98
|
-
PATH: process.env["PATH"],
|
|
99
|
-
},
|
|
100
|
-
nodeVersion: "22.14.0",
|
|
101
|
-
buildEnv: () => ({}),
|
|
102
|
-
resolve: () => ({
|
|
103
|
-
argsPrefix: [],
|
|
104
|
-
command: fakeCodegraph,
|
|
105
|
-
exists: true,
|
|
106
|
-
source: "env",
|
|
107
|
-
}),
|
|
108
|
-
stderr: { write: () => undefined },
|
|
109
|
-
stdin: input,
|
|
110
|
-
stdout: output,
|
|
111
|
-
parentWatchdog: {
|
|
112
|
-
pollIntervalMs: 10,
|
|
113
|
-
probeAlive: () => !existsSync(childPidFile),
|
|
114
|
-
},
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
// when
|
|
118
|
-
const exitCode = await run;
|
|
119
|
-
|
|
120
|
-
// then
|
|
121
|
-
expect(exitCode).not.toBe(0);
|
|
122
|
-
childPid = Number(readFileSync(childPidFile, "utf8"));
|
|
123
|
-
expect(isProcessAlive(childPid)).toBe(false);
|
|
124
|
-
} finally {
|
|
125
|
-
if (childPid !== undefined && isProcessAlive(childPid)) {
|
|
126
|
-
process.kill(childPid, "SIGKILL");
|
|
127
|
-
}
|
|
128
|
-
input.destroy();
|
|
129
|
-
output.destroy();
|
|
130
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
});
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { PassThrough, Writable } from "node:stream";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
|
|
7
|
-
import { runCodegraphServe } from "../src/serve.ts";
|
|
8
|
-
import {
|
|
9
|
-
arrayProperty,
|
|
10
|
-
CODEGRAPH_150_DEFAULT_TOOLS,
|
|
11
|
-
findTool,
|
|
12
|
-
frameMcpRequest,
|
|
13
|
-
parseMcpBodies,
|
|
14
|
-
recordProperty,
|
|
15
|
-
recordValue,
|
|
16
|
-
stringProperty,
|
|
17
|
-
writeFakeContractCodegraph,
|
|
18
|
-
writeFakeHeldOpenCodegraph,
|
|
19
|
-
writeFakeNewlineCodegraph,
|
|
20
|
-
} from "./mcp-bridge-fixtures.ts";
|
|
21
|
-
|
|
22
|
-
const componentRoot = realpathSync(fileURLToPath(new URL("..", import.meta.url)));
|
|
23
|
-
|
|
24
|
-
describe("runCodegraphServe MCP protocol bridge", () => {
|
|
25
|
-
it("#given Codex framed stdio and a newline-json CodeGraph child #when listing tools #then it bridges frames and serves from the project cwd", async () => {
|
|
26
|
-
// given
|
|
27
|
-
const tempRoot = mkdtempSync(join(componentRoot, ".tmp-codegraph-bridge-"));
|
|
28
|
-
const projectRoot = join(tempRoot, "project");
|
|
29
|
-
const pluginCacheRoot = join(tempRoot, "plugin-cache");
|
|
30
|
-
const fakeCodegraph = join(tempRoot, "codegraph-fake.cjs");
|
|
31
|
-
const childLog = join(tempRoot, "child.log");
|
|
32
|
-
const input = new PassThrough();
|
|
33
|
-
const output = new PassThrough();
|
|
34
|
-
let stdout = "";
|
|
35
|
-
output.on("data", (chunk: Buffer) => {
|
|
36
|
-
stdout += chunk.toString("utf8");
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
mkdirSync(projectRoot, { recursive: true });
|
|
41
|
-
mkdirSync(pluginCacheRoot, { recursive: true });
|
|
42
|
-
writeFakeNewlineCodegraph(fakeCodegraph);
|
|
43
|
-
|
|
44
|
-
const run = runCodegraphServe({
|
|
45
|
-
cwd: pluginCacheRoot,
|
|
46
|
-
env: {
|
|
47
|
-
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
48
|
-
CODEGRAPH_FAKE_LOG: childLog,
|
|
49
|
-
OMO_CODEGRAPH_BIN: fakeCodegraph,
|
|
50
|
-
OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
|
|
51
|
-
PATH: process.env["PATH"],
|
|
52
|
-
},
|
|
53
|
-
nodeVersion: "22.14.0",
|
|
54
|
-
buildEnv: () => ({}),
|
|
55
|
-
resolve: () => ({ argsPrefix: [], command: fakeCodegraph, exists: true, source: "env" }),
|
|
56
|
-
stderr: { write: () => undefined },
|
|
57
|
-
stdin: input,
|
|
58
|
-
stdout: output,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// when
|
|
62
|
-
input.end([
|
|
63
|
-
frameMcpRequest({
|
|
64
|
-
id: 1,
|
|
65
|
-
method: "initialize",
|
|
66
|
-
params: {
|
|
67
|
-
capabilities: {},
|
|
68
|
-
clientInfo: { name: "codex", version: "0.141.0" },
|
|
69
|
-
protocolVersion: "2025-06-18",
|
|
70
|
-
},
|
|
71
|
-
}),
|
|
72
|
-
frameMcpRequest({
|
|
73
|
-
id: 2,
|
|
74
|
-
method: "tools/list",
|
|
75
|
-
params: {},
|
|
76
|
-
}),
|
|
77
|
-
].join(""));
|
|
78
|
-
const exitCode = await run;
|
|
79
|
-
|
|
80
|
-
// then
|
|
81
|
-
expect(exitCode).toBe(0);
|
|
82
|
-
const bodies = parseMcpBodies(stdout);
|
|
83
|
-
expect(bodies).toEqual([
|
|
84
|
-
{
|
|
85
|
-
id: 1,
|
|
86
|
-
jsonrpc: "2.0",
|
|
87
|
-
result: {
|
|
88
|
-
capabilities: { tools: { listChanged: false } },
|
|
89
|
-
protocolVersion: "2025-06-18",
|
|
90
|
-
serverInfo: { name: "codegraph", version: "1.5.0" },
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
id: 2,
|
|
95
|
-
jsonrpc: "2.0",
|
|
96
|
-
result: {
|
|
97
|
-
tools: CODEGRAPH_150_DEFAULT_TOOLS,
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
]);
|
|
101
|
-
expect(readFileSync(childLog, "utf8")).toContain(`cwd=${realpathSync(projectRoot)}`);
|
|
102
|
-
} finally {
|
|
103
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it("#given old upstream codegraph_node metadata and container outline guidance #when bridging #then it exposes the corrected LazyCodex contract", async () => {
|
|
108
|
-
// given
|
|
109
|
-
const tempRoot = mkdtempSync(join(componentRoot, ".tmp-codegraph-contract-"));
|
|
110
|
-
const projectRoot = join(tempRoot, "project");
|
|
111
|
-
const fakeCodegraph = join(tempRoot, "codegraph-contract-fake.cjs");
|
|
112
|
-
const childLog = join(tempRoot, "child.log");
|
|
113
|
-
const input = new PassThrough();
|
|
114
|
-
const output = new PassThrough();
|
|
115
|
-
let stdout = "";
|
|
116
|
-
output.on("data", (chunk: Buffer) => {
|
|
117
|
-
stdout += chunk.toString("utf8");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
mkdirSync(projectRoot, { recursive: true });
|
|
122
|
-
writeFakeContractCodegraph(fakeCodegraph);
|
|
123
|
-
|
|
124
|
-
const run = runCodegraphServe({
|
|
125
|
-
cwd: tempRoot,
|
|
126
|
-
env: {
|
|
127
|
-
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
128
|
-
CODEGRAPH_FAKE_LOG: childLog,
|
|
129
|
-
OMO_CODEGRAPH_BIN: fakeCodegraph,
|
|
130
|
-
OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
|
|
131
|
-
PATH: process.env["PATH"],
|
|
132
|
-
},
|
|
133
|
-
nodeVersion: "22.14.0",
|
|
134
|
-
buildEnv: () => ({}),
|
|
135
|
-
resolve: () => ({ argsPrefix: [], command: fakeCodegraph, exists: true, source: "env" }),
|
|
136
|
-
stderr: { write: () => undefined },
|
|
137
|
-
stdin: input,
|
|
138
|
-
stdout: output,
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
// when
|
|
142
|
-
input.end([
|
|
143
|
-
frameMcpRequest({
|
|
144
|
-
id: 1,
|
|
145
|
-
method: "tools/list",
|
|
146
|
-
params: {},
|
|
147
|
-
}),
|
|
148
|
-
frameMcpRequest({
|
|
149
|
-
id: 2,
|
|
150
|
-
method: "tools/call",
|
|
151
|
-
params: {
|
|
152
|
-
arguments: { includeCode: true, symbol: "JsonlMCP" },
|
|
153
|
-
name: "codegraph_node",
|
|
154
|
-
},
|
|
155
|
-
}),
|
|
156
|
-
].join(""));
|
|
157
|
-
const exitCode = await run;
|
|
158
|
-
|
|
159
|
-
// then
|
|
160
|
-
expect(exitCode).toBe(0);
|
|
161
|
-
const bodies = parseMcpBodies(stdout);
|
|
162
|
-
const tools = arrayProperty(recordProperty(recordValue(bodies[0]), "result"), "tools");
|
|
163
|
-
const nodeTool = findTool(tools, "codegraph_node");
|
|
164
|
-
const searchTool = findTool(tools, "codegraph_search");
|
|
165
|
-
expect(stringProperty(nodeTool, "description")).toContain("Container symbols");
|
|
166
|
-
expect(stringProperty(nodeTool, "description")).toContain("file mode");
|
|
167
|
-
expect(stringProperty(nodeTool, "description")).not.toContain("verbatim source");
|
|
168
|
-
expect(stringProperty(nodeTool, "description")).not.toContain("full body");
|
|
169
|
-
expect(
|
|
170
|
-
stringProperty(
|
|
171
|
-
recordProperty(recordProperty(recordProperty(nodeTool, "inputSchema"), "properties"), "includeCode"),
|
|
172
|
-
"description",
|
|
173
|
-
),
|
|
174
|
-
).toBe(
|
|
175
|
-
"Symbol mode: include leaf-symbol source when available. Container symbols such as classes, interfaces, structs, enums, modules, and namespaces intentionally return structural outlines with members; request a specific member symbol or use file mode with symbolsOnly=false plus offset/limit for source.",
|
|
176
|
-
);
|
|
177
|
-
expect(searchTool).toEqual({ description: "search stays unchanged", name: "codegraph_search" });
|
|
178
|
-
|
|
179
|
-
const callResult = recordProperty(recordValue(bodies[1]), "result");
|
|
180
|
-
const text = stringProperty(recordValue(arrayProperty(callResult, "content")[0]), "text");
|
|
181
|
-
expect(text).toContain("Container symbols intentionally return structural outlines");
|
|
182
|
-
expect(text).toContain("specific member symbol");
|
|
183
|
-
expect(text).toContain("file mode");
|
|
184
|
-
expect(text).toContain("symbolsOnly=false");
|
|
185
|
-
expect(text).not.toContain("Read tool");
|
|
186
|
-
} finally {
|
|
187
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
it("#given a held-open Codegraph child and closed parent output #when response forwarding fails #then the child is terminated before rejection", async () => {
|
|
192
|
-
const tempRoot = mkdtempSync(join(componentRoot, ".tmp-codegraph-output-failure-"));
|
|
193
|
-
const projectRoot = join(tempRoot, "project");
|
|
194
|
-
const fakeCodegraph = join(tempRoot, "codegraph-held-open.cjs");
|
|
195
|
-
const childPidFile = join(tempRoot, "child.pid");
|
|
196
|
-
const input = new PassThrough();
|
|
197
|
-
const outputError = Object.assign(new Error("parent output closed"), { code: "EPIPE" });
|
|
198
|
-
const output = new Writable({
|
|
199
|
-
write(_chunk, _encoding, callback) {
|
|
200
|
-
callback(outputError);
|
|
201
|
-
},
|
|
202
|
-
});
|
|
203
|
-
let childPid: number | undefined;
|
|
204
|
-
|
|
205
|
-
try {
|
|
206
|
-
mkdirSync(projectRoot, { recursive: true });
|
|
207
|
-
writeFakeHeldOpenCodegraph(fakeCodegraph);
|
|
208
|
-
const run = runCodegraphServe({
|
|
209
|
-
cwd: tempRoot,
|
|
210
|
-
env: {
|
|
211
|
-
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
212
|
-
CODEGRAPH_FAKE_LOG: childPidFile,
|
|
213
|
-
OMO_CODEGRAPH_BIN: fakeCodegraph,
|
|
214
|
-
OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
|
|
215
|
-
PATH: process.env["PATH"],
|
|
216
|
-
},
|
|
217
|
-
nodeVersion: "22.14.0",
|
|
218
|
-
buildEnv: () => ({}),
|
|
219
|
-
resolve: () => ({ argsPrefix: [], command: fakeCodegraph, exists: true, source: "env" }),
|
|
220
|
-
stderr: { write: () => undefined },
|
|
221
|
-
stdin: input,
|
|
222
|
-
stdout: output,
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
input.end(frameMcpRequest({ id: 1, method: "tools/list", params: {} }));
|
|
226
|
-
|
|
227
|
-
await expect(run).rejects.toBe(outputError);
|
|
228
|
-
childPid = Number(readFileSync(childPidFile, "utf8"));
|
|
229
|
-
expect(isProcessAlive(childPid)).toBe(false);
|
|
230
|
-
} finally {
|
|
231
|
-
if (childPid !== undefined && isProcessAlive(childPid)) process.kill(childPid, "SIGKILL");
|
|
232
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
function isProcessAlive(pid: number): boolean {
|
|
238
|
-
try {
|
|
239
|
-
process.kill(pid, 0);
|
|
240
|
-
return true;
|
|
241
|
-
} catch (error) {
|
|
242
|
-
if (error instanceof Error && "code" in error && error.code === "ESRCH") return false;
|
|
243
|
-
throw error;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { PassThrough } from "node:stream";
|
|
3
|
-
|
|
4
|
-
import { runCodegraphServe } from "../src/serve.ts";
|
|
5
|
-
|
|
6
|
-
describe("runCodegraphServe MCP unavailable facade", () => {
|
|
7
|
-
it("#given CodeGraph is unavailable #when an MCP client initializes #then it answers with an empty-tool facade", async () => {
|
|
8
|
-
// given
|
|
9
|
-
const input = new PassThrough();
|
|
10
|
-
const output = new PassThrough();
|
|
11
|
-
const stderr: string[] = [];
|
|
12
|
-
let stdout = "";
|
|
13
|
-
output.on("data", (chunk: Buffer) => {
|
|
14
|
-
stdout += chunk.toString("utf8");
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const run = runCodegraphServe({
|
|
18
|
-
config: { codegraph: { auto_provision: false, enabled: true }, sources: [], warnings: [] },
|
|
19
|
-
env: { PATH: "/bin" },
|
|
20
|
-
nodeVersion: "22.14.0",
|
|
21
|
-
buildEnv: () => ({}),
|
|
22
|
-
resolve: () => ({ argsPrefix: [], command: "codegraph", exists: false, source: "path" }),
|
|
23
|
-
stderr: { write: (chunk: string) => stderr.push(chunk) },
|
|
24
|
-
stdin: input,
|
|
25
|
-
stdout: output,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// when
|
|
29
|
-
input.end(frameMcpRequest({
|
|
30
|
-
id: 1,
|
|
31
|
-
method: "initialize",
|
|
32
|
-
params: {
|
|
33
|
-
capabilities: {},
|
|
34
|
-
clientInfo: { name: "ulw-red", version: "0.0.0" },
|
|
35
|
-
protocolVersion: "2025-06-18",
|
|
36
|
-
},
|
|
37
|
-
}));
|
|
38
|
-
const exitCode = await run;
|
|
39
|
-
|
|
40
|
-
// then
|
|
41
|
-
expect(exitCode).toBe(0);
|
|
42
|
-
expect(stderr).toEqual([
|
|
43
|
-
"CodeGraph MCP skipped: codegraph binary not found. Install CodeGraph or set OMO_CODEGRAPH_BIN.\n",
|
|
44
|
-
]);
|
|
45
|
-
expect(parseFirstJsonRpcBody(stdout)).toEqual({
|
|
46
|
-
id: 1,
|
|
47
|
-
jsonrpc: "2.0",
|
|
48
|
-
result: {
|
|
49
|
-
capabilities: { tools: { listChanged: false } },
|
|
50
|
-
protocolVersion: "2025-06-18",
|
|
51
|
-
serverInfo: { name: "codegraph", version: "1.5.0" },
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
function frameMcpRequest(request: {
|
|
58
|
-
readonly id: number;
|
|
59
|
-
readonly method: string;
|
|
60
|
-
readonly params: Record<string, unknown>;
|
|
61
|
-
}): string {
|
|
62
|
-
const body = JSON.stringify({ jsonrpc: "2.0", ...request });
|
|
63
|
-
return `Content-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function parseFirstJsonRpcBody(transcript: string): unknown {
|
|
67
|
-
const [, body = ""] = transcript.split("\r\n\r\n", 2);
|
|
68
|
-
return JSON.parse(body);
|
|
69
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { PassThrough } from "node:stream";
|
|
3
|
-
|
|
4
|
-
import { CODEGRAPH_UNSAFE_NODE_ENV } from "../../../../../utils/src/codegraph/node-support.ts";
|
|
5
|
-
import { runCodegraphServe } from "../src/serve.ts";
|
|
6
|
-
|
|
7
|
-
describe("runCodegraphServe node support", () => {
|
|
8
|
-
it("#given Node is too new and no command resolves #when serving MCP #then the unsupported-node hint wins", async () => {
|
|
9
|
-
// given
|
|
10
|
-
const stderr: string[] = [];
|
|
11
|
-
const spawned: string[] = [];
|
|
12
|
-
|
|
13
|
-
// when
|
|
14
|
-
const exitCode = await runCodegraphServe({
|
|
15
|
-
...closedMcpStdio(),
|
|
16
|
-
env: { PATH: "/bin" },
|
|
17
|
-
nodeVersion: "26.3.0",
|
|
18
|
-
buildEnv: () => ({}),
|
|
19
|
-
resolve: () => ({ argsPrefix: [], command: "codegraph", exists: false, source: "path" }),
|
|
20
|
-
runProcess: (command: string) => {
|
|
21
|
-
spawned.push(command);
|
|
22
|
-
return Promise.resolve(0);
|
|
23
|
-
},
|
|
24
|
-
stderr: { write: (chunk: string) => stderr.push(chunk) },
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// then
|
|
28
|
-
expect(exitCode).toBe(0);
|
|
29
|
-
expect(spawned).toEqual([]);
|
|
30
|
-
expect(stderr).toHaveLength(1);
|
|
31
|
-
expect(stderr[0]).toContain("CodeGraph MCP skipped");
|
|
32
|
-
expect(stderr[0]).toContain("Node 26 is unsupported");
|
|
33
|
-
expect(stderr[0]).toContain(CODEGRAPH_UNSAFE_NODE_ENV);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
function closedMcpStdio(): { readonly stdin: PassThrough; readonly stdout: PassThrough } {
|
|
38
|
-
const stdin = new PassThrough();
|
|
39
|
-
const stdout = new PassThrough();
|
|
40
|
-
stdout.resume();
|
|
41
|
-
stdin.end();
|
|
42
|
-
return { stdin, stdout };
|
|
43
|
-
}
|