oh-my-opencode 4.11.1 → 4.12.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/.agents/skills/codex-qa/scripts/lib/app-server-client.mjs +132 -82
- package/.agents/skills/codex-qa/scripts/lib/app-server-client.test.js +48 -0
- package/.agents/skills/opencode-qa/scripts/serve-wake-split-probe.sh +361 -84
- package/.agents/skills/work-with-pr/SKILL.md +19 -5
- package/.opencode/skills/work-with-pr/SKILL.md +19 -5
- package/dist/agents/types.d.ts +7 -6
- package/dist/cli/index.js +460 -309
- package/dist/cli-node/index.js +460 -309
- package/dist/features/background-agent/parent-wake-flush-runner.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-history-state.d.ts +1 -0
- package/dist/features/background-agent/parent-wake-session-history.d.ts +1 -47
- package/dist/features/background-agent/parent-wake-session-message.d.ts +47 -0
- package/dist/index.js +593 -310
- package/dist/plugin/tool-execute-before.d.ts +2 -0
- package/dist/plugin-handlers/plugin-components-loader.d.ts +1 -0
- package/dist/skills/ultraresearch/SKILL.md +11 -2
- package/dist/skills/ulw-plan/SKILL.md +2 -1
- package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -2
- package/dist/tools/background-task/constants.d.ts +1 -1
- package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -2
- package/dist/tools/delegate-task/sync-session-turns.d.ts +3 -0
- package/dist/tui.js +25 -10
- package/package.json +13 -13
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +24 -2
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +25 -9
- 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/dist/cli.js +336 -173
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +284 -33
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +11 -0
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +12 -0
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +34 -0
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +47 -5
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +7 -5
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +58 -96
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +94 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +33 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +48 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +142 -0
- 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/comment-checker/test/package-smoke.test.ts +2 -71
- 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/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +26 -104
- 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/rules/test/package-smoke.test.ts +12 -92
- package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +157 -234
- 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 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +227 -15
- package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +62 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +34 -3
- package/packages/omo-codex/plugin/components/teammode/dist/cli.js +94 -0
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +17 -0
- package/packages/omo-codex/plugin/components/teammode/package.json +26 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +139 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +111 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +250 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +220 -0
- package/packages/omo-codex/plugin/components/teammode/src/cli.ts +12 -0
- package/packages/omo-codex/plugin/components/teammode/src/codex-hook.ts +125 -0
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +116 -0
- package/packages/omo-codex/plugin/components/teammode/tsconfig.json +25 -0
- 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/test-support/package-smoke-fixture.ts +158 -0
- 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 +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +76 -49
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +17 -0
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +17 -0
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +17 -0
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +17 -0
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +17 -0
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +17 -0
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +16 -0
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +16 -0
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +16 -0
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +16 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +16 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +17 -0
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +16 -0
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +16 -0
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +16 -0
- package/packages/omo-codex/plugin/package-lock.json +30 -22
- package/packages/omo-codex/plugin/package.json +2 -1
- package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +15 -11
- package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +15 -4
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +37 -0
- package/packages/omo-codex/plugin/skills/ast-grep/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/comment-checker/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/debugging/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/frontend/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/git-master/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/init-deep/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lcx-doctor/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/lsp/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/lsp-setup/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/programming/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/refactor/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/remove-ai-slops/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/review-work/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/rules/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +139 -0
- package/packages/omo-codex/plugin/skills/teammode/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +111 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +250 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +220 -0
- package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +11 -2
- package/packages/omo-codex/plugin/skills/ultraresearch/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/agents/openai.yaml +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -2
- package/packages/omo-codex/plugin/skills/visual-qa/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +70 -33
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +6 -2
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +14 -1
- package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +14 -6
- package/packages/omo-codex/plugin/test/bootstrap-ps-guard.test.mjs +7 -3
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +4 -3
- package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +24 -0
- package/packages/omo-codex/plugin/test/display-metadata.test.mjs +83 -0
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +31 -19
- package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +3 -3
- package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +6 -6
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -0
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +9 -4
- package/packages/omo-codex/plugin/test/teammode-safety-fixture.mjs +88 -0
- package/packages/omo-codex/plugin/test/teammode-safety.test.mjs +240 -0
- package/packages/omo-codex/plugin/test/ultraresearch-skill-contract.test.mjs +48 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +398 -206
- package/packages/omo-codex/scripts/install-hook-targets.test.mjs +93 -0
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +2 -2
- package/packages/omo-codex/scripts/install-local-bun-global-update.test.mjs +63 -0
- package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +109 -1
- package/packages/omo-codex/scripts/install-local.mjs +1 -0
- package/packages/shared-skills/skills/ultraresearch/SKILL.md +11 -2
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -2
- package/packages/omo-codex/plugin/hooks/hooks.json +0 -214
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
// src/serve.ts
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
-
import { existsSync as
|
|
6
|
-
import { homedir as
|
|
7
|
-
import { basename as
|
|
5
|
+
import { existsSync as existsSync5, realpathSync } from "node:fs";
|
|
6
|
+
import { homedir as homedir5 } from "node:os";
|
|
7
|
+
import { basename as basename3, extname, join as join6, resolve as resolve2 } from "node:path";
|
|
8
8
|
import {
|
|
9
9
|
cwd as processCwd,
|
|
10
10
|
env as processEnv,
|
|
@@ -59,16 +59,235 @@ function parseNodeMajor(version) {
|
|
|
59
59
|
return Number.isNaN(major) ? 0 : major;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
// ../../../../utils/src/codegraph/
|
|
62
|
+
// ../../../../utils/src/codegraph/provision.ts
|
|
63
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
64
|
+
import { execFile } from "node:child_process";
|
|
65
|
+
import { chmod, mkdir, readdir, readFile, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
63
66
|
import { existsSync } from "node:fs";
|
|
64
|
-
import { homedir as homedir2 } from "node:os";
|
|
67
|
+
import { homedir as homedir2, hostname } from "node:os";
|
|
68
|
+
import { basename, join as join2 } from "node:path";
|
|
69
|
+
import { promisify } from "node:util";
|
|
70
|
+
|
|
71
|
+
// ../../../../utils/src/codegraph/manifest.ts
|
|
72
|
+
var CODEGRAPH_PROVISION_MANIFEST = {
|
|
73
|
+
assets: {
|
|
74
|
+
"darwin-arm64": {
|
|
75
|
+
executableName: "codegraph",
|
|
76
|
+
sha256: "95bb27bf6382b69659e158e0c04d71cc394778951e1317d582be7807e7866908",
|
|
77
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-darwin-arm64.tar.gz"
|
|
78
|
+
},
|
|
79
|
+
"darwin-x64": {
|
|
80
|
+
executableName: "codegraph",
|
|
81
|
+
sha256: "3311cc1d1f0f0ad742709b6a43d8a9187b1ef0af0dd30e0b58008dc673e29478",
|
|
82
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-darwin-x64.tar.gz"
|
|
83
|
+
},
|
|
84
|
+
"linux-arm64": {
|
|
85
|
+
executableName: "codegraph",
|
|
86
|
+
sha256: "e16f612bc96c2ebccd04574cbed500c9939147c80666ad6bb024398dff7992ae",
|
|
87
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-linux-arm64.tar.gz"
|
|
88
|
+
},
|
|
89
|
+
"linux-x64": {
|
|
90
|
+
executableName: "codegraph",
|
|
91
|
+
sha256: "d45a068f44596a85c7ba7d0ef924eaf7103fbbf3cafbeb668127daff60a52228",
|
|
92
|
+
url: "https://github.com/colbymchenry/codegraph/releases/download/v1.0.1/codegraph-linux-x64.tar.gz"
|
|
93
|
+
},
|
|
94
|
+
"win32-arm64": {
|
|
95
|
+
executableName: "codegraph.cmd",
|
|
96
|
+
sha256: "8d57ced73b24d35f758f2ede2318e80e1d7241987f37a999e3d80edb6fddf961",
|
|
97
|
+
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-arm64/-/codegraph-win32-arm64-1.0.1.tgz"
|
|
98
|
+
},
|
|
99
|
+
"win32-x64": {
|
|
100
|
+
executableName: "codegraph.cmd",
|
|
101
|
+
sha256: "52607fe73b05e741fd1087da2ceca9d3c8f565e36bf1a7070600bdbdf3931e32",
|
|
102
|
+
url: "https://registry.npmjs.org/@colbymchenry/codegraph-win32-x64/-/codegraph-win32-x64-1.0.1.tgz"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
version: "1.0.1"
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// ../../../../utils/src/codegraph/provision.ts
|
|
109
|
+
var DEFAULT_LOCK_WAIT_MS = 5000;
|
|
110
|
+
var DEFAULT_LOCK_STALE_MS = 120000;
|
|
111
|
+
var DEFAULT_DOWNLOAD_TIMEOUT_MS = 60000;
|
|
112
|
+
var execFileAsync = promisify(execFile);
|
|
113
|
+
function platformKey() {
|
|
114
|
+
return `${process.platform}-${process.arch}`;
|
|
115
|
+
}
|
|
116
|
+
function markerPath(installDir, version) {
|
|
117
|
+
return join2(installDir, ".provisioned", `codegraph-${version}.json`);
|
|
118
|
+
}
|
|
119
|
+
function defaultInstallDir() {
|
|
120
|
+
return join2(homedir2(), ".omo", "codegraph");
|
|
121
|
+
}
|
|
122
|
+
function sha256(bytes) {
|
|
123
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
124
|
+
}
|
|
125
|
+
function isErrnoException(error) {
|
|
126
|
+
return error instanceof Error && "code" in error;
|
|
127
|
+
}
|
|
128
|
+
async function removeEmptyDirectory(path) {
|
|
129
|
+
try {
|
|
130
|
+
await rmdir(path);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (isErrnoException(error) && error.code === "ENOENT")
|
|
133
|
+
return;
|
|
134
|
+
if (isErrnoException(error) && error.code === "ENOTEMPTY")
|
|
135
|
+
return;
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function sleep(ms) {
|
|
140
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
141
|
+
}
|
|
142
|
+
async function defaultDownloader(asset, timeoutMs = DEFAULT_DOWNLOAD_TIMEOUT_MS) {
|
|
143
|
+
const response = await fetch(asset.url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
144
|
+
if (!response.ok)
|
|
145
|
+
throw new Error(`download failed with HTTP ${response.status}`);
|
|
146
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
147
|
+
}
|
|
148
|
+
function forcedBadChecksumOptions(options) {
|
|
149
|
+
if (options.forceBadChecksum !== true)
|
|
150
|
+
return null;
|
|
151
|
+
const key = options.platformKey ?? platformKey();
|
|
152
|
+
return {
|
|
153
|
+
downloader: async () => new TextEncoder().encode("checksum mismatch"),
|
|
154
|
+
installDir: options.installDir ?? join2(options.lockDir, "codegraph-force-bad-checksum"),
|
|
155
|
+
manifest: {
|
|
156
|
+
assets: {
|
|
157
|
+
[key]: { executableName: process.platform === "win32" ? "codegraph.cmd" : "codegraph", sha256: "0000", url: "memory://bad" }
|
|
158
|
+
},
|
|
159
|
+
version: options.version
|
|
160
|
+
},
|
|
161
|
+
platformKey: key
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
async function readMarker(path) {
|
|
165
|
+
if (!existsSync(path))
|
|
166
|
+
return null;
|
|
167
|
+
try {
|
|
168
|
+
const raw = JSON.parse(await readFile(path, "utf8"));
|
|
169
|
+
if (typeof raw === "object" && raw !== null && "binPath" in raw) {
|
|
170
|
+
const value = raw.binPath;
|
|
171
|
+
return typeof value === "string" && existsSync(value) ? value : null;
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (error instanceof Error)
|
|
176
|
+
return null;
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function acquireLock(lockPath, waitMs, staleMs) {
|
|
181
|
+
const startedAt = Date.now();
|
|
182
|
+
await mkdir(join2(lockPath, ".."), { recursive: true });
|
|
183
|
+
while (Date.now() - startedAt <= waitMs) {
|
|
184
|
+
try {
|
|
185
|
+
await mkdir(lockPath);
|
|
186
|
+
return () => rm(lockPath, { force: true, recursive: true });
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if (!isErrnoException(error) || error.code !== "EEXIST")
|
|
189
|
+
throw error;
|
|
190
|
+
const lockStat = await stat(lockPath).catch(() => null);
|
|
191
|
+
if (lockStat !== null && Date.now() - lockStat.mtimeMs > staleMs) {
|
|
192
|
+
await rm(lockPath, { force: true, recursive: true });
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
await sleep(25);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
async function extractTarGz(archivePath, destinationDir) {
|
|
201
|
+
await execFileAsync("tar", ["-xzf", archivePath, "-C", destinationDir]);
|
|
202
|
+
}
|
|
203
|
+
async function installExtractedBundle(extractDir, installDir, executableName) {
|
|
204
|
+
const roots = await readdir(extractDir);
|
|
205
|
+
if (roots.length !== 1)
|
|
206
|
+
throw new Error(`CodeGraph archive should contain one root directory, found ${roots.length}`);
|
|
207
|
+
const bundleDir = join2(extractDir, roots[0] ?? "");
|
|
208
|
+
const bundleEntries = await readdir(bundleDir);
|
|
209
|
+
await mkdir(installDir, { recursive: true });
|
|
210
|
+
for (const entry of bundleEntries) {
|
|
211
|
+
await rm(join2(installDir, entry), { force: true, recursive: true });
|
|
212
|
+
await rename(join2(bundleDir, entry), join2(installDir, entry));
|
|
213
|
+
}
|
|
214
|
+
const destination = join2(installDir, "bin", executableName);
|
|
215
|
+
if (!existsSync(destination))
|
|
216
|
+
throw new Error(`CodeGraph archive did not contain bin/${executableName}`);
|
|
217
|
+
await chmod(destination, 493);
|
|
218
|
+
return destination;
|
|
219
|
+
}
|
|
220
|
+
async function installAsset(layout) {
|
|
221
|
+
const { asset, downloader, installDir, version } = layout;
|
|
222
|
+
const stagingDir = join2(installDir, ".staging", randomUUID());
|
|
223
|
+
const archivePath = join2(stagingDir, basename(asset.url));
|
|
224
|
+
const extractDir = join2(stagingDir, "extract");
|
|
225
|
+
try {
|
|
226
|
+
await mkdir(extractDir, { recursive: true });
|
|
227
|
+
const bytes = await downloader(asset);
|
|
228
|
+
const actualChecksum = sha256(bytes);
|
|
229
|
+
if (actualChecksum !== asset.sha256) {
|
|
230
|
+
throw new Error(`checksum mismatch for ${basename(asset.url)}: expected ${asset.sha256}, got ${actualChecksum}`);
|
|
231
|
+
}
|
|
232
|
+
if (!asset.url.endsWith(".tar.gz") && !asset.url.endsWith(".tgz")) {
|
|
233
|
+
throw new Error(`unsupported CodeGraph archive type for ${basename(asset.url)}`);
|
|
234
|
+
}
|
|
235
|
+
await writeFile(archivePath, bytes);
|
|
236
|
+
await extractTarGz(archivePath, extractDir);
|
|
237
|
+
const destination = await installExtractedBundle(extractDir, installDir, asset.executableName);
|
|
238
|
+
await mkdir(join2(installDir, ".provisioned"), { recursive: true });
|
|
239
|
+
await writeFile(markerPath(installDir, version), `${JSON.stringify({ binPath: destination, version })}
|
|
240
|
+
`);
|
|
241
|
+
return destination;
|
|
242
|
+
} finally {
|
|
243
|
+
await rm(stagingDir, { force: true, recursive: true });
|
|
244
|
+
await removeEmptyDirectory(join2(installDir, ".staging"));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async function ensureCodegraphProvisioned(options) {
|
|
248
|
+
const forced = forcedBadChecksumOptions(options);
|
|
249
|
+
const installDir = forced?.installDir ?? options.installDir ?? defaultInstallDir();
|
|
250
|
+
const manifest = forced?.manifest ?? options.manifest ?? CODEGRAPH_PROVISION_MANIFEST;
|
|
251
|
+
const activePlatformKey = forced?.platformKey ?? options.platformKey ?? platformKey();
|
|
252
|
+
const downloader = forced?.downloader ?? options.downloader ?? ((asset) => defaultDownloader(asset, options.downloadTimeoutMs));
|
|
253
|
+
const marker = markerPath(installDir, options.version);
|
|
254
|
+
const existing = await readMarker(marker);
|
|
255
|
+
if (existing !== null)
|
|
256
|
+
return { binPath: existing, provisioned: true };
|
|
257
|
+
const lockPath = join2(options.lockDir, `codegraph-${hostname()}.lock`);
|
|
258
|
+
const release = await acquireLock(lockPath, options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS, options.lockStaleMs ?? DEFAULT_LOCK_STALE_MS);
|
|
259
|
+
if (release === null)
|
|
260
|
+
return { error: "timed out waiting for codegraph provisioning lock", provisioned: false };
|
|
261
|
+
try {
|
|
262
|
+
const lockedExisting = await readMarker(marker);
|
|
263
|
+
if (lockedExisting !== null)
|
|
264
|
+
return { binPath: lockedExisting, provisioned: true };
|
|
265
|
+
if (manifest.version !== options.version) {
|
|
266
|
+
return { error: `manifest version ${manifest.version} does not match requested ${options.version}`, provisioned: false };
|
|
267
|
+
}
|
|
268
|
+
const asset = manifest.assets[activePlatformKey];
|
|
269
|
+
if (asset === undefined) {
|
|
270
|
+
return { error: `no CodeGraph ${options.version} asset for ${activePlatformKey}`, provisioned: false };
|
|
271
|
+
}
|
|
272
|
+
const binPath = await installAsset({ asset, downloader, installDir, version: options.version });
|
|
273
|
+
return { binPath, provisioned: true };
|
|
274
|
+
} catch (error) {
|
|
275
|
+
return { error: error instanceof Error ? error.message : String(error), provisioned: false };
|
|
276
|
+
} finally {
|
|
277
|
+
await release();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ../../../../utils/src/codegraph/resolve.ts
|
|
282
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
283
|
+
import { homedir as homedir3 } from "node:os";
|
|
65
284
|
import { spawnSync } from "node:child_process";
|
|
66
|
-
import { basename, dirname, join as
|
|
285
|
+
import { basename as basename2, dirname, join as join4 } from "node:path";
|
|
67
286
|
import { createRequire } from "node:module";
|
|
68
287
|
|
|
69
288
|
// ../../../../utils/src/runtime/which.ts
|
|
70
289
|
import { accessSync, constants } from "node:fs";
|
|
71
|
-
import { delimiter, join as
|
|
290
|
+
import { delimiter, join as join3 } from "node:path";
|
|
72
291
|
var runtime = globalThis;
|
|
73
292
|
function isUnsafeCommandName(commandName) {
|
|
74
293
|
if (commandName.includes("/") || commandName.includes("\\"))
|
|
@@ -123,7 +342,7 @@ function bunWhich(commandName) {
|
|
|
123
342
|
return null;
|
|
124
343
|
for (const pathEntry of pathEntries) {
|
|
125
344
|
for (const candidateName of candidateNames) {
|
|
126
|
-
const candidatePath =
|
|
345
|
+
const candidatePath = join3(pathEntry, candidateName);
|
|
127
346
|
if (isExecutable(candidatePath))
|
|
128
347
|
return candidatePath;
|
|
129
348
|
}
|
|
@@ -132,6 +351,9 @@ function bunWhich(commandName) {
|
|
|
132
351
|
}
|
|
133
352
|
|
|
134
353
|
// ../../../../utils/src/codegraph/resolve.ts
|
|
354
|
+
function codegraphCommandRequiresSupportedLocalNode(resolution) {
|
|
355
|
+
return resolution.source !== "bundled" && resolution.source !== "env" && resolution.source !== "provisioned";
|
|
356
|
+
}
|
|
135
357
|
var CODEGRAPH_PACKAGE = "@colbymchenry/codegraph";
|
|
136
358
|
var CODEGRAPH_ENV_BIN = "OMO_CODEGRAPH_BIN";
|
|
137
359
|
var CODEGRAPH_LEGACY_ENV_BIN = "CODEGRAPH_BIN";
|
|
@@ -161,7 +383,7 @@ ${result.stderr}`.trim().split(/\s+/)[0];
|
|
|
161
383
|
}
|
|
162
384
|
}
|
|
163
385
|
function isNodeExecutableName(filePath) {
|
|
164
|
-
const executable =
|
|
386
|
+
const executable = basename2(filePath).toLowerCase();
|
|
165
387
|
return executable === "node" || executable === "node.exe" || /^node\d+(\.exe)?$/.test(executable);
|
|
166
388
|
}
|
|
167
389
|
function looksLikePath(command) {
|
|
@@ -201,8 +423,8 @@ function defaultNodeRuntime(env, fileExists, which, nodeVersion) {
|
|
|
201
423
|
function defaultProvisionedBin(homeDir, fileExists) {
|
|
202
424
|
const binaryName = process.platform === "win32" ? "codegraph.cmd" : "codegraph";
|
|
203
425
|
const candidates = [
|
|
204
|
-
|
|
205
|
-
|
|
426
|
+
join4(homeDir, ".omo", "codegraph", "bin", binaryName),
|
|
427
|
+
join4(homeDir, ".omo", "codegraph", "node-servers", "node_modules", ".bin", binaryName)
|
|
206
428
|
];
|
|
207
429
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
208
430
|
}
|
|
@@ -210,7 +432,7 @@ function resolveBundledShim(requireResolve, fileExists) {
|
|
|
210
432
|
try {
|
|
211
433
|
const packageJson = requireResolve(`${CODEGRAPH_PACKAGE}/package.json`);
|
|
212
434
|
const packageRoot = dirname(packageJson);
|
|
213
|
-
const candidates = [
|
|
435
|
+
const candidates = [join4(packageRoot, "bin", "codegraph.js"), join4(packageRoot, "npm-shim.js")];
|
|
214
436
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
215
437
|
} catch (error) {
|
|
216
438
|
if (error instanceof Error)
|
|
@@ -226,7 +448,7 @@ function resolveBundledShim(requireResolve, fileExists) {
|
|
|
226
448
|
}
|
|
227
449
|
function resolveCodegraphCommand(options = {}) {
|
|
228
450
|
const env = options.env ?? process.env;
|
|
229
|
-
const fileExists = options.fileExists ??
|
|
451
|
+
const fileExists = options.fileExists ?? existsSync2;
|
|
230
452
|
const configuredBin = env[CODEGRAPH_ENV_BIN]?.trim() || env[CODEGRAPH_LEGACY_ENV_BIN]?.trim();
|
|
231
453
|
if (configuredBin !== undefined && configuredBin.length > 0) {
|
|
232
454
|
return { argsPrefix: [], command: configuredBin, exists: fileExists(configuredBin), source: "env" };
|
|
@@ -238,7 +460,7 @@ function resolveCodegraphCommand(options = {}) {
|
|
|
238
460
|
if (bundled !== null && runtime2 !== null) {
|
|
239
461
|
return { argsPrefix: [bundled], command: runtime2, exists: true, source: "bundled" };
|
|
240
462
|
}
|
|
241
|
-
const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ??
|
|
463
|
+
const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ?? homedir3(), fileExists);
|
|
242
464
|
if (provisioned !== null && fileExists(provisioned)) {
|
|
243
465
|
return { argsPrefix: [], command: provisioned, exists: true, source: "provisioned" };
|
|
244
466
|
}
|
|
@@ -252,8 +474,8 @@ function resolveCodegraphCommand(options = {}) {
|
|
|
252
474
|
}
|
|
253
475
|
|
|
254
476
|
// ../../../../utils/src/omo-config/loader.ts
|
|
255
|
-
import { existsSync as
|
|
256
|
-
import { homedir as
|
|
477
|
+
import { existsSync as existsSync4, readFileSync } from "node:fs";
|
|
478
|
+
import { homedir as homedir4 } from "node:os";
|
|
257
479
|
|
|
258
480
|
// ../../../../utils/src/deep-merge.ts
|
|
259
481
|
var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -1209,8 +1431,8 @@ function buildEnvOverrides(harness, env, warnings, merge) {
|
|
|
1209
1431
|
}
|
|
1210
1432
|
|
|
1211
1433
|
// ../../../../utils/src/omo-config/resolve.ts
|
|
1212
|
-
import { existsSync as
|
|
1213
|
-
import { dirname as dirname2, isAbsolute, join as
|
|
1434
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
1435
|
+
import { dirname as dirname2, isAbsolute, join as join5, relative, resolve } from "node:path";
|
|
1214
1436
|
function containsPath(parent, child) {
|
|
1215
1437
|
const pathToChild = relative(parent, child);
|
|
1216
1438
|
return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute(pathToChild);
|
|
@@ -1223,8 +1445,8 @@ function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
|
1223
1445
|
while (true) {
|
|
1224
1446
|
if (stopBeforeDir !== null && currentDir === stopBeforeDir)
|
|
1225
1447
|
break;
|
|
1226
|
-
const configPath =
|
|
1227
|
-
if (
|
|
1448
|
+
const configPath = join5(currentDir, ".omo", "config.jsonc");
|
|
1449
|
+
if (existsSync3(configPath)) {
|
|
1228
1450
|
paths.push(configPath);
|
|
1229
1451
|
}
|
|
1230
1452
|
const parentDir = dirname2(currentDir);
|
|
@@ -1235,7 +1457,7 @@ function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
|
1235
1457
|
return paths;
|
|
1236
1458
|
}
|
|
1237
1459
|
function resolveOmoConfigPaths(options) {
|
|
1238
|
-
const globalPath =
|
|
1460
|
+
const globalPath = join5(resolve(options.homeDir), ".omo", "config.jsonc");
|
|
1239
1461
|
const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
|
|
1240
1462
|
return [
|
|
1241
1463
|
{ path: globalPath, scope: "global" },
|
|
@@ -1446,13 +1668,13 @@ function validateHarnessApplicability(config, harness) {
|
|
|
1446
1668
|
}
|
|
1447
1669
|
function loadOmoConfig(options) {
|
|
1448
1670
|
const cwd = options.cwd ?? process.cwd();
|
|
1449
|
-
const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ??
|
|
1671
|
+
const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ?? homedir4();
|
|
1450
1672
|
const env = options.env ?? process.env;
|
|
1451
1673
|
let config = BUILT_IN_DEFAULTS;
|
|
1452
1674
|
const sources = [];
|
|
1453
1675
|
const warnings = [];
|
|
1454
1676
|
for (const candidate of resolveOmoConfigPaths({ cwd, homeDir })) {
|
|
1455
|
-
if (!
|
|
1677
|
+
if (!existsSync4(candidate.path)) {
|
|
1456
1678
|
if (candidate.scope === "global") {
|
|
1457
1679
|
sources.push(toMissingSource(candidate));
|
|
1458
1680
|
}
|
|
@@ -1494,11 +1716,12 @@ var CODEGRAPH_SKIP_HINT = `CodeGraph MCP skipped: codegraph binary not found. In
|
|
|
1494
1716
|
`;
|
|
1495
1717
|
var CODEGRAPH_DISABLED_HINT = `CodeGraph MCP skipped: disabled by OMO SOT config. Set [codex].codegraph.enabled=true to enable it.
|
|
1496
1718
|
`;
|
|
1719
|
+
var CODEGRAPH_VERSION = "1.0.1";
|
|
1497
1720
|
var WINDOWS_CMD_EXTENSIONS = new Set([".bat", ".cmd"]);
|
|
1498
1721
|
var WINDOWS_NODE_SCRIPT_EXTENSIONS = new Set([".cjs", ".js", ".mjs"]);
|
|
1499
1722
|
async function runCodegraphServe(options = {}) {
|
|
1500
1723
|
const env = options.env ?? processEnv;
|
|
1501
|
-
const homeDir = options.homeDir ??
|
|
1724
|
+
const homeDir = options.homeDir ?? homedir5();
|
|
1502
1725
|
const config = options.config ?? getCodexOmoConfig({ cwd: options.cwd ?? processCwd(), env, homeDir });
|
|
1503
1726
|
const codegraphConfig = config.codegraph ?? {};
|
|
1504
1727
|
if (codegraphConfig.enabled === false) {
|
|
@@ -1510,13 +1733,26 @@ async function runCodegraphServe(options = {}) {
|
|
|
1510
1733
|
homeDir,
|
|
1511
1734
|
provisioned: () => provisionedBinFromInstallDir(codegraphConfig.install_dir)
|
|
1512
1735
|
};
|
|
1513
|
-
|
|
1514
|
-
if (!resolution.exists || shouldSkipResolvedCommand(resolution, options.commandExists ?? existsSync4)) {
|
|
1515
|
-
(options.stderr ?? processStderr).write(CODEGRAPH_SKIP_HINT);
|
|
1516
|
-
return 1;
|
|
1517
|
-
}
|
|
1736
|
+
let resolution = options.resolve?.(resolutionOptions) ?? resolveCodegraphCommand(resolutionOptions);
|
|
1518
1737
|
const nodeSupport = evaluateCodegraphNodeSupport({ env, nodeVersion: options.nodeVersion });
|
|
1519
|
-
if (resolution.
|
|
1738
|
+
if (!resolution.exists || shouldSkipResolvedCommand(resolution, options.commandExists ?? existsSync5)) {
|
|
1739
|
+
if (resolution.source === "path" && !nodeSupport.supported) {
|
|
1740
|
+
(options.stderr ?? processStderr).write(buildCodegraphNodeSkipHint(nodeSupport));
|
|
1741
|
+
return 1;
|
|
1742
|
+
}
|
|
1743
|
+
const provisioned = await provisionMissingCodegraph({
|
|
1744
|
+
config: codegraphConfig,
|
|
1745
|
+
ensureProvisioned: options.ensureProvisioned ?? ensureCodegraphProvisioned,
|
|
1746
|
+
homeDir,
|
|
1747
|
+
resolution
|
|
1748
|
+
});
|
|
1749
|
+
if (provisioned === null) {
|
|
1750
|
+
(options.stderr ?? processStderr).write(CODEGRAPH_SKIP_HINT);
|
|
1751
|
+
return 1;
|
|
1752
|
+
}
|
|
1753
|
+
resolution = provisioned;
|
|
1754
|
+
}
|
|
1755
|
+
if (codegraphCommandRequiresSupportedLocalNode(resolution) && !nodeSupport.supported) {
|
|
1520
1756
|
(options.stderr ?? processStderr).write(buildCodegraphNodeSkipHint(nodeSupport));
|
|
1521
1757
|
return 1;
|
|
1522
1758
|
}
|
|
@@ -1531,6 +1767,21 @@ async function runCodegraphServe(options = {}) {
|
|
|
1531
1767
|
stdio: "inherit"
|
|
1532
1768
|
});
|
|
1533
1769
|
}
|
|
1770
|
+
async function provisionMissingCodegraph(options) {
|
|
1771
|
+
if (options.resolution.source === "env")
|
|
1772
|
+
return null;
|
|
1773
|
+
if (options.config.auto_provision === false)
|
|
1774
|
+
return null;
|
|
1775
|
+
const installDir = options.config.install_dir ?? join6(options.homeDir, ".omo", "codegraph");
|
|
1776
|
+
const result = await options.ensureProvisioned({
|
|
1777
|
+
installDir,
|
|
1778
|
+
lockDir: join6(installDir, ".locks"),
|
|
1779
|
+
version: CODEGRAPH_VERSION
|
|
1780
|
+
});
|
|
1781
|
+
if (!result.provisioned || result.binPath === undefined)
|
|
1782
|
+
return null;
|
|
1783
|
+
return { argsPrefix: [], command: result.binPath, exists: true, source: "provisioned" };
|
|
1784
|
+
}
|
|
1534
1785
|
function shouldSkipResolvedCommand(resolution, commandExists) {
|
|
1535
1786
|
if (resolution.source !== "env")
|
|
1536
1787
|
return false;
|
|
@@ -1548,8 +1799,8 @@ function codegraphEnvForConfig(config, homeDir, buildEnv) {
|
|
|
1548
1799
|
function provisionedBinFromInstallDir(installDir) {
|
|
1549
1800
|
if (installDir === undefined)
|
|
1550
1801
|
return null;
|
|
1551
|
-
const candidate =
|
|
1552
|
-
return
|
|
1802
|
+
const candidate = join6(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
|
|
1803
|
+
return existsSync5(candidate) ? candidate : null;
|
|
1553
1804
|
}
|
|
1554
1805
|
async function runCodegraphServeCli() {
|
|
1555
1806
|
process.exitCode = await runCodegraphServe();
|
|
@@ -1591,7 +1842,7 @@ function isDirectInvocation(argvPath) {
|
|
|
1591
1842
|
if (argvPath === undefined)
|
|
1592
1843
|
return false;
|
|
1593
1844
|
const modulePath = fileURLToPath(import.meta.url);
|
|
1594
|
-
const moduleName =
|
|
1845
|
+
const moduleName = basename3(modulePath);
|
|
1595
1846
|
if (moduleName !== "serve.js" && moduleName !== "serve.ts")
|
|
1596
1847
|
return false;
|
|
1597
1848
|
return realpathSync(resolve2(argvPath)) === realpathSync(modulePath);
|
|
@@ -5,8 +5,10 @@ import { stderr as processStderr } from "node:process";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
+
runCodegraphPostToolUseHookCli,
|
|
8
9
|
runCodegraphSessionStartHook,
|
|
9
10
|
runCodegraphSessionStartWorker,
|
|
11
|
+
type PostToolUseHookOptions,
|
|
10
12
|
type SessionStartHookOptions,
|
|
11
13
|
type SessionStartWorkerOptions,
|
|
12
14
|
} from "./hook.js";
|
|
@@ -25,6 +27,15 @@ export async function runCodegraphCli(options: RunCodegraphCliOptions = {}): Pro
|
|
|
25
27
|
return runCodegraphSessionStartHook(options);
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
if (command === "hook" && subcommand === "post-tool-use") {
|
|
31
|
+
const hookOptions: PostToolUseHookOptions = {
|
|
32
|
+
...(options.env === undefined ? {} : { env: options.env }),
|
|
33
|
+
...(options.stdin === undefined ? {} : { stdin: options.stdin }),
|
|
34
|
+
...(options.stdout === undefined ? {} : { stdout: options.stdout }),
|
|
35
|
+
};
|
|
36
|
+
return runCodegraphPostToolUseHookCli(hookOptions);
|
|
37
|
+
}
|
|
38
|
+
|
|
28
39
|
if (command === "hook" && subcommand === "session-start-worker") {
|
|
29
40
|
const workerOptions: SessionStartWorkerOptions = {
|
|
30
41
|
...options.workerOptions,
|
|
@@ -10,6 +10,7 @@ import type { CodegraphWorkspacePreparation as SharedCodegraphWorkspacePreparati
|
|
|
10
10
|
import type { CodegraphConfig as SharedCodegraphConfig } from "../../../../../utils/src/omo-config.ts";
|
|
11
11
|
|
|
12
12
|
export type SessionStartAction = "skipped-disabled" | "spawned";
|
|
13
|
+
export type PostToolUseAction = "emitted-guidance" | "skipped";
|
|
13
14
|
export type WorkerAction = "failed" | "initialized" | "skipped-disabled" | "skipped-status" | "skipped-unavailable" | "skipped-unsupported-node" | "synced";
|
|
14
15
|
|
|
15
16
|
export interface WorkerSpawnInvocation {
|
|
@@ -27,6 +28,11 @@ export interface SessionStartHookResult {
|
|
|
27
28
|
readonly exitCode: 0;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
export interface PostToolUseHookResult {
|
|
32
|
+
readonly action: PostToolUseAction;
|
|
33
|
+
readonly exitCode: 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
30
36
|
export interface CodegraphCommandResult {
|
|
31
37
|
readonly exitCode: number;
|
|
32
38
|
readonly stderr?: string;
|
|
@@ -73,6 +79,12 @@ export interface SessionStartHookOptions {
|
|
|
73
79
|
readonly workerCliPath?: string;
|
|
74
80
|
}
|
|
75
81
|
|
|
82
|
+
export interface PostToolUseHookOptions {
|
|
83
|
+
readonly env?: Record<string, string | undefined>;
|
|
84
|
+
readonly stdin?: Readable & { readonly isTTY?: boolean };
|
|
85
|
+
readonly stdout?: HookStdout;
|
|
86
|
+
}
|
|
87
|
+
|
|
76
88
|
export interface SessionStartWorkerOptions {
|
|
77
89
|
readonly config?: CodexOmoConfig;
|
|
78
90
|
readonly cwd?: string;
|
|
@@ -4,10 +4,13 @@ import { cwd as processCwd, env as processEnv, stdin as processStdin, stdout as
|
|
|
4
4
|
import type { Readable } from "node:stream";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
+
import { buildCodegraphInitGuidanceForToolResult } from "../../../../../utils/src/codegraph/guidance.ts";
|
|
7
8
|
import { getCodexOmoConfig } from "../../../shared/src/config-loader.ts";
|
|
8
9
|
import { SESSION_START_CWD_ENV } from "./session-start-worker.js";
|
|
9
10
|
import type {
|
|
10
11
|
HookStdout,
|
|
12
|
+
PostToolUseHookOptions,
|
|
13
|
+
PostToolUseHookResult,
|
|
11
14
|
SessionStartHookOptions,
|
|
12
15
|
SessionStartHookResult,
|
|
13
16
|
WorkerSpawnInvocation,
|
|
@@ -23,6 +26,8 @@ export type {
|
|
|
23
26
|
CodexOmoConfig,
|
|
24
27
|
HookStdout,
|
|
25
28
|
OmoConfigSource,
|
|
29
|
+
PostToolUseHookOptions,
|
|
30
|
+
PostToolUseHookResult,
|
|
26
31
|
SessionStartAction,
|
|
27
32
|
SessionStartHookOptions,
|
|
28
33
|
SessionStartHookResult,
|
|
@@ -38,6 +43,10 @@ export async function runCodegraphSessionStartHook(options: SessionStartHookOpti
|
|
|
38
43
|
return (await executeCodegraphSessionStartHook(options)).exitCode;
|
|
39
44
|
}
|
|
40
45
|
|
|
46
|
+
export async function runCodegraphPostToolUseHookCli(options: PostToolUseHookOptions = {}): Promise<number> {
|
|
47
|
+
return (await executeCodegraphPostToolUseHook(options)).exitCode;
|
|
48
|
+
}
|
|
49
|
+
|
|
41
50
|
export async function executeCodegraphSessionStartHook(options: SessionStartHookOptions = {}): Promise<SessionStartHookResult> {
|
|
42
51
|
const env = options.env ?? processEnv;
|
|
43
52
|
const input = await readHookInput(options.stdin ?? processStdin);
|
|
@@ -58,6 +67,31 @@ export async function executeCodegraphSessionStartHook(options: SessionStartHook
|
|
|
58
67
|
return { action: "spawned", exitCode: 0 };
|
|
59
68
|
}
|
|
60
69
|
|
|
70
|
+
export async function executeCodegraphPostToolUseHook(options: PostToolUseHookOptions = {}): Promise<PostToolUseHookResult> {
|
|
71
|
+
const env = options.env ?? processEnv;
|
|
72
|
+
const input = await readHookInput(options.stdin ?? processStdin);
|
|
73
|
+
const output = runCodegraphPostToolUseHook(input, { homeDir: resolveHomeDir(env) });
|
|
74
|
+
if (output.length === 0) return { action: "skipped", exitCode: 0 };
|
|
75
|
+
|
|
76
|
+
(options.stdout ?? processStdout).write(output);
|
|
77
|
+
return { action: "emitted-guidance", exitCode: 0 };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function runCodegraphPostToolUseHook(input: unknown, options: { readonly homeDir?: string } = {}): string {
|
|
81
|
+
const toolName = isRecord(input) ? input["tool_name"] : undefined;
|
|
82
|
+
const cwd = isRecord(input) ? input["cwd"] : undefined;
|
|
83
|
+
const toolOutput = isRecord(input) ? (input["tool_response"] ?? input["tool_output"] ?? input["response"]) : input;
|
|
84
|
+
const guidance = buildCodegraphInitGuidanceForToolResult({ cwd, toolName, toolOutput }, options);
|
|
85
|
+
if (guidance === null) return "";
|
|
86
|
+
|
|
87
|
+
return `${JSON.stringify({
|
|
88
|
+
hookSpecificOutput: {
|
|
89
|
+
hookEventName: "PostToolUse",
|
|
90
|
+
additionalContext: guidance,
|
|
91
|
+
},
|
|
92
|
+
})}\n`;
|
|
93
|
+
}
|
|
94
|
+
|
|
61
95
|
function writeHookJson(stdout: HookStdout): void {
|
|
62
96
|
const output = {
|
|
63
97
|
hookSpecificOutput: {
|