@octavus/server-sdk 2.20.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -311,11 +311,12 @@ async function* executeStream(config, payload, signal) {
311
311
  return;
312
312
  }
313
313
  if (pendingToolCalls && pendingToolCalls.length > 0) {
314
- const serverTools = pendingToolCalls.filter((tc) => config.toolHandlers[tc.toolName]);
315
- const clientTools = pendingToolCalls.filter((tc) => !config.toolHandlers[tc.toolName]);
314
+ const toolHandlers = config.getToolHandlers();
315
+ const serverTools = pendingToolCalls.filter((tc) => toolHandlers[tc.toolName]);
316
+ const clientTools = pendingToolCalls.filter((tc) => !toolHandlers[tc.toolName]);
316
317
  const serverResults = await Promise.all(
317
318
  serverTools.map(async (tc) => {
318
- const handler = config.toolHandlers[tc.toolName];
319
+ const handler = toolHandlers[tc.toolName];
319
320
  try {
320
321
  const result = await handler(tc.args);
321
322
  return {
@@ -424,13 +425,17 @@ function toSSEStream(events) {
424
425
  }
425
426
  });
426
427
  }
428
+ function resolveDynamicTools(provider) {
429
+ const handlers = provider.toolHandlers();
430
+ return provider.toolSchemas().filter((s) => handlers[s.name]).map((s) => ({ schema: s, handler: handlers[s.name] }));
431
+ }
427
432
  var AgentSession = class {
428
433
  sessionId;
429
434
  config;
430
435
  toolHandlers;
431
436
  resourceMap;
432
- additionalToolSchemas;
433
- additionalToolSchemasSent = false;
437
+ dynamicToolSchemas;
438
+ dynamicToolNames = /* @__PURE__ */ new Set();
434
439
  socketAbortController = null;
435
440
  onToolResults;
436
441
  rejectClientToolCalls;
@@ -438,7 +443,6 @@ var AgentSession = class {
438
443
  this.sessionId = sessionConfig.sessionId;
439
444
  this.config = sessionConfig.config;
440
445
  this.toolHandlers = sessionConfig.tools ?? {};
441
- this.additionalToolSchemas = sessionConfig.additionalToolSchemas;
442
446
  this.onToolResults = sessionConfig.onToolResults;
443
447
  this.rejectClientToolCalls = sessionConfig.rejectClientToolCalls ?? false;
444
448
  this.resourceMap = /* @__PURE__ */ new Map();
@@ -491,6 +495,35 @@ var AgentSession = class {
491
495
  getSessionId() {
492
496
  return this.sessionId;
493
497
  }
498
+ /**
499
+ * Set the full list of dynamic tools (schemas + handlers).
500
+ * Replaces any previously set dynamic tools — removed tools are
501
+ * unregistered, new ones are added, and updated schemas are sent
502
+ * to the platform on the next request.
503
+ *
504
+ * Accepts either a `ToolProvider` (e.g. `Computer`) or an explicit
505
+ * `DynamicTool[]` array.
506
+ *
507
+ * Safe to call mid-session: executeStream resolves toolHandlers via
508
+ * a getter on each continuation loop, so new handlers are visible
509
+ * immediately.
510
+ */
511
+ setDynamicTools(source) {
512
+ const tools = Array.isArray(source) ? source : resolveDynamicTools(source);
513
+ const newNames = new Set(tools.map((t) => t.schema.name));
514
+ const cleaned = {};
515
+ for (const [name, handler] of Object.entries(this.toolHandlers)) {
516
+ if (!this.dynamicToolNames.has(name)) {
517
+ cleaned[name] = handler;
518
+ }
519
+ }
520
+ for (const tool of tools) {
521
+ cleaned[tool.schema.name] = tool.handler;
522
+ }
523
+ this.toolHandlers = cleaned;
524
+ this.dynamicToolNames = newNames;
525
+ this.dynamicToolSchemas = tools.map((t) => t.schema);
526
+ }
494
527
  /**
495
528
  * Handle a WebSocket protocol message (trigger, continue, or stop).
496
529
  * Manages abort controller lifecycle internally.
@@ -537,7 +570,7 @@ var AgentSession = class {
537
570
  yield* executeStream(
538
571
  {
539
572
  config: this.config,
540
- toolHandlers: this.toolHandlers,
573
+ getToolHandlers: () => this.toolHandlers,
541
574
  url: `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,
542
575
  buildBody: ({ executionId, toolResults }) => {
543
576
  const body = {};
@@ -547,9 +580,8 @@ var AgentSession = class {
547
580
  body.rollbackAfterMessageId = payload.rollbackAfterMessageId;
548
581
  if (executionId !== void 0) body.executionId = executionId;
549
582
  if (toolResults !== void 0) body.toolResults = toolResults;
550
- if (!this.additionalToolSchemasSent && (this.additionalToolSchemas?.length ?? 0) > 0) {
551
- body.additionalToolSchemas = this.additionalToolSchemas;
552
- this.additionalToolSchemasSent = true;
583
+ if (this.dynamicToolSchemas !== void 0) {
584
+ body.dynamicToolSchemas = this.dynamicToolSchemas;
553
585
  }
554
586
  return body;
555
587
  },
@@ -690,14 +722,11 @@ var AgentSessionsApi = class extends BaseApiClient {
690
722
  }
691
723
  /** Attach to an existing session for triggering events */
692
724
  attach(sessionId, options = {}) {
693
- const computerHandlers = options.computer?.toolHandlers() ?? {};
694
- const mergedTools = { ...computerHandlers, ...options.tools };
695
725
  return new AgentSession({
696
726
  sessionId,
697
727
  config: this.config,
698
- tools: mergedTools,
728
+ tools: options.tools,
699
729
  resources: options.resources,
700
- additionalToolSchemas: options.computer?.toolSchemas(),
701
730
  onToolResults: options.onToolResults,
702
731
  rejectClientToolCalls: options.rejectClientToolCalls
703
732
  });
@@ -811,12 +840,19 @@ var WorkersApi = class extends BaseApiClient {
811
840
  * ```
812
841
  */
813
842
  async *execute(agentId, input, options = {}) {
843
+ const tools = options.tools ?? {};
814
844
  yield* executeStream(
815
845
  {
816
846
  config: this.config,
817
- toolHandlers: options.tools ?? {},
847
+ getToolHandlers: () => tools,
818
848
  url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,
819
- buildBody: ({ executionId, toolResults }) => !executionId ? { type: "start", input } : { type: "continue", executionId, toolResults },
849
+ buildBody: ({ executionId, toolResults }) => !executionId ? {
850
+ type: "start",
851
+ input,
852
+ ...options.dynamicToolSchemas !== void 0 && {
853
+ dynamicToolSchemas: options.dynamicToolSchemas
854
+ }
855
+ } : { type: "continue", executionId, toolResults },
820
856
  errorContext: "Failed to execute worker"
821
857
  },
822
858
  {},
@@ -900,10 +936,11 @@ var WorkersApi = class extends BaseApiClient {
900
936
  * ```
901
937
  */
902
938
  async *continue(agentId, executionId, toolResults, options = {}) {
939
+ const tools = options.tools ?? {};
903
940
  yield* executeStream(
904
941
  {
905
942
  config: this.config,
906
- toolHandlers: options.tools ?? {},
943
+ getToolHandlers: () => tools,
907
944
  url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,
908
945
  buildBody: ({ executionId: execId, toolResults: results }) => ({
909
946
  type: "continue",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/api-error.ts","../src/base-api-client.ts","../src/agent-types.ts","../src/agents.ts","../src/agent-sessions.ts","../src/session.ts","../src/streaming.ts","../src/files.ts","../src/worker-error.ts","../src/workers.ts","../src/client.ts","../src/resource.ts","../src/normalize-images.ts"],"sourcesContent":["export { OctavusClient, type OctavusClientConfig } from '@/client.js';\nexport { AgentsApi } from '@/agents.js';\nexport {\n AgentSessionsApi,\n type SessionState,\n type UISessionState,\n type ExpiredSessionState,\n type RestoreSessionResult,\n type ClearSessionResult,\n type SessionStatus,\n type SessionAttachOptions,\n} from '@/agent-sessions.js';\nexport {\n FilesApi,\n type FileUploadRequest,\n type FileUploadInfo,\n type UploadUrlsResponse,\n} from '@/files.js';\nexport {\n AgentSession,\n toSSEStream,\n type SessionConfig,\n type TriggerOptions,\n type SessionRequest,\n type TriggerRequest,\n type ContinueRequest,\n type StopMessage,\n type SocketMessage,\n type SocketMessageHandlers,\n} from '@/session.js';\nexport {\n WorkersApi,\n type WorkerStartRequest,\n type WorkerContinueRequest,\n type WorkerRequest,\n type WorkerExecuteOptions,\n type WorkerGenerateResult,\n} from '@/workers.js';\nexport { WorkerError } from '@/worker-error.js';\nexport { Resource } from '@/resource.js';\nexport { ApiError } from '@/api-error.js';\nexport { normalizeToolResultImages } from '@/normalize-images.js';\n\n// Agent types (read-only - use @octavus/cli for agent management)\nexport type {\n AgentFormat,\n AgentSettings,\n AgentPrompt,\n Agent,\n AgentDefinition,\n} from '@/agent-types.js';\n\nexport type * from '@octavus/core';\nexport {\n // Error classes\n AppError,\n NotFoundError,\n ValidationError,\n ConflictError,\n ForbiddenError,\n OctavusError,\n // Error type guards\n isRateLimitError,\n isAuthenticationError,\n isProviderError,\n isToolError,\n isRetryableError,\n isValidationError,\n // Error event helpers\n createErrorEvent,\n errorToStreamEvent,\n createInternalErrorEvent,\n createApiErrorEvent,\n // Utilities\n generateId,\n isAbortError,\n // Thread helpers\n MAIN_THREAD,\n resolveThread,\n isMainThread,\n threadForPart,\n isOtherThread,\n // Type guards\n isFileReference,\n isFileReferenceArray,\n // Safe parse helpers\n safeParseStreamEvent,\n safeParseUIMessage,\n safeParseUIMessages,\n // Skills\n OCTAVUS_SKILL_TOOLS,\n isOctavusSkillTool,\n getSkillSlugFromToolCall,\n} from '@octavus/core';\n","import { z } from 'zod';\n\nconst ApiErrorResponseSchema = z.object({\n error: z.string().optional(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n/**\n * Error thrown when API request fails\n */\nexport class ApiError extends Error {\n constructor(\n message: string,\n public status: number,\n public code?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\ninterface ParsedApiError {\n message: string;\n code?: string;\n}\n\n/**\n * Parse error from API response using Zod\n */\nexport async function parseApiError(\n response: Response,\n defaultMessage: string,\n): Promise<ParsedApiError> {\n const fallbackMessage = `${defaultMessage}: ${response.statusText}`;\n\n try {\n const json: unknown = await response.json();\n const parsed = ApiErrorResponseSchema.safeParse(json);\n\n if (parsed.success) {\n return {\n message: parsed.data.error ?? parsed.data.message ?? fallbackMessage,\n code: parsed.data.code,\n };\n }\n } catch {\n // Use default message\n }\n\n return { message: fallbackMessage };\n}\n\n/**\n * Parse error from API response and throw ApiError\n */\nexport async function throwApiError(response: Response, defaultMessage: string): Promise<never> {\n const { message, code } = await parseApiError(response, defaultMessage);\n throw new ApiError(message, response.status, code);\n}\n","import type { ZodType } from 'zod';\nimport { throwApiError } from '@/api-error.js';\n\nexport { ApiError } from '@/api-error.js';\n\nexport interface ApiClientConfig {\n baseUrl: string;\n getHeaders: () => Record<string, string>;\n}\n\n/** Base class for API clients with shared HTTP utilities */\nexport abstract class BaseApiClient {\n protected readonly config: ApiClientConfig;\n\n constructor(config: ApiClientConfig) {\n this.config = config;\n }\n\n protected async httpGet<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPost<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'POST',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPatch<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'PATCH',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpDelete<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'DELETE',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n}\n","import { z } from 'zod';\n\n/** Agent format - interactive (chat) or worker (background task) */\nexport type AgentFormat = 'interactive' | 'worker';\n\n/** Agent settings */\nexport interface AgentSettings {\n slug: string;\n name: string;\n description?: string;\n format: AgentFormat;\n}\n\n/** Agent prompt */\nexport interface AgentPrompt {\n name: string;\n content: string;\n}\n\n/**\n * Agent summary returned from list endpoint\n */\nexport interface Agent {\n /** Agent slug (human-readable identifier within project) */\n slug: string;\n /** Agent ID - use this for API calls */\n id: string;\n name: string;\n description: string | null;\n format: AgentFormat;\n createdAt: string;\n updatedAt: string;\n projectId: string;\n}\n\n/**\n * Full agent definition returned from get endpoint\n */\nexport interface AgentDefinition {\n settings: AgentSettings;\n protocol: string;\n prompts: AgentPrompt[];\n /** Agent ID - use this for API calls like createSession */\n id: string;\n}\n\n// Schemas\n\nexport const agentFormatSchema = z.enum(['interactive', 'worker']);\n\nconst agentSettingsSchema = z.object({\n slug: z.string(),\n name: z.string(),\n description: z.string().optional(),\n format: agentFormatSchema,\n});\n\nconst agentPromptSchema = z.object({\n name: z.string(),\n content: z.string(),\n});\n\nexport const agentSchema = z.object({\n slug: z.string(),\n id: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n format: agentFormatSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n projectId: z.string(),\n});\n\nexport const agentsResponseSchema = z.object({\n agents: z.array(agentSchema),\n});\n\nexport const agentDefinitionSchema = z.object({\n settings: agentSettingsSchema,\n protocol: z.string(),\n prompts: z.array(agentPromptSchema),\n id: z.string(),\n});\n","import { BaseApiClient } from '@/base-api-client.js';\nimport {\n agentsResponseSchema,\n agentDefinitionSchema,\n type Agent,\n type AgentDefinition,\n} from '@/agent-types.js';\n\n/**\n * API for listing and retrieving agent definitions.\n *\n * Note: Agent management (create, update, sync) should be done via the @octavus/cli package.\n * This API uses agent IDs only - use CLI for slug-based operations.\n */\nexport class AgentsApi extends BaseApiClient {\n /** List all agents in the project */\n async list(): Promise<Agent[]> {\n const response = await this.httpGet('/api/agents', agentsResponseSchema);\n return response.agents;\n }\n\n /** Get a single agent by ID */\n async get(agentId: string): Promise<AgentDefinition> {\n return await this.httpGet(`/api/agents/${agentId}`, agentDefinitionSchema);\n }\n}\n","import { z } from 'zod';\nimport {\n chatMessageSchema,\n uiMessageSchema,\n type ChatMessage,\n type ToolProvider,\n type ToolHandlers,\n type ToolResult,\n type UIMessage,\n} from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { throwApiError } from '@/api-error.js';\nimport { AgentSession } from '@/session.js';\nimport type { Resource } from '@/resource.js';\n\nconst createSessionResponseSchema = z.object({\n sessionId: z.string(),\n});\n\nconst sessionStateSchema = z.object({\n id: z.string(),\n agentId: z.string(),\n input: z.record(z.string(), z.unknown()),\n variables: z.record(z.string(), z.unknown()),\n resources: z.record(z.string(), z.unknown()),\n messages: z.array(chatMessageSchema),\n status: z.literal('active').optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\nconst uiSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n messages: z.array(uiMessageSchema),\n status: z.literal('active').optional(),\n});\n\nconst expiredSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n status: z.literal('expired'),\n createdAt: z.string(),\n});\n\nconst restoreSessionResponseSchema = z.object({\n sessionId: z.string(),\n restored: z.boolean(),\n});\n\nconst clearSessionResponseSchema = z.object({\n sessionId: z.string(),\n cleared: z.boolean(),\n});\n\n/** Session status indicating whether it's active or expired */\nexport type SessionStatus = 'active' | 'expired';\n\nexport interface SessionState {\n id: string;\n agentId: string;\n input: Record<string, unknown>;\n variables: Record<string, unknown>;\n resources: Record<string, unknown>;\n messages: ChatMessage[];\n status?: 'active';\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface UISessionState {\n sessionId: string;\n agentId: string;\n messages: UIMessage[];\n status?: 'active';\n}\n\nexport interface ExpiredSessionState {\n sessionId: string;\n agentId: string;\n status: 'expired';\n createdAt: string;\n}\n\nexport interface RestoreSessionResult {\n sessionId: string;\n /** True if session was restored from messages, false if already active */\n restored: boolean;\n}\n\nexport interface ClearSessionResult {\n sessionId: string;\n cleared: boolean;\n}\n\nexport interface SessionAttachOptions {\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Computer capability provider (browser, filesystem, shell via MCP). */\n computer?: ToolProvider;\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/** API for managing agent sessions */\nexport class AgentSessionsApi extends BaseApiClient {\n /** Create a new session for an agent */\n async create(agentId: string, input?: Record<string, unknown>): Promise<string> {\n const response = await this.httpPost(\n '/api/agent-sessions',\n { agentId, input },\n createSessionResponseSchema,\n );\n return response.sessionId;\n }\n\n /**\n * Get full session state (for internal/debug use)\n * Note: Contains all messages including hidden content\n *\n * Returns SessionState for active sessions, ExpiredSessionState for expired sessions.\n * Check `status` field to determine which type was returned.\n */\n async get(sessionId: string): Promise<SessionState | ExpiredSessionState> {\n const response = await fetch(`${this.config.baseUrl}/api/agent-sessions/${sessionId}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return sessionStateSchema.parse(data);\n }\n\n /**\n * Get UI-ready session messages (for client display)\n * Returns only visible messages with hidden content filtered out.\n *\n * For expired sessions, returns status: 'expired' without messages.\n * Use restore() to restore from stored messages before continuing.\n */\n async getMessages(sessionId: string): Promise<UISessionState | ExpiredSessionState> {\n const response = await fetch(\n `${this.config.baseUrl}/api/agent-sessions/${sessionId}?format=ui`,\n {\n method: 'GET',\n headers: this.config.getHeaders(),\n },\n );\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return uiSessionResponseSchema.parse(data);\n }\n\n /**\n * Restore an expired session from stored messages.\n *\n * Use this to restore a session after its state has expired.\n * The consumer should have stored the UIMessage[] array from previous interactions.\n *\n * @param sessionId - The session ID to restore\n * @param messages - Previously stored UIMessage[] array\n * @param input - Optional session input for system prompt interpolation (same as create)\n * @returns { sessionId, restored: true } if restored, { sessionId, restored: false } if already active\n */\n async restore(\n sessionId: string,\n messages: UIMessage[],\n input?: Record<string, unknown>,\n ): Promise<RestoreSessionResult> {\n return await this.httpPost(\n `/api/agent-sessions/${sessionId}/restore`,\n { messages, input },\n restoreSessionResponseSchema,\n );\n }\n\n /**\n * Clear session state from the server.\n * The session will transition to 'expired' status and can be restored with restore().\n * Idempotent: succeeds even if state was already cleared/expired.\n */\n async clear(sessionId: string): Promise<ClearSessionResult> {\n return await this.httpDelete(`/api/agent-sessions/${sessionId}`, clearSessionResponseSchema);\n }\n\n /** Attach to an existing session for triggering events */\n attach(sessionId: string, options: SessionAttachOptions = {}): AgentSession {\n const computerHandlers = options.computer?.toolHandlers() ?? {};\n const mergedTools = { ...computerHandlers, ...options.tools };\n return new AgentSession({\n sessionId,\n config: this.config,\n tools: mergedTools,\n resources: options.resources,\n additionalToolSchemas: options.computer?.toolSchemas(),\n onToolResults: options.onToolResults,\n rejectClientToolCalls: options.rejectClientToolCalls,\n });\n }\n}\n","import {\n createInternalErrorEvent,\n type StreamEvent,\n type ToolHandlers,\n type ToolResult,\n type ToolSchema,\n} from '@octavus/core';\nimport type { ApiClientConfig } from '@/base-api-client.js';\nimport type { Resource } from '@/resource.js';\nimport { executeStream } from '@/streaming.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new trigger execution */\nexport interface TriggerRequest {\n type: 'trigger';\n triggerName: string;\n input?: Record<string, unknown>;\n /** ID of the last message to keep. Messages after this are removed before execution. `null` = truncate all. */\n rollbackAfterMessageId?: string | null;\n}\n\n/** Continue execution after client-side tool handling */\nexport interface ContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by the session */\nexport type SessionRequest = TriggerRequest | ContinueRequest;\n\n/** Stop message to abort in-flight requests */\nexport interface StopMessage {\n type: 'stop';\n}\n\n/** All socket protocol messages (trigger, continue, stop) */\nexport type SocketMessage = TriggerRequest | ContinueRequest | StopMessage;\n\n// =============================================================================\n// Socket Message Handler Types\n// =============================================================================\n\n/** Handlers for socket message streaming */\nexport interface SocketMessageHandlers {\n /** Called for each stream event */\n onEvent: (event: StreamEvent) => void;\n /** Called after streaming completes (not called if aborted) */\n onFinish?: () => void | Promise<void>;\n}\n\nconst SSE_HEARTBEAT_INTERVAL_MS = 15_000;\n\n/**\n * Converts an async iterable of stream events to an SSE-formatted ReadableStream.\n * Use this when you need to return an SSE response (e.g., HTTP endpoints).\n *\n * @example\n * ```typescript\n * const events = session.trigger('user-message', input);\n * return new Response(toSSEStream(events), {\n * headers: { 'Content-Type': 'text/event-stream' },\n * });\n * ```\n */\nexport function toSSEStream(events: AsyncIterable<StreamEvent>): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const heartbeatBytes = encoder.encode(': heartbeat\\n\\n');\n\n return new ReadableStream({\n async start(controller) {\n const heartbeat = setInterval(() => {\n try {\n controller.enqueue(heartbeatBytes);\n } catch {\n clearInterval(heartbeat);\n }\n }, SSE_HEARTBEAT_INTERVAL_MS);\n\n try {\n for await (const event of events) {\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\\n\\n`));\n }\n controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));\n controller.close();\n } catch (err) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}\\n\\n`));\n controller.close();\n } finally {\n clearInterval(heartbeat);\n }\n },\n });\n}\n\nexport interface SessionConfig {\n sessionId: string;\n config: ApiClientConfig;\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Tool schemas to send to the platform on the first trigger (device MCP tools, etc.) */\n additionalToolSchemas?: ToolSchema[];\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Options for trigger execution.\n */\nexport interface TriggerOptions {\n /** Abort signal to cancel the trigger execution */\n signal?: AbortSignal;\n}\n\n/** Handles streaming and tool continuation for agent sessions */\nexport class AgentSession {\n private sessionId: string;\n private config: ApiClientConfig;\n private toolHandlers: ToolHandlers;\n private resourceMap: Map<string, Resource>;\n private additionalToolSchemas: ToolSchema[] | undefined;\n private additionalToolSchemasSent = false;\n private socketAbortController: AbortController | null = null;\n private onToolResults?: (results: ToolResult[]) => Promise<void>;\n private rejectClientToolCalls: boolean;\n\n constructor(sessionConfig: SessionConfig) {\n this.sessionId = sessionConfig.sessionId;\n this.config = sessionConfig.config;\n this.toolHandlers = sessionConfig.tools ?? {};\n this.additionalToolSchemas = sessionConfig.additionalToolSchemas;\n this.onToolResults = sessionConfig.onToolResults;\n this.rejectClientToolCalls = sessionConfig.rejectClientToolCalls ?? false;\n this.resourceMap = new Map();\n\n for (const resource of sessionConfig.resources ?? []) {\n this.resourceMap.set(resource.name, resource);\n }\n }\n\n /**\n * Execute a session request and stream the response.\n *\n * This is the unified method that handles both triggers and continuations.\n * Use this when you want to pass through requests from the client directly.\n *\n * @param request - The request (check `request.type` for the kind)\n * @param options - Optional configuration including abort signal\n *\n * @example HTTP route (simple passthrough)\n * ```typescript\n * const events = session.execute(body, { signal: request.signal });\n * return new Response(toSSEStream(events));\n * ```\n *\n * @example WebSocket handler\n * ```typescript\n * socket.on('message', (data) => {\n * const events = session.execute(data);\n * for await (const event of events) {\n * socket.send(JSON.stringify(event));\n * }\n * });\n * ```\n */\n async *execute(request: SessionRequest, options?: TriggerOptions): AsyncGenerator<StreamEvent> {\n if (request.type === 'continue') {\n yield* this.executeStream(\n { executionId: request.executionId, toolResults: request.toolResults },\n options?.signal,\n );\n } else {\n yield* this.executeStream(\n {\n triggerName: request.triggerName,\n input: request.input,\n rollbackAfterMessageId: request.rollbackAfterMessageId,\n },\n options?.signal,\n );\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n /**\n * Handle a WebSocket protocol message (trigger, continue, or stop).\n * Manages abort controller lifecycle internally.\n *\n * @example\n * ```typescript\n * conn.on('data', (raw) => {\n * session.handleSocketMessage(JSON.parse(raw), {\n * onEvent: (event) => conn.write(JSON.stringify(event)),\n * onFinish: async () => {\n * // Fetch messages and persist to your database for restoration\n * },\n * });\n * });\n * ```\n */\n async handleSocketMessage(\n message: SocketMessage,\n handlers: SocketMessageHandlers,\n ): Promise<void> {\n if (message.type === 'stop') {\n this.socketAbortController?.abort();\n return;\n }\n\n this.socketAbortController?.abort();\n this.socketAbortController = new AbortController();\n\n const localController = this.socketAbortController;\n\n try {\n const events = this.execute(message, { signal: localController.signal });\n\n for await (const event of events) {\n if (localController.signal.aborted) break;\n handlers.onEvent(event);\n }\n\n if (!localController.signal.aborted && handlers.onFinish) {\n await handlers.onFinish();\n }\n } catch (err) {\n if (!localController.signal.aborted) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n handlers.onEvent(errorEvent);\n }\n }\n }\n\n private async *executeStream(\n payload: {\n triggerName?: string;\n input?: Record<string, unknown>;\n executionId?: string;\n toolResults?: ToolResult[];\n rollbackAfterMessageId?: string | null;\n },\n signal?: AbortSignal,\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n toolHandlers: this.toolHandlers,\n url: `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,\n buildBody: ({ executionId, toolResults }) => {\n const body: Record<string, unknown> = {};\n if (payload.triggerName !== undefined) body.triggerName = payload.triggerName;\n if (payload.input !== undefined) body.input = payload.input;\n if (payload.rollbackAfterMessageId !== undefined)\n body.rollbackAfterMessageId = payload.rollbackAfterMessageId;\n if (executionId !== undefined) body.executionId = executionId;\n if (toolResults !== undefined) body.toolResults = toolResults;\n if (!this.additionalToolSchemasSent && (this.additionalToolSchemas?.length ?? 0) > 0) {\n body.additionalToolSchemas = this.additionalToolSchemas;\n this.additionalToolSchemasSent = true;\n }\n return body;\n },\n onResourceUpdate: (name, value) => this.handleResourceUpdate(name, value),\n onToolResults: this.onToolResults,\n rejectClientToolCalls: this.rejectClientToolCalls,\n errorContext: 'Failed to trigger',\n },\n { executionId: payload.executionId, toolResults: payload.toolResults },\n signal,\n );\n }\n\n private handleResourceUpdate(name: string, value: unknown): void {\n const resource = this.resourceMap.get(name);\n if (resource) {\n void resource.onUpdate(value);\n }\n }\n}\n","import {\n safeParseStreamEvent,\n isAbortError,\n createInternalErrorEvent,\n createApiErrorEvent,\n type StreamEvent,\n type ToolHandlers,\n type PendingToolCall,\n type ToolResult,\n} from '@octavus/core';\nimport { parseApiError } from '@/api-error.js';\nimport type { ApiClientConfig } from '@/base-api-client.js';\n\n/**\n * Configuration for streaming execution.\n */\nexport interface StreamExecutionConfig {\n /** API client config with baseUrl and headers */\n config: ApiClientConfig;\n /** Tool handlers for server-side execution */\n toolHandlers: ToolHandlers;\n /** Full URL to make the request to */\n url: string;\n /** Build the request body for this execution */\n buildBody: (state: {\n executionId?: string;\n toolResults?: ToolResult[];\n }) => Record<string, unknown>;\n /** Called when a resource-update event is received (optional) */\n onResourceUpdate?: (name: string, value: unknown) => void;\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** Error message prefix for API errors */\n errorContext?: string;\n /**\n * When true, tool calls without a registered handler return an error result\n * instead of being emitted as client-tool-request events.\n * Use for server-only execution environments (e.g., OctoAgents) that have\n * no client-side tool executor.\n */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Initial payload for starting an execution stream.\n */\nexport interface StreamExecutionPayload {\n /** Initial execution ID (for continuation) */\n executionId?: string;\n /** Initial tool results (for continuation) */\n toolResults?: ToolResult[];\n}\n\n/**\n * Executes a streaming request with tool continuation support.\n *\n * This is the shared implementation for both interactive sessions and workers.\n * It handles:\n * - SSE stream parsing\n * - Abort signal handling\n * - Tool-request interception and server/client splitting\n * - Automatic continuation for server-handled tools\n * - Client-tool-request emission for client-handled tools\n */\nexport async function* executeStream(\n config: StreamExecutionConfig,\n payload: StreamExecutionPayload,\n signal?: AbortSignal,\n): AsyncGenerator<StreamEvent> {\n let toolResults = payload.toolResults;\n let executionId = payload.executionId;\n let continueLoop = true;\n\n while (continueLoop) {\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n const body = config.buildBody({ executionId, toolResults });\n\n let response: Response;\n try {\n response = await fetch(config.url, {\n method: 'POST',\n headers: config.config.getHeaders(),\n body: JSON.stringify(body),\n signal,\n });\n } catch (err) {\n if (isAbortError(err)) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n if (!response.ok) {\n const { message } = await parseApiError(response, config.errorContext ?? 'Request failed');\n yield createApiErrorEvent(response.status, message);\n return;\n }\n\n if (!response.body) {\n yield createInternalErrorEvent('Response body is not readable');\n return;\n }\n\n toolResults = undefined;\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let pendingToolCalls: PendingToolCall[] | null = null;\n\n let streamDone = false;\n while (!streamDone) {\n if (signal?.aborted) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n let readResult: ReadableStreamReadResult<Uint8Array>;\n try {\n readResult = await reader.read();\n } catch (err) {\n if (isAbortError(err)) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n const { done, value } = readResult;\n\n if (done) {\n streamDone = true;\n continue;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const parsed = safeParseStreamEvent(JSON.parse(line.slice(6)));\n if (!parsed.success) {\n continue;\n }\n const event = parsed.data;\n\n if (event.type === 'start' && event.executionId) {\n executionId = event.executionId;\n }\n\n if (event.type === 'tool-request') {\n pendingToolCalls = event.toolCalls;\n continue;\n }\n\n if (event.type === 'finish') {\n if (event.finishReason === 'tool-calls' && pendingToolCalls) {\n continue;\n }\n yield event;\n continueLoop = false;\n continue;\n }\n\n if (event.type === 'resource-update' && config.onResourceUpdate) {\n config.onResourceUpdate(event.name, event.value);\n }\n\n yield event;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n if (pendingToolCalls && pendingToolCalls.length > 0) {\n const serverTools = pendingToolCalls.filter((tc) => config.toolHandlers[tc.toolName]);\n const clientTools = pendingToolCalls.filter((tc) => !config.toolHandlers[tc.toolName]);\n\n const serverResults = await Promise.all(\n serverTools.map(async (tc): Promise<ToolResult> => {\n const handler = config.toolHandlers[tc.toolName]!;\n try {\n const result = await handler(tc.args);\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n result,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n } catch (err) {\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: err instanceof Error ? err.message : 'Tool execution failed',\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n }\n }),\n );\n\n if (config.onToolResults && serverResults.length > 0) {\n await config.onToolResults(serverResults);\n }\n\n for (const tr of serverResults) {\n if (tr.error) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error };\n } else {\n yield { type: 'tool-output-available', toolCallId: tr.toolCallId, output: tr.result };\n }\n }\n\n if (clientTools.length > 0) {\n if (config.rejectClientToolCalls) {\n const rejectedResults: ToolResult[] = clientTools.map((tc) => ({\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: `Tool \"${tc.toolName}\" is not available. No handler is registered for this tool.`,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n }));\n for (const tr of rejectedResults) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error! };\n }\n toolResults = [...serverResults, ...rejectedResults];\n } else {\n if (!executionId) {\n yield createInternalErrorEvent('Missing executionId for client-tool-request');\n return;\n }\n yield {\n type: 'client-tool-request',\n executionId,\n toolCalls: clientTools,\n serverToolResults: serverResults.length > 0 ? serverResults : undefined,\n };\n yield { type: 'finish', finishReason: 'client-tool-calls', executionId };\n continueLoop = false;\n }\n } else {\n toolResults = serverResults;\n }\n } else {\n continueLoop = false;\n }\n }\n}\n","import { z } from 'zod';\nimport { BaseApiClient } from '@/base-api-client.js';\n\n// =============================================================================\n// Schemas\n// =============================================================================\n\n/**\n * Schema for a single file upload request\n */\nexport const fileUploadRequestSchema = z.object({\n filename: z.string().min(1).max(255),\n mediaType: z.string().min(1),\n size: z.number().int().positive(),\n});\n\n/**\n * Schema for a single file upload response\n */\nexport const fileUploadInfoSchema = z.object({\n /** File ID to reference in messages */\n id: z.string(),\n /** Presigned PUT URL for uploading to S3 */\n uploadUrl: z.url(),\n /** Presigned GET URL for downloading after upload */\n downloadUrl: z.url(),\n});\n\n/**\n * Schema for the upload URLs response\n */\nexport const uploadUrlsResponseSchema = z.object({\n files: z.array(fileUploadInfoSchema),\n});\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type FileUploadRequest = z.infer<typeof fileUploadRequestSchema>;\nexport type FileUploadInfo = z.infer<typeof fileUploadInfoSchema>;\nexport type UploadUrlsResponse = z.infer<typeof uploadUrlsResponseSchema>;\n\n// =============================================================================\n// API\n// =============================================================================\n\n/**\n * API for file operations.\n *\n * Provides methods to generate presigned URLs for file uploads.\n * Files are uploaded directly to S3, not through the platform.\n *\n * @example\n * ```typescript\n * // Get upload URLs\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'image.png', mediaType: 'image/png', size: 12345 }\n * ]);\n *\n * // Upload directly to S3\n * await fetch(files[0].uploadUrl, {\n * method: 'PUT',\n * body: imageFile,\n * headers: { 'Content-Type': 'image/png' }\n * });\n *\n * // Use downloadUrl as FileReference in trigger input\n * ```\n */\nexport class FilesApi extends BaseApiClient {\n /**\n * Get presigned URLs for uploading files to a session.\n *\n * Returns upload URLs (PUT) and download URLs (GET) for each file.\n * Upload URLs expire in 15 minutes, download URLs match session TTL (24 hours).\n *\n * @param sessionId - The session ID to associate files with\n * @param files - Array of file metadata (filename, mediaType, size)\n * @returns Upload info with presigned URLs for each file\n *\n * @throws ApiError if session doesn't exist or validation fails\n *\n * @example\n * ```typescript\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'photo.jpg', mediaType: 'image/jpeg', size: 102400 },\n * { filename: 'doc.pdf', mediaType: 'application/pdf', size: 204800 },\n * ]);\n *\n * // files[0].id - Use in FileReference\n * // files[0].uploadUrl - PUT to this URL\n * // files[0].downloadUrl - Use as FileReference.url\n * ```\n */\n async getUploadUrls(sessionId: string, files: FileUploadRequest[]): Promise<UploadUrlsResponse> {\n return await this.httpPost(\n '/api/files/upload-urls',\n { sessionId, files },\n uploadUrlsResponseSchema,\n );\n }\n}\n","/** Error thrown when a worker execution fails */\nexport class WorkerError extends Error {\n constructor(\n message: string,\n /** Session ID if the worker started before failing (for debugging URLs) */\n public readonly sessionId?: string,\n ) {\n super(message);\n this.name = 'WorkerError';\n }\n}\n","import type { StreamEvent, ToolHandlers, ToolResult } from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { executeStream } from '@/streaming.js';\nimport { WorkerError } from '@/worker-error.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new worker execution */\nexport interface WorkerStartRequest {\n type: 'start';\n input: Record<string, unknown>;\n}\n\n/** Continue execution after client-side tool handling */\nexport interface WorkerContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by workers */\nexport type WorkerRequest = WorkerStartRequest | WorkerContinueRequest;\n\n// =============================================================================\n// Execution Options & Results\n// =============================================================================\n\n/** Options for worker execution */\nexport interface WorkerExecuteOptions {\n /** Tool handlers for server-side tool execution */\n tools?: ToolHandlers;\n /** Abort signal to cancel the execution */\n signal?: AbortSignal;\n}\n\n/** Result from a non-streaming worker execution via `generate()` */\nexport interface WorkerGenerateResult {\n /** The worker's output value */\n output: unknown;\n /** Session ID for the worker execution (usable for debugging/session URLs) */\n sessionId: string;\n}\n\n// =============================================================================\n// Workers API\n// =============================================================================\n\n/** API for executing worker agents */\nexport class WorkersApi extends BaseApiClient {\n /**\n * Execute a worker agent and stream the response.\n *\n * Worker agents execute steps sequentially and return an output value.\n * Unlike interactive sessions, workers don't maintain persistent state.\n *\n * The execution handles the tool continuation pattern automatically:\n * - Server tools (with handlers provided) are executed automatically\n * - Client tools (without handlers) emit a client-tool-request event\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example Basic execution\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' });\n * for await (const event of events) {\n * if (event.type === 'worker-start') {\n * console.log(`Worker ${event.workerSlug} started (${event.workerId})`);\n * }\n * if (event.type === 'worker-result') {\n * if (event.error) {\n * console.error('Worker failed:', event.error);\n * } else {\n * console.log('Output:', event.output);\n * }\n * }\n * }\n * ```\n *\n * @example With tool handlers\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' }, {\n * tools: {\n * 'web-search': async (args) => {\n * return await searchWeb(args.query);\n * },\n * },\n * });\n * ```\n */\n async *execute(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n toolHandlers: options.tools ?? {},\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId, toolResults }) =>\n !executionId ? { type: 'start', input } : { type: 'continue', executionId, toolResults },\n errorContext: 'Failed to execute worker',\n },\n {},\n options.signal,\n );\n }\n\n /**\n * Execute a worker agent and return the final output.\n *\n * Non-streaming equivalent of `execute()` — runs the worker to completion\n * and returns the output value directly. Use this when you don't need to\n * observe intermediate streaming events.\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns The worker output and session ID\n * @throws {WorkerError} If the worker fails or completes without output\n *\n * @example Basic usage\n * ```typescript\n * const { output, sessionId } = await client.workers.generate(agentId, {\n * TOPIC: 'AI safety',\n * });\n * console.log(output);\n * console.log(`Debug: ${client.baseUrl}/platform/sessions/${sessionId}`);\n * ```\n *\n * @example With timeout\n * ```typescript\n * const { output } = await client.workers.generate(agentId, input, {\n * signal: AbortSignal.timeout(120_000),\n * });\n * ```\n */\n async generate(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): Promise<WorkerGenerateResult> {\n let sessionId: string | undefined;\n\n for await (const event of this.execute(agentId, input, options)) {\n if (event.type === 'start' && event.executionId) {\n sessionId = event.executionId;\n } else if (event.type === 'error') {\n throw new WorkerError(event.message, sessionId);\n } else if (event.type === 'worker-result') {\n if (event.error) {\n throw new WorkerError(event.error, sessionId ?? event.workerId);\n }\n return {\n output: event.output,\n sessionId: sessionId ?? event.workerId,\n };\n }\n }\n\n throw new WorkerError('Worker completed without producing a result', sessionId);\n }\n\n /**\n * Continue a worker execution after client-side tool handling.\n *\n * Use this when your worker has tools without server-side handlers.\n * The execution returns a client-tool-request event with an executionId.\n * Execute the tools client-side, then call this method to continue.\n *\n * @param agentId - The worker agent ID\n * @param executionId - The execution ID from the client-tool-request event\n * @param toolResults - Results from client-side tool execution\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example\n * ```typescript\n * // Start execution\n * for await (const event of client.workers.execute(agentId, input)) {\n * if (event.type === 'client-tool-request') {\n * // Execute tools client-side\n * const results = await executeToolsClientSide(event.toolCalls);\n * // Continue execution\n * for await (const ev of client.workers.continue(agentId, event.executionId, results)) {\n * // Handle remaining events\n * }\n * }\n * }\n * ```\n */\n async *continue(\n agentId: string,\n executionId: string,\n toolResults: ToolResult[],\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n toolHandlers: options.tools ?? {},\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId: execId, toolResults: results }) => ({\n type: 'continue',\n executionId: execId ?? executionId,\n toolResults: results ?? toolResults,\n }),\n errorContext: 'Failed to continue worker',\n },\n { executionId, toolResults },\n options.signal,\n );\n }\n}\n","import type { ApiClientConfig } from '@/base-api-client.js';\nimport { AgentsApi } from '@/agents.js';\nimport { AgentSessionsApi } from '@/agent-sessions.js';\nimport { FilesApi } from '@/files.js';\nimport { WorkersApi } from '@/workers.js';\n\nexport interface OctavusClientConfig {\n baseUrl: string;\n apiKey?: string;\n /** Enable model request tracing to capture full payloads sent to providers (default: false) */\n traceModelRequests?: boolean;\n}\n\n/** Client for interacting with the Octavus platform API */\nexport class OctavusClient {\n readonly agents: AgentsApi;\n readonly agentSessions: AgentSessionsApi;\n readonly files: FilesApi;\n readonly workers: WorkersApi;\n readonly baseUrl: string;\n private readonly apiKey?: string;\n private readonly traceModelRequests: boolean;\n\n constructor(config: OctavusClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.traceModelRequests = config.traceModelRequests ?? false;\n\n const apiConfig: ApiClientConfig = {\n baseUrl: this.baseUrl,\n getHeaders: () => this.getHeaders(),\n };\n\n this.agents = new AgentsApi(apiConfig);\n this.agentSessions = new AgentSessionsApi(apiConfig);\n this.files = new FilesApi(apiConfig);\n this.workers = new WorkersApi(apiConfig);\n }\n\n getHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (this.apiKey) {\n headers.Authorization = `Bearer ${this.apiKey}`;\n }\n\n if (this.traceModelRequests) {\n headers['X-Octavus-Trace'] = 'true';\n }\n\n return headers;\n }\n}\n","/**\n * Base class for agent-managed resources.\n * Extend this class to define how each resource should be persisted when the agent updates it.\n */\nexport abstract class Resource {\n /** The resource name as defined in the agent protocol */\n abstract readonly name: string;\n\n /** Called when the agent updates this resource */\n abstract onUpdate(value: unknown): Promise<void> | void;\n}\n","import { generateId, type ToolResult, type FileReference } from '@octavus/core';\nimport type { FilesApi, FileUploadRequest } from '@/files.js';\n\ninterface ImagePart {\n type: 'image';\n data: string;\n mimeType?: string;\n}\n\nconst IMAGE_EXTENSIONS: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/webp': 'webp',\n 'image/gif': 'gif',\n 'image/svg+xml': 'svg',\n};\n\nfunction getExtensionFromMediaType(mediaType: string): string {\n return IMAGE_EXTENSIONS[mediaType] ?? 'png';\n}\n\nfunction isImagePart(part: unknown): part is ImagePart {\n return (\n typeof part === 'object' &&\n part !== null &&\n (part as Record<string, unknown>).type === 'image' &&\n typeof (part as Record<string, unknown>).data === 'string'\n );\n}\n\nfunction hasImageParts(value: unknown): value is unknown[] {\n return Array.isArray(value) && value.some(isImagePart);\n}\n\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const buffer = new ArrayBuffer(binary.length);\n const view = new Uint8Array(buffer);\n for (let i = 0; i < binary.length; i++) {\n view[i] = binary.charCodeAt(i);\n }\n return buffer;\n}\n\n/**\n * Extract base64 image blobs from tool results, upload them to S3 via\n * presigned URLs, and replace inline data with compact metadata +\n * FileReference entries.\n *\n * Runs at the server-sdk streaming layer so images are uploaded before\n * tool results travel over the network (WebSocket, HTTP continuation).\n */\nexport async function normalizeToolResultImages(\n toolResults: ToolResult[],\n filesApi: FilesApi,\n sessionId: string,\n): Promise<void> {\n for (const toolResult of toolResults) {\n if (toolResult.outputVariable) continue;\n if (!hasImageParts(toolResult.result)) continue;\n\n const parts = toolResult.result;\n const files: FileReference[] = toolResult.files ? [...toolResult.files] : [];\n\n const imageIndices: number[] = [];\n const imageBuffers: ArrayBuffer[] = [];\n const uploadRequests: FileUploadRequest[] = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (!isImagePart(part)) continue;\n\n const buffer = base64ToArrayBuffer(part.data);\n const mimeType = part.mimeType || 'image/png';\n\n imageIndices.push(i);\n imageBuffers.push(buffer);\n uploadRequests.push({\n filename: `image-${generateId()}.${getExtensionFromMediaType(mimeType)}`,\n mediaType: mimeType,\n size: buffer.byteLength,\n });\n }\n\n if (uploadRequests.length === 0) continue;\n\n let uploadInfos: { id: string; uploadUrl: string; downloadUrl: string }[];\n try {\n const response = await filesApi.getUploadUrls(sessionId, uploadRequests);\n uploadInfos = response.files;\n } catch {\n continue;\n }\n\n const uploadResults = await Promise.allSettled(\n uploadInfos.map((info, i) =>\n fetch(info.uploadUrl, {\n method: 'PUT',\n body: imageBuffers[i]!,\n headers: { 'Content-Type': uploadRequests[i]!.mediaType },\n }),\n ),\n );\n\n const summaryParts: unknown[] = [];\n let imageIdx = 0;\n\n for (let i = 0; i < parts.length; i++) {\n if (imageIdx < imageIndices.length && imageIndices[imageIdx] === i) {\n const uploadResult = uploadResults[imageIdx]!;\n const info = uploadInfos[imageIdx]!;\n const request = uploadRequests[imageIdx]!;\n const buf = imageBuffers[imageIdx]!;\n\n if (uploadResult.status === 'fulfilled' && uploadResult.value.ok) {\n files.push({\n id: info.id,\n mediaType: request.mediaType,\n url: info.downloadUrl,\n filename: request.filename,\n size: buf.byteLength,\n });\n\n summaryParts.push({\n type: 'image',\n mediaType: request.mediaType,\n size: buf.byteLength,\n url: info.downloadUrl,\n });\n } else {\n summaryParts.push(parts[i]);\n }\n\n imageIdx += 1;\n } else {\n summaryParts.push(parts[i]);\n }\n }\n\n toolResult.files = files;\n toolResult.result = summaryParts;\n }\n}\n"],"mappings":"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","names":["import_zod","import_zod","import_core","import_core","import_zod","import_core","import_core"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/api-error.ts","../src/base-api-client.ts","../src/agent-types.ts","../src/agents.ts","../src/agent-sessions.ts","../src/session.ts","../src/streaming.ts","../src/files.ts","../src/worker-error.ts","../src/workers.ts","../src/client.ts","../src/resource.ts","../src/normalize-images.ts"],"sourcesContent":["export { OctavusClient, type OctavusClientConfig } from '@/client.js';\nexport { AgentsApi } from '@/agents.js';\nexport {\n AgentSessionsApi,\n type SessionState,\n type UISessionState,\n type ExpiredSessionState,\n type RestoreSessionResult,\n type ClearSessionResult,\n type SessionStatus,\n type SessionAttachOptions,\n} from '@/agent-sessions.js';\nexport {\n FilesApi,\n type FileUploadRequest,\n type FileUploadInfo,\n type UploadUrlsResponse,\n} from '@/files.js';\nexport {\n AgentSession,\n toSSEStream,\n type SessionConfig,\n type TriggerOptions,\n type SessionRequest,\n type TriggerRequest,\n type ContinueRequest,\n type StopMessage,\n type SocketMessage,\n type SocketMessageHandlers,\n} from '@/session.js';\nexport {\n WorkersApi,\n type WorkerStartRequest,\n type WorkerContinueRequest,\n type WorkerRequest,\n type WorkerExecuteOptions,\n type WorkerGenerateResult,\n} from '@/workers.js';\nexport { WorkerError } from '@/worker-error.js';\nexport { Resource } from '@/resource.js';\nexport { ApiError } from '@/api-error.js';\nexport { normalizeToolResultImages } from '@/normalize-images.js';\n\n// Agent types (read-only - use @octavus/cli for agent management)\nexport type {\n AgentFormat,\n AgentSettings,\n AgentPrompt,\n Agent,\n AgentDefinition,\n} from '@/agent-types.js';\n\nexport type * from '@octavus/core';\nexport {\n // Error classes\n AppError,\n NotFoundError,\n ValidationError,\n ConflictError,\n ForbiddenError,\n OctavusError,\n // Error type guards\n isRateLimitError,\n isAuthenticationError,\n isProviderError,\n isToolError,\n isRetryableError,\n isValidationError,\n // Error event helpers\n createErrorEvent,\n errorToStreamEvent,\n createInternalErrorEvent,\n createApiErrorEvent,\n // Utilities\n generateId,\n isAbortError,\n // Thread helpers\n MAIN_THREAD,\n resolveThread,\n isMainThread,\n threadForPart,\n isOtherThread,\n // Type guards\n isFileReference,\n isFileReferenceArray,\n // Safe parse helpers\n safeParseStreamEvent,\n safeParseUIMessage,\n safeParseUIMessages,\n // Skills\n OCTAVUS_SKILL_TOOLS,\n isOctavusSkillTool,\n getSkillSlugFromToolCall,\n} from '@octavus/core';\n","import { z } from 'zod';\n\nconst ApiErrorResponseSchema = z.object({\n error: z.string().optional(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n/**\n * Error thrown when API request fails\n */\nexport class ApiError extends Error {\n constructor(\n message: string,\n public status: number,\n public code?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\ninterface ParsedApiError {\n message: string;\n code?: string;\n}\n\n/**\n * Parse error from API response using Zod\n */\nexport async function parseApiError(\n response: Response,\n defaultMessage: string,\n): Promise<ParsedApiError> {\n const fallbackMessage = `${defaultMessage}: ${response.statusText}`;\n\n try {\n const json: unknown = await response.json();\n const parsed = ApiErrorResponseSchema.safeParse(json);\n\n if (parsed.success) {\n return {\n message: parsed.data.error ?? parsed.data.message ?? fallbackMessage,\n code: parsed.data.code,\n };\n }\n } catch {\n // Use default message\n }\n\n return { message: fallbackMessage };\n}\n\n/**\n * Parse error from API response and throw ApiError\n */\nexport async function throwApiError(response: Response, defaultMessage: string): Promise<never> {\n const { message, code } = await parseApiError(response, defaultMessage);\n throw new ApiError(message, response.status, code);\n}\n","import type { ZodType } from 'zod';\nimport { throwApiError } from '@/api-error.js';\n\nexport { ApiError } from '@/api-error.js';\n\nexport interface ApiClientConfig {\n baseUrl: string;\n getHeaders: () => Record<string, string>;\n}\n\n/** Base class for API clients with shared HTTP utilities */\nexport abstract class BaseApiClient {\n protected readonly config: ApiClientConfig;\n\n constructor(config: ApiClientConfig) {\n this.config = config;\n }\n\n protected async httpGet<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPost<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'POST',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPatch<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'PATCH',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpDelete<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'DELETE',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n}\n","import { z } from 'zod';\n\n/** Agent format - interactive (chat) or worker (background task) */\nexport type AgentFormat = 'interactive' | 'worker';\n\n/** Agent settings */\nexport interface AgentSettings {\n slug: string;\n name: string;\n description?: string;\n format: AgentFormat;\n}\n\n/** Agent prompt */\nexport interface AgentPrompt {\n name: string;\n content: string;\n}\n\n/**\n * Agent summary returned from list endpoint\n */\nexport interface Agent {\n /** Agent slug (human-readable identifier within project) */\n slug: string;\n /** Agent ID - use this for API calls */\n id: string;\n name: string;\n description: string | null;\n format: AgentFormat;\n createdAt: string;\n updatedAt: string;\n projectId: string;\n}\n\n/**\n * Full agent definition returned from get endpoint\n */\nexport interface AgentDefinition {\n settings: AgentSettings;\n protocol: string;\n prompts: AgentPrompt[];\n /** Agent ID - use this for API calls like createSession */\n id: string;\n}\n\n// Schemas\n\nexport const agentFormatSchema = z.enum(['interactive', 'worker']);\n\nconst agentSettingsSchema = z.object({\n slug: z.string(),\n name: z.string(),\n description: z.string().optional(),\n format: agentFormatSchema,\n});\n\nconst agentPromptSchema = z.object({\n name: z.string(),\n content: z.string(),\n});\n\nexport const agentSchema = z.object({\n slug: z.string(),\n id: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n format: agentFormatSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n projectId: z.string(),\n});\n\nexport const agentsResponseSchema = z.object({\n agents: z.array(agentSchema),\n});\n\nexport const agentDefinitionSchema = z.object({\n settings: agentSettingsSchema,\n protocol: z.string(),\n prompts: z.array(agentPromptSchema),\n id: z.string(),\n});\n","import { BaseApiClient } from '@/base-api-client.js';\nimport {\n agentsResponseSchema,\n agentDefinitionSchema,\n type Agent,\n type AgentDefinition,\n} from '@/agent-types.js';\n\n/**\n * API for listing and retrieving agent definitions.\n *\n * Note: Agent management (create, update, sync) should be done via the @octavus/cli package.\n * This API uses agent IDs only - use CLI for slug-based operations.\n */\nexport class AgentsApi extends BaseApiClient {\n /** List all agents in the project */\n async list(): Promise<Agent[]> {\n const response = await this.httpGet('/api/agents', agentsResponseSchema);\n return response.agents;\n }\n\n /** Get a single agent by ID */\n async get(agentId: string): Promise<AgentDefinition> {\n return await this.httpGet(`/api/agents/${agentId}`, agentDefinitionSchema);\n }\n}\n","import { z } from 'zod';\nimport {\n chatMessageSchema,\n uiMessageSchema,\n type ChatMessage,\n type ToolHandlers,\n type ToolResult,\n type UIMessage,\n} from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { throwApiError } from '@/api-error.js';\nimport { AgentSession } from '@/session.js';\nimport type { Resource } from '@/resource.js';\n\nconst createSessionResponseSchema = z.object({\n sessionId: z.string(),\n});\n\nconst sessionStateSchema = z.object({\n id: z.string(),\n agentId: z.string(),\n input: z.record(z.string(), z.unknown()),\n variables: z.record(z.string(), z.unknown()),\n resources: z.record(z.string(), z.unknown()),\n messages: z.array(chatMessageSchema),\n status: z.literal('active').optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\nconst uiSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n messages: z.array(uiMessageSchema),\n status: z.literal('active').optional(),\n});\n\nconst expiredSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n status: z.literal('expired'),\n createdAt: z.string(),\n});\n\nconst restoreSessionResponseSchema = z.object({\n sessionId: z.string(),\n restored: z.boolean(),\n});\n\nconst clearSessionResponseSchema = z.object({\n sessionId: z.string(),\n cleared: z.boolean(),\n});\n\n/** Session status indicating whether it's active or expired */\nexport type SessionStatus = 'active' | 'expired';\n\nexport interface SessionState {\n id: string;\n agentId: string;\n input: Record<string, unknown>;\n variables: Record<string, unknown>;\n resources: Record<string, unknown>;\n messages: ChatMessage[];\n status?: 'active';\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface UISessionState {\n sessionId: string;\n agentId: string;\n messages: UIMessage[];\n status?: 'active';\n}\n\nexport interface ExpiredSessionState {\n sessionId: string;\n agentId: string;\n status: 'expired';\n createdAt: string;\n}\n\nexport interface RestoreSessionResult {\n sessionId: string;\n /** True if session was restored from messages, false if already active */\n restored: boolean;\n}\n\nexport interface ClearSessionResult {\n sessionId: string;\n cleared: boolean;\n}\n\nexport interface SessionAttachOptions {\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/** API for managing agent sessions */\nexport class AgentSessionsApi extends BaseApiClient {\n /** Create a new session for an agent */\n async create(agentId: string, input?: Record<string, unknown>): Promise<string> {\n const response = await this.httpPost(\n '/api/agent-sessions',\n { agentId, input },\n createSessionResponseSchema,\n );\n return response.sessionId;\n }\n\n /**\n * Get full session state (for internal/debug use)\n * Note: Contains all messages including hidden content\n *\n * Returns SessionState for active sessions, ExpiredSessionState for expired sessions.\n * Check `status` field to determine which type was returned.\n */\n async get(sessionId: string): Promise<SessionState | ExpiredSessionState> {\n const response = await fetch(`${this.config.baseUrl}/api/agent-sessions/${sessionId}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return sessionStateSchema.parse(data);\n }\n\n /**\n * Get UI-ready session messages (for client display)\n * Returns only visible messages with hidden content filtered out.\n *\n * For expired sessions, returns status: 'expired' without messages.\n * Use restore() to restore from stored messages before continuing.\n */\n async getMessages(sessionId: string): Promise<UISessionState | ExpiredSessionState> {\n const response = await fetch(\n `${this.config.baseUrl}/api/agent-sessions/${sessionId}?format=ui`,\n {\n method: 'GET',\n headers: this.config.getHeaders(),\n },\n );\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return uiSessionResponseSchema.parse(data);\n }\n\n /**\n * Restore an expired session from stored messages.\n *\n * Use this to restore a session after its state has expired.\n * The consumer should have stored the UIMessage[] array from previous interactions.\n *\n * @param sessionId - The session ID to restore\n * @param messages - Previously stored UIMessage[] array\n * @param input - Optional session input for system prompt interpolation (same as create)\n * @returns { sessionId, restored: true } if restored, { sessionId, restored: false } if already active\n */\n async restore(\n sessionId: string,\n messages: UIMessage[],\n input?: Record<string, unknown>,\n ): Promise<RestoreSessionResult> {\n return await this.httpPost(\n `/api/agent-sessions/${sessionId}/restore`,\n { messages, input },\n restoreSessionResponseSchema,\n );\n }\n\n /**\n * Clear session state from the server.\n * The session will transition to 'expired' status and can be restored with restore().\n * Idempotent: succeeds even if state was already cleared/expired.\n */\n async clear(sessionId: string): Promise<ClearSessionResult> {\n return await this.httpDelete(`/api/agent-sessions/${sessionId}`, clearSessionResponseSchema);\n }\n\n /** Attach to an existing session for triggering events */\n attach(sessionId: string, options: SessionAttachOptions = {}): AgentSession {\n return new AgentSession({\n sessionId,\n config: this.config,\n tools: options.tools,\n resources: options.resources,\n onToolResults: options.onToolResults,\n rejectClientToolCalls: options.rejectClientToolCalls,\n });\n }\n}\n","import {\n createInternalErrorEvent,\n type DynamicTool,\n type StreamEvent,\n type ToolHandlers,\n type ToolProvider,\n type ToolResult,\n type ToolSchema,\n} from '@octavus/core';\nimport type { ApiClientConfig } from '@/base-api-client.js';\nimport type { Resource } from '@/resource.js';\nimport { executeStream } from '@/streaming.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new trigger execution */\nexport interface TriggerRequest {\n type: 'trigger';\n triggerName: string;\n input?: Record<string, unknown>;\n /** ID of the last message to keep. Messages after this are removed before execution. `null` = truncate all. */\n rollbackAfterMessageId?: string | null;\n}\n\n/** Continue execution after client-side tool handling */\nexport interface ContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by the session */\nexport type SessionRequest = TriggerRequest | ContinueRequest;\n\n/** Stop message to abort in-flight requests */\nexport interface StopMessage {\n type: 'stop';\n}\n\n/** All socket protocol messages (trigger, continue, stop) */\nexport type SocketMessage = TriggerRequest | ContinueRequest | StopMessage;\n\n// =============================================================================\n// Socket Message Handler Types\n// =============================================================================\n\n/** Handlers for socket message streaming */\nexport interface SocketMessageHandlers {\n /** Called for each stream event */\n onEvent: (event: StreamEvent) => void;\n /** Called after streaming completes (not called if aborted) */\n onFinish?: () => void | Promise<void>;\n}\n\nconst SSE_HEARTBEAT_INTERVAL_MS = 15_000;\n\n/**\n * Converts an async iterable of stream events to an SSE-formatted ReadableStream.\n * Use this when you need to return an SSE response (e.g., HTTP endpoints).\n *\n * @example\n * ```typescript\n * const events = session.trigger('user-message', input);\n * return new Response(toSSEStream(events), {\n * headers: { 'Content-Type': 'text/event-stream' },\n * });\n * ```\n */\nexport function toSSEStream(events: AsyncIterable<StreamEvent>): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const heartbeatBytes = encoder.encode(': heartbeat\\n\\n');\n\n return new ReadableStream({\n async start(controller) {\n const heartbeat = setInterval(() => {\n try {\n controller.enqueue(heartbeatBytes);\n } catch {\n clearInterval(heartbeat);\n }\n }, SSE_HEARTBEAT_INTERVAL_MS);\n\n try {\n for await (const event of events) {\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\\n\\n`));\n }\n controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));\n controller.close();\n } catch (err) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}\\n\\n`));\n controller.close();\n } finally {\n clearInterval(heartbeat);\n }\n },\n });\n}\n\nfunction resolveDynamicTools(provider: ToolProvider): DynamicTool[] {\n const handlers = provider.toolHandlers();\n return provider\n .toolSchemas()\n .filter((s) => handlers[s.name])\n .map((s) => ({ schema: s, handler: handlers[s.name]! }));\n}\n\nexport interface SessionConfig {\n sessionId: string;\n config: ApiClientConfig;\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Options for trigger execution.\n */\nexport interface TriggerOptions {\n /** Abort signal to cancel the trigger execution */\n signal?: AbortSignal;\n}\n\n/** Handles streaming and tool continuation for agent sessions */\nexport class AgentSession {\n private sessionId: string;\n private config: ApiClientConfig;\n private toolHandlers: ToolHandlers;\n private resourceMap: Map<string, Resource>;\n private dynamicToolSchemas: ToolSchema[] | undefined;\n private dynamicToolNames = new Set<string>();\n private socketAbortController: AbortController | null = null;\n private onToolResults?: (results: ToolResult[]) => Promise<void>;\n private rejectClientToolCalls: boolean;\n\n constructor(sessionConfig: SessionConfig) {\n this.sessionId = sessionConfig.sessionId;\n this.config = sessionConfig.config;\n this.toolHandlers = sessionConfig.tools ?? {};\n this.onToolResults = sessionConfig.onToolResults;\n this.rejectClientToolCalls = sessionConfig.rejectClientToolCalls ?? false;\n this.resourceMap = new Map();\n\n for (const resource of sessionConfig.resources ?? []) {\n this.resourceMap.set(resource.name, resource);\n }\n }\n\n /**\n * Execute a session request and stream the response.\n *\n * This is the unified method that handles both triggers and continuations.\n * Use this when you want to pass through requests from the client directly.\n *\n * @param request - The request (check `request.type` for the kind)\n * @param options - Optional configuration including abort signal\n *\n * @example HTTP route (simple passthrough)\n * ```typescript\n * const events = session.execute(body, { signal: request.signal });\n * return new Response(toSSEStream(events));\n * ```\n *\n * @example WebSocket handler\n * ```typescript\n * socket.on('message', (data) => {\n * const events = session.execute(data);\n * for await (const event of events) {\n * socket.send(JSON.stringify(event));\n * }\n * });\n * ```\n */\n async *execute(request: SessionRequest, options?: TriggerOptions): AsyncGenerator<StreamEvent> {\n if (request.type === 'continue') {\n yield* this.executeStream(\n { executionId: request.executionId, toolResults: request.toolResults },\n options?.signal,\n );\n } else {\n yield* this.executeStream(\n {\n triggerName: request.triggerName,\n input: request.input,\n rollbackAfterMessageId: request.rollbackAfterMessageId,\n },\n options?.signal,\n );\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n /**\n * Set the full list of dynamic tools (schemas + handlers).\n * Replaces any previously set dynamic tools — removed tools are\n * unregistered, new ones are added, and updated schemas are sent\n * to the platform on the next request.\n *\n * Accepts either a `ToolProvider` (e.g. `Computer`) or an explicit\n * `DynamicTool[]` array.\n *\n * Safe to call mid-session: executeStream resolves toolHandlers via\n * a getter on each continuation loop, so new handlers are visible\n * immediately.\n */\n setDynamicTools(source: ToolProvider | DynamicTool[]): void {\n const tools = Array.isArray(source) ? source : resolveDynamicTools(source);\n const newNames = new Set(tools.map((t) => t.schema.name));\n\n const cleaned: ToolHandlers = {};\n for (const [name, handler] of Object.entries(this.toolHandlers)) {\n if (!this.dynamicToolNames.has(name)) {\n cleaned[name] = handler;\n }\n }\n\n for (const tool of tools) {\n cleaned[tool.schema.name] = tool.handler;\n }\n\n this.toolHandlers = cleaned;\n this.dynamicToolNames = newNames;\n this.dynamicToolSchemas = tools.map((t) => t.schema);\n }\n\n /**\n * Handle a WebSocket protocol message (trigger, continue, or stop).\n * Manages abort controller lifecycle internally.\n *\n * @example\n * ```typescript\n * conn.on('data', (raw) => {\n * session.handleSocketMessage(JSON.parse(raw), {\n * onEvent: (event) => conn.write(JSON.stringify(event)),\n * onFinish: async () => {\n * // Fetch messages and persist to your database for restoration\n * },\n * });\n * });\n * ```\n */\n async handleSocketMessage(\n message: SocketMessage,\n handlers: SocketMessageHandlers,\n ): Promise<void> {\n if (message.type === 'stop') {\n this.socketAbortController?.abort();\n return;\n }\n\n this.socketAbortController?.abort();\n this.socketAbortController = new AbortController();\n\n const localController = this.socketAbortController;\n\n try {\n const events = this.execute(message, { signal: localController.signal });\n\n for await (const event of events) {\n if (localController.signal.aborted) break;\n handlers.onEvent(event);\n }\n\n if (!localController.signal.aborted && handlers.onFinish) {\n await handlers.onFinish();\n }\n } catch (err) {\n if (!localController.signal.aborted) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n handlers.onEvent(errorEvent);\n }\n }\n }\n\n private async *executeStream(\n payload: {\n triggerName?: string;\n input?: Record<string, unknown>;\n executionId?: string;\n toolResults?: ToolResult[];\n rollbackAfterMessageId?: string | null;\n },\n signal?: AbortSignal,\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n getToolHandlers: () => this.toolHandlers,\n url: `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,\n buildBody: ({ executionId, toolResults }) => {\n const body: Record<string, unknown> = {};\n if (payload.triggerName !== undefined) body.triggerName = payload.triggerName;\n if (payload.input !== undefined) body.input = payload.input;\n if (payload.rollbackAfterMessageId !== undefined)\n body.rollbackAfterMessageId = payload.rollbackAfterMessageId;\n if (executionId !== undefined) body.executionId = executionId;\n if (toolResults !== undefined) body.toolResults = toolResults;\n if (this.dynamicToolSchemas !== undefined) {\n body.dynamicToolSchemas = this.dynamicToolSchemas;\n }\n return body;\n },\n onResourceUpdate: (name, value) => this.handleResourceUpdate(name, value),\n onToolResults: this.onToolResults,\n rejectClientToolCalls: this.rejectClientToolCalls,\n errorContext: 'Failed to trigger',\n },\n { executionId: payload.executionId, toolResults: payload.toolResults },\n signal,\n );\n }\n\n private handleResourceUpdate(name: string, value: unknown): void {\n const resource = this.resourceMap.get(name);\n if (resource) {\n void resource.onUpdate(value);\n }\n }\n}\n","import {\n safeParseStreamEvent,\n isAbortError,\n createInternalErrorEvent,\n createApiErrorEvent,\n type StreamEvent,\n type ToolHandlers,\n type PendingToolCall,\n type ToolResult,\n} from '@octavus/core';\nimport { parseApiError } from '@/api-error.js';\nimport type { ApiClientConfig } from '@/base-api-client.js';\n\n/**\n * Configuration for streaming execution.\n */\nexport interface StreamExecutionConfig {\n /** API client config with baseUrl and headers */\n config: ApiClientConfig;\n /** Tool handlers for server-side execution. Resolved on each continuation loop. */\n getToolHandlers: () => ToolHandlers;\n /** Full URL to make the request to */\n url: string;\n /** Build the request body for this execution */\n buildBody: (state: {\n executionId?: string;\n toolResults?: ToolResult[];\n }) => Record<string, unknown>;\n /** Called when a resource-update event is received (optional) */\n onResourceUpdate?: (name: string, value: unknown) => void;\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** Error message prefix for API errors */\n errorContext?: string;\n /**\n * When true, tool calls without a registered handler return an error result\n * instead of being emitted as client-tool-request events.\n * Use for server-only execution environments (e.g., OctoAgents) that have\n * no client-side tool executor.\n */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Initial payload for starting an execution stream.\n */\nexport interface StreamExecutionPayload {\n /** Initial execution ID (for continuation) */\n executionId?: string;\n /** Initial tool results (for continuation) */\n toolResults?: ToolResult[];\n}\n\n/**\n * Executes a streaming request with tool continuation support.\n *\n * This is the shared implementation for both interactive sessions and workers.\n * It handles:\n * - SSE stream parsing\n * - Abort signal handling\n * - Tool-request interception and server/client splitting\n * - Automatic continuation for server-handled tools\n * - Client-tool-request emission for client-handled tools\n */\nexport async function* executeStream(\n config: StreamExecutionConfig,\n payload: StreamExecutionPayload,\n signal?: AbortSignal,\n): AsyncGenerator<StreamEvent> {\n let toolResults = payload.toolResults;\n let executionId = payload.executionId;\n let continueLoop = true;\n\n while (continueLoop) {\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n const body = config.buildBody({ executionId, toolResults });\n\n let response: Response;\n try {\n response = await fetch(config.url, {\n method: 'POST',\n headers: config.config.getHeaders(),\n body: JSON.stringify(body),\n signal,\n });\n } catch (err) {\n if (isAbortError(err)) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n if (!response.ok) {\n const { message } = await parseApiError(response, config.errorContext ?? 'Request failed');\n yield createApiErrorEvent(response.status, message);\n return;\n }\n\n if (!response.body) {\n yield createInternalErrorEvent('Response body is not readable');\n return;\n }\n\n toolResults = undefined;\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let pendingToolCalls: PendingToolCall[] | null = null;\n\n let streamDone = false;\n while (!streamDone) {\n if (signal?.aborted) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n let readResult: ReadableStreamReadResult<Uint8Array>;\n try {\n readResult = await reader.read();\n } catch (err) {\n if (isAbortError(err)) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n const { done, value } = readResult;\n\n if (done) {\n streamDone = true;\n continue;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const parsed = safeParseStreamEvent(JSON.parse(line.slice(6)));\n if (!parsed.success) {\n continue;\n }\n const event = parsed.data;\n\n if (event.type === 'start' && event.executionId) {\n executionId = event.executionId;\n }\n\n if (event.type === 'tool-request') {\n pendingToolCalls = event.toolCalls;\n continue;\n }\n\n if (event.type === 'finish') {\n if (event.finishReason === 'tool-calls' && pendingToolCalls) {\n continue;\n }\n yield event;\n continueLoop = false;\n continue;\n }\n\n if (event.type === 'resource-update' && config.onResourceUpdate) {\n config.onResourceUpdate(event.name, event.value);\n }\n\n yield event;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n if (pendingToolCalls && pendingToolCalls.length > 0) {\n const toolHandlers = config.getToolHandlers();\n const serverTools = pendingToolCalls.filter((tc) => toolHandlers[tc.toolName]);\n const clientTools = pendingToolCalls.filter((tc) => !toolHandlers[tc.toolName]);\n\n const serverResults = await Promise.all(\n serverTools.map(async (tc): Promise<ToolResult> => {\n const handler = toolHandlers[tc.toolName]!;\n try {\n const result = await handler(tc.args);\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n result,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n } catch (err) {\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: err instanceof Error ? err.message : 'Tool execution failed',\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n }\n }),\n );\n\n if (config.onToolResults && serverResults.length > 0) {\n await config.onToolResults(serverResults);\n }\n\n for (const tr of serverResults) {\n if (tr.error) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error };\n } else {\n yield { type: 'tool-output-available', toolCallId: tr.toolCallId, output: tr.result };\n }\n }\n\n if (clientTools.length > 0) {\n if (config.rejectClientToolCalls) {\n const rejectedResults: ToolResult[] = clientTools.map((tc) => ({\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: `Tool \"${tc.toolName}\" is not available. No handler is registered for this tool.`,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n }));\n for (const tr of rejectedResults) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error! };\n }\n toolResults = [...serverResults, ...rejectedResults];\n } else {\n if (!executionId) {\n yield createInternalErrorEvent('Missing executionId for client-tool-request');\n return;\n }\n yield {\n type: 'client-tool-request',\n executionId,\n toolCalls: clientTools,\n serverToolResults: serverResults.length > 0 ? serverResults : undefined,\n };\n yield { type: 'finish', finishReason: 'client-tool-calls', executionId };\n continueLoop = false;\n }\n } else {\n toolResults = serverResults;\n }\n } else {\n continueLoop = false;\n }\n }\n}\n","import { z } from 'zod';\nimport { BaseApiClient } from '@/base-api-client.js';\n\n// =============================================================================\n// Schemas\n// =============================================================================\n\n/**\n * Schema for a single file upload request\n */\nexport const fileUploadRequestSchema = z.object({\n filename: z.string().min(1).max(255),\n mediaType: z.string().min(1),\n size: z.number().int().positive(),\n});\n\n/**\n * Schema for a single file upload response\n */\nexport const fileUploadInfoSchema = z.object({\n /** File ID to reference in messages */\n id: z.string(),\n /** Presigned PUT URL for uploading to S3 */\n uploadUrl: z.url(),\n /** Presigned GET URL for downloading after upload */\n downloadUrl: z.url(),\n});\n\n/**\n * Schema for the upload URLs response\n */\nexport const uploadUrlsResponseSchema = z.object({\n files: z.array(fileUploadInfoSchema),\n});\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type FileUploadRequest = z.infer<typeof fileUploadRequestSchema>;\nexport type FileUploadInfo = z.infer<typeof fileUploadInfoSchema>;\nexport type UploadUrlsResponse = z.infer<typeof uploadUrlsResponseSchema>;\n\n// =============================================================================\n// API\n// =============================================================================\n\n/**\n * API for file operations.\n *\n * Provides methods to generate presigned URLs for file uploads.\n * Files are uploaded directly to S3, not through the platform.\n *\n * @example\n * ```typescript\n * // Get upload URLs\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'image.png', mediaType: 'image/png', size: 12345 }\n * ]);\n *\n * // Upload directly to S3\n * await fetch(files[0].uploadUrl, {\n * method: 'PUT',\n * body: imageFile,\n * headers: { 'Content-Type': 'image/png' }\n * });\n *\n * // Use downloadUrl as FileReference in trigger input\n * ```\n */\nexport class FilesApi extends BaseApiClient {\n /**\n * Get presigned URLs for uploading files to a session.\n *\n * Returns upload URLs (PUT) and download URLs (GET) for each file.\n * Upload URLs expire in 15 minutes, download URLs match session TTL (24 hours).\n *\n * @param sessionId - The session ID to associate files with\n * @param files - Array of file metadata (filename, mediaType, size)\n * @returns Upload info with presigned URLs for each file\n *\n * @throws ApiError if session doesn't exist or validation fails\n *\n * @example\n * ```typescript\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'photo.jpg', mediaType: 'image/jpeg', size: 102400 },\n * { filename: 'doc.pdf', mediaType: 'application/pdf', size: 204800 },\n * ]);\n *\n * // files[0].id - Use in FileReference\n * // files[0].uploadUrl - PUT to this URL\n * // files[0].downloadUrl - Use as FileReference.url\n * ```\n */\n async getUploadUrls(sessionId: string, files: FileUploadRequest[]): Promise<UploadUrlsResponse> {\n return await this.httpPost(\n '/api/files/upload-urls',\n { sessionId, files },\n uploadUrlsResponseSchema,\n );\n }\n}\n","/** Error thrown when a worker execution fails */\nexport class WorkerError extends Error {\n constructor(\n message: string,\n /** Session ID if the worker started before failing (for debugging URLs) */\n public readonly sessionId?: string,\n ) {\n super(message);\n this.name = 'WorkerError';\n }\n}\n","import type { StreamEvent, ToolHandlers, ToolResult, ToolSchema } from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { executeStream } from '@/streaming.js';\nimport { WorkerError } from '@/worker-error.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new worker execution */\nexport interface WorkerStartRequest {\n type: 'start';\n input: Record<string, unknown>;\n /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */\n dynamicToolSchemas?: ToolSchema[];\n}\n\n/** Continue execution after client-side tool handling */\nexport interface WorkerContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by workers */\nexport type WorkerRequest = WorkerStartRequest | WorkerContinueRequest;\n\n// =============================================================================\n// Execution Options & Results\n// =============================================================================\n\n/** Options for worker execution */\nexport interface WorkerExecuteOptions {\n /** Tool handlers for server-side tool execution */\n tools?: ToolHandlers;\n /** Abort signal to cancel the execution */\n signal?: AbortSignal;\n /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */\n dynamicToolSchemas?: ToolSchema[];\n}\n\n/** Result from a non-streaming worker execution via `generate()` */\nexport interface WorkerGenerateResult {\n /** The worker's output value */\n output: unknown;\n /** Session ID for the worker execution (usable for debugging/session URLs) */\n sessionId: string;\n}\n\n// =============================================================================\n// Workers API\n// =============================================================================\n\n/** API for executing worker agents */\nexport class WorkersApi extends BaseApiClient {\n /**\n * Execute a worker agent and stream the response.\n *\n * Worker agents execute steps sequentially and return an output value.\n * Unlike interactive sessions, workers don't maintain persistent state.\n *\n * The execution handles the tool continuation pattern automatically:\n * - Server tools (with handlers provided) are executed automatically\n * - Client tools (without handlers) emit a client-tool-request event\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example Basic execution\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' });\n * for await (const event of events) {\n * if (event.type === 'worker-start') {\n * console.log(`Worker ${event.workerSlug} started (${event.workerId})`);\n * }\n * if (event.type === 'worker-result') {\n * if (event.error) {\n * console.error('Worker failed:', event.error);\n * } else {\n * console.log('Output:', event.output);\n * }\n * }\n * }\n * ```\n *\n * @example With tool handlers\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' }, {\n * tools: {\n * 'web-search': async (args) => {\n * return await searchWeb(args.query);\n * },\n * },\n * });\n * ```\n */\n async *execute(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n const tools = options.tools ?? {};\n yield* executeStream(\n {\n config: this.config,\n getToolHandlers: () => tools,\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId, toolResults }) =>\n !executionId\n ? {\n type: 'start',\n input,\n ...(options.dynamicToolSchemas !== undefined && {\n dynamicToolSchemas: options.dynamicToolSchemas,\n }),\n }\n : { type: 'continue', executionId, toolResults },\n errorContext: 'Failed to execute worker',\n },\n {},\n options.signal,\n );\n }\n\n /**\n * Execute a worker agent and return the final output.\n *\n * Non-streaming equivalent of `execute()` — runs the worker to completion\n * and returns the output value directly. Use this when you don't need to\n * observe intermediate streaming events.\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns The worker output and session ID\n * @throws {WorkerError} If the worker fails or completes without output\n *\n * @example Basic usage\n * ```typescript\n * const { output, sessionId } = await client.workers.generate(agentId, {\n * TOPIC: 'AI safety',\n * });\n * console.log(output);\n * console.log(`Debug: ${client.baseUrl}/platform/sessions/${sessionId}`);\n * ```\n *\n * @example With timeout\n * ```typescript\n * const { output } = await client.workers.generate(agentId, input, {\n * signal: AbortSignal.timeout(120_000),\n * });\n * ```\n */\n async generate(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): Promise<WorkerGenerateResult> {\n let sessionId: string | undefined;\n\n for await (const event of this.execute(agentId, input, options)) {\n if (event.type === 'start' && event.executionId) {\n sessionId = event.executionId;\n } else if (event.type === 'error') {\n throw new WorkerError(event.message, sessionId);\n } else if (event.type === 'worker-result') {\n if (event.error) {\n throw new WorkerError(event.error, sessionId ?? event.workerId);\n }\n return {\n output: event.output,\n sessionId: sessionId ?? event.workerId,\n };\n }\n }\n\n throw new WorkerError('Worker completed without producing a result', sessionId);\n }\n\n /**\n * Continue a worker execution after client-side tool handling.\n *\n * Use this when your worker has tools without server-side handlers.\n * The execution returns a client-tool-request event with an executionId.\n * Execute the tools client-side, then call this method to continue.\n *\n * @param agentId - The worker agent ID\n * @param executionId - The execution ID from the client-tool-request event\n * @param toolResults - Results from client-side tool execution\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example\n * ```typescript\n * // Start execution\n * for await (const event of client.workers.execute(agentId, input)) {\n * if (event.type === 'client-tool-request') {\n * // Execute tools client-side\n * const results = await executeToolsClientSide(event.toolCalls);\n * // Continue execution\n * for await (const ev of client.workers.continue(agentId, event.executionId, results)) {\n * // Handle remaining events\n * }\n * }\n * }\n * ```\n */\n async *continue(\n agentId: string,\n executionId: string,\n toolResults: ToolResult[],\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n const tools = options.tools ?? {};\n yield* executeStream(\n {\n config: this.config,\n getToolHandlers: () => tools,\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId: execId, toolResults: results }) => ({\n type: 'continue',\n executionId: execId ?? executionId,\n toolResults: results ?? toolResults,\n }),\n errorContext: 'Failed to continue worker',\n },\n { executionId, toolResults },\n options.signal,\n );\n }\n}\n","import type { ApiClientConfig } from '@/base-api-client.js';\nimport { AgentsApi } from '@/agents.js';\nimport { AgentSessionsApi } from '@/agent-sessions.js';\nimport { FilesApi } from '@/files.js';\nimport { WorkersApi } from '@/workers.js';\n\nexport interface OctavusClientConfig {\n baseUrl: string;\n apiKey?: string;\n /** Enable model request tracing to capture full payloads sent to providers (default: false) */\n traceModelRequests?: boolean;\n}\n\n/** Client for interacting with the Octavus platform API */\nexport class OctavusClient {\n readonly agents: AgentsApi;\n readonly agentSessions: AgentSessionsApi;\n readonly files: FilesApi;\n readonly workers: WorkersApi;\n readonly baseUrl: string;\n private readonly apiKey?: string;\n private readonly traceModelRequests: boolean;\n\n constructor(config: OctavusClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.traceModelRequests = config.traceModelRequests ?? false;\n\n const apiConfig: ApiClientConfig = {\n baseUrl: this.baseUrl,\n getHeaders: () => this.getHeaders(),\n };\n\n this.agents = new AgentsApi(apiConfig);\n this.agentSessions = new AgentSessionsApi(apiConfig);\n this.files = new FilesApi(apiConfig);\n this.workers = new WorkersApi(apiConfig);\n }\n\n getHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (this.apiKey) {\n headers.Authorization = `Bearer ${this.apiKey}`;\n }\n\n if (this.traceModelRequests) {\n headers['X-Octavus-Trace'] = 'true';\n }\n\n return headers;\n }\n}\n","/**\n * Base class for agent-managed resources.\n * Extend this class to define how each resource should be persisted when the agent updates it.\n */\nexport abstract class Resource {\n /** The resource name as defined in the agent protocol */\n abstract readonly name: string;\n\n /** Called when the agent updates this resource */\n abstract onUpdate(value: unknown): Promise<void> | void;\n}\n","import { generateId, type ToolResult, type FileReference } from '@octavus/core';\nimport type { FilesApi, FileUploadRequest } from '@/files.js';\n\ninterface ImagePart {\n type: 'image';\n data: string;\n mimeType?: string;\n}\n\nconst IMAGE_EXTENSIONS: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/webp': 'webp',\n 'image/gif': 'gif',\n 'image/svg+xml': 'svg',\n};\n\nfunction getExtensionFromMediaType(mediaType: string): string {\n return IMAGE_EXTENSIONS[mediaType] ?? 'png';\n}\n\nfunction isImagePart(part: unknown): part is ImagePart {\n return (\n typeof part === 'object' &&\n part !== null &&\n (part as Record<string, unknown>).type === 'image' &&\n typeof (part as Record<string, unknown>).data === 'string'\n );\n}\n\nfunction hasImageParts(value: unknown): value is unknown[] {\n return Array.isArray(value) && value.some(isImagePart);\n}\n\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const buffer = new ArrayBuffer(binary.length);\n const view = new Uint8Array(buffer);\n for (let i = 0; i < binary.length; i++) {\n view[i] = binary.charCodeAt(i);\n }\n return buffer;\n}\n\n/**\n * Extract base64 image blobs from tool results, upload them to S3 via\n * presigned URLs, and replace inline data with compact metadata +\n * FileReference entries.\n *\n * Runs at the server-sdk streaming layer so images are uploaded before\n * tool results travel over the network (WebSocket, HTTP continuation).\n */\nexport async function normalizeToolResultImages(\n toolResults: ToolResult[],\n filesApi: FilesApi,\n sessionId: string,\n): Promise<void> {\n for (const toolResult of toolResults) {\n if (toolResult.outputVariable) continue;\n if (!hasImageParts(toolResult.result)) continue;\n\n const parts = toolResult.result;\n const files: FileReference[] = toolResult.files ? [...toolResult.files] : [];\n\n const imageIndices: number[] = [];\n const imageBuffers: ArrayBuffer[] = [];\n const uploadRequests: FileUploadRequest[] = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (!isImagePart(part)) continue;\n\n const buffer = base64ToArrayBuffer(part.data);\n const mimeType = part.mimeType || 'image/png';\n\n imageIndices.push(i);\n imageBuffers.push(buffer);\n uploadRequests.push({\n filename: `image-${generateId()}.${getExtensionFromMediaType(mimeType)}`,\n mediaType: mimeType,\n size: buffer.byteLength,\n });\n }\n\n if (uploadRequests.length === 0) continue;\n\n let uploadInfos: { id: string; uploadUrl: string; downloadUrl: string }[];\n try {\n const response = await filesApi.getUploadUrls(sessionId, uploadRequests);\n uploadInfos = response.files;\n } catch {\n continue;\n }\n\n const uploadResults = await Promise.allSettled(\n uploadInfos.map((info, i) =>\n fetch(info.uploadUrl, {\n method: 'PUT',\n body: imageBuffers[i]!,\n headers: { 'Content-Type': uploadRequests[i]!.mediaType },\n }),\n ),\n );\n\n const summaryParts: unknown[] = [];\n let imageIdx = 0;\n\n for (let i = 0; i < parts.length; i++) {\n if (imageIdx < imageIndices.length && imageIndices[imageIdx] === i) {\n const uploadResult = uploadResults[imageIdx]!;\n const info = uploadInfos[imageIdx]!;\n const request = uploadRequests[imageIdx]!;\n const buf = imageBuffers[imageIdx]!;\n\n if (uploadResult.status === 'fulfilled' && uploadResult.value.ok) {\n files.push({\n id: info.id,\n mediaType: request.mediaType,\n url: info.downloadUrl,\n filename: request.filename,\n size: buf.byteLength,\n });\n\n summaryParts.push({\n type: 'image',\n mediaType: request.mediaType,\n size: buf.byteLength,\n url: info.downloadUrl,\n });\n } else {\n summaryParts.push(parts[i]);\n }\n\n imageIdx += 1;\n } else {\n summaryParts.push(parts[i]);\n }\n }\n\n toolResult.files = files;\n toolResult.result = summaryParts;\n }\n}\n"],"mappings":"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","names":["import_zod","import_zod","import_core","import_core","import_zod","import_core","import_core"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ZodType, z } from 'zod';
2
- import { ToolHandlers, ToolSchema, ToolResult, StreamEvent, ChatMessage, UIMessage, ToolProvider } from '@octavus/core';
2
+ import { ToolHandlers, ToolResult, StreamEvent, ToolProvider, DynamicTool, ChatMessage, UIMessage, ToolSchema } from '@octavus/core';
3
3
  export * from '@octavus/core';
4
4
  export { AppError, ConflictError, ForbiddenError, MAIN_THREAD, NotFoundError, OCTAVUS_SKILL_TOOLS, OctavusError, ValidationError, createApiErrorEvent, createErrorEvent, createInternalErrorEvent, errorToStreamEvent, generateId, getSkillSlugFromToolCall, isAbortError, isAuthenticationError, isFileReference, isFileReferenceArray, isMainThread, isOctavusSkillTool, isOtherThread, isProviderError, isRateLimitError, isRetryableError, isToolError, isValidationError, resolveThread, safeParseStreamEvent, safeParseUIMessage, safeParseUIMessages, threadForPart } from '@octavus/core';
5
5
 
@@ -137,8 +137,6 @@ interface SessionConfig {
137
137
  config: ApiClientConfig;
138
138
  tools?: ToolHandlers;
139
139
  resources?: Resource[];
140
- /** Tool schemas to send to the platform on the first trigger (device MCP tools, etc.) */
141
- additionalToolSchemas?: ToolSchema[];
142
140
  /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */
143
141
  onToolResults?: (results: ToolResult[]) => Promise<void>;
144
142
  /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */
@@ -157,8 +155,8 @@ declare class AgentSession {
157
155
  private config;
158
156
  private toolHandlers;
159
157
  private resourceMap;
160
- private additionalToolSchemas;
161
- private additionalToolSchemasSent;
158
+ private dynamicToolSchemas;
159
+ private dynamicToolNames;
162
160
  private socketAbortController;
163
161
  private onToolResults?;
164
162
  private rejectClientToolCalls;
@@ -190,6 +188,20 @@ declare class AgentSession {
190
188
  */
191
189
  execute(request: SessionRequest, options?: TriggerOptions): AsyncGenerator<StreamEvent>;
192
190
  getSessionId(): string;
191
+ /**
192
+ * Set the full list of dynamic tools (schemas + handlers).
193
+ * Replaces any previously set dynamic tools — removed tools are
194
+ * unregistered, new ones are added, and updated schemas are sent
195
+ * to the platform on the next request.
196
+ *
197
+ * Accepts either a `ToolProvider` (e.g. `Computer`) or an explicit
198
+ * `DynamicTool[]` array.
199
+ *
200
+ * Safe to call mid-session: executeStream resolves toolHandlers via
201
+ * a getter on each continuation loop, so new handlers are visible
202
+ * immediately.
203
+ */
204
+ setDynamicTools(source: ToolProvider | DynamicTool[]): void;
193
205
  /**
194
206
  * Handle a WebSocket protocol message (trigger, continue, or stop).
195
207
  * Manages abort controller lifecycle internally.
@@ -248,8 +260,6 @@ interface ClearSessionResult {
248
260
  interface SessionAttachOptions {
249
261
  tools?: ToolHandlers;
250
262
  resources?: Resource[];
251
- /** Computer capability provider (browser, filesystem, shell via MCP). */
252
- computer?: ToolProvider;
253
263
  /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */
254
264
  onToolResults?: (results: ToolResult[]) => Promise<void>;
255
265
  /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */
@@ -381,6 +391,8 @@ declare class FilesApi extends BaseApiClient {
381
391
  interface WorkerStartRequest {
382
392
  type: 'start';
383
393
  input: Record<string, unknown>;
394
+ /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */
395
+ dynamicToolSchemas?: ToolSchema[];
384
396
  }
385
397
  /** Continue execution after client-side tool handling */
386
398
  interface WorkerContinueRequest {
@@ -396,6 +408,8 @@ interface WorkerExecuteOptions {
396
408
  tools?: ToolHandlers;
397
409
  /** Abort signal to cancel the execution */
398
410
  signal?: AbortSignal;
411
+ /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */
412
+ dynamicToolSchemas?: ToolSchema[];
399
413
  }
400
414
  /** Result from a non-streaming worker execution via `generate()` */
401
415
  interface WorkerGenerateResult {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ZodType, z } from 'zod';
2
- import { ToolHandlers, ToolSchema, ToolResult, StreamEvent, ChatMessage, UIMessage, ToolProvider } from '@octavus/core';
2
+ import { ToolHandlers, ToolResult, StreamEvent, ToolProvider, DynamicTool, ChatMessage, UIMessage, ToolSchema } from '@octavus/core';
3
3
  export * from '@octavus/core';
4
4
  export { AppError, ConflictError, ForbiddenError, MAIN_THREAD, NotFoundError, OCTAVUS_SKILL_TOOLS, OctavusError, ValidationError, createApiErrorEvent, createErrorEvent, createInternalErrorEvent, errorToStreamEvent, generateId, getSkillSlugFromToolCall, isAbortError, isAuthenticationError, isFileReference, isFileReferenceArray, isMainThread, isOctavusSkillTool, isOtherThread, isProviderError, isRateLimitError, isRetryableError, isToolError, isValidationError, resolveThread, safeParseStreamEvent, safeParseUIMessage, safeParseUIMessages, threadForPart } from '@octavus/core';
5
5
 
@@ -137,8 +137,6 @@ interface SessionConfig {
137
137
  config: ApiClientConfig;
138
138
  tools?: ToolHandlers;
139
139
  resources?: Resource[];
140
- /** Tool schemas to send to the platform on the first trigger (device MCP tools, etc.) */
141
- additionalToolSchemas?: ToolSchema[];
142
140
  /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */
143
141
  onToolResults?: (results: ToolResult[]) => Promise<void>;
144
142
  /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */
@@ -157,8 +155,8 @@ declare class AgentSession {
157
155
  private config;
158
156
  private toolHandlers;
159
157
  private resourceMap;
160
- private additionalToolSchemas;
161
- private additionalToolSchemasSent;
158
+ private dynamicToolSchemas;
159
+ private dynamicToolNames;
162
160
  private socketAbortController;
163
161
  private onToolResults?;
164
162
  private rejectClientToolCalls;
@@ -190,6 +188,20 @@ declare class AgentSession {
190
188
  */
191
189
  execute(request: SessionRequest, options?: TriggerOptions): AsyncGenerator<StreamEvent>;
192
190
  getSessionId(): string;
191
+ /**
192
+ * Set the full list of dynamic tools (schemas + handlers).
193
+ * Replaces any previously set dynamic tools — removed tools are
194
+ * unregistered, new ones are added, and updated schemas are sent
195
+ * to the platform on the next request.
196
+ *
197
+ * Accepts either a `ToolProvider` (e.g. `Computer`) or an explicit
198
+ * `DynamicTool[]` array.
199
+ *
200
+ * Safe to call mid-session: executeStream resolves toolHandlers via
201
+ * a getter on each continuation loop, so new handlers are visible
202
+ * immediately.
203
+ */
204
+ setDynamicTools(source: ToolProvider | DynamicTool[]): void;
193
205
  /**
194
206
  * Handle a WebSocket protocol message (trigger, continue, or stop).
195
207
  * Manages abort controller lifecycle internally.
@@ -248,8 +260,6 @@ interface ClearSessionResult {
248
260
  interface SessionAttachOptions {
249
261
  tools?: ToolHandlers;
250
262
  resources?: Resource[];
251
- /** Computer capability provider (browser, filesystem, shell via MCP). */
252
- computer?: ToolProvider;
253
263
  /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */
254
264
  onToolResults?: (results: ToolResult[]) => Promise<void>;
255
265
  /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */
@@ -381,6 +391,8 @@ declare class FilesApi extends BaseApiClient {
381
391
  interface WorkerStartRequest {
382
392
  type: 'start';
383
393
  input: Record<string, unknown>;
394
+ /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */
395
+ dynamicToolSchemas?: ToolSchema[];
384
396
  }
385
397
  /** Continue execution after client-side tool handling */
386
398
  interface WorkerContinueRequest {
@@ -396,6 +408,8 @@ interface WorkerExecuteOptions {
396
408
  tools?: ToolHandlers;
397
409
  /** Abort signal to cancel the execution */
398
410
  signal?: AbortSignal;
411
+ /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */
412
+ dynamicToolSchemas?: ToolSchema[];
399
413
  }
400
414
  /** Result from a non-streaming worker execution via `generate()` */
401
415
  interface WorkerGenerateResult {
package/dist/index.js CHANGED
@@ -254,11 +254,12 @@ async function* executeStream(config, payload, signal) {
254
254
  return;
255
255
  }
256
256
  if (pendingToolCalls && pendingToolCalls.length > 0) {
257
- const serverTools = pendingToolCalls.filter((tc) => config.toolHandlers[tc.toolName]);
258
- const clientTools = pendingToolCalls.filter((tc) => !config.toolHandlers[tc.toolName]);
257
+ const toolHandlers = config.getToolHandlers();
258
+ const serverTools = pendingToolCalls.filter((tc) => toolHandlers[tc.toolName]);
259
+ const clientTools = pendingToolCalls.filter((tc) => !toolHandlers[tc.toolName]);
259
260
  const serverResults = await Promise.all(
260
261
  serverTools.map(async (tc) => {
261
- const handler = config.toolHandlers[tc.toolName];
262
+ const handler = toolHandlers[tc.toolName];
262
263
  try {
263
264
  const result = await handler(tc.args);
264
265
  return {
@@ -367,13 +368,17 @@ function toSSEStream(events) {
367
368
  }
368
369
  });
369
370
  }
371
+ function resolveDynamicTools(provider) {
372
+ const handlers = provider.toolHandlers();
373
+ return provider.toolSchemas().filter((s) => handlers[s.name]).map((s) => ({ schema: s, handler: handlers[s.name] }));
374
+ }
370
375
  var AgentSession = class {
371
376
  sessionId;
372
377
  config;
373
378
  toolHandlers;
374
379
  resourceMap;
375
- additionalToolSchemas;
376
- additionalToolSchemasSent = false;
380
+ dynamicToolSchemas;
381
+ dynamicToolNames = /* @__PURE__ */ new Set();
377
382
  socketAbortController = null;
378
383
  onToolResults;
379
384
  rejectClientToolCalls;
@@ -381,7 +386,6 @@ var AgentSession = class {
381
386
  this.sessionId = sessionConfig.sessionId;
382
387
  this.config = sessionConfig.config;
383
388
  this.toolHandlers = sessionConfig.tools ?? {};
384
- this.additionalToolSchemas = sessionConfig.additionalToolSchemas;
385
389
  this.onToolResults = sessionConfig.onToolResults;
386
390
  this.rejectClientToolCalls = sessionConfig.rejectClientToolCalls ?? false;
387
391
  this.resourceMap = /* @__PURE__ */ new Map();
@@ -434,6 +438,35 @@ var AgentSession = class {
434
438
  getSessionId() {
435
439
  return this.sessionId;
436
440
  }
441
+ /**
442
+ * Set the full list of dynamic tools (schemas + handlers).
443
+ * Replaces any previously set dynamic tools — removed tools are
444
+ * unregistered, new ones are added, and updated schemas are sent
445
+ * to the platform on the next request.
446
+ *
447
+ * Accepts either a `ToolProvider` (e.g. `Computer`) or an explicit
448
+ * `DynamicTool[]` array.
449
+ *
450
+ * Safe to call mid-session: executeStream resolves toolHandlers via
451
+ * a getter on each continuation loop, so new handlers are visible
452
+ * immediately.
453
+ */
454
+ setDynamicTools(source) {
455
+ const tools = Array.isArray(source) ? source : resolveDynamicTools(source);
456
+ const newNames = new Set(tools.map((t) => t.schema.name));
457
+ const cleaned = {};
458
+ for (const [name, handler] of Object.entries(this.toolHandlers)) {
459
+ if (!this.dynamicToolNames.has(name)) {
460
+ cleaned[name] = handler;
461
+ }
462
+ }
463
+ for (const tool of tools) {
464
+ cleaned[tool.schema.name] = tool.handler;
465
+ }
466
+ this.toolHandlers = cleaned;
467
+ this.dynamicToolNames = newNames;
468
+ this.dynamicToolSchemas = tools.map((t) => t.schema);
469
+ }
437
470
  /**
438
471
  * Handle a WebSocket protocol message (trigger, continue, or stop).
439
472
  * Manages abort controller lifecycle internally.
@@ -480,7 +513,7 @@ var AgentSession = class {
480
513
  yield* executeStream(
481
514
  {
482
515
  config: this.config,
483
- toolHandlers: this.toolHandlers,
516
+ getToolHandlers: () => this.toolHandlers,
484
517
  url: `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,
485
518
  buildBody: ({ executionId, toolResults }) => {
486
519
  const body = {};
@@ -490,9 +523,8 @@ var AgentSession = class {
490
523
  body.rollbackAfterMessageId = payload.rollbackAfterMessageId;
491
524
  if (executionId !== void 0) body.executionId = executionId;
492
525
  if (toolResults !== void 0) body.toolResults = toolResults;
493
- if (!this.additionalToolSchemasSent && (this.additionalToolSchemas?.length ?? 0) > 0) {
494
- body.additionalToolSchemas = this.additionalToolSchemas;
495
- this.additionalToolSchemasSent = true;
526
+ if (this.dynamicToolSchemas !== void 0) {
527
+ body.dynamicToolSchemas = this.dynamicToolSchemas;
496
528
  }
497
529
  return body;
498
530
  },
@@ -633,14 +665,11 @@ var AgentSessionsApi = class extends BaseApiClient {
633
665
  }
634
666
  /** Attach to an existing session for triggering events */
635
667
  attach(sessionId, options = {}) {
636
- const computerHandlers = options.computer?.toolHandlers() ?? {};
637
- const mergedTools = { ...computerHandlers, ...options.tools };
638
668
  return new AgentSession({
639
669
  sessionId,
640
670
  config: this.config,
641
- tools: mergedTools,
671
+ tools: options.tools,
642
672
  resources: options.resources,
643
- additionalToolSchemas: options.computer?.toolSchemas(),
644
673
  onToolResults: options.onToolResults,
645
674
  rejectClientToolCalls: options.rejectClientToolCalls
646
675
  });
@@ -754,12 +783,19 @@ var WorkersApi = class extends BaseApiClient {
754
783
  * ```
755
784
  */
756
785
  async *execute(agentId, input, options = {}) {
786
+ const tools = options.tools ?? {};
757
787
  yield* executeStream(
758
788
  {
759
789
  config: this.config,
760
- toolHandlers: options.tools ?? {},
790
+ getToolHandlers: () => tools,
761
791
  url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,
762
- buildBody: ({ executionId, toolResults }) => !executionId ? { type: "start", input } : { type: "continue", executionId, toolResults },
792
+ buildBody: ({ executionId, toolResults }) => !executionId ? {
793
+ type: "start",
794
+ input,
795
+ ...options.dynamicToolSchemas !== void 0 && {
796
+ dynamicToolSchemas: options.dynamicToolSchemas
797
+ }
798
+ } : { type: "continue", executionId, toolResults },
763
799
  errorContext: "Failed to execute worker"
764
800
  },
765
801
  {},
@@ -843,10 +879,11 @@ var WorkersApi = class extends BaseApiClient {
843
879
  * ```
844
880
  */
845
881
  async *continue(agentId, executionId, toolResults, options = {}) {
882
+ const tools = options.tools ?? {};
846
883
  yield* executeStream(
847
884
  {
848
885
  config: this.config,
849
- toolHandlers: options.tools ?? {},
886
+ getToolHandlers: () => tools,
850
887
  url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,
851
888
  buildBody: ({ executionId: execId, toolResults: results }) => ({
852
889
  type: "continue",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api-error.ts","../src/base-api-client.ts","../src/agent-types.ts","../src/agents.ts","../src/agent-sessions.ts","../src/session.ts","../src/streaming.ts","../src/files.ts","../src/worker-error.ts","../src/workers.ts","../src/client.ts","../src/resource.ts","../src/normalize-images.ts","../src/index.ts"],"sourcesContent":["import { z } from 'zod';\n\nconst ApiErrorResponseSchema = z.object({\n error: z.string().optional(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n/**\n * Error thrown when API request fails\n */\nexport class ApiError extends Error {\n constructor(\n message: string,\n public status: number,\n public code?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\ninterface ParsedApiError {\n message: string;\n code?: string;\n}\n\n/**\n * Parse error from API response using Zod\n */\nexport async function parseApiError(\n response: Response,\n defaultMessage: string,\n): Promise<ParsedApiError> {\n const fallbackMessage = `${defaultMessage}: ${response.statusText}`;\n\n try {\n const json: unknown = await response.json();\n const parsed = ApiErrorResponseSchema.safeParse(json);\n\n if (parsed.success) {\n return {\n message: parsed.data.error ?? parsed.data.message ?? fallbackMessage,\n code: parsed.data.code,\n };\n }\n } catch {\n // Use default message\n }\n\n return { message: fallbackMessage };\n}\n\n/**\n * Parse error from API response and throw ApiError\n */\nexport async function throwApiError(response: Response, defaultMessage: string): Promise<never> {\n const { message, code } = await parseApiError(response, defaultMessage);\n throw new ApiError(message, response.status, code);\n}\n","import type { ZodType } from 'zod';\nimport { throwApiError } from '@/api-error.js';\n\nexport { ApiError } from '@/api-error.js';\n\nexport interface ApiClientConfig {\n baseUrl: string;\n getHeaders: () => Record<string, string>;\n}\n\n/** Base class for API clients with shared HTTP utilities */\nexport abstract class BaseApiClient {\n protected readonly config: ApiClientConfig;\n\n constructor(config: ApiClientConfig) {\n this.config = config;\n }\n\n protected async httpGet<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPost<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'POST',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPatch<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'PATCH',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpDelete<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'DELETE',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n}\n","import { z } from 'zod';\n\n/** Agent format - interactive (chat) or worker (background task) */\nexport type AgentFormat = 'interactive' | 'worker';\n\n/** Agent settings */\nexport interface AgentSettings {\n slug: string;\n name: string;\n description?: string;\n format: AgentFormat;\n}\n\n/** Agent prompt */\nexport interface AgentPrompt {\n name: string;\n content: string;\n}\n\n/**\n * Agent summary returned from list endpoint\n */\nexport interface Agent {\n /** Agent slug (human-readable identifier within project) */\n slug: string;\n /** Agent ID - use this for API calls */\n id: string;\n name: string;\n description: string | null;\n format: AgentFormat;\n createdAt: string;\n updatedAt: string;\n projectId: string;\n}\n\n/**\n * Full agent definition returned from get endpoint\n */\nexport interface AgentDefinition {\n settings: AgentSettings;\n protocol: string;\n prompts: AgentPrompt[];\n /** Agent ID - use this for API calls like createSession */\n id: string;\n}\n\n// Schemas\n\nexport const agentFormatSchema = z.enum(['interactive', 'worker']);\n\nconst agentSettingsSchema = z.object({\n slug: z.string(),\n name: z.string(),\n description: z.string().optional(),\n format: agentFormatSchema,\n});\n\nconst agentPromptSchema = z.object({\n name: z.string(),\n content: z.string(),\n});\n\nexport const agentSchema = z.object({\n slug: z.string(),\n id: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n format: agentFormatSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n projectId: z.string(),\n});\n\nexport const agentsResponseSchema = z.object({\n agents: z.array(agentSchema),\n});\n\nexport const agentDefinitionSchema = z.object({\n settings: agentSettingsSchema,\n protocol: z.string(),\n prompts: z.array(agentPromptSchema),\n id: z.string(),\n});\n","import { BaseApiClient } from '@/base-api-client.js';\nimport {\n agentsResponseSchema,\n agentDefinitionSchema,\n type Agent,\n type AgentDefinition,\n} from '@/agent-types.js';\n\n/**\n * API for listing and retrieving agent definitions.\n *\n * Note: Agent management (create, update, sync) should be done via the @octavus/cli package.\n * This API uses agent IDs only - use CLI for slug-based operations.\n */\nexport class AgentsApi extends BaseApiClient {\n /** List all agents in the project */\n async list(): Promise<Agent[]> {\n const response = await this.httpGet('/api/agents', agentsResponseSchema);\n return response.agents;\n }\n\n /** Get a single agent by ID */\n async get(agentId: string): Promise<AgentDefinition> {\n return await this.httpGet(`/api/agents/${agentId}`, agentDefinitionSchema);\n }\n}\n","import { z } from 'zod';\nimport {\n chatMessageSchema,\n uiMessageSchema,\n type ChatMessage,\n type ToolProvider,\n type ToolHandlers,\n type ToolResult,\n type UIMessage,\n} from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { throwApiError } from '@/api-error.js';\nimport { AgentSession } from '@/session.js';\nimport type { Resource } from '@/resource.js';\n\nconst createSessionResponseSchema = z.object({\n sessionId: z.string(),\n});\n\nconst sessionStateSchema = z.object({\n id: z.string(),\n agentId: z.string(),\n input: z.record(z.string(), z.unknown()),\n variables: z.record(z.string(), z.unknown()),\n resources: z.record(z.string(), z.unknown()),\n messages: z.array(chatMessageSchema),\n status: z.literal('active').optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\nconst uiSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n messages: z.array(uiMessageSchema),\n status: z.literal('active').optional(),\n});\n\nconst expiredSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n status: z.literal('expired'),\n createdAt: z.string(),\n});\n\nconst restoreSessionResponseSchema = z.object({\n sessionId: z.string(),\n restored: z.boolean(),\n});\n\nconst clearSessionResponseSchema = z.object({\n sessionId: z.string(),\n cleared: z.boolean(),\n});\n\n/** Session status indicating whether it's active or expired */\nexport type SessionStatus = 'active' | 'expired';\n\nexport interface SessionState {\n id: string;\n agentId: string;\n input: Record<string, unknown>;\n variables: Record<string, unknown>;\n resources: Record<string, unknown>;\n messages: ChatMessage[];\n status?: 'active';\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface UISessionState {\n sessionId: string;\n agentId: string;\n messages: UIMessage[];\n status?: 'active';\n}\n\nexport interface ExpiredSessionState {\n sessionId: string;\n agentId: string;\n status: 'expired';\n createdAt: string;\n}\n\nexport interface RestoreSessionResult {\n sessionId: string;\n /** True if session was restored from messages, false if already active */\n restored: boolean;\n}\n\nexport interface ClearSessionResult {\n sessionId: string;\n cleared: boolean;\n}\n\nexport interface SessionAttachOptions {\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Computer capability provider (browser, filesystem, shell via MCP). */\n computer?: ToolProvider;\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/** API for managing agent sessions */\nexport class AgentSessionsApi extends BaseApiClient {\n /** Create a new session for an agent */\n async create(agentId: string, input?: Record<string, unknown>): Promise<string> {\n const response = await this.httpPost(\n '/api/agent-sessions',\n { agentId, input },\n createSessionResponseSchema,\n );\n return response.sessionId;\n }\n\n /**\n * Get full session state (for internal/debug use)\n * Note: Contains all messages including hidden content\n *\n * Returns SessionState for active sessions, ExpiredSessionState for expired sessions.\n * Check `status` field to determine which type was returned.\n */\n async get(sessionId: string): Promise<SessionState | ExpiredSessionState> {\n const response = await fetch(`${this.config.baseUrl}/api/agent-sessions/${sessionId}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return sessionStateSchema.parse(data);\n }\n\n /**\n * Get UI-ready session messages (for client display)\n * Returns only visible messages with hidden content filtered out.\n *\n * For expired sessions, returns status: 'expired' without messages.\n * Use restore() to restore from stored messages before continuing.\n */\n async getMessages(sessionId: string): Promise<UISessionState | ExpiredSessionState> {\n const response = await fetch(\n `${this.config.baseUrl}/api/agent-sessions/${sessionId}?format=ui`,\n {\n method: 'GET',\n headers: this.config.getHeaders(),\n },\n );\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return uiSessionResponseSchema.parse(data);\n }\n\n /**\n * Restore an expired session from stored messages.\n *\n * Use this to restore a session after its state has expired.\n * The consumer should have stored the UIMessage[] array from previous interactions.\n *\n * @param sessionId - The session ID to restore\n * @param messages - Previously stored UIMessage[] array\n * @param input - Optional session input for system prompt interpolation (same as create)\n * @returns { sessionId, restored: true } if restored, { sessionId, restored: false } if already active\n */\n async restore(\n sessionId: string,\n messages: UIMessage[],\n input?: Record<string, unknown>,\n ): Promise<RestoreSessionResult> {\n return await this.httpPost(\n `/api/agent-sessions/${sessionId}/restore`,\n { messages, input },\n restoreSessionResponseSchema,\n );\n }\n\n /**\n * Clear session state from the server.\n * The session will transition to 'expired' status and can be restored with restore().\n * Idempotent: succeeds even if state was already cleared/expired.\n */\n async clear(sessionId: string): Promise<ClearSessionResult> {\n return await this.httpDelete(`/api/agent-sessions/${sessionId}`, clearSessionResponseSchema);\n }\n\n /** Attach to an existing session for triggering events */\n attach(sessionId: string, options: SessionAttachOptions = {}): AgentSession {\n const computerHandlers = options.computer?.toolHandlers() ?? {};\n const mergedTools = { ...computerHandlers, ...options.tools };\n return new AgentSession({\n sessionId,\n config: this.config,\n tools: mergedTools,\n resources: options.resources,\n additionalToolSchemas: options.computer?.toolSchemas(),\n onToolResults: options.onToolResults,\n rejectClientToolCalls: options.rejectClientToolCalls,\n });\n }\n}\n","import {\n createInternalErrorEvent,\n type StreamEvent,\n type ToolHandlers,\n type ToolResult,\n type ToolSchema,\n} from '@octavus/core';\nimport type { ApiClientConfig } from '@/base-api-client.js';\nimport type { Resource } from '@/resource.js';\nimport { executeStream } from '@/streaming.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new trigger execution */\nexport interface TriggerRequest {\n type: 'trigger';\n triggerName: string;\n input?: Record<string, unknown>;\n /** ID of the last message to keep. Messages after this are removed before execution. `null` = truncate all. */\n rollbackAfterMessageId?: string | null;\n}\n\n/** Continue execution after client-side tool handling */\nexport interface ContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by the session */\nexport type SessionRequest = TriggerRequest | ContinueRequest;\n\n/** Stop message to abort in-flight requests */\nexport interface StopMessage {\n type: 'stop';\n}\n\n/** All socket protocol messages (trigger, continue, stop) */\nexport type SocketMessage = TriggerRequest | ContinueRequest | StopMessage;\n\n// =============================================================================\n// Socket Message Handler Types\n// =============================================================================\n\n/** Handlers for socket message streaming */\nexport interface SocketMessageHandlers {\n /** Called for each stream event */\n onEvent: (event: StreamEvent) => void;\n /** Called after streaming completes (not called if aborted) */\n onFinish?: () => void | Promise<void>;\n}\n\nconst SSE_HEARTBEAT_INTERVAL_MS = 15_000;\n\n/**\n * Converts an async iterable of stream events to an SSE-formatted ReadableStream.\n * Use this when you need to return an SSE response (e.g., HTTP endpoints).\n *\n * @example\n * ```typescript\n * const events = session.trigger('user-message', input);\n * return new Response(toSSEStream(events), {\n * headers: { 'Content-Type': 'text/event-stream' },\n * });\n * ```\n */\nexport function toSSEStream(events: AsyncIterable<StreamEvent>): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const heartbeatBytes = encoder.encode(': heartbeat\\n\\n');\n\n return new ReadableStream({\n async start(controller) {\n const heartbeat = setInterval(() => {\n try {\n controller.enqueue(heartbeatBytes);\n } catch {\n clearInterval(heartbeat);\n }\n }, SSE_HEARTBEAT_INTERVAL_MS);\n\n try {\n for await (const event of events) {\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\\n\\n`));\n }\n controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));\n controller.close();\n } catch (err) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}\\n\\n`));\n controller.close();\n } finally {\n clearInterval(heartbeat);\n }\n },\n });\n}\n\nexport interface SessionConfig {\n sessionId: string;\n config: ApiClientConfig;\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Tool schemas to send to the platform on the first trigger (device MCP tools, etc.) */\n additionalToolSchemas?: ToolSchema[];\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Options for trigger execution.\n */\nexport interface TriggerOptions {\n /** Abort signal to cancel the trigger execution */\n signal?: AbortSignal;\n}\n\n/** Handles streaming and tool continuation for agent sessions */\nexport class AgentSession {\n private sessionId: string;\n private config: ApiClientConfig;\n private toolHandlers: ToolHandlers;\n private resourceMap: Map<string, Resource>;\n private additionalToolSchemas: ToolSchema[] | undefined;\n private additionalToolSchemasSent = false;\n private socketAbortController: AbortController | null = null;\n private onToolResults?: (results: ToolResult[]) => Promise<void>;\n private rejectClientToolCalls: boolean;\n\n constructor(sessionConfig: SessionConfig) {\n this.sessionId = sessionConfig.sessionId;\n this.config = sessionConfig.config;\n this.toolHandlers = sessionConfig.tools ?? {};\n this.additionalToolSchemas = sessionConfig.additionalToolSchemas;\n this.onToolResults = sessionConfig.onToolResults;\n this.rejectClientToolCalls = sessionConfig.rejectClientToolCalls ?? false;\n this.resourceMap = new Map();\n\n for (const resource of sessionConfig.resources ?? []) {\n this.resourceMap.set(resource.name, resource);\n }\n }\n\n /**\n * Execute a session request and stream the response.\n *\n * This is the unified method that handles both triggers and continuations.\n * Use this when you want to pass through requests from the client directly.\n *\n * @param request - The request (check `request.type` for the kind)\n * @param options - Optional configuration including abort signal\n *\n * @example HTTP route (simple passthrough)\n * ```typescript\n * const events = session.execute(body, { signal: request.signal });\n * return new Response(toSSEStream(events));\n * ```\n *\n * @example WebSocket handler\n * ```typescript\n * socket.on('message', (data) => {\n * const events = session.execute(data);\n * for await (const event of events) {\n * socket.send(JSON.stringify(event));\n * }\n * });\n * ```\n */\n async *execute(request: SessionRequest, options?: TriggerOptions): AsyncGenerator<StreamEvent> {\n if (request.type === 'continue') {\n yield* this.executeStream(\n { executionId: request.executionId, toolResults: request.toolResults },\n options?.signal,\n );\n } else {\n yield* this.executeStream(\n {\n triggerName: request.triggerName,\n input: request.input,\n rollbackAfterMessageId: request.rollbackAfterMessageId,\n },\n options?.signal,\n );\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n /**\n * Handle a WebSocket protocol message (trigger, continue, or stop).\n * Manages abort controller lifecycle internally.\n *\n * @example\n * ```typescript\n * conn.on('data', (raw) => {\n * session.handleSocketMessage(JSON.parse(raw), {\n * onEvent: (event) => conn.write(JSON.stringify(event)),\n * onFinish: async () => {\n * // Fetch messages and persist to your database for restoration\n * },\n * });\n * });\n * ```\n */\n async handleSocketMessage(\n message: SocketMessage,\n handlers: SocketMessageHandlers,\n ): Promise<void> {\n if (message.type === 'stop') {\n this.socketAbortController?.abort();\n return;\n }\n\n this.socketAbortController?.abort();\n this.socketAbortController = new AbortController();\n\n const localController = this.socketAbortController;\n\n try {\n const events = this.execute(message, { signal: localController.signal });\n\n for await (const event of events) {\n if (localController.signal.aborted) break;\n handlers.onEvent(event);\n }\n\n if (!localController.signal.aborted && handlers.onFinish) {\n await handlers.onFinish();\n }\n } catch (err) {\n if (!localController.signal.aborted) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n handlers.onEvent(errorEvent);\n }\n }\n }\n\n private async *executeStream(\n payload: {\n triggerName?: string;\n input?: Record<string, unknown>;\n executionId?: string;\n toolResults?: ToolResult[];\n rollbackAfterMessageId?: string | null;\n },\n signal?: AbortSignal,\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n toolHandlers: this.toolHandlers,\n url: `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,\n buildBody: ({ executionId, toolResults }) => {\n const body: Record<string, unknown> = {};\n if (payload.triggerName !== undefined) body.triggerName = payload.triggerName;\n if (payload.input !== undefined) body.input = payload.input;\n if (payload.rollbackAfterMessageId !== undefined)\n body.rollbackAfterMessageId = payload.rollbackAfterMessageId;\n if (executionId !== undefined) body.executionId = executionId;\n if (toolResults !== undefined) body.toolResults = toolResults;\n if (!this.additionalToolSchemasSent && (this.additionalToolSchemas?.length ?? 0) > 0) {\n body.additionalToolSchemas = this.additionalToolSchemas;\n this.additionalToolSchemasSent = true;\n }\n return body;\n },\n onResourceUpdate: (name, value) => this.handleResourceUpdate(name, value),\n onToolResults: this.onToolResults,\n rejectClientToolCalls: this.rejectClientToolCalls,\n errorContext: 'Failed to trigger',\n },\n { executionId: payload.executionId, toolResults: payload.toolResults },\n signal,\n );\n }\n\n private handleResourceUpdate(name: string, value: unknown): void {\n const resource = this.resourceMap.get(name);\n if (resource) {\n void resource.onUpdate(value);\n }\n }\n}\n","import {\n safeParseStreamEvent,\n isAbortError,\n createInternalErrorEvent,\n createApiErrorEvent,\n type StreamEvent,\n type ToolHandlers,\n type PendingToolCall,\n type ToolResult,\n} from '@octavus/core';\nimport { parseApiError } from '@/api-error.js';\nimport type { ApiClientConfig } from '@/base-api-client.js';\n\n/**\n * Configuration for streaming execution.\n */\nexport interface StreamExecutionConfig {\n /** API client config with baseUrl and headers */\n config: ApiClientConfig;\n /** Tool handlers for server-side execution */\n toolHandlers: ToolHandlers;\n /** Full URL to make the request to */\n url: string;\n /** Build the request body for this execution */\n buildBody: (state: {\n executionId?: string;\n toolResults?: ToolResult[];\n }) => Record<string, unknown>;\n /** Called when a resource-update event is received (optional) */\n onResourceUpdate?: (name: string, value: unknown) => void;\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** Error message prefix for API errors */\n errorContext?: string;\n /**\n * When true, tool calls without a registered handler return an error result\n * instead of being emitted as client-tool-request events.\n * Use for server-only execution environments (e.g., OctoAgents) that have\n * no client-side tool executor.\n */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Initial payload for starting an execution stream.\n */\nexport interface StreamExecutionPayload {\n /** Initial execution ID (for continuation) */\n executionId?: string;\n /** Initial tool results (for continuation) */\n toolResults?: ToolResult[];\n}\n\n/**\n * Executes a streaming request with tool continuation support.\n *\n * This is the shared implementation for both interactive sessions and workers.\n * It handles:\n * - SSE stream parsing\n * - Abort signal handling\n * - Tool-request interception and server/client splitting\n * - Automatic continuation for server-handled tools\n * - Client-tool-request emission for client-handled tools\n */\nexport async function* executeStream(\n config: StreamExecutionConfig,\n payload: StreamExecutionPayload,\n signal?: AbortSignal,\n): AsyncGenerator<StreamEvent> {\n let toolResults = payload.toolResults;\n let executionId = payload.executionId;\n let continueLoop = true;\n\n while (continueLoop) {\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n const body = config.buildBody({ executionId, toolResults });\n\n let response: Response;\n try {\n response = await fetch(config.url, {\n method: 'POST',\n headers: config.config.getHeaders(),\n body: JSON.stringify(body),\n signal,\n });\n } catch (err) {\n if (isAbortError(err)) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n if (!response.ok) {\n const { message } = await parseApiError(response, config.errorContext ?? 'Request failed');\n yield createApiErrorEvent(response.status, message);\n return;\n }\n\n if (!response.body) {\n yield createInternalErrorEvent('Response body is not readable');\n return;\n }\n\n toolResults = undefined;\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let pendingToolCalls: PendingToolCall[] | null = null;\n\n let streamDone = false;\n while (!streamDone) {\n if (signal?.aborted) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n let readResult: ReadableStreamReadResult<Uint8Array>;\n try {\n readResult = await reader.read();\n } catch (err) {\n if (isAbortError(err)) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n const { done, value } = readResult;\n\n if (done) {\n streamDone = true;\n continue;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const parsed = safeParseStreamEvent(JSON.parse(line.slice(6)));\n if (!parsed.success) {\n continue;\n }\n const event = parsed.data;\n\n if (event.type === 'start' && event.executionId) {\n executionId = event.executionId;\n }\n\n if (event.type === 'tool-request') {\n pendingToolCalls = event.toolCalls;\n continue;\n }\n\n if (event.type === 'finish') {\n if (event.finishReason === 'tool-calls' && pendingToolCalls) {\n continue;\n }\n yield event;\n continueLoop = false;\n continue;\n }\n\n if (event.type === 'resource-update' && config.onResourceUpdate) {\n config.onResourceUpdate(event.name, event.value);\n }\n\n yield event;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n if (pendingToolCalls && pendingToolCalls.length > 0) {\n const serverTools = pendingToolCalls.filter((tc) => config.toolHandlers[tc.toolName]);\n const clientTools = pendingToolCalls.filter((tc) => !config.toolHandlers[tc.toolName]);\n\n const serverResults = await Promise.all(\n serverTools.map(async (tc): Promise<ToolResult> => {\n const handler = config.toolHandlers[tc.toolName]!;\n try {\n const result = await handler(tc.args);\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n result,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n } catch (err) {\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: err instanceof Error ? err.message : 'Tool execution failed',\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n }\n }),\n );\n\n if (config.onToolResults && serverResults.length > 0) {\n await config.onToolResults(serverResults);\n }\n\n for (const tr of serverResults) {\n if (tr.error) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error };\n } else {\n yield { type: 'tool-output-available', toolCallId: tr.toolCallId, output: tr.result };\n }\n }\n\n if (clientTools.length > 0) {\n if (config.rejectClientToolCalls) {\n const rejectedResults: ToolResult[] = clientTools.map((tc) => ({\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: `Tool \"${tc.toolName}\" is not available. No handler is registered for this tool.`,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n }));\n for (const tr of rejectedResults) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error! };\n }\n toolResults = [...serverResults, ...rejectedResults];\n } else {\n if (!executionId) {\n yield createInternalErrorEvent('Missing executionId for client-tool-request');\n return;\n }\n yield {\n type: 'client-tool-request',\n executionId,\n toolCalls: clientTools,\n serverToolResults: serverResults.length > 0 ? serverResults : undefined,\n };\n yield { type: 'finish', finishReason: 'client-tool-calls', executionId };\n continueLoop = false;\n }\n } else {\n toolResults = serverResults;\n }\n } else {\n continueLoop = false;\n }\n }\n}\n","import { z } from 'zod';\nimport { BaseApiClient } from '@/base-api-client.js';\n\n// =============================================================================\n// Schemas\n// =============================================================================\n\n/**\n * Schema for a single file upload request\n */\nexport const fileUploadRequestSchema = z.object({\n filename: z.string().min(1).max(255),\n mediaType: z.string().min(1),\n size: z.number().int().positive(),\n});\n\n/**\n * Schema for a single file upload response\n */\nexport const fileUploadInfoSchema = z.object({\n /** File ID to reference in messages */\n id: z.string(),\n /** Presigned PUT URL for uploading to S3 */\n uploadUrl: z.url(),\n /** Presigned GET URL for downloading after upload */\n downloadUrl: z.url(),\n});\n\n/**\n * Schema for the upload URLs response\n */\nexport const uploadUrlsResponseSchema = z.object({\n files: z.array(fileUploadInfoSchema),\n});\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type FileUploadRequest = z.infer<typeof fileUploadRequestSchema>;\nexport type FileUploadInfo = z.infer<typeof fileUploadInfoSchema>;\nexport type UploadUrlsResponse = z.infer<typeof uploadUrlsResponseSchema>;\n\n// =============================================================================\n// API\n// =============================================================================\n\n/**\n * API for file operations.\n *\n * Provides methods to generate presigned URLs for file uploads.\n * Files are uploaded directly to S3, not through the platform.\n *\n * @example\n * ```typescript\n * // Get upload URLs\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'image.png', mediaType: 'image/png', size: 12345 }\n * ]);\n *\n * // Upload directly to S3\n * await fetch(files[0].uploadUrl, {\n * method: 'PUT',\n * body: imageFile,\n * headers: { 'Content-Type': 'image/png' }\n * });\n *\n * // Use downloadUrl as FileReference in trigger input\n * ```\n */\nexport class FilesApi extends BaseApiClient {\n /**\n * Get presigned URLs for uploading files to a session.\n *\n * Returns upload URLs (PUT) and download URLs (GET) for each file.\n * Upload URLs expire in 15 minutes, download URLs match session TTL (24 hours).\n *\n * @param sessionId - The session ID to associate files with\n * @param files - Array of file metadata (filename, mediaType, size)\n * @returns Upload info with presigned URLs for each file\n *\n * @throws ApiError if session doesn't exist or validation fails\n *\n * @example\n * ```typescript\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'photo.jpg', mediaType: 'image/jpeg', size: 102400 },\n * { filename: 'doc.pdf', mediaType: 'application/pdf', size: 204800 },\n * ]);\n *\n * // files[0].id - Use in FileReference\n * // files[0].uploadUrl - PUT to this URL\n * // files[0].downloadUrl - Use as FileReference.url\n * ```\n */\n async getUploadUrls(sessionId: string, files: FileUploadRequest[]): Promise<UploadUrlsResponse> {\n return await this.httpPost(\n '/api/files/upload-urls',\n { sessionId, files },\n uploadUrlsResponseSchema,\n );\n }\n}\n","/** Error thrown when a worker execution fails */\nexport class WorkerError extends Error {\n constructor(\n message: string,\n /** Session ID if the worker started before failing (for debugging URLs) */\n public readonly sessionId?: string,\n ) {\n super(message);\n this.name = 'WorkerError';\n }\n}\n","import type { StreamEvent, ToolHandlers, ToolResult } from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { executeStream } from '@/streaming.js';\nimport { WorkerError } from '@/worker-error.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new worker execution */\nexport interface WorkerStartRequest {\n type: 'start';\n input: Record<string, unknown>;\n}\n\n/** Continue execution after client-side tool handling */\nexport interface WorkerContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by workers */\nexport type WorkerRequest = WorkerStartRequest | WorkerContinueRequest;\n\n// =============================================================================\n// Execution Options & Results\n// =============================================================================\n\n/** Options for worker execution */\nexport interface WorkerExecuteOptions {\n /** Tool handlers for server-side tool execution */\n tools?: ToolHandlers;\n /** Abort signal to cancel the execution */\n signal?: AbortSignal;\n}\n\n/** Result from a non-streaming worker execution via `generate()` */\nexport interface WorkerGenerateResult {\n /** The worker's output value */\n output: unknown;\n /** Session ID for the worker execution (usable for debugging/session URLs) */\n sessionId: string;\n}\n\n// =============================================================================\n// Workers API\n// =============================================================================\n\n/** API for executing worker agents */\nexport class WorkersApi extends BaseApiClient {\n /**\n * Execute a worker agent and stream the response.\n *\n * Worker agents execute steps sequentially and return an output value.\n * Unlike interactive sessions, workers don't maintain persistent state.\n *\n * The execution handles the tool continuation pattern automatically:\n * - Server tools (with handlers provided) are executed automatically\n * - Client tools (without handlers) emit a client-tool-request event\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example Basic execution\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' });\n * for await (const event of events) {\n * if (event.type === 'worker-start') {\n * console.log(`Worker ${event.workerSlug} started (${event.workerId})`);\n * }\n * if (event.type === 'worker-result') {\n * if (event.error) {\n * console.error('Worker failed:', event.error);\n * } else {\n * console.log('Output:', event.output);\n * }\n * }\n * }\n * ```\n *\n * @example With tool handlers\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' }, {\n * tools: {\n * 'web-search': async (args) => {\n * return await searchWeb(args.query);\n * },\n * },\n * });\n * ```\n */\n async *execute(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n toolHandlers: options.tools ?? {},\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId, toolResults }) =>\n !executionId ? { type: 'start', input } : { type: 'continue', executionId, toolResults },\n errorContext: 'Failed to execute worker',\n },\n {},\n options.signal,\n );\n }\n\n /**\n * Execute a worker agent and return the final output.\n *\n * Non-streaming equivalent of `execute()` — runs the worker to completion\n * and returns the output value directly. Use this when you don't need to\n * observe intermediate streaming events.\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns The worker output and session ID\n * @throws {WorkerError} If the worker fails or completes without output\n *\n * @example Basic usage\n * ```typescript\n * const { output, sessionId } = await client.workers.generate(agentId, {\n * TOPIC: 'AI safety',\n * });\n * console.log(output);\n * console.log(`Debug: ${client.baseUrl}/platform/sessions/${sessionId}`);\n * ```\n *\n * @example With timeout\n * ```typescript\n * const { output } = await client.workers.generate(agentId, input, {\n * signal: AbortSignal.timeout(120_000),\n * });\n * ```\n */\n async generate(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): Promise<WorkerGenerateResult> {\n let sessionId: string | undefined;\n\n for await (const event of this.execute(agentId, input, options)) {\n if (event.type === 'start' && event.executionId) {\n sessionId = event.executionId;\n } else if (event.type === 'error') {\n throw new WorkerError(event.message, sessionId);\n } else if (event.type === 'worker-result') {\n if (event.error) {\n throw new WorkerError(event.error, sessionId ?? event.workerId);\n }\n return {\n output: event.output,\n sessionId: sessionId ?? event.workerId,\n };\n }\n }\n\n throw new WorkerError('Worker completed without producing a result', sessionId);\n }\n\n /**\n * Continue a worker execution after client-side tool handling.\n *\n * Use this when your worker has tools without server-side handlers.\n * The execution returns a client-tool-request event with an executionId.\n * Execute the tools client-side, then call this method to continue.\n *\n * @param agentId - The worker agent ID\n * @param executionId - The execution ID from the client-tool-request event\n * @param toolResults - Results from client-side tool execution\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example\n * ```typescript\n * // Start execution\n * for await (const event of client.workers.execute(agentId, input)) {\n * if (event.type === 'client-tool-request') {\n * // Execute tools client-side\n * const results = await executeToolsClientSide(event.toolCalls);\n * // Continue execution\n * for await (const ev of client.workers.continue(agentId, event.executionId, results)) {\n * // Handle remaining events\n * }\n * }\n * }\n * ```\n */\n async *continue(\n agentId: string,\n executionId: string,\n toolResults: ToolResult[],\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n toolHandlers: options.tools ?? {},\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId: execId, toolResults: results }) => ({\n type: 'continue',\n executionId: execId ?? executionId,\n toolResults: results ?? toolResults,\n }),\n errorContext: 'Failed to continue worker',\n },\n { executionId, toolResults },\n options.signal,\n );\n }\n}\n","import type { ApiClientConfig } from '@/base-api-client.js';\nimport { AgentsApi } from '@/agents.js';\nimport { AgentSessionsApi } from '@/agent-sessions.js';\nimport { FilesApi } from '@/files.js';\nimport { WorkersApi } from '@/workers.js';\n\nexport interface OctavusClientConfig {\n baseUrl: string;\n apiKey?: string;\n /** Enable model request tracing to capture full payloads sent to providers (default: false) */\n traceModelRequests?: boolean;\n}\n\n/** Client for interacting with the Octavus platform API */\nexport class OctavusClient {\n readonly agents: AgentsApi;\n readonly agentSessions: AgentSessionsApi;\n readonly files: FilesApi;\n readonly workers: WorkersApi;\n readonly baseUrl: string;\n private readonly apiKey?: string;\n private readonly traceModelRequests: boolean;\n\n constructor(config: OctavusClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.traceModelRequests = config.traceModelRequests ?? false;\n\n const apiConfig: ApiClientConfig = {\n baseUrl: this.baseUrl,\n getHeaders: () => this.getHeaders(),\n };\n\n this.agents = new AgentsApi(apiConfig);\n this.agentSessions = new AgentSessionsApi(apiConfig);\n this.files = new FilesApi(apiConfig);\n this.workers = new WorkersApi(apiConfig);\n }\n\n getHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (this.apiKey) {\n headers.Authorization = `Bearer ${this.apiKey}`;\n }\n\n if (this.traceModelRequests) {\n headers['X-Octavus-Trace'] = 'true';\n }\n\n return headers;\n }\n}\n","/**\n * Base class for agent-managed resources.\n * Extend this class to define how each resource should be persisted when the agent updates it.\n */\nexport abstract class Resource {\n /** The resource name as defined in the agent protocol */\n abstract readonly name: string;\n\n /** Called when the agent updates this resource */\n abstract onUpdate(value: unknown): Promise<void> | void;\n}\n","import { generateId, type ToolResult, type FileReference } from '@octavus/core';\nimport type { FilesApi, FileUploadRequest } from '@/files.js';\n\ninterface ImagePart {\n type: 'image';\n data: string;\n mimeType?: string;\n}\n\nconst IMAGE_EXTENSIONS: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/webp': 'webp',\n 'image/gif': 'gif',\n 'image/svg+xml': 'svg',\n};\n\nfunction getExtensionFromMediaType(mediaType: string): string {\n return IMAGE_EXTENSIONS[mediaType] ?? 'png';\n}\n\nfunction isImagePart(part: unknown): part is ImagePart {\n return (\n typeof part === 'object' &&\n part !== null &&\n (part as Record<string, unknown>).type === 'image' &&\n typeof (part as Record<string, unknown>).data === 'string'\n );\n}\n\nfunction hasImageParts(value: unknown): value is unknown[] {\n return Array.isArray(value) && value.some(isImagePart);\n}\n\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const buffer = new ArrayBuffer(binary.length);\n const view = new Uint8Array(buffer);\n for (let i = 0; i < binary.length; i++) {\n view[i] = binary.charCodeAt(i);\n }\n return buffer;\n}\n\n/**\n * Extract base64 image blobs from tool results, upload them to S3 via\n * presigned URLs, and replace inline data with compact metadata +\n * FileReference entries.\n *\n * Runs at the server-sdk streaming layer so images are uploaded before\n * tool results travel over the network (WebSocket, HTTP continuation).\n */\nexport async function normalizeToolResultImages(\n toolResults: ToolResult[],\n filesApi: FilesApi,\n sessionId: string,\n): Promise<void> {\n for (const toolResult of toolResults) {\n if (toolResult.outputVariable) continue;\n if (!hasImageParts(toolResult.result)) continue;\n\n const parts = toolResult.result;\n const files: FileReference[] = toolResult.files ? [...toolResult.files] : [];\n\n const imageIndices: number[] = [];\n const imageBuffers: ArrayBuffer[] = [];\n const uploadRequests: FileUploadRequest[] = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (!isImagePart(part)) continue;\n\n const buffer = base64ToArrayBuffer(part.data);\n const mimeType = part.mimeType || 'image/png';\n\n imageIndices.push(i);\n imageBuffers.push(buffer);\n uploadRequests.push({\n filename: `image-${generateId()}.${getExtensionFromMediaType(mimeType)}`,\n mediaType: mimeType,\n size: buffer.byteLength,\n });\n }\n\n if (uploadRequests.length === 0) continue;\n\n let uploadInfos: { id: string; uploadUrl: string; downloadUrl: string }[];\n try {\n const response = await filesApi.getUploadUrls(sessionId, uploadRequests);\n uploadInfos = response.files;\n } catch {\n continue;\n }\n\n const uploadResults = await Promise.allSettled(\n uploadInfos.map((info, i) =>\n fetch(info.uploadUrl, {\n method: 'PUT',\n body: imageBuffers[i]!,\n headers: { 'Content-Type': uploadRequests[i]!.mediaType },\n }),\n ),\n );\n\n const summaryParts: unknown[] = [];\n let imageIdx = 0;\n\n for (let i = 0; i < parts.length; i++) {\n if (imageIdx < imageIndices.length && imageIndices[imageIdx] === i) {\n const uploadResult = uploadResults[imageIdx]!;\n const info = uploadInfos[imageIdx]!;\n const request = uploadRequests[imageIdx]!;\n const buf = imageBuffers[imageIdx]!;\n\n if (uploadResult.status === 'fulfilled' && uploadResult.value.ok) {\n files.push({\n id: info.id,\n mediaType: request.mediaType,\n url: info.downloadUrl,\n filename: request.filename,\n size: buf.byteLength,\n });\n\n summaryParts.push({\n type: 'image',\n mediaType: request.mediaType,\n size: buf.byteLength,\n url: info.downloadUrl,\n });\n } else {\n summaryParts.push(parts[i]);\n }\n\n imageIdx += 1;\n } else {\n summaryParts.push(parts[i]);\n }\n }\n\n toolResult.files = files;\n toolResult.result = summaryParts;\n }\n}\n","export { OctavusClient, type OctavusClientConfig } from '@/client.js';\nexport { AgentsApi } from '@/agents.js';\nexport {\n AgentSessionsApi,\n type SessionState,\n type UISessionState,\n type ExpiredSessionState,\n type RestoreSessionResult,\n type ClearSessionResult,\n type SessionStatus,\n type SessionAttachOptions,\n} from '@/agent-sessions.js';\nexport {\n FilesApi,\n type FileUploadRequest,\n type FileUploadInfo,\n type UploadUrlsResponse,\n} from '@/files.js';\nexport {\n AgentSession,\n toSSEStream,\n type SessionConfig,\n type TriggerOptions,\n type SessionRequest,\n type TriggerRequest,\n type ContinueRequest,\n type StopMessage,\n type SocketMessage,\n type SocketMessageHandlers,\n} from '@/session.js';\nexport {\n WorkersApi,\n type WorkerStartRequest,\n type WorkerContinueRequest,\n type WorkerRequest,\n type WorkerExecuteOptions,\n type WorkerGenerateResult,\n} from '@/workers.js';\nexport { WorkerError } from '@/worker-error.js';\nexport { Resource } from '@/resource.js';\nexport { ApiError } from '@/api-error.js';\nexport { normalizeToolResultImages } from '@/normalize-images.js';\n\n// Agent types (read-only - use @octavus/cli for agent management)\nexport type {\n AgentFormat,\n AgentSettings,\n AgentPrompt,\n Agent,\n AgentDefinition,\n} from '@/agent-types.js';\n\nexport type * from '@octavus/core';\nexport {\n // Error classes\n AppError,\n NotFoundError,\n ValidationError,\n ConflictError,\n ForbiddenError,\n OctavusError,\n // Error type guards\n isRateLimitError,\n isAuthenticationError,\n isProviderError,\n isToolError,\n isRetryableError,\n isValidationError,\n // Error event helpers\n createErrorEvent,\n errorToStreamEvent,\n createInternalErrorEvent,\n createApiErrorEvent,\n // Utilities\n generateId,\n isAbortError,\n // Thread helpers\n MAIN_THREAD,\n resolveThread,\n isMainThread,\n threadForPart,\n isOtherThread,\n // Type guards\n isFileReference,\n isFileReferenceArray,\n // Safe parse helpers\n safeParseStreamEvent,\n safeParseUIMessage,\n safeParseUIMessages,\n // Skills\n OCTAVUS_SKILL_TOOLS,\n isOctavusSkillTool,\n getSkillSlugFromToolCall,\n} from '@octavus/core';\n"],"mappings":"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","names":["z","z","createInternalErrorEvent","createInternalErrorEvent","z","z","z","createInternalErrorEvent","createApiErrorEvent","generateId","isAbortError","safeParseStreamEvent"]}
1
+ {"version":3,"sources":["../src/api-error.ts","../src/base-api-client.ts","../src/agent-types.ts","../src/agents.ts","../src/agent-sessions.ts","../src/session.ts","../src/streaming.ts","../src/files.ts","../src/worker-error.ts","../src/workers.ts","../src/client.ts","../src/resource.ts","../src/normalize-images.ts","../src/index.ts"],"sourcesContent":["import { z } from 'zod';\n\nconst ApiErrorResponseSchema = z.object({\n error: z.string().optional(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n/**\n * Error thrown when API request fails\n */\nexport class ApiError extends Error {\n constructor(\n message: string,\n public status: number,\n public code?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\ninterface ParsedApiError {\n message: string;\n code?: string;\n}\n\n/**\n * Parse error from API response using Zod\n */\nexport async function parseApiError(\n response: Response,\n defaultMessage: string,\n): Promise<ParsedApiError> {\n const fallbackMessage = `${defaultMessage}: ${response.statusText}`;\n\n try {\n const json: unknown = await response.json();\n const parsed = ApiErrorResponseSchema.safeParse(json);\n\n if (parsed.success) {\n return {\n message: parsed.data.error ?? parsed.data.message ?? fallbackMessage,\n code: parsed.data.code,\n };\n }\n } catch {\n // Use default message\n }\n\n return { message: fallbackMessage };\n}\n\n/**\n * Parse error from API response and throw ApiError\n */\nexport async function throwApiError(response: Response, defaultMessage: string): Promise<never> {\n const { message, code } = await parseApiError(response, defaultMessage);\n throw new ApiError(message, response.status, code);\n}\n","import type { ZodType } from 'zod';\nimport { throwApiError } from '@/api-error.js';\n\nexport { ApiError } from '@/api-error.js';\n\nexport interface ApiClientConfig {\n baseUrl: string;\n getHeaders: () => Record<string, string>;\n}\n\n/** Base class for API clients with shared HTTP utilities */\nexport abstract class BaseApiClient {\n protected readonly config: ApiClientConfig;\n\n constructor(config: ApiClientConfig) {\n this.config = config;\n }\n\n protected async httpGet<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPost<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'POST',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpPatch<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'PATCH',\n headers: this.config.getHeaders(),\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n\n protected async httpDelete<T>(path: string, schema: ZodType<T>): Promise<T> {\n const response = await fetch(`${this.config.baseUrl}${path}`, {\n method: 'DELETE',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n return schema.parse(data);\n }\n}\n","import { z } from 'zod';\n\n/** Agent format - interactive (chat) or worker (background task) */\nexport type AgentFormat = 'interactive' | 'worker';\n\n/** Agent settings */\nexport interface AgentSettings {\n slug: string;\n name: string;\n description?: string;\n format: AgentFormat;\n}\n\n/** Agent prompt */\nexport interface AgentPrompt {\n name: string;\n content: string;\n}\n\n/**\n * Agent summary returned from list endpoint\n */\nexport interface Agent {\n /** Agent slug (human-readable identifier within project) */\n slug: string;\n /** Agent ID - use this for API calls */\n id: string;\n name: string;\n description: string | null;\n format: AgentFormat;\n createdAt: string;\n updatedAt: string;\n projectId: string;\n}\n\n/**\n * Full agent definition returned from get endpoint\n */\nexport interface AgentDefinition {\n settings: AgentSettings;\n protocol: string;\n prompts: AgentPrompt[];\n /** Agent ID - use this for API calls like createSession */\n id: string;\n}\n\n// Schemas\n\nexport const agentFormatSchema = z.enum(['interactive', 'worker']);\n\nconst agentSettingsSchema = z.object({\n slug: z.string(),\n name: z.string(),\n description: z.string().optional(),\n format: agentFormatSchema,\n});\n\nconst agentPromptSchema = z.object({\n name: z.string(),\n content: z.string(),\n});\n\nexport const agentSchema = z.object({\n slug: z.string(),\n id: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n format: agentFormatSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n projectId: z.string(),\n});\n\nexport const agentsResponseSchema = z.object({\n agents: z.array(agentSchema),\n});\n\nexport const agentDefinitionSchema = z.object({\n settings: agentSettingsSchema,\n protocol: z.string(),\n prompts: z.array(agentPromptSchema),\n id: z.string(),\n});\n","import { BaseApiClient } from '@/base-api-client.js';\nimport {\n agentsResponseSchema,\n agentDefinitionSchema,\n type Agent,\n type AgentDefinition,\n} from '@/agent-types.js';\n\n/**\n * API for listing and retrieving agent definitions.\n *\n * Note: Agent management (create, update, sync) should be done via the @octavus/cli package.\n * This API uses agent IDs only - use CLI for slug-based operations.\n */\nexport class AgentsApi extends BaseApiClient {\n /** List all agents in the project */\n async list(): Promise<Agent[]> {\n const response = await this.httpGet('/api/agents', agentsResponseSchema);\n return response.agents;\n }\n\n /** Get a single agent by ID */\n async get(agentId: string): Promise<AgentDefinition> {\n return await this.httpGet(`/api/agents/${agentId}`, agentDefinitionSchema);\n }\n}\n","import { z } from 'zod';\nimport {\n chatMessageSchema,\n uiMessageSchema,\n type ChatMessage,\n type ToolHandlers,\n type ToolResult,\n type UIMessage,\n} from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { throwApiError } from '@/api-error.js';\nimport { AgentSession } from '@/session.js';\nimport type { Resource } from '@/resource.js';\n\nconst createSessionResponseSchema = z.object({\n sessionId: z.string(),\n});\n\nconst sessionStateSchema = z.object({\n id: z.string(),\n agentId: z.string(),\n input: z.record(z.string(), z.unknown()),\n variables: z.record(z.string(), z.unknown()),\n resources: z.record(z.string(), z.unknown()),\n messages: z.array(chatMessageSchema),\n status: z.literal('active').optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n});\n\nconst uiSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n messages: z.array(uiMessageSchema),\n status: z.literal('active').optional(),\n});\n\nconst expiredSessionResponseSchema = z.object({\n sessionId: z.string(),\n agentId: z.string(),\n status: z.literal('expired'),\n createdAt: z.string(),\n});\n\nconst restoreSessionResponseSchema = z.object({\n sessionId: z.string(),\n restored: z.boolean(),\n});\n\nconst clearSessionResponseSchema = z.object({\n sessionId: z.string(),\n cleared: z.boolean(),\n});\n\n/** Session status indicating whether it's active or expired */\nexport type SessionStatus = 'active' | 'expired';\n\nexport interface SessionState {\n id: string;\n agentId: string;\n input: Record<string, unknown>;\n variables: Record<string, unknown>;\n resources: Record<string, unknown>;\n messages: ChatMessage[];\n status?: 'active';\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface UISessionState {\n sessionId: string;\n agentId: string;\n messages: UIMessage[];\n status?: 'active';\n}\n\nexport interface ExpiredSessionState {\n sessionId: string;\n agentId: string;\n status: 'expired';\n createdAt: string;\n}\n\nexport interface RestoreSessionResult {\n sessionId: string;\n /** True if session was restored from messages, false if already active */\n restored: boolean;\n}\n\nexport interface ClearSessionResult {\n sessionId: string;\n cleared: boolean;\n}\n\nexport interface SessionAttachOptions {\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/** API for managing agent sessions */\nexport class AgentSessionsApi extends BaseApiClient {\n /** Create a new session for an agent */\n async create(agentId: string, input?: Record<string, unknown>): Promise<string> {\n const response = await this.httpPost(\n '/api/agent-sessions',\n { agentId, input },\n createSessionResponseSchema,\n );\n return response.sessionId;\n }\n\n /**\n * Get full session state (for internal/debug use)\n * Note: Contains all messages including hidden content\n *\n * Returns SessionState for active sessions, ExpiredSessionState for expired sessions.\n * Check `status` field to determine which type was returned.\n */\n async get(sessionId: string): Promise<SessionState | ExpiredSessionState> {\n const response = await fetch(`${this.config.baseUrl}/api/agent-sessions/${sessionId}`, {\n method: 'GET',\n headers: this.config.getHeaders(),\n });\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return sessionStateSchema.parse(data);\n }\n\n /**\n * Get UI-ready session messages (for client display)\n * Returns only visible messages with hidden content filtered out.\n *\n * For expired sessions, returns status: 'expired' without messages.\n * Use restore() to restore from stored messages before continuing.\n */\n async getMessages(sessionId: string): Promise<UISessionState | ExpiredSessionState> {\n const response = await fetch(\n `${this.config.baseUrl}/api/agent-sessions/${sessionId}?format=ui`,\n {\n method: 'GET',\n headers: this.config.getHeaders(),\n },\n );\n\n if (!response.ok) {\n await throwApiError(response, 'Request failed');\n }\n\n const data: unknown = await response.json();\n\n const expiredResult = expiredSessionResponseSchema.safeParse(data);\n if (expiredResult.success) {\n return expiredResult.data;\n }\n\n return uiSessionResponseSchema.parse(data);\n }\n\n /**\n * Restore an expired session from stored messages.\n *\n * Use this to restore a session after its state has expired.\n * The consumer should have stored the UIMessage[] array from previous interactions.\n *\n * @param sessionId - The session ID to restore\n * @param messages - Previously stored UIMessage[] array\n * @param input - Optional session input for system prompt interpolation (same as create)\n * @returns { sessionId, restored: true } if restored, { sessionId, restored: false } if already active\n */\n async restore(\n sessionId: string,\n messages: UIMessage[],\n input?: Record<string, unknown>,\n ): Promise<RestoreSessionResult> {\n return await this.httpPost(\n `/api/agent-sessions/${sessionId}/restore`,\n { messages, input },\n restoreSessionResponseSchema,\n );\n }\n\n /**\n * Clear session state from the server.\n * The session will transition to 'expired' status and can be restored with restore().\n * Idempotent: succeeds even if state was already cleared/expired.\n */\n async clear(sessionId: string): Promise<ClearSessionResult> {\n return await this.httpDelete(`/api/agent-sessions/${sessionId}`, clearSessionResponseSchema);\n }\n\n /** Attach to an existing session for triggering events */\n attach(sessionId: string, options: SessionAttachOptions = {}): AgentSession {\n return new AgentSession({\n sessionId,\n config: this.config,\n tools: options.tools,\n resources: options.resources,\n onToolResults: options.onToolResults,\n rejectClientToolCalls: options.rejectClientToolCalls,\n });\n }\n}\n","import {\n createInternalErrorEvent,\n type DynamicTool,\n type StreamEvent,\n type ToolHandlers,\n type ToolProvider,\n type ToolResult,\n type ToolSchema,\n} from '@octavus/core';\nimport type { ApiClientConfig } from '@/base-api-client.js';\nimport type { Resource } from '@/resource.js';\nimport { executeStream } from '@/streaming.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new trigger execution */\nexport interface TriggerRequest {\n type: 'trigger';\n triggerName: string;\n input?: Record<string, unknown>;\n /** ID of the last message to keep. Messages after this are removed before execution. `null` = truncate all. */\n rollbackAfterMessageId?: string | null;\n}\n\n/** Continue execution after client-side tool handling */\nexport interface ContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by the session */\nexport type SessionRequest = TriggerRequest | ContinueRequest;\n\n/** Stop message to abort in-flight requests */\nexport interface StopMessage {\n type: 'stop';\n}\n\n/** All socket protocol messages (trigger, continue, stop) */\nexport type SocketMessage = TriggerRequest | ContinueRequest | StopMessage;\n\n// =============================================================================\n// Socket Message Handler Types\n// =============================================================================\n\n/** Handlers for socket message streaming */\nexport interface SocketMessageHandlers {\n /** Called for each stream event */\n onEvent: (event: StreamEvent) => void;\n /** Called after streaming completes (not called if aborted) */\n onFinish?: () => void | Promise<void>;\n}\n\nconst SSE_HEARTBEAT_INTERVAL_MS = 15_000;\n\n/**\n * Converts an async iterable of stream events to an SSE-formatted ReadableStream.\n * Use this when you need to return an SSE response (e.g., HTTP endpoints).\n *\n * @example\n * ```typescript\n * const events = session.trigger('user-message', input);\n * return new Response(toSSEStream(events), {\n * headers: { 'Content-Type': 'text/event-stream' },\n * });\n * ```\n */\nexport function toSSEStream(events: AsyncIterable<StreamEvent>): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const heartbeatBytes = encoder.encode(': heartbeat\\n\\n');\n\n return new ReadableStream({\n async start(controller) {\n const heartbeat = setInterval(() => {\n try {\n controller.enqueue(heartbeatBytes);\n } catch {\n clearInterval(heartbeat);\n }\n }, SSE_HEARTBEAT_INTERVAL_MS);\n\n try {\n for await (const event of events) {\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\\n\\n`));\n }\n controller.enqueue(encoder.encode('data: [DONE]\\n\\n'));\n controller.close();\n } catch (err) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}\\n\\n`));\n controller.close();\n } finally {\n clearInterval(heartbeat);\n }\n },\n });\n}\n\nfunction resolveDynamicTools(provider: ToolProvider): DynamicTool[] {\n const handlers = provider.toolHandlers();\n return provider\n .toolSchemas()\n .filter((s) => handlers[s.name])\n .map((s) => ({ schema: s, handler: handlers[s.name]! }));\n}\n\nexport interface SessionConfig {\n sessionId: string;\n config: ApiClientConfig;\n tools?: ToolHandlers;\n resources?: Resource[];\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** When true, unhandled tool calls return errors instead of being emitted as client-tool-request events. */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Options for trigger execution.\n */\nexport interface TriggerOptions {\n /** Abort signal to cancel the trigger execution */\n signal?: AbortSignal;\n}\n\n/** Handles streaming and tool continuation for agent sessions */\nexport class AgentSession {\n private sessionId: string;\n private config: ApiClientConfig;\n private toolHandlers: ToolHandlers;\n private resourceMap: Map<string, Resource>;\n private dynamicToolSchemas: ToolSchema[] | undefined;\n private dynamicToolNames = new Set<string>();\n private socketAbortController: AbortController | null = null;\n private onToolResults?: (results: ToolResult[]) => Promise<void>;\n private rejectClientToolCalls: boolean;\n\n constructor(sessionConfig: SessionConfig) {\n this.sessionId = sessionConfig.sessionId;\n this.config = sessionConfig.config;\n this.toolHandlers = sessionConfig.tools ?? {};\n this.onToolResults = sessionConfig.onToolResults;\n this.rejectClientToolCalls = sessionConfig.rejectClientToolCalls ?? false;\n this.resourceMap = new Map();\n\n for (const resource of sessionConfig.resources ?? []) {\n this.resourceMap.set(resource.name, resource);\n }\n }\n\n /**\n * Execute a session request and stream the response.\n *\n * This is the unified method that handles both triggers and continuations.\n * Use this when you want to pass through requests from the client directly.\n *\n * @param request - The request (check `request.type` for the kind)\n * @param options - Optional configuration including abort signal\n *\n * @example HTTP route (simple passthrough)\n * ```typescript\n * const events = session.execute(body, { signal: request.signal });\n * return new Response(toSSEStream(events));\n * ```\n *\n * @example WebSocket handler\n * ```typescript\n * socket.on('message', (data) => {\n * const events = session.execute(data);\n * for await (const event of events) {\n * socket.send(JSON.stringify(event));\n * }\n * });\n * ```\n */\n async *execute(request: SessionRequest, options?: TriggerOptions): AsyncGenerator<StreamEvent> {\n if (request.type === 'continue') {\n yield* this.executeStream(\n { executionId: request.executionId, toolResults: request.toolResults },\n options?.signal,\n );\n } else {\n yield* this.executeStream(\n {\n triggerName: request.triggerName,\n input: request.input,\n rollbackAfterMessageId: request.rollbackAfterMessageId,\n },\n options?.signal,\n );\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n /**\n * Set the full list of dynamic tools (schemas + handlers).\n * Replaces any previously set dynamic tools — removed tools are\n * unregistered, new ones are added, and updated schemas are sent\n * to the platform on the next request.\n *\n * Accepts either a `ToolProvider` (e.g. `Computer`) or an explicit\n * `DynamicTool[]` array.\n *\n * Safe to call mid-session: executeStream resolves toolHandlers via\n * a getter on each continuation loop, so new handlers are visible\n * immediately.\n */\n setDynamicTools(source: ToolProvider | DynamicTool[]): void {\n const tools = Array.isArray(source) ? source : resolveDynamicTools(source);\n const newNames = new Set(tools.map((t) => t.schema.name));\n\n const cleaned: ToolHandlers = {};\n for (const [name, handler] of Object.entries(this.toolHandlers)) {\n if (!this.dynamicToolNames.has(name)) {\n cleaned[name] = handler;\n }\n }\n\n for (const tool of tools) {\n cleaned[tool.schema.name] = tool.handler;\n }\n\n this.toolHandlers = cleaned;\n this.dynamicToolNames = newNames;\n this.dynamicToolSchemas = tools.map((t) => t.schema);\n }\n\n /**\n * Handle a WebSocket protocol message (trigger, continue, or stop).\n * Manages abort controller lifecycle internally.\n *\n * @example\n * ```typescript\n * conn.on('data', (raw) => {\n * session.handleSocketMessage(JSON.parse(raw), {\n * onEvent: (event) => conn.write(JSON.stringify(event)),\n * onFinish: async () => {\n * // Fetch messages and persist to your database for restoration\n * },\n * });\n * });\n * ```\n */\n async handleSocketMessage(\n message: SocketMessage,\n handlers: SocketMessageHandlers,\n ): Promise<void> {\n if (message.type === 'stop') {\n this.socketAbortController?.abort();\n return;\n }\n\n this.socketAbortController?.abort();\n this.socketAbortController = new AbortController();\n\n const localController = this.socketAbortController;\n\n try {\n const events = this.execute(message, { signal: localController.signal });\n\n for await (const event of events) {\n if (localController.signal.aborted) break;\n handlers.onEvent(event);\n }\n\n if (!localController.signal.aborted && handlers.onFinish) {\n await handlers.onFinish();\n }\n } catch (err) {\n if (!localController.signal.aborted) {\n const errorEvent = createInternalErrorEvent(\n err instanceof Error ? err.message : 'Unknown error',\n );\n handlers.onEvent(errorEvent);\n }\n }\n }\n\n private async *executeStream(\n payload: {\n triggerName?: string;\n input?: Record<string, unknown>;\n executionId?: string;\n toolResults?: ToolResult[];\n rollbackAfterMessageId?: string | null;\n },\n signal?: AbortSignal,\n ): AsyncGenerator<StreamEvent> {\n yield* executeStream(\n {\n config: this.config,\n getToolHandlers: () => this.toolHandlers,\n url: `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,\n buildBody: ({ executionId, toolResults }) => {\n const body: Record<string, unknown> = {};\n if (payload.triggerName !== undefined) body.triggerName = payload.triggerName;\n if (payload.input !== undefined) body.input = payload.input;\n if (payload.rollbackAfterMessageId !== undefined)\n body.rollbackAfterMessageId = payload.rollbackAfterMessageId;\n if (executionId !== undefined) body.executionId = executionId;\n if (toolResults !== undefined) body.toolResults = toolResults;\n if (this.dynamicToolSchemas !== undefined) {\n body.dynamicToolSchemas = this.dynamicToolSchemas;\n }\n return body;\n },\n onResourceUpdate: (name, value) => this.handleResourceUpdate(name, value),\n onToolResults: this.onToolResults,\n rejectClientToolCalls: this.rejectClientToolCalls,\n errorContext: 'Failed to trigger',\n },\n { executionId: payload.executionId, toolResults: payload.toolResults },\n signal,\n );\n }\n\n private handleResourceUpdate(name: string, value: unknown): void {\n const resource = this.resourceMap.get(name);\n if (resource) {\n void resource.onUpdate(value);\n }\n }\n}\n","import {\n safeParseStreamEvent,\n isAbortError,\n createInternalErrorEvent,\n createApiErrorEvent,\n type StreamEvent,\n type ToolHandlers,\n type PendingToolCall,\n type ToolResult,\n} from '@octavus/core';\nimport { parseApiError } from '@/api-error.js';\nimport type { ApiClientConfig } from '@/base-api-client.js';\n\n/**\n * Configuration for streaming execution.\n */\nexport interface StreamExecutionConfig {\n /** API client config with baseUrl and headers */\n config: ApiClientConfig;\n /** Tool handlers for server-side execution. Resolved on each continuation loop. */\n getToolHandlers: () => ToolHandlers;\n /** Full URL to make the request to */\n url: string;\n /** Build the request body for this execution */\n buildBody: (state: {\n executionId?: string;\n toolResults?: ToolResult[];\n }) => Record<string, unknown>;\n /** Called when a resource-update event is received (optional) */\n onResourceUpdate?: (name: string, value: unknown) => void;\n /** Called after server-side tools execute, before yielding events or continuing. Use to normalize tool results (e.g., upload base64 images). */\n onToolResults?: (results: ToolResult[]) => Promise<void>;\n /** Error message prefix for API errors */\n errorContext?: string;\n /**\n * When true, tool calls without a registered handler return an error result\n * instead of being emitted as client-tool-request events.\n * Use for server-only execution environments (e.g., OctoAgents) that have\n * no client-side tool executor.\n */\n rejectClientToolCalls?: boolean;\n}\n\n/**\n * Initial payload for starting an execution stream.\n */\nexport interface StreamExecutionPayload {\n /** Initial execution ID (for continuation) */\n executionId?: string;\n /** Initial tool results (for continuation) */\n toolResults?: ToolResult[];\n}\n\n/**\n * Executes a streaming request with tool continuation support.\n *\n * This is the shared implementation for both interactive sessions and workers.\n * It handles:\n * - SSE stream parsing\n * - Abort signal handling\n * - Tool-request interception and server/client splitting\n * - Automatic continuation for server-handled tools\n * - Client-tool-request emission for client-handled tools\n */\nexport async function* executeStream(\n config: StreamExecutionConfig,\n payload: StreamExecutionPayload,\n signal?: AbortSignal,\n): AsyncGenerator<StreamEvent> {\n let toolResults = payload.toolResults;\n let executionId = payload.executionId;\n let continueLoop = true;\n\n while (continueLoop) {\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n const body = config.buildBody({ executionId, toolResults });\n\n let response: Response;\n try {\n response = await fetch(config.url, {\n method: 'POST',\n headers: config.config.getHeaders(),\n body: JSON.stringify(body),\n signal,\n });\n } catch (err) {\n if (isAbortError(err)) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n if (!response.ok) {\n const { message } = await parseApiError(response, config.errorContext ?? 'Request failed');\n yield createApiErrorEvent(response.status, message);\n return;\n }\n\n if (!response.body) {\n yield createInternalErrorEvent('Response body is not readable');\n return;\n }\n\n toolResults = undefined;\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let pendingToolCalls: PendingToolCall[] | null = null;\n\n let streamDone = false;\n while (!streamDone) {\n if (signal?.aborted) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n let readResult: ReadableStreamReadResult<Uint8Array>;\n try {\n readResult = await reader.read();\n } catch (err) {\n if (isAbortError(err)) {\n reader.releaseLock();\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n throw err;\n }\n\n const { done, value } = readResult;\n\n if (done) {\n streamDone = true;\n continue;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const parsed = safeParseStreamEvent(JSON.parse(line.slice(6)));\n if (!parsed.success) {\n continue;\n }\n const event = parsed.data;\n\n if (event.type === 'start' && event.executionId) {\n executionId = event.executionId;\n }\n\n if (event.type === 'tool-request') {\n pendingToolCalls = event.toolCalls;\n continue;\n }\n\n if (event.type === 'finish') {\n if (event.finishReason === 'tool-calls' && pendingToolCalls) {\n continue;\n }\n yield event;\n continueLoop = false;\n continue;\n }\n\n if (event.type === 'resource-update' && config.onResourceUpdate) {\n config.onResourceUpdate(event.name, event.value);\n }\n\n yield event;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n\n if (signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n if (pendingToolCalls && pendingToolCalls.length > 0) {\n const toolHandlers = config.getToolHandlers();\n const serverTools = pendingToolCalls.filter((tc) => toolHandlers[tc.toolName]);\n const clientTools = pendingToolCalls.filter((tc) => !toolHandlers[tc.toolName]);\n\n const serverResults = await Promise.all(\n serverTools.map(async (tc): Promise<ToolResult> => {\n const handler = toolHandlers[tc.toolName]!;\n try {\n const result = await handler(tc.args);\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n result,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n } catch (err) {\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: err instanceof Error ? err.message : 'Tool execution failed',\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n };\n }\n }),\n );\n\n if (config.onToolResults && serverResults.length > 0) {\n await config.onToolResults(serverResults);\n }\n\n for (const tr of serverResults) {\n if (tr.error) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error };\n } else {\n yield { type: 'tool-output-available', toolCallId: tr.toolCallId, output: tr.result };\n }\n }\n\n if (clientTools.length > 0) {\n if (config.rejectClientToolCalls) {\n const rejectedResults: ToolResult[] = clientTools.map((tc) => ({\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: `Tool \"${tc.toolName}\" is not available. No handler is registered for this tool.`,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n thread: tc.thread,\n workerId: tc.workerId,\n }));\n for (const tr of rejectedResults) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, error: tr.error! };\n }\n toolResults = [...serverResults, ...rejectedResults];\n } else {\n if (!executionId) {\n yield createInternalErrorEvent('Missing executionId for client-tool-request');\n return;\n }\n yield {\n type: 'client-tool-request',\n executionId,\n toolCalls: clientTools,\n serverToolResults: serverResults.length > 0 ? serverResults : undefined,\n };\n yield { type: 'finish', finishReason: 'client-tool-calls', executionId };\n continueLoop = false;\n }\n } else {\n toolResults = serverResults;\n }\n } else {\n continueLoop = false;\n }\n }\n}\n","import { z } from 'zod';\nimport { BaseApiClient } from '@/base-api-client.js';\n\n// =============================================================================\n// Schemas\n// =============================================================================\n\n/**\n * Schema for a single file upload request\n */\nexport const fileUploadRequestSchema = z.object({\n filename: z.string().min(1).max(255),\n mediaType: z.string().min(1),\n size: z.number().int().positive(),\n});\n\n/**\n * Schema for a single file upload response\n */\nexport const fileUploadInfoSchema = z.object({\n /** File ID to reference in messages */\n id: z.string(),\n /** Presigned PUT URL for uploading to S3 */\n uploadUrl: z.url(),\n /** Presigned GET URL for downloading after upload */\n downloadUrl: z.url(),\n});\n\n/**\n * Schema for the upload URLs response\n */\nexport const uploadUrlsResponseSchema = z.object({\n files: z.array(fileUploadInfoSchema),\n});\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type FileUploadRequest = z.infer<typeof fileUploadRequestSchema>;\nexport type FileUploadInfo = z.infer<typeof fileUploadInfoSchema>;\nexport type UploadUrlsResponse = z.infer<typeof uploadUrlsResponseSchema>;\n\n// =============================================================================\n// API\n// =============================================================================\n\n/**\n * API for file operations.\n *\n * Provides methods to generate presigned URLs for file uploads.\n * Files are uploaded directly to S3, not through the platform.\n *\n * @example\n * ```typescript\n * // Get upload URLs\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'image.png', mediaType: 'image/png', size: 12345 }\n * ]);\n *\n * // Upload directly to S3\n * await fetch(files[0].uploadUrl, {\n * method: 'PUT',\n * body: imageFile,\n * headers: { 'Content-Type': 'image/png' }\n * });\n *\n * // Use downloadUrl as FileReference in trigger input\n * ```\n */\nexport class FilesApi extends BaseApiClient {\n /**\n * Get presigned URLs for uploading files to a session.\n *\n * Returns upload URLs (PUT) and download URLs (GET) for each file.\n * Upload URLs expire in 15 minutes, download URLs match session TTL (24 hours).\n *\n * @param sessionId - The session ID to associate files with\n * @param files - Array of file metadata (filename, mediaType, size)\n * @returns Upload info with presigned URLs for each file\n *\n * @throws ApiError if session doesn't exist or validation fails\n *\n * @example\n * ```typescript\n * const { files } = await client.files.getUploadUrls(sessionId, [\n * { filename: 'photo.jpg', mediaType: 'image/jpeg', size: 102400 },\n * { filename: 'doc.pdf', mediaType: 'application/pdf', size: 204800 },\n * ]);\n *\n * // files[0].id - Use in FileReference\n * // files[0].uploadUrl - PUT to this URL\n * // files[0].downloadUrl - Use as FileReference.url\n * ```\n */\n async getUploadUrls(sessionId: string, files: FileUploadRequest[]): Promise<UploadUrlsResponse> {\n return await this.httpPost(\n '/api/files/upload-urls',\n { sessionId, files },\n uploadUrlsResponseSchema,\n );\n }\n}\n","/** Error thrown when a worker execution fails */\nexport class WorkerError extends Error {\n constructor(\n message: string,\n /** Session ID if the worker started before failing (for debugging URLs) */\n public readonly sessionId?: string,\n ) {\n super(message);\n this.name = 'WorkerError';\n }\n}\n","import type { StreamEvent, ToolHandlers, ToolResult, ToolSchema } from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.js';\nimport { executeStream } from '@/streaming.js';\nimport { WorkerError } from '@/worker-error.js';\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\n/** Start a new worker execution */\nexport interface WorkerStartRequest {\n type: 'start';\n input: Record<string, unknown>;\n /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */\n dynamicToolSchemas?: ToolSchema[];\n}\n\n/** Continue execution after client-side tool handling */\nexport interface WorkerContinueRequest {\n type: 'continue';\n executionId: string;\n toolResults: ToolResult[];\n}\n\n/** All request types supported by workers */\nexport type WorkerRequest = WorkerStartRequest | WorkerContinueRequest;\n\n// =============================================================================\n// Execution Options & Results\n// =============================================================================\n\n/** Options for worker execution */\nexport interface WorkerExecuteOptions {\n /** Tool handlers for server-side tool execution */\n tools?: ToolHandlers;\n /** Abort signal to cancel the execution */\n signal?: AbortSignal;\n /** Tool schemas for runtime-discovered tools (device MCPs, etc.) */\n dynamicToolSchemas?: ToolSchema[];\n}\n\n/** Result from a non-streaming worker execution via `generate()` */\nexport interface WorkerGenerateResult {\n /** The worker's output value */\n output: unknown;\n /** Session ID for the worker execution (usable for debugging/session URLs) */\n sessionId: string;\n}\n\n// =============================================================================\n// Workers API\n// =============================================================================\n\n/** API for executing worker agents */\nexport class WorkersApi extends BaseApiClient {\n /**\n * Execute a worker agent and stream the response.\n *\n * Worker agents execute steps sequentially and return an output value.\n * Unlike interactive sessions, workers don't maintain persistent state.\n *\n * The execution handles the tool continuation pattern automatically:\n * - Server tools (with handlers provided) are executed automatically\n * - Client tools (without handlers) emit a client-tool-request event\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example Basic execution\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' });\n * for await (const event of events) {\n * if (event.type === 'worker-start') {\n * console.log(`Worker ${event.workerSlug} started (${event.workerId})`);\n * }\n * if (event.type === 'worker-result') {\n * if (event.error) {\n * console.error('Worker failed:', event.error);\n * } else {\n * console.log('Output:', event.output);\n * }\n * }\n * }\n * ```\n *\n * @example With tool handlers\n * ```typescript\n * const events = client.workers.execute(agentId, { TOPIC: 'AI safety' }, {\n * tools: {\n * 'web-search': async (args) => {\n * return await searchWeb(args.query);\n * },\n * },\n * });\n * ```\n */\n async *execute(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n const tools = options.tools ?? {};\n yield* executeStream(\n {\n config: this.config,\n getToolHandlers: () => tools,\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId, toolResults }) =>\n !executionId\n ? {\n type: 'start',\n input,\n ...(options.dynamicToolSchemas !== undefined && {\n dynamicToolSchemas: options.dynamicToolSchemas,\n }),\n }\n : { type: 'continue', executionId, toolResults },\n errorContext: 'Failed to execute worker',\n },\n {},\n options.signal,\n );\n }\n\n /**\n * Execute a worker agent and return the final output.\n *\n * Non-streaming equivalent of `execute()` — runs the worker to completion\n * and returns the output value directly. Use this when you don't need to\n * observe intermediate streaming events.\n *\n * @param agentId - The worker agent ID\n * @param input - Input values for the worker\n * @param options - Optional configuration including tools and abort signal\n * @returns The worker output and session ID\n * @throws {WorkerError} If the worker fails or completes without output\n *\n * @example Basic usage\n * ```typescript\n * const { output, sessionId } = await client.workers.generate(agentId, {\n * TOPIC: 'AI safety',\n * });\n * console.log(output);\n * console.log(`Debug: ${client.baseUrl}/platform/sessions/${sessionId}`);\n * ```\n *\n * @example With timeout\n * ```typescript\n * const { output } = await client.workers.generate(agentId, input, {\n * signal: AbortSignal.timeout(120_000),\n * });\n * ```\n */\n async generate(\n agentId: string,\n input: Record<string, unknown>,\n options: WorkerExecuteOptions = {},\n ): Promise<WorkerGenerateResult> {\n let sessionId: string | undefined;\n\n for await (const event of this.execute(agentId, input, options)) {\n if (event.type === 'start' && event.executionId) {\n sessionId = event.executionId;\n } else if (event.type === 'error') {\n throw new WorkerError(event.message, sessionId);\n } else if (event.type === 'worker-result') {\n if (event.error) {\n throw new WorkerError(event.error, sessionId ?? event.workerId);\n }\n return {\n output: event.output,\n sessionId: sessionId ?? event.workerId,\n };\n }\n }\n\n throw new WorkerError('Worker completed without producing a result', sessionId);\n }\n\n /**\n * Continue a worker execution after client-side tool handling.\n *\n * Use this when your worker has tools without server-side handlers.\n * The execution returns a client-tool-request event with an executionId.\n * Execute the tools client-side, then call this method to continue.\n *\n * @param agentId - The worker agent ID\n * @param executionId - The execution ID from the client-tool-request event\n * @param toolResults - Results from client-side tool execution\n * @param options - Optional configuration including tools and abort signal\n * @returns An async generator of stream events\n *\n * @example\n * ```typescript\n * // Start execution\n * for await (const event of client.workers.execute(agentId, input)) {\n * if (event.type === 'client-tool-request') {\n * // Execute tools client-side\n * const results = await executeToolsClientSide(event.toolCalls);\n * // Continue execution\n * for await (const ev of client.workers.continue(agentId, event.executionId, results)) {\n * // Handle remaining events\n * }\n * }\n * }\n * ```\n */\n async *continue(\n agentId: string,\n executionId: string,\n toolResults: ToolResult[],\n options: WorkerExecuteOptions = {},\n ): AsyncGenerator<StreamEvent> {\n const tools = options.tools ?? {};\n yield* executeStream(\n {\n config: this.config,\n getToolHandlers: () => tools,\n url: `${this.config.baseUrl}/api/agents/${agentId}/execute`,\n buildBody: ({ executionId: execId, toolResults: results }) => ({\n type: 'continue',\n executionId: execId ?? executionId,\n toolResults: results ?? toolResults,\n }),\n errorContext: 'Failed to continue worker',\n },\n { executionId, toolResults },\n options.signal,\n );\n }\n}\n","import type { ApiClientConfig } from '@/base-api-client.js';\nimport { AgentsApi } from '@/agents.js';\nimport { AgentSessionsApi } from '@/agent-sessions.js';\nimport { FilesApi } from '@/files.js';\nimport { WorkersApi } from '@/workers.js';\n\nexport interface OctavusClientConfig {\n baseUrl: string;\n apiKey?: string;\n /** Enable model request tracing to capture full payloads sent to providers (default: false) */\n traceModelRequests?: boolean;\n}\n\n/** Client for interacting with the Octavus platform API */\nexport class OctavusClient {\n readonly agents: AgentsApi;\n readonly agentSessions: AgentSessionsApi;\n readonly files: FilesApi;\n readonly workers: WorkersApi;\n readonly baseUrl: string;\n private readonly apiKey?: string;\n private readonly traceModelRequests: boolean;\n\n constructor(config: OctavusClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\n this.traceModelRequests = config.traceModelRequests ?? false;\n\n const apiConfig: ApiClientConfig = {\n baseUrl: this.baseUrl,\n getHeaders: () => this.getHeaders(),\n };\n\n this.agents = new AgentsApi(apiConfig);\n this.agentSessions = new AgentSessionsApi(apiConfig);\n this.files = new FilesApi(apiConfig);\n this.workers = new WorkersApi(apiConfig);\n }\n\n getHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (this.apiKey) {\n headers.Authorization = `Bearer ${this.apiKey}`;\n }\n\n if (this.traceModelRequests) {\n headers['X-Octavus-Trace'] = 'true';\n }\n\n return headers;\n }\n}\n","/**\n * Base class for agent-managed resources.\n * Extend this class to define how each resource should be persisted when the agent updates it.\n */\nexport abstract class Resource {\n /** The resource name as defined in the agent protocol */\n abstract readonly name: string;\n\n /** Called when the agent updates this resource */\n abstract onUpdate(value: unknown): Promise<void> | void;\n}\n","import { generateId, type ToolResult, type FileReference } from '@octavus/core';\nimport type { FilesApi, FileUploadRequest } from '@/files.js';\n\ninterface ImagePart {\n type: 'image';\n data: string;\n mimeType?: string;\n}\n\nconst IMAGE_EXTENSIONS: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpg',\n 'image/webp': 'webp',\n 'image/gif': 'gif',\n 'image/svg+xml': 'svg',\n};\n\nfunction getExtensionFromMediaType(mediaType: string): string {\n return IMAGE_EXTENSIONS[mediaType] ?? 'png';\n}\n\nfunction isImagePart(part: unknown): part is ImagePart {\n return (\n typeof part === 'object' &&\n part !== null &&\n (part as Record<string, unknown>).type === 'image' &&\n typeof (part as Record<string, unknown>).data === 'string'\n );\n}\n\nfunction hasImageParts(value: unknown): value is unknown[] {\n return Array.isArray(value) && value.some(isImagePart);\n}\n\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const buffer = new ArrayBuffer(binary.length);\n const view = new Uint8Array(buffer);\n for (let i = 0; i < binary.length; i++) {\n view[i] = binary.charCodeAt(i);\n }\n return buffer;\n}\n\n/**\n * Extract base64 image blobs from tool results, upload them to S3 via\n * presigned URLs, and replace inline data with compact metadata +\n * FileReference entries.\n *\n * Runs at the server-sdk streaming layer so images are uploaded before\n * tool results travel over the network (WebSocket, HTTP continuation).\n */\nexport async function normalizeToolResultImages(\n toolResults: ToolResult[],\n filesApi: FilesApi,\n sessionId: string,\n): Promise<void> {\n for (const toolResult of toolResults) {\n if (toolResult.outputVariable) continue;\n if (!hasImageParts(toolResult.result)) continue;\n\n const parts = toolResult.result;\n const files: FileReference[] = toolResult.files ? [...toolResult.files] : [];\n\n const imageIndices: number[] = [];\n const imageBuffers: ArrayBuffer[] = [];\n const uploadRequests: FileUploadRequest[] = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (!isImagePart(part)) continue;\n\n const buffer = base64ToArrayBuffer(part.data);\n const mimeType = part.mimeType || 'image/png';\n\n imageIndices.push(i);\n imageBuffers.push(buffer);\n uploadRequests.push({\n filename: `image-${generateId()}.${getExtensionFromMediaType(mimeType)}`,\n mediaType: mimeType,\n size: buffer.byteLength,\n });\n }\n\n if (uploadRequests.length === 0) continue;\n\n let uploadInfos: { id: string; uploadUrl: string; downloadUrl: string }[];\n try {\n const response = await filesApi.getUploadUrls(sessionId, uploadRequests);\n uploadInfos = response.files;\n } catch {\n continue;\n }\n\n const uploadResults = await Promise.allSettled(\n uploadInfos.map((info, i) =>\n fetch(info.uploadUrl, {\n method: 'PUT',\n body: imageBuffers[i]!,\n headers: { 'Content-Type': uploadRequests[i]!.mediaType },\n }),\n ),\n );\n\n const summaryParts: unknown[] = [];\n let imageIdx = 0;\n\n for (let i = 0; i < parts.length; i++) {\n if (imageIdx < imageIndices.length && imageIndices[imageIdx] === i) {\n const uploadResult = uploadResults[imageIdx]!;\n const info = uploadInfos[imageIdx]!;\n const request = uploadRequests[imageIdx]!;\n const buf = imageBuffers[imageIdx]!;\n\n if (uploadResult.status === 'fulfilled' && uploadResult.value.ok) {\n files.push({\n id: info.id,\n mediaType: request.mediaType,\n url: info.downloadUrl,\n filename: request.filename,\n size: buf.byteLength,\n });\n\n summaryParts.push({\n type: 'image',\n mediaType: request.mediaType,\n size: buf.byteLength,\n url: info.downloadUrl,\n });\n } else {\n summaryParts.push(parts[i]);\n }\n\n imageIdx += 1;\n } else {\n summaryParts.push(parts[i]);\n }\n }\n\n toolResult.files = files;\n toolResult.result = summaryParts;\n }\n}\n","export { OctavusClient, type OctavusClientConfig } from '@/client.js';\nexport { AgentsApi } from '@/agents.js';\nexport {\n AgentSessionsApi,\n type SessionState,\n type UISessionState,\n type ExpiredSessionState,\n type RestoreSessionResult,\n type ClearSessionResult,\n type SessionStatus,\n type SessionAttachOptions,\n} from '@/agent-sessions.js';\nexport {\n FilesApi,\n type FileUploadRequest,\n type FileUploadInfo,\n type UploadUrlsResponse,\n} from '@/files.js';\nexport {\n AgentSession,\n toSSEStream,\n type SessionConfig,\n type TriggerOptions,\n type SessionRequest,\n type TriggerRequest,\n type ContinueRequest,\n type StopMessage,\n type SocketMessage,\n type SocketMessageHandlers,\n} from '@/session.js';\nexport {\n WorkersApi,\n type WorkerStartRequest,\n type WorkerContinueRequest,\n type WorkerRequest,\n type WorkerExecuteOptions,\n type WorkerGenerateResult,\n} from '@/workers.js';\nexport { WorkerError } from '@/worker-error.js';\nexport { Resource } from '@/resource.js';\nexport { ApiError } from '@/api-error.js';\nexport { normalizeToolResultImages } from '@/normalize-images.js';\n\n// Agent types (read-only - use @octavus/cli for agent management)\nexport type {\n AgentFormat,\n AgentSettings,\n AgentPrompt,\n Agent,\n AgentDefinition,\n} from '@/agent-types.js';\n\nexport type * from '@octavus/core';\nexport {\n // Error classes\n AppError,\n NotFoundError,\n ValidationError,\n ConflictError,\n ForbiddenError,\n OctavusError,\n // Error type guards\n isRateLimitError,\n isAuthenticationError,\n isProviderError,\n isToolError,\n isRetryableError,\n isValidationError,\n // Error event helpers\n createErrorEvent,\n errorToStreamEvent,\n createInternalErrorEvent,\n createApiErrorEvent,\n // Utilities\n generateId,\n isAbortError,\n // Thread helpers\n MAIN_THREAD,\n resolveThread,\n isMainThread,\n threadForPart,\n isOtherThread,\n // Type guards\n isFileReference,\n isFileReferenceArray,\n // Safe parse helpers\n safeParseStreamEvent,\n safeParseUIMessage,\n safeParseUIMessages,\n // Skills\n OCTAVUS_SKILL_TOOLS,\n isOctavusSkillTool,\n getSkillSlugFromToolCall,\n} from '@octavus/core';\n"],"mappings":"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","names":["z","z","createInternalErrorEvent","createInternalErrorEvent","z","z","z","createInternalErrorEvent","createApiErrorEvent","generateId","isAbortError","safeParseStreamEvent"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@octavus/server-sdk",
3
- "version": "2.20.0",
3
+ "version": "3.0.0",
4
4
  "description": "Server SDK for integrating Octavus agents",
5
5
  "license": "MIT",
6
6
  "author": "Octavus AI <dev@octavus.ai>",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "zod": "^4.3.5",
50
- "@octavus/core": "^2.20.0"
50
+ "@octavus/core": "^3.0.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "tsup": "^8.3.5",