forked from openclaw/openclaw
-
Notifications
You must be signed in to change notification settings - Fork 0
Implement CliRuntimeFactory #19
Copy link
Copy link
Closed
Description
Context
Factory module that maps provider name strings to AgentRuntime instances. This is the single entry point for runtime instantiation — callers never construct runtime classes directly.
src/middleware/
├── types.ts ← AgentRuntime interface (PR #4)
├── cli-runtime-base.ts ← CLIRuntimeBase abstract class (PR #6)
├── runtimes/
│ ├── claude.ts ← ClaudeCliRuntime (#8, PR #9)
│ ├── gemini.ts ← GeminiCliRuntime (#10, PR #11)
│ ├── codex.ts ← CodexCliRuntime (#12, PR #13)
│ └── opencode.ts ← OpenCodeCliRuntime (OpenCodeCliRuntime (#16), PR #17)
└── runtime-factory.ts ← THIS ISSUE
Dependencies: all four CLI runtimes (PRs #9, #11, #13, #17 — all merged).
Specification
createCliRuntime(provider: string): AgentRuntime
Exported function that maps a provider name string to a new runtime instance.
Provider mapping:
| Input string | Runtime class | CLI binary |
|---|---|---|
"claude" |
ClaudeCliRuntime |
claude |
"gemini" |
GeminiCliRuntime |
gemini |
"codex" |
CodexCliRuntime |
codex |
"opencode" |
OpenCodeCliRuntime |
opencode |
Behavior:
- Input is case-insensitive:
"Claude","CLAUDE","claude"all map toClaudeCliRuntime - Whitespace is trimmed:
" claude "maps toClaudeCliRuntime - Unknown provider names throw a descriptive
Error:Unknown runtime provider "foo". Supported providers: claude, gemini, codex, opencode - Returns a new instance on each call (no singleton/caching — callers may need separate state)
Implementation approach
import { ClaudeCliRuntime } from "./runtimes/claude.js";
import { GeminiCliRuntime } from "./runtimes/gemini.js";
import { CodexCliRuntime } from "./runtimes/codex.js";
import { OpenCodeCliRuntime } from "./runtimes/opencode.js";
import type { AgentRuntime } from "./types.js";
const SUPPORTED_PROVIDERS = ["claude", "gemini", "codex", "opencode"] as const;
type SupportedProvider = (typeof SUPPORTED_PROVIDERS)[number];
export function createCliRuntime(provider: string): AgentRuntime {
const normalized = provider.trim().toLowerCase();
switch (normalized) {
case "claude":
return new ClaudeCliRuntime();
case "gemini":
return new GeminiCliRuntime();
case "codex":
return new CodexCliRuntime();
case "opencode":
return new OpenCodeCliRuntime();
default:
throw new Error(
`Unknown runtime provider "${provider}". Supported providers: ${SUPPORTED_PROVIDERS.join(", ")}`
);
}
}Exports
The module should also export:
SUPPORTED_PROVIDERS— the array of supported provider name strings (for validation, help text, etc.)SupportedProvider— the union type of supported provider names
Test file specification
Create src/middleware/runtime-factory.test.ts.
Test categories
Provider mapping (~5 tests):
"claude"returns instance ofClaudeCliRuntime"gemini"returns instance ofGeminiCliRuntime"codex"returns instance ofCodexCliRuntime"opencode"returns instance ofOpenCodeCliRuntime- Each returned instance satisfies
AgentRuntimeinterface (hasexecutemethod)
Input normalization (~3 tests):
- Case-insensitive:
"Claude","GEMINI","Codex"map correctly - Whitespace trimmed:
" claude "maps correctly - Mixed case + whitespace:
" OpenCode "maps correctly
Error handling (~2 tests):
- Unknown provider throws Error with descriptive message including the invalid name
- Error message lists all supported providers
Instance freshness (~1 test):
- Two calls with same provider return distinct instances (not the same reference)
SUPPORTED_PROVIDERS export (~1 test):
- Contains exactly
["claude", "gemini", "codex", "opencode"]
Total: ~12 tests
Acceptance criteria
-
src/middleware/runtime-factory.tsexportscreateCliRuntimefunction -
src/middleware/runtime-factory.tsexportsSUPPORTED_PROVIDERSarray -
src/middleware/runtime-factory.tsexportsSupportedProvidertype - All 4 providers map to correct runtime class instances
- Input is normalized (case-insensitive, trimmed)
- Unknown providers throw descriptive Error listing supported providers
- Each call returns a new instance (no singleton caching)
-
src/middleware/runtime-factory.test.tscovers all specified categories (~12 tests) - All tests pass via
npx vitest run src/middleware/runtime-factory.test.ts
References
src/middleware/types.ts—AgentRuntimeinterfacesrc/middleware/runtimes/claude.ts—ClaudeCliRuntimesrc/middleware/runtimes/gemini.ts—GeminiCliRuntimesrc/middleware/runtimes/codex.ts—CodexCliRuntimesrc/middleware/runtimes/opencode.ts—OpenCodeCliRuntime
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels