@octavus/server-sdk 0.1.1 → 1.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/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # @octavus/server-sdk
2
+
3
+ Server SDK for integrating Octavus agents into your backend.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @octavus/server-sdk
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ This package provides a server-side SDK for interacting with the Octavus platform. Use it to:
14
+
15
+ - Create and manage agent sessions
16
+ - Execute triggers with tool handling
17
+ - Stream responses to clients
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { OctavusClient, toSSEStream } from '@octavus/server-sdk';
23
+
24
+ // Initialize client
25
+ const client = new OctavusClient({
26
+ baseUrl: process.env.OCTAVUS_BASE_URL!,
27
+ apiKey: process.env.OCTAVUS_API_KEY,
28
+ });
29
+
30
+ // Create a session
31
+ const sessionId = await client.agentSessions.create(agentId, {
32
+ COMPANY_NAME: 'Acme Corp',
33
+ });
34
+
35
+ // Attach to session with tool handlers
36
+ const session = client.agentSessions.attach(sessionId, {
37
+ tools: {
38
+ 'get-user': async (args) => {
39
+ return await db.users.findById(args.userId);
40
+ },
41
+ 'create-ticket': async (args) => {
42
+ return await ticketService.create(args);
43
+ },
44
+ },
45
+ });
46
+
47
+ // Trigger and stream response
48
+ const events = session.trigger('user-message', { USER_MESSAGE: 'Hello!' });
49
+ return new Response(toSSEStream(events), {
50
+ headers: { 'Content-Type': 'text/event-stream' },
51
+ });
52
+ ```
53
+
54
+ ## OctavusClient
55
+
56
+ ### Configuration
57
+
58
+ ```typescript
59
+ const client = new OctavusClient({
60
+ baseUrl: 'https://api.octavus.ai', // Or your self-hosted URL
61
+ apiKey: 'your-api-key', // Optional: for authenticated requests
62
+ });
63
+ ```
64
+
65
+ ### Agent Sessions API
66
+
67
+ ```typescript
68
+ // Create a new session
69
+ const sessionId = await client.agentSessions.create(agentId, input);
70
+
71
+ // Get session state (for debugging)
72
+ const state = await client.agentSessions.get(sessionId);
73
+
74
+ // Get UI-ready messages
75
+ const { messages, status } = await client.agentSessions.getMessages(sessionId);
76
+
77
+ // Restore expired session
78
+ await client.agentSessions.restore(sessionId, storedMessages, input);
79
+
80
+ // Attach to session for triggering
81
+ const session = client.agentSessions.attach(sessionId, options);
82
+ ```
83
+
84
+ ### Agents API
85
+
86
+ ```typescript
87
+ // List all agents
88
+ const agents = await client.agents.list();
89
+
90
+ // Get agent by ID
91
+ const agent = await client.agents.get(agentId);
92
+ ```
93
+
94
+ ### Files API
95
+
96
+ ```typescript
97
+ // Get presigned upload URLs
98
+ const { files } = await client.files.getUploadUrls(sessionId, [
99
+ { filename: 'photo.jpg', mediaType: 'image/jpeg', size: 102400 },
100
+ ]);
101
+
102
+ // Upload directly to S3
103
+ await fetch(files[0].uploadUrl, {
104
+ method: 'PUT',
105
+ body: imageFile,
106
+ headers: { 'Content-Type': 'image/jpeg' },
107
+ });
108
+
109
+ // Use downloadUrl in trigger input
110
+ await session.trigger('user-message', {
111
+ FILES: [{ id: files[0].id, url: files[0].downloadUrl, mediaType: 'image/jpeg' }],
112
+ });
113
+ ```
114
+
115
+ ## AgentSession
116
+
117
+ ### Triggering Events
118
+
119
+ ```typescript
120
+ const session = client.agentSessions.attach(sessionId, {
121
+ tools: {
122
+ 'tool-name': async (args) => {
123
+ // Execute tool and return result
124
+ return { success: true };
125
+ },
126
+ },
127
+ });
128
+
129
+ // Stream events (for WebSocket/Socket.io)
130
+ for await (const event of session.trigger('user-message', input)) {
131
+ socket.emit('stream-event', event);
132
+ }
133
+
134
+ // Convert to SSE (for HTTP endpoints)
135
+ const events = session.trigger('user-message', input);
136
+ return new Response(toSSEStream(events), {
137
+ headers: { 'Content-Type': 'text/event-stream' },
138
+ });
139
+ ```
140
+
141
+ ### Tool Handlers
142
+
143
+ The SDK automatically handles the tool execution loop:
144
+
145
+ 1. Platform requests tool execution via `tool-request` event
146
+ 2. SDK executes your tool handlers locally
147
+ 3. SDK sends results back to continue the conversation
148
+
149
+ ```typescript
150
+ const session = client.agentSessions.attach(sessionId, {
151
+ tools: {
152
+ 'get-user-account': async (args) => {
153
+ // Access your database, APIs, etc.
154
+ return await db.users.findById(args.userId);
155
+ },
156
+ 'create-support-ticket': async (args) => {
157
+ // Execute with full access to your backend
158
+ return await ticketService.create({
159
+ summary: args.summary,
160
+ priority: args.priority,
161
+ });
162
+ },
163
+ },
164
+ });
165
+ ```
166
+
167
+ ### Resource Handlers
168
+
169
+ Track resource updates from the agent:
170
+
171
+ ```typescript
172
+ import { Resource } from '@octavus/server-sdk';
173
+
174
+ class ConversationSummaryResource extends Resource {
175
+ readonly name = 'CONVERSATION_SUMMARY';
176
+
177
+ async onUpdate(value: unknown) {
178
+ // Persist to database, trigger webhooks, etc.
179
+ await db.sessions.update(sessionId, { summary: value });
180
+ }
181
+ }
182
+
183
+ const session = client.agentSessions.attach(sessionId, {
184
+ resources: [new ConversationSummaryResource()],
185
+ });
186
+ ```
187
+
188
+ ### Abort Support
189
+
190
+ ```typescript
191
+ const events = session.trigger('user-message', input, {
192
+ signal: request.signal, // AbortSignal from request
193
+ });
194
+ ```
195
+
196
+ ## Session Lifecycle
197
+
198
+ ### Active Sessions
199
+
200
+ Sessions remain active for 24 hours (configurable). Use `getMessages()` for UI display.
201
+
202
+ ### Expired Sessions
203
+
204
+ When Redis state expires:
205
+
206
+ ```typescript
207
+ const result = await client.agentSessions.getMessages(sessionId);
208
+
209
+ if (result.status === 'expired') {
210
+ // Restore from your stored messages
211
+ await client.agentSessions.restore(sessionId, storedMessages);
212
+ }
213
+ ```
214
+
215
+ ## Re-exports
216
+
217
+ This package re-exports everything from `@octavus/core`, so you don't need to install it separately.
218
+
219
+ ## Related Packages
220
+
221
+ - [`@octavus/react`](https://www.npmjs.com/package/@octavus/react) - React hooks
222
+ - [`@octavus/client-sdk`](https://www.npmjs.com/package/@octavus/client-sdk) - Client-side SDK
223
+ - [`@octavus/cli`](https://www.npmjs.com/package/@octavus/cli) - CLI for agent management
224
+
225
+ ## License
226
+
227
+ MIT
package/dist/index.d.ts CHANGED
@@ -24,32 +24,20 @@ declare abstract class BaseApiClient {
24
24
  protected httpPatch<T>(path: string, body: unknown, schema: ZodType<T>): Promise<T>;
25
25
  }
26
26
 
27
- /** Agent format - interactive (chat) or generation (background task) */
28
- type AgentFormat = 'interactive' | 'generation';
29
- /**
30
- * Agent settings input - used when creating/updating agents
31
- */
32
- interface AgentSettingsInput {
27
+ /** Agent format - interactive (chat) or worker (background task) */
28
+ type AgentFormat = 'interactive' | 'worker';
29
+ /** Agent settings */
30
+ interface AgentSettings {
33
31
  slug: string;
34
32
  name: string;
35
33
  description?: string;
36
34
  format: AgentFormat;
37
35
  }
38
- /**
39
- * Agent prompt - shared between input and response
40
- */
36
+ /** Agent prompt */
41
37
  interface AgentPrompt {
42
38
  name: string;
43
39
  content: string;
44
40
  }
45
- /**
46
- * Input for creating/updating an agent definition
47
- */
48
- interface AgentDefinitionInput {
49
- settings: AgentSettingsInput;
50
- protocol: string;
51
- prompts: AgentPrompt[];
52
- }
53
41
  /**
54
42
  * Agent summary returned from list endpoint
55
43
  */
@@ -69,7 +57,7 @@ interface Agent {
69
57
  * Full agent definition returned from get endpoint
70
58
  */
71
59
  interface AgentDefinition {
72
- settings: AgentSettingsInput;
60
+ settings: AgentSettings;
73
61
  protocol: string;
74
62
  prompts: AgentPrompt[];
75
63
  /** Agent ID - use this for API calls like createSession */
@@ -77,37 +65,8 @@ interface AgentDefinition {
77
65
  }
78
66
  declare const agentFormatSchema: z.ZodEnum<{
79
67
  interactive: "interactive";
80
- generation: "generation";
68
+ worker: "worker";
81
69
  }>;
82
- declare const agentSettingsInputSchema: z.ZodObject<{
83
- slug: z.ZodString;
84
- name: z.ZodString;
85
- description: z.ZodOptional<z.ZodString>;
86
- format: z.ZodEnum<{
87
- interactive: "interactive";
88
- generation: "generation";
89
- }>;
90
- }, z.core.$strip>;
91
- declare const agentPromptSchema: z.ZodObject<{
92
- name: z.ZodString;
93
- content: z.ZodString;
94
- }, z.core.$strip>;
95
- declare const agentDefinitionInputSchema: z.ZodObject<{
96
- settings: z.ZodObject<{
97
- slug: z.ZodString;
98
- name: z.ZodString;
99
- description: z.ZodOptional<z.ZodString>;
100
- format: z.ZodEnum<{
101
- interactive: "interactive";
102
- generation: "generation";
103
- }>;
104
- }, z.core.$strip>;
105
- protocol: z.ZodString;
106
- prompts: z.ZodArray<z.ZodObject<{
107
- name: z.ZodString;
108
- content: z.ZodString;
109
- }, z.core.$strip>>;
110
- }, z.core.$strip>;
111
70
  declare const agentSchema: z.ZodObject<{
112
71
  slug: z.ZodString;
113
72
  id: z.ZodString;
@@ -115,7 +74,7 @@ declare const agentSchema: z.ZodObject<{
115
74
  description: z.ZodNullable<z.ZodString>;
116
75
  format: z.ZodEnum<{
117
76
  interactive: "interactive";
118
- generation: "generation";
77
+ worker: "worker";
119
78
  }>;
120
79
  createdAt: z.ZodString;
121
80
  updatedAt: z.ZodString;
@@ -129,7 +88,7 @@ declare const agentsResponseSchema: z.ZodObject<{
129
88
  description: z.ZodNullable<z.ZodString>;
130
89
  format: z.ZodEnum<{
131
90
  interactive: "interactive";
132
- generation: "generation";
91
+ worker: "worker";
133
92
  }>;
134
93
  createdAt: z.ZodString;
135
94
  updatedAt: z.ZodString;
@@ -143,7 +102,7 @@ declare const agentDefinitionSchema: z.ZodObject<{
143
102
  description: z.ZodOptional<z.ZodString>;
144
103
  format: z.ZodEnum<{
145
104
  interactive: "interactive";
146
- generation: "generation";
105
+ worker: "worker";
147
106
  }>;
148
107
  }, z.core.$strip>;
149
108
  protocol: z.ZodString;
@@ -153,41 +112,18 @@ declare const agentDefinitionSchema: z.ZodObject<{
153
112
  }, z.core.$strip>>;
154
113
  id: z.ZodString;
155
114
  }, z.core.$strip>;
156
- declare const agentCreateResponseSchema: z.ZodObject<{
157
- agentId: z.ZodString;
158
- message: z.ZodString;
159
- }, z.core.$strip>;
160
- declare const agentUpdateResponseSchema: z.ZodObject<{
161
- agentId: z.ZodString;
162
- message: z.ZodString;
163
- }, z.core.$strip>;
164
115
 
165
- interface AgentUpdateInput {
166
- protocol?: string;
167
- prompts?: AgentPrompt[];
168
- }
169
- /** API for managing agent definitions */
116
+ /**
117
+ * API for listing and retrieving agent definitions.
118
+ *
119
+ * Note: Agent management (create, update, sync) should be done via the @octavus/cli package.
120
+ * This API uses agent IDs only - use CLI for slug-based operations.
121
+ */
170
122
  declare class AgentsApi extends BaseApiClient {
171
- /** List all agents */
123
+ /** List all agents in the project */
172
124
  list(): Promise<Agent[]>;
173
125
  /** Get a single agent by ID */
174
126
  get(agentId: string): Promise<AgentDefinition>;
175
- /** Get a single agent by slug */
176
- getBySlug(slug: string): Promise<AgentDefinition | null>;
177
- /** Create a new agent. Throws if agent with same slug exists. */
178
- create(definition: AgentDefinitionInput): Promise<string>;
179
- /** Partial update of an existing agent by ID */
180
- update(agentId: string, update: AgentUpdateInput): Promise<string>;
181
- /** Partial update of an existing agent by slug */
182
- updateBySlug(slug: string, update: AgentUpdateInput): Promise<string>;
183
- /**
184
- * Sync an agent definition - creates if new, updates if exists
185
- * Returns { agentId, created: boolean }
186
- */
187
- sync(definition: AgentDefinitionInput): Promise<{
188
- agentId: string;
189
- created: boolean;
190
- }>;
191
127
  }
192
128
 
193
129
  /**
@@ -220,6 +156,13 @@ interface SessionConfig {
220
156
  tools?: ToolHandlers;
221
157
  resources?: Resource[];
222
158
  }
159
+ /**
160
+ * Options for trigger execution.
161
+ */
162
+ interface TriggerOptions {
163
+ /** Abort signal to cancel the trigger execution */
164
+ signal?: AbortSignal;
165
+ }
223
166
  /** Handles streaming and tool continuation for agent sessions */
224
167
  declare class AgentSession {
225
168
  private sessionId;
@@ -237,6 +180,10 @@ declare class AgentSession {
237
180
  * 4. POSTs a new request with toolResults to continue
238
181
  * 5. Repeats until done (no more tool requests)
239
182
  *
183
+ * @param triggerName - The trigger name defined in the agent's protocol
184
+ * @param triggerInput - Input parameters for the trigger
185
+ * @param options - Optional configuration including abort signal
186
+ *
240
187
  * @example
241
188
  * ```typescript
242
189
  * // For sockets: iterate events directly
@@ -244,18 +191,20 @@ declare class AgentSession {
244
191
  * conn.write(JSON.stringify(event));
245
192
  * }
246
193
  *
247
- * // For HTTP: convert to SSE stream
248
- * const events = session.trigger('user-message', input);
194
+ * // For HTTP: convert to SSE stream with abort support
195
+ * const events = session.trigger('user-message', input, { signal: request.signal });
249
196
  * return new Response(toSSEStream(events), {
250
197
  * headers: { 'Content-Type': 'text/event-stream' },
251
198
  * });
252
199
  * ```
253
200
  */
254
- trigger(triggerName: string, triggerInput?: Record<string, unknown>): AsyncGenerator<StreamEvent>;
201
+ trigger(triggerName: string, triggerInput?: Record<string, unknown>, options?: TriggerOptions): AsyncGenerator<StreamEvent>;
255
202
  getSessionId(): string;
256
203
  private handleResourceUpdate;
257
204
  }
258
205
 
206
+ /** Session status indicating whether it's active or expired */
207
+ type SessionStatus = 'active' | 'expired';
259
208
  interface SessionState {
260
209
  id: string;
261
210
  agentId: string;
@@ -263,6 +212,7 @@ interface SessionState {
263
212
  variables: Record<string, unknown>;
264
213
  resources: Record<string, unknown>;
265
214
  messages: ChatMessage[];
215
+ status?: 'active';
266
216
  createdAt: string;
267
217
  updatedAt: string;
268
218
  }
@@ -270,6 +220,18 @@ interface UISessionState {
270
220
  sessionId: string;
271
221
  agentId: string;
272
222
  messages: UIMessage[];
223
+ status?: 'active';
224
+ }
225
+ interface ExpiredSessionState {
226
+ sessionId: string;
227
+ agentId: string;
228
+ status: 'expired';
229
+ createdAt: string;
230
+ }
231
+ interface RestoreSessionResult {
232
+ sessionId: string;
233
+ /** True if session was restored from messages, false if already active */
234
+ restored: boolean;
273
235
  }
274
236
  interface SessionAttachOptions {
275
237
  tools?: ToolHandlers;
@@ -282,13 +244,31 @@ declare class AgentSessionsApi extends BaseApiClient {
282
244
  /**
283
245
  * Get full session state (for internal/debug use)
284
246
  * Note: Contains all messages including hidden content
247
+ *
248
+ * Returns SessionState for active sessions, ExpiredSessionState for expired sessions.
249
+ * Check `status` field to determine which type was returned.
285
250
  */
286
- get(sessionId: string): Promise<SessionState>;
251
+ get(sessionId: string): Promise<SessionState | ExpiredSessionState>;
287
252
  /**
288
253
  * Get UI-ready session messages (for client display)
289
- * Returns only visible messages with hidden content filtered out
254
+ * Returns only visible messages with hidden content filtered out.
255
+ *
256
+ * For expired sessions, returns status: 'expired' without messages.
257
+ * Use restore() to restore from stored messages before continuing.
258
+ */
259
+ getMessages(sessionId: string): Promise<UISessionState | ExpiredSessionState>;
260
+ /**
261
+ * Restore an expired session from stored messages.
262
+ *
263
+ * Use this to restore a session after its state has expired.
264
+ * The consumer should have stored the UIMessage[] array from previous interactions.
265
+ *
266
+ * @param sessionId - The session ID to restore
267
+ * @param messages - Previously stored UIMessage[] array
268
+ * @param input - Optional session input for system prompt interpolation (same as create)
269
+ * @returns { sessionId, restored: true } if restored, { sessionId, restored: false } if already active
290
270
  */
291
- getMessages(sessionId: string): Promise<UISessionState>;
271
+ restore(sessionId: string, messages: UIMessage[], input?: Record<string, unknown>): Promise<RestoreSessionResult>;
292
272
  /** Attach to an existing session for triggering events */
293
273
  attach(sessionId: string, options?: SessionAttachOptions): AgentSession;
294
274
  }
@@ -388,4 +368,4 @@ declare class OctavusClient {
388
368
  getHeaders(): Record<string, string>;
389
369
  }
390
370
 
391
- export { type Agent, type AgentDefinition, type AgentDefinitionInput, type AgentFormat, type AgentPrompt, AgentSession, AgentSessionsApi, type AgentSettingsInput, type AgentUpdateInput, AgentsApi, ApiError, type FileUploadInfo, type FileUploadRequest, FilesApi, OctavusClient, type OctavusClientConfig, Resource, type SessionAttachOptions, type SessionState, type UISessionState, type UploadUrlsResponse, agentCreateResponseSchema, agentDefinitionInputSchema, agentDefinitionSchema, agentFormatSchema, agentPromptSchema, agentSchema, agentSettingsInputSchema, agentUpdateResponseSchema, agentsResponseSchema, fileUploadInfoSchema, fileUploadRequestSchema, toSSEStream, uploadUrlsResponseSchema };
371
+ export { type Agent, type AgentDefinition, type AgentFormat, type AgentPrompt, AgentSession, AgentSessionsApi, type AgentSettings, AgentsApi, ApiError, type ExpiredSessionState, type FileUploadInfo, type FileUploadRequest, FilesApi, OctavusClient, type OctavusClientConfig, Resource, type RestoreSessionResult, type SessionAttachOptions, type SessionConfig, type SessionState, type SessionStatus, type TriggerOptions, type UISessionState, type UploadUrlsResponse, agentDefinitionSchema, agentFormatSchema, agentSchema, agentsResponseSchema, fileUploadInfoSchema, fileUploadRequestSchema, toSSEStream, uploadUrlsResponseSchema };
package/dist/index.js CHANGED
@@ -78,22 +78,17 @@ var BaseApiClient = class {
78
78
 
79
79
  // src/agent-types.ts
80
80
  import { z as z2 } from "zod";
81
- var agentFormatSchema = z2.enum(["interactive", "generation"]);
82
- var agentSettingsInputSchema = z2.object({
83
- slug: z2.string().min(1),
84
- name: z2.string().min(1),
81
+ var agentFormatSchema = z2.enum(["interactive", "worker"]);
82
+ var agentSettingsSchema = z2.object({
83
+ slug: z2.string(),
84
+ name: z2.string(),
85
85
  description: z2.string().optional(),
86
86
  format: agentFormatSchema
87
87
  });
88
88
  var agentPromptSchema = z2.object({
89
- name: z2.string().min(1),
89
+ name: z2.string(),
90
90
  content: z2.string()
91
91
  });
92
- var agentDefinitionInputSchema = z2.object({
93
- settings: agentSettingsInputSchema,
94
- protocol: z2.string().min(1),
95
- prompts: z2.array(agentPromptSchema)
96
- });
97
92
  var agentSchema = z2.object({
98
93
  slug: z2.string(),
99
94
  id: z2.string(),
@@ -108,23 +103,15 @@ var agentsResponseSchema = z2.object({
108
103
  agents: z2.array(agentSchema)
109
104
  });
110
105
  var agentDefinitionSchema = z2.object({
111
- settings: agentSettingsInputSchema,
106
+ settings: agentSettingsSchema,
112
107
  protocol: z2.string(),
113
108
  prompts: z2.array(agentPromptSchema),
114
109
  id: z2.string()
115
110
  });
116
- var agentCreateResponseSchema = z2.object({
117
- agentId: z2.string(),
118
- message: z2.string()
119
- });
120
- var agentUpdateResponseSchema = z2.object({
121
- agentId: z2.string(),
122
- message: z2.string()
123
- });
124
111
 
125
112
  // src/agents.ts
126
113
  var AgentsApi = class extends BaseApiClient {
127
- /** List all agents */
114
+ /** List all agents in the project */
128
115
  async list() {
129
116
  const response = await this.httpGet("/api/agents", agentsResponseSchema);
130
117
  return response.agents;
@@ -133,56 +120,6 @@ var AgentsApi = class extends BaseApiClient {
133
120
  async get(agentId) {
134
121
  return await this.httpGet(`/api/agents/${agentId}`, agentDefinitionSchema);
135
122
  }
136
- /** Get a single agent by slug */
137
- async getBySlug(slug) {
138
- try {
139
- return await this.httpGet(`/api/agents/${slug}?by=slug`, agentDefinitionSchema);
140
- } catch (error) {
141
- if (error instanceof ApiError && error.status === 404) {
142
- return null;
143
- }
144
- throw error;
145
- }
146
- }
147
- /** Create a new agent. Throws if agent with same slug exists. */
148
- async create(definition) {
149
- const response = await this.httpPost("/api/agents", definition, agentCreateResponseSchema);
150
- return response.agentId;
151
- }
152
- /** Partial update of an existing agent by ID */
153
- async update(agentId, update) {
154
- const response = await this.httpPatch(
155
- `/api/agents/${agentId}`,
156
- update,
157
- agentUpdateResponseSchema
158
- );
159
- return response.agentId;
160
- }
161
- /** Partial update of an existing agent by slug */
162
- async updateBySlug(slug, update) {
163
- const response = await this.httpPatch(
164
- `/api/agents/${slug}?by=slug`,
165
- update,
166
- agentUpdateResponseSchema
167
- );
168
- return response.agentId;
169
- }
170
- /**
171
- * Sync an agent definition - creates if new, updates if exists
172
- * Returns { agentId, created: boolean }
173
- */
174
- async sync(definition) {
175
- const existing = await this.getBySlug(definition.settings.slug);
176
- if (existing) {
177
- const agentId2 = await this.update(existing.id, {
178
- protocol: definition.protocol,
179
- prompts: definition.prompts
180
- });
181
- return { agentId: agentId2, created: false };
182
- }
183
- const agentId = await this.create(definition);
184
- return { agentId, created: true };
185
- }
186
123
  };
187
124
 
188
125
  // src/agent-sessions.ts
@@ -194,7 +131,10 @@ import {
194
131
 
195
132
  // src/session.ts
196
133
  import {
197
- safeParseStreamEvent
134
+ safeParseStreamEvent,
135
+ isAbortError,
136
+ createInternalErrorEvent,
137
+ createApiErrorEvent
198
138
  } from "@octavus/core";
199
139
  function toSSEStream(events) {
200
140
  const encoder = new TextEncoder();
@@ -209,13 +149,12 @@ function toSSEStream(events) {
209
149
  controller.enqueue(encoder.encode("data: [DONE]\n\n"));
210
150
  controller.close();
211
151
  } catch (err) {
212
- controller.enqueue(
213
- encoder.encode(
214
- `data: ${JSON.stringify({ type: "error", errorText: err instanceof Error ? err.message : "Unknown error" })}
215
-
216
- `
217
- )
152
+ const errorEvent = createInternalErrorEvent(
153
+ err instanceof Error ? err.message : "Unknown error"
218
154
  );
155
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}
156
+
157
+ `));
219
158
  controller.close();
220
159
  }
221
160
  }
@@ -245,6 +184,10 @@ var AgentSession = class {
245
184
  * 4. POSTs a new request with toolResults to continue
246
185
  * 5. Repeats until done (no more tool requests)
247
186
  *
187
+ * @param triggerName - The trigger name defined in the agent's protocol
188
+ * @param triggerInput - Input parameters for the trigger
189
+ * @param options - Optional configuration including abort signal
190
+ *
248
191
  * @example
249
192
  * ```typescript
250
193
  * // For sockets: iterate events directly
@@ -252,32 +195,50 @@ var AgentSession = class {
252
195
  * conn.write(JSON.stringify(event));
253
196
  * }
254
197
  *
255
- * // For HTTP: convert to SSE stream
256
- * const events = session.trigger('user-message', input);
198
+ * // For HTTP: convert to SSE stream with abort support
199
+ * const events = session.trigger('user-message', input, { signal: request.signal });
257
200
  * return new Response(toSSEStream(events), {
258
201
  * headers: { 'Content-Type': 'text/event-stream' },
259
202
  * });
260
203
  * ```
261
204
  */
262
- async *trigger(triggerName, triggerInput) {
205
+ async *trigger(triggerName, triggerInput, options) {
263
206
  let toolResults;
264
207
  let continueLoop = true;
265
208
  while (continueLoop) {
266
- const response = await fetch(
267
- `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,
268
- {
269
- method: "POST",
270
- headers: this.config.getHeaders(),
271
- body: JSON.stringify({ triggerName, input: triggerInput, toolResults })
209
+ if (options?.signal?.aborted) {
210
+ yield { type: "finish", finishReason: "stop" };
211
+ return;
212
+ }
213
+ let response;
214
+ try {
215
+ response = await fetch(
216
+ `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,
217
+ {
218
+ method: "POST",
219
+ headers: this.config.getHeaders(),
220
+ body: JSON.stringify({
221
+ triggerName,
222
+ input: triggerInput,
223
+ toolResults
224
+ }),
225
+ signal: options?.signal
226
+ }
227
+ );
228
+ } catch (err) {
229
+ if (isAbortError(err)) {
230
+ yield { type: "finish", finishReason: "stop" };
231
+ return;
272
232
  }
273
- );
233
+ throw err;
234
+ }
274
235
  if (!response.ok) {
275
236
  const { message } = await parseApiError(response, "Failed to trigger");
276
- yield { type: "error", errorText: message };
237
+ yield createApiErrorEvent(response.status, message);
277
238
  return;
278
239
  }
279
240
  if (!response.body) {
280
- yield { type: "error", errorText: "Response body is not readable" };
241
+ yield createInternalErrorEvent("Response body is not readable");
281
242
  return;
282
243
  }
283
244
  toolResults = void 0;
@@ -287,7 +248,23 @@ var AgentSession = class {
287
248
  let pendingToolCalls = null;
288
249
  let streamDone = false;
289
250
  while (!streamDone) {
290
- const { done, value } = await reader.read();
251
+ if (options?.signal?.aborted) {
252
+ reader.releaseLock();
253
+ yield { type: "finish", finishReason: "stop" };
254
+ return;
255
+ }
256
+ let readResult;
257
+ try {
258
+ readResult = await reader.read();
259
+ } catch (err) {
260
+ if (isAbortError(err)) {
261
+ reader.releaseLock();
262
+ yield { type: "finish", finishReason: "stop" };
263
+ return;
264
+ }
265
+ throw err;
266
+ }
267
+ const { done, value } = readResult;
291
268
  if (done) {
292
269
  streamDone = true;
293
270
  continue;
@@ -324,6 +301,10 @@ var AgentSession = class {
324
301
  }
325
302
  }
326
303
  }
304
+ if (options?.signal?.aborted) {
305
+ yield { type: "finish", finishReason: "stop" };
306
+ return;
307
+ }
327
308
  if (pendingToolCalls && pendingToolCalls.length > 0) {
328
309
  toolResults = await Promise.all(
329
310
  pendingToolCalls.map(async (tc) => {
@@ -359,7 +340,7 @@ var AgentSession = class {
359
340
  );
360
341
  for (const tr of toolResults) {
361
342
  if (tr.error) {
362
- yield { type: "tool-output-error", toolCallId: tr.toolCallId, errorText: tr.error };
343
+ yield { type: "tool-output-error", toolCallId: tr.toolCallId, error: tr.error };
363
344
  } else {
364
345
  yield { type: "tool-output-available", toolCallId: tr.toolCallId, output: tr.result };
365
346
  }
@@ -391,13 +372,25 @@ var sessionStateSchema = z3.object({
391
372
  variables: z3.record(z3.string(), z3.unknown()),
392
373
  resources: z3.record(z3.string(), z3.unknown()),
393
374
  messages: z3.array(chatMessageSchema),
375
+ status: z3.literal("active").optional(),
394
376
  createdAt: z3.string(),
395
377
  updatedAt: z3.string()
396
378
  });
397
379
  var uiSessionResponseSchema = z3.object({
398
380
  sessionId: z3.string(),
399
381
  agentId: z3.string(),
400
- messages: z3.array(uiMessageSchema)
382
+ messages: z3.array(uiMessageSchema),
383
+ status: z3.literal("active").optional()
384
+ });
385
+ var expiredSessionResponseSchema = z3.object({
386
+ sessionId: z3.string(),
387
+ agentId: z3.string(),
388
+ status: z3.literal("expired"),
389
+ createdAt: z3.string()
390
+ });
391
+ var restoreSessionResponseSchema = z3.object({
392
+ sessionId: z3.string(),
393
+ restored: z3.boolean()
401
394
  });
402
395
  var AgentSessionsApi = class extends BaseApiClient {
403
396
  /** Create a new session for an agent */
@@ -412,18 +405,66 @@ var AgentSessionsApi = class extends BaseApiClient {
412
405
  /**
413
406
  * Get full session state (for internal/debug use)
414
407
  * Note: Contains all messages including hidden content
408
+ *
409
+ * Returns SessionState for active sessions, ExpiredSessionState for expired sessions.
410
+ * Check `status` field to determine which type was returned.
415
411
  */
416
412
  async get(sessionId) {
417
- return await this.httpGet(`/api/agent-sessions/${sessionId}`, sessionStateSchema);
413
+ const response = await fetch(`${this.config.baseUrl}/api/agent-sessions/${sessionId}`, {
414
+ method: "GET",
415
+ headers: this.config.getHeaders()
416
+ });
417
+ if (!response.ok) {
418
+ await throwApiError(response, "Request failed");
419
+ }
420
+ const data = await response.json();
421
+ const expiredResult = expiredSessionResponseSchema.safeParse(data);
422
+ if (expiredResult.success) {
423
+ return expiredResult.data;
424
+ }
425
+ return sessionStateSchema.parse(data);
418
426
  }
419
427
  /**
420
428
  * Get UI-ready session messages (for client display)
421
- * Returns only visible messages with hidden content filtered out
429
+ * Returns only visible messages with hidden content filtered out.
430
+ *
431
+ * For expired sessions, returns status: 'expired' without messages.
432
+ * Use restore() to restore from stored messages before continuing.
422
433
  */
423
434
  async getMessages(sessionId) {
424
- return await this.httpGet(
425
- `/api/agent-sessions/${sessionId}?format=ui`,
426
- uiSessionResponseSchema
435
+ const response = await fetch(
436
+ `${this.config.baseUrl}/api/agent-sessions/${sessionId}?format=ui`,
437
+ {
438
+ method: "GET",
439
+ headers: this.config.getHeaders()
440
+ }
441
+ );
442
+ if (!response.ok) {
443
+ await throwApiError(response, "Request failed");
444
+ }
445
+ const data = await response.json();
446
+ const expiredResult = expiredSessionResponseSchema.safeParse(data);
447
+ if (expiredResult.success) {
448
+ return expiredResult.data;
449
+ }
450
+ return uiSessionResponseSchema.parse(data);
451
+ }
452
+ /**
453
+ * Restore an expired session from stored messages.
454
+ *
455
+ * Use this to restore a session after its state has expired.
456
+ * The consumer should have stored the UIMessage[] array from previous interactions.
457
+ *
458
+ * @param sessionId - The session ID to restore
459
+ * @param messages - Previously stored UIMessage[] array
460
+ * @param input - Optional session input for system prompt interpolation (same as create)
461
+ * @returns { sessionId, restored: true } if restored, { sessionId, restored: false } if already active
462
+ */
463
+ async restore(sessionId, messages, input) {
464
+ return await this.httpPost(
465
+ `/api/agent-sessions/${sessionId}/restore`,
466
+ { messages, input },
467
+ restoreSessionResponseSchema
427
468
  );
428
469
  }
429
470
  /** Attach to an existing session for triggering events */
@@ -521,6 +562,9 @@ var OctavusClient = class {
521
562
  // src/resource.ts
522
563
  var Resource = class {
523
564
  };
565
+
566
+ // src/index.ts
567
+ export * from "@octavus/core";
524
568
  export {
525
569
  AgentSession,
526
570
  AgentSessionsApi,
@@ -529,14 +573,9 @@ export {
529
573
  FilesApi,
530
574
  OctavusClient,
531
575
  Resource,
532
- agentCreateResponseSchema,
533
- agentDefinitionInputSchema,
534
576
  agentDefinitionSchema,
535
577
  agentFormatSchema,
536
- agentPromptSchema,
537
578
  agentSchema,
538
- agentSettingsInputSchema,
539
- agentUpdateResponseSchema,
540
579
  agentsResponseSchema,
541
580
  fileUploadInfoSchema,
542
581
  fileUploadRequestSchema,
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/files.ts","../src/client.ts","../src/resource.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","import { z } from 'zod';\n\n/** Agent format - interactive (chat) or generation (background task) */\nexport type AgentFormat = 'interactive' | 'generation';\n\n/**\n * Agent settings input - used when creating/updating agents\n */\nexport interface AgentSettingsInput {\n slug: string;\n name: string;\n description?: string;\n format: AgentFormat;\n}\n\n/**\n * Agent prompt - shared between input and response\n */\nexport interface AgentPrompt {\n name: string;\n content: string;\n}\n\n/**\n * Input for creating/updating an agent definition\n */\nexport interface AgentDefinitionInput {\n settings: AgentSettingsInput;\n protocol: string;\n prompts: AgentPrompt[];\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: AgentSettingsInput;\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', 'generation']);\n\nexport const agentSettingsInputSchema = z.object({\n slug: z.string().min(1),\n name: z.string().min(1),\n description: z.string().optional(),\n format: agentFormatSchema,\n});\n\nexport const agentPromptSchema = z.object({\n name: z.string().min(1),\n content: z.string(),\n});\n\nexport const agentDefinitionInputSchema = z.object({\n settings: agentSettingsInputSchema,\n protocol: z.string().min(1),\n prompts: z.array(agentPromptSchema),\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: agentSettingsInputSchema,\n protocol: z.string(),\n prompts: z.array(agentPromptSchema),\n id: z.string(),\n});\n\nexport const agentCreateResponseSchema = z.object({\n agentId: z.string(),\n message: z.string(),\n});\n\nexport const agentUpdateResponseSchema = z.object({\n agentId: z.string(),\n message: z.string(),\n});\n","import { BaseApiClient, ApiError } from '@/base-api-client.js';\nimport {\n agentsResponseSchema,\n agentDefinitionSchema,\n agentCreateResponseSchema,\n agentUpdateResponseSchema,\n type Agent,\n type AgentDefinition,\n type AgentDefinitionInput,\n type AgentPrompt,\n} from '@/agent-types.js';\n\nexport interface AgentUpdateInput {\n protocol?: string;\n prompts?: AgentPrompt[];\n}\n\n/** API for managing agent definitions */\nexport class AgentsApi extends BaseApiClient {\n /** List all agents */\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 /** Get a single agent by slug */\n async getBySlug(slug: string): Promise<AgentDefinition | null> {\n try {\n return await this.httpGet(`/api/agents/${slug}?by=slug`, agentDefinitionSchema);\n } catch (error) {\n if (error instanceof ApiError && error.status === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /** Create a new agent. Throws if agent with same slug exists. */\n async create(definition: AgentDefinitionInput): Promise<string> {\n const response = await this.httpPost('/api/agents', definition, agentCreateResponseSchema);\n return response.agentId;\n }\n\n /** Partial update of an existing agent by ID */\n async update(agentId: string, update: AgentUpdateInput): Promise<string> {\n const response = await this.httpPatch(\n `/api/agents/${agentId}`,\n update,\n agentUpdateResponseSchema,\n );\n return response.agentId;\n }\n\n /** Partial update of an existing agent by slug */\n async updateBySlug(slug: string, update: AgentUpdateInput): Promise<string> {\n const response = await this.httpPatch(\n `/api/agents/${slug}?by=slug`,\n update,\n agentUpdateResponseSchema,\n );\n return response.agentId;\n }\n\n /**\n * Sync an agent definition - creates if new, updates if exists\n * Returns { agentId, created: boolean }\n */\n async sync(definition: AgentDefinitionInput): Promise<{ agentId: string; created: boolean }> {\n const existing = await this.getBySlug(definition.settings.slug);\n\n if (existing) {\n // Update existing agent\n const agentId = await this.update(existing.id, {\n protocol: definition.protocol,\n prompts: definition.prompts,\n });\n return { agentId, created: false };\n }\n // Create new agent\n const agentId = await this.create(definition);\n return { agentId, created: true };\n }\n}\n","import { z } from 'zod';\nimport {\n chatMessageSchema,\n uiMessageSchema,\n type ChatMessage,\n type ToolHandlers,\n type UIMessage,\n} from '@octavus/core';\nimport { BaseApiClient } from '@/base-api-client.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 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});\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 createdAt: string;\n updatedAt: string;\n}\n\nexport interface UISessionState {\n sessionId: string;\n agentId: string;\n messages: UIMessage[];\n}\n\nexport interface SessionAttachOptions {\n tools?: ToolHandlers;\n resources?: Resource[];\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 async get(sessionId: string): Promise<SessionState> {\n return await this.httpGet(`/api/agent-sessions/${sessionId}`, sessionStateSchema);\n }\n\n /**\n * Get UI-ready session messages (for client display)\n * Returns only visible messages with hidden content filtered out\n */\n async getMessages(sessionId: string): Promise<UISessionState> {\n return await this.httpGet(\n `/api/agent-sessions/${sessionId}?format=ui`,\n uiSessionResponseSchema,\n );\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 });\n }\n}\n","import {\n safeParseStreamEvent,\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';\nimport type { Resource } from '@/resource.js';\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\n return new ReadableStream({\n async start(controller) {\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 controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({ type: 'error', errorText: err instanceof Error ? err.message : 'Unknown error' })}\\n\\n`,\n ),\n );\n controller.close();\n }\n },\n });\n}\n\nexport interface SessionConfig {\n sessionId: string;\n config: ApiClientConfig;\n tools?: ToolHandlers;\n resources?: Resource[];\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\n constructor(sessionConfig: SessionConfig) {\n this.sessionId = sessionConfig.sessionId;\n this.config = sessionConfig.config;\n this.toolHandlers = sessionConfig.tools ?? {};\n this.resourceMap = new Map();\n\n // Index resources by name for fast lookup\n for (const resource of sessionConfig.resources ?? []) {\n this.resourceMap.set(resource.name, resource);\n }\n }\n\n /**\n * Trigger an agent action and stream the response as parsed events.\n *\n * This method:\n * 1. POSTs to the platform trigger endpoint\n * 2. Yields parsed stream events to the consumer\n * 3. When tool-request event is received: executes tools locally\n * 4. POSTs a new request with toolResults to continue\n * 5. Repeats until done (no more tool requests)\n *\n * @example\n * ```typescript\n * // For sockets: iterate events directly\n * for await (const event of session.trigger('user-message', input)) {\n * conn.write(JSON.stringify(event));\n * }\n *\n * // For HTTP: convert to SSE stream\n * const events = session.trigger('user-message', input);\n * return new Response(toSSEStream(events), {\n * headers: { 'Content-Type': 'text/event-stream' },\n * });\n * ```\n */\n async *trigger(\n triggerName: string,\n triggerInput?: Record<string, unknown>,\n ): AsyncGenerator<StreamEvent> {\n let toolResults: ToolResult[] | undefined;\n let continueLoop = true;\n\n while (continueLoop) {\n // Make request to platform (with toolResults on continuation)\n const response = await fetch(\n `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,\n {\n method: 'POST',\n headers: this.config.getHeaders(),\n body: JSON.stringify({ triggerName, input: triggerInput, toolResults }),\n },\n );\n\n if (!response.ok) {\n const { message } = await parseApiError(response, 'Failed to trigger');\n yield { type: 'error', errorText: message };\n return;\n }\n\n if (!response.body) {\n yield { type: 'error', errorText: 'Response body is not readable' };\n return;\n }\n\n // Reset tool results for next iteration\n toolResults = undefined;\n\n // Read and process the SSE stream\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let pendingToolCalls: PendingToolCall[] | null = null;\n\n // Read stream until done\n let streamDone = false;\n while (!streamDone) {\n const { done, value } = await reader.read();\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 // Skip malformed events\n continue;\n }\n const event = parsed.data;\n\n // Handle tool-request - execute tools and prepare continuation\n if (event.type === 'tool-request') {\n pendingToolCalls = event.toolCalls;\n // Don't forward tool-request to consumer\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 // Handle resource updates\n if (event.type === 'resource-update') {\n this.handleResourceUpdate(event.name, event.value);\n }\n\n // Yield all other events to the consumer\n yield event;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n\n // If we have pending tool calls, execute them and continue\n if (pendingToolCalls && pendingToolCalls.length > 0) {\n toolResults = await Promise.all(\n pendingToolCalls.map(async (tc): Promise<ToolResult> => {\n const handler = this.toolHandlers[tc.toolName];\n if (!handler) {\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: `No handler for tool: ${tc.toolName}`,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n };\n }\n\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 };\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 };\n }\n }),\n );\n\n // Emit tool-output events immediately so UI updates right away\n // (before making continuation request)\n for (const tr of toolResults) {\n if (tr.error) {\n yield { type: 'tool-output-error', toolCallId: tr.toolCallId, errorText: tr.error };\n } else {\n yield { type: 'tool-output-available', toolCallId: tr.toolCallId, output: tr.result };\n }\n }\n\n // Continue loop with tool results\n } else {\n // No pending tools, we're done\n continueLoop = false;\n }\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\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 { 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","import type { ApiClientConfig } from '@/base-api-client.js';\nimport { AgentsApi } from '@/agents.js';\nimport { AgentSessionsApi } from '@/agent-sessions.js';\nimport { FilesApi } from '@/files.js';\n\nexport interface OctavusClientConfig {\n baseUrl: string;\n apiKey?: string;\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 baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: OctavusClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\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 }\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 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"],"mappings":"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","names":["z","agentId","z","z","z","z"]}
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/files.ts","../src/client.ts","../src/resource.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","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 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\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 SessionAttachOptions {\n tools?: ToolHandlers;\n resources?: Resource[];\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 /** 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 });\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';\nimport type { Resource } from '@/resource.js';\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\n return new ReadableStream({\n async start(controller) {\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 }\n },\n });\n}\n\nexport interface SessionConfig {\n sessionId: string;\n config: ApiClientConfig;\n tools?: ToolHandlers;\n resources?: Resource[];\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\n constructor(sessionConfig: SessionConfig) {\n this.sessionId = sessionConfig.sessionId;\n this.config = sessionConfig.config;\n this.toolHandlers = sessionConfig.tools ?? {};\n this.resourceMap = new Map();\n\n // Index resources by name for fast lookup\n for (const resource of sessionConfig.resources ?? []) {\n this.resourceMap.set(resource.name, resource);\n }\n }\n\n /**\n * Trigger an agent action and stream the response as parsed events.\n *\n * This method:\n * 1. POSTs to the platform trigger endpoint\n * 2. Yields parsed stream events to the consumer\n * 3. When tool-request event is received: executes tools locally\n * 4. POSTs a new request with toolResults to continue\n * 5. Repeats until done (no more tool requests)\n *\n * @param triggerName - The trigger name defined in the agent's protocol\n * @param triggerInput - Input parameters for the trigger\n * @param options - Optional configuration including abort signal\n *\n * @example\n * ```typescript\n * // For sockets: iterate events directly\n * for await (const event of session.trigger('user-message', input)) {\n * conn.write(JSON.stringify(event));\n * }\n *\n * // For HTTP: convert to SSE stream with abort support\n * const events = session.trigger('user-message', input, { signal: request.signal });\n * return new Response(toSSEStream(events), {\n * headers: { 'Content-Type': 'text/event-stream' },\n * });\n * ```\n */\n async *trigger(\n triggerName: string,\n triggerInput?: Record<string, unknown>,\n options?: TriggerOptions,\n ): AsyncGenerator<StreamEvent> {\n let toolResults: ToolResult[] | undefined;\n let continueLoop = true;\n\n while (continueLoop) {\n // Check if aborted before making request\n if (options?.signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n // Make request to platform (with toolResults on continuation)\n let response: Response;\n try {\n response = await fetch(\n `${this.config.baseUrl}/api/agent-sessions/${this.sessionId}/trigger`,\n {\n method: 'POST',\n headers: this.config.getHeaders(),\n body: JSON.stringify({\n triggerName,\n input: triggerInput,\n toolResults,\n }),\n signal: options?.signal,\n },\n );\n } catch (err) {\n // Handle abort errors gracefully\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, 'Failed to trigger');\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 // Reset tool results for next iteration\n toolResults = undefined;\n\n // Read and process the SSE stream\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let pendingToolCalls: PendingToolCall[] | null = null;\n\n // Read stream until done\n let streamDone = false;\n while (!streamDone) {\n // Check if aborted during stream reading\n if (options?.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 // Handle abort errors gracefully during read\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 // Skip malformed events\n continue;\n }\n const event = parsed.data;\n\n // Handle tool-request - execute tools and prepare continuation\n if (event.type === 'tool-request') {\n pendingToolCalls = event.toolCalls;\n // Don't forward tool-request to consumer\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 // Handle resource updates\n if (event.type === 'resource-update') {\n this.handleResourceUpdate(event.name, event.value);\n }\n\n // Yield all other events to the consumer\n yield event;\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n\n // Check if aborted before tool execution\n if (options?.signal?.aborted) {\n yield { type: 'finish', finishReason: 'stop' };\n return;\n }\n\n // If we have pending tool calls, execute them and continue\n if (pendingToolCalls && pendingToolCalls.length > 0) {\n toolResults = await Promise.all(\n pendingToolCalls.map(async (tc): Promise<ToolResult> => {\n const handler = this.toolHandlers[tc.toolName];\n if (!handler) {\n return {\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n error: `No handler for tool: ${tc.toolName}`,\n outputVariable: tc.outputVariable,\n blockIndex: tc.blockIndex,\n };\n }\n\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 };\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 };\n }\n }),\n );\n\n // Emit tool-output events immediately so UI updates right away\n // (before making continuation request)\n for (const tr of toolResults) {\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 // Continue loop with tool results\n } else {\n // No pending tools, we're done\n continueLoop = false;\n }\n }\n }\n\n getSessionId(): string {\n return this.sessionId;\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 { 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","import type { ApiClientConfig } from '@/base-api-client.js';\nimport { AgentsApi } from '@/agents.js';\nimport { AgentSessionsApi } from '@/agent-sessions.js';\nimport { FilesApi } from '@/files.js';\n\nexport interface OctavusClientConfig {\n baseUrl: string;\n apiKey?: string;\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 baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: OctavusClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.apiKey = config.apiKey;\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 }\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 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","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 SessionStatus,\n type SessionAttachOptions,\n} from '@/agent-sessions.js';\nexport {\n FilesApi,\n type FileUploadRequest,\n type FileUploadInfo,\n type UploadUrlsResponse,\n fileUploadRequestSchema,\n fileUploadInfoSchema,\n uploadUrlsResponseSchema,\n} from '@/files.js';\nexport { AgentSession, toSSEStream, type SessionConfig, type TriggerOptions } from '@/session.js';\nexport { Resource } from '@/resource.js';\nexport { ApiError } from '@/api-error.js';\n\n// Agent types and schemas (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 {\n agentFormatSchema,\n agentSchema,\n agentsResponseSchema,\n agentDefinitionSchema,\n} from '@/agent-types.js';\n\n// Re-export everything from core so consumers don't need to install @octavus/core separately\nexport * from '@octavus/core';\n"],"mappings":"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","names":["z","z","z","z","z"]}
package/package.json CHANGED
@@ -1,16 +1,26 @@
1
1
  {
2
2
  "name": "@octavus/server-sdk",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "description": "Server SDK for integrating Octavus agents",
5
5
  "license": "MIT",
6
6
  "author": "Octavus AI <dev@octavus.ai>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/octavus-ai/js-sdk.git",
10
+ "directory": "packages/server-sdk"
11
+ },
12
+ "homepage": "https://octavus.ai",
13
+ "bugs": {
14
+ "url": "https://github.com/octavus-ai/js-sdk/issues"
15
+ },
7
16
  "keywords": [
8
17
  "octavus",
9
18
  "ai",
10
19
  "agents",
11
20
  "sdk",
12
21
  "server",
13
- "tools"
22
+ "tools",
23
+ "nodejs"
14
24
  ],
15
25
  "type": "module",
16
26
  "sideEffects": false,
@@ -30,7 +40,7 @@
30
40
  },
31
41
  "dependencies": {
32
42
  "zod": "^4.1.13",
33
- "@octavus/core": "^0.1.1"
43
+ "@octavus/core": "^1.0.0"
34
44
  },
35
45
  "devDependencies": {
36
46
  "tsup": "^8.3.5",