Skip to content

feat: enable Remote Control (BRIDGE_MODE) with stub completions#60

Open
amDosion wants to merge 4 commits intoclaude-code-best:mainfrom
amDosion:feat/rc-clean
Open

feat: enable Remote Control (BRIDGE_MODE) with stub completions#60
amDosion wants to merge 4 commits intoclaude-code-best:mainfrom
amDosion:feat/rc-clean

Conversation

@amDosion
Copy link
Copy Markdown

@amDosion amDosion commented Apr 2, 2026

Summary

  • Add BRIDGE_MODE to DEFAULT_FEATURES in scripts/dev.ts
  • Implement peerSessions.ts: cross-session peer messaging via bridge API (was empty stub)
  • Implement webhookSanitizer.ts: redact secrets/tokens from GitHub webhook payloads (was empty stub)
  • Replace any stubs in controlTypes.ts with z.infer types from existing Zod schemas
  • Fix tengu_bridge_system_init default value falsetrue so app shows "active" status

Files changed (5 only)

File Change
scripts/dev.ts Add BRIDGE_MODE to default features
src/bridge/peerSessions.ts Stub → full implementation
src/bridge/webhookSanitizer.ts Stub → full implementation
src/entrypoints/sdk/controlTypes.ts any → Zod schema-inferred types
src/hooks/useReplBridge.tsx Default value fix (1 char)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Inter‑Claude peer messaging for bridge communications.
    • Webhook sanitization with secret redaction, truncation, and resilient non‑throwing behavior.
  • Chores

    • Improved type safety for SDK control protocol definitions.
    • Updated default feature flags to enable bridge-related initialization behavior by default.

- Add BRIDGE_MODE to DEFAULT_FEATURES in dev.ts
- Implement peerSessions.ts: cross-session messaging via bridge API
- Implement webhookSanitizer.ts: redact secrets from webhook payloads
- Replace any stubs in controlTypes.ts with Zod schema-inferred types
- Fix tengu_bridge_system_init default to true for app "active" status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4c27104a-b319-4b85-98ab-fd542e72fefc

📥 Commits

Reviewing files that changed from the base of the PR and between 8645d37 and e784f23.

📒 Files selected for processing (1)
  • src/bridge/peerSessions.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/bridge/peerSessions.ts

📝 Walkthrough

Walkthrough

Implements real bridge peer messaging and inbound webhook sanitization, replaces loose SDK control protocol types with schema-derived TypeScript, adds BRIDGE_MODE to dev defaults, and enables the tengu_bridge_system_init feature by default.

Changes

Cohort / File(s) Summary
Bridge peer messaging
src/bridge/peerSessions.ts
Replaced stub with postInterClaudeMessage async implementation: validates bridge handle/target/token, converts/validates session id, POSTs { type: 'peer_message', from, content } to ingress with 10s timeout and validateStatus: s < 500; returns { ok: true } on 200/204, otherwise { ok: false, error }.
Webhook sanitization
src/bridge/webhookSanitizer.ts
Added sanitizeInboundWebhookContent(content: string): string: applies multiple regex-based redactions (resetting regex state), truncates outputs >100KB with a marker, and catches errors to return a fixed redaction-error placeholder (never throws).
Control protocol types
src/entrypoints/sdk/controlTypes.ts
Replaced loose any/generic control types with schema-derived TypeScript types using z.infer<ReturnType<...Schema>> for ~12 exported control-related types.
Dev / feature flags
scripts/dev.ts, src/hooks/useReplBridge.tsx
Added BRIDGE_MODE to DEFAULT_FEATURES; changed tengu_bridge_system_init feature check to default true, causing system-init path to run by default when feature value is absent.

Sequence Diagram

sequenceDiagram
    participant App as Calling Code
    participant PostFunc as postInterClaudeMessage()
    participant Bridge as Bridge Handle
    participant HTTP as axios
    participant Ingress as Ingress Endpoint

    App->>PostFunc: postInterClaudeMessage(target, message)
    PostFunc->>Bridge: fetch handle (get sender, ingress URL, token)
    alt no handle / missing token / empty target
        PostFunc-->>App: { ok: false, error }
    else
        PostFunc->>PostFunc: validate/convert target id
        PostFunc->>HTTP: POST ${ingressUrl}/v1/sessions/<encodedTarget>/messages (body, headers, timeout)
        HTTP->>Ingress: deliver peer_message
        Ingress-->>HTTP: response (200/204 or non-5xx)
        alt 200/204
            PostFunc-->>App: { ok: true }
        else
            PostFunc-->>App: { ok: false, error }
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through code, a bridge to mend,
Redacted secrets, messages I send.
Types aligned, no any in the night,
Features toggled on — the default's bright.
Cheers — a rabbit’s joyful dev delight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: enable Remote Control (BRIDGE_MODE) with stub completions' is directly related to the main changes in the pull request. It accurately reflects the primary objective of enabling the BRIDGE_MODE feature and implementing real functionality (peer messaging, webhook sanitization, type definitions) to replace previous stub implementations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/bridge/peerSessions.ts (2)

1-5: Consider using src/ path alias for imports.

As per coding guidelines, imports should use the src/ path alias via tsconfig mapping instead of relative paths. However, this appears to be a common pattern in this codebase for same-package imports.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bridge/peerSessions.ts` around lines 1 - 5, The imports at the top of
peerSessions.ts use relative paths (axios and local modules like
logForDebugging, errorMessage, getReplBridgeHandle, toCompatSessionId); update
these to use the project's src/ path alias (e.g., import { logForDebugging }
from 'src/utils/debug' etc.) so TS path mapping is respected, keeping the same
named symbols (logForDebugging, errorMessage, getReplBridgeHandle,
toCompatSessionId) and ensuring imports resolve under tsconfig paths.

18-21: Consider using a discriminated union for better type safety.

The return type { ok: boolean; error?: string } permits invalid states (e.g., { ok: true, error: '...' }). A discriminated union ensures callers handle both cases correctly.

🔧 Suggested type refinement
 export async function postInterClaudeMessage(
   target: string,
   message: string,
-): Promise<{ ok: boolean; error?: string }> {
+): Promise<{ ok: true } | { ok: false; error: string }> {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bridge/peerSessions.ts` around lines 18 - 21, The return type of
postInterClaudeMessage allows invalid states like { ok: true, error: '...' };
change its signature to a discriminated union (e.g., Promise<{ ok: true } | {
ok: false; error: string }>) and update all return sites inside
postInterClaudeMessage to return exactly one of those shapes (success returns {
ok: true } and all failure paths return { ok: false, error: <string> }). Also
export or define a named type (e.g., PostInterClaudeResult) if used elsewhere to
keep callers type-safe and update any callers to handle both union branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/bridge/webhookSanitizer.ts`:
- Line 8: The sanitizer currently "fails open" by returning the original payload
on error; change sanitizeWebhook (and the same logic around lines 53-55) so that
it never returns the raw input when an internal error occurs — instead catch any
exception synchronously and return a fully redacted/placeholder payload (or an
empty safe structure) that preserves the expected return type, and optionally
log the error; ensure sanitizeWebhook remains synchronous and never throws, and
update all paths that currently return the original content on error to return
the safe redacted value instead.
- Around line 40-50: The code currently truncates the payload (sanitized =
sanitized.slice(...)) before applying SECRET_PATTERNS, which can break regex
matches that span the truncation boundary; run the redaction loop over
SECRET_PATTERNS on the full sanitized input first (ensure pattern.lastIndex = 0
before each replace), then apply the MAX_CONTENT_LENGTH truncation step
afterwards (optionally reset lastIndex and run one final pass if you want to be
extra safe). Update the order around the variables sanitized, SECRET_PATTERNS,
and MAX_CONTENT_LENGTH in webhookSanitizer.ts accordingly.

---

Nitpick comments:
In `@src/bridge/peerSessions.ts`:
- Around line 1-5: The imports at the top of peerSessions.ts use relative paths
(axios and local modules like logForDebugging, errorMessage,
getReplBridgeHandle, toCompatSessionId); update these to use the project's src/
path alias (e.g., import { logForDebugging } from 'src/utils/debug' etc.) so TS
path mapping is respected, keeping the same named symbols (logForDebugging,
errorMessage, getReplBridgeHandle, toCompatSessionId) and ensuring imports
resolve under tsconfig paths.
- Around line 18-21: The return type of postInterClaudeMessage allows invalid
states like { ok: true, error: '...' }; change its signature to a discriminated
union (e.g., Promise<{ ok: true } | { ok: false; error: string }>) and update
all return sites inside postInterClaudeMessage to return exactly one of those
shapes (success returns { ok: true } and all failure paths return { ok: false,
error: <string> }). Also export or define a named type (e.g.,
PostInterClaudeResult) if used elsewhere to keep callers type-safe and update
any callers to handle both union branches.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0a1f7a5-70c7-4be8-a7f9-2662dc84fec8

📥 Commits

Reviewing files that changed from the base of the PR and between 1f0a2e4 and 74e51e7.

📒 Files selected for processing (5)
  • scripts/dev.ts
  • src/bridge/peerSessions.ts
  • src/bridge/webhookSanitizer.ts
  • src/entrypoints/sdk/controlTypes.ts
  • src/hooks/useReplBridge.tsx

- webhookSanitizer: redact before truncate to avoid split secrets at boundary
- webhookSanitizer: return safe placeholder on error instead of raw content
- peerSessions: use discriminated union return type for type safety

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/bridge/peerSessions.ts (1)

1-5: Use src/ path alias instead of relative imports.

The imports use relative paths (../utils/..., ./...) instead of the src/ path alias configured in tsconfig.

♻️ Suggested refactor
 import axios from 'axios'
-import { logForDebugging } from '../utils/debug.js'
-import { errorMessage } from '../utils/errors.js'
-import { getReplBridgeHandle } from './replBridgeHandle.js'
-import { toCompatSessionId } from './sessionIdCompat.js'
+import { logForDebugging } from 'src/utils/debug.js'
+import { errorMessage } from 'src/utils/errors.js'
+import { getReplBridgeHandle } from 'src/bridge/replBridgeHandle.js'
+import { toCompatSessionId } from 'src/bridge/sessionIdCompat.js'

As per coding guidelines: "Import src/ path alias via tsconfig mapping instead of relative paths in imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bridge/peerSessions.ts` around lines 1 - 5, Update the imports in
peerSessions.ts to use the tsconfig "src/" path alias instead of relative paths:
replace "../utils/debug.js" import of logForDebugging, "../utils/errors.js"
import of errorMessage, "./replBridgeHandle.js" import of getReplBridgeHandle,
and "./sessionIdCompat.js" import of toCompatSessionId with equivalent "src/..."
aliased imports; ensure the module specifiers match the tsconfig paths (and keep
the default axios import unchanged) so TypeScript path mapping resolves
correctly and local build/IDE tooling recognizes the alias.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/bridge/peerSessions.ts`:
- Around line 38-53: The POST to the peer message endpoint in
postInterClaudeMessage is missing an Authorization header because
ReplBridgeHandle doesn't expose the access token; fix by either adding
getAccessToken to the ReplBridgeHandle interface and using it inside
postInterClaudeMessage or by changing postInterClaudeMessage signature to accept
an accessToken parameter, then include "Authorization: Bearer <token>" in the
axios headers alongside Content-Type and anthropic-version; mirror how other
bridge calls (see remoteBridgeCore.ts / codeSessionApi.ts / bridgeApi.ts) attach
the Bearer token so this request is authenticated.

---

Nitpick comments:
In `@src/bridge/peerSessions.ts`:
- Around line 1-5: Update the imports in peerSessions.ts to use the tsconfig
"src/" path alias instead of relative paths: replace "../utils/debug.js" import
of logForDebugging, "../utils/errors.js" import of errorMessage,
"./replBridgeHandle.js" import of getReplBridgeHandle, and
"./sessionIdCompat.js" import of toCompatSessionId with equivalent "src/..."
aliased imports; ensure the module specifiers match the tsconfig paths (and keep
the default axios import unchanged) so TypeScript path mapping resolves
correctly and local build/IDE tooling recognizes the alias.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: cff0d28c-d025-4836-b89b-c094fff9242f

📥 Commits

Reviewing files that changed from the base of the PR and between 74e51e7 and 1d38eae.

📒 Files selected for processing (2)
  • src/bridge/peerSessions.ts
  • src/bridge/webhookSanitizer.ts

getBridgeAccessToken() provides the OAuth Bearer token, matching
the auth pattern used by bridgeApi.ts and codeSessionApi.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/bridge/peerSessions.ts (1)

2-6: Use src/ path aliases instead of relative imports

These imports should use the configured src/ alias for consistency with repo standards.

Suggested fix
-import { logForDebugging } from '../utils/debug.js'
-import { errorMessage } from '../utils/errors.js'
-import { getBridgeAccessToken } from './bridgeConfig.js'
-import { getReplBridgeHandle } from './replBridgeHandle.js'
-import { toCompatSessionId } from './sessionIdCompat.js'
+import { logForDebugging } from 'src/utils/debug.js'
+import { errorMessage } from 'src/utils/errors.js'
+import { getBridgeAccessToken } from 'src/bridge/bridgeConfig.js'
+import { getReplBridgeHandle } from 'src/bridge/replBridgeHandle.js'
+import { toCompatSessionId } from 'src/bridge/sessionIdCompat.js'

As per coding guidelines, "Import src/ path alias via tsconfig mapping instead of relative paths in imports".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bridge/peerSessions.ts` around lines 2 - 6, Replace the relative imports
at the top of peerSessions.ts with the project alias imports using the src/ path
mapping: update import statements that reference logForDebugging, errorMessage,
getBridgeAccessToken, getReplBridgeHandle, and toCompatSessionId so they import
from "src/utils/debug", "src/utils/errors", "src/bridge/bridgeConfig",
"src/bridge/replBridgeHandle", and "src/bridge/sessionIdCompat" respectively
(preserving the same exported identifiers) to align with the tsconfig path alias
convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/bridge/peerSessions.ts`:
- Around line 29-43: The URL path is built with compatTarget unescaped which can
break routing for reserved chars or slashes; update the code that computes
compatTarget (use the existing toCompatSessionId(target)) and then normalize and
percent-encode it before interpolating into url (e.g., trim/normalize any
leading/trailing slashes and apply an encodeURIComponent-style encoding) so the
constructed url =
`${handle.sessionIngressUrl}/v1/sessions/${encodedCompatTarget}/messages` is
safe; ensure you reference toCompatSessionId, compatTarget (or its encoded
variant) and handle.sessionIngressUrl when making the change.

---

Nitpick comments:
In `@src/bridge/peerSessions.ts`:
- Around line 2-6: Replace the relative imports at the top of peerSessions.ts
with the project alias imports using the src/ path mapping: update import
statements that reference logForDebugging, errorMessage, getBridgeAccessToken,
getReplBridgeHandle, and toCompatSessionId so they import from
"src/utils/debug", "src/utils/errors", "src/bridge/bridgeConfig",
"src/bridge/replBridgeHandle", and "src/bridge/sessionIdCompat" respectively
(preserving the same exported identifiers) to align with the tsconfig path alias
convention.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 905ffc73-8b03-4f9d-ac5d-9cf7df50215b

📥 Commits

Reviewing files that changed from the base of the PR and between 1d38eae and 8645d37.

📒 Files selected for processing (1)
  • src/bridge/peerSessions.ts

- Trim and normalize target before use
- Validate with validateBridgeId allowlist (same as bridgeApi.ts)
- URL-encode compatTarget to prevent path traversal/injection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant