@meistrari/agent-sdk 0.3.1 → 0.5.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 CHANGED
@@ -93,6 +93,83 @@ Multi-turn lifecycle rules:
93
93
  - Treat `completed`, `failed`, and `cancelled` as non-normal follow-up states in SDK consumers.
94
94
  - The SDK v4 path does not use the legacy `/v3/sessions/{sessionId}/continue` endpoint.
95
95
 
96
+ ### Cancel a running session
97
+
98
+ ```ts
99
+ const cancellation = await client.cancelSession(sessionId)
100
+
101
+ if (cancellation.success)
102
+ console.log(cancellation.message) // 'Message cancelled'
103
+ else
104
+ console.error(cancellation.error)
105
+ ```
106
+
107
+ `cancelSession` aborts the active turn (the model stops generating, ending token spend)
108
+ and restores the session to a continuable state: `waiting_messages` for multi-turn
109
+ sessions, `cancelled` for single-shot runs. A session that is not currently `running`
110
+ rejects with a `FetchError` (HTTP 409); branch on it with `isFetchError`.
111
+
112
+ ### Register session webhooks
113
+
114
+ Pass `webhooks` to `executeAgent` to receive lifecycle callbacks instead of polling.
115
+ Each entry takes an HTTPS `url`, an optional `events` filter, and an optional HMAC
116
+ `secret`:
117
+
118
+ ```ts
119
+ import type { SessionWebhookEventPayload } from '@meistrari/agent-sdk'
120
+
121
+ const { success, sessionId } = await client.executeAgent({
122
+ organizationName: 'acme',
123
+ repository: 'support-bot',
124
+ message: 'Summarize the latest tickets',
125
+ webhooks: [{
126
+ url: 'https://example.com/hooks/agent-session',
127
+ events: ['session.completed', 'session.failed', 'session.cancelled'],
128
+ secret: 'whsec_a-long-random-string',
129
+ }],
130
+ })
131
+ ```
132
+
133
+ Webhook semantics (full contract in [`docs/webhooks.md`](../../docs/webhooks.md)):
134
+
135
+ - Available on the v4 execute path only; up to **5 webhooks** per session.
136
+ - URLs must be HTTPS; localhost, `.local`/`.internal`, and private/loopback IP hosts are rejected.
137
+ - `events` defaults to **all `session.*` events** (`started`, `completed`, `failed`,
138
+ `cancelled`, `waiting_messages`); `subagent.started`/`subagent.completed` must be opted into.
139
+ - Passing `webhooks` on a continuation **replaces** the registered set; omitting it keeps
140
+ the existing registration.
141
+ - Deliveries are **at-least-once** with retries — make handlers idempotent.
142
+ - The payload (`SessionWebhookEventPayload`) is lightweight metadata: `eventType`,
143
+ `sessionId`, `runId`, `status`, `error`, `usage`, `subagent`, `deliveryId`. Fetch content
144
+ with `streamSession` or `fetchTimeline`.
145
+
146
+ When a `secret` is configured, verify the `x-tela-agent-webhook-signature` header with the bundled
147
+ helper (Web Crypto, works in Node/Bun/edge runtimes):
148
+
149
+ ```ts
150
+ import { verifyWebhookSignature } from '@meistrari/agent-sdk'
151
+
152
+ app.post('/hooks/agent-session', async (req) => {
153
+ const rawBody = await req.text()
154
+ const valid = await verifyWebhookSignature(
155
+ rawBody,
156
+ req.headers.get('x-tela-agent-webhook-signature'),
157
+ process.env.WEBHOOK_SECRET!,
158
+ )
159
+ if (!valid)
160
+ return new Response('invalid signature', { status: 401 })
161
+
162
+ const event = JSON.parse(rawBody) as SessionWebhookEventPayload
163
+ // ...
164
+ return new Response('ok')
165
+ })
166
+ ```
167
+
168
+ For [Trigger.dev wait-for-token](../../docs/trigger-dev-wait-token.md) flows, pass the
169
+ token's callback URL as a webhook filtered to terminal events — no `secret` needed (auth
170
+ is embedded in the token URL), and the waiting task resumes with the payload as the token
171
+ output.
172
+
96
173
  ### Update an agent model
97
174
 
98
175
  ```ts
@@ -125,6 +202,25 @@ console.log(timeline.status, timeline.metrics, timeline.spans)
125
202
  `prompt`, and `spans`. It does not return per-event detail. Consumers that need timeline
126
203
  events should consume `streamSession` and merge stream-derived timeline events locally.
127
204
 
205
+ ### Fetch captured session files
206
+
207
+ ```ts
208
+ const files = await client.listSessionFiles(sessionId, { signal })
209
+
210
+ for (const file of files.tree) {
211
+ console.log(file.path, file.size)
212
+ }
213
+
214
+ const report = await client.fetchSessionFile(sessionId, 'output/report.md', { signal })
215
+
216
+ if (report.encoding === 'raw')
217
+ console.log(report.content)
218
+ ```
219
+
220
+ `listSessionFiles` returns the file tree captured from the source sandbox after execution.
221
+ `fetchSessionFile` returns a single captured file. Text-like files are returned as
222
+ `encoding: 'raw'`; binary files are returned as base64.
223
+
128
224
  ### Resolve Vault references
129
225
 
130
226
  ```ts
@@ -147,7 +243,8 @@ This package mirrors `@meistrari/vault-sdk` and is published as `UNLICENSED`.
147
243
 
148
244
  ## Scope
149
245
 
