@raisindb/client 0.2.4 → 0.2.6
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/README.md +281 -70
- package/dist/chunk-3KMOXRTK.mjs +1377 -0
- package/dist/chunk-3KMOXRTK.mjs.map +1 -0
- package/dist/chunk-B6EFDYFS.mjs +170 -0
- package/dist/chunk-B6EFDYFS.mjs.map +1 -0
- package/dist/chunk-P44XWTPA.mjs +190 -0
- package/dist/chunk-P44XWTPA.mjs.map +1 -0
- package/dist/chunk-Q4IBPW2W.mjs +866 -0
- package/dist/chunk-Q4IBPW2W.mjs.map +1 -0
- package/dist/chunk-QJKYNLT4.mjs +532 -0
- package/dist/chunk-QJKYNLT4.mjs.map +1 -0
- package/dist/chunk-T2ZSNYFG.mjs +248 -0
- package/dist/chunk-T2ZSNYFG.mjs.map +1 -0
- package/dist/conversation-list-store-CU5mi_PE.d.mts +6842 -0
- package/dist/conversation-list-store-CU5mi_PE.d.ts +6842 -0
- package/dist/index-DDus5a7P.d.mts +301 -0
- package/dist/index-sFvMihQA.d.ts +301 -0
- package/dist/index.d.mts +72 -6109
- package/dist/index.d.ts +72 -6109
- package/dist/index.js +1640 -211
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1280 -3098
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +4 -0
- package/dist/react.d.ts +4 -0
- package/dist/react.js +2519 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +9 -0
- package/dist/react.mjs.map +1 -0
- package/dist/svelte-sql-B2G94Q9p.d.ts +52 -0
- package/dist/svelte-sql-CpXHXg34.d.mts +52 -0
- package/dist/svelte.d.mts +288 -0
- package/dist/svelte.d.ts +288 -0
- package/dist/svelte.js +2432 -0
- package/dist/svelte.js.map +1 -0
- package/dist/svelte.mjs +25 -0
- package/dist/svelte.mjs.map +1 -0
- package/dist/vue.d.mts +197 -0
- package/dist/vue.d.ts +197 -0
- package/dist/vue.js +1460 -0
- package/dist/vue.js.map +1 -0
- package/dist/vue.mjs +9 -0
- package/dist/vue.mjs.map +1 -0
- package/package.json +18 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/streaming/sse-client.ts","../src/flow-client.ts"],"sourcesContent":["/**\n * Error types for the RaisinDB JS SDK.\n *\n * Provides a structured error hierarchy for programmatic error handling.\n * All errors extend RaisinError and include a string `code` field for\n * easy matching in switch statements or error handlers.\n *\n * @example\n * ```typescript\n * import { RaisinError, RaisinConnectionError } from '@raisindb/client';\n *\n * try {\n * await flows.run('/flows/my-flow', {});\n * } catch (err) {\n * if (err instanceof RaisinConnectionError) {\n * console.log('Network issue:', err.code);\n * }\n * }\n * ```\n */\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\n/** Error codes for connection errors */\nexport type ConnectionErrorCode =\n | 'CONNECTION_FAILED'\n | 'CONNECTION_LOST'\n | 'SSE_STREAM_ERROR';\n\n/**\n * Error codes for authentication errors.\n *\n * Includes the well-known codes plus any server-provided code string\n * (e.g. identity endpoints return codes like `LOGIN_FAILED`).\n */\nexport type AuthErrorCode =\n | 'AUTH_UNAUTHORIZED'\n | 'AUTH_FORBIDDEN'\n | 'AUTH_TOKEN_EXPIRED'\n | 'LOGIN_FAILED'\n | 'REGISTRATION_FAILED'\n // eslint-disable-next-line @typescript-eslint/ban-types\n | (string & {});\n\n/** Error codes for flow execution errors */\nexport type FlowErrorCode =\n | 'FLOW_NOT_FOUND'\n | 'FLOW_EXECUTION_FAILED'\n | 'FLOW_INSTANCE_NOT_FOUND'\n | 'FLOW_RESUME_FAILED';\n\n/** Error codes for timeout errors */\nexport type TimeoutErrorCode =\n | 'REQUEST_TIMEOUT'\n | 'CONNECTION_TIMEOUT'\n | 'POLL_TIMEOUT'\n | 'SSE_INACTIVITY_TIMEOUT';\n\n/** Error codes for abort/cancellation errors */\nexport type AbortErrorCode = 'ABORTED';\n\n/** All error codes */\nexport type RaisinErrorCode =\n | ConnectionErrorCode\n | AuthErrorCode\n | FlowErrorCode\n | TimeoutErrorCode\n | AbortErrorCode;\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\n/**\n * Base error class for all RaisinDB SDK errors.\n *\n * All SDK errors extend this class, making it easy to catch any\n * RaisinDB-specific error with a single `instanceof` check.\n */\nexport class RaisinError extends Error {\n /** String error code for programmatic handling */\n readonly code: RaisinErrorCode;\n /** Optional additional details */\n readonly details?: unknown;\n\n constructor(message: string, code: RaisinErrorCode, details?: unknown) {\n super(message);\n this.name = 'RaisinError';\n this.code = code;\n this.details = details;\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when a network or connection failure occurs.\n *\n * This includes SSE stream errors, fetch failures, and lost connections.\n */\nexport class RaisinConnectionError extends RaisinError {\n /** HTTP status code, if available */\n readonly status?: number;\n\n constructor(message: string, code: ConnectionErrorCode, options?: { status?: number; details?: unknown }) {\n super(message, code, options?.details);\n this.name = 'RaisinConnectionError';\n this.status = options?.status;\n }\n}\n\n/**\n * Thrown when an authentication or authorization failure occurs.\n *\n * This includes 401 Unauthorized, 403 Forbidden, and expired tokens.\n */\nexport class RaisinAuthError extends RaisinError {\n /** HTTP status code (401 or 403) */\n readonly status: number;\n\n constructor(message: string, code: AuthErrorCode, status: number, details?: unknown) {\n super(message, code, details);\n this.name = 'RaisinAuthError';\n this.status = status;\n }\n}\n\n/**\n * Thrown when a flow execution error occurs.\n *\n * This includes flow not found, execution failures, and resume errors.\n */\nexport class RaisinFlowError extends RaisinError {\n /** Flow instance ID, if available */\n readonly instanceId?: string;\n\n constructor(message: string, code: FlowErrorCode, instanceId?: string, details?: unknown) {\n super(message, code, details);\n this.name = 'RaisinFlowError';\n this.instanceId = instanceId;\n }\n}\n\n/**\n * Thrown when a request or operation times out.\n *\n * Includes the timeout duration for debugging.\n */\nexport class RaisinTimeoutError extends RaisinError {\n /** Timeout duration in milliseconds */\n readonly timeoutMs: number;\n\n constructor(message: string, code: TimeoutErrorCode, timeoutMs: number, details?: unknown) {\n super(message, code, details);\n this.name = 'RaisinTimeoutError';\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Thrown when an operation is aborted via AbortSignal.\n */\nexport class RaisinAbortError extends RaisinError {\n constructor(message = 'Operation was aborted') {\n super(message, 'ABORTED');\n this.name = 'RaisinAbortError';\n }\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Classify an HTTP response error into the appropriate RaisinError subclass.\n *\n * @internal\n */\nexport function classifyHttpError(\n status: number,\n message: string,\n details?: unknown,\n): RaisinError {\n if (status === 401) {\n return new RaisinAuthError(message, 'AUTH_UNAUTHORIZED', status, details);\n }\n if (status === 403) {\n return new RaisinAuthError(message, 'AUTH_FORBIDDEN', status, details);\n }\n if (status === 404) {\n return new RaisinFlowError(message, 'FLOW_NOT_FOUND', undefined, details);\n }\n return new RaisinConnectionError(message, 'CONNECTION_FAILED', { status, details });\n}\n","/**\n * SSE (Server-Sent Events) client for streaming flow execution events.\n *\n * Uses fetch-based approach for better control over connection lifecycle,\n * headers, and reconnection compared to the native EventSource API.\n */\n\nimport { logger } from '../logger';\nimport { ReconnectManager, type ReconnectOptions } from '../utils/reconnect';\nimport { RaisinConnectionError, RaisinAuthError, RaisinAbortError, RaisinTimeoutError } from '../errors';\n\n/**\n * Parsed SSE event from the wire format\n */\nexport interface SSEEvent<T = unknown> {\n /** SSE event type (from \"event:\" field) */\n type: string;\n /** Parsed event data */\n data: T;\n /** SSE event ID (from \"id:\" field, if present) */\n id?: string;\n}\n\n/**\n * SSE connection state\n */\nexport type SSEConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n\n/**\n * Callback for SSE connection state changes\n */\nexport type SSEStateCallback = (state: SSEConnectionState) => void;\n\n/**\n * Options for creating an SSE client\n */\nexport interface SSEClientOptions {\n /** HTTP headers to include (e.g., Authorization) */\n headers?: Record<string, string>;\n /** Event types to filter for (if empty, all events are passed through) */\n eventTypes?: string[];\n /** Reconnection options (uses ReconnectManager) */\n reconnect?: ReconnectOptions & {\n /** Whether to automatically reconnect on disconnect (default: true) */\n enabled?: boolean;\n };\n /** Custom fetch implementation */\n fetch?: typeof fetch;\n /** Connection state change callback */\n onStateChange?: SSEStateCallback;\n /** Last-Event-ID for resuming streams */\n lastEventId?: string;\n /** External AbortSignal for cancellation */\n signal?: AbortSignal;\n /** HTTP method (default: 'GET'). Use 'POST' to avoid path in URL params. */\n method?: 'GET' | 'POST';\n /** Request body for POST requests (JSON-serialized automatically) */\n body?: unknown;\n /**\n * Inactivity timeout in milliseconds (default: disabled).\n *\n * The timer is reset whenever any bytes arrive on the stream (events,\n * comments/keep-alives, partial frames). If the stream produces nothing\n * for this long — including a fetch that never responds — the connection\n * is torn down. With reconnection enabled the client reconnects; with\n * reconnection disabled the stream ends with a `RaisinTimeoutError`\n * (code `SSE_INACTIVITY_TIMEOUT`).\n */\n inactivityTimeoutMs?: number;\n}\n\n/**\n * Parse a single SSE message block into event type, data, and id.\n *\n * SSE wire format:\n * event: <type>\\n\n * data: <json>\\n\n * id: <id>\\n\n * \\n\n */\nfunction parseSSEBlock(block: string): { event: string; data: string; id?: string } | null {\n let event = 'message';\n let data = '';\n let id: string | undefined;\n\n const lines = block.split('\\n');\n for (const line of lines) {\n if (line.startsWith('event:')) {\n event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n // Accumulate data lines (SSE spec allows multi-line data)\n if (data) data += '\\n';\n data += line.slice(5).trim();\n } else if (line.startsWith('id:')) {\n id = line.slice(3).trim();\n }\n // Lines starting with \":\" are comments (keep-alive), ignore them\n // Empty lines are block separators, handled by the caller\n }\n\n if (!data) return null;\n\n return { event, data, id };\n}\n\n/**\n * Fetch-based SSE client with reconnection, filtering, and AsyncIterable support.\n *\n * @example\n * ```typescript\n * const sse = new SSEClient('https://api.example.com/events/flow/123', {\n * headers: { Authorization: `Bearer ${token}` },\n * eventTypes: ['step_started', 'step_completed', 'flow_completed'],\n * });\n *\n * // AsyncIterable usage\n * for await (const event of sse) {\n * console.log(event.type, event.data);\n * }\n *\n * // Callback usage\n * sse.connect((event) => {\n * console.log(event.type, event.data);\n * });\n *\n * // Cleanup\n * sse.close();\n * ```\n */\nexport class SSEClient<T = unknown> implements AsyncIterable<SSEEvent<T>> {\n private url: string;\n private options: SSEClientOptions;\n private abortController: AbortController | null = null;\n private reconnectManager: ReconnectManager;\n private fetchImpl: typeof fetch;\n private _state: SSEConnectionState = 'disconnected';\n private _lastEventId?: string;\n private eventTypeSet: Set<string> | null;\n private autoReconnect: boolean;\n private externalSignal?: AbortSignal;\n private inactivityTimeoutMs?: number;\n\n constructor(url: string, options: SSEClientOptions = {}) {\n this.url = url;\n this.options = options;\n this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n this._lastEventId = options.lastEventId;\n this.autoReconnect = options.reconnect?.enabled ?? true;\n this.externalSignal = options.signal;\n this.inactivityTimeoutMs = options.inactivityTimeoutMs;\n this.eventTypeSet = options.eventTypes?.length\n ? new Set(options.eventTypes)\n : null;\n\n this.reconnectManager = new ReconnectManager({\n initialDelay: options.reconnect?.initialDelay ?? 1000,\n maxDelay: options.reconnect?.maxDelay ?? 30000,\n backoffMultiplier: options.reconnect?.backoffMultiplier ?? 2,\n maxAttempts: options.reconnect?.maxAttempts ?? Infinity,\n });\n }\n\n /** Current connection state */\n get state(): SSEConnectionState {\n return this._state;\n }\n\n /**\n * Returns a promise that resolves once the SSE connection is established.\n *\n * Useful for ensuring the connection is ready before triggering events\n * on the server side (e.g., calling resume before consuming the stream).\n * If the client is already connected, resolves immediately.\n */\n waitUntilConnected(): Promise<void> {\n if (this._state === 'connected') return Promise.resolve();\n return new Promise<void>((resolve, reject) => {\n const originalOnState = this.options.onStateChange;\n this.options.onStateChange = (state) => {\n originalOnState?.(state);\n if (state === 'connected') {\n // Restore original callback and resolve\n this.options.onStateChange = originalOnState;\n resolve();\n } else if (state === 'disconnected') {\n this.options.onStateChange = originalOnState;\n reject(new Error('SSE connection failed'));\n }\n };\n });\n }\n\n /** Last received event ID */\n get lastEventId(): string | undefined {\n return this._lastEventId;\n }\n\n private setState(state: SSEConnectionState): void {\n if (this._state !== state) {\n this._state = state;\n this.options.onStateChange?.(state);\n }\n }\n\n /**\n * Connect and consume events via callback.\n *\n * @param onEvent - Called for each matching SSE event\n * @param onError - Called when an error occurs (optional)\n */\n async connect(\n onEvent: (event: SSEEvent<T>) => void,\n onError?: (error: Error) => void,\n ): Promise<void> {\n this.close();\n await this.startStream(onEvent, onError);\n }\n\n /**\n * Close the SSE connection and stop reconnection attempts.\n */\n close(): void {\n this.reconnectManager.cancelReconnect();\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n this.setState('disconnected');\n }\n\n /**\n * AsyncIterable interface: allows `for await (const event of sseClient)`.\n *\n * The iterator ends when close() is called or the server closes the stream\n * (and auto-reconnect is disabled or max attempts are exhausted).\n */\n async *[Symbol.asyncIterator](): AsyncIterator<SSEEvent<T>> {\n // Use a queue and resolve-based approach for backpressure\n type QueueItem =\n | { done: false; value: SSEEvent<T> }\n | { done: true; error?: Error };\n\n const queue: QueueItem[] = [];\n let resolve: ((item: QueueItem) => void) | null = null;\n let finished = false;\n\n const push = (item: QueueItem) => {\n if (finished) return;\n if (resolve) {\n const r = resolve;\n resolve = null;\n r(item);\n } else {\n queue.push(item);\n }\n };\n\n const pull = (): Promise<QueueItem> => {\n const queued = queue.shift();\n if (queued) return Promise.resolve(queued);\n return new Promise<QueueItem>((r) => {\n resolve = r;\n });\n };\n\n // Start streaming in the background\n this.startStream(\n (event) => push({ done: false, value: event }),\n (error) => push({ done: true, error }),\n ).then(() => {\n push({ done: true });\n }).catch((error) => {\n push({ done: true, error });\n });\n\n try {\n while (!finished) {\n const item = await pull();\n if (item.done) {\n finished = true;\n if (item.error) {\n throw item.error;\n }\n return;\n }\n yield item.value;\n }\n } finally {\n finished = true;\n this.close();\n }\n }\n\n /**\n * Core streaming loop: connects, reads the SSE stream, and handles reconnection.\n */\n private async startStream(\n onEvent: (event: SSEEvent<T>) => void,\n onError?: (error: Error) => void,\n ): Promise<void> {\n while (true) {\n try {\n await this.readStream(onEvent);\n\n // Stream ended cleanly (server closed connection)\n if (!this.autoReconnect || this._state === 'disconnected') {\n return;\n }\n\n // Schedule reconnection\n this.setState('reconnecting');\n const scheduled = await this.waitForReconnect();\n if (!scheduled) {\n // Max attempts reached\n logger.warn('SSE max reconnection attempts reached');\n this.setState('disconnected');\n return;\n }\n } catch (error) {\n if (this._state === 'disconnected') {\n // close() was called, exit cleanly\n return;\n }\n\n const err = error instanceof Error ? error : new Error(String(error));\n\n // AbortError means close() was called or external AbortSignal fired\n if (err.name === 'AbortError' || err instanceof RaisinAbortError) {\n return;\n }\n\n // Inactivity timeout: reconnect silently if enabled, otherwise end\n // the stream with the typed timeout error.\n if (err instanceof RaisinTimeoutError && err.code === 'SSE_INACTIVITY_TIMEOUT') {\n logger.warn('SSE inactivity timeout:', err.message);\n if (!this.autoReconnect) {\n this.setState('disconnected');\n onError?.(err);\n throw err;\n }\n this.setState('reconnecting');\n const scheduled = await this.waitForReconnect();\n if (!scheduled) {\n logger.warn('SSE max reconnection attempts reached');\n this.setState('disconnected');\n onError?.(err);\n throw err;\n }\n continue;\n }\n\n logger.error('SSE connection error:', err.message);\n onError?.(err);\n\n if (!this.autoReconnect) {\n this.setState('disconnected');\n throw err;\n }\n\n // Schedule reconnection\n this.setState('reconnecting');\n const scheduled = await this.waitForReconnect();\n if (!scheduled) {\n logger.warn('SSE max reconnection attempts reached');\n this.setState('disconnected');\n throw err;\n }\n }\n }\n }\n\n /**\n * Perform a single fetch and read the response body as SSE stream.\n */\n private async readStream(onEvent: (event: SSEEvent<T>) => void): Promise<void> {\n this.abortController = new AbortController();\n this.setState('connecting');\n\n // If an external signal is provided, forward its abort to our internal controller\n if (this.externalSignal) {\n if (this.externalSignal.aborted) {\n this.abortController.abort();\n } else {\n const ctrl = this.abortController;\n this.externalSignal.addEventListener('abort', () => ctrl.abort(), { once: true });\n }\n }\n\n const headers: Record<string, string> = {\n Accept: 'text/event-stream',\n 'Cache-Control': 'no-cache',\n ...this.options.headers,\n };\n\n // Resume from last event ID if available\n if (this._lastEventId) {\n headers['Last-Event-ID'] = this._lastEventId;\n }\n\n const method = this.options.method ?? 'GET';\n const fetchOptions: RequestInit = {\n method,\n headers,\n signal: this.abortController.signal,\n };\n if (method === 'POST' && this.options.body !== undefined) {\n (fetchOptions.headers as Record<string, string>)['Content-Type'] = 'application/json';\n fetchOptions.body = JSON.stringify(this.options.body);\n }\n\n const response = await this.withInactivityTimeout(\n this.fetchImpl(this.url, fetchOptions),\n );\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n const msg = `SSE connection failed: ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`;\n if (response.status === 401 || response.status === 403) {\n throw new RaisinAuthError(\n msg,\n response.status === 401 ? 'AUTH_UNAUTHORIZED' : 'AUTH_FORBIDDEN',\n response.status,\n );\n }\n throw new RaisinConnectionError(msg, 'SSE_STREAM_ERROR', { status: response.status });\n }\n\n if (!response.body) {\n throw new RaisinConnectionError('SSE response has no body', 'SSE_STREAM_ERROR');\n }\n\n this.setState('connected');\n this.reconnectManager.reset();\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await this.withInactivityTimeout(reader.read());\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const blocks = buffer.split('\\n\\n');\n // Last element is incomplete, keep it in the buffer\n buffer = blocks.pop() ?? '';\n\n for (const block of blocks) {\n const trimmed = block.trim();\n if (!trimmed) continue;\n\n const parsed = parseSSEBlock(trimmed);\n if (!parsed) continue;\n\n // Track event ID for reconnection\n if (parsed.id) {\n this._lastEventId = parsed.id;\n }\n\n // Apply event type filter\n if (this.eventTypeSet && !this.eventTypeSet.has(parsed.event)) {\n continue;\n }\n\n // Parse JSON data\n let data: T;\n try {\n data = JSON.parse(parsed.data) as T;\n } catch {\n // If data isn't valid JSON, pass it as-is\n data = parsed.data as unknown as T;\n }\n\n const sseEvent = {\n type: parsed.event,\n data,\n id: parsed.id,\n };\n onEvent(sseEvent);\n }\n }\n } finally {\n try {\n reader.releaseLock();\n } catch {\n // Releasing while a read is pending can throw in some implementations\n }\n }\n }\n\n /**\n * Race a stream operation against the inactivity timeout.\n *\n * If no bytes (or response) arrive within `inactivityTimeoutMs`, the\n * internal connection is aborted and the operation rejects with a\n * `RaisinTimeoutError` (code `SSE_INACTIVITY_TIMEOUT`). The timer is\n * effectively reset on every chunk because each `reader.read()` is\n * wrapped individually.\n */\n private withInactivityTimeout<T>(promise: Promise<T>): Promise<T> {\n const timeoutMs = this.inactivityTimeoutMs;\n if (!timeoutMs || timeoutMs <= 0) return promise;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n // Swallow the eventual rejection of the underlying promise\n // (e.g. AbortError after we abort) to avoid unhandled rejections.\n promise.catch(() => undefined);\n this.abortController?.abort();\n reject(\n new RaisinTimeoutError(\n `SSE stream inactive for ${timeoutMs}ms`,\n 'SSE_INACTIVITY_TIMEOUT',\n timeoutMs,\n ),\n );\n }, timeoutMs);\n\n promise.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n }\n\n /**\n * Wait for the reconnect manager to schedule a reconnection attempt.\n * Returns true if reconnection was scheduled, false if max attempts reached.\n */\n private waitForReconnect(): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const scheduled = this.reconnectManager.scheduleReconnect(() => {\n resolve(true);\n });\n if (!scheduled) {\n resolve(false);\n }\n });\n }\n}\n","/**\n * FlowClient for executing and monitoring RaisinDB flows.\n *\n * Provides methods to:\n * - Run a flow by path and receive an instance ID\n * - Stream real-time execution events via SSE\n * - Resume a waiting flow with external data\n * - Respond to human tasks within a flow\n *\n * @example\n * ```typescript\n * import { RaisinHttpClient } from '@raisindb/client';\n * import { FlowClient } from '@raisindb/client/flow-client';\n *\n * const httpClient = new RaisinHttpClient('http://localhost:8081');\n * await httpClient.authenticate({ username: 'admin', password: 'admin' });\n *\n * const flows = new FlowClient(httpClient, 'my-repo');\n *\n * // Start a flow\n * const { instance_id } = await flows.run('/flows/my-flow', { key: 'value' });\n *\n * // Stream events\n * for await (const event of flows.streamEvents(instance_id)) {\n * console.log(event.type, event);\n * if (event.type === 'flow_completed') break;\n * }\n * ```\n */\n\nimport type { AuthManager } from './auth';\nimport type { FlowsApi } from './flows';\nimport type {\n FlowRunResponse,\n FlowExecutionEvent,\n FlowInstanceStatusResponse,\n FlowCompletedEvent,\n FlowFailedEvent,\n} from './types/flow';\nimport { SSEClient, type SSEEvent } from './streaming/sse-client';\nimport {\n classifyHttpError,\n RaisinAbortError,\n RaisinTimeoutError,\n} from './errors';\n\n/** Options for creating a FlowClient */\nexport interface FlowClientOptions {\n /** Request timeout in milliseconds (default: 60000 for long-running flows) */\n requestTimeout?: number;\n /** Custom fetch implementation */\n fetch?: typeof fetch;\n}\n\n/** Result from `runAndWait()` */\nexport interface FlowRunResult {\n /** Flow instance ID */\n instanceId: string;\n /** Terminal status */\n status: 'completed' | 'failed';\n /** Flow output (when completed) */\n output?: unknown;\n /** Error message (when failed) */\n error?: string;\n}\n\n/** Result from `runAndCollect()` */\nexport interface FlowCollectResult {\n /** Flow instance ID */\n instanceId: string;\n /** All collected events */\n events: FlowExecutionEvent[];\n}\n\n/**\n * Minimal interface the FlowClient needs from the HTTP client.\n * This avoids a hard dependency on the full RaisinHttpClient class.\n */\ninterface HttpClientLike {\n /** Get the auth manager for token access */\n getAuthManager(): AuthManager;\n}\n\n/**\n * Client for executing and monitoring RaisinDB flows.\n *\n * Uses the HTTP REST API for flow operations and SSE for real-time event streaming.\n */\nexport class FlowClient {\n private baseUrl: string;\n private repository: string;\n private authManager: AuthManager;\n private fetchImpl: typeof fetch;\n private requestTimeout: number;\n private flowsApi?: FlowsApi;\n\n /**\n * Create a new FlowClient.\n *\n * @param baseUrl - Base HTTP URL of the RaisinDB server (e.g., \"http://localhost:8081\")\n * @param repository - Repository name\n * @param authManager - Auth manager for token access\n * @param options - Additional options\n * @param flowsApi - Optional FlowsApi for WebSocket-based flow operations\n */\n constructor(\n baseUrl: string,\n repository: string,\n authManager: AuthManager,\n options: FlowClientOptions = {},\n flowsApi?: FlowsApi,\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, '');\n this.repository = repository;\n this.authManager = authManager;\n this.fetchImpl = options.fetch ?? fetch;\n this.requestTimeout = options.requestTimeout ?? 60000;\n this.flowsApi = flowsApi;\n }\n\n /**\n * Create a FlowClient from an existing RaisinHttpClient.\n *\n * @param httpClient - An authenticated RaisinHttpClient instance\n * @param baseUrl - Base HTTP URL (same as the one used for the HTTP client)\n * @param repository - Repository name\n * @param options - Additional options\n */\n static fromHttpClient(\n httpClient: HttpClientLike,\n baseUrl: string,\n repository: string,\n options: FlowClientOptions = {},\n flowsApi?: FlowsApi,\n ): FlowClient {\n return new FlowClient(\n baseUrl,\n repository,\n httpClient.getAuthManager(),\n options,\n flowsApi,\n );\n }\n\n // ==========================================================================\n // Flow Execution\n // ==========================================================================\n\n /**\n * Execute a flow by path.\n *\n * Creates a FlowInstance and queues it for execution. Returns immediately\n * with the instance ID - use `streamEvents()` to monitor progress.\n *\n * @param flowPath - Path to the raisin:Flow node (e.g., \"/flows/my-flow\")\n * @param input - Input data passed to the flow\n * @returns Flow run response with instance_id and job_id\n *\n * @example\n * ```typescript\n * const result = await flows.run('/flows/process-order', {\n * orderId: 'ord-123',\n * items: [{ sku: 'ABC', qty: 2 }],\n * });\n * console.log('Instance:', result.instance_id);\n * ```\n */\n async run(\n flowPath: string,\n input: Record<string, unknown> = {},\n options?: { signal?: AbortSignal },\n ): Promise<FlowRunResponse> {\n if (this.flowsApi) {\n return this.flowsApi.run(flowPath, input);\n }\n const response = await this.request<FlowRunResponse>({\n method: 'POST',\n path: `/api/flows/${this.repository}/run`,\n body: { flow_path: flowPath, input },\n signal: options?.signal,\n });\n return response;\n }\n\n // ==========================================================================\n // Instance Status\n // ==========================================================================\n\n /**\n * Get the current status of a flow instance.\n *\n * Returns the instance status, variables, and metadata. Useful for\n * polling-based approaches where SSE is not reliable (e.g., initial\n * flow execution where events may be missed).\n *\n * @param instanceId - Flow instance ID (from `run()`)\n * @returns Instance status including variables and flow path\n *\n * @example\n * ```typescript\n * const status = await flows.getInstanceStatus('instance-123');\n * console.log('Status:', status.status); // 'waiting', 'completed', etc.\n * ```\n */\n async getInstanceStatus(\n instanceId: string,\n options?: { signal?: AbortSignal },\n ): Promise<FlowInstanceStatusResponse> {\n if (this.flowsApi) {\n return this.flowsApi.getInstanceStatus(instanceId);\n }\n return this.request<FlowInstanceStatusResponse>({\n method: 'GET',\n path: `/api/flows/${this.repository}/instances/${instanceId}`,\n signal: options?.signal,\n });\n }\n\n // ==========================================================================\n // Event Streaming (SSE)\n // ==========================================================================\n\n /**\n * Stream real-time execution events for a flow instance via SSE.\n *\n * Returns an async iterable that yields FlowExecutionEvent objects.\n * The stream automatically closes when a terminal event is received\n * (flow_completed or flow_failed).\n *\n * @param instanceId - Flow instance ID (from `run()`)\n * @returns Async iterable of flow execution events\n *\n * @example\n * ```typescript\n * const { instance_id } = await flows.run('/flows/my-flow', { key: 'value' });\n *\n * for await (const event of flows.streamEvents(instance_id)) {\n * switch (event.type) {\n * case 'step_started':\n * console.log(`Step ${event.node_id} started`);\n * break;\n * case 'step_completed':\n * console.log(`Step ${event.node_id} completed in ${event.duration_ms}ms`);\n * break;\n * case 'text_chunk':\n * process.stdout.write(event.text);\n * break;\n * case 'flow_completed':\n * console.log('Flow done:', event.output);\n * break;\n * case 'flow_failed':\n * console.error('Flow failed:', event.error);\n * break;\n * }\n * }\n * ```\n */\n async *streamEvents(\n instanceId: string,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<FlowExecutionEvent> {\n if (this.flowsApi) {\n const sub = await this.flowsApi.subscribeEvents(instanceId);\n try {\n for await (const event of sub.events) {\n if (options?.signal?.aborted) throw new RaisinAbortError();\n yield event;\n if (event.type === 'flow_completed' || event.type === 'flow_failed') {\n return;\n }\n }\n } finally {\n await sub.unsubscribe();\n }\n return;\n }\n const url = `${this.baseUrl}/api/flows/${this.repository}/instances/${instanceId}/events`;\n const headers: Record<string, string> = {};\n\n const token = this.authManager.getAccessToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const sse = new SSEClient<FlowExecutionEvent>(url, {\n headers,\n eventTypes: ['flow-event', 'message'],\n reconnect: { enabled: false },\n fetch: this.fetchImpl,\n signal: options?.signal,\n });\n\n try {\n for await (const sseEvent of sse) {\n const event = sseEvent.data;\n yield event;\n\n // Stop on terminal events\n if (\n event.type === 'flow_completed' ||\n event.type === 'flow_failed'\n ) {\n return;\n }\n }\n } finally {\n sse.close();\n }\n }\n\n /**\n * Create an eagerly-connected event stream for a flow instance.\n *\n * Unlike `streamEvents()` (a lazy async generator), this method opens the\n * SSE connection immediately and waits until it is established before\n * returning. This is critical for resume flows: you must subscribe to\n * events BEFORE calling `resume()`, otherwise events emitted between\n * the resume and the SSE connection are lost.\n *\n * @param instanceId - Flow instance ID\n * @returns Object with an async iterable `events` and a `close()` method\n */\n async createEventStream(\n instanceId: string,\n options?: { signal?: AbortSignal },\n ): Promise<{\n events: AsyncIterable<FlowExecutionEvent>;\n close: () => void;\n }> {\n if (this.flowsApi) {\n const sub = await this.flowsApi.subscribeEvents(instanceId);\n return {\n events: sub.events,\n close: () => { sub.unsubscribe(); },\n };\n }\n const url = `${this.baseUrl}/api/flows/${this.repository}/instances/${instanceId}/events`;\n const headers: Record<string, string> = {};\n\n const token = this.authManager.getAccessToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const sse = new SSEClient<FlowExecutionEvent>(url, {\n headers,\n eventTypes: ['flow-event', 'message'],\n reconnect: { enabled: false },\n fetch: this.fetchImpl,\n signal: options?.signal,\n });\n\n // Kick-start the async generator to initiate the SSE connection.\n // Async generators are lazy — the body (which calls startStream)\n // only executes when .next() is called.\n const iterator = sse[Symbol.asyncIterator]();\n let pendingFirst: Promise<IteratorResult<SSEEvent<FlowExecutionEvent>>> | null = iterator.next();\n\n // Now that startStream is running, wait for the HTTP response\n await sse.waitUntilConnected();\n\n // Wrap in a terminal-event-aware iterable\n const events: AsyncIterable<FlowExecutionEvent> = {\n [Symbol.asyncIterator]() {\n return {\n async next() {\n let result;\n if (pendingFirst) {\n result = await pendingFirst;\n pendingFirst = null;\n } else {\n result = await iterator.next();\n }\n if (result.done) return { done: true as const, value: undefined };\n const event = result.value.data;\n return { done: false, value: event };\n },\n async return() {\n await iterator.return?.();\n sse.close();\n return { done: true as const, value: undefined };\n },\n };\n },\n };\n\n return { events, close: () => sse.close() };\n }\n\n // ==========================================================================\n // Flow Resume & Human Task\n // ==========================================================================\n\n /**\n * Resume a flow instance that is in a waiting state.\n *\n * Use this when a flow is waiting for external input (tool results,\n * external events, etc.). The resume data is passed to the waiting step.\n *\n * @param instanceId - Flow instance ID\n * @param data - Resume data to pass to the waiting step\n *\n * @example\n * ```typescript\n * await flows.resume('instance-123', {\n * tool_name: 'get_weather',\n * result: { temperature: 72, conditions: 'sunny' },\n * });\n * ```\n */\n async resume(\n instanceId: string,\n data: unknown,\n options?: { signal?: AbortSignal },\n ): Promise<void> {\n if (this.flowsApi) {\n await this.flowsApi.resume(instanceId, data);\n return;\n }\n await this.request<void>({\n method: 'POST',\n path: `/api/flows/${this.repository}/instances/${instanceId}/resume`,\n body: { resume_data: data },\n signal: options?.signal,\n });\n }\n\n /**\n * Respond to a human task within a flow.\n *\n * When a flow is waiting on a human_task step (approval, input, review),\n * use this method to submit the response. Completion is validated\n * (caller must be the task's assignee or an admin) and resumes the flow.\n *\n * Note: prefer `InboxApi` for full inbox functionality (listing tasks,\n * task details); this is a convenience passthrough to the same endpoint.\n *\n * @param instanceId - Flow instance ID (unused; kept for API stability)\n * @param taskId - The inbox task node ID (or path)\n * @param response - The response data\n *\n * @example\n * ```typescript\n * // Approve a task\n * await flows.respondToHumanTask('instance-123', 'task-abc', {\n * action: 'approve',\n * comment: 'Looks good!',\n * });\n * ```\n */\n async respondToHumanTask(\n _instanceId: string,\n taskId: string,\n response: unknown,\n options?: { signal?: AbortSignal },\n ): Promise<void> {\n await this.request<void>({\n method: 'POST',\n path: `/api/inbox/${this.repository}/tasks/${encodeURIComponent(taskId)}/complete`,\n body: { response },\n signal: options?.signal,\n });\n }\n\n // ==========================================================================\n // Convenience Methods\n // ==========================================================================\n\n /**\n * Run a flow and wait for the final result.\n *\n * Starts the flow, streams all events, and returns the terminal outcome.\n * This is a one-shot helper for fire-and-forget flows where you only\n * care about the final output.\n *\n * @param flowPath - Path to the raisin:Flow node\n * @param input - Input data passed to the flow\n * @param options - Optional abort signal\n * @returns The flow outcome including output or error\n *\n * @example\n * ```typescript\n * const result = await flows.runAndWait('/flows/process-order', { orderId: '123' });\n * if (result.status === 'completed') {\n * console.log('Output:', result.output);\n * }\n * ```\n */\n async runAndWait(\n flowPath: string,\n input: Record<string, unknown> = {},\n options?: { signal?: AbortSignal },\n ): Promise<FlowRunResult> {\n const { instance_id } = await this.run(flowPath, input, options);\n\n for await (const event of this.streamEvents(instance_id, options)) {\n if (event.type === 'flow_completed') {\n return {\n instanceId: instance_id,\n status: 'completed',\n output: (event as FlowCompletedEvent).output,\n };\n }\n if (event.type === 'flow_failed') {\n return {\n instanceId: instance_id,\n status: 'failed',\n error: (event as FlowFailedEvent).error,\n };\n }\n }\n\n return { instanceId: instance_id, status: 'failed', error: 'Stream ended without terminal event' };\n }\n\n /**\n * Run a flow and collect all events into an array.\n *\n * Starts the flow, streams all events, and returns them as a collected array.\n * Useful for testing, logging, or post-processing all flow events.\n *\n * @param flowPath - Path to the raisin:Flow node\n * @param input - Input data passed to the flow\n * @param options - Optional abort signal\n * @returns The instance ID and all collected events\n *\n * @example\n * ```typescript\n * const { events } = await flows.runAndCollect('/flows/etl-pipeline', { source: 'db' });\n * const steps = events.filter(e => e.type === 'step_completed');\n * console.log(`Completed ${steps.length} steps`);\n * ```\n */\n async runAndCollect(\n flowPath: string,\n input: Record<string, unknown> = {},\n options?: { signal?: AbortSignal },\n ): Promise<FlowCollectResult> {\n const { instance_id } = await this.run(flowPath, input, options);\n const events: FlowExecutionEvent[] = [];\n\n for await (const event of this.streamEvents(instance_id, options)) {\n events.push(event);\n }\n\n return { instanceId: instance_id, events };\n }\n\n // ==========================================================================\n // Internal HTTP request helper\n // ==========================================================================\n\n private async request<T>(options: {\n method: string;\n path: string;\n body?: unknown;\n signal?: AbortSignal;\n }): Promise<T> {\n const url = `${this.baseUrl}${options.path}`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n const token = this.authManager.getAccessToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.requestTimeout);\n\n // Forward external signal to our internal controller\n if (options.signal) {\n if (options.signal.aborted) {\n clearTimeout(timeoutId);\n throw new RaisinAbortError();\n }\n options.signal.addEventListener('abort', () => controller.abort(), { once: true });\n }\n\n try {\n const response = await this.fetchImpl(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage: string;\n try {\n const errorJson = JSON.parse(errorText);\n errorMessage = errorJson.message || errorJson.error || errorText;\n } catch {\n errorMessage =\n errorText || `HTTP ${response.status}: ${response.statusText}`;\n }\n\n throw classifyHttpError(response.status, errorMessage);\n }\n\n const contentType = response.headers.get('content-type');\n if (contentType?.includes('application/json')) {\n return (await response.json()) as T;\n }\n\n return undefined as unknown as T;\n } catch (error) {\n clearTimeout(timeoutId);\n // Re-throw our own errors as-is\n if (error instanceof RaisinAbortError || error instanceof RaisinTimeoutError) {\n throw error;\n }\n if (error instanceof Error && error.name === 'AbortError') {\n // Distinguish external abort from internal timeout\n if (options.signal?.aborted) {\n throw new RaisinAbortError();\n }\n throw new RaisinTimeoutError(\n `Request timeout after ${this.requestTimeout}ms`,\n 'REQUEST_TIMEOUT',\n this.requestTimeout,\n );\n }\n throw error;\n }\n }\n}\n"],"mappings":"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","names":["scheduled"]}
|
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FlowClient
|
|
3
|
+
} from "./chunk-Q4IBPW2W.mjs";
|
|
4
|
+
import {
|
|
5
|
+
ConversationListStore,
|
|
6
|
+
ConversationStore
|
|
7
|
+
} from "./chunk-3KMOXRTK.mjs";
|
|
8
|
+
|
|
9
|
+
// src/integrations/react/use-auth.ts
|
|
10
|
+
function createUseAuth(react, context) {
|
|
11
|
+
return function useAuth() {
|
|
12
|
+
const { useState, useEffect, useRef, useCallback, useContext } = react;
|
|
13
|
+
const ctx = useContext(context);
|
|
14
|
+
if (!ctx) {
|
|
15
|
+
throw new Error("useAuth must be used within a <RaisinProvider>");
|
|
16
|
+
}
|
|
17
|
+
const { client } = ctx;
|
|
18
|
+
const [user, setUser] = useState(client.getStoredUser());
|
|
19
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
20
|
+
const mountedRef = useRef(true);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
mountedRef.current = true;
|
|
23
|
+
const unsubAuth = client.onAuthStateChange(({ event, session }) => {
|
|
24
|
+
if (!mountedRef.current) return;
|
|
25
|
+
if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED" || event === "USER_UPDATED") {
|
|
26
|
+
setUser(session.user);
|
|
27
|
+
} else if (event === "SIGNED_OUT" || event === "SESSION_EXPIRED") {
|
|
28
|
+
setUser(null);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const unsubUser = client.onUserChange(({ node }) => {
|
|
32
|
+
if (!mountedRef.current) return;
|
|
33
|
+
setUser((prev) => {
|
|
34
|
+
if (!prev) return prev;
|
|
35
|
+
return {
|
|
36
|
+
...prev,
|
|
37
|
+
home: node.path,
|
|
38
|
+
displayName: node.properties.display_name ?? prev.displayName,
|
|
39
|
+
avatarUrl: node.properties.avatar_url ?? prev.avatarUrl
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
return () => {
|
|
44
|
+
mountedRef.current = false;
|
|
45
|
+
unsubAuth();
|
|
46
|
+
unsubUser();
|
|
47
|
+
};
|
|
48
|
+
}, [client]);
|
|
49
|
+
const login = useCallback(async (email, password, repository) => {
|
|
50
|
+
setIsLoading(true);
|
|
51
|
+
try {
|
|
52
|
+
const result = await client.loginWithEmail(email, password, repository);
|
|
53
|
+
return result;
|
|
54
|
+
} finally {
|
|
55
|
+
if (mountedRef.current) setIsLoading(false);
|
|
56
|
+
}
|
|
57
|
+
}, [client]);
|
|
58
|
+
const register = useCallback(async (email, password, repository, displayName) => {
|
|
59
|
+
setIsLoading(true);
|
|
60
|
+
try {
|
|
61
|
+
const result = await client.registerWithEmail(email, password, repository, displayName);
|
|
62
|
+
return result;
|
|
63
|
+
} finally {
|
|
64
|
+
if (mountedRef.current) setIsLoading(false);
|
|
65
|
+
}
|
|
66
|
+
}, [client]);
|
|
67
|
+
const logout = useCallback(async (options) => {
|
|
68
|
+
setIsLoading(true);
|
|
69
|
+
try {
|
|
70
|
+
await client.logout(options);
|
|
71
|
+
} finally {
|
|
72
|
+
if (mountedRef.current) setIsLoading(false);
|
|
73
|
+
}
|
|
74
|
+
}, [client]);
|
|
75
|
+
const initSession = useCallback(async (repository) => {
|
|
76
|
+
setIsLoading(true);
|
|
77
|
+
try {
|
|
78
|
+
const result = await client.initSession(repository);
|
|
79
|
+
return result;
|
|
80
|
+
} finally {
|
|
81
|
+
if (mountedRef.current) setIsLoading(false);
|
|
82
|
+
}
|
|
83
|
+
}, [client]);
|
|
84
|
+
return {
|
|
85
|
+
user,
|
|
86
|
+
isAuthenticated: user !== null,
|
|
87
|
+
isLoading,
|
|
88
|
+
login,
|
|
89
|
+
register,
|
|
90
|
+
logout,
|
|
91
|
+
initSession
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/integrations/react/use-connection.ts
|
|
97
|
+
function createUseConnection(react, context) {
|
|
98
|
+
return function useConnection() {
|
|
99
|
+
const { useState, useEffect, useCallback, useContext } = react;
|
|
100
|
+
const ctx = useContext(context);
|
|
101
|
+
if (!ctx) {
|
|
102
|
+
throw new Error("useConnection must be used within a <RaisinProvider>");
|
|
103
|
+
}
|
|
104
|
+
const { client } = ctx;
|
|
105
|
+
const [state, setState] = useState(client.getConnectionState());
|
|
106
|
+
const [isReady, setIsReady] = useState(client.isReady());
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
const unsubConn = client.onConnectionStateChange((newState) => {
|
|
109
|
+
setState(newState);
|
|
110
|
+
});
|
|
111
|
+
const unsubReady = client.onReadyStateChange((ready) => {
|
|
112
|
+
setIsReady(ready);
|
|
113
|
+
});
|
|
114
|
+
return () => {
|
|
115
|
+
unsubConn();
|
|
116
|
+
unsubReady();
|
|
117
|
+
};
|
|
118
|
+
}, [client]);
|
|
119
|
+
const connect = useCallback(async () => {
|
|
120
|
+
await client.connect();
|
|
121
|
+
}, [client]);
|
|
122
|
+
const disconnect = useCallback(() => {
|
|
123
|
+
client.disconnect();
|
|
124
|
+
}, [client]);
|
|
125
|
+
return {
|
|
126
|
+
state,
|
|
127
|
+
isConnected: state === "connected" /* Connected */,
|
|
128
|
+
isReady,
|
|
129
|
+
connect,
|
|
130
|
+
disconnect
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/integrations/react/use-sql.ts
|
|
136
|
+
function rowsToObjects(result) {
|
|
137
|
+
return result.rows;
|
|
138
|
+
}
|
|
139
|
+
function createUseSql(react, context) {
|
|
140
|
+
return function useSql(sql, params, options) {
|
|
141
|
+
const { useState, useEffect, useRef, useCallback, useContext } = react;
|
|
142
|
+
const ctx = useContext(context);
|
|
143
|
+
if (!ctx) {
|
|
144
|
+
throw new Error("useSql must be used within a <RaisinProvider>");
|
|
145
|
+
}
|
|
146
|
+
const { client, repository: defaultRepo } = ctx;
|
|
147
|
+
const [data, setData] = useState(null);
|
|
148
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
149
|
+
const [error, setError] = useState(null);
|
|
150
|
+
const mountedRef = useRef(true);
|
|
151
|
+
const enabled = options?.enabled !== false;
|
|
152
|
+
const repo = options?.repository ?? defaultRepo;
|
|
153
|
+
const refetchOnReconnect = options?.refetchOnReconnect !== false;
|
|
154
|
+
const realtime = options?.realtime;
|
|
155
|
+
const paramsKey = params ? JSON.stringify(params) : "";
|
|
156
|
+
const fetchData = useCallback(async () => {
|
|
157
|
+
if (!repo) return;
|
|
158
|
+
setIsLoading(true);
|
|
159
|
+
setError(null);
|
|
160
|
+
try {
|
|
161
|
+
const db = client.database(repo);
|
|
162
|
+
const result = await db.executeSql(sql, params);
|
|
163
|
+
if (mountedRef.current) {
|
|
164
|
+
setData(rowsToObjects(result));
|
|
165
|
+
}
|
|
166
|
+
} catch (err) {
|
|
167
|
+
if (mountedRef.current) {
|
|
168
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
169
|
+
}
|
|
170
|
+
} finally {
|
|
171
|
+
if (mountedRef.current) {
|
|
172
|
+
setIsLoading(false);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}, [client, repo, sql, paramsKey]);
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
mountedRef.current = true;
|
|
178
|
+
if (enabled) {
|
|
179
|
+
fetchData();
|
|
180
|
+
}
|
|
181
|
+
return () => {
|
|
182
|
+
mountedRef.current = false;
|
|
183
|
+
};
|
|
184
|
+
}, [enabled, fetchData]);
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
if (!enabled || !refetchOnReconnect) return;
|
|
187
|
+
const unsub = client.onReconnected(() => {
|
|
188
|
+
fetchData();
|
|
189
|
+
});
|
|
190
|
+
return unsub;
|
|
191
|
+
}, [client, enabled, refetchOnReconnect, fetchData]);
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
if (!enabled || !realtime || !repo) return;
|
|
194
|
+
const db = client.database(repo);
|
|
195
|
+
let unsubscribe;
|
|
196
|
+
db.events().subscribe(
|
|
197
|
+
{
|
|
198
|
+
workspace: realtime.workspace,
|
|
199
|
+
event_types: realtime.eventTypes,
|
|
200
|
+
path: realtime.path,
|
|
201
|
+
node_type: realtime.nodeType
|
|
202
|
+
},
|
|
203
|
+
() => {
|
|
204
|
+
fetchData();
|
|
205
|
+
}
|
|
206
|
+
).then((sub) => {
|
|
207
|
+
unsubscribe = () => sub.unsubscribe();
|
|
208
|
+
});
|
|
209
|
+
return () => {
|
|
210
|
+
unsubscribe?.();
|
|
211
|
+
};
|
|
212
|
+
}, [client, enabled, repo, realtime?.workspace, realtime?.path, realtime?.nodeType, fetchData]);
|
|
213
|
+
return {
|
|
214
|
+
data,
|
|
215
|
+
isLoading,
|
|
216
|
+
error,
|
|
217
|
+
refetch: fetchData
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// src/integrations/react/use-subscription.ts
|
|
223
|
+
function createUseSubscription(react, context) {
|
|
224
|
+
return function useSubscription(options, callback) {
|
|
225
|
+
const { useEffect, useRef, useContext } = react;
|
|
226
|
+
const ctx = useContext(context);
|
|
227
|
+
if (!ctx) {
|
|
228
|
+
throw new Error("useSubscription must be used within a <RaisinProvider>");
|
|
229
|
+
}
|
|
230
|
+
const { client, repository } = ctx;
|
|
231
|
+
const callbackRef = useRef(callback);
|
|
232
|
+
callbackRef.current = callback;
|
|
233
|
+
const enabled = options.enabled !== false;
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
if (!enabled || !repository || !options.workspace) return;
|
|
236
|
+
const db = client.database(repository);
|
|
237
|
+
let unsubscribe;
|
|
238
|
+
let cancelled = false;
|
|
239
|
+
db.events().subscribe(
|
|
240
|
+
{
|
|
241
|
+
workspace: options.workspace,
|
|
242
|
+
event_types: options.event_types,
|
|
243
|
+
path: options.path,
|
|
244
|
+
node_type: options.node_type,
|
|
245
|
+
include_node: options.include_node
|
|
246
|
+
},
|
|
247
|
+
(event) => {
|
|
248
|
+
if (!cancelled) {
|
|
249
|
+
callbackRef.current(event);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
).then((sub) => {
|
|
253
|
+
if (cancelled) {
|
|
254
|
+
sub.unsubscribe();
|
|
255
|
+
} else {
|
|
256
|
+
unsubscribe = () => sub.unsubscribe();
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
return () => {
|
|
260
|
+
cancelled = true;
|
|
261
|
+
unsubscribe?.();
|
|
262
|
+
};
|
|
263
|
+
}, [client, repository, enabled, options.workspace, options.path, options.node_type, options.include_node]);
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/integrations/react-conversation.ts
|
|
268
|
+
var INITIAL_SNAPSHOT = {
|
|
269
|
+
conversation: null,
|
|
270
|
+
messages: [],
|
|
271
|
+
isStreaming: false,
|
|
272
|
+
isWaiting: false,
|
|
273
|
+
streamingText: "",
|
|
274
|
+
error: null,
|
|
275
|
+
activeToolCalls: [],
|
|
276
|
+
plans: [],
|
|
277
|
+
isLoading: false,
|
|
278
|
+
conversationPath: null
|
|
279
|
+
};
|
|
280
|
+
function useConversation(react, options) {
|
|
281
|
+
const { useState, useEffect, useRef, useCallback } = react;
|
|
282
|
+
const [snapshot, setSnapshot] = useState(INITIAL_SNAPSHOT);
|
|
283
|
+
const storeRef = useRef(null);
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
const store = new ConversationStore(options);
|
|
286
|
+
storeRef.current = store;
|
|
287
|
+
const unsubscribe = store.subscribe((next) => setSnapshot(next));
|
|
288
|
+
return () => {
|
|
289
|
+
unsubscribe();
|
|
290
|
+
store.destroy();
|
|
291
|
+
storeRef.current = null;
|
|
292
|
+
};
|
|
293
|
+
}, [options.conversationPath]);
|
|
294
|
+
const sendMessage = useCallback(async (content) => {
|
|
295
|
+
await storeRef.current?.sendMessage(content);
|
|
296
|
+
}, []);
|
|
297
|
+
const approvePlan = useCallback(async (planPath) => {
|
|
298
|
+
await storeRef.current?.approvePlan(planPath);
|
|
299
|
+
}, []);
|
|
300
|
+
const rejectPlan = useCallback(async (planPath, feedback) => {
|
|
301
|
+
await storeRef.current?.rejectPlan(planPath, feedback);
|
|
302
|
+
}, []);
|
|
303
|
+
const stop = useCallback(() => {
|
|
304
|
+
storeRef.current?.stop();
|
|
305
|
+
}, []);
|
|
306
|
+
const loadMessages = useCallback(async () => {
|
|
307
|
+
return await storeRef.current?.loadMessages() ?? [];
|
|
308
|
+
}, []);
|
|
309
|
+
return {
|
|
310
|
+
...snapshot,
|
|
311
|
+
sendMessage,
|
|
312
|
+
approvePlan,
|
|
313
|
+
rejectPlan,
|
|
314
|
+
stop,
|
|
315
|
+
loadMessages
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
var INITIAL_LIST_SNAPSHOT = {
|
|
319
|
+
conversations: [],
|
|
320
|
+
totalUnreadCount: 0,
|
|
321
|
+
isLoading: true,
|
|
322
|
+
error: null
|
|
323
|
+
};
|
|
324
|
+
function useConversationList(react, options) {
|
|
325
|
+
const { useState, useEffect, useRef, useCallback } = react;
|
|
326
|
+
const [snapshot, setSnapshot] = useState(INITIAL_LIST_SNAPSHOT);
|
|
327
|
+
const storeRef = useRef(null);
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
const store = new ConversationListStore(options);
|
|
330
|
+
storeRef.current = store;
|
|
331
|
+
const unsubscribe = store.subscribe((next) => setSnapshot(next));
|
|
332
|
+
store.load();
|
|
333
|
+
return () => {
|
|
334
|
+
unsubscribe();
|
|
335
|
+
store.destroy();
|
|
336
|
+
storeRef.current = null;
|
|
337
|
+
};
|
|
338
|
+
}, [options.type, options.realtime]);
|
|
339
|
+
const createConversation = useCallback(async (opts) => {
|
|
340
|
+
return storeRef.current.createConversation(opts);
|
|
341
|
+
}, []);
|
|
342
|
+
const deleteConversation = useCallback(async (conversationPath) => {
|
|
343
|
+
await storeRef.current?.deleteConversation(conversationPath);
|
|
344
|
+
}, []);
|
|
345
|
+
const markAsRead = useCallback(async (conversationPath) => {
|
|
346
|
+
await storeRef.current?.markAsRead(conversationPath);
|
|
347
|
+
}, []);
|
|
348
|
+
return {
|
|
349
|
+
...snapshot,
|
|
350
|
+
createConversation,
|
|
351
|
+
deleteConversation,
|
|
352
|
+
markAsRead
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// src/integrations/react-flow.ts
|
|
357
|
+
function useFlow(react, options) {
|
|
358
|
+
const { useState, useEffect, useRef, useCallback } = react;
|
|
359
|
+
const [events, setEvents] = useState([]);
|
|
360
|
+
const [status, setStatus] = useState("idle");
|
|
361
|
+
const [error, setError] = useState(null);
|
|
362
|
+
const [output, setOutput] = useState(null);
|
|
363
|
+
const [instanceId, setInstanceId] = useState(null);
|
|
364
|
+
const clientRef = useRef(null);
|
|
365
|
+
const abortRef = useRef(false);
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
if (options.database) {
|
|
368
|
+
clientRef.current = options.database.flow;
|
|
369
|
+
} else if (options.baseUrl && options.repository && options.authManager) {
|
|
370
|
+
clientRef.current = new FlowClient(
|
|
371
|
+
options.baseUrl,
|
|
372
|
+
options.repository,
|
|
373
|
+
options.authManager,
|
|
374
|
+
options.clientOptions,
|
|
375
|
+
options.flowsApi
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
return () => {
|
|
379
|
+
abortRef.current = true;
|
|
380
|
+
clientRef.current = null;
|
|
381
|
+
};
|
|
382
|
+
}, [options.database, options.baseUrl, options.repository]);
|
|
383
|
+
const run = useCallback(async (flowPath, input = {}) => {
|
|
384
|
+
const client = clientRef.current;
|
|
385
|
+
if (!client) return;
|
|
386
|
+
abortRef.current = false;
|
|
387
|
+
setEvents([]);
|
|
388
|
+
setError(null);
|
|
389
|
+
setOutput(null);
|
|
390
|
+
setStatus("running");
|
|
391
|
+
try {
|
|
392
|
+
const result = await client.run(flowPath, input);
|
|
393
|
+
setInstanceId(result.instance_id);
|
|
394
|
+
for await (const event of client.streamEvents(result.instance_id)) {
|
|
395
|
+
if (abortRef.current) break;
|
|
396
|
+
setEvents((prev) => [...prev, event]);
|
|
397
|
+
if (event.type === "flow_waiting") {
|
|
398
|
+
setStatus("waiting");
|
|
399
|
+
} else if (event.type === "flow_completed") {
|
|
400
|
+
setOutput(event.output);
|
|
401
|
+
setStatus("completed");
|
|
402
|
+
} else if (event.type === "flow_failed") {
|
|
403
|
+
setError(event.error);
|
|
404
|
+
setStatus("failed");
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
} catch (err) {
|
|
408
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
409
|
+
setStatus("failed");
|
|
410
|
+
}
|
|
411
|
+
}, []);
|
|
412
|
+
const resume = useCallback(async (data) => {
|
|
413
|
+
const client = clientRef.current;
|
|
414
|
+
if (!client || !instanceId) return;
|
|
415
|
+
setStatus("running");
|
|
416
|
+
setError(null);
|
|
417
|
+
try {
|
|
418
|
+
const stream = await client.createEventStream(instanceId);
|
|
419
|
+
await client.resume(instanceId, data);
|
|
420
|
+
for await (const event of stream.events) {
|
|
421
|
+
if (abortRef.current) break;
|
|
422
|
+
setEvents((prev) => [...prev, event]);
|
|
423
|
+
if (event.type === "flow_waiting") {
|
|
424
|
+
setStatus("waiting");
|
|
425
|
+
stream.close();
|
|
426
|
+
return;
|
|
427
|
+
} else if (event.type === "flow_completed") {
|
|
428
|
+
setOutput(event.output);
|
|
429
|
+
setStatus("completed");
|
|
430
|
+
stream.close();
|
|
431
|
+
return;
|
|
432
|
+
} else if (event.type === "flow_failed") {
|
|
433
|
+
setError(event.error);
|
|
434
|
+
setStatus("failed");
|
|
435
|
+
stream.close();
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
stream.close();
|
|
440
|
+
} catch (err) {
|
|
441
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
442
|
+
setStatus("failed");
|
|
443
|
+
}
|
|
444
|
+
}, [instanceId]);
|
|
445
|
+
const reset = useCallback(() => {
|
|
446
|
+
abortRef.current = true;
|
|
447
|
+
setEvents([]);
|
|
448
|
+
setStatus("idle");
|
|
449
|
+
setError(null);
|
|
450
|
+
setOutput(null);
|
|
451
|
+
setInstanceId(null);
|
|
452
|
+
}, []);
|
|
453
|
+
return {
|
|
454
|
+
events,
|
|
455
|
+
status,
|
|
456
|
+
isRunning: status === "running",
|
|
457
|
+
error,
|
|
458
|
+
output,
|
|
459
|
+
instanceId,
|
|
460
|
+
run,
|
|
461
|
+
resume,
|
|
462
|
+
reset
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/integrations/react/index.ts
|
|
467
|
+
function createRaisinReact(react) {
|
|
468
|
+
const RaisinContext = react.createContext(null);
|
|
469
|
+
function RaisinProvider(props) {
|
|
470
|
+
const { client, repository, children } = props;
|
|
471
|
+
const value = react.useMemo(
|
|
472
|
+
() => ({ client, repository }),
|
|
473
|
+
[client, repository]
|
|
474
|
+
);
|
|
475
|
+
return react.createElement(
|
|
476
|
+
RaisinContext.Provider,
|
|
477
|
+
{ value },
|
|
478
|
+
children
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
function useRaisinClient() {
|
|
482
|
+
const ctx = react.useContext(RaisinContext);
|
|
483
|
+
if (!ctx) {
|
|
484
|
+
throw new Error("useRaisinClient must be used within a <RaisinProvider>");
|
|
485
|
+
}
|
|
486
|
+
return ctx.client;
|
|
487
|
+
}
|
|
488
|
+
function useDatabase(repository) {
|
|
489
|
+
const ctx = react.useContext(RaisinContext);
|
|
490
|
+
if (!ctx) {
|
|
491
|
+
throw new Error("useDatabase must be used within a <RaisinProvider>");
|
|
492
|
+
}
|
|
493
|
+
const repo = repository ?? ctx.repository;
|
|
494
|
+
if (!repo) {
|
|
495
|
+
throw new Error("useDatabase requires a repository \u2014 pass it as an argument or set it on <RaisinProvider>");
|
|
496
|
+
}
|
|
497
|
+
return react.useMemo(() => ctx.client.database(repo), [ctx.client, repo]);
|
|
498
|
+
}
|
|
499
|
+
const useAuth = createUseAuth(react, RaisinContext);
|
|
500
|
+
const useConnection = createUseConnection(react, RaisinContext);
|
|
501
|
+
const useSql = createUseSql(react, RaisinContext);
|
|
502
|
+
const useSubscription = createUseSubscription(react, RaisinContext);
|
|
503
|
+
function useConversation2(options) {
|
|
504
|
+
return useConversation(react, options);
|
|
505
|
+
}
|
|
506
|
+
function useConversationList2(options) {
|
|
507
|
+
return useConversationList(react, options);
|
|
508
|
+
}
|
|
509
|
+
function useFlow2(options) {
|
|
510
|
+
return useFlow(react, options);
|
|
511
|
+
}
|
|
512
|
+
return {
|
|
513
|
+
RaisinProvider,
|
|
514
|
+
useRaisinClient,
|
|
515
|
+
useDatabase,
|
|
516
|
+
useAuth,
|
|
517
|
+
useConnection,
|
|
518
|
+
useSql,
|
|
519
|
+
useSubscription,
|
|
520
|
+
useConversation: useConversation2,
|
|
521
|
+
useConversationList: useConversationList2,
|
|
522
|
+
useFlow: useFlow2
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
export {
|
|
527
|
+
useConversation,
|
|
528
|
+
useConversationList,
|
|
529
|
+
useFlow,
|
|
530
|
+
createRaisinReact
|
|
531
|
+
};
|
|
532
|
+
//# sourceMappingURL=chunk-QJKYNLT4.mjs.map
|