6e37722383
Add a `kind` field to BridgedConfig.Worker — "claude-code" (default) or "opencode" — the discriminator the CompositePeerLauncher will route spawn/reap by so each adapter drives only its own peer kind. Normalised to lower-case; blank/absent ⇒ claude-code, so every existing config and call site is unchanged. argv now defaults to the kind's own binary (claude vs opencode) rather than always `claude`, so an opencode profile never inherits the Claude command. kind is appended at the record tail; a new 14-arg back-compat constructor (git fields, no kind) keeps the CB-302 call sites working, and the existing 12-arg constructor is untouched. Also drop the never-used Primary(String) legacy constructor to keep the file warning-clean. example.yaml documents the key and carries a commented opencode-gemini profile. Tests cover default/normalisation/argv-defaulting. 245 tests green, config files 0 IDE problems.
96 lines
5.0 KiB
YAML
96 lines
5.0 KiB
YAML
# bridged configuration (example). Copy to bridged.yaml and adjust.
|
|
#
|
|
# bridged is the sole gateway between primary/worker Claude sessions and herdr.
|
|
# It is NOT a Claude process and must never carry ANTHROPIC_BASE_URL.
|
|
|
|
# REST + MCP listen address. Keep it on loopback — bridged is same-host in Stage-1.
|
|
bind:
|
|
host: 127.0.0.1
|
|
port: 8765
|
|
|
|
# herdr Unix socket. Omit to use the client default
|
|
# (${HERDR_SOCKET_PATH:-~/.config/herdr/herdr.sock}).
|
|
herdrSocket: ~/.config/herdr/herdr.sock
|
|
|
|
# How worker sessions are spawned. Define one or more named profiles (backends) under
|
|
# `workers`; each key is the profile name (also the ccs profile). `defaultWorker` picks
|
|
# which one a no-argument spawn uses (bridge_spawn with no profile / POST /workers).
|
|
#
|
|
# Shared knobs (placement/workspace/tabLabel) can be repeated per profile; they usually match.
|
|
# placement: tab → each worker lands in its OWN tab in a dedicated worker space (default).
|
|
# Use `pane` for the legacy behaviour (split the focused tab).
|
|
# mcpUrl → bridged mounts the bridge MCP (--mcp-config, inline) + reply charter
|
|
# (--append-system-prompt) as launch flags; nothing is written to the profile.
|
|
# tokenEnv → host env var holding the worker's auth token (value never stored in config);
|
|
# omit for a backend that needs no token (e.g. a local ollama).
|
|
# cwd → pin this profile's working directory (CB-112). Omit to inherit the primary's
|
|
# cwd on an MCP spawn, else the daemon's cwd — never $HOME. See
|
|
# docs/Worker-Startup-and-Trust.md.
|
|
# Put `defaultMode: "auto"` in each ccs profile so the worker runs autonomously.
|
|
workers:
|
|
gx10: # ccs profile name (NOT a hostname)
|
|
kind: claude-code # which adapter spawns this profile (default; may omit)
|
|
baseUrl: http://gx01.gw:8000 # the vLLM host this profile targets (gx00.gw / gx01.gw)
|
|
model: coder
|
|
placement: tab
|
|
workspace: bridged-workers
|
|
tabLabel: "worker: {profile} #{n}" # {profile}/{model}/{n} substituted; {n} keeps sibling tabs distinct
|
|
mcpUrl: http://127.0.0.1:8765/mcp
|
|
tokenEnv: BRIDGED_WORKER_TOKEN
|
|
argv: ["ccs", "gx10"]
|
|
ollama:
|
|
baseUrl: http://ollama.ltms.dev # local/self-hosted; usually no token
|
|
placement: tab
|
|
workspace: bridged-workers
|
|
tabLabel: "worker: {profile} #{n}"
|
|
mcpUrl: http://127.0.0.1:8765/mcp
|
|
argv: ["ccs", "ollama"]
|
|
# CB-402: a second coding-agent kind, proving the PeerLauncher SPI is provider-neutral.
|
|
# opencode is provider-agnostic and uses NONE of Claude's private seams: no ANTHROPIC_BASE_URL /
|
|
# SubscriptionGuard (so it needs no `guard` host entry), no --mcp-config / --append-system-prompt.
|
|
# The bridge MCP + reply charter mount via a generated OPENCODE_CONFIG file, and the model is a
|
|
# `provider/model` selector. Placement, tabs, cwd, and the readiness gate are shared with Claude.
|
|
# opencode-gemini:
|
|
# kind: opencode
|
|
# model: google/gemini-2.5-pro # opencode `provider/model` selector, injected as `-m`
|
|
# placement: tab
|
|
# workspace: bridged-workers
|
|
# tabLabel: "opencode: {model} #{n}"
|
|
# mcpUrl: http://127.0.0.1:8765/mcp
|
|
# argv: ["opencode"]
|
|
defaultWorker: gx10
|
|
|
|
# Subscription boundary. A worker's base_url host MUST be one of these; the primary
|
|
# must carry none. Every profile above must have its host listed here.
|
|
guard:
|
|
offSubscriptionHosts:
|
|
- gx00.gw
|
|
- gx01.gw
|
|
- ollama.ltms.dev
|
|
|
|
# Spawn-readiness gate (CB-306). The launcher blocks until the worker's herdr status is
|
|
# injectable (IDLE/BLOCKED/DONE) or the timeout elapses. 0 disables the gate.
|
|
# spawn_ready_timeout_ms: 20000
|
|
# spawn_ready_poll_ms: 300
|
|
|
|
# Session lifecycle limits (CB-303). All knobs are opt-in; omit or set to null to keep
|
|
# the feature disabled. By default the daemon never reaps, caps, or drains sessions.
|
|
# idleTtlSeconds → reap READY/DONE sessions idle longer than this (never BUSY/SPAWNING)
|
|
# contextCap → force-release a session after this many delegated turns
|
|
# drainTimeoutSeconds → seconds to wait for BUSY sessions on shutdown before forced teardown
|
|
# lifecycle:
|
|
# idleTtlSeconds: 300
|
|
# contextCap: 10
|
|
# drainTimeoutSeconds: 5
|
|
|
|
# Durable reply delivery (CB-307 Stage 2). OMIT this block entirely to keep the default
|
|
# in-memory, soft-state reply inbox (late worker replies are held only until a daemon bounce).
|
|
# Set a broker uri to swap in the AMQP-backed inbox: worker replies with no open send are held
|
|
# on a durable per-target queue (agent.<target>.inbox) and survive a restart — the broker
|
|
# redelivers anything the primary had not yet drained. Production default is LavinMQ; a stock
|
|
# RabbitMQ speaks the same AMQP 0-9-1, so it is a URI-only swap.
|
|
# uri → AMQP connection URI. No trailing slash ⇒ the default vhost "/"; an empty path ("/")
|
|
# is vhost "" and will NOT connect. Encode a named vhost as .../%2Fmyvhost.
|
|
# broker:
|
|
# uri: amqp://guest:guest@127.0.0.1:5672
|