@sinas/sdk 0.5.0 → 0.8.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/index.ts","../src/client/errors.ts","../src/client/auth.ts","../src/client/SinasClient.ts","../src/client/queries.ts","../src/client/functions.ts","../src/client/states.ts","../src/client/chat.ts","../src/client/collections.ts"],"sourcesContent":["export { SinasClient, SinasClientAuth, type SinasClientOptions } from './SinasClient';\nexport { executeQuery } from './queries';\nexport { executeFunction } from './functions';\nexport { stateGet, stateSet, stateDelete, stateList } from './states';\nexport { createChat, sendMessage, streamMessage, getChat, approveToolCall, streamFromChannel } from './chat';\nexport { listCollections, listFiles, uploadFile, generateFileUrl } from './collections';\nexport {\n getInfo,\n login,\n verifyOTP,\n refresh,\n logout,\n getMe,\n checkPermissions,\n} from './auth';\nexport {\n SinasError,\n SinasAuthError,\n SinasPermissionError,\n SinasNotFoundError,\n SinasTimeoutError,\n} from './errors';\nexport type {\n SinasConfig,\n QueryResult,\n FunctionResult,\n StateGetResult,\n StateListResult,\n ChatCreateResult,\n ChatMessage,\n ChatMessageFull,\n ToolCallInfo,\n ChatDetail,\n ApprovalRequest,\n ApprovalResult,\n ContentPart,\n TextContentPart,\n ImageContentPart,\n AudioContentPart,\n FileContentPart,\n ComponentContentPart,\n MessageContent,\n SSEChunk,\n Collection,\n FileInfo,\n FileUploadRequest,\n FileUrlResult,\n AuthMode,\n AuthUser,\n InfoResponse,\n LoginRequest,\n LoginResponse,\n OTPVerifyRequest,\n OTPVerifyResponse,\n RefreshResponse,\n PermissionCheckRequest,\n PermissionCheckResult,\n PermissionCheckResponse,\n} from './types';\n","export class SinasError extends Error {\n public readonly status: number;\n public readonly detail: string;\n\n constructor(message: string, status: number = 0, detail?: string) {\n super(message);\n this.name = 'SinasError';\n this.status = status;\n this.detail = detail || message;\n }\n}\n\nexport class SinasAuthError extends SinasError {\n constructor(message: string = 'Authentication required') {\n super(message, 401);\n this.name = 'SinasAuthError';\n }\n}\n\nexport class SinasPermissionError extends SinasError {\n constructor(message: string = 'Permission denied') {\n super(message, 403);\n this.name = 'SinasPermissionError';\n }\n}\n\nexport class SinasNotFoundError extends SinasError {\n constructor(resource: string) {\n super(`${resource} not found`, 404);\n this.name = 'SinasNotFoundError';\n }\n}\n\nexport class SinasTimeoutError extends SinasError {\n constructor(message: string = 'Request timed out') {\n super(message, 408);\n this.name = 'SinasTimeoutError';\n }\n}\n","import {\n SinasError,\n SinasAuthError,\n SinasPermissionError,\n SinasNotFoundError,\n} from './errors';\nimport type {\n AuthUser,\n InfoResponse,\n LoginRequest,\n LoginResponse,\n OTPVerifyRequest,\n OTPVerifyResponse,\n PermissionCheckRequest,\n PermissionCheckResponse,\n RefreshResponse,\n} from './types';\n\nfunction trimBase(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, '');\n}\n\nasync function authFetch(\n baseUrl: string,\n path: string,\n init: RequestInit = {},\n accessToken?: string | null,\n): Promise<Response> {\n const headers = new Headers(init.headers);\n if (!headers.has('Content-Type') && init.body !== undefined) {\n headers.set('Content-Type', 'application/json');\n }\n if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`);\n\n const res = await fetch(`${trimBase(baseUrl)}${path}`, { ...init, headers });\n if (res.ok || res.status === 204) return res;\n\n let detail: string = res.statusText;\n try {\n const body = await res.clone().json();\n detail = body.detail || body.message || detail;\n } catch {\n // body wasn't JSON\n }\n if (res.status === 401) throw new SinasAuthError(detail);\n if (res.status === 403) throw new SinasPermissionError(detail);\n if (res.status === 404) throw new SinasNotFoundError(detail);\n throw new SinasError(detail, res.status, detail);\n}\n\n/** Fetch unauthenticated instance info. Use before showing a login screen. */\nexport async function getInfo(baseUrl: string): Promise<InfoResponse> {\n const res = await authFetch(baseUrl, '/info');\n return (await res.json()) as InfoResponse;\n}\n\n/**\n * Start a login. Response shape depends on the workspace's auth_mode:\n * - \"password\": access_token + refresh_token are set → done.\n * - \"otp\" or \"password+otp\": session_id is set → call verifyOTP next.\n */\nexport async function login(\n baseUrl: string,\n request: LoginRequest,\n): Promise<LoginResponse> {\n const res = await authFetch(baseUrl, '/auth/login', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n return (await res.json()) as LoginResponse;\n}\n\n/** Second step for \"otp\" / \"password+otp\" modes. Returns final tokens. */\nexport async function verifyOTP(\n baseUrl: string,\n request: OTPVerifyRequest,\n): Promise<OTPVerifyResponse> {\n const res = await authFetch(baseUrl, '/auth/verify-otp', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n return (await res.json()) as OTPVerifyResponse;\n}\n\n/** Exchange a refresh token for a new access token. */\nexport async function refresh(\n baseUrl: string,\n refreshToken: string,\n): Promise<RefreshResponse> {\n const res = await authFetch(baseUrl, '/auth/refresh', {\n method: 'POST',\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n return (await res.json()) as RefreshResponse;\n}\n\n/** Revoke a refresh token. Best-effort; ignore 404. */\nexport async function logout(\n baseUrl: string,\n refreshToken: string,\n): Promise<void> {\n try {\n await authFetch(baseUrl, '/auth/logout', {\n method: 'POST',\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n } catch (e) {\n if (e instanceof SinasNotFoundError) return;\n throw e;\n }\n}\n\n/** Return the authenticated user (id, email, roles). */\nexport async function getMe(\n baseUrl: string,\n accessToken: string,\n): Promise<AuthUser> {\n const res = await authFetch(baseUrl, '/auth/me', { method: 'GET' }, accessToken);\n return (await res.json()) as AuthUser;\n}\n\n/** Check whether the authenticated user has the given permissions. */\nexport async function checkPermissions(\n baseUrl: string,\n accessToken: string,\n request: PermissionCheckRequest,\n): Promise<PermissionCheckResponse> {\n const res = await authFetch(\n baseUrl,\n '/auth/check-permissions',\n {\n method: 'POST',\n body: JSON.stringify({ logic: 'AND', ...request }),\n },\n accessToken,\n );\n return (await res.json()) as PermissionCheckResponse;\n}\n","import {\n SinasError,\n SinasAuthError,\n SinasPermissionError,\n SinasNotFoundError,\n} from './errors';\nimport * as authApi from './auth';\nimport type {\n SinasConfig,\n InfoResponse,\n LoginRequest,\n LoginResponse,\n OTPVerifyRequest,\n OTPVerifyResponse,\n PermissionCheckRequest,\n PermissionCheckResponse,\n RefreshResponse,\n AuthUser,\n} from './types';\n\ndeclare global {\n interface Window {\n __SINAS_CONFIG__?: SinasConfig;\n __SINAS_AUTH_TOKEN__?: string | null;\n }\n}\n\nexport interface SinasClientOptions {\n /** Embedded-component config. Falls back to window.__SINAS_CONFIG__. */\n config?: SinasConfig;\n /** Workspace base URL for standalone use. Overrides config.apiBase for non-proxy calls. */\n baseUrl?: string;\n /** Returns the current access token, or null. Falls back to window.__SINAS_AUTH_TOKEN__. */\n getAccessToken?: () => string | null;\n /** Returns the current refresh token. Required for auto-refresh on 401. */\n getRefreshToken?: () => string | null;\n /** Called with the new access token after a successful /auth/refresh. */\n onTokenRefresh?: (accessToken: string) => void;\n /** Called when a request remains unauthenticated after a refresh attempt. */\n onUnauthenticated?: () => void;\n}\n\nfunction hasWindow(): boolean {\n return typeof window !== 'undefined';\n}\n\nfunction trim(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n\n/**\n * Auth namespace on SinasClient. Standalone counterparts live in client/auth.ts.\n */\nexport class SinasClientAuth {\n constructor(private readonly client: SinasClient) {}\n\n getInfo(): Promise<InfoResponse> {\n return authApi.getInfo(this.client.requireBaseUrl());\n }\n\n login(request: LoginRequest): Promise<LoginResponse> {\n return authApi.login(this.client.requireBaseUrl(), request);\n }\n\n verifyOTP(request: OTPVerifyRequest): Promise<OTPVerifyResponse> {\n return authApi.verifyOTP(this.client.requireBaseUrl(), request);\n }\n\n refresh(refreshToken: string): Promise<RefreshResponse> {\n return authApi.refresh(this.client.requireBaseUrl(), refreshToken);\n }\n\n logout(refreshToken: string): Promise<void> {\n return authApi.logout(this.client.requireBaseUrl(), refreshToken);\n }\n\n getMe(): Promise<AuthUser> {\n const token = this.client.getAccessToken();\n if (!token) throw new SinasAuthError('No access token available');\n return authApi.getMe(this.client.requireBaseUrl(), token);\n }\n\n checkPermissions(request: PermissionCheckRequest): Promise<PermissionCheckResponse> {\n const token = this.client.getAccessToken();\n if (!token) throw new SinasAuthError('No access token available');\n return authApi.checkPermissions(this.client.requireBaseUrl(), token, request);\n }\n}\n\nexport class SinasClient {\n readonly auth: SinasClientAuth;\n\n private readonly options: SinasClientOptions;\n private refreshInFlight: Promise<string | null> | null = null;\n\n constructor(options: SinasClientOptions = {}) {\n this.options = options;\n this.auth = new SinasClientAuth(this);\n }\n\n // ─── Config / base URL ───\n\n getConfig(): SinasConfig {\n const config =\n this.options.config || (hasWindow() ? window.__SINAS_CONFIG__ : undefined);\n if (!config) {\n return {\n apiBase: this.options.baseUrl ? `${trim(this.options.baseUrl)}/api/v1` : '',\n component: { namespace: '', name: '', version: '' },\n resources: {\n enabledAgents: [],\n enabledFunctions: [],\n enabledQueries: [],\n enabledComponents: [],\n enabledStores: [],\n },\n input: {},\n };\n }\n return config;\n }\n\n getInput(): Record<string, unknown> {\n return this.getConfig().input || {};\n }\n\n /** Workspace base URL (root of the Sinas instance). Throws if unset. */\n requireBaseUrl(): string {\n const url = this.getBaseUrl();\n if (!url) {\n throw new SinasError(\n 'No baseUrl configured. Construct with `new SinasClient({ baseUrl })` for standalone use.',\n 0,\n );\n }\n return url;\n }\n\n getBaseUrl(): string | null {\n if (this.options.baseUrl) return trim(this.options.baseUrl);\n // Embedded mode: derive from config.apiBase by stripping /api/v1\n const apiBase = this.getConfig().apiBase;\n if (!apiBase) return null;\n return trim(apiBase).replace(/\\/api\\/v1$/, '');\n }\n\n // ─── Tokens ───\n\n getAccessToken(): string | null {\n if (this.options.getAccessToken) return this.options.getAccessToken();\n if (hasWindow()) return window.__SINAS_AUTH_TOKEN__ ?? null;\n return null;\n }\n\n private getRefreshToken(): string | null {\n return this.options.getRefreshToken ? this.options.getRefreshToken() : null;\n }\n\n private async tryRefresh(): Promise<string | null> {\n const refreshToken = this.getRefreshToken();\n if (!refreshToken) return null;\n if (this.refreshInFlight) return this.refreshInFlight;\n const baseUrl = this.getBaseUrl();\n if (!baseUrl) return null;\n\n this.refreshInFlight = (async () => {\n try {\n const resp = await authApi.refresh(baseUrl, refreshToken);\n this.options.onTokenRefresh?.(resp.access_token);\n return resp.access_token;\n } catch {\n return null;\n } finally {\n this.refreshInFlight = null;\n }\n })();\n return this.refreshInFlight;\n }\n\n // ─── Headers / proxy ───\n\n getAuthHeaders(): Record<string, string> {\n const token = this.getAccessToken();\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (token) headers['Authorization'] = `Bearer ${token}`;\n return headers;\n }\n\n getProxyBase(): string {\n const config = this.getConfig();\n const comp = config.component;\n return `${config.apiBase}/components/${comp.namespace}/${comp.name}/proxy`;\n }\n\n // ─── Fetch with refresh-on-401 ───\n\n async fetch(url: string, options: RequestInit = {}, _retried = false): Promise<Response> {\n const res = await fetch(url, {\n ...options,\n headers: {\n ...this.getAuthHeaders(),\n ...((options.headers as Record<string, string>) || {}),\n },\n });\n\n if (res.ok || res.status === 204) return res;\n\n if (res.status === 401 && !_retried) {\n const newToken = await this.tryRefresh();\n if (newToken) return this.fetch(url, options, true);\n this.options.onUnauthenticated?.();\n }\n\n const body = await res.json().catch(() => ({ detail: res.statusText }));\n const message = body.detail || body.message || res.statusText;\n\n if (res.status === 401) throw new SinasAuthError(message);\n if (res.status === 403) throw new SinasPermissionError(message);\n if (res.status === 404) throw new SinasNotFoundError(message);\n throw new SinasError(message, res.status);\n }\n}\n","import type { SinasClient } from './SinasClient';\nimport type { QueryResult } from './types';\n\nfunction parseRef(ref: string): [string, string] {\n const parts = ref.split('/');\n if (parts.length !== 2) {\n throw new Error(`Invalid query ref \"${ref}\": expected \"namespace/name\"`);\n }\n return [parts[0], parts[1]];\n}\n\nexport async function executeQuery(\n client: SinasClient,\n ref: string,\n input: Record<string, unknown> = {}\n): Promise<QueryResult> {\n const [ns, name] = parseRef(ref);\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/queries/${ns}/${name}/execute`, {\n method: 'POST',\n body: JSON.stringify({ input }),\n });\n const data = await res.json();\n return {\n success: data.success,\n operation: data.operation,\n data: data.data,\n rowCount: data.row_count,\n affectedRows: data.affected_rows,\n durationMs: data.duration_ms,\n };\n}\n","import type { SinasClient } from './SinasClient';\nimport type { FunctionResult } from './types';\n\nfunction parseRef(ref: string): [string, string] {\n const parts = ref.split('/');\n if (parts.length !== 2) {\n throw new Error(`Invalid function ref \"${ref}\": expected \"namespace/name\"`);\n }\n return [parts[0], parts[1]];\n}\n\nexport async function executeFunction(\n client: SinasClient,\n ref: string,\n input: Record<string, unknown> = {},\n timeout?: number\n): Promise<FunctionResult> {\n const [ns, name] = parseRef(ref);\n const base = client.getProxyBase();\n const body: Record<string, unknown> = { input };\n if (timeout !== undefined) {\n body.timeout = timeout;\n }\n const res = await client.fetch(`${base}/functions/${ns}/${name}/execute`, {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = await res.json();\n return {\n status: data.status,\n executionId: data.execution_id,\n result: data.result,\n error: data.error,\n };\n}\n","import type { SinasClient } from './SinasClient';\nimport type { StateGetResult, StateListResult } from './types';\n\nexport async function stateGet(\n client: SinasClient,\n ns: string,\n key: string\n): Promise<StateGetResult> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'get', key }),\n });\n return res.json();\n}\n\nexport async function stateSet(\n client: SinasClient,\n ns: string,\n key: string,\n value: unknown,\n visibility: 'private' | 'shared' = 'private'\n): Promise<void> {\n const base = client.getProxyBase();\n await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'set', key, value, visibility }),\n });\n}\n\nexport async function stateDelete(\n client: SinasClient,\n ns: string,\n key: string\n): Promise<void> {\n const base = client.getProxyBase();\n await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'delete', key }),\n });\n}\n\nexport async function stateList(\n client: SinasClient,\n ns: string\n): Promise<StateListResult> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'list' }),\n });\n return res.json();\n}\n","import type { SinasClient } from './SinasClient';\nimport type { ChatCreateResult, ChatMessage, ChatDetail, ChatMessageFull, ApprovalRequest, ApprovalResult, SSEChunk, MessageContent } from './types';\n\nexport async function createChat(\n client: SinasClient,\n agentRef: string,\n input?: Record<string, unknown>\n): Promise<ChatCreateResult> {\n const [ns, name] = agentRef.split('/');\n if (!ns || !name) {\n throw new Error(`Invalid agent ref \"${agentRef}\": expected \"namespace/name\"`);\n }\n const config = client.getConfig();\n const res = await client.fetch(`${config.apiBase}/agents/${ns}/${name}/chats`, {\n method: 'POST',\n body: JSON.stringify({ input: input || {} }),\n });\n const data = await res.json();\n return {\n id: data.id,\n agentNamespace: data.agent_namespace,\n agentName: data.agent_name,\n title: data.title,\n };\n}\n\nexport async function sendMessage(\n client: SinasClient,\n chatId: string,\n content: MessageContent\n): Promise<ChatMessage> {\n const config = client.getConfig();\n const res = await client.fetch(`${config.apiBase}/chats/${chatId}/messages`, {\n method: 'POST',\n body: JSON.stringify({ content }),\n });\n const data = await res.json();\n return {\n id: data.id,\n chatId: data.chat_id,\n role: data.role,\n content: data.content,\n createdAt: data.created_at,\n };\n}\n\nfunction mapMessage(data: Record<string, unknown>): ChatMessageFull {\n const toolCalls = data.tool_calls as ChatMessageFull['toolCalls'] | undefined;\n return {\n id: data.id as string,\n chatId: data.chat_id as string,\n role: data.role as ChatMessageFull['role'],\n content: (data.content as string) ?? null,\n toolCalls: toolCalls ?? null,\n toolCallId: (data.tool_call_id as string) ?? null,\n name: (data.name as string) ?? null,\n createdAt: data.created_at as string,\n };\n}\n\nexport async function getChat(\n client: SinasClient,\n chatId: string,\n): Promise<ChatDetail> {\n const config = client.getConfig();\n const res = await client.fetch(`${config.apiBase}/chats/${chatId}`);\n const data = await res.json();\n return {\n id: data.id,\n agentNamespace: data.agent_namespace,\n agentName: data.agent_name,\n title: data.title,\n messages: (data.messages || []).map(mapMessage),\n pendingApprovals: (data.pending_approvals || []).map((pa: Record<string, unknown>): ApprovalRequest => ({\n type: 'approval_required',\n toolCallId: pa.tool_call_id as string,\n functionNamespace: pa.function_namespace as string,\n functionName: pa.function_name as string,\n arguments: (pa.arguments as Record<string, unknown>) || {},\n })),\n };\n}\n\nexport async function approveToolCall(\n client: SinasClient,\n chatId: string,\n toolCallId: string,\n approved: boolean,\n): Promise<ApprovalResult> {\n const config = client.getConfig();\n const res = await client.fetch(\n `${config.apiBase}/chats/${chatId}/approve-tool/${toolCallId}`,\n { method: 'POST', body: JSON.stringify({ approved }) },\n );\n const data = await res.json();\n return {\n status: data.status,\n toolCallId: data.tool_call_id,\n channelId: data.channel_id,\n };\n}\n\nexport function streamFromChannel(\n client: SinasClient,\n chatId: string,\n channelId: string,\n onChunk: (chunk: SSEChunk) => void,\n onDone?: () => void,\n onError?: (error: Error) => void,\n): AbortController {\n const controller = new AbortController();\n const config = client.getConfig();\n\n (async () => {\n try {\n const res = await fetch(\n `${config.apiBase}/chats/${chatId}/stream/${channelId}?last_id=0`,\n { headers: client.getAuthHeaders(), signal: controller.signal },\n );\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ detail: res.statusText }));\n throw new Error(body.detail || 'Stream reconnect failed');\n }\n\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { chunks, remaining } = parseSSE(buffer);\n buffer = remaining;\n\n for (const chunk of chunks) {\n onChunk(chunk);\n if (chunk.event === 'done') {\n onDone?.();\n return;\n }\n }\n }\n\n if (buffer.trim()) {\n const { chunks } = parseSSE(buffer + '\\n\\n');\n for (const chunk of chunks) {\n onChunk(chunk);\n }\n }\n\n onDone?.();\n } catch (err) {\n if ((err as Error).name === 'AbortError') return;\n onError?.(err as Error);\n }\n })();\n\n return controller;\n}\n\nfunction parseSSE(buffer: string): { chunks: SSEChunk[]; remaining: string } {\n const chunks: SSEChunk[] = [];\n // Normalize \\r\\n to \\n (sse_starlette uses \\r\\n line endings)\n const normalized = buffer.replace(/\\r\\n/g, '\\n');\n const lines = normalized.split('\\n');\n let event = '';\n let data = '';\n let remaining = '';\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // If last line and doesn't end with newline, it's incomplete\n if (i === lines.length - 1 && !normalized.endsWith('\\n')) {\n remaining = line;\n break;\n }\n\n if (line.startsWith('event:')) {\n event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n data = line.slice(5).trim();\n } else if (line === '') {\n if (event || data) {\n chunks.push({ event: event || 'message', data });\n event = '';\n data = '';\n }\n }\n }\n\n return { chunks, remaining };\n}\n\nexport function streamMessage(\n client: SinasClient,\n chatId: string,\n content: MessageContent,\n onChunk: (chunk: SSEChunk) => void,\n onDone?: () => void,\n onError?: (error: Error) => void\n): AbortController {\n const controller = new AbortController();\n const config = client.getConfig();\n\n (async () => {\n try {\n const res = await fetch(`${config.apiBase}/chats/${chatId}/messages/stream`, {\n method: 'POST',\n headers: client.getAuthHeaders(),\n body: JSON.stringify({ content }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ detail: res.statusText }));\n throw new Error(body.detail || 'Stream request failed');\n }\n\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { chunks, remaining } = parseSSE(buffer);\n buffer = remaining;\n\n for (const chunk of chunks) {\n onChunk(chunk);\n if (chunk.event === 'done') {\n onDone?.();\n return;\n }\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim()) {\n const { chunks } = parseSSE(buffer + '\\n\\n');\n for (const chunk of chunks) {\n onChunk(chunk);\n }\n }\n\n onDone?.();\n } catch (err) {\n if ((err as Error).name === 'AbortError') return;\n onError?.(err as Error);\n }\n })();\n\n return controller;\n}\n","import type { SinasClient } from './SinasClient';\nimport type { Collection, FileInfo, FileUploadRequest, FileUrlResult } from './types';\n\nexport async function listCollections(client: SinasClient): Promise<Collection[]> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/collections`);\n return res.json();\n}\n\nexport async function listFiles(\n client: SinasClient,\n namespace: string,\n collection: string\n): Promise<FileInfo[]> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/files/${namespace}/${collection}`);\n return res.json();\n}\n\nexport async function uploadFile(\n client: SinasClient,\n namespace: string,\n collection: string,\n data: FileUploadRequest,\n): Promise<FileInfo> {\n const apiBase = client.getConfig().apiBase;\n const res = await client.fetch(`${apiBase}/files/${namespace}/${collection}`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n return res.json();\n}\n\nexport async function generateFileUrl(\n client: SinasClient,\n namespace: string,\n collection: string,\n filename: string,\n expiresIn?: number,\n): Promise<FileUrlResult> {\n const apiBase = client.getConfig().apiBase;\n const params = new URLSearchParams();\n if (expiresIn) params.set('expires_in', String(expiresIn));\n const qs = params.toString() ? `?${params.toString()}` : '';\n const res = await client.fetch(\n `${apiBase}/files/${namespace}/${collection}/${encodeURIComponent(filename)}/url${qs}`,\n { method: 'POST' },\n );\n return res.json();\n}\n"],"mappings":"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","names":["parseRef"]}
1
+ {"version":3,"sources":["../src/client/index.ts","../src/client/errors.ts","../src/client/auth.ts","../src/client/SinasClient.ts","../src/client/queries.ts","../src/client/functions.ts","../src/client/states.ts","../src/client/chatEvents.ts","../src/client/chat.ts","../src/client/collections.ts"],"sourcesContent":["export { SinasClient, SinasClientAuth, type SinasClientOptions } from './SinasClient';\nexport { executeQuery } from './queries';\nexport {\n executeFunction,\n enqueueFunction,\n submitFunctionBatch,\n submitAgentBatch,\n getBatch,\n listBatchExecutions,\n cancelBatch,\n} from './functions';\nexport type {\n EnqueueFunctionOptions,\n EnqueueFunctionResult,\n SubmitFunctionBatchOptions,\n SubmitFunctionBatchResult,\n AgentBatchItem,\n SubmitAgentBatchOptions,\n SubmitAgentBatchResult,\n BatchStatus,\n BatchExecutionItem,\n} from './functions';\nexport { stateGet, stateSet, stateDelete, stateList } from './states';\nexport {\n createChat,\n sendMessage,\n streamMessage,\n getChat,\n approveToolCall,\n streamFromChannel,\n invokeAgent,\n listPendingInputs,\n answerPendingInput,\n} from './chat';\nexport {\n parsePendingInput,\n parsePendingInputs,\n pendingInputFromChunk,\n approvalResumeChannel,\n answerResumeChannel,\n} from './chatEvents';\nexport { listCollections, listFiles, uploadFile, generateFileUrl } from './collections';\nexport {\n getInfo,\n login,\n verifyOTP,\n refresh,\n logout,\n getMe,\n checkPermissions,\n} from './auth';\nexport {\n SinasError,\n SinasAuthError,\n SinasPermissionError,\n SinasNotFoundError,\n SinasTimeoutError,\n} from './errors';\nexport type {\n SinasConfig,\n QueryResult,\n FunctionResult,\n StateGetResult,\n StateListResult,\n ChatCreateResult,\n ChatMessage,\n ChatMessageFull,\n ToolCallInfo,\n ChatDetail,\n ApprovalRequest,\n ApprovalResult,\n ApprovalResume,\n ApproveToolCallOptions,\n PendingInput,\n TurnStatus,\n TurnUsage,\n TurnState,\n MessageSendResult,\n InvokeOptions,\n InvokeResult,\n AnswerPendingInputOptions,\n PendingInputAnswerAccepted,\n PendingInputAnswerResult,\n StreamOptions,\n StreamFromChannelOptions,\n StreamDone,\n InputRequiredEvent,\n RoundSuspendedEvent,\n ContentPart,\n TextContentPart,\n ImageContentPart,\n AudioContentPart,\n FileContentPart,\n ComponentContentPart,\n MessageContent,\n SSEChunk,\n Collection,\n FileInfo,\n FileUploadRequest,\n FileUrlResult,\n AuthMode,\n AuthUser,\n InfoResponse,\n LoginRequest,\n LoginResponse,\n OTPVerifyRequest,\n OTPVerifyResponse,\n RefreshResponse,\n PermissionCheckRequest,\n PermissionCheckResult,\n PermissionCheckResponse,\n} from './types';\n","export class SinasError extends Error {\n public readonly status: number;\n public readonly detail: string;\n\n constructor(message: string, status: number = 0, detail?: string) {\n super(message);\n this.name = 'SinasError';\n this.status = status;\n this.detail = detail || message;\n }\n}\n\nexport class SinasAuthError extends SinasError {\n constructor(message: string = 'Authentication required') {\n super(message, 401);\n this.name = 'SinasAuthError';\n }\n}\n\nexport class SinasPermissionError extends SinasError {\n constructor(message: string = 'Permission denied') {\n super(message, 403);\n this.name = 'SinasPermissionError';\n }\n}\n\nexport class SinasNotFoundError extends SinasError {\n constructor(resource: string) {\n super(`${resource} not found`, 404);\n this.name = 'SinasNotFoundError';\n }\n}\n\nexport class SinasTimeoutError extends SinasError {\n constructor(message: string = 'Request timed out') {\n super(message, 408);\n this.name = 'SinasTimeoutError';\n }\n}\n","import {\n SinasError,\n SinasAuthError,\n SinasPermissionError,\n SinasNotFoundError,\n} from './errors';\nimport type {\n AuthUser,\n InfoResponse,\n LoginRequest,\n LoginResponse,\n OTPVerifyRequest,\n OTPVerifyResponse,\n PermissionCheckRequest,\n PermissionCheckResponse,\n RefreshResponse,\n} from './types';\n\nfunction trimBase(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, '');\n}\n\nasync function authFetch(\n baseUrl: string,\n path: string,\n init: RequestInit = {},\n accessToken?: string | null,\n): Promise<Response> {\n const headers = new Headers(init.headers);\n if (!headers.has('Content-Type') && init.body !== undefined) {\n headers.set('Content-Type', 'application/json');\n }\n if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`);\n\n const res = await fetch(`${trimBase(baseUrl)}${path}`, { ...init, headers });\n if (res.ok || res.status === 204) return res;\n\n let detail: string = res.statusText;\n try {\n const body = await res.clone().json();\n detail = body.detail || body.message || detail;\n } catch {\n // body wasn't JSON\n }\n if (res.status === 401) throw new SinasAuthError(detail);\n if (res.status === 403) throw new SinasPermissionError(detail);\n if (res.status === 404) throw new SinasNotFoundError(detail);\n throw new SinasError(detail, res.status, detail);\n}\n\n/** Fetch unauthenticated instance info. Use before showing a login screen. */\nexport async function getInfo(baseUrl: string): Promise<InfoResponse> {\n const res = await authFetch(baseUrl, '/info');\n return (await res.json()) as InfoResponse;\n}\n\n/**\n * Start a login. Response shape depends on the workspace's auth_mode:\n * - \"password\": access_token + refresh_token are set → done.\n * - \"otp\" or \"password+otp\": session_id is set → call verifyOTP next.\n */\nexport async function login(\n baseUrl: string,\n request: LoginRequest,\n): Promise<LoginResponse> {\n const res = await authFetch(baseUrl, '/auth/login', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n return (await res.json()) as LoginResponse;\n}\n\n/** Second step for \"otp\" / \"password+otp\" modes. Returns final tokens. */\nexport async function verifyOTP(\n baseUrl: string,\n request: OTPVerifyRequest,\n): Promise<OTPVerifyResponse> {\n const res = await authFetch(baseUrl, '/auth/verify-otp', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n return (await res.json()) as OTPVerifyResponse;\n}\n\n/** Exchange a refresh token for a new access token. */\nexport async function refresh(\n baseUrl: string,\n refreshToken: string,\n): Promise<RefreshResponse> {\n const res = await authFetch(baseUrl, '/auth/refresh', {\n method: 'POST',\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n return (await res.json()) as RefreshResponse;\n}\n\n/** Revoke a refresh token. Best-effort; ignore 404. */\nexport async function logout(\n baseUrl: string,\n refreshToken: string,\n): Promise<void> {\n try {\n await authFetch(baseUrl, '/auth/logout', {\n method: 'POST',\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n } catch (e) {\n if (e instanceof SinasNotFoundError) return;\n throw e;\n }\n}\n\n/** Return the authenticated user (id, email, roles). */\nexport async function getMe(\n baseUrl: string,\n accessToken: string,\n): Promise<AuthUser> {\n const res = await authFetch(baseUrl, '/auth/me', { method: 'GET' }, accessToken);\n return (await res.json()) as AuthUser;\n}\n\n/** Check whether the authenticated user has the given permissions. */\nexport async function checkPermissions(\n baseUrl: string,\n accessToken: string,\n request: PermissionCheckRequest,\n): Promise<PermissionCheckResponse> {\n const res = await authFetch(\n baseUrl,\n '/auth/check-permissions',\n {\n method: 'POST',\n body: JSON.stringify({ logic: 'AND', ...request }),\n },\n accessToken,\n );\n return (await res.json()) as PermissionCheckResponse;\n}\n","import {\n SinasError,\n SinasAuthError,\n SinasPermissionError,\n SinasNotFoundError,\n} from './errors';\nimport * as authApi from './auth';\nimport type {\n SinasConfig,\n InfoResponse,\n LoginRequest,\n LoginResponse,\n OTPVerifyRequest,\n OTPVerifyResponse,\n PermissionCheckRequest,\n PermissionCheckResponse,\n RefreshResponse,\n AuthUser,\n} from './types';\n\ndeclare global {\n interface Window {\n __SINAS_CONFIG__?: SinasConfig;\n __SINAS_AUTH_TOKEN__?: string | null;\n }\n}\n\nexport interface SinasClientOptions {\n /** Embedded-component config. Falls back to window.__SINAS_CONFIG__. */\n config?: SinasConfig;\n /** Workspace base URL for standalone use. Overrides config.apiBase for non-proxy calls. */\n baseUrl?: string;\n /** Returns the current access token, or null. Falls back to window.__SINAS_AUTH_TOKEN__. */\n getAccessToken?: () => string | null;\n /** Returns the current refresh token. Required for auto-refresh on 401. */\n getRefreshToken?: () => string | null;\n /** Called with the new access token after a successful /auth/refresh. */\n onTokenRefresh?: (accessToken: string) => void;\n /** Called when a request remains unauthenticated after a refresh attempt. */\n onUnauthenticated?: () => void;\n}\n\nfunction hasWindow(): boolean {\n return typeof window !== 'undefined';\n}\n\nfunction trim(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n\n/**\n * Auth namespace on SinasClient. Standalone counterparts live in client/auth.ts.\n */\nexport class SinasClientAuth {\n constructor(private readonly client: SinasClient) {}\n\n getInfo(): Promise<InfoResponse> {\n return authApi.getInfo(this.client.requireBaseUrl());\n }\n\n login(request: LoginRequest): Promise<LoginResponse> {\n return authApi.login(this.client.requireBaseUrl(), request);\n }\n\n verifyOTP(request: OTPVerifyRequest): Promise<OTPVerifyResponse> {\n return authApi.verifyOTP(this.client.requireBaseUrl(), request);\n }\n\n refresh(refreshToken: string): Promise<RefreshResponse> {\n return authApi.refresh(this.client.requireBaseUrl(), refreshToken);\n }\n\n logout(refreshToken: string): Promise<void> {\n return authApi.logout(this.client.requireBaseUrl(), refreshToken);\n }\n\n getMe(): Promise<AuthUser> {\n const token = this.client.getAccessToken();\n if (!token) throw new SinasAuthError('No access token available');\n return authApi.getMe(this.client.requireBaseUrl(), token);\n }\n\n checkPermissions(request: PermissionCheckRequest): Promise<PermissionCheckResponse> {\n const token = this.client.getAccessToken();\n if (!token) throw new SinasAuthError('No access token available');\n return authApi.checkPermissions(this.client.requireBaseUrl(), token, request);\n }\n}\n\nexport class SinasClient {\n readonly auth: SinasClientAuth;\n\n private readonly options: SinasClientOptions;\n private refreshInFlight: Promise<string | null> | null = null;\n\n constructor(options: SinasClientOptions = {}) {\n this.options = options;\n this.auth = new SinasClientAuth(this);\n }\n\n // ─── Config / base URL ───\n\n getConfig(): SinasConfig {\n const config =\n this.options.config || (hasWindow() ? window.__SINAS_CONFIG__ : undefined);\n if (!config) {\n return {\n apiBase: this.options.baseUrl ? `${trim(this.options.baseUrl)}/api/v1` : '',\n component: { namespace: '', name: '', version: '' },\n resources: {\n enabledAgents: [],\n enabledFunctions: [],\n enabledQueries: [],\n enabledComponents: [],\n enabledStores: [],\n },\n input: {},\n };\n }\n return config;\n }\n\n getInput(): Record<string, unknown> {\n return this.getConfig().input || {};\n }\n\n /** Workspace base URL (root of the Sinas instance). Throws if unset. */\n requireBaseUrl(): string {\n const url = this.getBaseUrl();\n if (!url) {\n throw new SinasError(\n 'No baseUrl configured. Construct with `new SinasClient({ baseUrl })` for standalone use.',\n 0,\n );\n }\n return url;\n }\n\n getBaseUrl(): string | null {\n if (this.options.baseUrl) return trim(this.options.baseUrl);\n // Embedded mode: derive from config.apiBase by stripping /api/v1\n const apiBase = this.getConfig().apiBase;\n if (!apiBase) return null;\n return trim(apiBase).replace(/\\/api\\/v1$/, '');\n }\n\n // ─── Tokens ───\n\n getAccessToken(): string | null {\n if (this.options.getAccessToken) return this.options.getAccessToken();\n if (hasWindow()) return window.__SINAS_AUTH_TOKEN__ ?? null;\n return null;\n }\n\n private getRefreshToken(): string | null {\n return this.options.getRefreshToken ? this.options.getRefreshToken() : null;\n }\n\n private async tryRefresh(): Promise<string | null> {\n const refreshToken = this.getRefreshToken();\n if (!refreshToken) return null;\n if (this.refreshInFlight) return this.refreshInFlight;\n const baseUrl = this.getBaseUrl();\n if (!baseUrl) return null;\n\n this.refreshInFlight = (async () => {\n try {\n const resp = await authApi.refresh(baseUrl, refreshToken);\n this.options.onTokenRefresh?.(resp.access_token);\n return resp.access_token;\n } catch {\n return null;\n } finally {\n this.refreshInFlight = null;\n }\n })();\n return this.refreshInFlight;\n }\n\n // ─── Headers / proxy ───\n\n getAuthHeaders(): Record<string, string> {\n const token = this.getAccessToken();\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (token) headers['Authorization'] = `Bearer ${token}`;\n return headers;\n }\n\n getProxyBase(): string {\n const config = this.getConfig();\n const comp = config.component;\n return `${config.apiBase}/components/${comp.namespace}/${comp.name}/proxy`;\n }\n\n // ─── Fetch with refresh-on-401 ───\n\n async fetch(url: string, options: RequestInit = {}, _retried = false): Promise<Response> {\n const res = await fetch(url, {\n ...options,\n headers: {\n ...this.getAuthHeaders(),\n ...((options.headers as Record<string, string>) || {}),\n },\n });\n\n if (res.ok || res.status === 204) return res;\n\n if (res.status === 401 && !_retried) {\n const newToken = await this.tryRefresh();\n if (newToken) return this.fetch(url, options, true);\n this.options.onUnauthenticated?.();\n }\n\n const body = await res.json().catch(() => ({ detail: res.statusText }));\n const message = body.detail || body.message || res.statusText;\n\n if (res.status === 401) throw new SinasAuthError(message);\n if (res.status === 403) throw new SinasPermissionError(message);\n if (res.status === 404) throw new SinasNotFoundError(message);\n throw new SinasError(message, res.status);\n }\n}\n","import type { SinasClient } from './SinasClient';\nimport type { QueryResult } from './types';\n\nfunction parseRef(ref: string): [string, string] {\n const parts = ref.split('/');\n if (parts.length !== 2) {\n throw new Error(`Invalid query ref \"${ref}\": expected \"namespace/name\"`);\n }\n return [parts[0], parts[1]];\n}\n\nexport async function executeQuery(\n client: SinasClient,\n ref: string,\n input: Record<string, unknown> = {}\n): Promise<QueryResult> {\n const [ns, name] = parseRef(ref);\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/queries/${ns}/${name}/execute`, {\n method: 'POST',\n body: JSON.stringify({ input }),\n });\n const data = await res.json();\n return {\n success: data.success,\n operation: data.operation,\n data: data.data,\n rowCount: data.row_count,\n affectedRows: data.affected_rows,\n durationMs: data.duration_ms,\n };\n}\n","import type { SinasClient } from './SinasClient';\nimport type { FunctionResult } from './types';\n\nfunction parseRef(ref: string): [string, string] {\n const parts = ref.split('/');\n if (parts.length !== 2) {\n throw new Error(`Invalid function ref \"${ref}\": expected \"namespace/name\"`);\n }\n return [parts[0], parts[1]];\n}\n\nexport async function executeFunction(\n client: SinasClient,\n ref: string,\n input: Record<string, unknown> = {},\n timeout?: number\n): Promise<FunctionResult> {\n const [ns, name] = parseRef(ref);\n const base = client.getProxyBase();\n const body: Record<string, unknown> = { input };\n if (timeout !== undefined) {\n body.timeout = timeout;\n }\n const res = await client.fetch(`${base}/functions/${ns}/${name}/execute`, {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = await res.json();\n return {\n status: data.status,\n executionId: data.execution_id,\n result: data.result,\n error: data.error,\n };\n}\n\nexport interface EnqueueFunctionOptions {\n /** App-supplied correlation id stored on the execution record. */\n triggerId?: string;\n /** Delay before the worker picks up the job, in seconds. */\n delaySeconds?: number;\n /**\n * HTTPS URL Sinas will POST to once the execution terminates.\n * Must match the instance's CALLBACK_URL_HOSTS allowlist.\n */\n callbackUrl?: string;\n}\n\nexport interface EnqueueFunctionResult {\n executionId: string;\n status: string;\n}\n\n/**\n * Fire-and-forget function enqueue. Returns immediately with the\n * execution_id. Poll `executions.get(id)` or rely on the callback URL\n * if one was provided.\n *\n * Standalone-mode only — uses the SinasClient's baseUrl (set in the\n * constructor). Embedded components should use `executeFunction` instead.\n */\nexport async function enqueueFunction(\n client: SinasClient,\n ref: string,\n input: Record<string, unknown> = {},\n options: EnqueueFunctionOptions = {},\n): Promise<EnqueueFunctionResult> {\n const [ns, name] = parseRef(ref);\n const baseUrl = client.requireBaseUrl();\n const body: Record<string, unknown> = { input };\n if (options.triggerId !== undefined) body.trigger_id = options.triggerId;\n if (options.delaySeconds !== undefined) body.delay_seconds = options.delaySeconds;\n if (options.callbackUrl !== undefined) body.callback_url = options.callbackUrl;\n\n const res = await client.fetch(`${baseUrl}/functions/${ns}/${name}/execute/async`, {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = await res.json();\n return {\n executionId: data.execution_id,\n status: data.status,\n };\n}\n\nexport interface SubmitFunctionBatchOptions {\n triggerIdPrefix?: string;\n delaySeconds?: number;\n /** Fires once per execution. */\n callbackUrl?: string;\n /** Fires once when the entire batch terminates. */\n batchCallbackUrl?: string;\n}\n\nexport interface SubmitFunctionBatchResult {\n batchId: string;\n executionIds: string[];\n total: number;\n status: string;\n}\n\n/** Submit N function executions as a single batch. */\nexport async function submitFunctionBatch(\n client: SinasClient,\n ref: string,\n inputs: Record<string, unknown>[],\n options: SubmitFunctionBatchOptions = {},\n): Promise<SubmitFunctionBatchResult> {\n const [ns, name] = parseRef(ref);\n const baseUrl = client.requireBaseUrl();\n const body: Record<string, unknown> = { inputs };\n if (options.triggerIdPrefix !== undefined) body.trigger_id_prefix = options.triggerIdPrefix;\n if (options.delaySeconds !== undefined) body.delay_seconds = options.delaySeconds;\n if (options.callbackUrl !== undefined) body.callback_url = options.callbackUrl;\n if (options.batchCallbackUrl !== undefined) body.batch_callback_url = options.batchCallbackUrl;\n\n const res = await client.fetch(`${baseUrl}/functions/${ns}/${name}/execute/batch`, {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = await res.json();\n return {\n batchId: data.batch_id,\n executionIds: data.execution_ids,\n total: data.total,\n status: data.status,\n };\n}\n\nexport interface AgentBatchItem {\n inputVariables?: Record<string, unknown>;\n message: string;\n}\n\nexport interface SubmitAgentBatchOptions {\n triggerIdPrefix?: string;\n callbackUrl?: string;\n batchCallbackUrl?: string;\n}\n\nexport interface SubmitAgentBatchResult {\n batchId: string;\n executionIds: string[];\n chatIds: string[];\n total: number;\n status: string;\n}\n\n/** Submit N agent invocations as a single batch. */\nexport async function submitAgentBatch(\n client: SinasClient,\n ref: string,\n inputs: AgentBatchItem[],\n options: SubmitAgentBatchOptions = {},\n): Promise<SubmitAgentBatchResult> {\n const [ns, name] = parseRef(ref);\n const baseUrl = client.requireBaseUrl();\n const body: Record<string, unknown> = {\n inputs: inputs.map((item) => ({\n input_variables: item.inputVariables || {},\n message: item.message,\n })),\n };\n if (options.triggerIdPrefix !== undefined) body.trigger_id_prefix = options.triggerIdPrefix;\n if (options.callbackUrl !== undefined) body.callback_url = options.callbackUrl;\n if (options.batchCallbackUrl !== undefined) body.batch_callback_url = options.batchCallbackUrl;\n\n const res = await client.fetch(`${baseUrl}/agents/${ns}/${name}/chats/batch`, {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = await res.json();\n return {\n batchId: data.batch_id,\n executionIds: data.execution_ids,\n chatIds: data.chat_ids,\n total: data.total,\n status: data.status,\n };\n}\n\nexport interface BatchStatus {\n batchId: string;\n kind: string;\n target: { namespace: string; name: string };\n userId: string;\n total: number;\n completed: number;\n failed: number;\n cancelled: number;\n running: number;\n queued: number;\n status: string;\n startedAt: string | null;\n finishedAt: string | null;\n triggerIdPrefix: string | null;\n}\n\n/** Get aggregate progress for a batch. */\nexport async function getBatch(\n client: SinasClient,\n batchId: string,\n): Promise<BatchStatus> {\n const baseUrl = client.requireBaseUrl();\n const res = await client.fetch(`${baseUrl}/batches/${batchId}`);\n const data = await res.json();\n return {\n batchId: data.batch_id,\n kind: data.kind,\n target: data.target,\n userId: data.user_id,\n total: data.total,\n completed: data.completed,\n failed: data.failed,\n cancelled: data.cancelled,\n running: data.running,\n queued: data.queued,\n status: data.status,\n startedAt: data.started_at,\n finishedAt: data.finished_at,\n triggerIdPrefix: data.trigger_id_prefix,\n };\n}\n\nexport interface BatchExecutionItem {\n executionId: string;\n status: string;\n functionName: string;\n chatId: string | null;\n triggerId: string;\n startedAt: string | null;\n completedAt: string | null;\n durationMs: number | null;\n error: string | null;\n}\n\n/** List child executions of a batch, optionally filtered by status. */\nexport async function listBatchExecutions(\n client: SinasClient,\n batchId: string,\n options: { status?: string; limit?: number; offset?: number } = {},\n): Promise<BatchExecutionItem[]> {\n const baseUrl = client.requireBaseUrl();\n const params = new URLSearchParams();\n if (options.status) params.set('status', options.status);\n if (options.limit !== undefined) params.set('limit', String(options.limit));\n if (options.offset !== undefined) params.set('offset', String(options.offset));\n const q = params.toString();\n const res = await client.fetch(\n `${baseUrl}/batches/${batchId}/executions${q ? '?' + q : ''}`,\n );\n const data = await res.json();\n return (data.executions || []).map((row: Record<string, unknown>) => ({\n executionId: row.execution_id as string,\n status: row.status as string,\n functionName: row.function_name as string,\n chatId: (row.chat_id as string | null) ?? null,\n triggerId: row.trigger_id as string,\n startedAt: (row.started_at as string | null) ?? null,\n completedAt: (row.completed_at as string | null) ?? null,\n durationMs: (row.duration_ms as number | null) ?? null,\n error: (row.error as string | null) ?? null,\n }));\n}\n\n/** Cancel any queued/pending children of a batch. */\nexport async function cancelBatch(\n client: SinasClient,\n batchId: string,\n): Promise<{ batchId: string; status: string; cancelledChildren: number }> {\n const baseUrl = client.requireBaseUrl();\n const res = await client.fetch(`${baseUrl}/batches/${batchId}/cancel`, {\n method: 'POST',\n });\n const data = await res.json();\n return {\n batchId: data.batch_id,\n status: data.status,\n cancelledChildren: data.cancelled_children,\n };\n}\n","import type { SinasClient } from './SinasClient';\nimport type { StateGetResult, StateListResult } from './types';\n\nexport async function stateGet(\n client: SinasClient,\n ns: string,\n key: string\n): Promise<StateGetResult> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'get', key }),\n });\n return res.json();\n}\n\nexport async function stateSet(\n client: SinasClient,\n ns: string,\n key: string,\n value: unknown,\n visibility: 'private' | 'shared' = 'private'\n): Promise<void> {\n const base = client.getProxyBase();\n await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'set', key, value, visibility }),\n });\n}\n\nexport async function stateDelete(\n client: SinasClient,\n ns: string,\n key: string\n): Promise<void> {\n const base = client.getProxyBase();\n await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'delete', key }),\n });\n}\n\nexport async function stateList(\n client: SinasClient,\n ns: string\n): Promise<StateListResult> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/states/${ns}`, {\n method: 'POST',\n body: JSON.stringify({ action: 'list' }),\n });\n return res.json();\n}\n","// Pure parsers for chat API payloads and stream events (no I/O), shared by\n// the client functions in chat.ts and the useChat hook.\nimport type {\n ApprovalRequest,\n ChatMessageFull,\n PendingInput,\n SSEChunk,\n StreamDone,\n TurnState,\n TurnStatus,\n TurnUsage,\n} from './types';\n\ntype Raw = Record<string, unknown>;\n\nconst isObject = (v: unknown): v is Raw => !!v && typeof v === 'object' && !Array.isArray(v);\nconst str = (v: unknown): string | null => (typeof v === 'string' ? v : null);\nconst num = (v: unknown): number => (typeof v === 'number' && Number.isFinite(v) ? v : 0);\n\nconst optionsOf = (v: unknown): string[] | null =>\n Array.isArray(v) && v.length > 0 && v.every((o) => typeof o === 'string') ? (v as string[]) : null;\n\n/**\n * One ask_user question from the API (`GET /chats/{id}/pending-input`, the\n * chat detail, a turn result, or an `input_required` stream event), or null\n * when the value isn't one.\n */\nexport function parsePendingInput(raw: unknown): PendingInput | null {\n if (!isObject(raw)) return null;\n if (typeof raw.tool_call_id !== 'string' || !raw.tool_call_id) return null;\n return {\n toolCallId: raw.tool_call_id,\n question: str(raw.question) ?? '',\n options: optionsOf(raw.options),\n expiresAt: str(raw.expires_at),\n createdAt: str(raw.created_at),\n };\n}\n\nexport function parsePendingInputs(raw: unknown): PendingInput[] {\n return Array.isArray(raw) ? raw.map(parsePendingInput).filter((p): p is PendingInput => p !== null) : [];\n}\n\n/**\n * The question an SSE chunk announces, or null. Streams send it as its own\n * `input_required` event; some earlier backends sent an inline turn's as a\n * `message` event whose data has `type: \"input_required\"`. Both are handled.\n */\nexport function pendingInputFromChunk(chunk: SSEChunk): PendingInput | null {\n if (chunk.event !== 'input_required' && chunk.event !== 'message') return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(chunk.data);\n } catch {\n return null;\n }\n if (chunk.event === 'message' && (!isObject(parsed) || parsed.type !== 'input_required')) return null;\n return parsePendingInput(parsed);\n}\n\n/** An approval as the API reports it (stream event or chat detail), or null when malformed. */\nexport function parseApproval(raw: unknown): ApprovalRequest | null {\n if (!isObject(raw) || typeof raw.tool_call_id !== 'string') return null;\n return {\n type: str(raw.type) ?? 'approval_required',\n toolCallId: raw.tool_call_id,\n functionNamespace: str(raw.function_namespace) ?? '',\n functionName: str(raw.function_name) ?? '',\n arguments: isObject(raw.arguments) ? raw.arguments : {},\n };\n}\n\nexport function parseUsage(raw: unknown): TurnUsage | null {\n if (!isObject(raw)) return null;\n return {\n calls: num(raw.calls),\n promptTokens: num(raw.prompt_tokens),\n completionTokens: num(raw.completion_tokens),\n totalTokens: num(raw.total_tokens),\n cacheReadTokens: num(raw.cache_read_tokens),\n cacheWriteTokens: num(raw.cache_write_tokens),\n costUsd: typeof raw.cost_usd === 'number' ? raw.cost_usd : null,\n unpricedCalls: num(raw.unpriced_calls),\n errors: num(raw.errors),\n };\n}\n\nconst TURN_STATUSES: readonly TurnStatus[] = ['completed', 'input_required', 'in_progress', 'injected'];\n\n/** The turn-state fields of a send / invoke / answer response; servers before 0.5 omit them. */\nexport function parseTurnState(raw: Raw): TurnState {\n const status = TURN_STATUSES.includes(raw.status as TurnStatus) ? (raw.status as TurnStatus) : 'completed';\n return {\n status,\n pendingInputs: parsePendingInputs(raw.pending_inputs),\n channelId: str(raw.channel_id),\n usage: parseUsage(raw.usage),\n };\n}\n\nexport function parseMessage(data: Raw): ChatMessageFull {\n const toolCalls = data.tool_calls as ChatMessageFull['toolCalls'] | undefined;\n return {\n id: data.id as string,\n chatId: data.chat_id as string,\n role: data.role as ChatMessageFull['role'],\n content: (data.content as string) ?? null,\n toolCalls: toolCalls ?? null,\n toolCallId: (data.tool_call_id as string) ?? null,\n name: (data.name as string) ?? null,\n createdAt: data.created_at as string,\n };\n}\n\n/** How a `done` event ended the stream. */\nexport function parseDone(data: string): StreamDone {\n try {\n const parsed = JSON.parse(data);\n if (isObject(parsed) && typeof parsed.status === 'string') return { status: parsed.status };\n } catch {\n // fall through\n }\n return { status: 'completed' };\n}\n\n/**\n * The channel to follow after an approval decision, or null when there is\n * nothing to stream yet. A round with several asked calls resumes once,\n * after its last decision; until then the response says `resume: \"waiting\"`.\n * On servers before 0.5 (no `resume` field) only an approval resumed.\n */\nexport function approvalResumeChannel(\n result: { resume?: string | null; channelId?: string | null },\n approved = true,\n): string | null {\n if (result.resume === 'waiting') return null;\n if (result.resume === undefined && !approved) return null;\n return result.channelId || null;\n}\n\n/**\n * The channel to follow after answering a question (202 response), or null.\n * The answer resumes the conversation only when it was the round's last\n * outstanding completion (`resumed`) or that resume is being retried\n * (`resumePending`).\n */\nexport function answerResumeChannel(result: {\n resumed?: boolean;\n resumePending?: boolean;\n channelId?: string | null;\n}): string | null {\n if (!result.resumed && !result.resumePending) return null;\n return result.channelId || null;\n}\n","import type { SinasClient } from './SinasClient';\nimport type {\n AnswerPendingInputOptions,\n ApprovalRequest,\n ApprovalResult,\n ApprovalResume,\n ApproveToolCallOptions,\n ChatCreateResult,\n ChatDetail,\n InvokeOptions,\n InvokeResult,\n MessageContent,\n MessageSendResult,\n PendingInput,\n PendingInputAnswerAccepted,\n PendingInputAnswerResult,\n SSEChunk,\n StreamDone,\n StreamFromChannelOptions,\n StreamOptions,\n} from './types';\nimport {\n parseApproval,\n parseDone,\n parseMessage,\n parsePendingInputs,\n parseTurnState,\n} from './chatEvents';\n\nfunction splitAgentRef(agentRef: string): [string, string] {\n const [ns, name] = agentRef.split('/');\n if (!ns || !name) {\n throw new Error(`Invalid agent ref \"${agentRef}\": expected \"namespace/name\"`);\n }\n return [ns, name];\n}\n\nexport async function createChat(\n client: SinasClient,\n agentRef: string,\n input?: Record<string, unknown>\n): Promise<ChatCreateResult> {\n const [ns, name] = splitAgentRef(agentRef);\n const config = client.getConfig();\n const res = await client.fetch(`${config.apiBase}/agents/${ns}/${name}/chats`, {\n method: 'POST',\n body: JSON.stringify({ input: input || {} }),\n });\n const data = await res.json();\n return {\n id: data.id,\n agentNamespace: data.agent_namespace,\n agentName: data.agent_name,\n title: data.title,\n };\n}\n\n/**\n * Send a message and wait for the turn (non-streaming). On Sinas 0.5+ the\n * result says how the turn ended (`status`): with `input_required`, answer\n * the questions in `pendingInputs` with `answerPendingInput`.\n */\nexport async function sendMessage(\n client: SinasClient,\n chatId: string,\n content: MessageContent\n): Promise<MessageSendResult> {\n const config = client.getConfig();\n const res = await client.fetch(`${config.apiBase}/chats/${chatId}/messages`, {\n method: 'POST',\n body: JSON.stringify({ content }),\n });\n const data = await res.json();\n return {\n id: data.id,\n chatId: data.chat_id,\n role: data.role,\n content: data.content,\n createdAt: data.created_at,\n ...parseTurnState(data),\n };\n}\n\n/**\n * Synchronous agent invoke: send a message, get the reply. Creates the chat\n * (or reuses the one for `sessionKey`). Check `status`: with\n * `input_required`, answer `pendingInputs` via `answerPendingInput`\n * (`{ wait: true }` returns the resumed turn's result the same way).\n */\nexport async function invokeAgent(\n client: SinasClient,\n agentRef: string,\n message: MessageContent,\n options: InvokeOptions = {},\n): Promise<InvokeResult> {\n const [ns, name] = splitAgentRef(agentRef);\n const config = client.getConfig();\n const body: Record<string, unknown> = { message };\n if (options.sessionKey !== undefined) body.session_key = options.sessionKey;\n if (options.reset !== undefined) body.reset = options.reset;\n if (options.input !== undefined) body.input = options.input;\n const res = await client.fetch(`${config.apiBase}/agents/${ns}/${name}/invoke`, {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = await res.json();\n return {\n reply: typeof data.reply === 'string' ? data.reply : '',\n chatId: data.chat_id,\n sessionKey: data.session_key ?? null,\n ...parseTurnState(data),\n };\n}\n\nexport async function getChat(\n client: SinasClient,\n chatId: string,\n): Promise<ChatDetail> {\n const config = client.getConfig();\n const res = await client.fetch(`${config.apiBase}/chats/${chatId}`);\n const data = await res.json();\n const detail: ChatDetail = {\n id: data.id,\n agentNamespace: data.agent_namespace,\n agentName: data.agent_name,\n title: data.title,\n messages: (data.messages || []).map(parseMessage),\n pendingApprovals: (data.pending_approvals || [])\n .map(parseApproval)\n .filter((a: ApprovalRequest | null): a is ApprovalRequest => a !== null),\n };\n if (Array.isArray(data.pending_inputs)) {\n detail.pendingInputs = parsePendingInputs(data.pending_inputs);\n }\n return detail;\n}\n\n/**\n * Approve or reject a tool call that asked for approval. On Sinas 0.5+,\n * `resume` says whether the round resumes now (`queued`, follow `channelId`)\n * or waits for decisions on its other calls (`waiting`, nothing to stream);\n * `approvalResumeChannel(result, approved)` picks the channel to follow.\n */\nexport async function approveToolCall(\n client: SinasClient,\n chatId: string,\n toolCallId: string,\n approved: boolean,\n options: ApproveToolCallOptions = {},\n): Promise<ApprovalResult> {\n const config = client.getConfig();\n const body: Record<string, unknown> = { approved };\n if (approved && options.alwaysAllow) body.always_allow = true;\n const res = await client.fetch(\n `${config.apiBase}/chats/${chatId}/approve-tool/${encodeURIComponent(toolCallId)}`,\n { method: 'POST', body: JSON.stringify(body) },\n );\n const data = await res.json();\n const result: ApprovalResult = {\n status: data.status,\n toolCallId: data.tool_call_id,\n channelId: data.channel_id,\n };\n if (data.resume === 'waiting' || data.resume === 'queued') result.resume = data.resume as ApprovalResume;\n if (typeof data.message === 'string') result.message = data.message;\n return result;\n}\n\n/** The ask_user questions the chat is suspended on (Sinas 0.5+). */\nexport async function listPendingInputs(\n client: SinasClient,\n chatId: string,\n): Promise<PendingInput[]> {\n const config = client.getConfig();\n const res = await client.fetch(`${config.apiBase}/chats/${chatId}/pending-input`);\n return parsePendingInputs(await res.json());\n}\n\n/**\n * Answer an ask_user question; the answer becomes the call's tool result.\n * Without `wait`, resolves once the answer is recorded: follow\n * `answerResumeChannel(result)` (when not null) to stream the resumed turn.\n * With `{ wait: true }`, resolves with the resumed turn's result instead\n * (`input_required` again if the agent asks again).\n */\nexport function answerPendingInput(\n client: SinasClient,\n chatId: string,\n toolCallId: string,\n answer: string,\n options: AnswerPendingInputOptions & { wait: true },\n): Promise<PendingInputAnswerResult>;\nexport function answerPendingInput(\n client: SinasClient,\n chatId: string,\n toolCallId: string,\n answer: string,\n options?: AnswerPendingInputOptions & { wait?: false },\n): Promise<PendingInputAnswerAccepted>;\nexport function answerPendingInput(\n client: SinasClient,\n chatId: string,\n toolCallId: string,\n answer: string,\n options?: AnswerPendingInputOptions,\n): Promise<PendingInputAnswerAccepted | PendingInputAnswerResult>;\nexport async function answerPendingInput(\n client: SinasClient,\n chatId: string,\n toolCallId: string,\n answer: string,\n options: AnswerPendingInputOptions = {},\n): Promise<PendingInputAnswerAccepted | PendingInputAnswerResult> {\n const config = client.getConfig();\n const body: Record<string, unknown> = { answer };\n if (options.wait) body.wait = true;\n const res = await client.fetch(\n `${config.apiBase}/chats/${chatId}/pending-input/${encodeURIComponent(toolCallId)}`,\n { method: 'POST', body: JSON.stringify(body) },\n );\n const data = await res.json();\n if (options.wait) {\n return {\n toolCallId: data.tool_call_id,\n chatId: data.chat_id,\n reply: typeof data.reply === 'string' ? data.reply : '',\n message: data.message && typeof data.message === 'object' ? parseMessage(data.message) : null,\n ...parseTurnState(data),\n };\n }\n return {\n status: 'answered',\n toolCallId: data.tool_call_id,\n resumed: !!data.resumed,\n resumePending: !!data.resume_pending,\n channelId: data.channel_id ?? null,\n message: typeof data.message === 'string' ? data.message : '',\n };\n}\n\n/**\n * Follow a stream channel: the stream of a resumed round (after an approval\n * or an answer), an `in_progress` turn, or a reconnect.\n */\nexport function streamFromChannel(\n client: SinasClient,\n chatId: string,\n channelId: string,\n onChunk: (chunk: SSEChunk) => void,\n onDone?: (done: StreamDone) => void,\n onError?: (error: Error) => void,\n options: StreamFromChannelOptions = {},\n): AbortController {\n const config = client.getConfig();\n const params = new URLSearchParams({ last_id: options.lastId ?? '0' });\n if (options.includeThinking) params.set('include_thinking', 'true');\n return runSSE(\n `${config.apiBase}/chats/${chatId}/stream/${encodeURIComponent(channelId)}?${params}`,\n (signal) => ({ headers: client.getAuthHeaders(), signal }),\n 'Stream reconnect failed',\n onChunk,\n onDone,\n onError,\n );\n}\n\n/**\n * Open an SSE request and hand its events to `onChunk` until a `done`\n * event (or the end of the body), then call `onDone` once. Aborting the\n * returned controller ends it silently.\n */\nfunction runSSE(\n url: string,\n init: (signal: AbortSignal) => RequestInit,\n failure: string,\n onChunk: (chunk: SSEChunk) => void,\n onDone?: (done: StreamDone) => void,\n onError?: (error: Error) => void,\n): AbortController {\n const controller = new AbortController();\n\n (async () => {\n try {\n const res = await fetch(url, init(controller.signal));\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ detail: res.statusText }));\n throw new Error(body.detail || failure);\n }\n\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const { chunks, remaining } = parseSSE(buffer);\n buffer = remaining;\n\n for (const chunk of chunks) {\n onChunk(chunk);\n if (chunk.event === 'done') {\n onDone?.(parseDone(chunk.data));\n return;\n }\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim()) {\n const { chunks } = parseSSE(buffer + '\\n\\n');\n for (const chunk of chunks) {\n onChunk(chunk);\n if (chunk.event === 'done') {\n onDone?.(parseDone(chunk.data));\n return;\n }\n }\n }\n\n onDone?.({ status: 'closed' });\n } catch (err) {\n if ((err as Error).name === 'AbortError') return;\n onError?.(err as Error);\n }\n })();\n\n return controller;\n}\n\n/**\n * Splits buffered SSE text into complete events (each ends with a blank\n * line); the incomplete tail is returned as `remaining` for the next read.\n */\nexport function parseSSE(buffer: string): { chunks: SSEChunk[]; remaining: string } {\n const chunks: SSEChunk[] = [];\n // Normalize \\r\\n to \\n (sse_starlette uses \\r\\n line endings). A \\r at\n // the very end stays in `remaining` until its \\n arrives.\n const normalized = buffer.replace(/\\r\\n/g, '\\n');\n let start = 0;\n let end: number;\n\n while ((end = normalized.indexOf('\\n\\n', start)) !== -1) {\n const block = normalized.slice(start, end);\n start = end + 2;\n let event = '';\n const data: string[] = [];\n for (const line of block.split('\\n')) {\n if (line.startsWith('event:')) event = line.slice(6).trim();\n else if (line.startsWith('data:')) data.push(line.slice(5).trim());\n }\n if (event || data.length) chunks.push({ event: event || 'message', data: data.join('\\n') });\n }\n\n return { chunks, remaining: normalized.slice(start) };\n}\n\n/** Send a message and stream the turn as SSE events. */\nexport function streamMessage(\n client: SinasClient,\n chatId: string,\n content: MessageContent,\n onChunk: (chunk: SSEChunk) => void,\n onDone?: (done: StreamDone) => void,\n onError?: (error: Error) => void,\n options: StreamOptions = {},\n): AbortController {\n const config = client.getConfig();\n const body: Record<string, unknown> = { content };\n if (options.includeThinking) body.include_thinking = true;\n return runSSE(\n `${config.apiBase}/chats/${chatId}/messages/stream`,\n (signal) => ({ method: 'POST', headers: client.getAuthHeaders(), body: JSON.stringify(body), signal }),\n 'Stream request failed',\n onChunk,\n onDone,\n onError,\n );\n}\n","import type { SinasClient } from './SinasClient';\nimport type { Collection, FileInfo, FileUploadRequest, FileUrlResult } from './types';\n\nexport async function listCollections(client: SinasClient): Promise<Collection[]> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/collections`);\n return res.json();\n}\n\nexport async function listFiles(\n client: SinasClient,\n namespace: string,\n collection: string\n): Promise<FileInfo[]> {\n const base = client.getProxyBase();\n const res = await client.fetch(`${base}/files/${namespace}/${collection}`);\n return res.json();\n}\n\nexport async function uploadFile(\n client: SinasClient,\n namespace: string,\n collection: string,\n data: FileUploadRequest,\n): Promise<FileInfo> {\n const apiBase = client.getConfig().apiBase;\n const res = await client.fetch(`${apiBase}/files/${namespace}/${collection}`, {\n method: 'POST',\n body: JSON.stringify(data),\n });\n return res.json();\n}\n\nexport async function generateFileUrl(\n client: SinasClient,\n namespace: string,\n collection: string,\n filename: string,\n expiresIn?: number,\n): Promise<FileUrlResult> {\n const apiBase = client.getConfig().apiBase;\n const params = new URLSearchParams();\n if (expiresIn) params.set('expires_in', String(expiresIn));\n const qs = params.toString() ? `?${params.toString()}` : '';\n const res = await client.fetch(\n `${apiBase}/files/${namespace}/${collection}/${encodeURIComponent(filename)}/url${qs}`,\n { method: 'POST' },\n );\n return res.json();\n}\n"],"mappings":"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","names":["parseRef"]}
package/dist/client.d.cts CHANGED
@@ -139,6 +139,12 @@ interface ChatDetail {
139
139
  title: string;
140
140
  messages: ChatMessageFull[];
141
141
  pendingApprovals: ApprovalRequest[];
142
+ /**
143
+ * The ask_user questions the chat is suspended on. Present when the
144
+ * server reports them (Sinas 0.5+); undefined on older servers, which
145
+ * have no ask_user.
146
+ */
147
+ pendingInputs?: PendingInput[];
142
148
  }
