MCPcopy Create free account
hub / github.com/bearlyai/OpenADE / RuntimeClient

Class RuntimeClient

projects/runtime-client/src/client.ts:54–254  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

52}
53
54export class RuntimeClient {
55 private socket: WebSocket | null = null
56 private nextId = 1
57 private retryMs = 1000
58 private stopped = false
59 private connecting: Promise<void> | null = null
60 private lastStatus: RuntimeClientStatus | null = null
61 private lastCursor: string | null = null
62 private readonly pending = new Map<RuntimeRequestId, { resolve: (value: unknown) => void; reject: (error: Error) => void }>()
63 private readonly listeners = new Set<NotificationListener>()
64
65 constructor(private readonly options: RuntimeClientOptions) {}
66
67 async request<T>(method: string, params?: unknown): Promise<T> {
68 await this.connect()
69
70 const socket = this.socket
71 if (!socket || socket.readyState !== WebSocket.OPEN) throw new Error("Runtime socket is not connected")
72
73 return this.sendRequest<T>(socket, method, params)
74 }
75
76 private sendRequest<T>(socket: WebSocket, method: string, params?: unknown): Promise<T> {
77 const id = this.nextId++
78 const message = params === undefined ? { id, method } : { id, method, params }
79
80 return new Promise<T>((resolve, reject) => {
81 this.pending.set(id, {
82 resolve: (value) => resolve(value as T),
83 reject,
84 })
85 try {
86 socket.send(JSON.stringify(message))
87 } catch (error) {
88 this.pending.delete(id)
89 reject(error instanceof Error ? error : new Error("Runtime socket send failed"))
90 }
91 })
92 }
93
94 subscribe(listener: NotificationListener): () => void {
95 this.listeners.add(listener)
96 this.connectQuietly()
97 return () => {
98 this.listeners.delete(listener)
99 }
100 }
101
102 close(): void {
103 this.stopped = true
104 this.socket?.close()
105 this.socket = null
106 for (const pending of this.pending.values()) {
107 pending.reject(new Error("Runtime socket closed"))
108 }
109 this.pending.clear()
110 this.emitStatus("disconnected")
111 }

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected