mirror of
https://github.com/stablyai/orca.git
synced 2026-11-04 19:17:28 +00:00
* fix(orcad): orca serve owns its Claude and Codex accounts again (#28962) orcad never wired account services, so every accounts.* RPC failed once orca serve moved onto orcad. Build the same account services the desktop builds (now in provider-account-services.ts), made Electron-free, and install them in orcad except on a WSL host, whose desktop owns its accounts. * test(orcad): keep account-services test off the real userData when XDG_CONFIG_HOME is set * fix(orcad): structured Codex chats and session discovery follow this host's managed accounts Create orcad's account services before the runtime so its structured Codex launch/read resolvers and catalog-probe prep are constructor deps, as on the desktop. A client-sent account home still wins, and a WSL host keeps them unset so the desktop-pushed CODEX_HOME applies. AI Vault session discovery now includes this host's managed Codex homes. * fix(orcad): automatic Codex resumes follow the account home their session was recorded in Share the desktop's resume launch prep as a factory and wire it into orcad's PTY registration and AI Vault resume, so a pane restored after an account switch resumes from its origin home. A client-sent account home keeps resuming from itself. --------- Co-authored-by: Neil <neil@stably.ai>
55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
import type { Session } from 'electron'
|
|
|
|
/**
|
|
* Outbound HTTP for main-process integrations.
|
|
*
|
|
* Why a port: the desktop uses Electron's Chromium-backed network stack — it follows
|
|
* session/proxy state, avoids undici's stale keep-alive sockets after a VPN path change,
|
|
* and sends a Chrome user agent that some APIs (Jira's XSRF check) depend on. None of
|
|
* that exists on a host with no Chromium.
|
|
*
|
|
* The Node default is the platform global. That is a real behavioural difference, not a
|
|
* transparent swap, which is why this is a named port rather than a silent fallback:
|
|
* a Node host reads proxy configuration from the environment instead of from Chromium,
|
|
* and sends Node's user agent.
|
|
*
|
|
* Body safety (orca#8695): the global uses undici, where an unread response body can
|
|
* crash the process. This port hands the Response straight to its caller and never
|
|
* inspects it, so the consume/cancel obligation stays exactly where it already was —
|
|
* with the caller, unchanged from when they called Electron's net directly.
|
|
*/
|
|
|
|
export type MainHttpClient = {
|
|
fetch(url: string, init?: RequestInit): Promise<Response>
|
|
/** The Chromium session whose proxy state applies, or null on a host without one. */
|
|
proxySession(): Session | null
|
|
/** An isolated Chromium cookie jar; absent on a host without Chromium. */
|
|
partitionSession?(partition: string): Session
|
|
}
|
|
|
|
const nodeHttpClient: MainHttpClient = {
|
|
fetch: (url, init) => globalThis.fetch(url, init),
|
|
proxySession: () => null
|
|
}
|
|
|
|
let current: MainHttpClient = nodeHttpClient
|
|
|
|
export function setMainHttpClient(client: MainHttpClient | null): void {
|
|
current = client ?? nodeHttpClient
|
|
}
|
|
|
|
export function getMainHttpClient(): MainHttpClient {
|
|
return current
|
|
}
|
|
|
|
/** A provider's isolated cookie jar; throws where no Chromium session exists (orcad). */
|
|
export function requirePartitionSession(partition: string, providerLabel: string): Session {
|
|
const client = getMainHttpClient()
|
|
if (!client.partitionSession) {
|
|
throw new Error(
|
|
`${providerLabel} usage from a session cookie needs the Orca desktop app and is not available on this server`
|
|
)
|
|
}
|
|
return client.partitionSession(partition)
|
|
}
|