import type { EnvironmentId, ProviderInstanceId, ThreadId } from "@t3tools/contracts"; export interface McpProviderSessionConfig { readonly environmentId: EnvironmentId; readonly threadId: ThreadId; readonly providerSessionId: string; readonly providerInstanceId: ProviderInstanceId; readonly endpoint: string; readonly authorizationHeader: string; /** Capabilities the credential grants ("preview", "device"). */ readonly capabilities: ReadonlySet; /** * Set when the session may drive devices. Adapters spread this into the * provider subprocess environment so the `agent-device` CLI is on PATH and * already pointed at the server's daemon; the agent never handles a token. */ readonly agentDeviceEnvironment?: Readonly>; } /** Provider env with the device variables applied over `base`, or `base` untouched. */ export function withAgentDeviceEnvironment( base: NodeJS.ProcessEnv, config: Pick | undefined, ): NodeJS.ProcessEnv { const extra = config?.agentDeviceEnvironment; if (!extra) return base; const separator = extra.PATH_SEPARATOR ?? ":"; const basePath = base.PATH ?? base.Path; const { PATH: shimDir, PATH_SEPARATOR: _separator, ...rest } = extra; return { ...base, ...rest, ...(shimDir ? { PATH: basePath ? `${shimDir}${separator}${basePath}` : shimDir } : {}), }; } const sessionsByThread = new Map(); export function setMcpProviderSession(config: McpProviderSessionConfig): void { sessionsByThread.set(config.threadId, config); } export function readMcpProviderSession(threadId: ThreadId): McpProviderSessionConfig | undefined { return sessionsByThread.get(threadId); } export function clearMcpProviderSession(threadId: ThreadId): void { sessionsByThread.delete(threadId); } export function clearAllMcpProviderSessions(): void { sessionsByThread.clear(); }