@workerdeck/client 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { AttachedFrame, CreateJobRequest, CreateProfileRequest, CreateSessionRequest, FindHostFilesResponse, GetProfileResponse, JobEvent, JobInfo, ListHostDirResponse, ListHostRootsResponse, ListProfilesResponse, McpServerActionRequest, McpServerStatusInfo, MessageAttachment, PermissionMode, ProfileInfo, QueueStats, ReadHostFileResponse, ResolvePermissionRequest, SdkSessionSummary, SessionEvent, SessionFileInfo, SessionInfo, SubmitExecutionResultRequest, SubmitExecutionResultResponse, ToolCallRequestFrame, ToolExecutionOutput, ToolResultBlock, UpdateProfileRequest, UpdateSessionRequest, WriteHostFileRequest, WriteHostFileResponse } from "@workerdeck/protocol";
2
-
3
2
  //#region src/lib/emitter.d.ts
4
3
  type Listener<T> = (payload: T) => void;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#listeners","#client","#options","#lastSeq","#connectTimer","#connect","#events","#sendFrame","#closed","#ws","#retries","#outbox","#client","#reconnect","#connectTimer","#connect","#events","#closed","#ws","#retries","#options","#fetch","#WebSocketImpl","#call","#callRaw"],"sources":["../src/lib/emitter.ts","../src/session-handle.ts","../src/queue-handle.ts","../src/host-url.ts","../src/host-auth.ts","../src/index.ts"],"sourcesContent":["export type Listener<T> = (payload: T) => void\n\n/**\n * The handles' listener registry. A throwing listener must never stop the ones queued behind it:\n * these fire from a socket callback, where an escaping error would take the connection with it.\n */\nexport class Emitter<Events> {\n #listeners = new Map<keyof Events, Set<Listener<never>>>()\n\n on<K extends keyof Events>(kind: K, listener: Listener<Events[K]>): () => void {\n let set = this.#listeners.get(kind)\n if (!set) {\n set = new Set()\n this.#listeners.set(kind, set)\n }\n set.add(listener as Listener<never>)\n return () => set.delete(listener as Listener<never>)\n }\n\n emit<K extends keyof Events>(kind: K, payload: Events[K]): void {\n const set = this.#listeners.get(kind)\n if (!set) {\n return\n }\n for (const listener of set) {\n try {\n ;(listener as Listener<Events[K]>)(payload)\n } catch {}\n }\n }\n}\n\n/** 500ms doubling from a zero-based attempt count, capped at 10s. */\nexport function reconnectDelay(retries: number): number {\n return Math.min(500 * 2 ** retries, 10_000)\n}\n","import type {\n AttachedFrame,\n ClientFrame,\n PermissionMode,\n ServerFrame,\n SessionEvent,\n ToolCallRequestFrame,\n ToolExecutionOutput,\n} from '@workerdeck/protocol'\nimport { Emitter, reconnectDelay, type Listener } from './lib/emitter.ts'\nimport type { WorkerDeckClient } from './index.ts'\n\nexport type AttachOptions = {\n afterSeq?: number\n reconnect?: boolean\n truncateResults?: boolean\n imageRefs?: boolean\n}\n\nexport type SessionHandleEvents = {\n attached: AttachedFrame\n event: SessionEvent\n protocolError: string\n connectionChange: boolean\n reconnectAttempt: number\n toolCallRequest: ToolCallRequestFrame\n toolCallCanceled: { executionId: string; reason: string }\n}\n\nexport class SessionHandle {\n readonly sessionId: string\n #client: WorkerDeckClient\n #options: Required<Pick<AttachOptions, 'reconnect'>> & AttachOptions\n #ws: WebSocket | undefined\n #events = new Emitter<SessionHandleEvents>()\n #lastSeq: number\n #closed = false\n #retries = 0\n #outbox: string[] = []\n #connectTimer: ReturnType<typeof setTimeout> | undefined\n\n constructor(client: WorkerDeckClient, sessionId: string, options: AttachOptions = {}) {\n this.#client = client\n this.sessionId = sessionId\n this.#options = { reconnect: true, ...options }\n this.#lastSeq = options.afterSeq ?? 0\n // Deferred a tick so a same-tick detach (React StrictMode's dev mount) never closes a WebSocket mid-upgrade, which breaks proxies.\n this.#connectTimer = setTimeout(() => this.#connect(), 0)\n }\n\n get lastSeq(): number {\n return this.#lastSeq\n }\n\n on<K extends keyof SessionHandleEvents>(kind: K, listener: Listener<SessionHandleEvents[K]>): () => void {\n return this.#events.on(kind, listener)\n }\n\n send(text: string, attachmentIds?: string[]): void {\n this.#sendFrame({\n type: 'user_message',\n text,\n attachmentIds: attachmentIds?.length ? attachmentIds : undefined,\n })\n }\n\n approve(requestId: string, updatedInput?: Record<string, unknown>): void {\n this.#sendFrame({ type: 'permission_decision', requestId, behavior: 'allow', updatedInput })\n }\n\n deny(requestId: string, message?: string, interrupt?: boolean): void {\n this.#sendFrame({ type: 'permission_decision', requestId, behavior: 'deny', message, interrupt })\n }\n\n interrupt(): void {\n this.#sendFrame({ type: 'interrupt' })\n }\n\n clearContext(): void {\n this.#sendFrame({ type: 'clear_context' })\n }\n\n setPermissionMode(mode: PermissionMode): void {\n this.#sendFrame({ type: 'set_permission_mode', mode })\n }\n\n setModel(model?: string): void {\n this.#sendFrame({ type: 'set_model', model })\n }\n\n sendToolCallResult(executionId: string, output: ToolExecutionOutput, logs?: string[]): void {\n this.#sendFrame({ type: 'tool_call_result', executionId, output, logs })\n }\n\n sendToolCallError(executionId: string, reason: string, error: string, logs?: string[]): void {\n this.#sendFrame({ type: 'tool_call_error', executionId, reason, error, logs })\n }\n\n closeSession(): void {\n this.#sendFrame({ type: 'close' })\n this.detach()\n }\n\n reconnectNow(): void {\n if (this.#closed || (this.#ws && this.#ws.readyState === 1)) {\n return\n }\n clearTimeout(this.#connectTimer)\n this.#retries = 0\n this.#connect()\n }\n\n detach(): void {\n this.#closed = true\n clearTimeout(this.#connectTimer)\n this.#ws?.close()\n this.#ws = undefined\n }\n\n #sendFrame(frame: ClientFrame): void {\n const payload = JSON.stringify(frame)\n // readyState 1 === OPEN (avoid touching the WebSocket global; impl may be injected)\n if (this.#ws && this.#ws.readyState === 1) {\n this.#ws.send(payload)\n } else {\n this.#outbox.push(payload)\n }\n }\n\n #connect(): void {\n if (this.#closed) {\n return\n }\n const ws = this.#client.openSocket(this.sessionId, this.#lastSeq, this.#options.truncateResults, this.#options.imageRefs)\n this.#ws = ws\n ws.onopen = () => {\n this.#retries = 0\n this.#events.emit('connectionChange', true)\n for (const payload of this.#outbox.splice(0)) {\n ws.send(payload)\n }\n }\n ws.onmessage = (msg: MessageEvent) => {\n const frame = JSON.parse(String(msg.data)) as ServerFrame\n if (frame.type === 'attached') {\n this.#events.emit('attached', frame)\n } else if (frame.type === 'event') {\n if (frame.event.seq <= this.#lastSeq) {\n return\n }\n this.#lastSeq = frame.event.seq\n this.#events.emit('event', frame.event)\n } else if (frame.type === 'tool_call_request') {\n this.#events.emit('toolCallRequest', frame)\n } else if (frame.type === 'tool_call_canceled') {\n this.#events.emit('toolCallCanceled', { executionId: frame.executionId, reason: frame.reason })\n } else if (frame.type === 'protocol_error') {\n this.#events.emit('protocolError', frame.message)\n }\n }\n ws.onclose = () => {\n this.#events.emit('connectionChange', false)\n if (this.#closed || !this.#options.reconnect) {\n return\n }\n const delay = reconnectDelay(this.#retries++)\n this.#events.emit('reconnectAttempt', this.#retries)\n this.#connectTimer = setTimeout(() => this.#connect(), delay)\n }\n ws.onerror = () => {}\n }\n}\n","import type { JobEvent, QueueServerFrame, QueueStats } from '@workerdeck/protocol'\nimport { Emitter, reconnectDelay, type Listener } from './lib/emitter.ts'\nimport type { WorkerDeckClient } from './index.ts'\n\nexport type QueueHandleEvents = {\n attached: QueueStats\n event: JobEvent\n stats: QueueStats\n connectionChange: boolean\n}\n\nexport class QueueHandle {\n #client: WorkerDeckClient\n #reconnect: boolean\n #ws: WebSocket | undefined\n #events = new Emitter<QueueHandleEvents>()\n #closed = false\n #retries = 0\n #connectTimer: ReturnType<typeof setTimeout> | undefined\n\n constructor(client: WorkerDeckClient, options: { reconnect?: boolean } = {}) {\n this.#client = client\n this.#reconnect = options.reconnect ?? true\n // Deferred a tick for the same StrictMode reason as SessionHandle.\n this.#connectTimer = setTimeout(() => this.#connect(), 0)\n }\n\n on<K extends keyof QueueHandleEvents>(kind: K, listener: Listener<QueueHandleEvents[K]>): () => void {\n return this.#events.on(kind, listener)\n }\n\n detach(): void {\n this.#closed = true\n clearTimeout(this.#connectTimer)\n this.#ws?.close()\n this.#ws = undefined\n }\n\n #connect(): void {\n if (this.#closed) {\n return\n }\n const ws = this.#client.openQueueSocket()\n this.#ws = ws\n ws.onopen = () => {\n this.#retries = 0\n this.#events.emit('connectionChange', true)\n }\n ws.onmessage = (msg: MessageEvent) => {\n const frame = JSON.parse(String(msg.data)) as QueueServerFrame\n if (frame.type === 'queue_attached') {\n this.#events.emit('attached', frame.stats)\n this.#events.emit('stats', frame.stats)\n } else if (frame.type === 'job_event') {\n this.#events.emit('event', frame.event)\n } else if (frame.type === 'queue_stats') {\n this.#events.emit('stats', frame.stats)\n }\n }\n ws.onclose = () => {\n this.#events.emit('connectionChange', false)\n if (this.#closed || !this.#reconnect) {\n return\n }\n const delay = reconnectDelay(this.#retries++)\n this.#connectTimer = setTimeout(() => this.#connect(), delay)\n }\n ws.onerror = () => {}\n }\n}\n","export type HostUrl = { baseUrl: string }\n\nexport function apiUrl(host: HostUrl): string | undefined {\n let text = host.baseUrl.trim()\n while (text.endsWith('/')) {\n text = text.slice(0, -1)\n }\n if (text === '') {\n return undefined\n }\n // A bare `mac.tailnet.ts.net:8787` is a host:port, not a scheme, and tailnet gateways are plain http.\n if (!text.includes('://')) {\n text = 'http://' + text\n }\n if (!text.endsWith('/v1')) {\n text += '/v1'\n }\n try {\n // Validation only — the string, not the URL object, is what we keep.\n new URL(text)\n } catch {\n return undefined\n }\n return text\n}\n\nexport function isLoopbackHost(host: HostUrl): boolean {\n const api = apiUrl(host)\n if (!api) {\n return false\n }\n try {\n const { hostname } = new URL(api)\n return hostname === '127.0.0.1' || hostname === 'localhost' || hostname === '::1' || hostname === '[::1]'\n } catch {\n return false\n }\n}\n","import type { ClientOptions } from './index.ts'\n\nexport function hostAuth(options: { baseUrl: string; key: string }): Pick<ClientOptions, 'headers' | 'buildWsUrl' | 'buildQueueWsUrl'> {\n const { baseUrl, key } = options\n if (key === '') {\n return {}\n }\n\n const wsRoot = baseUrl.replace(/^http/, 'ws')\n const withKey = (url: string): string => `${url}${url.includes('?') ? '&' : '?'}key=${encodeURIComponent(key)}`\n\n return {\n headers: { authorization: `Bearer ${key}` },\n buildWsUrl: (sessionId, afterSeq) => withKey(`${wsRoot}/sessions/${encodeURIComponent(sessionId)}/ws?afterSeq=${afterSeq}`),\n buildQueueWsUrl: () => withKey(`${wsRoot}/queue/ws`),\n }\n}\n","import type {\n CreateJobRequest,\n CreateProfileRequest,\n CreateSessionRequest,\n JobInfo,\n FindHostFilesResponse,\n GetProfileResponse,\n ListHostDirResponse,\n ListHostRootsResponse,\n ListProfilesResponse,\n ListSessionFilesResponse,\n McpServerActionRequest,\n McpServersResponse,\n McpServerStatusInfo,\n MessageAttachment,\n ReadHostFileResponse,\n UploadAttachmentResponse,\n WriteHostFileRequest,\n WriteHostFileResponse,\n ProfileInfo,\n QueueStats,\n ResolvePermissionRequest,\n UpdateSessionRequest,\n SubmitExecutionResultRequest,\n SubmitExecutionResultResponse,\n SaveProfileResponse,\n SdkSessionSummary,\n SessionFileInfo,\n SessionInfo,\n UpdateProfileRequest,\n ToolResultBlock,\n} from '@workerdeck/protocol'\nimport { SessionHandle, type AttachOptions } from './session-handle.ts'\nimport { QueueHandle } from './queue-handle.ts'\n\nexport type FetchBody = NonNullable<NonNullable<Parameters<typeof fetch>[1]>['body']>\n\nexport type ClientOptions = {\n baseUrl: string\n headers?: Record<string, string>\n buildWsUrl?: (sessionId: string, afterSeq: number, truncateResults?: boolean, imageRefs?: boolean) => string\n buildQueueWsUrl?: () => string\n WebSocketImpl?: typeof WebSocket\n fetchImpl?: typeof fetch\n}\n\nexport class WorkerDeckError extends Error {\n readonly status: number\n constructor(message: string, status: number) {\n super(message)\n this.name = 'WorkerDeckError'\n this.status = status\n }\n}\n\nexport class WorkerDeckClient {\n #options: ClientOptions\n #fetch: typeof fetch\n #WebSocketImpl: typeof WebSocket\n\n constructor(options: ClientOptions) {\n this.#options = options\n this.#fetch = options.fetchImpl ?? fetch.bind(globalThis)\n this.#WebSocketImpl = options.WebSocketImpl ?? WebSocket\n }\n\n get identityKey(): string {\n const headers = Object.entries(this.#options.headers ?? {}).map(([name, value]) => [name.toLowerCase(), value] as const)\n headers.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return JSON.stringify([this.#options.baseUrl, headers])\n }\n\n async createSession(request: CreateSessionRequest): Promise<SessionInfo> {\n const body = await this.#call('POST', '/sessions', request)\n return (body as { session: SessionInfo }).session\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n const body = await this.#call('GET', '/sessions')\n return (body as { sessions: SessionInfo[] }).sessions\n }\n\n async getSession(id: string): Promise<SessionInfo> {\n const body = await this.#call('GET', `/sessions/${encodeURIComponent(id)}`)\n return (body as { session: SessionInfo }).session\n }\n\n async updateSession(id: string, patch: UpdateSessionRequest): Promise<SessionInfo> {\n const body = await this.#call('PATCH', `/sessions/${encodeURIComponent(id)}`, patch)\n return (body as { session: SessionInfo }).session\n }\n\n async deleteSession(id: string): Promise<SessionInfo> {\n const body = await this.#call('DELETE', `/sessions/${encodeURIComponent(id)}`)\n return (body as { session: SessionInfo }).session\n }\n\n async listSessionFiles(sessionId: string): Promise<SessionFileInfo[]> {\n const body = await this.#call('GET', `/sessions/${encodeURIComponent(sessionId)}/files`)\n return (body as ListSessionFilesResponse).files\n }\n\n async fetchSessionFile(sessionId: string, path: string): Promise<string> {\n const res = await this.#callRaw(this.sessionFileUrl(sessionId, path), { headers: this.#options.headers }, 'GET file failed')\n return await res.text()\n }\n\n async uploadAttachment(sessionId: string, file: { name: string; mediaType: string; data: FetchBody }): Promise<MessageAttachment> {\n const url = `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/attachments?name=${encodeURIComponent(file.name)}`\n const res = await this.#callRaw(\n url,\n { method: 'POST', headers: { ...this.#options.headers, 'content-type': file.mediaType }, body: file.data },\n 'upload failed',\n )\n return ((await res.json()) as UploadAttachmentResponse).attachment\n }\n\n attachmentUrl(sessionId: string, attachmentId: string): string {\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/attachments/${encodeURIComponent(attachmentId)}`\n }\n\n producedFileUrl(sessionId: string, fileId: string): string {\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/produced/${encodeURIComponent(fileId)}`\n }\n\n async readProducedFile(sessionId: string, fileId: string): Promise<Blob> {\n const res = await this.#callRaw(\n this.producedFileUrl(sessionId, fileId),\n { headers: { ...this.#options.headers } },\n 'produced file request failed',\n )\n return await res.blob()\n }\n\n projectIconUrl(sessionId: string): string {\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/project/icon`\n }\n\n async projectIcon(sessionId: string): Promise<Blob> {\n const res = await this.#callRaw(\n this.projectIconUrl(sessionId),\n { headers: { ...this.#options.headers } },\n 'project icon request failed',\n )\n return await res.blob()\n }\n\n async listMcpServers(sessionId: string): Promise<McpServerStatusInfo[]> {\n const body = await this.#call('GET', `/sessions/${encodeURIComponent(sessionId)}/mcp`)\n return (body as McpServersResponse).servers\n }\n\n async mcpServerAction(sessionId: string, serverName: string, action: McpServerActionRequest['action']): Promise<McpServerStatusInfo[]> {\n const body = await this.#call('POST', `/sessions/${encodeURIComponent(sessionId)}/mcp/${encodeURIComponent(serverName)}`, { action })\n return (body as McpServersResponse).servers\n }\n\n sessionFileUrl(sessionId: string, path: string): string {\n const encoded = path.split('/').filter(Boolean).map(encodeURIComponent).join('/')\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/files/${encoded}`\n }\n\n async resolvePermission(sessionId: string, requestId: string, decision: ResolvePermissionRequest): Promise<void> {\n await this.#call('POST', `/sessions/${encodeURIComponent(sessionId)}/permissions/${encodeURIComponent(requestId)}`, decision)\n }\n\n async submitExecutionResult(executionId: string, result: SubmitExecutionResultRequest): Promise<SubmitExecutionResultResponse> {\n return (await this.#call('POST', `/executions/${encodeURIComponent(executionId)}/result`, result)) as SubmitExecutionResultResponse\n }\n\n async listProfiles(): Promise<ListProfilesResponse> {\n return (await this.#call('GET', '/profiles')) as ListProfilesResponse\n }\n\n async getProfile(name: string): Promise<GetProfileResponse> {\n return (await this.#call('GET', `/profiles/${encodeURIComponent(name)}`)) as GetProfileResponse\n }\n\n async createProfile(profile: CreateProfileRequest): Promise<ProfileInfo> {\n const body = await this.#call('POST', '/profiles', profile)\n return (body as SaveProfileResponse).profile\n }\n\n async updateProfile(name: string, patch: UpdateProfileRequest): Promise<ProfileInfo> {\n const body = await this.#call('PATCH', `/profiles/${encodeURIComponent(name)}`, patch)\n return (body as SaveProfileResponse).profile\n }\n\n async deleteProfile(name: string): Promise<void> {\n await this.#call('DELETE', `/profiles/${encodeURIComponent(name)}`)\n }\n\n async listSdkSessions(params?: { dir?: string; limit?: number; offset?: number; profile?: string }): Promise<SdkSessionSummary[]> {\n const search = new URLSearchParams()\n if (params?.dir) {\n search.set('dir', params.dir)\n }\n if (params?.limit !== undefined) {\n search.set('limit', String(params.limit))\n }\n if (params?.offset !== undefined) {\n search.set('offset', String(params.offset))\n }\n if (params?.profile) {\n search.set('profile', params.profile)\n }\n const qs = search.size > 0 ? `?${search.toString()}` : ''\n const body = await this.#call('GET', `/sdk-sessions${qs}`)\n return (body as { sdkSessions: SdkSessionSummary[] }).sdkSessions\n }\n\n async listHostRoots(): Promise<ListHostRootsResponse> {\n return (await this.#call('GET', '/fs/roots')) as ListHostRootsResponse\n }\n\n async listHostDir(path: string): Promise<ListHostDirResponse> {\n const qs = `?path=${encodeURIComponent(path)}`\n return (await this.#call('GET', `/fs/list${qs}`)) as ListHostDirResponse\n }\n\n async findHostFiles(path: string, query = '', limit?: number): Promise<FindHostFilesResponse> {\n const search = new URLSearchParams({ path, q: query })\n if (limit !== undefined) {\n search.set('limit', String(limit))\n }\n return (await this.#call('GET', `/fs/find?${search.toString()}`)) as FindHostFilesResponse\n }\n\n async readHostFile(path: string): Promise<ReadHostFileResponse> {\n const qs = `?path=${encodeURIComponent(path)}`\n return (await this.#call('GET', `/fs/read${qs}`)) as ReadHostFileResponse\n }\n\n async writeHostFile(request: WriteHostFileRequest): Promise<WriteHostFileResponse> {\n return (await this.#call('PUT', '/fs/write', request)) as WriteHostFileResponse\n }\n\n async createJob(request: CreateJobRequest): Promise<JobInfo> {\n const body = await this.#call('POST', '/jobs', request)\n return (body as { job: JobInfo }).job\n }\n\n async listJobs(): Promise<JobInfo[]> {\n const body = await this.#call('GET', '/jobs')\n return (body as { jobs: JobInfo[] }).jobs\n }\n\n async getJob(id: string): Promise<JobInfo> {\n const body = await this.#call('GET', `/jobs/${encodeURIComponent(id)}`)\n return (body as { job: JobInfo }).job\n }\n\n async cancelJob(id: string): Promise<JobInfo> {\n const body = await this.#call('DELETE', `/jobs/${encodeURIComponent(id)}`)\n return (body as { job: JobInfo }).job\n }\n\n async queueStats(): Promise<QueueStats> {\n const body = await this.#call('GET', '/queue')\n return (body as { stats: QueueStats }).stats\n }\n\n attach(sessionId: string, options?: AttachOptions): SessionHandle {\n return new SessionHandle(this, sessionId, options)\n }\n\n attachQueue(options?: { reconnect?: boolean }): QueueHandle {\n return new QueueHandle(this, options)\n }\n\n openSocket(sessionId: string, afterSeq: number, truncateResults = false, imageRefs = false): WebSocket {\n const query = `afterSeq=${afterSeq}` + (truncateResults ? '&truncateResults=1' : '') + (imageRefs ? '&imageRefs=1' : '')\n const url =\n this.#options.buildWsUrl?.(sessionId, afterSeq, truncateResults, imageRefs) ??\n `${this.#options.baseUrl.replace(/^http/, 'ws')}/sessions/${encodeURIComponent(sessionId)}/ws?${query}`\n return new this.#WebSocketImpl(url)\n }\n\n async toolResult(\n sessionId: string,\n seq: number,\n toolUseId: string,\n options?: { imageRefs?: boolean },\n ): Promise<{ seq: number; toolUseId: string; content: ToolResultBlock['content']; isError: boolean }> {\n return (await this.#call(\n 'GET',\n `/sessions/${encodeURIComponent(sessionId)}/events/${seq}/result?toolUseId=${encodeURIComponent(toolUseId)}` +\n (options?.imageRefs ? '&imageRefs=1' : ''),\n )) as { seq: number; toolUseId: string; content: ToolResultBlock['content']; isError: boolean }\n }\n\n async toolResultImage(sessionId: string, seq: number, toolUseId: string, partIndex: number): Promise<Blob> {\n const path =\n `/sessions/${encodeURIComponent(sessionId)}/events/${seq}/result` + `?toolUseId=${encodeURIComponent(toolUseId)}&part=${partIndex}`\n const res = await this.#callRaw(\n `${this.#options.baseUrl}${path}`,\n { headers: { ...this.#options.headers } },\n 'image part request failed',\n )\n return await res.blob()\n }\n\n openQueueSocket(): WebSocket {\n const url = this.#options.buildQueueWsUrl?.() ?? `${this.#options.baseUrl.replace(/^http/, 'ws')}/queue/ws`\n return new this.#WebSocketImpl(url)\n }\n\n /** The byte-serving routes' shared failure arm: `#call` owns the same rule for JSON routes. */\n async #callRaw(url: string, init: NonNullable<Parameters<typeof fetch>[1]>, failure: string): Promise<Response> {\n const res = await this.#fetch(url, init)\n if (!res.ok) {\n const payload = (await res.json().catch(() => ({}))) as { error?: string }\n throw new WorkerDeckError(payload.error ?? `${failure} with ${res.status}`, res.status)\n }\n return res\n }\n\n async #call(method: string, path: string, body?: unknown): Promise<unknown> {\n const res = await this.#fetch(`${this.#options.baseUrl}${path}`, {\n method,\n headers: {\n ...(body !== undefined ? { 'content-type': 'application/json' } : {}),\n ...this.#options.headers,\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n const payload = (await res.json().catch(() => ({}))) as { error?: string }\n if (!res.ok) {\n throw new WorkerDeckError(payload.error ?? `${method} ${path} failed with ${res.status}`, res.status)\n }\n return payload\n }\n}\n\nexport { SessionHandle } from './session-handle.ts'\nexport type { AttachOptions, SessionHandleEvents } from './session-handle.ts'\nexport { QueueHandle } from './queue-handle.ts'\nexport type { QueueHandleEvents } from './queue-handle.ts'\nexport { apiUrl, isLoopbackHost } from './host-url.ts'\nexport type { HostUrl } from './host-url.ts'\nexport { hostAuth } from './host-auth.ts'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/emitter.ts","../src/session-handle.ts","../src/queue-handle.ts","../src/host-url.ts","../src/host-auth.ts","../src/index.ts"],"sourcesContent":["export type Listener<T> = (payload: T) => void\n\n/**\n * The handles' listener registry. A throwing listener must never stop the ones queued behind it:\n * these fire from a socket callback, where an escaping error would take the connection with it.\n */\nexport class Emitter<Events> {\n #listeners = new Map<keyof Events, Set<Listener<never>>>()\n\n on<K extends keyof Events>(kind: K, listener: Listener<Events[K]>): () => void {\n let set = this.#listeners.get(kind)\n if (!set) {\n set = new Set()\n this.#listeners.set(kind, set)\n }\n set.add(listener as Listener<never>)\n return () => set.delete(listener as Listener<never>)\n }\n\n emit<K extends keyof Events>(kind: K, payload: Events[K]): void {\n const set = this.#listeners.get(kind)\n if (!set) {\n return\n }\n for (const listener of set) {\n try {\n ;(listener as Listener<Events[K]>)(payload)\n } catch {}\n }\n }\n}\n\n/** 500ms doubling from a zero-based attempt count, capped at 10s. */\nexport function reconnectDelay(retries: number): number {\n return Math.min(500 * 2 ** retries, 10_000)\n}\n","import type {\n AttachedFrame,\n ClientFrame,\n PermissionMode,\n ServerFrame,\n SessionEvent,\n ToolCallRequestFrame,\n ToolExecutionOutput,\n} from '@workerdeck/protocol'\nimport { Emitter, reconnectDelay, type Listener } from './lib/emitter.ts'\nimport type { WorkerDeckClient } from './index.ts'\n\nexport type AttachOptions = {\n afterSeq?: number\n reconnect?: boolean\n truncateResults?: boolean\n imageRefs?: boolean\n}\n\nexport type SessionHandleEvents = {\n attached: AttachedFrame\n event: SessionEvent\n protocolError: string\n connectionChange: boolean\n reconnectAttempt: number\n toolCallRequest: ToolCallRequestFrame\n toolCallCanceled: { executionId: string; reason: string }\n}\n\nexport class SessionHandle {\n readonly sessionId: string\n #client: WorkerDeckClient\n #options: Required<Pick<AttachOptions, 'reconnect'>> & AttachOptions\n #ws: WebSocket | undefined\n #events = new Emitter<SessionHandleEvents>()\n #lastSeq: number\n #closed = false\n #retries = 0\n #outbox: string[] = []\n #connectTimer: ReturnType<typeof setTimeout> | undefined\n\n constructor(client: WorkerDeckClient, sessionId: string, options: AttachOptions = {}) {\n this.#client = client\n this.sessionId = sessionId\n this.#options = { reconnect: true, ...options }\n this.#lastSeq = options.afterSeq ?? 0\n // Deferred a tick so a same-tick detach (React StrictMode's dev mount) never closes a WebSocket mid-upgrade, which breaks proxies.\n this.#connectTimer = setTimeout(() => this.#connect(), 0)\n }\n\n get lastSeq(): number {\n return this.#lastSeq\n }\n\n on<K extends keyof SessionHandleEvents>(kind: K, listener: Listener<SessionHandleEvents[K]>): () => void {\n return this.#events.on(kind, listener)\n }\n\n send(text: string, attachmentIds?: string[]): void {\n this.#sendFrame({\n type: 'user_message',\n text,\n attachmentIds: attachmentIds?.length ? attachmentIds : undefined,\n })\n }\n\n approve(requestId: string, updatedInput?: Record<string, unknown>): void {\n this.#sendFrame({ type: 'permission_decision', requestId, behavior: 'allow', updatedInput })\n }\n\n deny(requestId: string, message?: string, interrupt?: boolean): void {\n this.#sendFrame({ type: 'permission_decision', requestId, behavior: 'deny', message, interrupt })\n }\n\n interrupt(): void {\n this.#sendFrame({ type: 'interrupt' })\n }\n\n clearContext(): void {\n this.#sendFrame({ type: 'clear_context' })\n }\n\n setPermissionMode(mode: PermissionMode): void {\n this.#sendFrame({ type: 'set_permission_mode', mode })\n }\n\n setModel(model?: string): void {\n this.#sendFrame({ type: 'set_model', model })\n }\n\n sendToolCallResult(executionId: string, output: ToolExecutionOutput, logs?: string[]): void {\n this.#sendFrame({ type: 'tool_call_result', executionId, output, logs })\n }\n\n sendToolCallError(executionId: string, reason: string, error: string, logs?: string[]): void {\n this.#sendFrame({ type: 'tool_call_error', executionId, reason, error, logs })\n }\n\n closeSession(): void {\n this.#sendFrame({ type: 'close' })\n this.detach()\n }\n\n reconnectNow(): void {\n if (this.#closed || (this.#ws && this.#ws.readyState === 1)) {\n return\n }\n clearTimeout(this.#connectTimer)\n this.#retries = 0\n this.#connect()\n }\n\n detach(): void {\n this.#closed = true\n clearTimeout(this.#connectTimer)\n this.#ws?.close()\n this.#ws = undefined\n }\n\n #sendFrame(frame: ClientFrame): void {\n const payload = JSON.stringify(frame)\n // readyState 1 === OPEN (avoid touching the WebSocket global; impl may be injected)\n if (this.#ws && this.#ws.readyState === 1) {\n this.#ws.send(payload)\n } else {\n this.#outbox.push(payload)\n }\n }\n\n #connect(): void {\n if (this.#closed) {\n return\n }\n const ws = this.#client.openSocket(this.sessionId, this.#lastSeq, this.#options.truncateResults, this.#options.imageRefs)\n this.#ws = ws\n ws.onopen = () => {\n this.#retries = 0\n this.#events.emit('connectionChange', true)\n for (const payload of this.#outbox.splice(0)) {\n ws.send(payload)\n }\n }\n ws.onmessage = (msg: MessageEvent) => {\n const frame = JSON.parse(String(msg.data)) as ServerFrame\n if (frame.type === 'attached') {\n this.#events.emit('attached', frame)\n } else if (frame.type === 'event') {\n if (frame.event.seq <= this.#lastSeq) {\n return\n }\n this.#lastSeq = frame.event.seq\n this.#events.emit('event', frame.event)\n } else if (frame.type === 'tool_call_request') {\n this.#events.emit('toolCallRequest', frame)\n } else if (frame.type === 'tool_call_canceled') {\n this.#events.emit('toolCallCanceled', { executionId: frame.executionId, reason: frame.reason })\n } else if (frame.type === 'protocol_error') {\n this.#events.emit('protocolError', frame.message)\n }\n }\n ws.onclose = () => {\n this.#events.emit('connectionChange', false)\n if (this.#closed || !this.#options.reconnect) {\n return\n }\n const delay = reconnectDelay(this.#retries++)\n this.#events.emit('reconnectAttempt', this.#retries)\n this.#connectTimer = setTimeout(() => this.#connect(), delay)\n }\n ws.onerror = () => {}\n }\n}\n","import type { JobEvent, QueueServerFrame, QueueStats } from '@workerdeck/protocol'\nimport { Emitter, reconnectDelay, type Listener } from './lib/emitter.ts'\nimport type { WorkerDeckClient } from './index.ts'\n\nexport type QueueHandleEvents = {\n attached: QueueStats\n event: JobEvent\n stats: QueueStats\n connectionChange: boolean\n}\n\nexport class QueueHandle {\n #client: WorkerDeckClient\n #reconnect: boolean\n #ws: WebSocket | undefined\n #events = new Emitter<QueueHandleEvents>()\n #closed = false\n #retries = 0\n #connectTimer: ReturnType<typeof setTimeout> | undefined\n\n constructor(client: WorkerDeckClient, options: { reconnect?: boolean } = {}) {\n this.#client = client\n this.#reconnect = options.reconnect ?? true\n // Deferred a tick for the same StrictMode reason as SessionHandle.\n this.#connectTimer = setTimeout(() => this.#connect(), 0)\n }\n\n on<K extends keyof QueueHandleEvents>(kind: K, listener: Listener<QueueHandleEvents[K]>): () => void {\n return this.#events.on(kind, listener)\n }\n\n detach(): void {\n this.#closed = true\n clearTimeout(this.#connectTimer)\n this.#ws?.close()\n this.#ws = undefined\n }\n\n #connect(): void {\n if (this.#closed) {\n return\n }\n const ws = this.#client.openQueueSocket()\n this.#ws = ws\n ws.onopen = () => {\n this.#retries = 0\n this.#events.emit('connectionChange', true)\n }\n ws.onmessage = (msg: MessageEvent) => {\n const frame = JSON.parse(String(msg.data)) as QueueServerFrame\n if (frame.type === 'queue_attached') {\n this.#events.emit('attached', frame.stats)\n this.#events.emit('stats', frame.stats)\n } else if (frame.type === 'job_event') {\n this.#events.emit('event', frame.event)\n } else if (frame.type === 'queue_stats') {\n this.#events.emit('stats', frame.stats)\n }\n }\n ws.onclose = () => {\n this.#events.emit('connectionChange', false)\n if (this.#closed || !this.#reconnect) {\n return\n }\n const delay = reconnectDelay(this.#retries++)\n this.#connectTimer = setTimeout(() => this.#connect(), delay)\n }\n ws.onerror = () => {}\n }\n}\n","export type HostUrl = { baseUrl: string }\n\nexport function apiUrl(host: HostUrl): string | undefined {\n let text = host.baseUrl.trim()\n while (text.endsWith('/')) {\n text = text.slice(0, -1)\n }\n if (text === '') {\n return undefined\n }\n // A bare `mac.tailnet.ts.net:8787` is a host:port, not a scheme, and tailnet gateways are plain http.\n if (!text.includes('://')) {\n text = 'http://' + text\n }\n if (!text.endsWith('/v1')) {\n text += '/v1'\n }\n try {\n // Validation only — the string, not the URL object, is what we keep.\n new URL(text)\n } catch {\n return undefined\n }\n return text\n}\n\nexport function isLoopbackHost(host: HostUrl): boolean {\n const api = apiUrl(host)\n if (!api) {\n return false\n }\n try {\n const { hostname } = new URL(api)\n return hostname === '127.0.0.1' || hostname === 'localhost' || hostname === '::1' || hostname === '[::1]'\n } catch {\n return false\n }\n}\n","import type { ClientOptions } from './index.ts'\n\nexport function hostAuth(options: { baseUrl: string; key: string }): Pick<ClientOptions, 'headers' | 'buildWsUrl' | 'buildQueueWsUrl'> {\n const { baseUrl, key } = options\n if (key === '') {\n return {}\n }\n\n const wsRoot = baseUrl.replace(/^http/, 'ws')\n const withKey = (url: string): string => `${url}${url.includes('?') ? '&' : '?'}key=${encodeURIComponent(key)}`\n\n return {\n headers: { authorization: `Bearer ${key}` },\n buildWsUrl: (sessionId, afterSeq) => withKey(`${wsRoot}/sessions/${encodeURIComponent(sessionId)}/ws?afterSeq=${afterSeq}`),\n buildQueueWsUrl: () => withKey(`${wsRoot}/queue/ws`),\n }\n}\n","import type {\n CreateJobRequest,\n CreateProfileRequest,\n CreateSessionRequest,\n JobInfo,\n FindHostFilesResponse,\n GetProfileResponse,\n ListHostDirResponse,\n ListHostRootsResponse,\n ListProfilesResponse,\n ListSessionFilesResponse,\n McpServerActionRequest,\n McpServersResponse,\n McpServerStatusInfo,\n MessageAttachment,\n ReadHostFileResponse,\n UploadAttachmentResponse,\n WriteHostFileRequest,\n WriteHostFileResponse,\n ProfileInfo,\n QueueStats,\n ResolvePermissionRequest,\n UpdateSessionRequest,\n SubmitExecutionResultRequest,\n SubmitExecutionResultResponse,\n SaveProfileResponse,\n SdkSessionSummary,\n SessionFileInfo,\n SessionInfo,\n UpdateProfileRequest,\n ToolResultBlock,\n} from '@workerdeck/protocol'\nimport { SessionHandle, type AttachOptions } from './session-handle.ts'\nimport { QueueHandle } from './queue-handle.ts'\n\nexport type FetchBody = NonNullable<NonNullable<Parameters<typeof fetch>[1]>['body']>\n\nexport type ClientOptions = {\n baseUrl: string\n headers?: Record<string, string>\n buildWsUrl?: (sessionId: string, afterSeq: number, truncateResults?: boolean, imageRefs?: boolean) => string\n buildQueueWsUrl?: () => string\n WebSocketImpl?: typeof WebSocket\n fetchImpl?: typeof fetch\n}\n\nexport class WorkerDeckError extends Error {\n readonly status: number\n constructor(message: string, status: number) {\n super(message)\n this.name = 'WorkerDeckError'\n this.status = status\n }\n}\n\nexport class WorkerDeckClient {\n #options: ClientOptions\n #fetch: typeof fetch\n #WebSocketImpl: typeof WebSocket\n\n constructor(options: ClientOptions) {\n this.#options = options\n this.#fetch = options.fetchImpl ?? fetch.bind(globalThis)\n this.#WebSocketImpl = options.WebSocketImpl ?? WebSocket\n }\n\n get identityKey(): string {\n const headers = Object.entries(this.#options.headers ?? {}).map(([name, value]) => [name.toLowerCase(), value] as const)\n headers.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return JSON.stringify([this.#options.baseUrl, headers])\n }\n\n async createSession(request: CreateSessionRequest): Promise<SessionInfo> {\n const body = await this.#call('POST', '/sessions', request)\n return (body as { session: SessionInfo }).session\n }\n\n async listSessions(): Promise<SessionInfo[]> {\n const body = await this.#call('GET', '/sessions')\n return (body as { sessions: SessionInfo[] }).sessions\n }\n\n async getSession(id: string): Promise<SessionInfo> {\n const body = await this.#call('GET', `/sessions/${encodeURIComponent(id)}`)\n return (body as { session: SessionInfo }).session\n }\n\n async updateSession(id: string, patch: UpdateSessionRequest): Promise<SessionInfo> {\n const body = await this.#call('PATCH', `/sessions/${encodeURIComponent(id)}`, patch)\n return (body as { session: SessionInfo }).session\n }\n\n async deleteSession(id: string): Promise<SessionInfo> {\n const body = await this.#call('DELETE', `/sessions/${encodeURIComponent(id)}`)\n return (body as { session: SessionInfo }).session\n }\n\n async listSessionFiles(sessionId: string): Promise<SessionFileInfo[]> {\n const body = await this.#call('GET', `/sessions/${encodeURIComponent(sessionId)}/files`)\n return (body as ListSessionFilesResponse).files\n }\n\n async fetchSessionFile(sessionId: string, path: string): Promise<string> {\n const res = await this.#callRaw(this.sessionFileUrl(sessionId, path), { headers: this.#options.headers }, 'GET file failed')\n return await res.text()\n }\n\n async uploadAttachment(sessionId: string, file: { name: string; mediaType: string; data: FetchBody }): Promise<MessageAttachment> {\n const url = `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/attachments?name=${encodeURIComponent(file.name)}`\n const res = await this.#callRaw(\n url,\n { method: 'POST', headers: { ...this.#options.headers, 'content-type': file.mediaType }, body: file.data },\n 'upload failed',\n )\n return ((await res.json()) as UploadAttachmentResponse).attachment\n }\n\n attachmentUrl(sessionId: string, attachmentId: string): string {\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/attachments/${encodeURIComponent(attachmentId)}`\n }\n\n producedFileUrl(sessionId: string, fileId: string): string {\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/produced/${encodeURIComponent(fileId)}`\n }\n\n async readProducedFile(sessionId: string, fileId: string): Promise<Blob> {\n const res = await this.#callRaw(\n this.producedFileUrl(sessionId, fileId),\n { headers: { ...this.#options.headers } },\n 'produced file request failed',\n )\n return await res.blob()\n }\n\n projectIconUrl(sessionId: string): string {\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/project/icon`\n }\n\n async projectIcon(sessionId: string): Promise<Blob> {\n const res = await this.#callRaw(\n this.projectIconUrl(sessionId),\n { headers: { ...this.#options.headers } },\n 'project icon request failed',\n )\n return await res.blob()\n }\n\n async listMcpServers(sessionId: string): Promise<McpServerStatusInfo[]> {\n const body = await this.#call('GET', `/sessions/${encodeURIComponent(sessionId)}/mcp`)\n return (body as McpServersResponse).servers\n }\n\n async mcpServerAction(sessionId: string, serverName: string, action: McpServerActionRequest['action']): Promise<McpServerStatusInfo[]> {\n const body = await this.#call('POST', `/sessions/${encodeURIComponent(sessionId)}/mcp/${encodeURIComponent(serverName)}`, { action })\n return (body as McpServersResponse).servers\n }\n\n sessionFileUrl(sessionId: string, path: string): string {\n const encoded = path.split('/').filter(Boolean).map(encodeURIComponent).join('/')\n return `${this.#options.baseUrl}/sessions/${encodeURIComponent(sessionId)}/files/${encoded}`\n }\n\n async resolvePermission(sessionId: string, requestId: string, decision: ResolvePermissionRequest): Promise<void> {\n await this.#call('POST', `/sessions/${encodeURIComponent(sessionId)}/permissions/${encodeURIComponent(requestId)}`, decision)\n }\n\n async submitExecutionResult(executionId: string, result: SubmitExecutionResultRequest): Promise<SubmitExecutionResultResponse> {\n return (await this.#call('POST', `/executions/${encodeURIComponent(executionId)}/result`, result)) as SubmitExecutionResultResponse\n }\n\n async listProfiles(): Promise<ListProfilesResponse> {\n return (await this.#call('GET', '/profiles')) as ListProfilesResponse\n }\n\n async getProfile(name: string): Promise<GetProfileResponse> {\n return (await this.#call('GET', `/profiles/${encodeURIComponent(name)}`)) as GetProfileResponse\n }\n\n async createProfile(profile: CreateProfileRequest): Promise<ProfileInfo> {\n const body = await this.#call('POST', '/profiles', profile)\n return (body as SaveProfileResponse).profile\n }\n\n async updateProfile(name: string, patch: UpdateProfileRequest): Promise<ProfileInfo> {\n const body = await this.#call('PATCH', `/profiles/${encodeURIComponent(name)}`, patch)\n return (body as SaveProfileResponse).profile\n }\n\n async deleteProfile(name: string): Promise<void> {\n await this.#call('DELETE', `/profiles/${encodeURIComponent(name)}`)\n }\n\n async listSdkSessions(params?: { dir?: string; limit?: number; offset?: number; profile?: string }): Promise<SdkSessionSummary[]> {\n const search = new URLSearchParams()\n if (params?.dir) {\n search.set('dir', params.dir)\n }\n if (params?.limit !== undefined) {\n search.set('limit', String(params.limit))\n }\n if (params?.offset !== undefined) {\n search.set('offset', String(params.offset))\n }\n if (params?.profile) {\n search.set('profile', params.profile)\n }\n const qs = search.size > 0 ? `?${search.toString()}` : ''\n const body = await this.#call('GET', `/sdk-sessions${qs}`)\n return (body as { sdkSessions: SdkSessionSummary[] }).sdkSessions\n }\n\n async listHostRoots(): Promise<ListHostRootsResponse> {\n return (await this.#call('GET', '/fs/roots')) as ListHostRootsResponse\n }\n\n async listHostDir(path: string): Promise<ListHostDirResponse> {\n const qs = `?path=${encodeURIComponent(path)}`\n return (await this.#call('GET', `/fs/list${qs}`)) as ListHostDirResponse\n }\n\n async findHostFiles(path: string, query = '', limit?: number): Promise<FindHostFilesResponse> {\n const search = new URLSearchParams({ path, q: query })\n if (limit !== undefined) {\n search.set('limit', String(limit))\n }\n return (await this.#call('GET', `/fs/find?${search.toString()}`)) as FindHostFilesResponse\n }\n\n async readHostFile(path: string): Promise<ReadHostFileResponse> {\n const qs = `?path=${encodeURIComponent(path)}`\n return (await this.#call('GET', `/fs/read${qs}`)) as ReadHostFileResponse\n }\n\n async writeHostFile(request: WriteHostFileRequest): Promise<WriteHostFileResponse> {\n return (await this.#call('PUT', '/fs/write', request)) as WriteHostFileResponse\n }\n\n async createJob(request: CreateJobRequest): Promise<JobInfo> {\n const body = await this.#call('POST', '/jobs', request)\n return (body as { job: JobInfo }).job\n }\n\n async listJobs(): Promise<JobInfo[]> {\n const body = await this.#call('GET', '/jobs')\n return (body as { jobs: JobInfo[] }).jobs\n }\n\n async getJob(id: string): Promise<JobInfo> {\n const body = await this.#call('GET', `/jobs/${encodeURIComponent(id)}`)\n return (body as { job: JobInfo }).job\n }\n\n async cancelJob(id: string): Promise<JobInfo> {\n const body = await this.#call('DELETE', `/jobs/${encodeURIComponent(id)}`)\n return (body as { job: JobInfo }).job\n }\n\n async queueStats(): Promise<QueueStats> {\n const body = await this.#call('GET', '/queue')\n return (body as { stats: QueueStats }).stats\n }\n\n attach(sessionId: string, options?: AttachOptions): SessionHandle {\n return new SessionHandle(this, sessionId, options)\n }\n\n attachQueue(options?: { reconnect?: boolean }): QueueHandle {\n return new QueueHandle(this, options)\n }\n\n openSocket(sessionId: string, afterSeq: number, truncateResults = false, imageRefs = false): WebSocket {\n const query = `afterSeq=${afterSeq}` + (truncateResults ? '&truncateResults=1' : '') + (imageRefs ? '&imageRefs=1' : '')\n const url =\n this.#options.buildWsUrl?.(sessionId, afterSeq, truncateResults, imageRefs) ??\n `${this.#options.baseUrl.replace(/^http/, 'ws')}/sessions/${encodeURIComponent(sessionId)}/ws?${query}`\n return new this.#WebSocketImpl(url)\n }\n\n async toolResult(\n sessionId: string,\n seq: number,\n toolUseId: string,\n options?: { imageRefs?: boolean },\n ): Promise<{ seq: number; toolUseId: string; content: ToolResultBlock['content']; isError: boolean }> {\n return (await this.#call(\n 'GET',\n `/sessions/${encodeURIComponent(sessionId)}/events/${seq}/result?toolUseId=${encodeURIComponent(toolUseId)}` +\n (options?.imageRefs ? '&imageRefs=1' : ''),\n )) as { seq: number; toolUseId: string; content: ToolResultBlock['content']; isError: boolean }\n }\n\n async toolResultImage(sessionId: string, seq: number, toolUseId: string, partIndex: number): Promise<Blob> {\n const path =\n `/sessions/${encodeURIComponent(sessionId)}/events/${seq}/result` + `?toolUseId=${encodeURIComponent(toolUseId)}&part=${partIndex}`\n const res = await this.#callRaw(\n `${this.#options.baseUrl}${path}`,\n { headers: { ...this.#options.headers } },\n 'image part request failed',\n )\n return await res.blob()\n }\n\n openQueueSocket(): WebSocket {\n const url = this.#options.buildQueueWsUrl?.() ?? `${this.#options.baseUrl.replace(/^http/, 'ws')}/queue/ws`\n return new this.#WebSocketImpl(url)\n }\n\n /** The byte-serving routes' shared failure arm: `#call` owns the same rule for JSON routes. */\n async #callRaw(url: string, init: NonNullable<Parameters<typeof fetch>[1]>, failure: string): Promise<Response> {\n const res = await this.#fetch(url, init)\n if (!res.ok) {\n const payload = (await res.json().catch(() => ({}))) as { error?: string }\n throw new WorkerDeckError(payload.error ?? `${failure} with ${res.status}`, res.status)\n }\n return res\n }\n\n async #call(method: string, path: string, body?: unknown): Promise<unknown> {\n const res = await this.#fetch(`${this.#options.baseUrl}${path}`, {\n method,\n headers: {\n ...(body !== undefined ? { 'content-type': 'application/json' } : {}),\n ...this.#options.headers,\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n const payload = (await res.json().catch(() => ({}))) as { error?: string }\n if (!res.ok) {\n throw new WorkerDeckError(payload.error ?? `${method} ${path} failed with ${res.status}`, res.status)\n }\n return payload\n }\n}\n\nexport { SessionHandle } from './session-handle.ts'\nexport type { AttachOptions, SessionHandleEvents } from './session-handle.ts'\nexport { QueueHandle } from './queue-handle.ts'\nexport type { QueueHandleEvents } from './queue-handle.ts'\nexport { apiUrl, isLoopbackHost } from './host-url.ts'\nexport type { HostUrl } from './host-url.ts'\nexport { hostAuth } from './host-auth.ts'\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workerdeck/client",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "Typed WorkerDeck protocol client for browsers and Node: REST session management plus a WebSocket attach with auto-reconnect and replay-from-last-seq. Uses the platform's fetch and WebSocket; zero runtime deps.",
6
6
  "license": "MIT",
@@ -17,17 +17,17 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@workerdeck/protocol": "1.0.0"
20
+ "@workerdeck/protocol": "1.1.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@types/node": "^22.10.0",
23
+ "@types/node": "^26.4.0",
24
24
  "@types/ws": "^8.18.1",
25
25
  "rimraf": "^6.1.3",
26
- "tsdown": "^0.21.10",
27
- "vitest": "^3.2.7",
28
- "ws": "^8.21.1",
29
- "@workerdeck/core": "1.0.0",
30
- "@workerdeck/server": "1.0.0"
26
+ "tsdown": "^0.22.14",
27
+ "vitest": "^4.1.11",
28
+ "ws": "^8.21.3",
29
+ "@workerdeck/core": "1.1.0",
30
+ "@workerdeck/server": "1.1.0"
31
31
  },
32
32
  "author": "Tobias Strebitzer",
33
33
  "repository": {