Skip to content

Commit 613c752

Browse files
committed
feat: activate BRIDGE_MODE with local bridge defaults
Minimal changes to 3 bridge files for local bridge server support: - bridgeEnabled.ts: bypass OAuth subscriber check (local bridge needs no subscription), let _openBuildDefaults control runtime gates - bridgeConfig.ts: add localhost:4080 fallback + default token - initReplBridge.ts: skip org policy check when using token override
1 parent c1d99ec commit 613c752

2 files changed

Lines changed: 33 additions & 40 deletions

File tree

src/bridge/bridgeConfig.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/**
2-
* Shared bridge auth/URL resolution. Consolidates the internal-only
3-
* CLAUDE_BRIDGE_* dev overrides that were previously copy-pasted across
4-
* a dozen files — inboundAttachments, BriefTool/upload, bridgeMain,
5-
* initReplBridge, remoteBridgeCore, daemon workers, /rename,
6-
* /remote-control.
2+
* Shared bridge auth/URL resolution. Consolidates the CLAUDE_BRIDGE_*
3+
* dev overrides that were previously copy-pasted across a dozen files —
4+
* inboundAttachments, BriefTool/upload, bridgeMain, initReplBridge,
5+
* remoteBridgeCore, daemon workers, /rename, /remote-control.
76
*
8-
* Two layers: *Override() returns the internal-only env var (or undefined);
7+
* Two layers: *Override() returns the dev env var (or undefined);
98
* the non-Override versions fall through to the real OAuth store/config.
109
* Callers that compose with a different auth source (e.g. daemon workers
1110
* using IPC auth) use the Override getters directly.
@@ -14,35 +13,36 @@
1413
import { getOauthConfig } from '../constants/oauth.js'
1514
import { getClaudeAIOAuthTokens } from '../utils/auth.js'
1615

17-
/** Ant-only dev override: CLAUDE_BRIDGE_OAUTH_TOKEN, else undefined. */
16+
/** Dev override: CLAUDE_BRIDGE_OAUTH_TOKEN, else undefined. */
1817
export function getBridgeTokenOverride(): string | undefined {
19-
return (
20-
(process.env.USER_TYPE === 'ant' &&
21-
process.env.CLAUDE_BRIDGE_OAUTH_TOKEN) ||
22-
undefined
23-
)
18+
return process.env.CLAUDE_BRIDGE_OAUTH_TOKEN || undefined
2419
}
2520

26-
/** Ant-only dev override: CLAUDE_BRIDGE_BASE_URL, else undefined. */
21+
/** Dev override: CLAUDE_BRIDGE_BASE_URL, else undefined. */
2722
export function getBridgeBaseUrlOverride(): string | undefined {
28-
return (
29-
(process.env.USER_TYPE === 'ant' && process.env.CLAUDE_BRIDGE_BASE_URL) ||
30-
undefined
31-
)
23+
return process.env.CLAUDE_BRIDGE_BASE_URL || undefined
3224
}
3325

3426
/**
35-
* Access token for bridge API calls: dev override first, then the OAuth
36-
* keychain. Undefined means "not logged in".
27+
* Access token for bridge API calls: env override first, then OAuth
28+
* keychain, then local bridge default token.
3729
*/
3830
export function getBridgeAccessToken(): string | undefined {
39-
return getBridgeTokenOverride() ?? getClaudeAIOAuthTokens()?.accessToken
31+
return (
32+
getBridgeTokenOverride() ??
33+
getClaudeAIOAuthTokens()?.accessToken ??
34+
'openclaude-local-bridge'
35+
)
4036
}
4137

4238
/**
43-
* Base URL for bridge API calls: dev override first, then the production
44-
* OAuth config. Always returns a URL.
39+
* Base URL for bridge API calls: env override first, then OAuth config,
40+
* then localhost default for the local bridge server.
4541
*/
4642
export function getBridgeBaseUrl(): string {
47-
return getBridgeBaseUrlOverride() ?? getOauthConfig().BASE_API_URL
43+
return (
44+
getBridgeBaseUrlOverride() ??
45+
getOauthConfig()?.BASE_API_URL ??
46+
'http://localhost:4080'
47+
)
4848
}

src/bridge/bridgeEnabled.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ import { lt } from '../utils/semver.js'
2626
* is only referenced when bridge mode is enabled at build time.
2727
*/
2828
export function isBridgeEnabled(): boolean {
29-
// Positive ternary pattern — see docs/feature-gating.md.
30-
// Negative pattern (if (!feature(...)) return) does not eliminate
31-
// inline string literals from external builds.
29+
// Open build: bypass isClaudeAISubscriber() (no OAuth needed for local bridge).
30+
// The tengu_ccr_bridge gate defaults to true via _openBuildDefaults in the
31+
// GrowthBook stub — users can override with ~/.claude/feature-flags.json.
3232
return feature('BRIDGE_MODE')
33-
? isClaudeAISubscriber() &&
34-
getFeatureValue_CACHED_MAY_BE_STALE('tengu_ccr_bridge', false)
33+
? getFeatureValue_CACHED_MAY_BE_STALE('tengu_ccr_bridge', false)
3534
: false
3635
}
3736

@@ -48,9 +47,9 @@ export function isBridgeEnabled(): boolean {
4847
* `isBridgeEnabled()` instead.
4948
*/
5049
export async function isBridgeEnabledBlocking(): Promise<boolean> {
50+
// Open build: bypass isClaudeAISubscriber() — local bridge needs no OAuth.
5151
return feature('BRIDGE_MODE')
52-
? isClaudeAISubscriber() &&
53-
(await checkGate_CACHED_OR_BLOCKING('tengu_ccr_bridge'))
52+
? (await checkGate_CACHED_OR_BLOCKING('tengu_ccr_bridge'))
5453
: false
5554
}
5655

@@ -69,17 +68,10 @@ export async function isBridgeEnabledBlocking(): Promise<boolean> {
6968
*/
7069
export async function getBridgeDisabledReason(): Promise<string | null> {
7170
if (feature('BRIDGE_MODE')) {
72-
if (!isClaudeAISubscriber()) {
73-
return 'Remote Control requires a claude.ai subscription. Run `claude auth login` to sign in with your claude.ai account.'
74-
}
75-
if (!hasProfileScope()) {
76-
return 'Remote Control requires a full-scope login token. Long-lived tokens (from `claude setup-token` or CLAUDE_CODE_OAUTH_TOKEN) are limited to inference-only for security reasons. Run `claude auth login` to use Remote Control.'
77-
}
78-
if (!getOauthAccountInfo()?.organizationUuid) {
79-
return 'Unable to determine your organization for Remote Control eligibility. Run `claude auth login` to refresh your account information.'
80-
}
71+
// Open build: skip OAuth/org checks (local bridge needs no subscription).
72+
// Only check the GrowthBook gate which defaults to true via _openBuildDefaults.
8173
if (!(await checkGate_CACHED_OR_BLOCKING('tengu_ccr_bridge'))) {
82-
return 'Remote Control is not yet enabled for your account.'
74+
return 'Remote Control is disabled. Enable it with: echo \'{"tengu_ccr_bridge": true}\' > ~/.claude/feature-flags.json'
8375
}
8476
return null
8577
}
@@ -124,6 +116,7 @@ function getOauthAccountInfo(): ReturnType<
124116
* on the env-based implementation regardless of this gate.
125117
*/
126118
export function isEnvLessBridgeEnabled(): boolean {
119+
// Open build: defaults to true via _openBuildDefaults → forces v2 (env-less) path.
127120
return feature('BRIDGE_MODE')
128121
? getFeatureValue_CACHED_MAY_BE_STALE('tengu_bridge_repl_v2', false)
129122
: false

0 commit comments

Comments
 (0)