feat: enable Remote Control (BRIDGE_MODE) with stub completions#60
feat: enable Remote Control (BRIDGE_MODE) with stub completions#60amDosion wants to merge 4 commits intoclaude-code-best:mainfrom
Conversation
- 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>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughImplements real bridge peer messaging and inbound webhook sanitization, replaces loose SDK control protocol types with schema-derived TypeScript, adds Changes
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/bridge/peerSessions.ts (2)
1-5: Consider usingsrc/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
📒 Files selected for processing (5)
scripts/dev.tssrc/bridge/peerSessions.tssrc/bridge/webhookSanitizer.tssrc/entrypoints/sdk/controlTypes.tssrc/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>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/bridge/peerSessions.ts (1)
1-5: Usesrc/path alias instead of relative imports.The imports use relative paths (
../utils/...,./...) instead of thesrc/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
📒 Files selected for processing (2)
src/bridge/peerSessions.tssrc/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>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/bridge/peerSessions.ts (1)
2-6: Usesrc/path aliases instead of relative importsThese 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
📒 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>
Summary
BRIDGE_MODEtoDEFAULT_FEATURESinscripts/dev.tspeerSessions.ts: cross-session peer messaging via bridge API (was empty stub)webhookSanitizer.ts: redact secrets/tokens from GitHub webhook payloads (was empty stub)anystubs incontrolTypes.tswithz.infertypes from existing Zod schemastengu_bridge_system_initdefault valuefalse→trueso app shows "active" statusFiles changed (5 only)
scripts/dev.tsBRIDGE_MODEto default featuressrc/bridge/peerSessions.tssrc/bridge/webhookSanitizer.tssrc/entrypoints/sdk/controlTypes.tsany→ Zod schema-inferred typessrc/hooks/useReplBridge.tsx🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores