oh-my-opencode 4.18.1 → 4.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/codex-qa/scripts/lsp-e2e.sh +39 -16
- package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +111 -28
- package/README.ja.md +2 -2
- package/README.ko.md +2 -2
- package/README.md +4 -4
- package/README.ru.md +2 -2
- package/README.zh-cn.md +2 -2
- package/bin/AGENTS.md +33 -0
- package/dist/agents/atlas/agent.d.ts +6 -5
- package/dist/agents/sisyphus/index.d.ts +5 -0
- package/dist/agents/sisyphus/kimi-k3.d.ts +19 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-junior/agent.d.ts +8 -4
- package/dist/agents/sisyphus-junior/index.d.ts +2 -0
- package/dist/agents/sisyphus-junior/kimi-k3.d.ts +12 -0
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/index.js +690 -139
- package/dist/cli-node/index.js +690 -139
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schema/browser-automation.d.ts +1 -0
- package/dist/config/schema/commands.d.ts +1 -3
- package/dist/config/schema/default-mode.d.ts +1 -1
- package/dist/config/schema/goal.d.ts +7 -0
- package/dist/config/schema/hooks.d.ts +1 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +6 -10
- package/dist/config/schema/ralph-loop.d.ts +1 -1
- package/dist/config/schema.d.ts +1 -1
- package/dist/create-hooks.d.ts +1 -1
- package/dist/features/builtin-commands/templates/goal.d.ts +1 -0
- package/dist/features/builtin-commands/templates/stop-continuation.d.ts +1 -1
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.d.ts +6 -0
- package/dist/hooks/auto-slash-command/executor.d.ts +1 -0
- package/dist/hooks/category-skill-reminder/hook.d.ts +9 -1
- package/dist/hooks/comment-checker/hook.d.ts +8 -1
- package/dist/hooks/goal/command-arguments.d.ts +13 -0
- package/dist/hooks/goal/controller.d.ts +26 -0
- package/dist/hooks/goal/index.d.ts +23 -0
- package/dist/hooks/goal/prompt.d.ts +3 -0
- package/dist/hooks/goal/store.d.ts +8 -0
- package/dist/hooks/goal/tools.d.ts +10 -0
- package/dist/hooks/goal/types.d.ts +93 -0
- package/dist/hooks/goal/validation.d.ts +4 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/keyword-detector/hook.d.ts +1 -2
- package/dist/hooks/ralph-loop/types.d.ts +1 -1
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +3 -0
- package/dist/index.js +3706 -4329
- package/dist/oh-my-opencode.schema.json +23 -19
- package/dist/plugin/chat-message/loop-commands.d.ts +1 -1
- package/dist/plugin/chat-message/types.d.ts +23 -10
- package/dist/plugin/hooks/create-core-hooks.d.ts +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +3 -2
- package/dist/plugin/hooks/create-transform-hooks.d.ts +0 -2
- package/dist/plugin/messages-transform.d.ts +1 -0
- package/dist/plugin/stop-continuation.d.ts +2 -2
- package/dist/plugin-handlers/prometheus-agent-config-builder.d.ts +2 -0
- package/dist/shared/system-directive.d.ts +0 -1
- package/dist/skills/ulw-plan/SKILL.md +11 -7
- package/dist/skills/ulw-plan/references/full-workflow.md +117 -6
- package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/dist/skills/ulw-research/SKILL.md +3 -3
- package/dist/tools/delegate-task/types.d.ts +0 -1
- package/dist/tui.js +115 -28
- package/package.json +14 -14
- package/packages/git-bash-mcp/dist/cli.js +81 -19
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +4 -4
- package/packages/lsp-core/src/lsp/directory-diagnostics.test.ts +118 -1
- package/packages/lsp-core/src/lsp/directory-diagnostics.ts +1 -1
- package/packages/lsp-daemon/dist/cli.js +262 -63
- package/packages/lsp-daemon/dist/client.js +194 -50
- package/packages/lsp-daemon/dist/daemon-client.d.ts +2 -2
- package/packages/lsp-daemon/dist/daemon-client.js +26 -2
- package/packages/lsp-daemon/dist/ensure-daemon.d.ts +5 -4
- package/packages/lsp-daemon/dist/ensure-daemon.js +79 -18
- package/packages/lsp-daemon/dist/index.js +262 -63
- package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
- package/packages/lsp-daemon/dist/proxy.js +79 -23
- package/packages/lsp-tools-mcp/dist/cli.js +82 -20
- package/packages/lsp-tools-mcp/dist/mcp.js +82 -20
- package/packages/lsp-tools-mcp/dist/tools.js +1 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/.mcp.json +2 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +352 -17
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +7 -6
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +195 -56
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +100 -28
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +21 -9
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +1 -1
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +35 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +69 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +57 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/.mcp.json +2 -1
- package/packages/omo-codex/plugin/components/lsp/AGENTS.md +1 -0
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +113 -31
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +1 -0
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.5.md +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +5 -3
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +8 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/README.md +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +3 -3
- package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +148 -61
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +4 -72
- package/packages/omo-codex/plugin/components/start-work-continuation/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/src/plan-checklist.ts +171 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +213 -24
- package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +4 -3
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +25 -4
- package/packages/omo-codex/plugin/components/start-work-continuation/test/fixtures/plan-scaffold.md +15 -0
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -10
- package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +3 -3
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +50 -33
- 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/ultrawork/SKILL.md +50 -33
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +11 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +117 -6
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +50 -33
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +5 -6
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +5 -6
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +2 -2
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +32 -28
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +17 -45
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +455 -0
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +13 -20
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +7 -0
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +50 -33
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +11 -7
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +117 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -0
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +6 -6
- package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +3 -3
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +62 -0
- package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +271 -14
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +7 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +38 -22
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +0 -5
- package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +293 -0
- package/packages/omo-codex/scripts/install-config.test.mjs +10 -10
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +353 -18
- package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +39 -2
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +11 -7
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +117 -6
- package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +46 -10
- package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -3
- package/dist/features/builtin-commands/templates/ralph-loop.d.ts +0 -3
- package/dist/skills/ultraresearch/SKILL.md +0 -10
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +0 -273
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -12
- package/packages/shared-skills/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -107
- package/packages/shared-skills/skills/lcx-doctor/SKILL.md +0 -128
- package/packages/shared-skills/skills/lcx-doctor/agents/openai.yaml +0 -11
- package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +0 -268
- package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +0 -11
- package/packages/shared-skills/skills/ultraresearch/SKILL.md +0 -10
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/SKILL.md +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/agents/openai.yaml +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-contribute-bug-fix/scripts/create-pr-body.mjs +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/SKILL.md +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-doctor/agents/openai.yaml +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/SKILL.md +0 -0
- /package/{dist → packages/omo-codex/plugin/components/lcx}/skills/lcx-report-bug/agents/openai.yaml +0 -0
|
@@ -63,18 +63,30 @@ export async function runBridgedCodegraphProcess(
|
|
|
63
63
|
resolveExit(signal === null ? 0 : 1);
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
const clientForwardingDone = forwardClientToCodegraph(options.input, childInput, pendingResponses, (mode) => {
|
|
67
|
+
defaultResponseMode = mode;
|
|
68
|
+
});
|
|
69
|
+
const responseForwardingDone = forwardCodegraphToClient(
|
|
70
|
+
childOutput,
|
|
71
|
+
options.output,
|
|
72
|
+
pendingResponses,
|
|
73
|
+
() => defaultResponseMode,
|
|
74
|
+
);
|
|
75
|
+
const bridgeDone = Promise.all([clientForwardingDone, responseForwardingDone]);
|
|
76
|
+
const childAndResponsesDone = Promise.all([childExit, responseForwardingDone]).then(([exitCode]) => exitCode);
|
|
72
77
|
const destroyChildPipes = (): void => {
|
|
73
78
|
childInput.destroy();
|
|
74
79
|
childOutput.destroy();
|
|
75
80
|
};
|
|
76
81
|
void childExit.then(destroyChildPipes, destroyChildPipes);
|
|
77
|
-
|
|
82
|
+
try {
|
|
83
|
+
return await Promise.race([childAndResponsesDone, bridgeDone.then(() => childExit)]);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
destroyChildPipes();
|
|
86
|
+
if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL");
|
|
87
|
+
await childExit.catch(() => undefined);
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
78
90
|
}
|
|
79
91
|
|
|
80
92
|
async function forwardClientToCodegraph(
|
|
@@ -110,14 +122,14 @@ async function forwardCodegraphToClient(
|
|
|
110
122
|
): Promise<void> {
|
|
111
123
|
for await (const message of readStdioJsonRpcMessages(childOutput)) {
|
|
112
124
|
if (message.kind === "parse_error") {
|
|
113
|
-
writeStdioJsonRpcResponse(output, errorResponse(null, -32700, "Parse error", message.message), defaultResponseMode());
|
|
125
|
+
await writeStdioJsonRpcResponse(output, errorResponse(null, -32700, "Parse error", message.message), defaultResponseMode());
|
|
114
126
|
continue;
|
|
115
127
|
}
|
|
116
128
|
const key = responseModeKey(message.payload);
|
|
117
129
|
const pendingResponse = key === null ? undefined : pendingResponses.get(key);
|
|
118
130
|
const responseMode = pendingResponse?.responseMode ?? defaultResponseMode();
|
|
119
131
|
if (key !== null) pendingResponses.delete(key);
|
|
120
|
-
writeStdioJsonRpcResponse(output, clarifyCodegraphResponse(message.payload, pendingResponse), responseMode);
|
|
132
|
+
await writeStdioJsonRpcResponse(output, clarifyCodegraphResponse(message.payload, pendingResponse), responseMode);
|
|
121
133
|
}
|
|
122
134
|
}
|
|
123
135
|
|
|
@@ -21,7 +21,7 @@ describe("CodeGraph SessionStart exclusion policy", () => {
|
|
|
21
21
|
const stdout: string[] = [];
|
|
22
22
|
const spawned: WorkerSpawnInvocation[] = [];
|
|
23
23
|
const stateRoot = createAllowedWorkspace("codegraph-omo-state");
|
|
24
|
-
const workspace = join(stateRoot, ".omo", "
|
|
24
|
+
const workspace = join(stateRoot, ".omo", "ulw-research", "run", "clones", "repo");
|
|
25
25
|
mkdirSync(workspace, { recursive: true });
|
|
26
26
|
|
|
27
27
|
try {
|
|
@@ -49,6 +49,41 @@ export function writeFakeContractCodegraph(filePath: string): void {
|
|
|
49
49
|
chmodSync(filePath, 0o755);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
export function writeFakeHeldOpenCodegraph(filePath: string): void {
|
|
53
|
+
writeFileSync(
|
|
54
|
+
filePath,
|
|
55
|
+
[
|
|
56
|
+
"#!/usr/bin/env node",
|
|
57
|
+
"const fs = require('node:fs');",
|
|
58
|
+
"const readline = require('node:readline');",
|
|
59
|
+
"fs.writeFileSync(process.env.CODEGRAPH_FAKE_LOG, String(process.pid));",
|
|
60
|
+
"const rl = readline.createInterface({ input: process.stdin });",
|
|
61
|
+
"rl.once('line', (line) => {",
|
|
62
|
+
" const request = JSON.parse(line);",
|
|
63
|
+
" process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { ok: true } }) + '\\n');",
|
|
64
|
+
"});",
|
|
65
|
+
"setInterval(() => {}, 1000);",
|
|
66
|
+
].join("\n"),
|
|
67
|
+
);
|
|
68
|
+
chmodSync(filePath, 0o755);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function writeFakeExitingCodegraph(filePath: string): void {
|
|
72
|
+
writeFileSync(
|
|
73
|
+
filePath,
|
|
74
|
+
[
|
|
75
|
+
"#!/usr/bin/env node",
|
|
76
|
+
"const readline = require('node:readline');",
|
|
77
|
+
"const rl = readline.createInterface({ input: process.stdin });",
|
|
78
|
+
"rl.once('line', (line) => {",
|
|
79
|
+
" const request = JSON.parse(line);",
|
|
80
|
+
" process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { ok: true } }) + '\\n', () => process.exit(0));",
|
|
81
|
+
"});",
|
|
82
|
+
].join("\n"),
|
|
83
|
+
);
|
|
84
|
+
chmodSync(filePath, 0o755);
|
|
85
|
+
}
|
|
86
|
+
|
|
52
87
|
export function frameMcpRequest(request: {
|
|
53
88
|
readonly id: number;
|
|
54
89
|
readonly method: string;
|
package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { mkdirSync, mkdtempSync, realpathSync, rmSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { PassThrough, Writable } from "node:stream";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
import { runCodegraphServe } from "../src/serve.ts";
|
|
8
|
+
import {
|
|
9
|
+
frameMcpRequest,
|
|
10
|
+
writeFakeExitingCodegraph,
|
|
11
|
+
} from "./mcp-bridge-fixtures.ts";
|
|
12
|
+
|
|
13
|
+
const componentRoot = realpathSync(
|
|
14
|
+
fileURLToPath(new URL("..", import.meta.url)),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
describe("runCodegraphServe MCP bridge lifecycle", () => {
|
|
18
|
+
it("#given an exiting Codegraph child and delayed closed parent output #when the final response write fails #then the output error is preserved", async () => {
|
|
19
|
+
const tempRoot = mkdtempSync(
|
|
20
|
+
join(componentRoot, ".tmp-codegraph-exit-output-failure-"),
|
|
21
|
+
);
|
|
22
|
+
const projectRoot = join(tempRoot, "project");
|
|
23
|
+
const fakeCodegraph = join(tempRoot, "codegraph-exiting.cjs");
|
|
24
|
+
const input = new PassThrough();
|
|
25
|
+
const outputError = Object.assign(
|
|
26
|
+
new Error("parent output closed after child exit"),
|
|
27
|
+
{ code: "EPIPE" },
|
|
28
|
+
);
|
|
29
|
+
const writeStarted = Promise.withResolvers<void>();
|
|
30
|
+
const output = new Writable({
|
|
31
|
+
write(_chunk, _encoding, callback) {
|
|
32
|
+
writeStarted.resolve();
|
|
33
|
+
setTimeout(() => callback(outputError), 150);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
mkdirSync(projectRoot, { recursive: true });
|
|
39
|
+
writeFakeExitingCodegraph(fakeCodegraph);
|
|
40
|
+
const run = runCodegraphServe({
|
|
41
|
+
cwd: tempRoot,
|
|
42
|
+
env: {
|
|
43
|
+
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
44
|
+
OMO_CODEGRAPH_BIN: fakeCodegraph,
|
|
45
|
+
OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
|
|
46
|
+
PATH: process.env["PATH"],
|
|
47
|
+
},
|
|
48
|
+
nodeVersion: "22.14.0",
|
|
49
|
+
buildEnv: () => ({}),
|
|
50
|
+
resolve: () => ({
|
|
51
|
+
argsPrefix: [],
|
|
52
|
+
command: fakeCodegraph,
|
|
53
|
+
exists: true,
|
|
54
|
+
source: "env",
|
|
55
|
+
}),
|
|
56
|
+
stderr: { write: () => undefined },
|
|
57
|
+
stdin: input,
|
|
58
|
+
stdout: output,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
input.end(frameMcpRequest({ id: 1, method: "tools/list", params: {} }));
|
|
62
|
+
|
|
63
|
+
await writeStarted.promise;
|
|
64
|
+
await expect(run).rejects.toBe(outputError);
|
|
65
|
+
} finally {
|
|
66
|
+
rmSync(tempRoot, { recursive: true, force: true });
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from "bun:test";
|
|
2
2
|
import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { PassThrough } from "node:stream";
|
|
4
|
+
import { PassThrough, Writable } from "node:stream";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
7
|
import { runCodegraphServe } from "../src/serve.ts";
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
recordValue,
|
|
15
15
|
stringProperty,
|
|
16
16
|
writeFakeContractCodegraph,
|
|
17
|
+
writeFakeHeldOpenCodegraph,
|
|
17
18
|
writeFakeNewlineCodegraph,
|
|
18
19
|
} from "./mcp-bridge-fixtures.ts";
|
|
19
20
|
|
|
@@ -190,4 +191,59 @@ describe("runCodegraphServe MCP protocol bridge", () => {
|
|
|
190
191
|
rmSync(tempRoot, { recursive: true, force: true });
|
|
191
192
|
}
|
|
192
193
|
});
|
|
194
|
+
|
|
195
|
+
it("#given a held-open Codegraph child and closed parent output #when response forwarding fails #then the child is terminated before rejection", async () => {
|
|
196
|
+
const tempRoot = mkdtempSync(join(componentRoot, ".tmp-codegraph-output-failure-"));
|
|
197
|
+
const projectRoot = join(tempRoot, "project");
|
|
198
|
+
const fakeCodegraph = join(tempRoot, "codegraph-held-open.cjs");
|
|
199
|
+
const childPidFile = join(tempRoot, "child.pid");
|
|
200
|
+
const input = new PassThrough();
|
|
201
|
+
const outputError = Object.assign(new Error("parent output closed"), { code: "EPIPE" });
|
|
202
|
+
const output = new Writable({
|
|
203
|
+
write(_chunk, _encoding, callback) {
|
|
204
|
+
callback(outputError);
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
let childPid: number | undefined;
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
mkdirSync(projectRoot, { recursive: true });
|
|
211
|
+
writeFakeHeldOpenCodegraph(fakeCodegraph);
|
|
212
|
+
const run = runCodegraphServe({
|
|
213
|
+
cwd: tempRoot,
|
|
214
|
+
env: {
|
|
215
|
+
CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
|
|
216
|
+
CODEGRAPH_FAKE_LOG: childPidFile,
|
|
217
|
+
OMO_CODEGRAPH_BIN: fakeCodegraph,
|
|
218
|
+
OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
|
|
219
|
+
PATH: process.env["PATH"],
|
|
220
|
+
},
|
|
221
|
+
nodeVersion: "22.14.0",
|
|
222
|
+
buildEnv: () => ({}),
|
|
223
|
+
resolve: () => ({ argsPrefix: [], command: fakeCodegraph, exists: true, source: "env" }),
|
|
224
|
+
stderr: { write: () => undefined },
|
|
225
|
+
stdin: input,
|
|
226
|
+
stdout: output,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
input.end(frameMcpRequest({ id: 1, method: "tools/list", params: {} }));
|
|
230
|
+
|
|
231
|
+
await expect(run).rejects.toBe(outputError);
|
|
232
|
+
childPid = Number(readFileSync(childPidFile, "utf8"));
|
|
233
|
+
expect(isProcessAlive(childPid)).toBe(false);
|
|
234
|
+
} finally {
|
|
235
|
+
if (childPid !== undefined && isProcessAlive(childPid)) process.kill(childPid, "SIGKILL");
|
|
236
|
+
rmSync(tempRoot, { recursive: true, force: true });
|
|
237
|
+
}
|
|
238
|
+
});
|
|
193
239
|
});
|
|
240
|
+
|
|
241
|
+
function isProcessAlive(pid: number): boolean {
|
|
242
|
+
try {
|
|
243
|
+
process.kill(pid, 0);
|
|
244
|
+
return true;
|
|
245
|
+
} catch (error) {
|
|
246
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") return false;
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
|
|
10
10
|
"timeout": 5,
|
|
11
|
-
"statusMessage": "(OmO 4.
|
|
11
|
+
"statusMessage": "(OmO 4.19.0) Recommending Git Bash MCP"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"type": "command",
|
|
21
21
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
22
22
|
"timeout": 5,
|
|
23
|
-
"statusMessage": "(OmO 4.
|
|
23
|
+
"statusMessage": "(OmO 4.19.0) Resetting Git Bash MCP Reminder"
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
26
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
|
|
10
10
|
"timeout": 10,
|
|
11
|
-
"statusMessage": "(OmO 4.
|
|
11
|
+
"statusMessage": "(OmO 4.19.0) Verifying LazyCodex Executor Evidence"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -22,4 +22,5 @@ Conventions for humans and agents working on this repository.
|
|
|
22
22
|
- LSP server processes are owned by `LspManager`.
|
|
23
23
|
- Tool execution acquires clients through `withLspClient(...)` unless it only reports static status.
|
|
24
24
|
- `lsp.rename` mutates files by applying workspace edits; keep it sequential at the MCP caller level.
|
|
25
|
+
- `.mcp.json` sets `lsp` MCP server `startup_timeout_sec: 10` to bound startup; preserve the bound on edits.
|
|
25
26
|
- Do not add pi-coding-agent or omo source dependencies. This package is standalone.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "4.
|
|
4
|
-
"inputDigest": "sha256:
|
|
3
|
+
"version": "4.19.0",
|
|
4
|
+
"inputDigest": "sha256:1c26ab90eb222f050b468e7088ee9e655d0db850605ab425e8636c089a910f79",
|
|
5
5
|
"outputs": [
|
|
6
6
|
{
|
|
7
7
|
"path": "cli.d.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "cli.js",
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "e92c3fee5795bf44de9504b0e85c2be208c78a31e966ec9a7a807d621431c74a"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "codex-hook-cli.d.ts",
|
|
@@ -13,13 +13,13 @@ import { homedir as homedir3 } from "node:os";
|
|
|
13
13
|
import { join as join11, resolve as resolve11 } from "node:path";
|
|
14
14
|
|
|
15
15
|
// ../../../../lsp-daemon/dist/client.js
|
|
16
|
-
import { connect
|
|
16
|
+
import { connect } from "node:net";
|
|
17
17
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
18
18
|
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
19
19
|
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
20
20
|
import { spawn } from "node:child_process";
|
|
21
21
|
import { closeSync as closeSync2, mkdirSync as mkdirSync2, openSync as openSync2 } from "node:fs";
|
|
22
|
-
import {
|
|
22
|
+
import { Socket } from "node:net";
|
|
23
23
|
import { dirname as dirname3 } from "node:path";
|
|
24
24
|
import { execPath } from "node:process";
|
|
25
25
|
import {
|
|
@@ -426,42 +426,48 @@ class DaemonUnreachableError extends Error {
|
|
|
426
426
|
async function ensureDaemonRunning(paths, deps = defaultEnsureDaemonDeps(), options = {}) {
|
|
427
427
|
const readyTimeoutMs = options.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
|
|
428
428
|
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
429
|
-
|
|
429
|
+
const signal = options.signal;
|
|
430
|
+
throwIfAborted(signal);
|
|
431
|
+
if (await awaitWithSignal(deps.probe(paths, signal), signal))
|
|
430
432
|
return;
|
|
433
|
+
throwIfAborted(signal);
|
|
431
434
|
deps.spawnDaemon(paths);
|
|
432
|
-
await waitUntilReachable(paths, deps, readyTimeoutMs, pollIntervalMs);
|
|
435
|
+
await waitUntilReachable(paths, deps, readyTimeoutMs, pollIntervalMs, signal);
|
|
433
436
|
}
|
|
434
|
-
async function waitUntilReachable(paths, deps, readyTimeoutMs, pollIntervalMs) {
|
|
437
|
+
async function waitUntilReachable(paths, deps, readyTimeoutMs, pollIntervalMs, signal) {
|
|
435
438
|
const deadline = deps.now() + readyTimeoutMs;
|
|
436
439
|
for (;; ) {
|
|
437
|
-
|
|
440
|
+
throwIfAborted(signal);
|
|
441
|
+
if (await awaitWithSignal(deps.probe(paths, signal), signal))
|
|
438
442
|
return;
|
|
439
443
|
if (deps.now() >= deadline)
|
|
440
444
|
throw new DaemonUnreachableError(paths.socket);
|
|
441
|
-
await deps.sleep(pollIntervalMs);
|
|
445
|
+
await awaitWithSignal(deps.sleep(pollIntervalMs, signal), signal);
|
|
442
446
|
}
|
|
443
447
|
}
|
|
444
|
-
async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
448
|
+
async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
445
449
|
const token = readAuthToken(paths);
|
|
446
450
|
if (!token)
|
|
447
451
|
return false;
|
|
448
|
-
return await pingDaemon(paths, token, timeoutMs) !== null;
|
|
452
|
+
return await pingDaemon(paths, token, timeoutMs, signal) !== null;
|
|
449
453
|
}
|
|
450
|
-
function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
454
|
+
function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
451
455
|
return new Promise((resolve22) => {
|
|
452
|
-
const socket =
|
|
456
|
+
const socket = new Socket;
|
|
453
457
|
let settled = false;
|
|
458
|
+
let timer;
|
|
454
459
|
const finish = (value) => {
|
|
455
460
|
if (settled)
|
|
456
461
|
return;
|
|
457
462
|
settled = true;
|
|
463
|
+
if (timer !== undefined)
|
|
464
|
+
clearTimeout(timer);
|
|
465
|
+
signal?.removeEventListener("abort", onAbort);
|
|
458
466
|
socket.destroy();
|
|
459
467
|
resolve22(value);
|
|
460
468
|
};
|
|
461
|
-
const
|
|
462
|
-
timer.unref?.();
|
|
469
|
+
const onAbort = () => finish(null);
|
|
463
470
|
const decoder = createLineDecoder((message) => {
|
|
464
|
-
clearTimeout(timer);
|
|
465
471
|
finish(parsePingResponse(message));
|
|
466
472
|
});
|
|
467
473
|
socket.once("connect", () => {
|
|
@@ -469,9 +475,16 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
|
469
475
|
});
|
|
470
476
|
socket.on("data", (chunk) => decoder.push(chunk));
|
|
471
477
|
socket.once("error", () => {
|
|
472
|
-
clearTimeout(timer);
|
|
473
478
|
finish(null);
|
|
474
479
|
});
|
|
480
|
+
timer = setTimeout(() => finish(null), timeoutMs);
|
|
481
|
+
timer.unref?.();
|
|
482
|
+
if (signal?.aborted) {
|
|
483
|
+
onAbort();
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
487
|
+
socket.connect(paths.socket);
|
|
475
488
|
});
|
|
476
489
|
}
|
|
477
490
|
function spawnDaemonProcess(paths) {
|
|
@@ -489,14 +502,62 @@ function spawnDaemonProcess(paths) {
|
|
|
489
502
|
}
|
|
490
503
|
function defaultEnsureDaemonDeps() {
|
|
491
504
|
return {
|
|
492
|
-
probe: (paths) => probeDaemon(paths),
|
|
505
|
+
probe: (paths, signal) => probeDaemon(paths, PROBE_TIMEOUT_MS, signal),
|
|
493
506
|
spawnDaemon: (paths) => spawnDaemonProcess(paths),
|
|
494
|
-
sleep: (ms) =>
|
|
495
|
-
setTimeout(resolve22, ms);
|
|
496
|
-
}),
|
|
507
|
+
sleep: (ms, signal) => sleepWithSignal(ms, signal),
|
|
497
508
|
now: () => Date.now()
|
|
498
509
|
};
|
|
499
510
|
}
|
|
511
|
+
function sleepWithSignal(ms, signal) {
|
|
512
|
+
return new Promise((resolve22) => {
|
|
513
|
+
let settled = false;
|
|
514
|
+
const finish = () => {
|
|
515
|
+
if (settled)
|
|
516
|
+
return;
|
|
517
|
+
settled = true;
|
|
518
|
+
clearTimeout(timer);
|
|
519
|
+
signal?.removeEventListener("abort", finish);
|
|
520
|
+
resolve22();
|
|
521
|
+
};
|
|
522
|
+
const timer = setTimeout(finish, ms);
|
|
523
|
+
if (signal?.aborted) {
|
|
524
|
+
finish();
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
signal?.addEventListener("abort", finish, { once: true });
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function awaitWithSignal(promise, signal) {
|
|
531
|
+
if (!signal)
|
|
532
|
+
return promise;
|
|
533
|
+
if (signal.aborted)
|
|
534
|
+
return Promise.reject(abortError(signal));
|
|
535
|
+
return new Promise((resolve22, reject) => {
|
|
536
|
+
let settled = false;
|
|
537
|
+
const finish = (run) => {
|
|
538
|
+
if (settled)
|
|
539
|
+
return;
|
|
540
|
+
settled = true;
|
|
541
|
+
signal.removeEventListener("abort", onAbort);
|
|
542
|
+
run();
|
|
543
|
+
};
|
|
544
|
+
const onAbort = () => finish(() => reject(abortError(signal)));
|
|
545
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
546
|
+
promise.then((value) => finish(() => resolve22(value)), (error) => finish(() => reject(error)));
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
function throwIfAborted(signal) {
|
|
550
|
+
if (signal?.aborted)
|
|
551
|
+
throw abortError(signal);
|
|
552
|
+
}
|
|
553
|
+
function abortError(signal) {
|
|
554
|
+
const reason = signal.reason;
|
|
555
|
+
if (reason instanceof Error)
|
|
556
|
+
return reason;
|
|
557
|
+
const error = new Error(typeof reason === "string" ? reason : "daemon startup cancelled");
|
|
558
|
+
error.name = "AbortError";
|
|
559
|
+
return error;
|
|
560
|
+
}
|
|
500
561
|
function parsePingResponse(message) {
|
|
501
562
|
if (!message || typeof message !== "object" || Array.isArray(message))
|
|
502
563
|
return null;
|
|
@@ -692,7 +753,7 @@ class JsonRpcConnection {
|
|
|
692
753
|
settled = true;
|
|
693
754
|
this.pendingRequests.delete(key);
|
|
694
755
|
cleanup();
|
|
695
|
-
const rejectCancelled = () => reject(
|
|
756
|
+
const rejectCancelled = () => reject(abortError2(options.signal));
|
|
696
757
|
if (!requestWritten) {
|
|
697
758
|
cancelAfterWrite = true;
|
|
698
759
|
rejectCancelled();
|
|
@@ -896,7 +957,7 @@ ${body}`;
|
|
|
896
957
|
}
|
|
897
958
|
}
|
|
898
959
|
}
|
|
899
|
-
function
|
|
960
|
+
function abortError2(signal) {
|
|
900
961
|
const reason = signal?.reason;
|
|
901
962
|
if (reason instanceof Error)
|
|
902
963
|
return reason;
|
|
@@ -3118,11 +3179,11 @@ function waitForDiagnosticsActivity(wait, signal) {
|
|
|
3118
3179
|
if (!signal)
|
|
3119
3180
|
return wait;
|
|
3120
3181
|
if (signal.aborted)
|
|
3121
|
-
return Promise.reject(
|
|
3182
|
+
return Promise.reject(abortError3(signal));
|
|
3122
3183
|
return new Promise((resolve72, reject) => {
|
|
3123
3184
|
const onAbort = () => {
|
|
3124
3185
|
signal.removeEventListener("abort", onAbort);
|
|
3125
|
-
reject(
|
|
3186
|
+
reject(abortError3(signal));
|
|
3126
3187
|
};
|
|
3127
3188
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3128
3189
|
wait.then(() => {
|
|
@@ -3157,7 +3218,7 @@ function preCommitAbortReason(source) {
|
|
|
3157
3218
|
return reason;
|
|
3158
3219
|
return new Error("LSP request cancelled before workspace edit commit");
|
|
3159
3220
|
}
|
|
3160
|
-
function
|
|
3221
|
+
function abortError3(signal) {
|
|
3161
3222
|
const reason = signal.reason;
|
|
3162
3223
|
if (reason instanceof Error)
|
|
3163
3224
|
return reason;
|
|
@@ -3188,7 +3249,7 @@ async function stopClientBestEffort(client) {
|
|
|
3188
3249
|
reportBestEffortCleanupError("client stop", error);
|
|
3189
3250
|
}
|
|
3190
3251
|
}
|
|
3191
|
-
function
|
|
3252
|
+
function awaitWithSignal2(promise, signal) {
|
|
3192
3253
|
if (!signal)
|
|
3193
3254
|
return promise;
|
|
3194
3255
|
return new Promise((resolve72, reject) => {
|
|
@@ -3291,7 +3352,7 @@ class LspManager {
|
|
|
3291
3352
|
if (managed.initPromise) {
|
|
3292
3353
|
managed.pendingWaiters++;
|
|
3293
3354
|
try {
|
|
3294
|
-
await
|
|
3355
|
+
await awaitWithSignal2(managed.initPromise, signal);
|
|
3295
3356
|
} catch (err) {
|
|
3296
3357
|
managed.pendingWaiters--;
|
|
3297
3358
|
await this.tryDeleteIfOrphaned(key, managed);
|
|
@@ -3329,7 +3390,7 @@ class LspManager {
|
|
|
3329
3390
|
};
|
|
3330
3391
|
this.clients.set(key, newManaged);
|
|
3331
3392
|
try {
|
|
3332
|
-
await
|
|
3393
|
+
await awaitWithSignal2(initPromise, signal);
|
|
3333
3394
|
} catch (err) {
|
|
3334
3395
|
newManaged.pendingWaiters--;
|
|
3335
3396
|
if (this.clients.get(key) === newManaged) {
|
|
@@ -4280,7 +4341,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4280
4341
|
const fileErrors = [];
|
|
4281
4342
|
const maxConcurrency = Math.max(1, options.maxConcurrency ?? DIRECTORY_DIAGNOSTICS_MAX_CONCURRENCY);
|
|
4282
4343
|
options.signal?.throwIfAborted();
|
|
4283
|
-
const client = await manager.getClient(root, server2);
|
|
4344
|
+
const client = await manager.getClient(root, server2, options.signal);
|
|
4284
4345
|
try {
|
|
4285
4346
|
let nextIndex = 0;
|
|
4286
4347
|
const workers = Array.from({ length: Math.min(maxConcurrency, filesToProcess.length) }, async () => {
|
|
@@ -4960,14 +5021,14 @@ class DaemonRequestCancelledError extends DaemonRequestError {
|
|
|
4960
5021
|
async function callToolViaDaemon(name, args, options) {
|
|
4961
5022
|
const context = requireContext(options.context);
|
|
4962
5023
|
const paths = options.paths ?? daemonPaths();
|
|
4963
|
-
const ensure = options.ensure ?? ensureDaemonRunning;
|
|
5024
|
+
const ensure = options.ensure ?? ((ensurePaths, signal) => ensureDaemonRunning(ensurePaths, undefined, signal === undefined ? {} : { signal }));
|
|
4964
5025
|
const timeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
4965
5026
|
const requestArgs = withContext(args, context);
|
|
4966
5027
|
let lastError;
|
|
4967
5028
|
let authRefreshUsed = false;
|
|
4968
5029
|
for (let attempt = 0;attempt < 3; attempt += 1) {
|
|
4969
5030
|
try {
|
|
4970
|
-
await
|
|
5031
|
+
await ensureDaemonAvailable(paths, ensure, options.signal);
|
|
4971
5032
|
const token = readAuthToken(paths);
|
|
4972
5033
|
if (!token)
|
|
4973
5034
|
throw new DaemonRequestError("daemon auth token missing", false);
|
|
@@ -4998,6 +5059,27 @@ function requireContext(context) {
|
|
|
4998
5059
|
function withContext(args, context) {
|
|
4999
5060
|
return { ...args, [CONTEXT_KEY]: context };
|
|
5000
5061
|
}
|
|
5062
|
+
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5063
|
+
if (!signal)
|
|
5064
|
+
return ensure(paths);
|
|
5065
|
+
return new Promise((resolve9, reject) => {
|
|
5066
|
+
let settled = false;
|
|
5067
|
+
const finish = (run) => {
|
|
5068
|
+
if (settled)
|
|
5069
|
+
return;
|
|
5070
|
+
settled = true;
|
|
5071
|
+
signal.removeEventListener("abort", onAbort);
|
|
5072
|
+
run();
|
|
5073
|
+
};
|
|
5074
|
+
const onAbort = () => finish(() => reject(new DaemonRequestCancelledError(false)));
|
|
5075
|
+
if (signal.aborted) {
|
|
5076
|
+
onAbort();
|
|
5077
|
+
return;
|
|
5078
|
+
}
|
|
5079
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
5080
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5081
|
+
});
|
|
5082
|
+
}
|
|
5001
5083
|
function daemonUnreachableResult(paths, error) {
|
|
5002
5084
|
const text2 = [
|
|
5003
5085
|
`LSP daemon unreachable: ${errorText(error)}.`,
|
|
@@ -5011,7 +5093,7 @@ function daemonUnreachableResult(paths, error) {
|
|
|
5011
5093
|
}
|
|
5012
5094
|
function sendToolCall(paths, token, name, args, options) {
|
|
5013
5095
|
return new Promise((resolve9, reject) => {
|
|
5014
|
-
const socket =
|
|
5096
|
+
const socket = connect(paths.socket);
|
|
5015
5097
|
const requestId = allocateProxyRequestId();
|
|
5016
5098
|
let settled = false;
|
|
5017
5099
|
let requestWritten = false;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
10
10
|
"timeout": 60,
|
|
11
|
-
"statusMessage": "(OmO 4.
|
|
11
|
+
"statusMessage": "(OmO 4.19.0) Checking LSP Diagnostics"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"type": "command",
|
|
22
22
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
23
23
|
"timeout": 5,
|
|
24
|
-
"statusMessage": "(OmO 4.
|
|
24
|
+
"statusMessage": "(OmO 4.19.0) Resetting LSP Diagnostics Cache"
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
}
|