oh-my-opencode 4.19.2 → 4.19.3
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/command/publish.md +95 -28
- package/.agents/skills/publish/SKILL.md +20 -6
- package/.opencode/command/publish.md +95 -28
- package/THIRD-PARTY-NOTICES.md +7 -7
- package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +1 -1
- package/dist/cli/config-migrate.d.ts +8 -0
- package/dist/cli/doctor/checks/legacy-config-leftovers.d.ts +10 -0
- package/dist/cli/doctor/checks/model-resolution-config.d.ts +1 -1
- package/dist/cli/doctor/checks/tools-lsp.d.ts +1 -1
- package/dist/cli/doctor/framework/constants.d.ts +1 -1
- package/dist/cli/index.js +95557 -92944
- package/dist/cli-node/index.js +95539 -92926
- package/dist/config/validate.d.ts +2 -1
- package/dist/config-migration/deep-diff.d.ts +1 -0
- package/dist/config-migration/discovery-paths.d.ts +11 -0
- package/dist/config-migration/discovery-roots.d.ts +7 -0
- package/dist/config-migration/discovery.d.ts +4 -0
- package/dist/config-migration/index.d.ts +9 -0
- package/dist/config-migration/legacy-history.d.ts +3 -0
- package/dist/config-migration/migration-executor.d.ts +4 -0
- package/dist/config-migration/migration-plans.d.ts +14 -0
- package/dist/config-migration/record-values.d.ts +4 -0
- package/dist/config-migration/schema-url.d.ts +1 -0
- package/dist/config-migration/transform-config-jsonc.d.ts +2 -0
- package/dist/config-migration/transform-opencode.d.ts +2 -0
- package/dist/config-migration/transform-types.d.ts +24 -0
- package/dist/config-migration/types.d.ts +39 -0
- package/dist/features/builtin-commands/templates/hyperplan.d.ts +1 -1
- package/dist/hooks/auto-update-checker/constants.d.ts +3 -3
- package/dist/index.js +10424 -8161
- package/dist/plugin-config/omo-config-chain.d.ts +14 -0
- package/dist/plugin-config/unknown-key-diagnostics.d.ts +5 -0
- package/dist/plugin-config.d.ts +2 -2
- package/dist/shared/agent-display-names.d.ts +1 -1
- package/dist/shared/jsonc-parser.d.ts +1 -1
- package/dist/shared/migration.d.ts +5 -1
- package/dist/shared/opencode-config-dir-types.d.ts +0 -1
- package/dist/shared/plugin-identity.d.ts +6 -8
- package/dist/shared/project-discovery-dirs.d.ts +0 -1
- package/dist/skills/frontend/ATTRIBUTION.md +7 -0
- package/dist/skills/frontend/SKILL.md +4 -1
- package/dist/skills/frontend/references/design/README.md +8 -0
- package/dist/skills/frontend/references/design/_INDEX.md +14 -1
- package/dist/skills/frontend/references/design/interaction-skill.md +144 -0
- package/dist/startup-migration.d.ts +28 -0
- package/dist/testing/create-plugin-module.d.ts +4 -0
- package/dist/tui.js +5356 -4643
- package/package.json +13 -13
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +19 -3
- package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +11 -2
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +2 -2
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- 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/codegraph/AGENTS.md +11 -5
- package/packages/omo-codex/plugin/components/codegraph/NOTICE +1 -1
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +10153 -2571
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +7311 -572
- package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
- package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +33 -0
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +36 -10
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +164 -159
- package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +34 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +20 -2
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +106 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +145 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +21 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +139 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +15 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +32 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +109 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +148 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +126 -175
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +4 -4
- package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +160 -0
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +12 -138
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +28 -24
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +3 -3
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +2 -2
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +5 -5
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -3
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +45 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +2 -2
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +70 -13
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +58 -0
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +104 -0
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +4 -2
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +116 -0
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +58 -57
- 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/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/dist/cli.js +31 -14
- 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/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/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/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- 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/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/SKILL.md +17 -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-codegraph-init-guidance.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-checking-codegraph-bootstrap.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-start-work-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-start-work-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 +42 -41
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/shared/src/config-loader.ts +165 -16
- package/packages/omo-codex/plugin/shared/src/config-migration.ts +162 -0
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +186 -9
- package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +7 -0
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +4 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +8 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +14 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/interaction-skill.md +144 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +17 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +1 -1
- package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +7 -0
- package/packages/shared-skills/skills/frontend/SKILL.md +4 -1
- package/packages/shared-skills/skills/frontend/references/design/README.md +8 -0
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +14 -1
- package/packages/shared-skills/skills/frontend/references/design/interaction-skill.md +144 -0
- package/dist/plugin-config/layered-config-loader.d.ts +0 -2
- package/dist/plugin-config/single-config-loader.d.ts +0 -4
- package/dist/shared/migrate-legacy-config-file.d.ts +0 -1
- package/dist/shared/migration/config-migration.d.ts +0 -1
package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
|
|
6
6
|
import { runCodegraphSessionStartWorker } from "../src/hook.ts";
|
|
7
7
|
|
|
8
|
+
function writeProjectDatabase(workspace: string): void {
|
|
9
|
+
mkdirSync(join(workspace, ".codegraph"), { recursive: true });
|
|
10
|
+
writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
describe("CodeGraph SessionStart worker Node support", () => {
|
|
9
14
|
it("#given an unsupported local Node and a PATH CodeGraph command with auto provisioning disabled #when worker runs #then it skips without touching the workspace", async () => {
|
|
10
15
|
// given
|
|
@@ -52,7 +57,7 @@ describe("CodeGraph SessionStart worker Node support", () => {
|
|
|
52
57
|
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-node-provision-home-"));
|
|
53
58
|
const binPath = join(homeDir, ".omo", "codegraph", "bin", "codegraph");
|
|
54
59
|
const calls: Array<{ readonly args: readonly string[]; readonly command: string }> = [];
|
|
55
|
-
const provisionCalls: Array<{ readonly installDir?: string; readonly lockDir: string; readonly version: "1.
|
|
60
|
+
const provisionCalls: Array<{ readonly installDir?: string; readonly lockDir: string; readonly version: "1.5.0" }> = [];
|
|
56
61
|
const outcomes: unknown[] = [];
|
|
57
62
|
|
|
58
63
|
try {
|
|
@@ -78,19 +83,17 @@ describe("CodeGraph SessionStart worker Node support", () => {
|
|
|
78
83
|
resolveCommand: () => ({ argsPrefix: [], command: "/usr/local/bin/codegraph", exists: true, source: "path" }),
|
|
79
84
|
runCommand: (_projectRoot, command, args) => {
|
|
80
85
|
calls.push({ args, command });
|
|
81
|
-
|
|
86
|
+
writeProjectDatabase(workspace);
|
|
87
|
+
return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
|
|
82
88
|
},
|
|
83
89
|
},
|
|
84
90
|
});
|
|
85
91
|
|
|
86
92
|
// then
|
|
87
93
|
expect(result).toEqual({ action: "initialized" });
|
|
88
|
-
expect(calls).toEqual([
|
|
89
|
-
{ args: ["status", "--json"], command: binPath },
|
|
90
|
-
{ args: ["init"], command: binPath },
|
|
91
|
-
]);
|
|
94
|
+
expect(calls).toEqual([{ args: ["init"], command: binPath }]);
|
|
92
95
|
expect(provisionCalls).toEqual([
|
|
93
|
-
{ installDir: join(homeDir, ".omo", "codegraph"), lockDir: join(homeDir, ".omo", "codegraph", ".locks"), version: "1.
|
|
96
|
+
{ installDir: join(homeDir, ".omo", "codegraph"), lockDir: join(homeDir, ".omo", "codegraph", ".locks"), version: "1.5.0" },
|
|
94
97
|
]);
|
|
95
98
|
expect(outcomes).toEqual([{ action: "initialized", exitCode: 0, projectRoot: workspace, source: "provisioned", timedOut: false }]);
|
|
96
99
|
} finally {
|
|
@@ -99,6 +102,62 @@ describe("CodeGraph SessionStart worker Node support", () => {
|
|
|
99
102
|
}
|
|
100
103
|
});
|
|
101
104
|
|
|
105
|
+
it("#given bundled CodeGraph and a stale managed install #when the worker runs #then it upgrades and uses the managed runtime", async () => {
|
|
106
|
+
// given
|
|
107
|
+
const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-managed-upgrade-"));
|
|
108
|
+
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-managed-upgrade-home-"));
|
|
109
|
+
const installDir = join(homeDir, ".omo", "codegraph");
|
|
110
|
+
const binPath = join(installDir, "bin", "codegraph");
|
|
111
|
+
mkdirSync(join(installDir, "bin"), { recursive: true });
|
|
112
|
+
mkdirSync(join(installDir, ".provisioned"), { recursive: true });
|
|
113
|
+
writeFileSync(binPath, "stale codegraph\n");
|
|
114
|
+
writeFileSync(
|
|
115
|
+
join(installDir, ".provisioned", "codegraph-1.4.1.json"),
|
|
116
|
+
`${JSON.stringify({ binPath, version: "1.4.1" })}\n`,
|
|
117
|
+
);
|
|
118
|
+
const provisionCalls: unknown[] = [];
|
|
119
|
+
const commandCalls: Array<{ readonly args: readonly string[]; readonly command: string }> = [];
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
// when
|
|
123
|
+
const result = await runCodegraphSessionStartWorker({
|
|
124
|
+
cwd: workspace,
|
|
125
|
+
env: { HOME: homeDir },
|
|
126
|
+
nodeVersion: "22.14.0",
|
|
127
|
+
deps: {
|
|
128
|
+
ensureGitignored: () => true,
|
|
129
|
+
ensureProvisioned: (options) => {
|
|
130
|
+
provisionCalls.push(options);
|
|
131
|
+
return Promise.resolve({ binPath, provisioned: true });
|
|
132
|
+
},
|
|
133
|
+
managedInstallExists: () => true,
|
|
134
|
+
prepareWorkspace: () => ({
|
|
135
|
+
dataDir: join(homeDir, ".omo/codegraph/projects/test"),
|
|
136
|
+
dataRoot: join(homeDir, ".omo/codegraph"),
|
|
137
|
+
linked: true,
|
|
138
|
+
mode: "global-linked",
|
|
139
|
+
projectLink: join(workspace, ".codegraph"),
|
|
140
|
+
}),
|
|
141
|
+
resolveCommand: () => ({ argsPrefix: ["codegraph.js"], command: "/opt/node22/bin/node", exists: true, source: "bundled" }),
|
|
142
|
+
resolveManagedBin: () => null,
|
|
143
|
+
runCommand: (_projectRoot, command, args) => {
|
|
144
|
+
commandCalls.push({ args, command });
|
|
145
|
+
writeProjectDatabase(workspace);
|
|
146
|
+
return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// then
|
|
152
|
+
expect(result).toEqual({ action: "initialized" });
|
|
153
|
+
expect(provisionCalls).toEqual([{ installDir, lockDir: join(installDir, ".locks"), version: "1.5.0" }]);
|
|
154
|
+
expect(commandCalls).toEqual([{ args: ["init"], command: binPath }]);
|
|
155
|
+
} finally {
|
|
156
|
+
rmSync(workspace, { recursive: true, force: true });
|
|
157
|
+
rmSync(homeDir, { recursive: true, force: true });
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
102
161
|
it("#given an unsupported local Node but bundled CodeGraph resolves through CODEGRAPH_NODE_BIN #when worker runs #then it bootstraps with the compatible runtime", async () => {
|
|
103
162
|
// given
|
|
104
163
|
const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-compatible-node-"));
|
|
@@ -129,17 +188,15 @@ describe("CodeGraph SessionStart worker Node support", () => {
|
|
|
129
188
|
resolveCommand: () => ({ argsPrefix: ["codegraph.js"], command: nodeBin, exists: true, source: "bundled" }),
|
|
130
189
|
runCommand: (_projectRoot, command, args) => {
|
|
131
190
|
calls.push({ args, command });
|
|
132
|
-
|
|
191
|
+
writeProjectDatabase(workspace);
|
|
192
|
+
return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
|
|
133
193
|
},
|
|
134
194
|
},
|
|
135
195
|
});
|
|
136
196
|
|
|
137
197
|
// then
|
|
138
198
|
expect(result).toEqual({ action: "initialized" });
|
|
139
|
-
expect(calls).toEqual([
|
|
140
|
-
{ args: ["codegraph.js", "status", "--json"], command: nodeBin },
|
|
141
|
-
{ args: ["codegraph.js", "init"], command: nodeBin },
|
|
142
|
-
]);
|
|
199
|
+
expect(calls).toEqual([{ args: ["codegraph.js", "init"], command: nodeBin }]);
|
|
143
200
|
expect(outcomes).toEqual([{ action: "initialized", exitCode: 0, projectRoot: workspace, source: "bundled", timedOut: false }]);
|
|
144
201
|
} finally {
|
|
145
202
|
rmSync(workspace, { recursive: true, force: true });
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
import { probeCodegraphProject } from "../src/session-start-project.ts";
|
|
7
|
+
|
|
8
|
+
describe("CodeGraph SessionStart project probe", () => {
|
|
9
|
+
it("#given the exact project directory has a CodeGraph database #when probing #then it is initialized", () => {
|
|
10
|
+
// given
|
|
11
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-probe-exact-"));
|
|
12
|
+
try {
|
|
13
|
+
mkdirSync(join(projectRoot, ".codegraph"), { recursive: true });
|
|
14
|
+
writeFileSync(join(projectRoot, ".codegraph", "codegraph.db"), "fixture");
|
|
15
|
+
|
|
16
|
+
// when
|
|
17
|
+
const result = probeCodegraphProject(projectRoot);
|
|
18
|
+
|
|
19
|
+
// then
|
|
20
|
+
expect(result).toEqual({ kind: "initialized" });
|
|
21
|
+
} finally {
|
|
22
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("#given an ancestor directory has a CodeGraph database #when probing a nested project #then the ancestor covers it", () => {
|
|
27
|
+
// given
|
|
28
|
+
const ancestorRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-probe-ancestor-"));
|
|
29
|
+
const projectRoot = join(ancestorRoot, "apps", "server");
|
|
30
|
+
try {
|
|
31
|
+
mkdirSync(join(ancestorRoot, ".codegraph"), { recursive: true });
|
|
32
|
+
mkdirSync(projectRoot, { recursive: true });
|
|
33
|
+
writeFileSync(join(ancestorRoot, ".codegraph", "codegraph.db"), "fixture");
|
|
34
|
+
|
|
35
|
+
// when
|
|
36
|
+
const result = probeCodegraphProject(projectRoot);
|
|
37
|
+
|
|
38
|
+
// then
|
|
39
|
+
expect(result).toEqual({ ancestorRoot: realpathSync(ancestorRoot), kind: "nested-root" });
|
|
40
|
+
} finally {
|
|
41
|
+
rmSync(ancestorRoot, { recursive: true, force: true });
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("#given neither the project nor its ancestors have a CodeGraph database #when probing #then it is definitively uninitialized", () => {
|
|
46
|
+
// given
|
|
47
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-probe-missing-"));
|
|
48
|
+
try {
|
|
49
|
+
// when
|
|
50
|
+
const result = probeCodegraphProject(projectRoot);
|
|
51
|
+
|
|
52
|
+
// then
|
|
53
|
+
expect(result).toEqual({ kind: "uninitialized" });
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { mkdtempSync, rmSync, utimesSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
clearSessionStartCooldown,
|
|
8
|
+
readSessionStartCooldown,
|
|
9
|
+
recordSessionStartFailure,
|
|
10
|
+
} from "../src/session-start-cooldown.ts";
|
|
11
|
+
import {
|
|
12
|
+
acquireSessionStartLock,
|
|
13
|
+
releaseSessionStartLock,
|
|
14
|
+
} from "../src/session-start-lock.ts";
|
|
15
|
+
|
|
16
|
+
describe("CodeGraph SessionStart lock", () => {
|
|
17
|
+
it("#given a live project lock #when a second hook acquires it #then the second hook is deduplicated", () => {
|
|
18
|
+
// given
|
|
19
|
+
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-lock-home-"));
|
|
20
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-lock-project-"));
|
|
21
|
+
try {
|
|
22
|
+
const first = acquireSessionStartLock({ homeDir, nowMs: 10_000, projectRoot, staleMs: 60_000 });
|
|
23
|
+
expect(first.kind).toBe("acquired");
|
|
24
|
+
|
|
25
|
+
// when
|
|
26
|
+
const second = acquireSessionStartLock({ homeDir, nowMs: 10_001, projectRoot, staleMs: 60_000 });
|
|
27
|
+
|
|
28
|
+
// then
|
|
29
|
+
expect(second).toEqual({ kind: "locked" });
|
|
30
|
+
if (first.kind === "acquired") releaseSessionStartLock(first.lock);
|
|
31
|
+
} finally {
|
|
32
|
+
rmSync(homeDir, { recursive: true, force: true });
|
|
33
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("#given a project lock older than the stale threshold #when another hook acquires it #then the stale lock is recovered", () => {
|
|
38
|
+
// given
|
|
39
|
+
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-stale-home-"));
|
|
40
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-stale-project-"));
|
|
41
|
+
try {
|
|
42
|
+
const first = acquireSessionStartLock({ homeDir, nowMs: 1_000, projectRoot, staleMs: 500 });
|
|
43
|
+
expect(first.kind).toBe("acquired");
|
|
44
|
+
if (first.kind !== "acquired") return;
|
|
45
|
+
const staleDate = new Date(1_000);
|
|
46
|
+
utimesSync(first.lock.path, staleDate, staleDate);
|
|
47
|
+
|
|
48
|
+
// when
|
|
49
|
+
const second = acquireSessionStartLock({ homeDir, nowMs: 2_000, projectRoot, staleMs: 500 });
|
|
50
|
+
|
|
51
|
+
// then
|
|
52
|
+
expect(second.kind).toBe("acquired");
|
|
53
|
+
if (second.kind === "acquired") {
|
|
54
|
+
expect(second.recoveredStale).toBe(true);
|
|
55
|
+
releaseSessionStartLock(second.lock);
|
|
56
|
+
}
|
|
57
|
+
} finally {
|
|
58
|
+
rmSync(homeDir, { recursive: true, force: true });
|
|
59
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("CodeGraph SessionStart cooldown", () => {
|
|
65
|
+
it("#given a failed worker outcome #when the cooldown is checked #then retries are suppressed until expiry and the next failure backs off", () => {
|
|
66
|
+
// given
|
|
67
|
+
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-cooldown-home-"));
|
|
68
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-cooldown-project-"));
|
|
69
|
+
try {
|
|
70
|
+
const first = recordSessionStartFailure({
|
|
71
|
+
action: "failed",
|
|
72
|
+
baseCooldownMs: 1_000,
|
|
73
|
+
homeDir,
|
|
74
|
+
nowMs: 1_000,
|
|
75
|
+
projectRoot,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// when
|
|
79
|
+
const active = readSessionStartCooldown({ baseCooldownMs: 1_000, homeDir, nowMs: 1_999, projectRoot });
|
|
80
|
+
const expired = readSessionStartCooldown({ baseCooldownMs: 1_000, homeDir, nowMs: 2_000, projectRoot });
|
|
81
|
+
const second = recordSessionStartFailure({
|
|
82
|
+
action: "skipped-status",
|
|
83
|
+
baseCooldownMs: 1_000,
|
|
84
|
+
homeDir,
|
|
85
|
+
nowMs: 2_000,
|
|
86
|
+
projectRoot,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// then
|
|
90
|
+
expect(first).toMatchObject({ cooldownUntil: 2_000, failureCount: 1 });
|
|
91
|
+
expect(active).toMatchObject({ cooldownUntil: 2_000, failureCount: 1, kind: "active" });
|
|
92
|
+
expect(expired).toEqual({ failureCount: 1, kind: "inactive" });
|
|
93
|
+
expect(second).toMatchObject({ cooldownUntil: 4_000, failureCount: 2 });
|
|
94
|
+
clearSessionStartCooldown({ homeDir, projectRoot });
|
|
95
|
+
expect(readSessionStartCooldown({ baseCooldownMs: 1_000, homeDir, nowMs: 2_001, projectRoot })).toEqual({
|
|
96
|
+
failureCount: 0,
|
|
97
|
+
kind: "inactive",
|
|
98
|
+
});
|
|
99
|
+
} finally {
|
|
100
|
+
rmSync(homeDir, { recursive: true, force: true });
|
|
101
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts
CHANGED
|
@@ -15,7 +15,7 @@ describe("CodeGraph SessionStart trust boundary", () => {
|
|
|
15
15
|
const calls: Array<{ readonly env: Record<string, string>; readonly installDir?: string; readonly lockDir?: string }> = [];
|
|
16
16
|
try {
|
|
17
17
|
mkdirSync(join(workspace, ".omo"), { recursive: true });
|
|
18
|
-
writeFileSync(join(workspace, ".omo", "
|
|
18
|
+
writeFileSync(join(workspace, ".omo", "omo.jsonc"), JSON.stringify({ codegraph: { enabled: true, install_dir: attackerInstallDir } }));
|
|
19
19
|
|
|
20
20
|
// when
|
|
21
21
|
const result = await runCodegraphSessionStartWorker({
|
|
@@ -45,7 +45,9 @@ describe("CodeGraph SessionStart trust boundary", () => {
|
|
|
45
45
|
},
|
|
46
46
|
runCommand: (_projectRoot, _command, _args, options) => {
|
|
47
47
|
calls.push({ env: options.env });
|
|
48
|
-
|
|
48
|
+
mkdirSync(join(workspace, ".codegraph"), { recursive: true });
|
|
49
|
+
writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
|
|
50
|
+
return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
|
|
49
51
|
},
|
|
50
52
|
},
|
|
51
53
|
});
|
package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
import type { CodegraphSessionStartOutcome } from "../src/hook.ts";
|
|
7
|
+
import { runCodegraphSessionStartWorker } from "../src/hook.ts";
|
|
8
|
+
import { readSessionStartCooldown } from "../src/session-start-cooldown.ts";
|
|
9
|
+
|
|
10
|
+
describe("CodeGraph SessionStart worker cooldown", () => {
|
|
11
|
+
it("#given codegraph init times out #when the worker finishes #then it records a failed outcome and cooldown", async () => {
|
|
12
|
+
// given
|
|
13
|
+
const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-timeout-"));
|
|
14
|
+
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-timeout-home-"));
|
|
15
|
+
const outcomes: CodegraphSessionStartOutcome[] = [];
|
|
16
|
+
try {
|
|
17
|
+
// when
|
|
18
|
+
const result = await runCodegraphSessionStartWorker({
|
|
19
|
+
config: { codegraph: { enabled: true, session_start_cooldown_ms: 60_000 }, sources: [], warnings: [] },
|
|
20
|
+
cwd: workspace,
|
|
21
|
+
env: { HOME: homeDir },
|
|
22
|
+
logOutcome: (outcome) => outcomes.push(outcome),
|
|
23
|
+
nodeVersion: "22.14.0",
|
|
24
|
+
nowMs: 1_000,
|
|
25
|
+
projectProbe: () => ({ kind: "uninitialized" }),
|
|
26
|
+
deps: {
|
|
27
|
+
ensureGitignored: () => true,
|
|
28
|
+
ensureProvisioned: () => Promise.resolve({ binPath: "/tmp/codegraph", provisioned: true }),
|
|
29
|
+
prepareWorkspace: () => ({
|
|
30
|
+
dataDir: join(homeDir, ".omo/codegraph/projects/test"),
|
|
31
|
+
dataRoot: join(homeDir, ".omo/codegraph"),
|
|
32
|
+
linked: true,
|
|
33
|
+
mode: "global-linked",
|
|
34
|
+
projectLink: join(workspace, ".codegraph"),
|
|
35
|
+
}),
|
|
36
|
+
resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
|
|
37
|
+
runCommand: () => Promise.resolve({ exitCode: 1, stdout: "", timedOut: true }),
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const cooldown = readSessionStartCooldown({
|
|
41
|
+
baseCooldownMs: 60_000,
|
|
42
|
+
homeDir,
|
|
43
|
+
nowMs: 2_000,
|
|
44
|
+
projectRoot: workspace,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// then
|
|
48
|
+
expect(result).toEqual({ action: "failed" });
|
|
49
|
+
expect(outcomes).toEqual([{
|
|
50
|
+
action: "failed",
|
|
51
|
+
error: "codegraph init timed out",
|
|
52
|
+
exitCode: 1,
|
|
53
|
+
projectRoot: workspace,
|
|
54
|
+
source: "path",
|
|
55
|
+
timedOut: true,
|
|
56
|
+
}]);
|
|
57
|
+
expect(cooldown).toEqual({ cooldownUntil: 61_000, failureCount: 1, kind: "active" });
|
|
58
|
+
} finally {
|
|
59
|
+
rmSync(homeDir, { recursive: true, force: true });
|
|
60
|
+
rmSync(workspace, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("#given codegraph init exits zero without an exact database #when the worker verifies the result #then it records a failure cooldown", async () => {
|
|
65
|
+
// given
|
|
66
|
+
const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-no-db-"));
|
|
67
|
+
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-no-db-home-"));
|
|
68
|
+
const outcomes: CodegraphSessionStartOutcome[] = [];
|
|
69
|
+
try {
|
|
70
|
+
// when
|
|
71
|
+
const result = await runCodegraphSessionStartWorker({
|
|
72
|
+
config: { codegraph: { enabled: true, session_start_cooldown_ms: 60_000 }, sources: [], warnings: [] },
|
|
73
|
+
cwd: workspace,
|
|
74
|
+
env: { HOME: homeDir },
|
|
75
|
+
logOutcome: (outcome) => outcomes.push(outcome),
|
|
76
|
+
nodeVersion: "22.14.0",
|
|
77
|
+
nowMs: 1_000,
|
|
78
|
+
projectProbe: () => ({ kind: "uninitialized" }),
|
|
79
|
+
deps: {
|
|
80
|
+
ensureGitignored: () => true,
|
|
81
|
+
ensureProvisioned: () => Promise.resolve({ binPath: "/tmp/codegraph", provisioned: true }),
|
|
82
|
+
prepareWorkspace: () => ({
|
|
83
|
+
dataDir: join(homeDir, ".omo/codegraph/projects/test"),
|
|
84
|
+
dataRoot: join(homeDir, ".omo/codegraph"),
|
|
85
|
+
linked: true,
|
|
86
|
+
mode: "global-linked",
|
|
87
|
+
projectLink: join(workspace, ".codegraph"),
|
|
88
|
+
}),
|
|
89
|
+
resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
|
|
90
|
+
runCommand: () => Promise.resolve({ exitCode: 0, stdout: "", timedOut: false }),
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const cooldown = readSessionStartCooldown({
|
|
94
|
+
baseCooldownMs: 60_000,
|
|
95
|
+
homeDir,
|
|
96
|
+
nowMs: 2_000,
|
|
97
|
+
projectRoot: workspace,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// then
|
|
101
|
+
expect(result).toEqual({ action: "failed" });
|
|
102
|
+
expect(outcomes).toEqual([{
|
|
103
|
+
action: "failed",
|
|
104
|
+
error: "codegraph init completed without creating an exact project database",
|
|
105
|
+
exitCode: 0,
|
|
106
|
+
projectRoot: workspace,
|
|
107
|
+
source: "path",
|
|
108
|
+
timedOut: false,
|
|
109
|
+
}]);
|
|
110
|
+
expect(cooldown).toEqual({ cooldownUntil: 61_000, failureCount: 1, kind: "active" });
|
|
111
|
+
} finally {
|
|
112
|
+
rmSync(homeDir, { recursive: true, force: true });
|
|
113
|
+
rmSync(workspace, { recursive: true, force: true });
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts
CHANGED
|
@@ -6,6 +6,11 @@ import { join } from "node:path";
|
|
|
6
6
|
import { CODEGRAPH_PINNED_VERSION } from "../../../../../utils/src/codegraph/manifest.ts";
|
|
7
7
|
import { resolveCodegraphCommandInvocation, runCodegraphSessionStartWorker } from "../src/hook.ts";
|
|
8
8
|
|
|
9
|
+
function writeProjectDatabase(workspace: string): void {
|
|
10
|
+
mkdirSync(join(workspace, ".codegraph"), { recursive: true });
|
|
11
|
+
writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
|
|
12
|
+
}
|
|
13
|
+
|
|
9
14
|
describe("CodeGraph SessionStart worker flow", () => {
|
|
10
15
|
it("#given install_dir has the pinned platform binary #when worker resolves provisioned CodeGraph #then it uses that launcher", async () => {
|
|
11
16
|
// given
|
|
@@ -47,9 +52,11 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
47
52
|
const provisioned = options?.provisioned?.() ?? null;
|
|
48
53
|
return { argsPrefix: [], command: provisioned ?? "missing-codegraph", exists: provisioned !== null, source: provisioned === null ? "path" : "provisioned" };
|
|
49
54
|
},
|
|
55
|
+
resolveManagedBin: () => binPath,
|
|
50
56
|
runCommand: (_projectRoot, command, args, options) => {
|
|
51
57
|
calls.push({ args, command, env: options.env });
|
|
52
|
-
|
|
58
|
+
writeProjectDatabase(workspace);
|
|
59
|
+
return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
|
|
53
60
|
},
|
|
54
61
|
},
|
|
55
62
|
});
|
|
@@ -57,7 +64,6 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
57
64
|
// then
|
|
58
65
|
expect(result).toEqual({ action: "initialized" });
|
|
59
66
|
expect(calls.map((call) => ({ args: [...call.args], command: call.command }))).toEqual([
|
|
60
|
-
{ args: ["status", "--json"], command: binPath },
|
|
61
67
|
{ args: ["init"], command: binPath },
|
|
62
68
|
]);
|
|
63
69
|
expect(calls[0]?.env["CODEGRAPH_INSTALL_DIR"]).toBe(installDir);
|
|
@@ -74,11 +80,11 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
74
80
|
const command = "C:\\Users\\test\\.omo\\codegraph\\bin\\codegraph.cmd";
|
|
75
81
|
|
|
76
82
|
// when
|
|
77
|
-
const invocation = resolveCodegraphCommandInvocation(command, ["
|
|
83
|
+
const invocation = resolveCodegraphCommandInvocation(command, ["init"], "win32");
|
|
78
84
|
|
|
79
85
|
// then
|
|
80
86
|
expect(invocation).toEqual({
|
|
81
|
-
args: ["/d", "/s", "/c", command, "
|
|
87
|
+
args: ["/d", "/s", "/c", command, "init"],
|
|
82
88
|
command: "cmd.exe",
|
|
83
89
|
});
|
|
84
90
|
});
|
|
@@ -88,11 +94,11 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
88
94
|
const command = "C:\\Users\\test\\.omo\\codegraph\\bin\\codegraph.cjs";
|
|
89
95
|
|
|
90
96
|
// when
|
|
91
|
-
const invocation = resolveCodegraphCommandInvocation(command, ["
|
|
97
|
+
const invocation = resolveCodegraphCommandInvocation(command, ["init"], "win32");
|
|
92
98
|
|
|
93
99
|
// then
|
|
94
100
|
expect(invocation).toEqual({
|
|
95
|
-
args: [command, "
|
|
101
|
+
args: [command, "init"],
|
|
96
102
|
command: process.execPath,
|
|
97
103
|
});
|
|
98
104
|
});
|
|
@@ -108,51 +114,47 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
108
114
|
expect(invocation).toEqual({ args: ["sync"], command });
|
|
109
115
|
});
|
|
110
116
|
|
|
111
|
-
it("#given
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
runCommand: (_projectRoot, command, args, options) => {
|
|
141
|
-
calls.push({ args, command, env: options.env });
|
|
142
|
-
return Promise.resolve({ exitCode: 0, stdout: calls.length === 1 ? scenario.stdout : "", timedOut: false });
|
|
143
|
-
},
|
|
117
|
+
it("#given an uninitialized exact project #when worker runs #then it invokes init directly without a status command", async () => {
|
|
118
|
+
// given
|
|
119
|
+
const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-init-direct-"));
|
|
120
|
+
const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-init-direct-home-"));
|
|
121
|
+
const calls: { readonly args: readonly string[]; readonly env: Record<string, string> }[] = [];
|
|
122
|
+
const outcomes: unknown[] = [];
|
|
123
|
+
try {
|
|
124
|
+
// when
|
|
125
|
+
const result = await runCodegraphSessionStartWorker({
|
|
126
|
+
config: { codegraph: { enabled: true, install_dir: "/tmp/codegraph-install" }, sources: [], trustedCodegraphInstallDir: "/tmp/codegraph-install", warnings: [] },
|
|
127
|
+
nodeVersion: "22.14.0",
|
|
128
|
+
cwd: workspace,
|
|
129
|
+
env: { HOME: homeDir },
|
|
130
|
+
logOutcome: (outcome) => outcomes.push(outcome),
|
|
131
|
+
deps: {
|
|
132
|
+
ensureGitignored: () => true,
|
|
133
|
+
ensureProvisioned: () => Promise.resolve({ binPath: "/tmp/codegraph", provisioned: true }),
|
|
134
|
+
prepareWorkspace: () => ({
|
|
135
|
+
dataDir: join(homeDir, ".omo/codegraph/projects/test"),
|
|
136
|
+
dataRoot: join(homeDir, ".omo/codegraph"),
|
|
137
|
+
linked: true,
|
|
138
|
+
mode: "global-linked",
|
|
139
|
+
projectLink: join(workspace, ".codegraph"),
|
|
140
|
+
}),
|
|
141
|
+
resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
|
|
142
|
+
runCommand: (_projectRoot, _command, args, options) => {
|
|
143
|
+
calls.push({ args, env: options.env });
|
|
144
|
+
writeProjectDatabase(workspace);
|
|
145
|
+
return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
|
|
144
146
|
},
|
|
145
|
-
}
|
|
147
|
+
},
|
|
148
|
+
});
|
|
146
149
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
150
|
+
// then
|
|
151
|
+
expect(result).toEqual({ action: "initialized" });
|
|
152
|
+
expect(calls.map((call) => [...call.args])).toEqual([["init"]]);
|
|
153
|
+
expect(calls[0]?.env["CODEGRAPH_INSTALL_DIR"]).toBe("/tmp/codegraph-install");
|
|
154
|
+
expect(outcomes).toEqual([{ action: "initialized", exitCode: 0, projectRoot: workspace, source: "path", timedOut: false }]);
|
|
155
|
+
} finally {
|
|
156
|
+
rmSync(workspace, { recursive: true, force: true });
|
|
157
|
+
rmSync(homeDir, { recursive: true, force: true });
|
|
156
158
|
}
|
|
157
159
|
});
|
|
158
160
|
|
|
@@ -182,13 +184,14 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
182
184
|
resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
|
|
183
185
|
runCommand: (_projectRoot, command, args, options) => {
|
|
184
186
|
calls.push({ args, command, env: options.env });
|
|
185
|
-
|
|
187
|
+
writeProjectDatabase(workspace);
|
|
188
|
+
return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
|
|
186
189
|
},
|
|
187
190
|
},
|
|
188
191
|
});
|
|
189
192
|
|
|
190
193
|
// then
|
|
191
|
-
expect(result).toEqual({ action: "
|
|
194
|
+
expect(result).toEqual({ action: "initialized" });
|
|
192
195
|
expect(calls.length).toBeGreaterThan(0);
|
|
193
196
|
for (const call of calls) {
|
|
194
197
|
expect(call.env["CODEGRAPH_NO_DAEMON"]).toBe("1");
|
|
@@ -211,7 +214,8 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
211
214
|
const fakeCodegraphScript = [
|
|
212
215
|
"const fs = require('node:fs');",
|
|
213
216
|
`fs.appendFileSync(${JSON.stringify(logPath)}, JSON.stringify({install:process.env.CODEGRAPH_INSTALL_DIR,openai:process.env.OPENAI_API_KEY}) + '\\n');`,
|
|
214
|
-
"
|
|
217
|
+
"fs.mkdirSync('.codegraph', { recursive: true });",
|
|
218
|
+
"fs.writeFileSync('.codegraph/codegraph.db', 'fixture');",
|
|
215
219
|
].join("");
|
|
216
220
|
|
|
217
221
|
// when
|
|
@@ -238,15 +242,12 @@ describe("CodeGraph SessionStart worker flow", () => {
|
|
|
238
242
|
});
|
|
239
243
|
|
|
240
244
|
// then
|
|
241
|
-
expect(result).toEqual({ action: "
|
|
245
|
+
expect(result).toEqual({ action: "initialized" });
|
|
242
246
|
const captured = readFileSync(logPath, "utf8")
|
|
243
247
|
.trim()
|
|
244
248
|
.split("\n")
|
|
245
249
|
.map((line) => JSON.parse(line));
|
|
246
|
-
expect(captured).toEqual([
|
|
247
|
-
{ install: join(homeDir, ".omo", "codegraph") },
|
|
248
|
-
{ install: join(homeDir, ".omo", "codegraph") },
|
|
249
|
-
]);
|
|
250
|
+
expect(captured).toEqual([{ install: join(homeDir, ".omo", "codegraph") }]);
|
|
250
251
|
} finally {
|
|
251
252
|
if (originalOpenAiKey === undefined) delete process.env["OPENAI_API_KEY"];
|
|
252
253
|
else process.env["OPENAI_API_KEY"] = originalOpenAiKey;
|