150
- Focused on sandbox execution and the public v4 consumer paths: `executeAgent`,
151
- `streamSession`, `updateAgentModel`, `fetchTimeline`, and `resolveReference`. Agent CRUD,
152
- legacy polling, and the internal sandbox timeline callback are intentionally out of
153
- scope.
246
+ Focused on sandbox execution and the public v4 consumer paths: `executeAgent` (including
247
+ session webhook registration), `streamSession`, `cancelSession`, `updateAgentModel`,
248
+ `fetchTimeline`, `listSessionFiles`, `fetchSessionFile`, `resolveReference`, and webhook
249
+ signature verification via `verifyWebhookSignature`. Agent CRUD, legacy polling, and the
250
+ internal sandbox timeline callback are intentionally out of scope.
package/dist/index.cjs CHANGED
@@ -231,6 +231,34 @@ function agentClient(config) {
231
231
  });
232
232
  return schemas.sessionTimelineResponseSchema.parse(await response.json());
233
233
  }
234
+ async function listSessionFiles(sessionId, options) {
235
+ const parsedSessionId = schemas.sessionTimelineIdSchema.parse(sessionId);
236
+ const response = await request({
237
+ method: "GET",
238
+ path: `/v3/sessions/${encodeURIComponent(parsedSessionId)}/files`,
239
+ signal: options?.signal
240
+ });
241
+ return schemas.sessionFilesTreeResponseSchema.parse(await response.json());
242
+ }
243
+ async function fetchSessionFile(sessionId, filePath, options) {
244
+ const parsedSessionId = schemas.sessionTimelineIdSchema.parse(sessionId);
245
+ if (!filePath)
246
+ throw new Error("filePath is required");
247
+ const response = await request({
248
+ method: "GET",
249
+ path: `/v3/sessions/${encodeURIComponent(parsedSessionId)}/files/${encodeURIComponent(filePath)}`,
250
+ signal: options?.signal
251
+ });
252
+ return schemas.sessionFileContentResponseSchema.parse(await response.json());
253
+ }
254
+ async function cancelSession(sessionId) {
255
+ const parsedSessionId = schemas.sessionTimelineIdSchema.parse(sessionId);
256
+ const response = await request({
257
+ method: "POST",
258
+ path: `/v4/sessions/${encodeURIComponent(parsedSessionId)}/cancel`
259
+ });
260
+ return schemas.cancelSessionResponseSchema.parse(await response.json());
261
+ }
234
262
  async function streamSession(sessionId, options) {
235
263
  const response = await request({
236
264
  method: "GET",
@@ -267,7 +295,58 @@ function agentClient(config) {
267
295
  return JSON.parse(await vaultFile.content.text());
268
296
  return vaultFile.content.arrayBuffer();
269
297
  }
270
- return { executeAgent, updateAgentModel, fetchTimeline, streamSession, resolveReference };
298
+ return {
299
+ executeAgent,
300
+ updateAgentModel,
301
+ fetchTimeline,
302
+ listSessionFiles,
303
+ fetchSessionFile,
304
+ cancelSession,
305
+ streamSession,
306
+ resolveReference
307
+ };
308
+ }
309
+
310
+ const SIGNATURE_PREFIX = "sha256=";
311
+ function toBytes(rawBody) {
312
+ if (typeof rawBody === "string") {
313
+ return new TextEncoder().encode(rawBody);
314
+ }
315
+ const copy = new Uint8Array(rawBody.byteLength);
316
+ copy.set(rawBody);
317
+ return copy;
318
+ }
319
+ function toHex(buffer) {
320
+ return Array.from(new Uint8Array(buffer), (byte) => byte.toString(16).padStart(2, "0")).join("");
321
+ }
322
+ function timingSafeEqualStrings(a, b) {
323
+ if (a.length !== b.length) {
324
+ return false;
325
+ }
326
+ let mismatch = 0;
327
+ for (let index = 0; index < a.length; index++) {
328
+ mismatch |= a.charCodeAt(index) ^ b.charCodeAt(index);
329
+ }
330
+ return mismatch === 0;
331
+ }
332
+ async function verifyWebhookSignature(rawBody, signatureHeader, secret) {
333
+ if (!signatureHeader || !signatureHeader.startsWith(SIGNATURE_PREFIX) || !secret) {
334
+ return false;
335
+ }
336
+ try {
337
+ const key = await crypto.subtle.importKey(
338
+ "raw",
339
+ new TextEncoder().encode(secret),
340
+ { name: "HMAC", hash: "SHA-256" },
341
+ false,
342
+ ["sign"]
343
+ );
344
+ const digest = await crypto.subtle.sign("HMAC", key, toBytes(rawBody));
345
+ const expected = `${SIGNATURE_PREFIX}${toHex(digest)}`;
346
+ return timingSafeEqualStrings(signatureHeader, expected);
347
+ } catch {
348
+ return false;
349
+ }
271
350
  }
272
351
 
273
352
  exports.APIKeyAuthStrategy = APIKeyAuthStrategy;
@@ -278,3 +357,4 @@ exports.agentClient = agentClient;
278
357
  exports.isFetchError = isFetchError;
279
358
  exports.isNetworkError = isNetworkError;
280
359
  exports.parseSessionStream = parseSessionStream;
360
+ exports.verifyWebhookSignature = verifyWebhookSignature;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as ExecuteAgentRequest, a as ExecuteAgentResponse, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, S as SessionTimelineResponse, c as SessionStreamEvent } from './shared/agent-sdk.3fcc7aba.cjs';
2
- export { A as AgentInput, d as SessionStatus, T as TimelineEvent, e as TimelineMetrics, f as TimelinePrompt, g as TimelineRunTurnMetrics, h as TimelineSpan, i as TimelineToolResult } from './shared/agent-sdk.3fcc7aba.cjs';
1
+ import { E as ExecuteAgentRequest, a as ExecuteAgentResponse, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, S as SessionTimelineResponse, c as SessionFilesTreeResponse, d as SessionFileContentResponse, C as CancelSessionResponse, e as SessionStreamEvent } from './shared/agent-sdk.ed11095c.cjs';
2
+ export { A as AgentInput, f as SessionStatus, g as SessionWebhookConfig, h as SessionWebhookEventPayload, i as SessionWebhookEventType, j as SessionWebhookSubagent, k as SessionWebhookUsage, T as TimelineEvent, l as TimelineMetrics, m as TimelinePrompt, n as TimelineRunTurnMetrics, o as TimelineSpan, p as TimelineToolResult } from './shared/agent-sdk.ed11095c.cjs';
3
3
  import 'zod';
4
4
 
5
5
  interface AuthStrategy {
@@ -38,6 +38,13 @@ declare function agentClient(config: AgentClientConfig): {
38
38
  executeAgent: (input: ExecuteAgentRequest) => Promise<ExecuteAgentResponse>;
39
39
  updateAgentModel: (input: UpdateAgentModelRequest) => Promise<UpdateAgentModelResponse>;
40
40
  fetchTimeline: (sessionId: string, options?: FetchTimelineOptions) => Promise<SessionTimelineResponse>;
41
+ listSessionFiles: (sessionId: string, options?: {
42
+ signal?: AbortSignal;
43
+ }) => Promise<SessionFilesTreeResponse>;
44
+ fetchSessionFile: (sessionId: string, filePath: string, options?: {
45
+ signal?: AbortSignal;
46
+ }) => Promise<SessionFileContentResponse>;
47
+ cancelSession: (sessionId: string) => Promise<CancelSessionResponse>;
41
48
  streamSession: (sessionId: string, options?: StreamSessionOptions) => Promise<AsyncIterable<SessionStreamEvent>>;
42
49
  resolveReference: {
43
50
  (reference: string, options?: {
@@ -78,5 +85,7 @@ declare function isNetworkError(error: unknown): error is NetworkError;
78
85
 
79
86
  declare function parseSessionStream(stream: ReadableStream<Uint8Array>): AsyncIterable<SessionStreamEvent>;
80
87
 
81
- export { APIKeyAuthStrategy, DataTokenAuthStrategy, ExecuteAgentRequest, ExecuteAgentResponse, FetchError, NetworkError, SessionStreamEvent, SessionTimelineResponse, UpdateAgentModelRequest, UpdateAgentModelResponse, agentClient, isFetchError, isNetworkError, parseSessionStream };
88
+ declare function verifyWebhookSignature(rawBody: string | Uint8Array, signatureHeader: string | null | undefined, secret: string): Promise<boolean>;
89
+
90
+ export { APIKeyAuthStrategy, CancelSessionResponse, DataTokenAuthStrategy, ExecuteAgentRequest, ExecuteAgentResponse, FetchError, NetworkError, SessionFileContentResponse, SessionFilesTreeResponse, SessionStreamEvent, SessionTimelineResponse, UpdateAgentModelRequest, UpdateAgentModelResponse, agentClient, isFetchError, isNetworkError, parseSessionStream, verifyWebhookSignature };
82
91
  export type { AgentClient, AgentClientConfig, AgentRequestError, AuthStrategy, FetchTimelineOptions, ResolveReferenceAs, ResolveReferenceOptions, StreamSessionOptions };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as ExecuteAgentRequest, a as ExecuteAgentResponse, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, S as SessionTimelineResponse, c as SessionStreamEvent } from './shared/agent-sdk.3fcc7aba.mjs';
2
- export { A as AgentInput, d as SessionStatus, T as TimelineEvent, e as TimelineMetrics, f as TimelinePrompt, g as TimelineRunTurnMetrics, h as TimelineSpan, i as TimelineToolResult } from './shared/agent-sdk.3fcc7aba.mjs';
1
+ import { E as ExecuteAgentRequest, a as ExecuteAgentResponse, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, S as SessionTimelineResponse, c as SessionFilesTreeResponse, d as SessionFileContentResponse, C as CancelSessionResponse, e as SessionStreamEvent } from './shared/agent-sdk.ed11095c.mjs';
2
+ export { A as AgentInput, f as SessionStatus, g as SessionWebhookConfig, h as SessionWebhookEventPayload, i as SessionWebhookEventType, j as SessionWebhookSubagent, k as SessionWebhookUsage, T as TimelineEvent, l as TimelineMetrics, m as TimelinePrompt, n as TimelineRunTurnMetrics, o as TimelineSpan, p as TimelineToolResult } from './shared/agent-sdk.ed11095c.mjs';
3
3
  import 'zod';
4
4
 
5
5
  interface AuthStrategy {
@@ -38,6 +38,13 @@ declare function agentClient(config: AgentClientConfig): {
38
38
  executeAgent: (input: ExecuteAgentRequest) => Promise<ExecuteAgentResponse>;
39
39
  updateAgentModel: (input: UpdateAgentModelRequest) => Promise<UpdateAgentModelResponse>;
40
40
  fetchTimeline: (sessionId: string, options?: FetchTimelineOptions) => Promise<SessionTimelineResponse>;
41
+ listSessionFiles: (sessionId: string, options?: {
42
+ signal?: AbortSignal;
43
+ }) => Promise<SessionFilesTreeResponse>;
44
+ fetchSessionFile: (sessionId: string, filePath: string, options?: {
45
+ signal?: AbortSignal;
46
+ }) => Promise<SessionFileContentResponse>;
47
+ cancelSession: (sessionId: string) => Promise<CancelSessionResponse>;
41
48
  streamSession: (sessionId: string, options?: StreamSessionOptions) => Promise<AsyncIterable<SessionStreamEvent>>;
42
49
  resolveReference: {
43
50
  (reference: string, options?: {
@@ -78,5 +85,7 @@ declare function isNetworkError(error: unknown): error is NetworkError;
78
85
 
79
86
  declare function parseSessionStream(stream: ReadableStream<Uint8Array>): AsyncIterable<SessionStreamEvent>;
80
87
 
81
- export { APIKeyAuthStrategy, DataTokenAuthStrategy, ExecuteAgentRequest, ExecuteAgentResponse, FetchError, NetworkError, SessionStreamEvent, SessionTimelineResponse, UpdateAgentModelRequest, UpdateAgentModelResponse, agentClient, isFetchError, isNetworkError, parseSessionStream };
88
+ declare function verifyWebhookSignature(rawBody: string | Uint8Array, signatureHeader: string | null | undefined, secret: string): Promise<boolean>;
89
+
90
+ export { APIKeyAuthStrategy, CancelSessionResponse, DataTokenAuthStrategy, ExecuteAgentRequest, ExecuteAgentResponse, FetchError, NetworkError, SessionFileContentResponse, SessionFilesTreeResponse, SessionStreamEvent, SessionTimelineResponse, UpdateAgentModelRequest, UpdateAgentModelResponse, agentClient, isFetchError, isNetworkError, parseSessionStream, verifyWebhookSignature };
82
91
  export type { AgentClient, AgentClientConfig, AgentRequestError, AuthStrategy, FetchTimelineOptions, ResolveReferenceAs, ResolveReferenceOptions, StreamSessionOptions };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as ExecuteAgentRequest, a as ExecuteAgentResponse, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, S as SessionTimelineResponse, c as SessionStreamEvent } from './shared/agent-sdk.3fcc7aba.js';
2
- export { A as AgentInput, d as SessionStatus, T as TimelineEvent, e as TimelineMetrics, f as TimelinePrompt, g as TimelineRunTurnMetrics, h as TimelineSpan, i as TimelineToolResult } from './shared/agent-sdk.3fcc7aba.js';
1
+ import { E as ExecuteAgentRequest, a as ExecuteAgentResponse, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, S as SessionTimelineResponse, c as SessionFilesTreeResponse, d as SessionFileContentResponse, C as CancelSessionResponse, e as SessionStreamEvent } from './shared/agent-sdk.ed11095c.js';
2
+ export { A as AgentInput, f as SessionStatus, g as SessionWebhookConfig, h as SessionWebhookEventPayload, i as SessionWebhookEventType, j as SessionWebhookSubagent, k as SessionWebhookUsage, T as TimelineEvent, l as TimelineMetrics, m as TimelinePrompt, n as TimelineRunTurnMetrics, o as TimelineSpan, p as TimelineToolResult } from './shared/agent-sdk.ed11095c.js';
3
3
  import 'zod';
4
4
 
5
5
  interface AuthStrategy {
@@ -38,6 +38,13 @@ declare function agentClient(config: AgentClientConfig): {
38
38
  executeAgent: (input: ExecuteAgentRequest) => Promise<ExecuteAgentResponse>;
39
39
  updateAgentModel: (input: UpdateAgentModelRequest) => Promise<UpdateAgentModelResponse>;
40
40
  fetchTimeline: (sessionId: string, options?: FetchTimelineOptions) => Promise<SessionTimelineResponse>;
41
+ listSessionFiles: (sessionId: string, options?: {
42
+ signal?: AbortSignal;
43
+ }) => Promise<SessionFilesTreeResponse>;
44
+ fetchSessionFile: (sessionId: string, filePath: string, options?: {
45
+ signal?: AbortSignal;
46
+ }) => Promise<SessionFileContentResponse>;
47
+ cancelSession: (sessionId: string) => Promise<CancelSessionResponse>;
41
48
  streamSession: (sessionId: string, options?: StreamSessionOptions) => Promise<AsyncIterable<SessionStreamEvent>>;
42
49
  resolveReference: {
43
50
  (reference: string, options?: {
@@ -78,5 +85,7 @@ declare function isNetworkError(error: unknown): error is NetworkError;
78
85
 
79
86
  declare function parseSessionStream(stream: ReadableStream<Uint8Array>): AsyncIterable<SessionStreamEvent>;
80
87
 
81
- export { APIKeyAuthStrategy, DataTokenAuthStrategy, ExecuteAgentRequest, ExecuteAgentResponse, FetchError, NetworkError, SessionStreamEvent, SessionTimelineResponse, UpdateAgentModelRequest, UpdateAgentModelResponse, agentClient, isFetchError, isNetworkError, parseSessionStream };
88
+ declare function verifyWebhookSignature(rawBody: string | Uint8Array, signatureHeader: string | null | undefined, secret: string): Promise<boolean>;
89
+
90
+ export { APIKeyAuthStrategy, CancelSessionResponse, DataTokenAuthStrategy, ExecuteAgentRequest, ExecuteAgentResponse, FetchError, NetworkError, SessionFileContentResponse, SessionFilesTreeResponse, SessionStreamEvent, SessionTimelineResponse, UpdateAgentModelRequest, UpdateAgentModelResponse, agentClient, isFetchError, isNetworkError, parseSessionStream, verifyWebhookSignature };
82
91
  export type { AgentClient, AgentClientConfig, AgentRequestError, AuthStrategy, FetchTimelineOptions, ResolveReferenceAs, ResolveReferenceOptions, StreamSessionOptions };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { VaultFile } from '@meistrari/vault-sdk';
2
- import { SESSION_STREAM_EVENT_KINDS, sessionStreamEventSchema, executeAgentRequestSchema, executeAgentResponseSchema, updateAgentModelRequestSchema, updateAgentModelResponseSchema, sessionTimelineIdSchema, sessionTimelineResponseSchema } from './schemas.mjs';
2
+ import { SESSION_STREAM_EVENT_KINDS, sessionStreamEventSchema, executeAgentRequestSchema, executeAgentResponseSchema, updateAgentModelRequestSchema, updateAgentModelResponseSchema, sessionTimelineIdSchema, sessionTimelineResponseSchema, sessionFilesTreeResponseSchema, sessionFileContentResponseSchema, cancelSessionResponseSchema } from './schemas.mjs';
3
3
  import 'zod';
4
4
 
5
5
  var __defProp$1 = Object.defineProperty;
@@ -229,6 +229,34 @@ function agentClient(config) {
229
229
  });
230
230
  return sessionTimelineResponseSchema.parse(await response.json());
231
231
  }
232
+ async function listSessionFiles(sessionId, options) {
233
+ const parsedSessionId = sessionTimelineIdSchema.parse(sessionId);
234
+ const response = await request({
235
+ method: "GET",
236
+ path: `/v3/sessions/${encodeURIComponent(parsedSessionId)}/files`,
237
+ signal: options?.signal
238
+ });
239
+ return sessionFilesTreeResponseSchema.parse(await response.json());
240
+ }
241
+ async function fetchSessionFile(sessionId, filePath, options) {
242
+ const parsedSessionId = sessionTimelineIdSchema.parse(sessionId);
243
+ if (!filePath)
244
+ throw new Error("filePath is required");
245
+ const response = await request({
246
+ method: "GET",
247
+ path: `/v3/sessions/${encodeURIComponent(parsedSessionId)}/files/${encodeURIComponent(filePath)}`,
248
+ signal: options?.signal
249
+ });
250
+ return sessionFileContentResponseSchema.parse(await response.json());
251
+ }
252
+ async function cancelSession(sessionId) {
253
+ const parsedSessionId = sessionTimelineIdSchema.parse(sessionId);
254
+ const response = await request({
255
+ method: "POST",
256
+ path: `/v4/sessions/${encodeURIComponent(parsedSessionId)}/cancel`
257
+ });
258
+ return cancelSessionResponseSchema.parse(await response.json());
259
+ }
232
260
  async function streamSession(sessionId, options) {
233
261
  const response = await request({
234
262
  method: "GET",
@@ -265,7 +293,58 @@ function agentClient(config) {
265
293
  return JSON.parse(await vaultFile.content.text());
266
294
  return vaultFile.content.arrayBuffer();
267
295
  }
268
- return { executeAgent, updateAgentModel, fetchTimeline, streamSession, resolveReference };
296
+ return {
297
+ executeAgent,
298
+ updateAgentModel,
299
+ fetchTimeline,
300
+ listSessionFiles,
301
+ fetchSessionFile,
302
+ cancelSession,
303
+ streamSession,
304
+ resolveReference
305
+ };
306
+ }
307
+
308
+ const SIGNATURE_PREFIX = "sha256=";
309
+ function toBytes(rawBody) {
310
+ if (typeof rawBody === "string") {
311
+ return new TextEncoder().encode(rawBody);
312
+ }
313
+ const copy = new Uint8Array(rawBody.byteLength);
314
+ copy.set(rawBody);
315
+ return copy;
316
+ }
317
+ function toHex(buffer) {
318
+ return Array.from(new Uint8Array(buffer), (byte) => byte.toString(16).padStart(2, "0")).join("");
319
+ }
320
+ function timingSafeEqualStrings(a, b) {
321
+ if (a.length !== b.length) {
322
+ return false;
323
+ }
324
+ let mismatch = 0;
325
+ for (let index = 0; index < a.length; index++) {
326
+ mismatch |= a.charCodeAt(index) ^ b.charCodeAt(index);
327
+ }
328
+ return mismatch === 0;
329
+ }
330
+ async function verifyWebhookSignature(rawBody, signatureHeader, secret) {
331
+ if (!signatureHeader || !signatureHeader.startsWith(SIGNATURE_PREFIX) || !secret) {
332
+ return false;
333
+ }
334
+ try {
335
+ const key = await crypto.subtle.importKey(
336
+ "raw",
337
+ new TextEncoder().encode(secret),
338
+ { name: "HMAC", hash: "SHA-256" },
339
+ false,
340
+ ["sign"]
341
+ );
342
+ const digest = await crypto.subtle.sign("HMAC", key, toBytes(rawBody));
343
+ const expected = `${SIGNATURE_PREFIX}${toHex(digest)}`;
344
+ return timingSafeEqualStrings(signatureHeader, expected);
345
+ } catch {
346
+ return false;
347
+ }
269
348
  }
270
349
 
271
- export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, NetworkError, agentClient, isFetchError, isNetworkError, parseSessionStream };
350
+ export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, NetworkError, agentClient, isFetchError, isNetworkError, parseSessionStream, verifyWebhookSignature };
package/dist/schemas.cjs CHANGED
@@ -430,6 +430,7 @@ const nativeAnthropicModelIds = [
430
430
  "claude-sonnet-4-5",
431
431
  "claude-sonnet-4-6",
432
432
  "claude-haiku-4-5",
433
+ "claude-fable-5",
433
434
  "claude-opus-4-6",
434
435
  "claude-opus-4-7",
435
436
  "claude-opus-4-8"
@@ -442,6 +443,118 @@ const modelSchema = zod.z.enum([
442
443
  ...openrouterModelIds
443
444
  ]);
444
445
 
446
+ const sessionWebhookEventTypeSchema = zod.z.enum([
447
+ "session.started",
448
+ "session.completed",
449
+ "session.failed",
450
+ "session.cancelled",
451
+ "session.waiting_messages",
452
+ "subagent.started",
453
+ "subagent.completed"
454
+ ]);
455
+ const SESSION_WEBHOOK_DEFAULT_EVENTS = [
456
+ "session.started",
457
+ "session.completed",
458
+ "session.failed",
459
+ "session.cancelled",
460
+ "session.waiting_messages"
461
+ ];
462
+ const BLOCKED_HOSTNAME_SUFFIXES = [".localhost", ".local", ".internal"];
463
+ const BLOCKED_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "metadata.google.internal"]);
464
+ function isPrivateIpv4(hostname) {
465
+ const match = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
466
+ if (!match) {
467
+ return false;
468
+ }
469
+ const octets = match.slice(1).map(Number);
470
+ if (octets.some((octet) => octet > 255)) {
471
+ return true;
472
+ }
473
+ const a = octets[0] ?? 0;
474
+ const b = octets[1] ?? 0;
475
+ return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168;
476
+ }
477
+ function isPrivateIpv6(hostname) {
478
+ const normalized = hostname.replace(/^\[|\]$/g, "").toLowerCase();
479
+ if (!normalized.includes(":")) {
480
+ return false;
481
+ }
482
+ return normalized === "::" || normalized === "::1" || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("fe8") || normalized.startsWith("fe9") || normalized.startsWith("fea") || normalized.startsWith("feb") || normalized.startsWith("::ffff:");
483
+ }
484
+ function isBlockedWebhookHostname(hostname) {
485
+ const normalized = hostname.toLowerCase();
486
+ if (BLOCKED_HOSTNAMES.has(normalized)) {
487
+ return true;
488
+ }
489
+ if (BLOCKED_HOSTNAME_SUFFIXES.some((suffix) => normalized.endsWith(suffix))) {
490
+ return true;
491
+ }
492
+ return isPrivateIpv4(normalized) || isPrivateIpv6(normalized);
493
+ }
494
+ function validateWebhookUrl(value) {
495
+ let parsed;
496
+ try {
497
+ parsed = new URL(value);
498
+ } catch {
499
+ return "Webhook URL is invalid";
500
+ }
501
+ if (parsed.protocol !== "https:") {
502
+ return "Webhook URLs must use https";
503
+ }
504
+ if (isBlockedWebhookHostname(parsed.hostname)) {
505
+ return "Webhook URL host is not allowed";
506
+ }
507
+ return null;
508
+ }
509
+ const sessionWebhookConfigSchema = zod.z.object({
510
+ url: zod.z.string().max(2048).superRefine((value, ctx) => {
511
+ const error = validateWebhookUrl(value);
512
+ if (error) {
513
+ ctx.addIssue({ code: "custom", message: error });
514
+ }
515
+ }).describe("HTTPS endpoint that receives lifecycle event POSTs (e.g. a Trigger.dev wait-token URL)"),
516
+ events: zod.z.array(sessionWebhookEventTypeSchema).min(1).optional().describe("Event filter; defaults to all session.* events (subagent.* events must be opted into)"),
517
+ secret: zod.z.string().min(8).max(256).optional().describe("Optional HMAC-SHA256 signing secret used for the x-tela-agent-webhook-signature header")
518
+ }).strict();
519
+ const sessionWebhooksSchema = zod.z.array(sessionWebhookConfigSchema).max(5).describe("Webhook endpoints notified about session lifecycle and subagent events");
520
+ const sessionWebhookUsageSchema = zod.z.object({
521
+ inputTokens: zod.z.number().int().nonnegative().optional(),
522
+ outputTokens: zod.z.number().int().nonnegative().optional(),
523
+ cacheReadInputTokens: zod.z.number().int().nonnegative().optional(),
524
+ cacheCreationInputTokens: zod.z.number().int().nonnegative().optional(),
525
+ totalCostUsd: zod.z.number().nullable().optional(),
526
+ durationMs: zod.z.number().int().nonnegative().optional(),
527
+ numTurns: zod.z.number().int().nonnegative().optional()
528
+ }).strict();
529
+ const sessionWebhookSubagentSchema = zod.z.object({
530
+ callId: zod.z.string().min(1).max(256),
531
+ subagentType: zod.z.string().max(256).optional(),
532
+ status: zod.z.enum(["success", "failed"]).optional(),
533
+ durationMs: zod.z.number().int().nonnegative().optional()
534
+ }).strict();
535
+ const sessionWebhookEventPayloadSchema = zod.z.object({
536
+ eventType: sessionWebhookEventTypeSchema,
537
+ sessionId: zod.z.string(),
538
+ workspaceId: zod.z.string().optional(),
539
+ runId: zod.z.string().optional(),
540
+ status: zod.z.string(),
541
+ error: zod.z.string().optional(),
542
+ usage: sessionWebhookUsageSchema.optional(),
543
+ subagent: sessionWebhookSubagentSchema.optional(),
544
+ timestamp: zod.z.string(),
545
+ apiVersion: zod.z.literal("v4"),
546
+ deliveryId: zod.z.string()
547
+ });
548
+ const sessionAgentEventSchema = zod.z.object({
549
+ type: zod.z.enum(["subagent.started", "subagent.completed"]),
550
+ callId: zod.z.string().min(1).max(256),
551
+ subagentType: zod.z.string().max(256).optional(),
552
+ status: zod.z.enum(["success", "failed"]).optional(),
553
+ durationMs: zod.z.number().int().nonnegative().optional(),
554
+ timestamp: zod.z.number().int().nonnegative()
555
+ }).strict();
556
+ const sessionAgentEventsSchema = zod.z.array(sessionAgentEventSchema).max(20);
557
+
445
558
  const vaultReferenceSchema = zod.z.string().regex(/^vault:\/\/\S+$/, "vaultRef must start with vault:// and cannot contain whitespace");
446
559
  const agentInputSchema = zod.z.object({
447
560
  vaultRef: vaultReferenceSchema,
@@ -456,7 +569,8 @@ const executeAgentRequestSchema = zod.z.object({
456
569
  message: zod.z.string().min(1).max(8e5).optional(),
457
570
  inputs: zod.z.array(agentInputSchema).optional(),
458
571
  environmentVariables: zod.z.record(zod.z.string(), zod.z.string()).optional(),
459
- recover: zod.z.boolean().optional()
572
+ recover: zod.z.boolean().optional(),
573
+ webhooks: sessionWebhooksSchema.optional()
460
574
  }).strict().superRefine((data, ctx) => {
461
575
  if (!data.sessionId) {
462
576
  if (!data.organizationName) {
@@ -586,6 +700,21 @@ const sessionTimelineResponseSchema = zod.z.object({
586
700
  prompt: timelinePromptSchema,
587
701
  spans: zod.z.array(timelineSpanSchema)
588
702
  });
703
+ const sessionFilesTreeResponseSchema = zod.z.object({
704
+ sessionId: zod.z.string(),
705
+ tree: zod.z.array(zod.z.object({
706
+ path: zod.z.string(),
707
+ size: zod.z.number()
708
+ })),
709
+ truncated: zod.z.boolean(),
710
+ capturedAt: zod.z.number()
711
+ });
712
+ const sessionFileContentResponseSchema = zod.z.object({
713
+ filePath: zod.z.string(),
714
+ content: zod.z.string(),
715
+ encoding: zod.z.enum(["raw", "base64"]),
716
+ size: zod.z.number()
717
+ });
589
718
  const sessionStatusEventSchema = zod.z.object({
590
719
  kind: zod.z.literal("status"),
591
720
  sessionId: zod.z.string(),
@@ -637,22 +766,39 @@ const sessionStreamEventSchema = zod.z.discriminatedUnion("kind", [
637
766
  sessionErrorEventSchema
638
767
  ]);
639
768
  const SESSION_STREAM_EVENT_KINDS = /* @__PURE__ */ new Set(["status", "steps", "result", "timeline-finalize", "error"]);
769
+ const cancelSessionResponseSchema = zod.z.discriminatedUnion("success", [
770
+ zod.z.object({ success: zod.z.literal(true), message: zod.z.string() }),
771
+ zod.z.object({ success: zod.z.literal(false), error: zod.z.string() })
772
+ ]);
640
773
 
641
774
  exports.SESSION_STREAM_EVENT_KINDS = SESSION_STREAM_EVENT_KINDS;
775
+ exports.SESSION_WEBHOOK_DEFAULT_EVENTS = SESSION_WEBHOOK_DEFAULT_EVENTS;
642
776
  exports.agentInputSchema = agentInputSchema;
777
+ exports.cancelSessionResponseSchema = cancelSessionResponseSchema;
643
778
  exports.executeAgentErrorResponseSchema = executeAgentErrorResponseSchema;
644
779
  exports.executeAgentRequestSchema = executeAgentRequestSchema;
645
780
  exports.executeAgentResponseSchema = executeAgentResponseSchema;
646
781
  exports.executeAgentSuccessResponseSchema = executeAgentSuccessResponseSchema;
782
+ exports.isBlockedWebhookHostname = isBlockedWebhookHostname;
647
783
  exports.modelSchema = modelSchema;
648
784
  exports.nativeAnthropicModelIds = nativeAnthropicModelIds;
649
785
  exports.nativeModelSchema = nativeModelSchema;
650
786
  exports.openrouterModelCatalog = openrouterModelCatalog;
651
787
  exports.openrouterModelIds = openrouterModelIds;
788
+ exports.sessionAgentEventSchema = sessionAgentEventSchema;
789
+ exports.sessionAgentEventsSchema = sessionAgentEventsSchema;
790
+ exports.sessionFileContentResponseSchema = sessionFileContentResponseSchema;
791
+ exports.sessionFilesTreeResponseSchema = sessionFilesTreeResponseSchema;
652
792
  exports.sessionStatusSchema = sessionStatusSchema;
653
793
  exports.sessionStreamEventSchema = sessionStreamEventSchema;
654
794
  exports.sessionTimelineIdSchema = sessionTimelineIdSchema;
655
795
  exports.sessionTimelineResponseSchema = sessionTimelineResponseSchema;
796
+ exports.sessionWebhookConfigSchema = sessionWebhookConfigSchema;
797
+ exports.sessionWebhookEventPayloadSchema = sessionWebhookEventPayloadSchema;
798
+ exports.sessionWebhookEventTypeSchema = sessionWebhookEventTypeSchema;
799
+ exports.sessionWebhookSubagentSchema = sessionWebhookSubagentSchema;
800
+ exports.sessionWebhookUsageSchema = sessionWebhookUsageSchema;
801
+ exports.sessionWebhooksSchema = sessionWebhooksSchema;
656
802
  exports.timelineEventSchema = timelineEventSchema;
657
803
  exports.timelineMetricsSchema = timelineMetricsSchema;
658
804
  exports.timelinePromptSchema = timelinePromptSchema;
@@ -663,3 +809,4 @@ exports.updateAgentModelErrorResponseSchema = updateAgentModelErrorResponseSchem
663
809
  exports.updateAgentModelRequestSchema = updateAgentModelRequestSchema;
664
810
  exports.updateAgentModelResponseSchema = updateAgentModelResponseSchema;
665
811
  exports.updateAgentModelSuccessResponseSchema = updateAgentModelSuccessResponseSchema;
812
+ exports.validateWebhookUrl = validateWebhookUrl;
@@ -1,13 +1,14 @@
1
- export { A as AgentInput, E as ExecuteAgentRequest, a as ExecuteAgentResponse, D as SESSION_STREAM_EVENT_KINDS, d as SessionStatus, c as SessionStreamEvent, S as SessionTimelineResponse, T as TimelineEvent, e as TimelineMetrics, f as TimelinePrompt, g as TimelineRunTurnMetrics, h as TimelineSpan, i as TimelineToolResult, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, j as agentInputSchema, m as executeAgentErrorResponseSchema, k as executeAgentRequestSchema, n as executeAgentResponseSchema, l as executeAgentSuccessResponseSchema, s as sessionStatusSchema, C as sessionStreamEventSchema, r as sessionTimelineIdSchema, B as sessionTimelineResponseSchema, y as timelineEventSchema, t as timelineMetricsSchema, v as timelinePromptSchema, x as timelineRunTurnMetricsSchema, z as timelineSpanSchema, w as timelineToolResultSchema, p as updateAgentModelErrorResponseSchema, u as updateAgentModelRequestSchema, q as updateAgentModelResponseSchema, o as updateAgentModelSuccessResponseSchema } from './shared/agent-sdk.3fcc7aba.cjs';
1
+ export { A as AgentInput, C as CancelSessionResponse, E as ExecuteAgentRequest, a as ExecuteAgentResponse, O as SESSION_STREAM_EVENT_KINDS, R as SESSION_WEBHOOK_DEFAULT_EVENTS, a1 as SessionAgentEvent, d as SessionFileContentResponse, c as SessionFilesTreeResponse, f as SessionStatus, e as SessionStreamEvent, S as SessionTimelineResponse, g as SessionWebhookConfig, h as SessionWebhookEventPayload, i as SessionWebhookEventType, j as SessionWebhookSubagent, k as SessionWebhookUsage, T as TimelineEvent, l as TimelineMetrics, m as TimelinePrompt, n as TimelineRunTurnMetrics, o as TimelineSpan, p as TimelineToolResult, U as UpdateAgentModelRequest, b as UpdateAgentModelResponse, q as agentInputSchema, P as cancelSessionResponseSchema, t as executeAgentErrorResponseSchema, r as executeAgentRequestSchema, u as executeAgentResponseSchema, s as executeAgentSuccessResponseSchema, V as isBlockedWebhookHostname, a0 as sessionAgentEventSchema, a2 as sessionAgentEventsSchema, M as sessionFileContentResponseSchema, L as sessionFilesTreeResponseSchema, z as sessionStatusSchema, N as sessionStreamEventSchema, B as sessionTimelineIdSchema, K as sessionTimelineResponseSchema, X as sessionWebhookConfigSchema, $ as sessionWebhookEventPayloadSchema, Q as sessionWebhookEventTypeSchema, _ as sessionWebhookSubagentSchema, Z as sessionWebhookUsageSchema, Y as sessionWebhooksSchema, I as timelineEventSchema, D as timelineMetricsSchema, F as timelinePromptSchema, H as timelineRunTurnMetricsSchema, J as timelineSpanSchema, G as timelineToolResultSchema, x as updateAgentModelErrorResponseSchema, v as updateAgentModelRequestSchema, y as updateAgentModelResponseSchema, w as updateAgentModelSuccessResponseSchema, W as validateWebhookUrl } from './shared/agent-sdk.ed11095c.cjs';
2
2
  import { z } from 'zod';
3
3
 
4
- declare const nativeAnthropicModelIds: readonly ["claude-sonnet-4-5", "claude-sonnet-4-6", "claude-haiku-4-5", "claude-opus-4-6", "claude-opus-4-7", "claude-opus-4-8"];
4
+ declare const nativeAnthropicModelIds: readonly ["claude-sonnet-4-5", "claude-sonnet-4-6", "claude-haiku-4-5", "claude-fable-5", "claude-opus-4-6", "claude-opus-4-7", "claude-opus-4-8"];
5
5
  type NativeAnthropicModelId = typeof nativeAnthropicModelIds[number];
6
6
  type V3Provider = 'anthropic' | 'vertex-ai' | 'openrouter' | 'bedrock' | 'tela-claude-agent-gateway';
7
7
  declare const nativeModelSchema: z.ZodEnum<{
8
8
  "claude-sonnet-4-5": "claude-sonnet-4-5";
9
9
  "claude-sonnet-4-6": "claude-sonnet-4-6";
10
10
  "claude-haiku-4-5": "claude-haiku-4-5";
11
+ "claude-fable-5": "claude-fable-5";
11
12
  "claude-opus-4-6": "claude-opus-4-6";
12
13
  "claude-opus-4-7": "claude-opus-4-7";
13
14
  "claude-opus-4-8": "claude-opus-4-8";