143
149
  interface ApprovalRequest {
144
150
  type: string;
@@ -147,10 +153,133 @@ interface ApprovalRequest {
147
153
  functionName: string;
148
154
  arguments: Record<string, unknown>;
149
155
  }
156
+ /**
157
+ * What happens to the round after an approval decision (Sinas 0.5+).
158
+ * `waiting`: other calls of the same round still wait for a decision, so
159
+ * nothing resumes yet and there is nothing to stream. `queued`: this was the
160
+ * round's last decision; the round resumes on `channelId` (this includes a
161
+ * final rejection, which the model gets as a rejection result).
162
+ */
163
+ type ApprovalResume = 'waiting' | 'queued';
150
164
  interface ApprovalResult {
151
165
  status: string;
152
166
  toolCallId: string;
153
167
  channelId: string;
168
+ /** Undefined on servers before Sinas 0.5, which resume on every approval. */
169
+ resume?: ApprovalResume;
170
+ message?: string;
171
+ }
172
+ interface ApproveToolCallOptions {
173
+ /**
174
+ * Approve this tool for the rest of the chat: later calls of the same tool
175
+ * skip the ask. Only applies to an approval (ignored when rejecting).
176
+ */
177
+ alwaysAllow?: boolean;
178
+ }
179
+ /** An ask_user question the conversation is suspended on. */
180
+ interface PendingInput {
181
+ toolCallId: string;
182
+ question: string;
183
+ /** Suggested answers, or null for a free-text question. */
184
+ options: string[] | null;
185
+ /** ISO timestamp after which the question expires (the round then resumes without it). */
186
+ expiresAt: string | null;
187
+ createdAt: string | null;
188
+ }
189
+ /**
190
+ * How a synchronously answered turn ended.
191
+ * - `completed`: the final reply is in the response.
192
+ * - `input_required`: the agent asked the user; see `pendingInputs` and
193
+ * answer with `answerPendingInput`.
194
+ * - `in_progress`: the turn goes on without this request; follow it on
195
+ * `channelId` (`streamFromChannel`) or read the chat later.
196
+ * - `injected`: the chat was busy, so the message was delivered into the
197
+ * running (or parked) turn; nothing was answered by this request.
198
+ */
199
+ type TurnStatus = 'completed' | 'input_required' | 'in_progress' | 'injected';
200
+ /** LLM usage of one request (the reply plus its tool rounds). */
201
+ interface TurnUsage {
202
+ calls: number;
203
+ promptTokens: number;
204
+ completionTokens: number;
205
+ totalTokens: number;
206
+ cacheReadTokens: number;
207
+ cacheWriteTokens: number;
208
+ /** Null when calls were made but none could be priced. */
209
+ costUsd: number | null;
210
+ unpricedCalls: number;
211
+ errors: number;
212
+ }
213
+ interface TurnState {
214
+ status: TurnStatus;
215
+ pendingInputs: PendingInput[];
216
+ /** Channel of the turn still going on (`in_progress`) or of the parked turn (`injected`). */
217
+ channelId: string | null;
218
+ /** Null when the server could not determine it (or predates Sinas 0.5). */
219
+ usage: TurnUsage | null;
220
+ }
221
+ /** Result of a non-streaming `sendMessage`. The base fields are unchanged; the turn state is Sinas 0.5+. */
222
+ interface MessageSendResult extends ChatMessage, TurnState {
223
+ }
224
+ interface InvokeOptions {
225
+ /** Session key for conversation continuity across invokes. */
226
+ sessionKey?: string;
227
+ /** Archive the session's existing chat and start fresh. */
228
+ reset?: boolean;
229
+ /** Agent input variables (only used when a new chat is created). */
230
+ input?: Record<string, unknown>;
231
+ }
232
+ interface InvokeResult extends TurnState {
233
+ /** The final reply (`completed`); what the agent said before asking or waiting otherwise; empty when `injected`. */
234
+ reply: string;
235
+ chatId: string;
236
+ sessionKey: string | null;
237
+ }
238
+ interface AnswerPendingInputOptions {
239
+ /**
240
+ * Wait for the resumed turn and return its result instead of a channel to
241
+ * stream it from.
242
+ */
243
+ wait?: boolean;
244
+ }
245
+ /** The answer was recorded (HTTP 202, without `wait`). */
246
+ interface PendingInputAnswerAccepted {
247
+ status: 'answered';
248
+ toolCallId: string;
249
+ /** The answer was the round's last outstanding completion; its resume is queued. */
250
+ resumed: boolean;
251
+ /** The last completion, but the resume could not be queued yet; it is retried shortly. */
252
+ resumePending: boolean;
253
+ /** Where the resumed turn streams, when `resumed` or `resumePending`. */
254
+ channelId: string | null;
255
+ message: string;
256
+ }
257
+ /** The resumed turn's result (HTTP 200, with `wait: true`). */
258
+ interface PendingInputAnswerResult extends TurnState {
259
+ toolCallId: string;
260
+ chatId: string;
261
+ reply: string;
262
+ /** The message `reply` comes from, when there is one. */
263
+ message: ChatMessageFull | null;
264
+ }
265
+ interface StreamOptions {
266
+ /**
267
+ * Stream the model's thinking text (Sinas 0.5+). Without it, a stream still
268
+ * gets one empty `thinking` when the model starts thinking.
269
+ */
270
+ includeThinking?: boolean;
271
+ }
272
+ interface StreamFromChannelOptions extends StreamOptions {
273
+ /** Last received stream entry id to resume after (default "0": from the start). */
274
+ lastId?: string;
275
+ }
276
+ /**
277
+ * How a stream ended. `completed`: the turn finished. `suspended`: the turn
278
+ * is parked waiting on the user (an ask_user question); the answer resumes it
279
+ * on a new channel. `closed`: the connection ended without a `done` event.
280
+ */
281
+ interface StreamDone {
282
+ status: 'completed' | 'suspended' | 'closed' | (string & {});
154
283
  }
155
284
  interface TextContentPart {
156
285
  type: 'text';
@@ -186,6 +315,26 @@ interface SSEChunk {
186
315
  event: string;
187
316
  data: string;
188
317
  }
318
+ /** Data of an `input_required` stream event: the agent asked the user (ask_user). */
319
+ interface InputRequiredEvent {
320
+ type: 'input_required';
321
+ tool_call_id: string;
322
+ question: string;
323
+ options?: string[] | null;
324
+ expires_at?: string | null;
325
+ }
326
+ /**
327
+ * Data of a `round_suspended` stream event: the tool round is parked on
328
+ * deferred work (questions, background runs, sub-agents). It resumes on
329
+ * `channel_id` when that work lands by itself.
330
+ */
331
+ interface RoundSuspendedEvent {
332
+ type: 'round_suspended';
333
+ tool_call_ids: string[];
334
+ channel_id?: string | null;
335
+ pending_completion_id?: string;
336
+ usage?: Record<string, unknown> | null;
337
+ }
189
338
  interface Collection {
190
339
  id: string;
191
340
  namespace: string;
@@ -271,6 +420,108 @@ declare class SinasClient {
271
420
  declare function executeQuery(client: SinasClient, ref: string, input?: Record<string, unknown>): Promise<QueryResult>;
272
421
 
273
422
  declare function executeFunction(client: SinasClient, ref: string, input?: Record<string, unknown>, timeout?: number): Promise<FunctionResult>;
423
+ interface EnqueueFunctionOptions {
424
+ /** App-supplied correlation id stored on the execution record. */
425
+ triggerId?: string;
426
+ /** Delay before the worker picks up the job, in seconds. */
427
+ delaySeconds?: number;
428
+ /**
429
+ * HTTPS URL Sinas will POST to once the execution terminates.
430
+ * Must match the instance's CALLBACK_URL_HOSTS allowlist.
431
+ */
432
+ callbackUrl?: string;
433
+ }
434
+ interface EnqueueFunctionResult {
435
+ executionId: string;
436
+ status: string;
437
+ }
438
+ /**
439
+ * Fire-and-forget function enqueue. Returns immediately with the
440
+ * execution_id. Poll `executions.get(id)` or rely on the callback URL
441
+ * if one was provided.
442
+ *
443
+ * Standalone-mode only — uses the SinasClient's baseUrl (set in the
444
+ * constructor). Embedded components should use `executeFunction` instead.
445
+ */
446
+ declare function enqueueFunction(client: SinasClient, ref: string, input?: Record<string, unknown>, options?: EnqueueFunctionOptions): Promise<EnqueueFunctionResult>;
447
+ interface SubmitFunctionBatchOptions {
448
+ triggerIdPrefix?: string;
449
+ delaySeconds?: number;
450
+ /** Fires once per execution. */
451
+ callbackUrl?: string;
452
+ /** Fires once when the entire batch terminates. */
453
+ batchCallbackUrl?: string;
454
+ }
455
+ interface SubmitFunctionBatchResult {
456
+ batchId: string;
457
+ executionIds: string[];
458
+ total: number;
459
+ status: string;
460
+ }
461
+ /** Submit N function executions as a single batch. */
462
+ declare function submitFunctionBatch(client: SinasClient, ref: string, inputs: Record<string, unknown>[], options?: SubmitFunctionBatchOptions): Promise<SubmitFunctionBatchResult>;
463
+ interface AgentBatchItem {
464
+ inputVariables?: Record<string, unknown>;
465
+ message: string;
466
+ }
467
+ interface SubmitAgentBatchOptions {
468
+ triggerIdPrefix?: string;
469
+ callbackUrl?: string;
470
+ batchCallbackUrl?: string;
471
+ }
472
+ interface SubmitAgentBatchResult {
473
+ batchId: string;
474
+ executionIds: string[];
475
+ chatIds: string[];
476
+ total: number;
477
+ status: string;
478
+ }
479
+ /** Submit N agent invocations as a single batch. */
480
+ declare function submitAgentBatch(client: SinasClient, ref: string, inputs: AgentBatchItem[], options?: SubmitAgentBatchOptions): Promise<SubmitAgentBatchResult>;
481
+ interface BatchStatus {
482
+ batchId: string;
483
+ kind: string;
484
+ target: {
485
+ namespace: string;
486
+ name: string;
487
+ };
488
+ userId: string;
489
+ total: number;
490
+ completed: number;
491
+ failed: number;
492
+ cancelled: number;
493
+ running: number;
494
+ queued: number;
495
+ status: string;
496
+ startedAt: string | null;
497
+ finishedAt: string | null;
498
+ triggerIdPrefix: string | null;
499
+ }
500
+ /** Get aggregate progress for a batch. */
501
+ declare function getBatch(client: SinasClient, batchId: string): Promise<BatchStatus>;
502
+ interface BatchExecutionItem {
503
+ executionId: string;
504
+ status: string;
505
+ functionName: string;
506
+ chatId: string | null;
507
+ triggerId: string;
508
+ startedAt: string | null;
509
+ completedAt: string | null;
510
+ durationMs: number | null;
511
+ error: string | null;
512
+ }
513
+ /** List child executions of a batch, optionally filtered by status. */
514
+ declare function listBatchExecutions(client: SinasClient, batchId: string, options?: {
515
+ status?: string;
516
+ limit?: number;
517
+ offset?: number;
518
+ }): Promise<BatchExecutionItem[]>;
519
+ /** Cancel any queued/pending children of a batch. */
520
+ declare function cancelBatch(client: SinasClient, batchId: string): Promise<{
521
+ batchId: string;
522
+ status: string;
523
+ cancelledChildren: number;
524
+ }>;
274
525
 
275
526
  declare function stateGet(client: SinasClient, ns: string, key: string): Promise<StateGetResult>;
276
527
  declare function stateSet(client: SinasClient, ns: string, key: string, value: unknown, visibility?: 'private' | 'shared'): Promise<void>;
@@ -278,11 +529,85 @@ declare function stateDelete(client: SinasClient, ns: string, key: string): Prom
278
529
  declare function stateList(client: SinasClient, ns: string): Promise<StateListResult>;
279
530
 
280
531
  declare function createChat(client: SinasClient, agentRef: string, input?: Record<string, unknown>): Promise<ChatCreateResult>;
281
- declare function sendMessage(client: SinasClient, chatId: string, content: MessageContent): Promise<ChatMessage>;
532
+ /**
533
+ * Send a message and wait for the turn (non-streaming). On Sinas 0.5+ the
534
+ * result says how the turn ended (`status`): with `input_required`, answer
535
+ * the questions in `pendingInputs` with `answerPendingInput`.
536
+ */
537
+ declare function sendMessage(client: SinasClient, chatId: string, content: MessageContent): Promise<MessageSendResult>;
538
+ /**
539
+ * Synchronous agent invoke: send a message, get the reply. Creates the chat
540
+ * (or reuses the one for `sessionKey`). Check `status`: with
541
+ * `input_required`, answer `pendingInputs` via `answerPendingInput`
542
+ * (`{ wait: true }` returns the resumed turn's result the same way).
543
+ */
544
+ declare function invokeAgent(client: SinasClient, agentRef: string, message: MessageContent, options?: InvokeOptions): Promise<InvokeResult>;
282
545
  declare function getChat(client: SinasClient, chatId: string): Promise<ChatDetail>;
283
- declare function approveToolCall(client: SinasClient, chatId: string, toolCallId: string, approved: boolean): Promise<ApprovalResult>;
284
- declare function streamFromChannel(client: SinasClient, chatId: string, channelId: string, onChunk: (chunk: SSEChunk) => void, onDone?: () => void, onError?: (error: Error) => void): AbortController;
285
- declare function streamMessage(client: SinasClient, chatId: string, content: MessageContent, onChunk: (chunk: SSEChunk) => void, onDone?: () => void, onError?: (error: Error) => void): AbortController;
546
+ /**
547
+ * Approve or reject a tool call that asked for approval. On Sinas 0.5+,
548
+ * `resume` says whether the round resumes now (`queued`, follow `channelId`)
549
+ * or waits for decisions on its other calls (`waiting`, nothing to stream);
550
+ * `approvalResumeChannel(result, approved)` picks the channel to follow.
551
+ */
552
+ declare function approveToolCall(client: SinasClient, chatId: string, toolCallId: string, approved: boolean, options?: ApproveToolCallOptions): Promise<ApprovalResult>;
553
+ /** The ask_user questions the chat is suspended on (Sinas 0.5+). */
554
+ declare function listPendingInputs(client: SinasClient, chatId: string): Promise<PendingInput[]>;
555
+ /**
556
+ * Answer an ask_user question; the answer becomes the call's tool result.
557
+ * Without `wait`, resolves once the answer is recorded: follow
558
+ * `answerResumeChannel(result)` (when not null) to stream the resumed turn.
559
+ * With `{ wait: true }`, resolves with the resumed turn's result instead
560
+ * (`input_required` again if the agent asks again).
561
+ */
562
+ declare function answerPendingInput(client: SinasClient, chatId: string, toolCallId: string, answer: string, options: AnswerPendingInputOptions & {
563
+ wait: true;
564
+ }): Promise<PendingInputAnswerResult>;
565
+ declare function answerPendingInput(client: SinasClient, chatId: string, toolCallId: string, answer: string, options?: AnswerPendingInputOptions & {
566
+ wait?: false;
567
+ }): Promise<PendingInputAnswerAccepted>;
568
+ declare function answerPendingInput(client: SinasClient, chatId: string, toolCallId: string, answer: string, options?: AnswerPendingInputOptions): Promise<PendingInputAnswerAccepted | PendingInputAnswerResult>;
569
+ /**
570
+ * Follow a stream channel: the stream of a resumed round (after an approval
571
+ * or an answer), an `in_progress` turn, or a reconnect.
572
+ */
573
+ declare function streamFromChannel(client: SinasClient, chatId: string, channelId: string, onChunk: (chunk: SSEChunk) => void, onDone?: (done: StreamDone) => void, onError?: (error: Error) => void, options?: StreamFromChannelOptions): AbortController;
574
+ /** Send a message and stream the turn as SSE events. */
575
+ declare function streamMessage(client: SinasClient, chatId: string, content: MessageContent, onChunk: (chunk: SSEChunk) => void, onDone?: (done: StreamDone) => void, onError?: (error: Error) => void, options?: StreamOptions): AbortController;
576
+
577
+ /**
578
+ * One ask_user question from the API (`GET /chats/{id}/pending-input`, the
579
+ * chat detail, a turn result, or an `input_required` stream event), or null
580
+ * when the value isn't one.
581
+ */
582
+ declare function parsePendingInput(raw: unknown): PendingInput | null;
583
+ declare function parsePendingInputs(raw: unknown): PendingInput[];
584
+ /**
585
+ * The question an SSE chunk announces, or null. Streams send it as its own
586
+ * `input_required` event; some earlier backends sent an inline turn's as a
587
+ * `message` event whose data has `type: "input_required"`. Both are handled.
588
+ */
589
+ declare function pendingInputFromChunk(chunk: SSEChunk): PendingInput | null;
590
+ /**
591
+ * The channel to follow after an approval decision, or null when there is
592
+ * nothing to stream yet. A round with several asked calls resumes once,
593
+ * after its last decision; until then the response says `resume: "waiting"`.
594
+ * On servers before 0.5 (no `resume` field) only an approval resumed.
595
+ */
596
+ declare function approvalResumeChannel(result: {
597
+ resume?: string | null;
598
+ channelId?: string | null;
599
+ }, approved?: boolean): string | null;
600
+ /**
601
+ * The channel to follow after answering a question (202 response), or null.
602
+ * The answer resumes the conversation only when it was the round's last
603
+ * outstanding completion (`resumed`) or that resume is being retried
604
+ * (`resumePending`).
605
+ */
606
+ declare function answerResumeChannel(result: {
607
+ resumed?: boolean;
608
+ resumePending?: boolean;
609
+ channelId?: string | null;
610
+ }): string | null;
286
611
 
287
612
  declare function listCollections(client: SinasClient): Promise<Collection[]>;
288
613
  declare function listFiles(client: SinasClient, namespace: string, collection: string): Promise<FileInfo[]>;
@@ -326,4 +651,4 @@ declare class SinasTimeoutError extends SinasError {
326
651
  constructor(message?: string);
327
652
  }
328
653
 
329
- export { type ApprovalRequest, type ApprovalResult, type AudioContentPart, type AuthMode, type AuthUser, type ChatCreateResult, type ChatDetail, type ChatMessage, type ChatMessageFull, type Collection, type ComponentContentPart, type ContentPart, type FileContentPart, type FileInfo, type FileUploadRequest, type FileUrlResult, type FunctionResult, type ImageContentPart, type InfoResponse, type LoginRequest, type LoginResponse, type MessageContent, type OTPVerifyRequest, type OTPVerifyResponse, type PermissionCheckRequest, type PermissionCheckResponse, type PermissionCheckResult, type QueryResult, type RefreshResponse, type SSEChunk, SinasAuthError, SinasClient, SinasClientAuth, type SinasClientOptions, type SinasConfig, SinasError, SinasNotFoundError, SinasPermissionError, SinasTimeoutError, type StateGetResult, type StateListResult, type TextContentPart, type ToolCallInfo, approveToolCall, checkPermissions, createChat, executeFunction, executeQuery, generateFileUrl, getChat, getInfo, getMe, listCollections, listFiles, login, logout, refresh, sendMessage, stateDelete, stateGet, stateList, stateSet, streamFromChannel, streamMessage, uploadFile, verifyOTP };
654
+ export { type AgentBatchItem, type AnswerPendingInputOptions, type ApprovalRequest, type ApprovalResult, type ApprovalResume, type ApproveToolCallOptions, type AudioContentPart, type AuthMode, type AuthUser, type BatchExecutionItem, type BatchStatus, type ChatCreateResult, type ChatDetail, type ChatMessage, type ChatMessageFull, type Collection, type ComponentContentPart, type ContentPart, type EnqueueFunctionOptions, type EnqueueFunctionResult, type FileContentPart, type FileInfo, type FileUploadRequest, type FileUrlResult, type FunctionResult, type ImageContentPart, type InfoResponse, type InputRequiredEvent, type InvokeOptions, type InvokeResult, type LoginRequest, type LoginResponse, type MessageContent, type MessageSendResult, type OTPVerifyRequest, type OTPVerifyResponse, type PendingInput, type PendingInputAnswerAccepted, type PendingInputAnswerResult, type PermissionCheckRequest, type PermissionCheckResponse, type PermissionCheckResult, type QueryResult, type RefreshResponse, type RoundSuspendedEvent, type SSEChunk, SinasAuthError, SinasClient, SinasClientAuth, type SinasClientOptions, type SinasConfig, SinasError, SinasNotFoundError, SinasPermissionError, SinasTimeoutError, type StateGetResult, type StateListResult, type StreamDone, type StreamFromChannelOptions, type StreamOptions, type SubmitAgentBatchOptions, type SubmitAgentBatchResult, type SubmitFunctionBatchOptions, type SubmitFunctionBatchResult, type TextContentPart, type ToolCallInfo, type TurnState, type TurnStatus, type TurnUsage, answerPendingInput, answerResumeChannel, approvalResumeChannel, approveToolCall, cancelBatch, checkPermissions, createChat, enqueueFunction, executeFunction, executeQuery, generateFileUrl, getBatch, getChat, getInfo, getMe, invokeAgent, listBatchExecutions, listCollections, listFiles, listPendingInputs, login, logout, parsePendingInput, parsePendingInputs, pendingInputFromChunk, refresh, sendMessage, stateDelete, stateGet, stateList, stateSet, streamFromChannel, streamMessage, submitAgentBatch, submitFunctionBatch, uploadFile, verifyOTP };