Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
4.7 kB · 127 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128import axios from 'axios'import { jsonParse, jsonStringify } from '../utils/slowOperations.js'import type { WorkSecret } from './types.js'
/** Decode a base64url-encoded work secret and validate its version. */export function decodeWorkSecret(secret: string): WorkSecret { const json = Buffer.from(secret, 'base64url').toString('utf-8') const parsed: unknown = jsonParse(json) if ( !parsed || typeof parsed !== 'object' || !('version' in parsed) || parsed.version !== 1 ) { throw new Error( `Unsupported work secret version: ${parsed && typeof parsed === 'object' && 'version' in parsed ? parsed.version : 'unknown'}`, ) } const obj = parsed as Record<string, unknown> if ( typeof obj.session_ingress_token !== 'string' || obj.session_ingress_token.length === 0 ) { throw new Error( 'Invalid work secret: missing or empty session_ingress_token', ) } if (typeof obj.api_base_url !== 'string') { throw new Error('Invalid work secret: missing api_base_url') } return parsed as WorkSecret}
/** * Build a WebSocket SDK URL from the API base URL and session ID. * Strips the HTTP(S) protocol and constructs a ws(s):// ingress URL. * * Uses /v2/ for localhost (direct to session-ingress, no Envoy rewrite) * and /v1/ for production (Envoy rewrites /v1/ → /v2/). */export function buildSdkUrl(apiBaseUrl: string, sessionId: string): string { const isLocalhost = apiBaseUrl.includes('localhost') || apiBaseUrl.includes('127.0.0.1') const protocol = isLocalhost ? 'ws' : 'wss' const version = isLocalhost ? 'v2' : 'v1' const host = apiBaseUrl.replace(/^https?:\/\//, '').replace(/\/+$/, '') return `${protocol}://${host}/${version}/session_ingress/ws/${sessionId}`}
/** * Compare two session IDs regardless of their tagged-ID prefix. * * Tagged IDs have the form {tag}_{body} or {tag}_staging_{body}, where the * body encodes a UUID. CCR v2's compat layer returns `session_*` to v1 API * clients (compat/convert.go:41) but the infrastructure layer (sandbox-gateway * work queue, work poll response) uses `cse_*` (compat/CLAUDE.md:13). Both * have the same underlying UUID. * * Without this, replBridge rejects its own session as "foreign" at the * work-received check when the ccr_v2_compat_enabled gate is on. */export function sameSessionId(a: string, b: string): boolean { if (a === b) return true // The body is everything after the last underscore — this handles both // `{tag}_{body}` and `{tag}_staging_{body}`. const aBody = a.slice(a.lastIndexOf('_') + 1) const bBody = b.slice(b.lastIndexOf('_') + 1) // Guard against IDs with no underscore (bare UUIDs): lastIndexOf returns -1, // slice(0) returns the whole string, and we already checked a === b above. // Require a minimum length to avoid accidental matches on short suffixes // (e.g. single-char tag remnants from malformed IDs). return aBody.length >= 4 && aBody === bBody}
/** * Build a CCR v2 session URL from the API base URL and session ID. * Unlike buildSdkUrl, this returns an HTTP(S) URL (not ws://) and points at * /v1/code/sessions/{id} — the child CC will derive the SSE stream path * and worker endpoints from this base. */export function buildCCRv2SdkUrl( apiBaseUrl: string, sessionId: string,): string { const base = apiBaseUrl.replace(/\/+$/, '') return `${base}/v1/code/sessions/${sessionId}`}
/** * Register this bridge as the worker for a CCR v2 session. * Returns the worker_epoch, which must be passed to the child CC process * so its CCRClient can include it in every heartbeat/state/event request. * * Mirrors what environment-manager does in the container path * (api-go/environment-manager/cmd/cmd_task_run.go RegisterWorker). */export async function registerWorker( sessionUrl: string, accessToken: string,): Promise<number> { const response = await axios.post( `${sessionUrl}/worker/register`, {}, { headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', 'anthropic-version': '2023-06-01', }, timeout: 10_000, }, ) // protojson serializes int64 as a string to avoid JS number precision loss; // the Go side may also return a number depending on encoder settings. const raw = response.data?.worker_epoch const epoch = typeof raw === 'string' ? Number(raw) : raw if ( typeof epoch !== 'number' || !Number.isFinite(epoch) || !Number.isSafeInteger(epoch) ) { throw new Error( `registerWorker: invalid worker_epoch in response: ${jsonStringify(response.data)}`, ) } return epoch}