refactor(openclaw): migrate onto ContainerAgentRuntime; collapse legacy ContainerRuntime#970
refactor(openclaw): migrate onto ContainerAgentRuntime; collapse legacy ContainerRuntime#970Dani Akash (DaniAkash) wants to merge 6 commits intodevfrom
Conversation
…time; delete legacy ContainerRuntime
✅ Tests passed — 1210/1214
|
Greptile SummaryMigrates the OpenClaw adapter onto
Confidence Score: 4/5Safe to merge; the refactor is well-scoped and backed by a comprehensive test suite. The style/logic observations do not block the happy path. The core behavioral change — moving ACP exec command assembly out of packages/browseros-agent/apps/server/src/lib/agents/runtime/openclaw-container-runtime.ts and packages/browseros-agent/apps/server/src/api/services/openclaw/openclaw-service.ts warrant a second look for the ignored-parameter and configure-path-drift issues noted above. Important Files Changed
Sequence DiagramsequenceDiagram
participant main as main.ts
participant reg as AgentRuntimeRegistry
participant svc as OpenClawService
participant rt as OpenClawContainerRuntime
participant acpx as AcpxRuntime
participant base as ContainerAgentRuntime
main->>reg: "configureOpenClawRuntime({ resourcesDir })"
reg-->>main: runtime registered
main->>svc: new OpenClawService(config)
svc->>reg: getOpenClawRuntime()
reg-->>svc: OpenClawContainerRuntime
svc->>rt: setHostPort(hostPort)
Note over svc,rt: Lifecycle ops
svc->>rt: startGateway(_, onLog)
rt->>base: "executeAction({ type: 'start' })"
base-->>svc: container started
Note over acpx,reg: ACP turn spawn
acpx->>reg: getOpenClawRuntime()
reg-->>acpx: runtime
acpx->>rt: "getAcpExecSpec({ commandEnv, sessionKey })"
rt-->>acpx: ExecSpec (argv + env)
acpx->>rt: buildExecArgv(execSpec)
rt-->>acpx: "env LIMA_HOME=... limactl shell ... nerdctl exec ... openclaw acp ..."
|
| async waitForReady(_hostPort?: number, timeoutMs = 30_000): Promise<boolean> { | ||
| const start = Date.now() | ||
| while (Date.now() - start < timeoutMs) { | ||
| if (await this.readinessProbe()) return true | ||
| await Bun.sleep(1000) | ||
| } | ||
| return false | ||
| } |
There was a problem hiding this comment.
Silently ignored
_hostPort parameter
waitForReady accepts a _hostPort argument that is immediately discarded; the method always probes this.hostPort via readinessProbe(). The service calls this.runtime.waitForReady(this.hostPort, READY_TIMEOUT_MS), so in practice the values always match — but the accepted parameter creates a false expectation that a caller could probe a different port. Any future caller passing a port other than this.hostPort will silently get the wrong port probed, with no error or warning.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/browseros-agent/apps/server/src/lib/agents/runtime/openclaw-container-runtime.ts
Line: 265-272
Comment:
**Silently ignored `_hostPort` parameter**
`waitForReady` accepts a `_hostPort` argument that is immediately discarded; the method always probes `this.hostPort` via `readinessProbe()`. The service calls `this.runtime.waitForReady(this.hostPort, READY_TIMEOUT_MS)`, so in practice the values always match — but the accepted parameter creates a false expectation that a caller could probe a different port. Any future caller passing a port other than `this.hostPort` will silently get the wrong port probed, with no error or warning.
How can I resolve this? If you propose a fix, please make it concise.…sts + linux CI work The previous configureOpenClawRuntime short-circuited to null on non-darwin, which caused OpenClawService's constructor to throw "runtime is not available on platform linux" on linux CI runners — breaking server-api tests (which build the service then mock service.runtime) and the server-integration test (which spawns the server on linux). The legacy ContainerRuntime constructor was platform-agnostic; this restores that. The runtime now constructs on every platform. descriptor.platforms: ['darwin'] is still the live signal for the UI / adapter health, and inherited start() fails at limactl-not-found on linux if anyone actually invokes it. Tests that override service.runtime post-construction (the standard pattern) work uniformly. ensureOpenClawRuntime simplifies to a one-liner. The configureOpenClawRuntime non-darwin test retargets to assert the runtime is still returned (instead of asserting null).
resolveBundledLimactl / resolveBundledLimaTemplate throw synchronously when the host has no Lima and no bundled resources — that fired during configureOpenClawRuntime on linux CI runners, breaking server-integration. Wrap both calls so construction falls back to the bare 'limactl' command name (and undefined template). Lifecycle ops still fail at spawn time on platforms without Lima, matching how Hermes/Claude/Codex degrade.
Summary
Migrates the OpenClaw adapter onto the
ContainerAgentRuntimebase, completing the runtime-architecture sweep (Hermes / Claude / Codex landed in earlier PRs). The legacy pre-ManagedContainerContainerRuntimeclass deletes;OpenClawServicekeeps its public surface but uses the new runtime for container operations.OpenClawContainerRuntime extends ContainerAgentRuntimeowns the gateway descriptor, container spec, readiness probe (HTTP/readyz), mount roots, ACP exec spec, and per-turn prep. InheritsisImageCurrent,getLogs,tailLogs,runOneShotfrom the base shipped in the predecessor PR.configureOpenClawRuntime()factory registers the runtime inAgentRuntimeRegistry. Returnsnullon non-darwin; idempotent on repeat calls (returns the already-registered instance).OpenClawServiceswaps its internalruntime: ContainerRuntimeforOpenClawContainerRuntime. Lifecycle methods (setup,start,stop,restart,tryAutoStart,prewarm,shutdown) delegate container ops via thin compat wrappers (startGateway/stopGateway/ etc. → inheritedexecuteAction). Auxiliary surface (logs, sibling-exec, image-current) routes through inherited base methods.resolveOpenclawAcpCommandand the entireOpenclawGatewayAccessorplumbing chain (server.ts→routes/agents.ts→agent-harness-service.ts→AcpxRuntime) deletes.prepareOpenClawContextco-locates with the runtime;acpx-agent-adapter.tsimports it from the runtime barrel.lib/agents/openclaw/prepare.tsdeletes.api/services/openclaw/container-runtime.ts(~430 LOC) and itscontainer-runtime-factory.tscompanion delete.Net diff: +615 source / −830 (legacy class removal dominates) + tests.
Test plan
bun run typecheckclean across the server packagebiome checkclean on touched sourcesopenclaw-container-runtime.test.ts— 9 cases covering descriptor, mount roots, dynamic hostPort plumbing, container spec composition, ACP exec spec (with + without session, plus synthetic session normalization),buildExecArgvchain, compat surface presence, and the platform-aware factory + idempotencyopenclaw-service.test.tsretargeted — drops spec-object assertions on the lifecycle calls (the runtime now owns the spec internally) and updates one mock for the readiness-vs-auth restart-port testacpx-runtime.test.tsopenclaw cases retargeted — register a realOpenClawContainerRuntimewith stub deps; the inheritedbuildExecArgvproduces the canonicalnerdctl exec openclaw acpchain via the registry pathmain.test.tsHermes/Claude/Codex/OpenClaw factory mocks consolidatedorigin/dev: aContainerCliname-release race and a browser-environmental observation tool test)server.integration.test.ts) passes — the spawned subprocess starts cleanly with the new runtime registered alongside the service