import { type TerminalSummary, WS_METHODS } from "@t3tools/contracts"; import * as Stream from "effect/Stream"; import { Atom } from "effect/unstable/reactivity"; import { createAtomCommandScheduler, createEnvironmentRpcCommand, createEnvironmentRpcSubscriptionAtomFamily, createEnvironmentSubscriptionAtomFamily, } from "./runtime.ts"; import type { EnvironmentRegistry } from "../connection/registry.ts"; import { subscribe, type EnvironmentRpcInput } from "../rpc/client.ts"; import { applyTerminalAttachStreamEvent, applyTerminalMetadataStreamEvent, EMPTY_TERMINAL_BUFFER_STATE, } from "./terminalSession.ts"; export function createTerminalEnvironmentAtoms( runtime: Atom.AtomRuntime, ) { const lifecycleScheduler = createAtomCommandScheduler(); const resizeScheduler = createAtomCommandScheduler(); const terminalThreadKey = ({ environmentId, input, }: { readonly environmentId: string; readonly input: { readonly threadId: string; readonly terminalId?: string | undefined }; }) => JSON.stringify([environmentId, input.threadId]); const terminalSessionKey = ({ environmentId, input, }: { readonly environmentId: string; readonly input: { readonly threadId: string; readonly terminalId?: string | undefined }; }) => JSON.stringify([environmentId, input.threadId, input.terminalId ?? null]); const lifecycleConcurrency = { mode: "serial" as const, key: terminalThreadKey }; return { attach: createEnvironmentSubscriptionAtomFamily(runtime, { label: "environment-data:terminal:attach", subscribe: (input: EnvironmentRpcInput) => subscribe(WS_METHODS.terminalAttach, input).pipe( Stream.scan(EMPTY_TERMINAL_BUFFER_STATE, applyTerminalAttachStreamEvent), ), }), events: createEnvironmentRpcSubscriptionAtomFamily(runtime, { label: "environment-data:terminal:events", tag: WS_METHODS.subscribeTerminalEvents, }), metadata: createEnvironmentSubscriptionAtomFamily(runtime, { label: "environment-data:terminal:metadata", subscribe: (_input: null) => subscribe(WS_METHODS.subscribeTerminalMetadata, {}).pipe( Stream.scan([] as ReadonlyArray, applyTerminalMetadataStreamEvent), ), }), open: createEnvironmentRpcCommand(runtime, { label: "environment-data:terminal:open", tag: WS_METHODS.terminalOpen, scheduler: lifecycleScheduler, concurrency: lifecycleConcurrency, }), write: createEnvironmentRpcCommand(runtime, { label: "environment-data:terminal:write", tag: WS_METHODS.terminalWrite, }), resize: createEnvironmentRpcCommand(runtime, { label: "environment-data:terminal:resize", tag: WS_METHODS.terminalResize, scheduler: resizeScheduler, concurrency: { mode: "latest", key: terminalSessionKey }, }), clear: createEnvironmentRpcCommand(runtime, { label: "environment-data:terminal:clear", tag: WS_METHODS.terminalClear, scheduler: lifecycleScheduler, concurrency: lifecycleConcurrency, }), restart: createEnvironmentRpcCommand(runtime, { label: "environment-data:terminal:restart", tag: WS_METHODS.terminalRestart, scheduler: lifecycleScheduler, concurrency: lifecycleConcurrency, }), close: createEnvironmentRpcCommand(runtime, { label: "environment-data:terminal:close", tag: WS_METHODS.terminalClose, scheduler: lifecycleScheduler, concurrency: lifecycleConcurrency, }), }; } export * from "./terminalSession.ts";