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
|
@@ -8,13 +8,205 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
|
8
8
|
|
|
9
9
|
// components/codegraph/src/hook.ts
|
|
10
10
|
import { spawn } from "node:child_process";
|
|
11
|
-
import { homedir as
|
|
11
|
+
import { homedir as homedir8 } from "node:os";
|
|
12
12
|
import { cwd as processCwd2, env as processEnv2, stdin as processStdin, stdout as processStdout } from "node:process";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
14
|
|
|
15
|
-
// ../../utils/src/
|
|
16
|
-
import {
|
|
15
|
+
// ../../utils/src/codegraph/guidance.ts
|
|
16
|
+
import { homedir as homedir2 } from "node:os";
|
|
17
|
+
|
|
18
|
+
// ../../utils/src/codegraph/workspace.ts
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
import {
|
|
21
|
+
appendFileSync,
|
|
22
|
+
existsSync,
|
|
23
|
+
lstatSync,
|
|
24
|
+
mkdirSync,
|
|
25
|
+
readFileSync,
|
|
26
|
+
readdirSync,
|
|
27
|
+
realpathSync,
|
|
28
|
+
rmSync,
|
|
29
|
+
statSync,
|
|
30
|
+
symlinkSync
|
|
31
|
+
} from "node:fs";
|
|
17
32
|
import { homedir } from "node:os";
|
|
33
|
+
import { basename, join, resolve } from "node:path";
|
|
34
|
+
function sanitizeBase(value) {
|
|
35
|
+
const sanitized = value.replace(/[^A-Za-z0-9._-]/g, "-").replace(/-+/g, "-");
|
|
36
|
+
return sanitized.length > 0 ? sanitized : "workspace";
|
|
37
|
+
}
|
|
38
|
+
function codegraphDataRoot(homeDir) {
|
|
39
|
+
return join(homeDir, ".omo", "codegraph");
|
|
40
|
+
}
|
|
41
|
+
function workspaceStorageName(workspace) {
|
|
42
|
+
const resolved = resolve(workspace);
|
|
43
|
+
const hash = createHash("sha256").update(resolved).digest("hex").slice(0, 16);
|
|
44
|
+
return `${sanitizeBase(basename(resolved))}-${hash}`;
|
|
45
|
+
}
|
|
46
|
+
function resolveCodegraphWorkspacePaths(workspace, options = {}) {
|
|
47
|
+
const resolvedWorkspace = resolve(workspace);
|
|
48
|
+
const dataRoot = codegraphDataRoot(options.homeDir ?? homedir());
|
|
49
|
+
return {
|
|
50
|
+
dataDir: join(dataRoot, "projects", workspaceStorageName(resolvedWorkspace)),
|
|
51
|
+
dataRoot,
|
|
52
|
+
projectLink: join(resolvedWorkspace, ".codegraph")
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function fallbackResult(dataRoot, projectLink, reason) {
|
|
56
|
+
return { dataDir: projectLink, dataRoot, linked: false, mode: "in-place-fallback", projectLink, reason };
|
|
57
|
+
}
|
|
58
|
+
function isSameFilesystem(workspace, dataRoot, override) {
|
|
59
|
+
if (override !== undefined)
|
|
60
|
+
return override;
|
|
61
|
+
return statSync(workspace).dev === statSync(dataRoot).dev;
|
|
62
|
+
}
|
|
63
|
+
function ensureInPlaceFallback(projectLink) {
|
|
64
|
+
if (!existsSync(projectLink))
|
|
65
|
+
mkdirSync(projectLink, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
function prepareCodegraphWorkspace(workspace, options = {}) {
|
|
68
|
+
const resolvedWorkspace = resolve(workspace);
|
|
69
|
+
const { dataDir, dataRoot, projectLink } = resolveCodegraphWorkspacePaths(resolvedWorkspace, options);
|
|
70
|
+
try {
|
|
71
|
+
mkdirSync(dataDir, { recursive: true });
|
|
72
|
+
if (existsSync(projectLink)) {
|
|
73
|
+
const linkStat = lstatSync(projectLink);
|
|
74
|
+
if (!linkStat.isSymbolicLink()) {
|
|
75
|
+
return { dataDir: projectLink, dataRoot, linked: false, mode: "in-project", projectLink };
|
|
76
|
+
}
|
|
77
|
+
if (realpathSync(projectLink) === realpathSync(dataDir)) {
|
|
78
|
+
return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
|
|
79
|
+
}
|
|
80
|
+
return fallbackResult(dataRoot, projectLink, "existing .codegraph symlink points outside OMO store");
|
|
81
|
+
}
|
|
82
|
+
if (!isSameFilesystem(resolvedWorkspace, dataRoot, options.sameFilesystem)) {
|
|
83
|
+
ensureInPlaceFallback(projectLink);
|
|
84
|
+
return fallbackResult(dataRoot, projectLink, "workspace and OMO store are on different filesystems");
|
|
85
|
+
}
|
|
86
|
+
const symlink = options.symlink ?? symlinkSync;
|
|
87
|
+
symlink(dataDir, projectLink, (options.platform ?? process.platform) === "win32" ? "junction" : "dir");
|
|
88
|
+
return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
|
|
89
|
+
} catch (error) {
|
|
90
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
91
|
+
try {
|
|
92
|
+
ensureInPlaceFallback(projectLink);
|
|
93
|
+
} catch (fallbackError) {
|
|
94
|
+
return fallbackResult(dataRoot, projectLink, `${reason}; fallback failed: ${String(fallbackError)}`);
|
|
95
|
+
}
|
|
96
|
+
return fallbackResult(dataRoot, projectLink, reason);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function ensureCodegraphGitignored(workspace) {
|
|
100
|
+
const gitDir = join(workspace, ".git");
|
|
101
|
+
if (!existsSync(gitDir))
|
|
102
|
+
return false;
|
|
103
|
+
const excludePath = join(gitDir, "info", "exclude");
|
|
104
|
+
try {
|
|
105
|
+
mkdirSync(join(gitDir, "info"), { recursive: true });
|
|
106
|
+
const existing = existsSync(excludePath) ? readFileSync(excludePath, "utf8") : "";
|
|
107
|
+
if (existing.split(/\r?\n/).includes(".codegraph"))
|
|
108
|
+
return true;
|
|
109
|
+
appendFileSync(excludePath, `${existing.endsWith(`
|
|
110
|
+
`) || existing.length === 0 ? "" : `
|
|
111
|
+
`}.codegraph
|
|
112
|
+
`);
|
|
113
|
+
return true;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (error instanceof Error)
|
|
116
|
+
return false;
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ../../utils/src/codegraph/guidance.ts
|
|
122
|
+
var CODEGRAPH_UNINITIALIZED_PATTERN = /CodeGraph not initialized in ([\s\S]*?)\.\s*Run ['`]codegraph init['`] in that project first\./i;
|
|
123
|
+
var ANSI_ESCAPE_PATTERN = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
|
|
124
|
+
var CODEGRAPH_STATUS_PROJECT_PATTERN = /^.*?\bProject:\s*(.+?)\s*$/im;
|
|
125
|
+
var CODEGRAPH_STATUS_UNINITIALIZED_PATTERN = /^.*?\bNot initialized\s*$/im;
|
|
126
|
+
var CODEGRAPH_INIT_HINT_PATTERN = /Run\s+["'`]codegraph init["'`]\s+(?:in that project first|to initialize)\.?/i;
|
|
127
|
+
function getCodegraphUninitializedProject(input) {
|
|
128
|
+
const output = textFromUnknown(input.toolOutput);
|
|
129
|
+
if (!isCodegraphTool(input.toolName))
|
|
130
|
+
return null;
|
|
131
|
+
const projectPath = extractProjectPath(output);
|
|
132
|
+
if (projectPath !== null)
|
|
133
|
+
return projectPath;
|
|
134
|
+
if (!looksLikeCodegraphUninitializedOutput(output))
|
|
135
|
+
return null;
|
|
136
|
+
return typeof input.cwd === "string" && input.cwd.trim().length > 0 ? input.cwd.trim() : null;
|
|
137
|
+
}
|
|
138
|
+
function buildCodegraphInitGuidance(projectPath, options = {}) {
|
|
139
|
+
const { dataDir, dataRoot, projectLink } = resolveCodegraphWorkspacePaths(projectPath, {
|
|
140
|
+
homeDir: options.homeDir ?? homedir2()
|
|
141
|
+
});
|
|
142
|
+
const displayProjectPath = formatDisplayPath(projectPath);
|
|
143
|
+
const displayProjectLink = formatDisplayPath(projectLink);
|
|
144
|
+
const displayDataDir = formatDisplayPath(dataDir);
|
|
145
|
+
const displayDataRoot = formatDisplayPath(dataRoot);
|
|
146
|
+
return [
|
|
147
|
+
"OMO CodeGraph initialization guidance:",
|
|
148
|
+
"",
|
|
149
|
+
`CodeGraph is not initialized for ${displayProjectPath}. Initialize it through OMO's global local store instead of leaving a standalone project-local index.`,
|
|
150
|
+
"",
|
|
151
|
+
`- Link or create ${displayProjectLink} so it points at ${displayDataDir} under the OMO store ${displayDataRoot}.`,
|
|
152
|
+
`- Then run \`codegraph init\` from ${displayProjectPath} and retry the CodeGraph tool.`,
|
|
153
|
+
"- OMO's CodeGraph bootstrap does this automatically on session start; if bootstrap just ran, wait for it to finish and retry."
|
|
154
|
+
].join(`
|
|
155
|
+
`);
|
|
156
|
+
}
|
|
157
|
+
function buildCodegraphInitGuidanceForToolResult(input, options = {}) {
|
|
158
|
+
const projectPath = getCodegraphUninitializedProject(input);
|
|
159
|
+
return projectPath === null ? null : buildCodegraphInitGuidance(projectPath, options);
|
|
160
|
+
}
|
|
161
|
+
function extractProjectPath(output) {
|
|
162
|
+
const normalizedOutput = normalizeCodegraphOutput(output);
|
|
163
|
+
const uninitializedMatch = normalizedOutput.match(CODEGRAPH_UNINITIALIZED_PATTERN);
|
|
164
|
+
const uninitializedProject = uninitializedMatch?.[1]?.trim();
|
|
165
|
+
if (uninitializedProject && uninitializedProject.length > 0)
|
|
166
|
+
return uninitializedProject;
|
|
167
|
+
if (!looksLikeCodegraphUninitializedOutput(normalizedOutput))
|
|
168
|
+
return null;
|
|
169
|
+
const statusMatch = normalizedOutput.match(CODEGRAPH_STATUS_PROJECT_PATTERN);
|
|
170
|
+
const statusProject = statusMatch?.[1]?.trim();
|
|
171
|
+
return statusProject && statusProject.length > 0 ? statusProject : null;
|
|
172
|
+
}
|
|
173
|
+
function looksLikeCodegraphUninitializedOutput(output) {
|
|
174
|
+
const normalizedOutput = normalizeCodegraphOutput(output);
|
|
175
|
+
if (normalizedOutput.match(CODEGRAPH_UNINITIALIZED_PATTERN) !== null)
|
|
176
|
+
return true;
|
|
177
|
+
return CODEGRAPH_STATUS_UNINITIALIZED_PATTERN.test(normalizedOutput) && CODEGRAPH_INIT_HINT_PATTERN.test(normalizedOutput);
|
|
178
|
+
}
|
|
179
|
+
function normalizeCodegraphOutput(output) {
|
|
180
|
+
return output.replace(ANSI_ESCAPE_PATTERN, "");
|
|
181
|
+
}
|
|
182
|
+
function isCodegraphTool(toolName) {
|
|
183
|
+
if (typeof toolName !== "string")
|
|
184
|
+
return false;
|
|
185
|
+
return toolName.startsWith("codegraph.") || toolName.startsWith("codegraph_") || toolName.startsWith("mcp__codegraph__");
|
|
186
|
+
}
|
|
187
|
+
function formatDisplayPath(value) {
|
|
188
|
+
return JSON.stringify(value);
|
|
189
|
+
}
|
|
190
|
+
function textFromUnknown(value) {
|
|
191
|
+
if (typeof value === "string")
|
|
192
|
+
return value;
|
|
193
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint")
|
|
194
|
+
return String(value);
|
|
195
|
+
if (Array.isArray(value))
|
|
196
|
+
return value.map(textFromUnknown).filter(Boolean).join(`
|
|
197
|
+
`);
|
|
198
|
+
if (!isRecord(value))
|
|
199
|
+
return "";
|
|
200
|
+
return Object.entries(value).map(([key, nested]) => `${key}: ${textFromUnknown(nested)}`).filter((line) => line.trim().length > 0).join(`
|
|
201
|
+
`);
|
|
202
|
+
}
|
|
203
|
+
function isRecord(value) {
|
|
204
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ../../utils/src/omo-config/loader.ts
|
|
208
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
209
|
+
import { homedir as homedir3 } from "node:os";
|
|
18
210
|
|
|
19
211
|
// ../../utils/src/deep-merge.ts
|
|
20
212
|
var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -970,22 +1162,22 @@ function buildEnvOverrides(harness, env, warnings, merge) {
|
|
|
970
1162
|
}
|
|
971
1163
|
|
|
972
1164
|
// ../../utils/src/omo-config/resolve.ts
|
|
973
|
-
import { existsSync } from "node:fs";
|
|
974
|
-
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
1165
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
1166
|
+
import { dirname, isAbsolute, join as join2, relative, resolve as resolve2 } from "node:path";
|
|
975
1167
|
function containsPath(parent, child) {
|
|
976
1168
|
const pathToChild = relative(parent, child);
|
|
977
1169
|
return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute(pathToChild);
|
|
978
1170
|
}
|
|
979
1171
|
function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
980
|
-
const startDir =
|
|
981
|
-
const stopBeforeDir = containsPath(
|
|
1172
|
+
const startDir = resolve2(cwd);
|
|
1173
|
+
const stopBeforeDir = containsPath(resolve2(homeDir), startDir) ? resolve2(homeDir) : null;
|
|
982
1174
|
const paths = [];
|
|
983
1175
|
let currentDir = startDir;
|
|
984
1176
|
while (true) {
|
|
985
1177
|
if (stopBeforeDir !== null && currentDir === stopBeforeDir)
|
|
986
1178
|
break;
|
|
987
|
-
const configPath =
|
|
988
|
-
if (
|
|
1179
|
+
const configPath = join2(currentDir, ".omo", "config.jsonc");
|
|
1180
|
+
if (existsSync2(configPath)) {
|
|
989
1181
|
paths.push(configPath);
|
|
990
1182
|
}
|
|
991
1183
|
const parentDir = dirname(currentDir);
|
|
@@ -996,7 +1188,7 @@ function findProjectConfigPathsNearestFirst(cwd, homeDir) {
|
|
|
996
1188
|
return paths;
|
|
997
1189
|
}
|
|
998
1190
|
function resolveOmoConfigPaths(options) {
|
|
999
|
-
const globalPath =
|
|
1191
|
+
const globalPath = join2(resolve2(options.homeDir), ".omo", "config.jsonc");
|
|
1000
1192
|
const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
|
|
1001
1193
|
return [
|
|
1002
1194
|
{ path: globalPath, scope: "global" },
|
|
@@ -1028,7 +1220,7 @@ var CODEGRAPH_SETTING_KEYS = [
|
|
|
1028
1220
|
"telemetry",
|
|
1029
1221
|
"watch_debounce_ms"
|
|
1030
1222
|
];
|
|
1031
|
-
function
|
|
1223
|
+
function isRecord2(value) {
|
|
1032
1224
|
return isPlainObject(value);
|
|
1033
1225
|
}
|
|
1034
1226
|
function hasOwn(record, key) {
|
|
@@ -1056,7 +1248,7 @@ function mergeValues(base, override) {
|
|
|
1056
1248
|
}
|
|
1057
1249
|
function mergeCodegraphConfig(base, override) {
|
|
1058
1250
|
const merged = mergeValues(base, override);
|
|
1059
|
-
if (!
|
|
1251
|
+
if (!isRecord2(merged))
|
|
1060
1252
|
return;
|
|
1061
1253
|
const codegraph = {};
|
|
1062
1254
|
for (const key of CODEGRAPH_SETTING_KEYS) {
|
|
@@ -1111,7 +1303,7 @@ function setCodegraphSetting2(config, key, value) {
|
|
|
1111
1303
|
}
|
|
1112
1304
|
}
|
|
1113
1305
|
function normalizeCodegraphSection(section, pathPrefix, warnings) {
|
|
1114
|
-
if (!
|
|
1306
|
+
if (!isRecord2(section)) {
|
|
1115
1307
|
warnings.push(`${pathPrefix} must be an object`);
|
|
1116
1308
|
return {};
|
|
1117
1309
|
}
|
|
@@ -1131,7 +1323,7 @@ function normalizeCodegraphSection(section, pathPrefix, warnings) {
|
|
|
1131
1323
|
return codegraph;
|
|
1132
1324
|
}
|
|
1133
1325
|
function normalizeConfigBody(value, pathPrefix, warnings) {
|
|
1134
|
-
if (!
|
|
1326
|
+
if (!isRecord2(value)) {
|
|
1135
1327
|
warnings.push(`${pathPrefix} must be an object`);
|
|
1136
1328
|
return {};
|
|
1137
1329
|
}
|
|
@@ -1152,7 +1344,7 @@ function normalizeConfigBody(value, pathPrefix, warnings) {
|
|
|
1152
1344
|
return config;
|
|
1153
1345
|
}
|
|
1154
1346
|
function normalizeActiveHarnessBlock(value, harness, pathPrefix, warnings) {
|
|
1155
|
-
if (!
|
|
1347
|
+
if (!isRecord2(value))
|
|
1156
1348
|
return {};
|
|
1157
1349
|
const blockKey = `[${harness}]`;
|
|
1158
1350
|
if (!hasOwn(value, blockKey))
|
|
@@ -1161,7 +1353,7 @@ function normalizeActiveHarnessBlock(value, harness, pathPrefix, warnings) {
|
|
|
1161
1353
|
}
|
|
1162
1354
|
function loadConfigFile(path, harness) {
|
|
1163
1355
|
try {
|
|
1164
|
-
const content =
|
|
1356
|
+
const content = readFileSync2(path, "utf-8");
|
|
1165
1357
|
const parsed = parseJsoncSafe(content);
|
|
1166
1358
|
if (parsed.errors.length > 0) {
|
|
1167
1359
|
return {
|
|
@@ -1207,13 +1399,13 @@ function validateHarnessApplicability(config, harness) {
|
|
|
1207
1399
|
}
|
|
1208
1400
|
function loadOmoConfig(options) {
|
|
1209
1401
|
const cwd = options.cwd ?? process.cwd();
|
|
1210
|
-
const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ??
|
|
1402
|
+
const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ?? homedir3();
|
|
1211
1403
|
const env = options.env ?? process.env;
|
|
1212
1404
|
let config = BUILT_IN_DEFAULTS;
|
|
1213
1405
|
const sources = [];
|
|
1214
1406
|
const warnings = [];
|
|
1215
1407
|
for (const candidate of resolveOmoConfigPaths({ cwd, homeDir })) {
|
|
1216
|
-
if (!
|
|
1408
|
+
if (!existsSync3(candidate.path)) {
|
|
1217
1409
|
if (candidate.scope === "global") {
|
|
1218
1410
|
sources.push(toMissingSource(candidate));
|
|
1219
1411
|
}
|
|
@@ -1253,21 +1445,21 @@ function getCodexOmoConfig(options = {}) {
|
|
|
1253
1445
|
// components/codegraph/src/session-start-worker.ts
|
|
1254
1446
|
import { execFile as execFile2 } from "node:child_process";
|
|
1255
1447
|
import { appendFileSync as appendFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "node:fs";
|
|
1256
|
-
import { homedir as
|
|
1448
|
+
import { homedir as homedir7 } from "node:os";
|
|
1257
1449
|
import { extname, join as join7 } from "node:path";
|
|
1258
1450
|
import { cwd as processCwd, env as processEnv, stderr as processStderr } from "node:process";
|
|
1259
1451
|
|
|
1260
1452
|
// ../../utils/src/codegraph/env.ts
|
|
1261
|
-
import { homedir as
|
|
1262
|
-
import { join as
|
|
1453
|
+
import { homedir as homedir4 } from "node:os";
|
|
1454
|
+
import { join as join3 } from "node:path";
|
|
1263
1455
|
var CODEGRAPH_INSTALL_DIR_ENV = "CODEGRAPH_INSTALL_DIR";
|
|
1264
1456
|
var CODEGRAPH_NO_DOWNLOAD_ENV = "CODEGRAPH_NO_DOWNLOAD";
|
|
1265
1457
|
var CODEGRAPH_TELEMETRY_ENV = "CODEGRAPH_TELEMETRY";
|
|
1266
1458
|
var DO_NOT_TRACK_ENV = "DO_NOT_TRACK";
|
|
1267
1459
|
function buildCodegraphEnv(options = {}) {
|
|
1268
|
-
const homeDir = options.homeDir ??
|
|
1460
|
+
const homeDir = options.homeDir ?? homedir4();
|
|
1269
1461
|
return {
|
|
1270
|
-
[CODEGRAPH_INSTALL_DIR_ENV]:
|
|
1462
|
+
[CODEGRAPH_INSTALL_DIR_ENV]: join3(homeDir, ".omo", "codegraph"),
|
|
1271
1463
|
[CODEGRAPH_NO_DOWNLOAD_ENV]: "1",
|
|
1272
1464
|
[CODEGRAPH_TELEMETRY_ENV]: "0",
|
|
1273
1465
|
[DO_NOT_TRACK_ENV]: "1"
|
|
@@ -1304,12 +1496,12 @@ function parseNodeMajor(version) {
|
|
|
1304
1496
|
}
|
|
1305
1497
|
|
|
1306
1498
|
// ../../utils/src/codegraph/provision.ts
|
|
1307
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
1499
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
1308
1500
|
import { execFile } from "node:child_process";
|
|
1309
1501
|
import { chmod, mkdir, readdir, readFile, rename, rm, rmdir, stat, writeFile } from "node:fs/promises";
|
|
1310
|
-
import { existsSync as
|
|
1311
|
-
import { homedir as
|
|
1312
|
-
import { basename, join as
|
|
1502
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
1503
|
+
import { homedir as homedir5, hostname } from "node:os";
|
|
1504
|
+
import { basename as basename2, join as join4 } from "node:path";
|
|
1313
1505
|
import { promisify } from "node:util";
|
|
1314
1506
|
|
|
1315
1507
|
// ../../utils/src/codegraph/manifest.ts
|
|
@@ -1358,13 +1550,13 @@ function platformKey() {
|
|
|
1358
1550
|
return `${process.platform}-${process.arch}`;
|
|
1359
1551
|
}
|
|
1360
1552
|
function markerPath(installDir, version) {
|
|
1361
|
-
return
|
|
1553
|
+
return join4(installDir, ".provisioned", `codegraph-${version}.json`);
|
|
1362
1554
|
}
|
|
1363
1555
|
function defaultInstallDir() {
|
|
1364
|
-
return
|
|
1556
|
+
return join4(homedir5(), ".omo", "codegraph");
|
|
1365
1557
|
}
|
|
1366
1558
|
function sha256(bytes) {
|
|
1367
|
-
return
|
|
1559
|
+
return createHash2("sha256").update(bytes).digest("hex");
|
|
1368
1560
|
}
|
|
1369
1561
|
function isErrnoException(error) {
|
|
1370
1562
|
return error instanceof Error && "code" in error;
|
|
@@ -1381,7 +1573,7 @@ async function removeEmptyDirectory(path) {
|
|
|
1381
1573
|
}
|
|
1382
1574
|
}
|
|
1383
1575
|
function sleep(ms) {
|
|
1384
|
-
return new Promise((
|
|
1576
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
1385
1577
|
}
|
|
1386
1578
|
async function defaultDownloader(asset, timeoutMs = DEFAULT_DOWNLOAD_TIMEOUT_MS) {
|
|
1387
1579
|
const response = await fetch(asset.url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
@@ -1395,7 +1587,7 @@ function forcedBadChecksumOptions(options) {
|
|
|
1395
1587
|
const key = options.platformKey ?? platformKey();
|
|
1396
1588
|
return {
|
|
1397
1589
|
downloader: async () => new TextEncoder().encode("checksum mismatch"),
|
|
1398
|
-
installDir: options.installDir ??
|
|
1590
|
+
installDir: options.installDir ?? join4(options.lockDir, "codegraph-force-bad-checksum"),
|
|
1399
1591
|
manifest: {
|
|
1400
1592
|
assets: {
|
|
1401
1593
|
[key]: { executableName: process.platform === "win32" ? "codegraph.cmd" : "codegraph", sha256: "0000", url: "memory://bad" }
|
|
@@ -1406,13 +1598,13 @@ function forcedBadChecksumOptions(options) {
|
|
|
1406
1598
|
};
|
|
1407
1599
|
}
|
|
1408
1600
|
async function readMarker(path) {
|
|
1409
|
-
if (!
|
|
1601
|
+
if (!existsSync4(path))
|
|
1410
1602
|
return null;
|
|
1411
1603
|
try {
|
|
1412
1604
|
const raw = JSON.parse(await readFile(path, "utf8"));
|
|
1413
1605
|
if (typeof raw === "object" && raw !== null && "binPath" in raw) {
|
|
1414
1606
|
const value = raw.binPath;
|
|
1415
|
-
return typeof value === "string" &&
|
|
1607
|
+
return typeof value === "string" && existsSync4(value) ? value : null;
|
|
1416
1608
|
}
|
|
1417
1609
|
return null;
|
|
1418
1610
|
} catch (error) {
|
|
@@ -1423,7 +1615,7 @@ async function readMarker(path) {
|
|
|
1423
1615
|
}
|
|
1424
1616
|
async function acquireLock(lockPath, waitMs, staleMs) {
|
|
1425
1617
|
const startedAt = Date.now();
|
|
1426
|
-
await mkdir(
|
|
1618
|
+
await mkdir(join4(lockPath, ".."), { recursive: true });
|
|
1427
1619
|
while (Date.now() - startedAt <= waitMs) {
|
|
1428
1620
|
try {
|
|
1429
1621
|
await mkdir(lockPath);
|
|
@@ -1448,44 +1640,44 @@ async function installExtractedBundle(extractDir, installDir, executableName) {
|
|
|
1448
1640
|
const roots = await readdir(extractDir);
|
|
1449
1641
|
if (roots.length !== 1)
|
|
1450
1642
|
throw new Error(`CodeGraph archive should contain one root directory, found ${roots.length}`);
|
|
1451
|
-
const bundleDir =
|
|
1643
|
+
const bundleDir = join4(extractDir, roots[0] ?? "");
|
|
1452
1644
|
const bundleEntries = await readdir(bundleDir);
|
|
1453
1645
|
await mkdir(installDir, { recursive: true });
|
|
1454
1646
|
for (const entry of bundleEntries) {
|
|
1455
|
-
await rm(
|
|
1456
|
-
await rename(
|
|
1647
|
+
await rm(join4(installDir, entry), { force: true, recursive: true });
|
|
1648
|
+
await rename(join4(bundleDir, entry), join4(installDir, entry));
|
|
1457
1649
|
}
|
|
1458
|
-
const destination =
|
|
1459
|
-
if (!
|
|
1650
|
+
const destination = join4(installDir, "bin", executableName);
|
|
1651
|
+
if (!existsSync4(destination))
|
|
1460
1652
|
throw new Error(`CodeGraph archive did not contain bin/${executableName}`);
|
|
1461
1653
|
await chmod(destination, 493);
|
|
1462
1654
|
return destination;
|
|
1463
1655
|
}
|
|
1464
1656
|
async function installAsset(layout) {
|
|
1465
1657
|
const { asset, downloader, installDir, version } = layout;
|
|
1466
|
-
const stagingDir =
|
|
1467
|
-
const archivePath =
|
|
1468
|
-
const extractDir =
|
|
1658
|
+
const stagingDir = join4(installDir, ".staging", randomUUID());
|
|
1659
|
+
const archivePath = join4(stagingDir, basename2(asset.url));
|
|
1660
|
+
const extractDir = join4(stagingDir, "extract");
|
|
1469
1661
|
try {
|
|
1470
1662
|
await mkdir(extractDir, { recursive: true });
|
|
1471
1663
|
const bytes = await downloader(asset);
|
|
1472
1664
|
const actualChecksum = sha256(bytes);
|
|
1473
1665
|
if (actualChecksum !== asset.sha256) {
|
|
1474
|
-
throw new Error(`checksum mismatch for ${
|
|
1666
|
+
throw new Error(`checksum mismatch for ${basename2(asset.url)}: expected ${asset.sha256}, got ${actualChecksum}`);
|
|
1475
1667
|
}
|
|
1476
1668
|
if (!asset.url.endsWith(".tar.gz") && !asset.url.endsWith(".tgz")) {
|
|
1477
|
-
throw new Error(`unsupported CodeGraph archive type for ${
|
|
1669
|
+
throw new Error(`unsupported CodeGraph archive type for ${basename2(asset.url)}`);
|
|
1478
1670
|
}
|
|
1479
1671
|
await writeFile(archivePath, bytes);
|
|
1480
1672
|
await extractTarGz(archivePath, extractDir);
|
|
1481
1673
|
const destination = await installExtractedBundle(extractDir, installDir, asset.executableName);
|
|
1482
|
-
await mkdir(
|
|
1674
|
+
await mkdir(join4(installDir, ".provisioned"), { recursive: true });
|
|
1483
1675
|
await writeFile(markerPath(installDir, version), `${JSON.stringify({ binPath: destination, version })}
|
|
1484
1676
|
`);
|
|
1485
1677
|
return destination;
|
|
1486
1678
|
} finally {
|
|
1487
1679
|
await rm(stagingDir, { force: true, recursive: true });
|
|
1488
|
-
await removeEmptyDirectory(
|
|
1680
|
+
await removeEmptyDirectory(join4(installDir, ".staging"));
|
|
1489
1681
|
}
|
|
1490
1682
|
}
|
|
1491
1683
|
async function ensureCodegraphProvisioned(options) {
|
|
@@ -1498,7 +1690,7 @@ async function ensureCodegraphProvisioned(options) {
|
|
|
1498
1690
|
const existing = await readMarker(marker);
|
|
1499
1691
|
if (existing !== null)
|
|
1500
1692
|
return { binPath: existing, provisioned: true };
|
|
1501
|
-
const lockPath =
|
|
1693
|
+
const lockPath = join4(options.lockDir, `codegraph-${hostname()}.lock`);
|
|
1502
1694
|
const release = await acquireLock(lockPath, options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS, options.lockStaleMs ?? DEFAULT_LOCK_STALE_MS);
|
|
1503
1695
|
if (release === null)
|
|
1504
1696
|
return { error: "timed out waiting for codegraph provisioning lock", provisioned: false };
|
|
@@ -1523,15 +1715,15 @@ async function ensureCodegraphProvisioned(options) {
|
|
|
1523
1715
|
}
|
|
1524
1716
|
|
|
1525
1717
|
// ../../utils/src/codegraph/resolve.ts
|
|
1526
|
-
import { existsSync as
|
|
1527
|
-
import { homedir as
|
|
1718
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
1719
|
+
import { homedir as homedir6 } from "node:os";
|
|
1528
1720
|
import { spawnSync } from "node:child_process";
|
|
1529
|
-
import { basename as
|
|
1721
|
+
import { basename as basename3, dirname as dirname2, join as join6 } from "node:path";
|
|
1530
1722
|
import { createRequire } from "node:module";
|
|
1531
1723
|
|
|
1532
1724
|
// ../../utils/src/runtime/which.ts
|
|
1533
1725
|
import { accessSync, constants } from "node:fs";
|
|
1534
|
-
import { delimiter, join as
|
|
1726
|
+
import { delimiter, join as join5 } from "node:path";
|
|
1535
1727
|
var runtime = globalThis;
|
|
1536
1728
|
function isUnsafeCommandName(commandName) {
|
|
1537
1729
|
if (commandName.includes("/") || commandName.includes("\\"))
|
|
@@ -1586,7 +1778,7 @@ function bunWhich(commandName) {
|
|
|
1586
1778
|
return null;
|
|
1587
1779
|
for (const pathEntry of pathEntries) {
|
|
1588
1780
|
for (const candidateName of candidateNames) {
|
|
1589
|
-
const candidatePath =
|
|
1781
|
+
const candidatePath = join5(pathEntry, candidateName);
|
|
1590
1782
|
if (isExecutable(candidatePath))
|
|
1591
1783
|
return candidatePath;
|
|
1592
1784
|
}
|
|
@@ -1595,6 +1787,9 @@ function bunWhich(commandName) {
|
|
|
1595
1787
|
}
|
|
1596
1788
|
|
|
1597
1789
|
// ../../utils/src/codegraph/resolve.ts
|
|
1790
|
+
function codegraphCommandRequiresSupportedLocalNode(resolution) {
|
|
1791
|
+
return resolution.source !== "bundled" && resolution.source !== "env" && resolution.source !== "provisioned";
|
|
1792
|
+
}
|
|
1598
1793
|
var CODEGRAPH_PACKAGE = "@colbymchenry/codegraph";
|
|
1599
1794
|
var CODEGRAPH_ENV_BIN = "OMO_CODEGRAPH_BIN";
|
|
1600
1795
|
var CODEGRAPH_LEGACY_ENV_BIN = "CODEGRAPH_BIN";
|
|
@@ -1624,7 +1819,7 @@ ${result.stderr}`.trim().split(/\s+/)[0];
|
|
|
1624
1819
|
}
|
|
1625
1820
|
}
|
|
1626
1821
|
function isNodeExecutableName(filePath) {
|
|
1627
|
-
const executable =
|
|
1822
|
+
const executable = basename3(filePath).toLowerCase();
|
|
1628
1823
|
return executable === "node" || executable === "node.exe" || /^node\d+(\.exe)?$/.test(executable);
|
|
1629
1824
|
}
|
|
1630
1825
|
function looksLikePath(command) {
|
|
@@ -1664,8 +1859,8 @@ function defaultNodeRuntime(env, fileExists, which, nodeVersion) {
|
|
|
1664
1859
|
function defaultProvisionedBin(homeDir, fileExists) {
|
|
1665
1860
|
const binaryName = process.platform === "win32" ? "codegraph.cmd" : "codegraph";
|
|
1666
1861
|
const candidates = [
|
|
1667
|
-
|
|
1668
|
-
|
|
1862
|
+
join6(homeDir, ".omo", "codegraph", "bin", binaryName),
|
|
1863
|
+
join6(homeDir, ".omo", "codegraph", "node-servers", "node_modules", ".bin", binaryName)
|
|
1669
1864
|
];
|
|
1670
1865
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
1671
1866
|
}
|
|
@@ -1673,7 +1868,7 @@ function resolveBundledShim(requireResolve, fileExists) {
|
|
|
1673
1868
|
try {
|
|
1674
1869
|
const packageJson = requireResolve(`${CODEGRAPH_PACKAGE}/package.json`);
|
|
1675
1870
|
const packageRoot = dirname2(packageJson);
|
|
1676
|
-
const candidates = [
|
|
1871
|
+
const candidates = [join6(packageRoot, "bin", "codegraph.js"), join6(packageRoot, "npm-shim.js")];
|
|
1677
1872
|
return candidates.find((candidate) => fileExists(candidate)) ?? null;
|
|
1678
1873
|
} catch (error) {
|
|
1679
1874
|
if (error instanceof Error)
|
|
@@ -1689,7 +1884,7 @@ function resolveBundledShim(requireResolve, fileExists) {
|
|
|
1689
1884
|
}
|
|
1690
1885
|
function resolveCodegraphCommand(options = {}) {
|
|
1691
1886
|
const env = options.env ?? process.env;
|
|
1692
|
-
const fileExists = options.fileExists ??
|
|
1887
|
+
const fileExists = options.fileExists ?? existsSync5;
|
|
1693
1888
|
const configuredBin = env[CODEGRAPH_ENV_BIN]?.trim() || env[CODEGRAPH_LEGACY_ENV_BIN]?.trim();
|
|
1694
1889
|
if (configuredBin !== undefined && configuredBin.length > 0) {
|
|
1695
1890
|
return { argsPrefix: [], command: configuredBin, exists: fileExists(configuredBin), source: "env" };
|
|
@@ -1701,7 +1896,7 @@ function resolveCodegraphCommand(options = {}) {
|
|
|
1701
1896
|
if (bundled !== null && runtime2 !== null) {
|
|
1702
1897
|
return { argsPrefix: [bundled], command: runtime2, exists: true, source: "bundled" };
|
|
1703
1898
|
}
|
|
1704
|
-
const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ??
|
|
1899
|
+
const provisioned = options.provisioned?.() ?? defaultProvisionedBin(options.homeDir ?? homedir6(), fileExists);
|
|
1705
1900
|
if (provisioned !== null && fileExists(provisioned)) {
|
|
1706
1901
|
return { argsPrefix: [], command: provisioned, exists: true, source: "provisioned" };
|
|
1707
1902
|
}
|
|
@@ -1714,102 +1909,6 @@ function resolveCodegraphCommand(options = {}) {
|
|
|
1714
1909
|
};
|
|
1715
1910
|
}
|
|
1716
1911
|
|
|
1717
|
-
// ../../utils/src/codegraph/workspace.ts
|
|
1718
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
1719
|
-
import {
|
|
1720
|
-
appendFileSync,
|
|
1721
|
-
existsSync as existsSync5,
|
|
1722
|
-
lstatSync,
|
|
1723
|
-
mkdirSync,
|
|
1724
|
-
readFileSync as readFileSync2,
|
|
1725
|
-
readdirSync,
|
|
1726
|
-
realpathSync,
|
|
1727
|
-
rmSync,
|
|
1728
|
-
statSync,
|
|
1729
|
-
symlinkSync
|
|
1730
|
-
} from "node:fs";
|
|
1731
|
-
import { homedir as homedir5 } from "node:os";
|
|
1732
|
-
import { basename as basename3, join as join6, resolve as resolve2 } from "node:path";
|
|
1733
|
-
function sanitizeBase(value) {
|
|
1734
|
-
const sanitized = value.replace(/[^A-Za-z0-9._-]/g, "-").replace(/-+/g, "-");
|
|
1735
|
-
return sanitized.length > 0 ? sanitized : "workspace";
|
|
1736
|
-
}
|
|
1737
|
-
function codegraphDataRoot(homeDir) {
|
|
1738
|
-
return join6(homeDir, ".omo", "codegraph");
|
|
1739
|
-
}
|
|
1740
|
-
function workspaceStorageName(workspace) {
|
|
1741
|
-
const resolved = resolve2(workspace);
|
|
1742
|
-
const hash = createHash2("sha256").update(resolved).digest("hex").slice(0, 16);
|
|
1743
|
-
return `${sanitizeBase(basename3(resolved))}-${hash}`;
|
|
1744
|
-
}
|
|
1745
|
-
function fallbackResult(dataRoot, projectLink, reason) {
|
|
1746
|
-
return { dataDir: projectLink, dataRoot, linked: false, mode: "in-place-fallback", projectLink, reason };
|
|
1747
|
-
}
|
|
1748
|
-
function isSameFilesystem(workspace, dataRoot, override) {
|
|
1749
|
-
if (override !== undefined)
|
|
1750
|
-
return override;
|
|
1751
|
-
return statSync(workspace).dev === statSync(dataRoot).dev;
|
|
1752
|
-
}
|
|
1753
|
-
function ensureInPlaceFallback(projectLink) {
|
|
1754
|
-
if (!existsSync5(projectLink))
|
|
1755
|
-
mkdirSync(projectLink, { recursive: true });
|
|
1756
|
-
}
|
|
1757
|
-
function prepareCodegraphWorkspace(workspace, options = {}) {
|
|
1758
|
-
const resolvedWorkspace = resolve2(workspace);
|
|
1759
|
-
const dataRoot = codegraphDataRoot(options.homeDir ?? homedir5());
|
|
1760
|
-
const dataDir = join6(dataRoot, "projects", workspaceStorageName(resolvedWorkspace));
|
|
1761
|
-
const projectLink = join6(resolvedWorkspace, ".codegraph");
|
|
1762
|
-
try {
|
|
1763
|
-
mkdirSync(dataDir, { recursive: true });
|
|
1764
|
-
if (existsSync5(projectLink)) {
|
|
1765
|
-
const linkStat = lstatSync(projectLink);
|
|
1766
|
-
if (!linkStat.isSymbolicLink()) {
|
|
1767
|
-
return { dataDir: projectLink, dataRoot, linked: false, mode: "in-project", projectLink };
|
|
1768
|
-
}
|
|
1769
|
-
if (realpathSync(projectLink) === realpathSync(dataDir)) {
|
|
1770
|
-
return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
|
|
1771
|
-
}
|
|
1772
|
-
return fallbackResult(dataRoot, projectLink, "existing .codegraph symlink points outside OMO store");
|
|
1773
|
-
}
|
|
1774
|
-
if (!isSameFilesystem(resolvedWorkspace, dataRoot, options.sameFilesystem)) {
|
|
1775
|
-
ensureInPlaceFallback(projectLink);
|
|
1776
|
-
return fallbackResult(dataRoot, projectLink, "workspace and OMO store are on different filesystems");
|
|
1777
|
-
}
|
|
1778
|
-
const symlink = options.symlink ?? symlinkSync;
|
|
1779
|
-
symlink(dataDir, projectLink, (options.platform ?? process.platform) === "win32" ? "junction" : "dir");
|
|
1780
|
-
return { dataDir, dataRoot, linked: true, mode: "global-linked", projectLink };
|
|
1781
|
-
} catch (error) {
|
|
1782
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
1783
|
-
try {
|
|
1784
|
-
ensureInPlaceFallback(projectLink);
|
|
1785
|
-
} catch (fallbackError) {
|
|
1786
|
-
return fallbackResult(dataRoot, projectLink, `${reason}; fallback failed: ${String(fallbackError)}`);
|
|
1787
|
-
}
|
|
1788
|
-
return fallbackResult(dataRoot, projectLink, reason);
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
function ensureCodegraphGitignored(workspace) {
|
|
1792
|
-
const gitDir = join6(workspace, ".git");
|
|
1793
|
-
if (!existsSync5(gitDir))
|
|
1794
|
-
return false;
|
|
1795
|
-
const excludePath = join6(gitDir, "info", "exclude");
|
|
1796
|
-
try {
|
|
1797
|
-
mkdirSync(join6(gitDir, "info"), { recursive: true });
|
|
1798
|
-
const existing = existsSync5(excludePath) ? readFileSync2(excludePath, "utf8") : "";
|
|
1799
|
-
if (existing.split(/\r?\n/).includes(".codegraph"))
|
|
1800
|
-
return true;
|
|
1801
|
-
appendFileSync(excludePath, `${existing.endsWith(`
|
|
1802
|
-
`) || existing.length === 0 ? "" : `
|
|
1803
|
-
`}.codegraph
|
|
1804
|
-
`);
|
|
1805
|
-
return true;
|
|
1806
|
-
} catch (error) {
|
|
1807
|
-
if (error instanceof Error)
|
|
1808
|
-
return false;
|
|
1809
|
-
throw error;
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
|
|
1813
1912
|
// components/codegraph/src/session-start-worker.ts
|
|
1814
1913
|
var SESSION_START_CWD_ENV = "OMO_CODEGRAPH_SESSION_START_CWD";
|
|
1815
1914
|
var CODEGRAPH_VERSION = "1.0.1";
|
|
@@ -1863,13 +1962,10 @@ function finish(action, detail, logOutcome) {
|
|
|
1863
1962
|
}
|
|
1864
1963
|
async function resolveOrProvisionCommand(deps, config, env, homeDir, nodeSupport) {
|
|
1865
1964
|
const resolved = deps.resolveCommand({ env, homeDir, provisioned: () => provisionedBinFromInstallDir(config.install_dir) });
|
|
1866
|
-
if (resolved.exists) {
|
|
1867
|
-
if (resolved.source !== "bundled" && resolved.source !== "env" && !nodeSupport.supported) {
|
|
1868
|
-
return { kind: "unsupported-node" };
|
|
1869
|
-
}
|
|
1965
|
+
if (resolved.exists && canUseResolvedCommand(resolved, nodeSupport)) {
|
|
1870
1966
|
return { kind: "resolved", resolution: resolved };
|
|
1871
1967
|
}
|
|
1872
|
-
if (
|
|
1968
|
+
if (resolved.exists && config.auto_provision === false)
|
|
1873
1969
|
return { kind: "unsupported-node" };
|
|
1874
1970
|
if (config.auto_provision === false)
|
|
1875
1971
|
return { error: "codegraph binary unavailable and auto_provision is disabled", kind: "unavailable", source: resolved.source };
|
|
@@ -1880,6 +1976,9 @@ async function resolveOrProvisionCommand(deps, config, env, homeDir, nodeSupport
|
|
|
1880
1976
|
}
|
|
1881
1977
|
return { kind: "resolved", resolution: { argsPrefix: [], command: provisioned.binPath, exists: true, source: "provisioned" } };
|
|
1882
1978
|
}
|
|
1979
|
+
function canUseResolvedCommand(resolved, nodeSupport) {
|
|
1980
|
+
return !codegraphCommandRequiresSupportedLocalNode(resolved) || nodeSupport.supported;
|
|
1981
|
+
}
|
|
1883
1982
|
function decideStartupAction(status) {
|
|
1884
1983
|
if (status.timedOut)
|
|
1885
1984
|
return { kind: "skip", reason: "status timed out" };
|
|
@@ -1897,7 +1996,7 @@ ${status.stderr ?? ""}`.toLowerCase();
|
|
|
1897
1996
|
return { kind: "sync" };
|
|
1898
1997
|
}
|
|
1899
1998
|
function jsonSaysInitialized(value) {
|
|
1900
|
-
if (!
|
|
1999
|
+
if (!isRecord3(value))
|
|
1901
2000
|
return;
|
|
1902
2001
|
const initialized = value["initialized"] ?? value["isInitialized"] ?? value["ready"];
|
|
1903
2002
|
if (typeof initialized === "boolean")
|
|
@@ -1963,7 +2062,7 @@ function toOutputText(value) {
|
|
|
1963
2062
|
return Buffer.isBuffer(value) ? value.toString("utf8") : value;
|
|
1964
2063
|
}
|
|
1965
2064
|
function resolveHomeDir(env) {
|
|
1966
|
-
return env["HOME"] ?? env["USERPROFILE"] ??
|
|
2065
|
+
return env["HOME"] ?? env["USERPROFILE"] ?? homedir7();
|
|
1967
2066
|
}
|
|
1968
2067
|
function parseJson(text) {
|
|
1969
2068
|
try {
|
|
@@ -1974,7 +2073,7 @@ function parseJson(text) {
|
|
|
1974
2073
|
throw error;
|
|
1975
2074
|
}
|
|
1976
2075
|
}
|
|
1977
|
-
function
|
|
2076
|
+
function isRecord3(value) {
|
|
1978
2077
|
return typeof value === "object" && value !== null;
|
|
1979
2078
|
}
|
|
1980
2079
|
|
|
@@ -1983,6 +2082,9 @@ var CODEGRAPH_SESSION_START_NOTICE = "LazyCodex CodeGraph bootstrap scheduled in
|
|
|
1983
2082
|
async function runCodegraphSessionStartHook(options = {}) {
|
|
1984
2083
|
return (await executeCodegraphSessionStartHook(options)).exitCode;
|
|
1985
2084
|
}
|
|
2085
|
+
async function runCodegraphPostToolUseHookCli(options = {}) {
|
|
2086
|
+
return (await executeCodegraphPostToolUseHook(options)).exitCode;
|
|
2087
|
+
}
|
|
1986
2088
|
async function executeCodegraphSessionStartHook(options = {}) {
|
|
1987
2089
|
const env = options.env ?? processEnv2;
|
|
1988
2090
|
const input = await readHookInput(options.stdin ?? processStdin);
|
|
@@ -2000,6 +2102,30 @@ async function executeCodegraphSessionStartHook(options = {}) {
|
|
|
2000
2102
|
writeHookJson(options.stdout ?? processStdout);
|
|
2001
2103
|
return { action: "spawned", exitCode: 0 };
|
|
2002
2104
|
}
|
|
2105
|
+
async function executeCodegraphPostToolUseHook(options = {}) {
|
|
2106
|
+
const env = options.env ?? processEnv2;
|
|
2107
|
+
const input = await readHookInput(options.stdin ?? processStdin);
|
|
2108
|
+
const output = runCodegraphPostToolUseHook(input, { homeDir: resolveHomeDir2(env) });
|
|
2109
|
+
if (output.length === 0)
|
|
2110
|
+
return { action: "skipped", exitCode: 0 };
|
|
2111
|
+
(options.stdout ?? processStdout).write(output);
|
|
2112
|
+
return { action: "emitted-guidance", exitCode: 0 };
|
|
2113
|
+
}
|
|
2114
|
+
function runCodegraphPostToolUseHook(input, options = {}) {
|
|
2115
|
+
const toolName = isRecord4(input) ? input["tool_name"] : undefined;
|
|
2116
|
+
const cwd = isRecord4(input) ? input["cwd"] : undefined;
|
|
2117
|
+
const toolOutput = isRecord4(input) ? input["tool_response"] ?? input["tool_output"] ?? input["response"] : input;
|
|
2118
|
+
const guidance = buildCodegraphInitGuidanceForToolResult({ cwd, toolName, toolOutput }, options);
|
|
2119
|
+
if (guidance === null)
|
|
2120
|
+
return "";
|
|
2121
|
+
return `${JSON.stringify({
|
|
2122
|
+
hookSpecificOutput: {
|
|
2123
|
+
hookEventName: "PostToolUse",
|
|
2124
|
+
additionalContext: guidance
|
|
2125
|
+
}
|
|
2126
|
+
})}
|
|
2127
|
+
`;
|
|
2128
|
+
}
|
|
2003
2129
|
function writeHookJson(stdout) {
|
|
2004
2130
|
const output = {
|
|
2005
2131
|
hookSpecificOutput: {
|
|
@@ -2015,10 +2141,10 @@ function spawnDetachedWorker(invocation) {
|
|
|
2015
2141
|
child.unref();
|
|
2016
2142
|
}
|
|
2017
2143
|
function resolveHomeDir2(env) {
|
|
2018
|
-
return env["HOME"] ?? env["USERPROFILE"] ??
|
|
2144
|
+
return env["HOME"] ?? env["USERPROFILE"] ?? homedir8();
|
|
2019
2145
|
}
|
|
2020
2146
|
function resolveProjectRoot(input, fallback) {
|
|
2021
|
-
if (!
|
|
2147
|
+
if (!isRecord4(input))
|
|
2022
2148
|
return fallback;
|
|
2023
2149
|
const cwd = input["cwd"];
|
|
2024
2150
|
return typeof cwd === "string" && cwd.trim().length > 0 ? cwd : fallback;
|
|
@@ -2042,7 +2168,7 @@ function parseJson2(text) {
|
|
|
2042
2168
|
throw error;
|
|
2043
2169
|
}
|
|
2044
2170
|
}
|
|
2045
|
-
function
|
|
2171
|
+
function isRecord4(value) {
|
|
2046
2172
|
return typeof value === "object" && value !== null;
|
|
2047
2173
|
}
|
|
2048
2174
|
function defaultWorkerCliPath() {
|
|
@@ -2052,7 +2178,7 @@ function defaultWorkerCliPath() {
|
|
|
2052
2178
|
// components/codegraph/src/serve.ts
|
|
2053
2179
|
import { spawn as spawn2 } from "node:child_process";
|
|
2054
2180
|
import { existsSync as existsSync7, realpathSync as realpathSync2 } from "node:fs";
|
|
2055
|
-
import { homedir as
|
|
2181
|
+
import { homedir as homedir9 } from "node:os";
|
|
2056
2182
|
import { basename as basename4, extname as extname2, join as join8, resolve as resolve3 } from "node:path";
|
|
2057
2183
|
import {
|
|
2058
2184
|
cwd as processCwd3,
|
|
@@ -2065,11 +2191,12 @@ var CODEGRAPH_SKIP_HINT = `CodeGraph MCP skipped: codegraph binary not found. In
|
|
|
2065
2191
|
`;
|
|
2066
2192
|
var CODEGRAPH_DISABLED_HINT = `CodeGraph MCP skipped: disabled by OMO SOT config. Set [codex].codegraph.enabled=true to enable it.
|
|
2067
2193
|
`;
|
|
2194
|
+
var CODEGRAPH_VERSION2 = "1.0.1";
|
|
2068
2195
|
var WINDOWS_CMD_EXTENSIONS2 = new Set([".bat", ".cmd"]);
|
|
2069
2196
|
var WINDOWS_NODE_SCRIPT_EXTENSIONS = new Set([".cjs", ".js", ".mjs"]);
|
|
2070
2197
|
async function runCodegraphServe(options = {}) {
|
|
2071
2198
|
const env = options.env ?? processEnv3;
|
|
2072
|
-
const homeDir = options.homeDir ??
|
|
2199
|
+
const homeDir = options.homeDir ?? homedir9();
|
|
2073
2200
|
const config = options.config ?? getCodexOmoConfig({ cwd: options.cwd ?? processCwd3(), env, homeDir });
|
|
2074
2201
|
const codegraphConfig = config.codegraph ?? {};
|
|
2075
2202
|
if (codegraphConfig.enabled === false) {
|
|
@@ -2081,13 +2208,26 @@ async function runCodegraphServe(options = {}) {
|
|
|
2081
2208
|
homeDir,
|
|
2082
2209
|
provisioned: () => provisionedBinFromInstallDir2(codegraphConfig.install_dir)
|
|
2083
2210
|
};
|
|
2084
|
-
|
|
2211
|
+
let resolution = options.resolve?.(resolutionOptions) ?? resolveCodegraphCommand(resolutionOptions);
|
|
2212
|
+
const nodeSupport = evaluateCodegraphNodeSupport({ env, nodeVersion: options.nodeVersion });
|
|
2085
2213
|
if (!resolution.exists || shouldSkipResolvedCommand(resolution, options.commandExists ?? existsSync7)) {
|
|
2086
|
-
(
|
|
2087
|
-
|
|
2214
|
+
if (resolution.source === "path" && !nodeSupport.supported) {
|
|
2215
|
+
(options.stderr ?? processStderr2).write(buildCodegraphNodeSkipHint(nodeSupport));
|
|
2216
|
+
return 1;
|
|
2217
|
+
}
|
|
2218
|
+
const provisioned = await provisionMissingCodegraph({
|
|
2219
|
+
config: codegraphConfig,
|
|
2220
|
+
ensureProvisioned: options.ensureProvisioned ?? ensureCodegraphProvisioned,
|
|
2221
|
+
homeDir,
|
|
2222
|
+
resolution
|
|
2223
|
+
});
|
|
2224
|
+
if (provisioned === null) {
|
|
2225
|
+
(options.stderr ?? processStderr2).write(CODEGRAPH_SKIP_HINT);
|
|
2226
|
+
return 1;
|
|
2227
|
+
}
|
|
2228
|
+
resolution = provisioned;
|
|
2088
2229
|
}
|
|
2089
|
-
|
|
2090
|
-
if (resolution.source !== "bundled" && resolution.source !== "env" && !nodeSupport.supported) {
|
|
2230
|
+
if (codegraphCommandRequiresSupportedLocalNode(resolution) && !nodeSupport.supported) {
|
|
2091
2231
|
(options.stderr ?? processStderr2).write(buildCodegraphNodeSkipHint(nodeSupport));
|
|
2092
2232
|
return 1;
|
|
2093
2233
|
}
|
|
@@ -2102,6 +2242,21 @@ async function runCodegraphServe(options = {}) {
|
|
|
2102
2242
|
stdio: "inherit"
|
|
2103
2243
|
});
|
|
2104
2244
|
}
|
|
2245
|
+
async function provisionMissingCodegraph(options) {
|
|
2246
|
+
if (options.resolution.source === "env")
|
|
2247
|
+
return null;
|
|
2248
|
+
if (options.config.auto_provision === false)
|
|
2249
|
+
return null;
|
|
2250
|
+
const installDir = options.config.install_dir ?? join8(options.homeDir, ".omo", "codegraph");
|
|
2251
|
+
const result = await options.ensureProvisioned({
|
|
2252
|
+
installDir,
|
|
2253
|
+
lockDir: join8(installDir, ".locks"),
|
|
2254
|
+
version: CODEGRAPH_VERSION2
|
|
2255
|
+
});
|
|
2256
|
+
if (!result.provisioned || result.binPath === undefined)
|
|
2257
|
+
return null;
|
|
2258
|
+
return { argsPrefix: [], command: result.binPath, exists: true, source: "provisioned" };
|
|
2259
|
+
}
|
|
2105
2260
|
function shouldSkipResolvedCommand(resolution, commandExists) {
|
|
2106
2261
|
if (resolution.source !== "env")
|
|
2107
2262
|
return false;
|
|
@@ -2176,6 +2331,14 @@ async function runCodegraphCli(options = {}) {
|
|
|
2176
2331
|
if (command === "hook" && subcommand === "session-start") {
|
|
2177
2332
|
return runCodegraphSessionStartHook(options);
|
|
2178
2333
|
}
|
|
2334
|
+
if (command === "hook" && subcommand === "post-tool-use") {
|
|
2335
|
+
const hookOptions = {
|
|
2336
|
+
...options.env === undefined ? {} : { env: options.env },
|
|
2337
|
+
...options.stdin === undefined ? {} : { stdin: options.stdin },
|
|
2338
|
+
...options.stdout === undefined ? {} : { stdout: options.stdout }
|
|
2339
|
+
};
|
|
2340
|
+
return runCodegraphPostToolUseHookCli(hookOptions);
|
|
2341
|
+
}
|
|
2179
2342
|
if (command === "hook" && subcommand === "session-start-worker") {
|
|
2180
2343
|
const workerOptions = {
|
|
2181
2344
|
...options.workerOptions,
|