oh-my-opencode 4.5.12 → 4.6.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/opencode-qa/SKILL.md +194 -0
- package/.agents/skills/opencode-qa/references/cli-commands.md +188 -0
- package/.agents/skills/opencode-qa/references/db-investigation.md +197 -0
- package/.agents/skills/opencode-qa/references/events-hooks.md +110 -0
- package/.agents/skills/opencode-qa/references/sdk.md +96 -0
- package/.agents/skills/opencode-qa/references/server-api.md +200 -0
- package/.agents/skills/opencode-qa/references/testing-harness.md +218 -0
- package/.agents/skills/opencode-qa/references/tui-tmux.md +52 -0
- package/.agents/skills/opencode-qa/scripts/db-session-by-id.sh +53 -0
- package/.agents/skills/opencode-qa/scripts/db-session-by-name.sh +57 -0
- package/.agents/skills/opencode-qa/scripts/db-session-by-text.sh +158 -0
- package/.agents/skills/opencode-qa/scripts/export-roundtrip.sh +57 -0
- package/.agents/skills/opencode-qa/scripts/lib/common.sh +216 -0
- package/.agents/skills/opencode-qa/scripts/server-smoke.sh +64 -0
- package/.agents/skills/opencode-qa/scripts/sse-hook-probe.sh +106 -0
- package/.agents/skills/opencode-qa/scripts/tui-smoke.sh +89 -0
- package/README.ja.md +13 -3
- package/README.ko.md +13 -3
- package/README.md +24 -14
- package/README.ru.md +13 -3
- package/README.zh-cn.md +13 -3
- package/bin/oh-my-opencode.js +4 -3
- package/bin/oh-my-opencode.test.ts +35 -7
- package/bin/platform.d.ts +1 -1
- package/bin/platform.js +4 -4
- package/bin/platform.test.ts +31 -9
- package/dist/cli/cleanup-command.d.ts +4 -0
- package/dist/cli/cleanup.d.ts +11 -0
- package/dist/cli/cli-program.d.ts +2 -1
- package/dist/cli/index.js +1837 -450
- package/dist/cli/install-codex/codex-cache.d.ts +1 -0
- package/dist/cli/install-codex/codex-cleanup-config.d.ts +6 -0
- package/dist/cli/install-codex/codex-cleanup.d.ts +21 -0
- package/dist/cli/install-codex/codex-config-mcp.d.ts +1 -0
- package/dist/cli/install-codex/codex-config-permissions.d.ts +1 -0
- package/dist/cli/install-codex/codex-config-reasoning.d.ts +1 -0
- package/dist/cli/install-codex/codex-config-toml.d.ts +2 -1
- package/dist/cli/install-codex/codex-installation-detection.d.ts +36 -0
- package/dist/cli/install-codex/codex-package-layout.d.ts +1 -0
- package/dist/cli/install-codex/codex-project-local-cleanup-best-effort.d.ts +7 -0
- package/dist/cli/install-codex/codex-project-local-cleanup.d.ts +35 -0
- package/dist/cli/install-codex/git-bash.d.ts +35 -0
- package/dist/cli/install-codex/index.d.ts +4 -0
- package/dist/cli/install-codex/toml-section-editor.d.ts +2 -0
- package/dist/cli/install-codex/types.d.ts +20 -0
- package/dist/cli/run/event-state.d.ts +1 -0
- package/dist/cli/run/poll-for-completion.d.ts +1 -0
- package/dist/cli/run/prompt-start.d.ts +7 -0
- package/dist/cli/star-request.d.ts +9 -0
- package/dist/config/schema/hooks.d.ts +0 -1
- package/dist/create-hooks.d.ts +0 -1
- package/dist/features/builtin-skills/skills/debugging.d.ts +2 -0
- package/dist/features/builtin-skills/skills/index.d.ts +1 -0
- package/dist/hooks/index.d.ts +0 -1
- package/dist/index.js +267 -114
- package/dist/plugin/hooks/create-core-hooks.d.ts +0 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +1 -2
- package/dist/plugin/messages-transform.d.ts +8 -1
- package/dist/plugin/user-abort-interrupted-recovery-guard.d.ts +6 -0
- package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +14 -0
- package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +7 -0
- package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +1 -0
- package/dist/shared/prompt-async-gate/timing.d.ts +1 -0
- package/dist/shared/prompt-async-gate/types.d.ts +2 -0
- package/dist/shared/prompt-async-gate.d.ts +1 -1
- package/package.json +22 -17
- package/packages/git-bash-mcp/dist/cli.js +367 -0
- package/packages/omo-codex/plugin/.mcp.json +11 -0
- package/packages/omo-codex/plugin/components/comment-checker/README.md +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +29 -0
- package/packages/omo-codex/plugin/components/git-bash/package.json +23 -0
- package/packages/omo-codex/plugin/components/git-bash/src/cli.ts +33 -0
- package/packages/omo-codex/plugin/components/git-bash/src/codex-hook.ts +180 -0
- package/packages/omo-codex/plugin/components/git-bash/src/index.ts +10 -0
- package/packages/omo-codex/plugin/components/git-bash/test/codex-hook.test.ts +195 -0
- package/packages/omo-codex/plugin/components/git-bash/tsconfig.build.json +13 -0
- package/packages/omo-codex/plugin/components/git-bash/tsconfig.json +25 -0
- package/packages/omo-codex/plugin/components/lsp/README.md +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/cli.ts +5 -5
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook-cli.ts +33 -0
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +19 -27
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-cli.test.ts +28 -0
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-errors.test.ts +55 -0
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +7 -5
- package/packages/omo-codex/plugin/components/rules/README.md +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/windows-git-bash.md +10 -0
- package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +3 -1
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +97 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +5 -4
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +22 -0
- package/packages/omo-codex/plugin/components/ultrawork/README.md +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/codex-ultrawork-reviewer.toml +1 -0
- package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +8 -7
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +31 -5
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +27 -4
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +25 -0
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +27 -205
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +230 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +102 -5
- package/packages/omo-codex/plugin/hooks/hooks.json +24 -2
- package/packages/omo-codex/plugin/package-lock.json +19 -0
- package/packages/omo-codex/plugin/package.json +3 -1
- package/packages/omo-codex/plugin/scripts/build-bundled-mcp-runtimes.mjs +16 -1
- package/packages/omo-codex/plugin/scripts/build-components.mjs +2 -1
- package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +87 -0
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +27 -2
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +20 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +27 -205
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +230 -0
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +23 -8
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +56 -11
- package/packages/omo-codex/plugin/test/install-time-build-runtime.test.mjs +34 -0
- package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +21 -0
- package/packages/omo-codex/plugin/test/node-install-surface.test.mjs +48 -0
- package/packages/omo-codex/plugin/test/subagent-guidance.test.mjs +76 -0
- package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +66 -0
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +32 -2
- package/packages/omo-codex/scripts/install/cache.mjs +5 -3
- package/packages/omo-codex/scripts/install/cli-args.mjs +112 -0
- package/packages/omo-codex/scripts/install/config.mjs +36 -1
- package/packages/omo-codex/scripts/install/delegated-command.mjs +25 -0
- package/packages/omo-codex/scripts/install/git-bash.mjs +99 -0
- package/packages/omo-codex/scripts/install/git-bash.test.mjs +174 -0
- package/packages/omo-codex/scripts/install/mcp-runtime-cache.mjs +5 -1
- package/packages/omo-codex/scripts/install/multi-agent-v2-config.mjs +7 -1
- package/packages/omo-codex/scripts/install/permissions.d.mts +1 -0
- package/packages/omo-codex/scripts/install/permissions.mjs +26 -0
- package/packages/omo-codex/scripts/install/project-local-cleanup.mjs +229 -0
- package/packages/omo-codex/scripts/install/reasoning-config.mjs +14 -0
- package/packages/omo-codex/scripts/install/source-package-build.mjs +20 -0
- package/packages/omo-codex/scripts/install/toml-editor.mjs +19 -2
- package/packages/omo-codex/scripts/install-cli-args.test.mjs +146 -0
- package/packages/omo-codex/scripts/install-config-autonomous.test.mjs +48 -0
- package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +62 -0
- package/packages/omo-codex/scripts/install-config.test.mjs +206 -0
- package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +129 -0
- package/packages/omo-codex/scripts/install-local-git-bash-preflight.test.mjs +145 -0
- package/packages/omo-codex/scripts/install-local.mjs +91 -8
- package/packages/omo-codex/scripts/install-local.test.mjs +15 -0
- package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +60 -0
- package/packages/omo-codex/scripts/install-packaged-local.test.mjs +67 -0
- package/packages/omo-codex/scripts/install-project-local-cleanup.test.mjs +277 -0
- package/packages/shared-skills/skills/review-work/SKILL.md +27 -2
- package/packages/shared-skills/skills/start-work/SKILL.md +20 -0
- package/dist/hooks/context-window-monitor.d.ts +0 -19
|
@@ -37,7 +37,6 @@ export declare function createCoreHooks(args: {
|
|
|
37
37
|
teamToolGating: ReturnType<typeof import("../../hooks").createTeamToolGating> | null;
|
|
38
38
|
notepadWriteGuard: ReturnType<typeof import("../../hooks").createNotepadWriteGuardHook> | null;
|
|
39
39
|
planFormatValidator: ReturnType<typeof import("../../hooks").createPlanFormatValidatorHook> | null;
|
|
40
|
-
contextWindowMonitor: ReturnType<typeof import("../../hooks").createContextWindowMonitorHook> | null;
|
|
41
40
|
preemptiveCompaction: ReturnType<typeof import("../../hooks").createPreemptiveCompactionHook> | null;
|
|
42
41
|
sessionRecovery: ReturnType<typeof import("../../hooks").createSessionRecoveryHook> | null;
|
|
43
42
|
sessionNotification: ReturnType<typeof import("../../hooks").createSessionNotification> | null;
|
|
@@ -3,10 +3,9 @@ import type { BackgroundManager } from "../../features/background-agent";
|
|
|
3
3
|
import type { ModelFallbackControllerAccessor } from "../../hooks/model-fallback";
|
|
4
4
|
import type { ModelCacheState } from "../../plugin-state";
|
|
5
5
|
import type { PluginContext } from "../types";
|
|
6
|
-
import {
|
|
6
|
+
import { createSessionRecoveryHook, createSessionNotification, createThinkModeHook, createModelFallbackHook, createAnthropicContextWindowLimitRecoveryHook, createAutoUpdateCheckerHook, createAgentUsageReminderHook, createNonInteractiveEnvHook, createInteractiveBashSessionHook, createRalphLoopHook, createEditErrorRecoveryHook, createDelegateTaskRetryHook, createTaskResumeInfoHook, createStartWorkHook, createPrometheusMdOnlyHook, createSisyphusJuniorNotepadHook, createNoSisyphusGptHook, createNoHephaestusNonGptHook, createQuestionLabelTruncatorHook, createPreemptiveCompactionHook, createRuntimeFallbackHook, createLegacyPluginToastHook } from "../../hooks";
|
|
7
7
|
import { createAnthropicEffortHook } from "../../hooks/anthropic-effort";
|
|
8
8
|
export type SessionHooks = {
|
|
9
|
-
contextWindowMonitor: ReturnType<typeof createContextWindowMonitorHook> | null;
|
|
10
9
|
preemptiveCompaction: ReturnType<typeof createPreemptiveCompactionHook> | null;
|
|
11
10
|
sessionRecovery: ReturnType<typeof createSessionRecoveryHook> | null;
|
|
12
11
|
sessionNotification: ReturnType<typeof createSessionNotification> | null;
|
|
@@ -7,7 +7,14 @@ type MessageWithParts = {
|
|
|
7
7
|
type MessagesTransformOutput = {
|
|
8
8
|
messages: MessageWithParts[];
|
|
9
9
|
};
|
|
10
|
+
type MessagesTransformHooks = {
|
|
11
|
+
contextInjectorMessagesTransform?: CreatedHooks["contextInjectorMessagesTransform"];
|
|
12
|
+
teamModeStatusInjector?: CreatedHooks["teamModeStatusInjector"];
|
|
13
|
+
teamMailboxInjector?: CreatedHooks["teamMailboxInjector"];
|
|
14
|
+
thinkingBlockValidator?: CreatedHooks["thinkingBlockValidator"];
|
|
15
|
+
toolPairValidator?: CreatedHooks["toolPairValidator"];
|
|
16
|
+
};
|
|
10
17
|
export declare function createMessagesTransformHandler(args: {
|
|
11
|
-
hooks:
|
|
18
|
+
hooks: MessagesTransformHooks;
|
|
12
19
|
}): (input: Record<string, never>, output: MessagesTransformOutput) => Promise<void>;
|
|
13
20
|
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type UserAbortInterruptedRecoveryGuard = {
|
|
2
|
+
readonly noteSessionError: (sessionID: string, errorName: string | undefined) => boolean;
|
|
3
|
+
readonly shouldSkipRecovery: (sessionID: string) => boolean;
|
|
4
|
+
readonly clear: (sessionID: string) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare function createUserAbortInterruptedRecoveryGuard(): UserAbortInterruptedRecoveryGuard;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type RecentPromptDispatch = {
|
|
2
|
+
readonly source: string;
|
|
3
|
+
readonly expiresAt: number;
|
|
4
|
+
};
|
|
5
|
+
export declare function getRecentPromptDispatch(sessionID: string, dedupeKey: string): RecentPromptDispatch | undefined;
|
|
6
|
+
export declare function rememberRecentPromptDispatch(args: {
|
|
7
|
+
readonly sessionID: string;
|
|
8
|
+
readonly dedupeKey: string;
|
|
9
|
+
readonly source: string;
|
|
10
|
+
readonly holdMs: number;
|
|
11
|
+
}): void;
|
|
12
|
+
export declare function deleteRecentPromptDispatch(sessionID: string, dedupeKey: string): void;
|
|
13
|
+
export declare function clearRecentPromptDispatchesForTesting(): void;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InternalPromptDispatchResult } from "./types";
|
|
2
|
+
export declare function createSemanticPromptDedupeKey(input: unknown): string;
|
|
3
|
+
export declare function coalesceRecentSemanticPromptDispatch(args: {
|
|
4
|
+
readonly sessionID: string;
|
|
5
|
+
readonly dedupeKey: string;
|
|
6
|
+
readonly source: string;
|
|
7
|
+
}): InternalPromptDispatchResult | undefined;
|
|
@@ -8,6 +8,7 @@ export declare function dispatchAfterSessionIdle<TInput>(args: {
|
|
|
8
8
|
readonly dedupeKey: string;
|
|
9
9
|
readonly settleMs: number;
|
|
10
10
|
readonly postDispatchHoldMs: number;
|
|
11
|
+
readonly semanticDedupeHoldMs: number;
|
|
11
12
|
readonly dispatchTimeoutMs: number;
|
|
12
13
|
readonly checkStatus: boolean;
|
|
13
14
|
readonly checkToolState: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const DEFAULT_PROMPT_ASYNC_POST_DISPATCH_HOLD_MS = 2000;
|
|
2
|
+
export declare const DEFAULT_PROMPT_SEMANTIC_DEDUPE_HOLD_MS = 15000;
|
|
2
3
|
export declare const DEFAULT_PROMPT_DISPATCH_TIMEOUT_MS = 30000;
|
|
3
4
|
export declare const DEFAULT_PROMPT_GATE_MESSAGES_FETCH_TIMEOUT_MS = 5000;
|
|
4
5
|
export declare const DEFAULT_PROMPT_QUEUE_RETRY_MS = 250;
|
|
@@ -49,6 +49,7 @@ type InternalPromptDispatchCommonArgs<TInput> = {
|
|
|
49
49
|
readonly queueRetryMs?: number;
|
|
50
50
|
readonly settleMs?: number;
|
|
51
51
|
readonly postDispatchHoldMs?: number;
|
|
52
|
+
readonly semanticDedupeHoldMs?: number;
|
|
52
53
|
readonly dispatchTimeoutMs?: number;
|
|
53
54
|
readonly checkStatus?: boolean;
|
|
54
55
|
readonly checkToolState?: boolean;
|
|
@@ -112,6 +113,7 @@ export type QueuedInternalPrompt = {
|
|
|
112
113
|
readonly dedupeKey: string;
|
|
113
114
|
readonly settleMs: number;
|
|
114
115
|
readonly postDispatchHoldMs: number;
|
|
116
|
+
readonly semanticDedupeHoldMs: number;
|
|
115
117
|
readonly dispatchTimeoutMs: number;
|
|
116
118
|
readonly queueRetryMs: number;
|
|
117
119
|
readonly checkStatus: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { InternalPromptDispatchArgs, InternalPromptDispatchResult, PromptAsyncInput, PromptAsyncReservationReleaseOptions } from "./prompt-async-gate/types";
|
|
2
|
-
export { DEFAULT_PROMPT_ASYNC_POST_DISPATCH_HOLD_MS, DEFAULT_PROMPT_DISPATCH_TIMEOUT_MS, DEFAULT_PROMPT_GATE_MESSAGES_FETCH_TIMEOUT_MS, DEFAULT_PROMPT_QUEUE_RETRY_MS, _setPromptGateMessagesFetchTimeoutMsForTesting, } from "./prompt-async-gate/timing";
|
|
2
|
+
export { DEFAULT_PROMPT_ASYNC_POST_DISPATCH_HOLD_MS, DEFAULT_PROMPT_DISPATCH_TIMEOUT_MS, DEFAULT_PROMPT_GATE_MESSAGES_FETCH_TIMEOUT_MS, DEFAULT_PROMPT_QUEUE_RETRY_MS, DEFAULT_PROMPT_SEMANTIC_DEDUPE_HOLD_MS, _setPromptGateMessagesFetchTimeoutMsForTesting, } from "./prompt-async-gate/timing";
|
|
3
3
|
export type { InternalPromptDispatchArgs, InternalPromptDispatchMode, InternalPromptDispatchResult, InternalPromptQueueBehavior, PromptAsyncGateResult, } from "./prompt-async-gate/types";
|
|
4
4
|
export declare function dispatchInternalPrompt<TInput = PromptAsyncInput>(args: InternalPromptDispatchArgs<TInput>): Promise<InternalPromptDispatchResult>;
|
|
5
5
|
export declare function releaseAllPromptAsyncReservationsForTesting(): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-my-opencode",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"packages/rules-engine",
|
|
10
10
|
"packages/ast-grep-core",
|
|
11
11
|
"packages/ast-grep-mcp",
|
|
12
|
+
"packages/git-bash-mcp",
|
|
12
13
|
"packages/utils",
|
|
13
14
|
"packages/model-core",
|
|
14
15
|
"packages/prompts-core",
|
|
@@ -23,7 +24,8 @@
|
|
|
23
24
|
"oh-my-opencode": "bin/oh-my-opencode.js",
|
|
24
25
|
"oh-my-openagent": "bin/oh-my-opencode.js",
|
|
25
26
|
"omo": "bin/oh-my-opencode.js",
|
|
26
|
-
"lazycodex": "bin/oh-my-opencode.js"
|
|
27
|
+
"lazycodex": "bin/oh-my-opencode.js",
|
|
28
|
+
"lazycodex-ai": "bin/oh-my-opencode.js"
|
|
27
29
|
},
|
|
28
30
|
"files": [
|
|
29
31
|
"dist",
|
|
@@ -35,6 +37,7 @@
|
|
|
35
37
|
".agents/skills",
|
|
36
38
|
"packages/lsp-tools-mcp/dist",
|
|
37
39
|
"packages/ast-grep-mcp/dist",
|
|
40
|
+
"packages/git-bash-mcp/dist",
|
|
38
41
|
"packages/shared-skills/package.json",
|
|
39
42
|
"packages/shared-skills/index.mjs",
|
|
40
43
|
"packages/shared-skills/skills",
|
|
@@ -52,7 +55,7 @@
|
|
|
52
55
|
"./schema.json": "./dist/oh-my-opencode.schema.json"
|
|
53
56
|
},
|
|
54
57
|
"scripts": {
|
|
55
|
-
"build": "bun run build:ast-grep-mcp && bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi --external zod && bun run build:node-require-shim && tsc --emitDeclarationOnly && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi && bun run build:schema",
|
|
58
|
+
"build": "bun run build:ast-grep-mcp && bun run build:git-bash-mcp && bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi --external zod && bun run build:node-require-shim && tsc --emitDeclarationOnly && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi && bun run build:schema",
|
|
56
59
|
"build:lsp-tools-mcp": "npm --prefix packages/lsp-tools-mcp ci && npm --prefix packages/lsp-tools-mcp run build",
|
|
57
60
|
"build:node-require-shim": "bun run script/patch-node-require-shim.ts",
|
|
58
61
|
"build:all": "bun run build && bun run build:binaries",
|
|
@@ -65,12 +68,13 @@
|
|
|
65
68
|
"prepublishOnly": "bun run clean && bun run build:lsp-tools-mcp && bun run build",
|
|
66
69
|
"test:model-capabilities": "bun test src/shared/model-capability-aliases.test.ts src/shared/model-capability-guardrails.test.ts src/shared/model-capabilities.test.ts src/cli/doctor/checks/model-resolution.test.ts --bail",
|
|
67
70
|
"typecheck": "tsgo --noEmit && bun run typecheck:packages",
|
|
68
|
-
"typecheck:packages": "tsgo --noEmit -p packages/rules-engine/tsconfig.json && tsgo --noEmit -p packages/ast-grep-core/tsconfig.json && tsgo --noEmit -p packages/ast-grep-mcp/tsconfig.json && tsgo --noEmit -p packages/utils/tsconfig.json && tsgo --noEmit -p packages/model-core/tsconfig.json && tsgo --noEmit -p packages/prompts-core/tsconfig.json && tsgo --noEmit -p packages/comment-checker-core/tsconfig.json && tsgo --noEmit -p packages/hashline-core/tsconfig.json && tsgo --noEmit -p packages/boulder-state/tsconfig.json && tsgo --noEmit -p packages/agents-md-core/tsconfig.json && tsgo --noEmit -p packages/omo-codex/tsconfig.json",
|
|
71
|
+
"typecheck:packages": "tsgo --noEmit -p packages/rules-engine/tsconfig.json && tsgo --noEmit -p packages/ast-grep-core/tsconfig.json && tsgo --noEmit -p packages/ast-grep-mcp/tsconfig.json && tsgo --noEmit -p packages/git-bash-mcp/tsconfig.json && tsgo --noEmit -p packages/utils/tsconfig.json && tsgo --noEmit -p packages/model-core/tsconfig.json && tsgo --noEmit -p packages/prompts-core/tsconfig.json && tsgo --noEmit -p packages/comment-checker-core/tsconfig.json && tsgo --noEmit -p packages/hashline-core/tsconfig.json && tsgo --noEmit -p packages/boulder-state/tsconfig.json && tsgo --noEmit -p packages/agents-md-core/tsconfig.json && tsgo --noEmit -p packages/omo-codex/tsconfig.json",
|
|
69
72
|
"typecheck:script": "tsgo --noEmit -p script/tsconfig.json",
|
|
70
73
|
"test": "bun test",
|
|
71
|
-
"test:codex": "bun run build:ast-grep-mcp && bun run build:lsp-tools-mcp && npm --prefix packages/omo-codex/plugin ci && bun run --cwd packages/omo-codex/plugin build && bun test src/cli/cli-installer.platform.test.ts src/cli/install-codex/codex-cache.test.ts src/cli/install-codex/codex-config-agent-cleanup.test.ts src/cli/install-codex/codex-config-toml.test.ts src/cli/install-codex/install-codex.test.ts src/cli/install-codex/link-cached-plugin-agents.test.ts packages/omo-codex/src/**/*.test.ts packages/utils/src/jsonc-parser.test.ts packages/utils/src/frontmatter.test.ts packages/hashline-core/src/hash-computation.test.ts packages/hashline-core/src/smoke-untested-modules.test.ts packages/rules-engine/src/index.test.ts packages/rules-engine/src/security-boundary.test.ts packages/agents-md-core/src/injector.test.ts packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts && node --test packages/omo-codex/plugin/test/*.test.mjs packages/omo-codex/scripts/install-cache-copy.test.mjs packages/omo-codex/scripts/install-config.test.mjs packages/omo-codex/scripts/install-local.test.mjs packages/omo-codex/scripts/install-mcp-runtime.test.mjs packages/omo-codex/scripts/install-agent-links.test.mjs packages/omo-codex/scripts/install-bin-links.test.mjs packages/omo-codex/scripts/sync-telemetry-component.test.mjs",
|
|
74
|
+
"test:codex": "bun run build:ast-grep-mcp && bun run build:lsp-tools-mcp && npm --prefix packages/omo-codex/plugin ci && bun run --cwd packages/omo-codex/plugin build && bun test src/cli/cli-installer.platform.test.ts src/cli/install-codex/codex-cache.test.ts src/cli/install-codex/codex-cleanup.test.ts src/cli/install-codex/codex-config-agent-cleanup.test.ts src/cli/install-codex/codex-config-reasoning.test.ts src/cli/install-codex/codex-config-toml.test.ts src/cli/install-codex/codex-project-local-cleanup.test.ts src/cli/install-codex/install-codex-project-local-cleanup.test.ts src/cli/install-codex/install-codex.test.ts src/cli/install-codex/install-codex-packaged.test.ts src/cli/install-codex/link-cached-plugin-agents.test.ts packages/omo-codex/src/**/*.test.ts packages/utils/src/jsonc-parser.test.ts packages/utils/src/frontmatter.test.ts packages/hashline-core/src/hash-computation.test.ts packages/hashline-core/src/smoke-untested-modules.test.ts packages/rules-engine/src/index.test.ts packages/rules-engine/src/security-boundary.test.ts packages/agents-md-core/src/injector.test.ts packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts && node --test packages/omo-codex/plugin/test/*.test.mjs packages/omo-codex/scripts/install-cache-copy.test.mjs packages/omo-codex/scripts/install-cli-args.test.mjs packages/omo-codex/scripts/install-config-autonomous.test.mjs packages/omo-codex/scripts/install-config-reasoning.test.mjs packages/omo-codex/scripts/install-config.test.mjs packages/omo-codex/scripts/install-project-local-cleanup.test.mjs packages/omo-codex/scripts/install-local-entrypoint.test.mjs packages/omo-codex/scripts/install-local-git-bash-preflight.test.mjs packages/omo-codex/scripts/install-local.test.mjs packages/omo-codex/scripts/install-mcp-runtime.test.mjs packages/omo-codex/scripts/install-packaged-local.test.mjs packages/omo-codex/scripts/install/git-bash.test.mjs packages/omo-codex/scripts/install-agent-links.test.mjs packages/omo-codex/scripts/install-bin-links.test.mjs packages/omo-codex/scripts/sync-telemetry-component.test.mjs",
|
|
72
75
|
"test:windows-codex": "bun run test:codex",
|
|
73
|
-
"build:ast-grep-mcp": "bun run --cwd packages/ast-grep-mcp build"
|
|
76
|
+
"build:ast-grep-mcp": "bun run --cwd packages/ast-grep-mcp build",
|
|
77
|
+
"build:git-bash-mcp": "bun run --cwd packages/git-bash-mcp build"
|
|
74
78
|
},
|
|
75
79
|
"keywords": [
|
|
76
80
|
"opencode",
|
|
@@ -113,6 +117,7 @@
|
|
|
113
117
|
"devDependencies": {
|
|
114
118
|
"@oh-my-opencode/ast-grep-core": "workspace:*",
|
|
115
119
|
"@oh-my-opencode/ast-grep-mcp": "workspace:*",
|
|
120
|
+
"@oh-my-opencode/git-bash-mcp": "workspace:*",
|
|
116
121
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
117
122
|
"@oh-my-opencode/boulder-state": "workspace:*",
|
|
118
123
|
"@oh-my-opencode/comment-checker-core": "workspace:*",
|
|
@@ -131,17 +136,17 @@
|
|
|
131
136
|
"zod": "^4.4.3"
|
|
132
137
|
},
|
|
133
138
|
"optionalDependencies": {
|
|
134
|
-
"oh-my-opencode-darwin-arm64": "4.
|
|
135
|
-
"oh-my-opencode-darwin-x64": "4.
|
|
136
|
-
"oh-my-opencode-darwin-x64-baseline": "4.
|
|
137
|
-
"oh-my-opencode-linux-arm64": "4.
|
|
138
|
-
"oh-my-opencode-linux-arm64-musl": "4.
|
|
139
|
-
"oh-my-opencode-linux-x64": "4.
|
|
140
|
-
"oh-my-opencode-linux-x64-baseline": "4.
|
|
141
|
-
"oh-my-opencode-linux-x64-musl": "4.
|
|
142
|
-
"oh-my-opencode-linux-x64-musl-baseline": "4.
|
|
143
|
-
"oh-my-opencode-windows-x64": "4.
|
|
144
|
-
"oh-my-opencode-windows-x64-baseline": "4.
|
|
139
|
+
"oh-my-opencode-darwin-arm64": "4.6.0",
|
|
140
|
+
"oh-my-opencode-darwin-x64": "4.6.0",
|
|
141
|
+
"oh-my-opencode-darwin-x64-baseline": "4.6.0",
|
|
142
|
+
"oh-my-opencode-linux-arm64": "4.6.0",
|
|
143
|
+
"oh-my-opencode-linux-arm64-musl": "4.6.0",
|
|
144
|
+
"oh-my-opencode-linux-x64": "4.6.0",
|
|
145
|
+
"oh-my-opencode-linux-x64-baseline": "4.6.0",
|
|
146
|
+
"oh-my-opencode-linux-x64-musl": "4.6.0",
|
|
147
|
+
"oh-my-opencode-linux-x64-musl-baseline": "4.6.0",
|
|
148
|
+
"oh-my-opencode-windows-x64": "4.6.0",
|
|
149
|
+
"oh-my-opencode-windows-x64-baseline": "4.6.0"
|
|
145
150
|
},
|
|
146
151
|
"overrides": {
|
|
147
152
|
"hono": "^4.12.18",
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { argv, stderr } from "node:process";
|
|
5
|
+
|
|
6
|
+
// src/git-bash-resolver.ts
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
var GIT_BASH_ENV_KEY = "OMO_CODEX_GIT_BASH_PATH";
|
|
10
|
+
var PROGRAM_FILES_GIT_BASH = "C:\\Program Files\\Git\\bin\\bash.exe";
|
|
11
|
+
var PROGRAM_FILES_X86_GIT_BASH = "C:\\Program Files (x86)\\Git\\bin\\bash.exe";
|
|
12
|
+
function resolveGitBash(input) {
|
|
13
|
+
if (input.platform !== "win32")
|
|
14
|
+
return { found: true, path: null, source: "not-required" };
|
|
15
|
+
const checkedPaths = [];
|
|
16
|
+
const envPath = nonEmptyEnvValue(input.env, GIT_BASH_ENV_KEY);
|
|
17
|
+
if (envPath !== undefined) {
|
|
18
|
+
checkedPaths.push(envPath);
|
|
19
|
+
if (isBashExePath(envPath) && input.exists(envPath))
|
|
20
|
+
return { found: true, path: envPath, source: "env" };
|
|
21
|
+
return missingGitBash(checkedPaths);
|
|
22
|
+
}
|
|
23
|
+
for (const candidate of [
|
|
24
|
+
{ path: PROGRAM_FILES_GIT_BASH, source: "program-files" },
|
|
25
|
+
{ path: PROGRAM_FILES_X86_GIT_BASH, source: "program-files-x86" }
|
|
26
|
+
]) {
|
|
27
|
+
checkedPaths.push(candidate.path);
|
|
28
|
+
if (input.exists(candidate.path))
|
|
29
|
+
return { found: true, path: candidate.path, source: candidate.source };
|
|
30
|
+
}
|
|
31
|
+
for (const pathCandidate of input.where("bash")) {
|
|
32
|
+
const candidate = pathCandidate.trim();
|
|
33
|
+
if (candidate.length === 0)
|
|
34
|
+
continue;
|
|
35
|
+
checkedPaths.push(candidate);
|
|
36
|
+
if (isBashExePath(candidate) && input.exists(candidate))
|
|
37
|
+
return { found: true, path: candidate, source: "path" };
|
|
38
|
+
}
|
|
39
|
+
return missingGitBash(checkedPaths);
|
|
40
|
+
}
|
|
41
|
+
function resolveGitBashForCurrentProcess(input = {}) {
|
|
42
|
+
return resolveGitBash({
|
|
43
|
+
platform: input.platform ?? process.platform,
|
|
44
|
+
env: input.env ?? process.env,
|
|
45
|
+
exists: existsSync,
|
|
46
|
+
where: whereCommand
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function missingGitBash(checkedPaths) {
|
|
50
|
+
return {
|
|
51
|
+
found: false,
|
|
52
|
+
checkedPaths,
|
|
53
|
+
installHint: [
|
|
54
|
+
"Git Bash is required before the git_bash MCP can run commands on native Windows.",
|
|
55
|
+
"Install it with: winget install --id Git.Git -e --source winget",
|
|
56
|
+
`For a custom install, set ${GIT_BASH_ENV_KEY}=C:\\path\\to\\bash.exe`
|
|
57
|
+
].join(`
|
|
58
|
+
`)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function nonEmptyEnvValue(env, key) {
|
|
62
|
+
const value = env[key];
|
|
63
|
+
if (value === undefined)
|
|
64
|
+
return;
|
|
65
|
+
const trimmed = value.trim();
|
|
66
|
+
return trimmed.length === 0 ? undefined : trimmed;
|
|
67
|
+
}
|
|
68
|
+
function isBashExePath(path) {
|
|
69
|
+
return path.toLowerCase().endsWith("bash.exe");
|
|
70
|
+
}
|
|
71
|
+
function whereCommand(command) {
|
|
72
|
+
try {
|
|
73
|
+
return execFileSync("where", [command], { encoding: "utf8" }).split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error instanceof Error)
|
|
76
|
+
return [];
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/runner.ts
|
|
82
|
+
import { spawn } from "node:child_process";
|
|
83
|
+
async function runGitBashCommand(input) {
|
|
84
|
+
return await new Promise((resolve, reject) => {
|
|
85
|
+
const child = spawn(input.bashPath, ["-lc", input.command], {
|
|
86
|
+
cwd: input.cwd,
|
|
87
|
+
env: input.env,
|
|
88
|
+
windowsHide: true,
|
|
89
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
90
|
+
});
|
|
91
|
+
let stdout = "";
|
|
92
|
+
let stderr = "";
|
|
93
|
+
let timedOut = false;
|
|
94
|
+
const timeout = setTimeout(() => {
|
|
95
|
+
timedOut = true;
|
|
96
|
+
child.kill();
|
|
97
|
+
}, input.timeoutMs);
|
|
98
|
+
timeout.unref();
|
|
99
|
+
child.stdout.setEncoding("utf8");
|
|
100
|
+
child.stderr.setEncoding("utf8");
|
|
101
|
+
child.stdout.on("data", (chunk) => {
|
|
102
|
+
stdout += chunk;
|
|
103
|
+
});
|
|
104
|
+
child.stderr.on("data", (chunk) => {
|
|
105
|
+
stderr += chunk;
|
|
106
|
+
});
|
|
107
|
+
child.on("error", (error) => {
|
|
108
|
+
clearTimeout(timeout);
|
|
109
|
+
reject(error);
|
|
110
|
+
});
|
|
111
|
+
child.on("close", (exitCode) => {
|
|
112
|
+
clearTimeout(timeout);
|
|
113
|
+
resolve({ exitCode, stdout, stderr, timedOut });
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/mcp.ts
|
|
119
|
+
var DEFAULT_TIMEOUT_MS = 120000;
|
|
120
|
+
var MAX_TIMEOUT_MS = 30 * 60000;
|
|
121
|
+
var EXEC_COMMAND_TIMEOUT_ENV_KEYS = [
|
|
122
|
+
"OMO_CODEX_GIT_BASH_TIMEOUT_MS",
|
|
123
|
+
"OMO_CODEX_EXEC_COMMAND_TIMEOUT_MS",
|
|
124
|
+
"CODEX_EXEC_COMMAND_TIMEOUT_MS",
|
|
125
|
+
"EXEC_COMMAND_TIMEOUT_MS"
|
|
126
|
+
];
|
|
127
|
+
async function handleGitBashMcpRequest(input, options = {}) {
|
|
128
|
+
if (!isRecord(input))
|
|
129
|
+
return errorResponse(null, -32600, "Invalid Request");
|
|
130
|
+
const id = jsonRpcId(input.id);
|
|
131
|
+
const method = typeof input.method === "string" ? input.method : null;
|
|
132
|
+
if (method === "initialize") {
|
|
133
|
+
const protocolVersion = protocolVersionFromInput(input) ?? "2024-11-05";
|
|
134
|
+
return successResponse(id, {
|
|
135
|
+
capabilities: { tools: { listChanged: false } },
|
|
136
|
+
serverInfo: { name: "git_bash", version: "0.1.0" },
|
|
137
|
+
protocolVersion
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (method === "tools/list")
|
|
141
|
+
return successResponse(id, { tools: toolsForOptions(options) });
|
|
142
|
+
if (method === "tools/call") {
|
|
143
|
+
const params = isRecord(input.params) ? input.params : {};
|
|
144
|
+
const name = typeof params.name === "string" ? params.name : "";
|
|
145
|
+
const args = isRecord(params.arguments) ? params.arguments : {};
|
|
146
|
+
return await callTool(id, name, args, options);
|
|
147
|
+
}
|
|
148
|
+
if (method === "notifications/initialized")
|
|
149
|
+
return;
|
|
150
|
+
return errorResponse(id, -32601, "Method not found");
|
|
151
|
+
}
|
|
152
|
+
async function runMcpStdioServer(input, output, options = {}) {
|
|
153
|
+
if (!canRunGitBash(options))
|
|
154
|
+
return;
|
|
155
|
+
let buffer = "";
|
|
156
|
+
for await (const chunk of input) {
|
|
157
|
+
buffer += String(chunk);
|
|
158
|
+
while (true) {
|
|
159
|
+
const lineEnd = buffer.indexOf(`
|
|
160
|
+
`);
|
|
161
|
+
if (lineEnd === -1)
|
|
162
|
+
break;
|
|
163
|
+
const line = buffer.slice(0, lineEnd).trim();
|
|
164
|
+
buffer = buffer.slice(lineEnd + 1);
|
|
165
|
+
if (line.length === 0)
|
|
166
|
+
continue;
|
|
167
|
+
const response = await handleGitBashMcpRequest(parseJsonRpcLine(line), options);
|
|
168
|
+
if (response !== undefined)
|
|
169
|
+
output.write(`${JSON.stringify(response)}
|
|
170
|
+
`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async function callTool(id, name, args, options) {
|
|
175
|
+
if (name === "which_bash")
|
|
176
|
+
return toolResponse(id, whichBashPayload(resolve(options)));
|
|
177
|
+
if (name === "diagnose")
|
|
178
|
+
return toolResponse(id, diagnosePayload(resolve(options), platformFromOptions(options)));
|
|
179
|
+
if (name === "run")
|
|
180
|
+
return await runToolResponse(id, args, options);
|
|
181
|
+
return toolResponse(id, `Unknown git_bash tool: ${name}`, true);
|
|
182
|
+
}
|
|
183
|
+
async function runToolResponse(id, args, options) {
|
|
184
|
+
const platform = platformFromOptions(options);
|
|
185
|
+
if (platform !== "win32")
|
|
186
|
+
return toolResponse(id, "git_bash run is only available on native Windows.", true);
|
|
187
|
+
const command = typeof args.command === "string" ? args.command.trim() : "";
|
|
188
|
+
if (command.length === 0)
|
|
189
|
+
return toolResponse(id, "run.command must be a non-empty string.", true);
|
|
190
|
+
const cwd = parseWorkdir(args);
|
|
191
|
+
if (cwd === null)
|
|
192
|
+
return toolResponse(id, "run.workdir must be a non-empty string when provided.", true);
|
|
193
|
+
const timeoutMs = parseTimeoutMs(args.timeout ?? args.timeout_ms, options);
|
|
194
|
+
if (timeoutMs === null)
|
|
195
|
+
return toolResponse(id, `run.timeout must be an integer between 1 and ${MAX_TIMEOUT_MS}.`, true);
|
|
196
|
+
const resolution = resolve(options);
|
|
197
|
+
if (!resolution.found || resolution.path === null)
|
|
198
|
+
return toolResponse(id, whichBashPayload(resolution), true);
|
|
199
|
+
try {
|
|
200
|
+
const run = options.runGitBash ?? runGitBashCommand;
|
|
201
|
+
const result = await run({ bashPath: resolution.path, command, cwd, timeoutMs, env: options.env ?? process.env });
|
|
202
|
+
return toolResponse(id, runPayload(result));
|
|
203
|
+
} catch (error) {
|
|
204
|
+
return toolResponse(id, error instanceof Error ? error.message : String(error), true);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function toolsForOptions(options) {
|
|
208
|
+
const sharedTools = [
|
|
209
|
+
{
|
|
210
|
+
name: "which_bash",
|
|
211
|
+
description: "Resolve the Git Bash bash.exe path used by the git_bash MCP.",
|
|
212
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: "diagnose",
|
|
216
|
+
description: "Report whether Git Bash command execution is available on this host.",
|
|
217
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
218
|
+
}
|
|
219
|
+
];
|
|
220
|
+
if (!canRunGitBash(options))
|
|
221
|
+
return sharedTools;
|
|
222
|
+
return [
|
|
223
|
+
{
|
|
224
|
+
name: "run",
|
|
225
|
+
description: "Run a shell command through Git Bash on native Windows. Prefer this git_bash run tool for bash/shell commands on Windows before built-in exec_command or Bash; use exec_command only when git_bash is unavailable or for non-shell operations.",
|
|
226
|
+
inputSchema: {
|
|
227
|
+
type: "object",
|
|
228
|
+
properties: {
|
|
229
|
+
command: { type: "string", description: "The command to execute." },
|
|
230
|
+
timeout: {
|
|
231
|
+
type: "integer",
|
|
232
|
+
minimum: 1,
|
|
233
|
+
maximum: MAX_TIMEOUT_MS,
|
|
234
|
+
description: `Optional timeout in milliseconds. If omitted, uses the inherited exec_command timeout when configured; otherwise ${defaultTimeoutMs(options)}ms.`
|
|
235
|
+
},
|
|
236
|
+
workdir: {
|
|
237
|
+
type: "string",
|
|
238
|
+
description: "The working directory to run the command in. Defaults to the current directory. Use this instead of 'cd' commands."
|
|
239
|
+
},
|
|
240
|
+
description: {
|
|
241
|
+
type: "string",
|
|
242
|
+
description: "Clear, concise description of what this command does in 5-10 words."
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
required: ["command"],
|
|
246
|
+
additionalProperties: false
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
...sharedTools
|
|
250
|
+
];
|
|
251
|
+
}
|
|
252
|
+
function canRunGitBash(options) {
|
|
253
|
+
if (platformFromOptions(options) !== "win32")
|
|
254
|
+
return false;
|
|
255
|
+
const resolution = resolve(options);
|
|
256
|
+
return resolution.found && resolution.path !== null;
|
|
257
|
+
}
|
|
258
|
+
function resolve(options) {
|
|
259
|
+
if (options.exists === undefined && options.where === undefined) {
|
|
260
|
+
return resolveGitBashForCurrentProcess({
|
|
261
|
+
platform: options.platform,
|
|
262
|
+
env: options.env
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
return resolveGitBash({
|
|
266
|
+
platform: platformFromOptions(options),
|
|
267
|
+
env: options.env ?? process.env,
|
|
268
|
+
exists: options.exists ?? (() => false),
|
|
269
|
+
where: options.where ?? (() => [])
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
function platformFromOptions(options) {
|
|
273
|
+
return options.platform ?? process.platform;
|
|
274
|
+
}
|
|
275
|
+
function whichBashPayload(resolution) {
|
|
276
|
+
return JSON.stringify(resolution, null, 2);
|
|
277
|
+
}
|
|
278
|
+
function diagnosePayload(resolution, platform) {
|
|
279
|
+
const enabled = platform === "win32" && resolution.found && resolution.path !== null;
|
|
280
|
+
const payload = {
|
|
281
|
+
platform,
|
|
282
|
+
enabled,
|
|
283
|
+
status: platform === "win32" ? enabled ? "ready" : "missing-git-bash" : "disabled: git_bash command execution is only exposed on native Windows",
|
|
284
|
+
resolution
|
|
285
|
+
};
|
|
286
|
+
return JSON.stringify(payload, null, 2);
|
|
287
|
+
}
|
|
288
|
+
function runPayload(result) {
|
|
289
|
+
return JSON.stringify(result, null, 2);
|
|
290
|
+
}
|
|
291
|
+
function toolResponse(id, text, isError = false) {
|
|
292
|
+
return successResponse(id, { content: [{ type: "text", text }], isError });
|
|
293
|
+
}
|
|
294
|
+
function successResponse(id, result) {
|
|
295
|
+
return { jsonrpc: "2.0", id, result };
|
|
296
|
+
}
|
|
297
|
+
function errorResponse(id, code, message, data) {
|
|
298
|
+
return { jsonrpc: "2.0", id, error: data === undefined ? { code, message } : { code, message, data } };
|
|
299
|
+
}
|
|
300
|
+
function parseWorkdir(args) {
|
|
301
|
+
const value = args.workdir ?? args.cwd;
|
|
302
|
+
if (value === undefined)
|
|
303
|
+
return;
|
|
304
|
+
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
305
|
+
}
|
|
306
|
+
function parseTimeoutMs(value, options) {
|
|
307
|
+
if (value === undefined)
|
|
308
|
+
return defaultTimeoutMs(options);
|
|
309
|
+
return normalizeTimeoutMs(value);
|
|
310
|
+
}
|
|
311
|
+
function defaultTimeoutMs(options) {
|
|
312
|
+
const configured = normalizeTimeoutMs(options.defaultTimeoutMs);
|
|
313
|
+
if (configured !== null)
|
|
314
|
+
return configured;
|
|
315
|
+
const env = options.env ?? process.env;
|
|
316
|
+
for (const key of EXEC_COMMAND_TIMEOUT_ENV_KEYS) {
|
|
317
|
+
const timeoutMs = normalizeTimeoutMs(env[key]);
|
|
318
|
+
if (timeoutMs !== null)
|
|
319
|
+
return timeoutMs;
|
|
320
|
+
}
|
|
321
|
+
return DEFAULT_TIMEOUT_MS;
|
|
322
|
+
}
|
|
323
|
+
function normalizeTimeoutMs(value) {
|
|
324
|
+
const parsed = typeof value === "string" && value.trim().length > 0 ? Number(value) : value;
|
|
325
|
+
if (!Number.isInteger(parsed))
|
|
326
|
+
return null;
|
|
327
|
+
const timeoutMs = Number(parsed);
|
|
328
|
+
if (timeoutMs < 1 || timeoutMs > MAX_TIMEOUT_MS)
|
|
329
|
+
return null;
|
|
330
|
+
return timeoutMs;
|
|
331
|
+
}
|
|
332
|
+
function protocolVersionFromInput(input) {
|
|
333
|
+
if (!isRecord(input.params))
|
|
334
|
+
return null;
|
|
335
|
+
return typeof input.params.protocolVersion === "string" ? input.params.protocolVersion : null;
|
|
336
|
+
}
|
|
337
|
+
function parseJsonRpcLine(line) {
|
|
338
|
+
try {
|
|
339
|
+
const parsed = JSON.parse(line);
|
|
340
|
+
return parsed;
|
|
341
|
+
} catch (error) {
|
|
342
|
+
return { jsonrpc: "2.0", id: null, method: null, parseError: error instanceof Error ? error.message : String(error) };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function jsonRpcId(value) {
|
|
346
|
+
return typeof value === "string" || typeof value === "number" || value === null ? value : null;
|
|
347
|
+
}
|
|
348
|
+
function isRecord(value) {
|
|
349
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/cli.ts
|
|
353
|
+
async function main() {
|
|
354
|
+
const [command = "mcp"] = argv.slice(2);
|
|
355
|
+
if (command === "mcp") {
|
|
356
|
+
await runMcpStdioServer(process.stdin, process.stdout);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
stderr.write(`Usage: omo-git-bash [mcp]
|
|
360
|
+
`);
|
|
361
|
+
process.exitCode = 2;
|
|
362
|
+
}
|
|
363
|
+
main().catch((error) => {
|
|
364
|
+
stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}
|
|
365
|
+
`);
|
|
366
|
+
process.exitCode = 1;
|
|
367
|
+
});
|
|
@@ -5,6 +5,17 @@
|
|
|
5
5
|
"args": ["../../ast-grep-mcp/dist/cli.js", "mcp"],
|
|
6
6
|
"cwd": "."
|
|
7
7
|
},
|
|
8
|
+
"grep_app": {
|
|
9
|
+
"url": "https://mcp.grep.app"
|
|
10
|
+
},
|
|
11
|
+
"context7": {
|
|
12
|
+
"url": "https://mcp.context7.com/mcp"
|
|
13
|
+
},
|
|
14
|
+
"git_bash": {
|
|
15
|
+
"command": "node",
|
|
16
|
+
"args": ["../../git-bash-mcp/dist/cli.js", "mcp"],
|
|
17
|
+
"cwd": "."
|
|
18
|
+
},
|
|
8
19
|
"lsp": {
|
|
9
20
|
"command": "node",
|
|
10
21
|
"args": ["../../lsp-tools-mcp/dist/cli.js", "mcp"],
|
|
@@ -52,7 +52,7 @@ node dist/cli.js hook post-tool-use < test/fixtures/post-tool-use.json
|
|
|
52
52
|
## Local Codex Installation
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
|
|
55
|
+
npx lazycodex-ai install
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
The installer builds and copies the plugin into `~/.codex/plugins/cache/sisyphuslabs/omo/0.1.0`, registers the `sisyphuslabs` marketplace from the `lazycodex` Git repository, installs runtime dependencies there, and enables:
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PreToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "^Bash$",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
|
|
10
|
+
"timeout": 5,
|
|
11
|
+
"statusMessage": "LazyCodex(0.1.0): Recommending Git Bash Mcp"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"PostCompact": [
|
|
17
|
+
{
|
|
18
|
+
"hooks": [
|
|
19
|
+
{
|
|
20
|
+
"type": "command",
|
|
21
|
+
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
22
|
+
"timeout": 5,
|
|
23
|
+
"statusMessage": "LazyCodex(0.1.0): Resetting Git Bash Mcp Reminder"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
}
|