Repository navigation
feat(opencode): bridge OpenCode to CAS specialised agents - #9
Conversation
Wire agent.alterspective.com.au into the fork via .opencode/: MCP entry, permission denials for resolve/admin tools, cas_safe_* tools with agent allowlist and payload guards, façade subagents, and routing/degraded system-prompt injection. Includes unit tests and FEAT-CAS-OPENCODE-BRIDGE docs. Closes #8 No user-doc impact: developer/fork integration only.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdded a token-gated MCP bridge between OpenCode and CAS. The bridge provides restricted tools, façade agents, routing prompts, payload validation, untrusted-output fencing, run controls, tests, and implementation documentation. ChangesCAS OpenCode Bridge
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant OpenCode
participant cas_bridge_routing
participant cas_safe_delegate
participant cas_bridge_lib
participant alterspective_agent
OpenCode->>cas_bridge_routing: transform system prompt
cas_bridge_routing-->>OpenCode: routing or degraded-mode guidance
OpenCode->>cas_safe_delegate: delegate agentId, task, context
cas_safe_delegate->>cas_bridge_lib: validate delegate input
cas_bridge_lib->>alterspective_agent: initialize MCP session
cas_bridge_lib->>alterspective_agent: call cas_delegate
alterspective_agent-->>cas_bridge_lib: CAS result
cas_bridge_lib-->>cas_safe_delegate: bounded untrusted result
cas_safe_delegate-->>OpenCode: fenced delegation output
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (1)
packages/opencode/test/plugin/cas-bridge/cas-bridge-routing.test.ts (1)
11-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winType the plugin fixture and hook values.
mockInput,hooks, and the threelocalHooksvalues useany. This can hide a changed plugin input contract or a missing hook. Use the actual plugin input type,Awaited<ReturnType<typeof plugin>>forhooks, and inferred types for eachlocalHooksvalue.Suggested type changes
-let hooks: any +let hooks: Awaited<ReturnType<typeof plugin>> - const localHooks: any = await plugin(mockInput) + const localHooks = await plugin(mockInput)Construct
mockInputas the minimal valid value forParameters<typeof plugin>[0]instead of casting it toany.As per coding guidelines, avoid the
anytype in TypeScript tests.Also applies to: 19-19, 45-45, 55-55, 65-65
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/opencode/test/plugin/cas-bridge/cas-bridge-routing.test.ts` at line 11, Replace the any-based casts in the cas-bridge routing test: construct mockInput as a minimal valid Parameters<typeof plugin>[0] value, type hooks as Awaited<ReturnType<typeof plugin>>, and let each of the three localHooks values use inferred types. Remove all any usage while preserving the existing fixture behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.opencode/tool/cas-bridge-lib.ts:
- Around line 45-50: Update looksLikeSecret so Bearer-token detection is not
gated by the overall text.length; remove the 500-character condition or limit
evaluation to the matched local token context, while preserving the existing
Bearer pattern and other secret checks.
In @.opencode/tool/cas-safe-list-agents.ts:
- Around line 8-14: Update execute in the cas-safe-list-agents tool to wrap
callCasMcpTool in try/catch, matching cas-safe-delegate.ts, cas-safe-get-run.ts,
and cas-safe-cancel-run.ts. Return a safe error message from the catch path
after redacting any Bearer token pattern (Bearer\s+\S+) from the error text,
while preserving the existing token check and successful wrapUntrusted flow.
In
`@docs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/adversarial-review-gpt56.md`:
- Line 245: Remove the standalone `|` row from the Markdown table in the
reviewed document, leaving the surrounding two-column table rows unchanged.
In
`@docs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/adversarial-synthesis.md`:
- Line 29: Update both records in
docs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/adversarial-synthesis.md:29-29
and docs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/status.md:38-38 to make
denying raw cas_delegate and other CAS MCP tools to the primary agent an
explicit release-gated requirement, or document and enforce a user-only path
with permission tests. Ensure the primary agent cannot bypass the safe façade
through model-callable raw tools; both records must reflect the same
requirement.
- Line 23: Harden the CAS-output path around wrapUntrusted by escaping or
stripping hostile delimiters, system-prompt markers, and tool-call text before
producing model-facing output, or replace the boundary with structured output.
Ensure raw CAS-result tools cannot bypass wrapUntrusted, and add regression
coverage for marker payloads and truncation behavior.
- Line 21: Update the raw CAS tool authorization flow described in the “Auth not
verified” row to disable or deny tools such as cas_delegate whenever
CAS_MCP_TOKEN is missing or empty, rather than allowing an empty Bearer
credential to reach the raw MCP transport. Route unauthenticated calls through
the safe bridge if that is the established path, and add a test that verifies no
network request occurs without a token.
In `@docs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/status.md`:
- Around line 21-24: Update the validation command documentation in status.md to
specify packages/opencode as the working directory and place the command in a
shell-formatted code fence. Preserve the existing test command while making its
execution context explicit and reproducible.
In `@packages/opencode/test/plugin/cas-bridge/cas-bridge-routing.test.ts`:
- Around line 114-119: Strengthen the wrapUntrusted test to validate the
complete untrusted-output contract: assert that the output includes the
untrusted-output instruction or warning text, and exercise a body exceeding the
configured response limit to verify truncation behavior. Keep the existing
delimiter and body assertions while using the relevant limit configuration
symbol.
- Around line 21-37: Update the test setup around beforeAll and afterEach to
reset CAS_BRIDGE_ROUTING_ENABLED, CAS_BRIDGE_ROUTING_DISABLED, and
CAS_AGENT_ALLOWLIST to known values before every test, using beforeEach rather
than one-time initialization. Preserve afterEach restoration of the original
environment values so each test remains isolated.
---
Nitpick comments:
In `@packages/opencode/test/plugin/cas-bridge/cas-bridge-routing.test.ts`:
- Line 11: Replace the any-based casts in the cas-bridge routing test: construct
mockInput as a minimal valid Parameters<typeof plugin>[0] value, type hooks as
Awaited<ReturnType<typeof plugin>>, and let each of the three localHooks values
use inferred types. Remove all any usage while preserving the existing fixture
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a272c18f-a649-47ea-b46d-9c012cf9775e
📒 Files selected for processing (17)
.opencode/agent/cas-delegate.md.opencode/agent/cas-drafter.md.opencode/agent/cas-matter-audit.md.opencode/opencode.jsonc.opencode/plugin/cas-bridge-routing.ts.opencode/tool/cas-bridge-lib.ts.opencode/tool/cas-safe-cancel-run.ts.opencode/tool/cas-safe-delegate.ts.opencode/tool/cas-safe-get-run.ts.opencode/tool/cas-safe-list-agents.tsAGENTS.mddocs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/adversarial-review-fable.mddocs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/adversarial-review-gpt56.mddocs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/adversarial-synthesis.mddocs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/plan.mddocs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/status.mdpackages/opencode/test/plugin/cas-bridge/cas-bridge-routing.test.ts
Remove Bearer length gate, redact list-agents errors, harden tests and docs formatting from PR #9 review.
PR-loop disposition (cycle 1)Head: CodeRabbit
Compliance / standards
CI gap
Merging with documented CI-queue residual; no unresolved threads. |
Issue for this PR
Closes #8
Type of change
What does this PR do?
Bridges the OpenCode fork to the Central Agent Service (CAS) at
agent.alterspective.com.auso specialised business agents can be used from the coding shell without moving worktree ownership off the machine.Hardened after adversarial review (
claude-fable-5+openai/gpt-5.6-solvia Synapse):alterspective-agent→/api/v1/mcpwithCAS_MCP_TOKEN(missing env → empty bearer → 401 fail-closed)cas_resolve_tool_callandcas_admin_*cas-safe-*: agent allowlist, size caps, secret/source heuristics, untrusted output fencingcas-delegate,cas-drafter,cas-matter-auditdocs/implementation/current/FEAT-CAS-OPENCODE-BRIDGE/How did you verify your code works?
bun test test/plugin/cas-bridge/cas-bridge-routing.test.tsfrompackages/opencode: 11 pass / 0 fail (observed)CAS_MCP_TOKEN: not run (token absent on this machine)Screenshots / recordings
N/A — config/plugin/tools only; no UI change.
Checklist
No user-doc impact: developer/fork integration only.
Summary by CodeRabbit
New Features
Documentation
Tests