@machinemetrics/agent-event-protocol 0.1.0 → 0.2.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
@@ -84,17 +84,17 @@ When the agent needs client-side action, the stream pauses and resumes via a new
84
84
 
85
85
  The protocol defines 9 event types covering the complete lifecycle of an agent response.
86
86
 
87
- | Event | Description |
88
- |-------|-------------|
89
- | `metadata` | Stream initialization with threadId, requestId, agentId |
90
- | `text` | Streaming text output with stage lifecycle |
91
- | `thinking` | Model reasoning/thinking content (extended thinking) |
92
- | `tool_call` | Tool invocation with streaming arguments |
93
- | `tool_result` | Tool execution result (status and summary only) |
94
- | `done` | Stream complete with full content array |
95
- | `error` | Error condition with code and retry guidance |
96
- | `aborted` | Client cancellation acknowledgment |
97
- | `continuation` | Pause for client action (tools, approval, input) |
87
+ | Event | Description |
88
+ | -------------- | ------------------------------------------------------- |
89
+ | `metadata` | Stream initialization with threadId, requestId, agentId |
90
+ | `text` | Streaming text output with stage lifecycle |
91
+ | `thinking` | Model reasoning/thinking content (extended thinking) |
92
+ | `tool_call` | Tool invocation with streaming arguments |
93
+ | `tool_result` | Tool execution result (status and summary only) |
94
+ | `done` | Stream complete with full content array |
95
+ | `error` | Error condition with code and retry guidance |
96
+ | `aborted` | Client cancellation acknowledgment |
97
+ | `continuation` | Pause for client action (tools, approval, input) |
98
98
 
99
99
  ### Terminal Events
100
100
 
@@ -104,21 +104,21 @@ Each request must end with exactly one terminal event: `done`, `error`, or `abor
104
104
 
105
105
  Content events (`text`, `thinking`, `tool_call`, `tool_result`) use a consistent stage pattern:
106
106
 
107
- | Stage | Description |
108
- |-------|-------------|
109
- | `start` | Block begins, includes `blockIndex` for ordering |
107
+ | Stage | Description |
108
+ | ------- | -------------------------------------------------------------- |
109
+ | `start` | Block begins, includes `blockIndex` for ordering |
110
110
  | `delta` | Content chunk, includes `deltaIndex` for ordering within block |
111
- | `stop` | Block complete, includes final data for that block type |
111
+ | `stop` | Block complete, includes final data for that block type |
112
112
 
113
113
  ## Request Schema
114
114
 
115
115
  ```typescript
116
116
  type AgentRequest = {
117
- messages: InputMessage[]; // New user input
118
- threadId?: string; // Resume existing thread
117
+ messages: InputMessage[]; // New user input
118
+ threadId?: string; // Resume existing thread
119
119
  context?: {
120
- actionResults?: ActionResult[]; // Results from continuation events
121
- [key: string]: unknown; // Additional passthrough data
120
+ actionResults?: ActionResult[]; // Results from continuation events
121
+ [key: string]: unknown; // Additional passthrough data
122
122
  };
123
123
  };
124
124
  ```
@@ -128,9 +128,12 @@ Only `messages` is required. The server loads thread history from storage via `t
128
128
  ## Content Blocks
129
129
 
130
130
  **User Content Blocks** (in requests):
131
+
131
132
  - `text` - Plain text input
133
+ - `attachment` - A file the user uploaded ahead of the message, referenced by `attachmentId`, with its `mimeType` and optional `name`. The protocol accepts any media type; the server decides which it supports and how each reaches the model (image, document, extracted text, tool).
132
134
 
133
135
  **Assistant Content Blocks** (in responses):
136
+
134
137
  - `text` - Text output
135
138
  - `thinking` - Model reasoning
136
139
  - `tool_use` - Tool invocation with args
@@ -140,32 +143,33 @@ Only `messages` is required. The server loads thread history from storage via `t
140
143
 
141
144
  ### Error Codes
142
145
 
143
- | Code | Description |
144
- |------|-------------|
145
- | `auth_failed` | Authentication failed |
146
- | `thread_not_found` | Thread does not exist |
147
- | `thread_access_denied` | Thread ownership violation |
148
- | `invalid_message_format` | Invalid request format |
149
- | `message_too_large` | Message exceeds size limit |
150
- | `rate_limit_exceeded` | Rate limit hit |
151
- | `stream_timeout` | Stream timed out |
152
- | `agent_error` | Agent execution error |
153
- | `tool_error` | Tool execution error |
154
- | `internal_error` | Internal server error |
155
- | `invalid_action_id` | Action ID not found or already resolved |
146
+ | Code | Description |
147
+ | ------------------------ | --------------------------------------- |
148
+ | `auth_failed` | Authentication failed |
149
+ | `thread_not_found` | Thread does not exist |
150
+ | `thread_access_denied` | Thread ownership violation |
151
+ | `invalid_message_format` | Invalid request format |
152
+ | `message_too_large` | Message exceeds size limit |
153
+ | `rate_limit_exceeded` | Rate limit hit |
154
+ | `stream_timeout` | Stream timed out |
155
+ | `stream_stalled` | Model went silent mid-reply; retryable |
156
+ | `agent_error` | Agent execution error |
157
+ | `tool_error` | Tool execution error |
158
+ | `internal_error` | Internal server error |
159
+ | `invalid_action_id` | Action ID not found or already resolved |
156
160
 
157
161
  ### HTTP Status Mapping
158
162
 
159
- | Status | Error Codes |
160
- |--------|-------------|
161
- | 400 | `invalid_message_format`, `invalid_action_id` |
162
- | 401 | `auth_failed` |
163
- | 403 | `thread_access_denied` |
164
- | 404 | `thread_not_found` |
165
- | 413 | `message_too_large` |
166
- | 429 | `rate_limit_exceeded` |
167
- | 500 | `internal_error` |
168
- | 504 | `stream_timeout` |
163
+ | Status | Error Codes |
164
+ | ------ | --------------------------------------------- |
165
+ | 400 | `invalid_message_format`, `invalid_action_id` |
166
+ | 401 | `auth_failed` |
167
+ | 403 | `thread_access_denied` |
168
+ | 404 | `thread_not_found` |
169
+ | 413 | `message_too_large` |
170
+ | 429 | `rate_limit_exceeded` |
171
+ | 500 | `internal_error` |
172
+ | 504 | `stream_timeout` |
169
173
 
170
174
  ### Retry Guidance
171
175
 
@@ -215,11 +219,13 @@ const { events, remainder } = parseSSEChunk(chunk);
215
219
  ## Extensibility
216
220
 
217
221
  **Adding new events is backward compatible:**
222
+
218
223
  - Clients should ignore unknown event types
219
224
  - New optional fields can be added to existing events
220
225
  - No version bump required for additive changes
221
226
 
222
227
  **Breaking changes require new endpoint version:**
228
+
223
229
  ```
224
230
  /v1/agents/{agentName}/stream → Current
225
231
  /v2/agents/{agentName}/stream → Breaking changes
@@ -1,9 +1,24 @@
1
1
  // src/core/schemas.ts
2
2
  import { z } from "zod";
3
- var UserContentBlockSchema = z.object({
3
+ var UserTextBlockSchema = z.object({
4
4
  type: z.literal("text"),
5
5
  text: z.string()
6
6
  });
7
+ var RESTRICTED_NAME = "[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}";
8
+ var MediaTypeSchema = z.string().regex(
9
+ new RegExp(`^${RESTRICTED_NAME}/${RESTRICTED_NAME}$`),
10
+ "expected a media type such as image/png"
11
+ );
12
+ var UserAttachmentBlockSchema = z.object({
13
+ type: z.literal("attachment"),
14
+ attachmentId: z.string().min(1),
15
+ mimeType: MediaTypeSchema,
16
+ name: z.string().min(1).optional()
17
+ });
18
+ var UserContentBlockSchema = z.discriminatedUnion("type", [
19
+ UserTextBlockSchema,
20
+ UserAttachmentBlockSchema
21
+ ]);
7
22
  var AssistantContentBlockSchema = z.discriminatedUnion("type", [
8
23
  z.object({ type: z.literal("text"), text: z.string() }),
9
24
  z.object({ type: z.literal("thinking"), text: z.string() }),
@@ -18,7 +33,8 @@ var AssistantContentBlockSchema = z.discriminatedUnion("type", [
18
33
  toolCallId: z.string(),
19
34
  tool: z.string(),
20
35
  status: z.enum(["success", "error"]),
21
- summary: z.string().optional()
36
+ summary: z.string().optional(),
37
+ output: z.record(z.string(), z.unknown()).optional()
22
38
  })
23
39
  ]);
24
40
  var InputMessageSchema = z.object({
@@ -47,6 +63,7 @@ var ErrorCodeSchema = z.enum([
47
63
  "message_too_large",
48
64
  "rate_limit_exceeded",
49
65
  "stream_timeout",
66
+ "stream_stalled",
50
67
  "agent_error",
51
68
  "tool_error",
52
69
  "internal_error",
@@ -107,6 +124,7 @@ var ToolResultEventSchema = z.object({
107
124
  tool: z.string().optional(),
108
125
  status: z.enum(["success", "error"]).optional(),
109
126
  summary: z.string().optional(),
127
+ output: z.record(z.string(), z.unknown()).optional(),
110
128
  timestamp: z.string()
111
129
  });
112
130
  var DoneEventSchema = z.object({
@@ -156,8 +174,97 @@ var AgentEventSchema = z.discriminatedUnion("event", [
156
174
  AbortedEventSchema,
157
175
  ContinuationEventSchema
158
176
  ]);
177
+ if (import.meta.vitest) {
178
+ const { describe, it, expect } = import.meta.vitest;
179
+ describe("UserContentBlockSchema", () => {
180
+ it("accepts a text block", () => {
181
+ expect(UserContentBlockSchema.safeParse({ type: "text", text: "hi" }).success).toBe(true);
182
+ });
183
+ it("accepts an attachment of any media type, with or without a name", () => {
184
+ for (const block of [
185
+ { type: "attachment", attachmentId: "att-1", mimeType: "image/png" },
186
+ {
187
+ type: "attachment",
188
+ attachmentId: "att-2",
189
+ mimeType: "application/pdf",
190
+ name: "spec.pdf"
191
+ },
192
+ { type: "attachment", attachmentId: "att-3", mimeType: "text/csv", name: "scrap.csv" }
193
+ ]) {
194
+ expect(UserContentBlockSchema.safeParse(block).success).toBe(true);
195
+ }
196
+ });
197
+ it("rejects an attachment without an id", () => {
198
+ expect(
199
+ UserContentBlockSchema.safeParse({ type: "attachment", mimeType: "image/png" }).success
200
+ ).toBe(false);
201
+ });
202
+ it("rejects a malformed media type", () => {
203
+ expect(
204
+ UserContentBlockSchema.safeParse({
205
+ type: "attachment",
206
+ attachmentId: "att-1",
207
+ mimeType: "png"
208
+ }).success
209
+ ).toBe(false);
210
+ });
211
+ it("follows RFC 6838 restricted names for the media type", () => {
212
+ const ok = (mimeType) => UserContentBlockSchema.safeParse({ type: "attachment", attachmentId: "a", mimeType }).success;
213
+ expect(ok("application/vnd.ms-excel")).toBe(true);
214
+ expect(ok("application/x-foo!#$&^_.+-bar")).toBe(true);
215
+ expect(ok("image/svg+xml")).toBe(true);
216
+ expect(ok(".foo/bar")).toBe(false);
217
+ expect(ok("image/-png")).toBe(false);
218
+ expect(ok("image/png; charset=x")).toBe(false);
219
+ expect(ok(`image/${"a".repeat(127)}`)).toBe(true);
220
+ expect(ok(`image/${"a".repeat(128)}`)).toBe(false);
221
+ });
222
+ it("rejects an unknown block type", () => {
223
+ expect(
224
+ UserContentBlockSchema.safeParse({
225
+ type: "image",
226
+ mimeType: "image/png",
227
+ attachmentId: "a"
228
+ }).success
229
+ ).toBe(false);
230
+ });
231
+ });
232
+ describe("ErrorEventSchema", () => {
233
+ it("accepts a stream_stalled error", () => {
234
+ expect(
235
+ AgentEventSchema.safeParse({
236
+ event: "error",
237
+ requestId: "r",
238
+ message: "The agent stopped responding",
239
+ code: "stream_stalled",
240
+ retryable: true,
241
+ timestamp: "2026-11-04T00:00:00.000Z"
242
+ }).success
243
+ ).toBe(true);
244
+ });
245
+ });
246
+ describe("AgentRequestSchema with attachment blocks", () => {
247
+ it("accepts a message mixing text and attachment blocks", () => {
248
+ const result = AgentRequestSchema.safeParse({
249
+ messages: [
250
+ {
251
+ content: [
252
+ { type: "text", text: "What is this?" },
253
+ { type: "attachment", attachmentId: "a", mimeType: "image/webp", name: "photo.webp" }
254
+ ]
255
+ }
256
+ ],
257
+ threadId: "t"
258
+ });
259
+ expect(result.success).toBe(true);
260
+ });
261
+ });
262
+ }
159
263
 
160
264
  export {
265
+ UserTextBlockSchema,
266
+ MediaTypeSchema,
267
+ UserAttachmentBlockSchema,
161
268
  UserContentBlockSchema,
162
269
  AssistantContentBlockSchema,
163
270
  InputMessageSchema,
@@ -177,4 +284,4 @@ export {
177
284
  ContinuationEventSchema,
178
285
  AgentEventSchema
179
286
  };
180
- //# sourceMappingURL=chunk-WZD2VBMM.js.map
287
+ //# sourceMappingURL=chunk-434TVYA5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/schemas.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Zod schema for a user text block.\n */\nexport const UserTextBlockSchema = z.object({\n type: z.literal('text'),\n text: z.string(),\n});\n\n/**\n * Zod schema for a media type (`type/subtype`, e.g. `image/png`,\n * `application/pdf`): RFC 6838 restricted names, each starting with a letter\n * or digit and at most 127 characters. Which media types a server accepts is the server's\n * decision, not the protocol's.\n */\nconst RESTRICTED_NAME = '[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}';\n\nexport const MediaTypeSchema = z\n .string()\n .regex(\n new RegExp(`^${RESTRICTED_NAME}/${RESTRICTED_NAME}$`),\n 'expected a media type such as image/png',\n );\n\n/**\n * Zod schema for a user attachment block: a file the user uploaded ahead of\n * the message and now refers to by id. How the file reaches the model (an\n * image, a document, extracted text, a tool) is the server's decision.\n */\nexport const UserAttachmentBlockSchema = z.object({\n type: z.literal('attachment'),\n attachmentId: z.string().min(1),\n mimeType: MediaTypeSchema,\n name: z.string().min(1).optional(),\n});\n\n/**\n * Zod schema for validating user content blocks: text or an attachment.\n */\nexport const UserContentBlockSchema = z.discriminatedUnion('type', [\n UserTextBlockSchema,\n UserAttachmentBlockSchema,\n]);\n\n/**\n * Zod schema for validating assistant content blocks.\n * Discriminated union supporting text, thinking, tool_use, and tool_result.\n */\nexport const AssistantContentBlockSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('text'), text: z.string() }),\n z.object({ type: z.literal('thinking'), text: z.string() }),\n z.object({\n type: z.literal('tool_use'),\n toolCallId: z.string(),\n tool: z.string(),\n args: z.record(z.string(), z.unknown()),\n }),\n z.object({\n type: z.literal('tool_result'),\n toolCallId: z.string(),\n tool: z.string(),\n status: z.enum(['success', 'error']),\n summary: z.string().optional(),\n output: z.record(z.string(), z.unknown()).optional(),\n }),\n]);\n\n/**\n * Zod schema for validating input messages.\n */\nexport const InputMessageSchema = z.object({\n content: z.array(UserContentBlockSchema),\n});\n\n/**\n * Zod schema for validating action results from continuation events.\n */\nexport const ActionResultSchema = z.object({\n actionId: z.string(),\n kind: z.string(),\n status: z.enum(['success', 'error']),\n data: z.unknown().optional(),\n error: z.string().optional(),\n});\n\n/**\n * Zod schema for validating agent request payloads.\n * Context object uses passthrough() to allow additional fields.\n */\nexport const AgentRequestSchema = z.object({\n messages: z.array(InputMessageSchema),\n threadId: z.string().optional(),\n context: z\n .object({\n actionResults: z.array(ActionResultSchema).optional(),\n })\n .passthrough()\n .optional(),\n});\n\n/**\n * Zod schema for event lifecycle stages.\n */\nexport const EventStageSchema = z.enum(['start', 'delta', 'stop']);\n\n/**\n * Zod schema for protocol error codes.\n */\nexport const ErrorCodeSchema = z.enum([\n 'auth_failed',\n 'thread_not_found',\n 'thread_access_denied',\n 'invalid_message_format',\n 'message_too_large',\n 'rate_limit_exceeded',\n 'stream_timeout',\n 'stream_stalled',\n 'agent_error',\n 'tool_error',\n 'internal_error',\n 'invalid_action_id',\n]);\n\n/**\n * Zod schema for stream finish reasons.\n */\nexport const FinishReasonSchema = z.enum(['stop', 'length', 'error', 'action_required']);\n\n/**\n * Zod schema for metadata events.\n * First event in every stream, provides identifiers.\n */\nexport const MetadataEventSchema = z.object({\n event: z.literal('metadata'),\n requestId: z.string(),\n threadId: z.string(),\n agentId: z.string(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for text streaming events.\n * Validates the stage lifecycle with appropriate optional fields per stage.\n */\nexport const TextEventSchema = z.object({\n event: z.literal('text'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for thinking/reasoning events.\n * Structure mirrors TextEventSchema.\n */\nexport const ThinkingEventSchema = z.object({\n event: z.literal('thinking'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for tool call events.\n * Args are optional (only present on stop stage).\n */\nexport const ToolCallEventSchema = z.object({\n event: z.literal('tool_call'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n toolCallId: z.string().optional(),\n tool: z.string().optional(),\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n args: z.record(z.string(), z.unknown()).optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for tool result events.\n * Status and summary only present on stop stage.\n */\nexport const ToolResultEventSchema = z.object({\n event: z.literal('tool_result'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n toolCallId: z.string().optional(),\n tool: z.string().optional(),\n status: z.enum(['success', 'error']).optional(),\n summary: z.string().optional(),\n output: z.record(z.string(), z.unknown()).optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for done events.\n * Terminal event with complete content array.\n */\nexport const DoneEventSchema = z.object({\n event: z.literal('done'),\n requestId: z.string(),\n messageId: z.string(),\n threadId: z.string(),\n content: z.array(AssistantContentBlockSchema),\n usage: z\n .object({\n promptTokens: z.number(),\n completionTokens: z.number(),\n })\n .optional(),\n finishReason: FinishReasonSchema,\n traceId: z.string().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for error events.\n * Terminal event with error details and retry guidance.\n */\nexport const ErrorEventSchema = z.object({\n event: z.literal('error'),\n requestId: z.string(),\n message: z.string(),\n code: ErrorCodeSchema.optional(),\n retryable: z.boolean().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for aborted events.\n * Terminal event acknowledging client cancellation.\n */\nexport const AbortedEventSchema = z.object({\n event: z.literal('aborted'),\n requestId: z.string(),\n messageId: z.string().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for continuation events.\n * Signals client action required before stream can continue.\n */\nexport const ContinuationEventSchema = z.object({\n event: z.literal('continuation'),\n requestId: z.string(),\n actionId: z.string(),\n kind: z.string(),\n payload: z.record(z.string(), z.unknown()),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for all protocol events.\n * Discriminated union on the `event` field for efficient parsing.\n */\nexport const AgentEventSchema = z.discriminatedUnion('event', [\n MetadataEventSchema,\n TextEventSchema,\n ThinkingEventSchema,\n ToolCallEventSchema,\n ToolResultEventSchema,\n DoneEventSchema,\n ErrorEventSchema,\n AbortedEventSchema,\n ContinuationEventSchema,\n]);\n\nif (import.meta.vitest) {\n const { describe, it, expect } = import.meta.vitest;\n\n describe('UserContentBlockSchema', () => {\n it('accepts a text block', () => {\n expect(UserContentBlockSchema.safeParse({ type: 'text', text: 'hi' }).success).toBe(true);\n });\n\n it('accepts an attachment of any media type, with or without a name', () => {\n for (const block of [\n { type: 'attachment', attachmentId: 'att-1', mimeType: 'image/png' },\n {\n type: 'attachment',\n attachmentId: 'att-2',\n mimeType: 'application/pdf',\n name: 'spec.pdf',\n },\n { type: 'attachment', attachmentId: 'att-3', mimeType: 'text/csv', name: 'scrap.csv' },\n ]) {\n expect(UserContentBlockSchema.safeParse(block).success).toBe(true);\n }\n });\n\n it('rejects an attachment without an id', () => {\n expect(\n UserContentBlockSchema.safeParse({ type: 'attachment', mimeType: 'image/png' }).success,\n ).toBe(false);\n });\n\n it('rejects a malformed media type', () => {\n expect(\n UserContentBlockSchema.safeParse({\n type: 'attachment',\n attachmentId: 'att-1',\n mimeType: 'png',\n }).success,\n ).toBe(false);\n });\n\n it('follows RFC 6838 restricted names for the media type', () => {\n const ok = (mimeType: string) =>\n UserContentBlockSchema.safeParse({ type: 'attachment', attachmentId: 'a', mimeType })\n .success;\n expect(ok('application/vnd.ms-excel')).toBe(true);\n expect(ok('application/x-foo!#$&^_.+-bar')).toBe(true);\n expect(ok('image/svg+xml')).toBe(true);\n expect(ok('.foo/bar')).toBe(false);\n expect(ok('image/-png')).toBe(false);\n expect(ok('image/png; charset=x')).toBe(false);\n expect(ok(`image/${'a'.repeat(127)}`)).toBe(true);\n expect(ok(`image/${'a'.repeat(128)}`)).toBe(false);\n });\n\n it('rejects an unknown block type', () => {\n expect(\n UserContentBlockSchema.safeParse({\n type: 'image',\n mimeType: 'image/png',\n attachmentId: 'a',\n }).success,\n ).toBe(false);\n });\n });\n\n describe('ErrorEventSchema', () => {\n it('accepts a stream_stalled error', () => {\n expect(\n AgentEventSchema.safeParse({\n event: 'error',\n requestId: 'r',\n message: 'The agent stopped responding',\n code: 'stream_stalled',\n retryable: true,\n timestamp: '2026-11-04T00:00:00.000Z',\n }).success,\n ).toBe(true);\n });\n });\n\n describe('AgentRequestSchema with attachment blocks', () => {\n it('accepts a message mixing text and attachment blocks', () => {\n const result = AgentRequestSchema.safeParse({\n messages: [\n {\n content: [\n { type: 'text', text: 'What is this?' },\n { type: 'attachment', attachmentId: 'a', mimeType: 'image/webp', name: 'photo.webp' },\n ],\n },\n ],\n threadId: 't',\n });\n expect(result.success).toBe(true);\n });\n });\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AgentEventSchema
3
- } from "./chunk-WZD2VBMM.js";
3
+ } from "./chunk-434TVYA5.js";
4
4
 
5
5
  // src/sse/encode.ts
6
6
  function encodeSSE(event, data) {
@@ -217,4 +217,4 @@ export {
217
217
  encodeSSE,
218
218
  parseSSEChunk
219
219
  };
220
- //# sourceMappingURL=chunk-RSG7CUUT.js.map
220
+ //# sourceMappingURL=chunk-QIKNRCHJ.js.map
package/dist/core.cjs CHANGED
@@ -33,22 +33,41 @@ __export(core_exports, {
33
33
  EventStageSchema: () => EventStageSchema,
34
34
  FinishReasonSchema: () => FinishReasonSchema,
35
35
  InputMessageSchema: () => InputMessageSchema,
36
+ MediaTypeSchema: () => MediaTypeSchema,
36
37
  MetadataEventSchema: () => MetadataEventSchema,
37
38
  PROTOCOL_VERSION: () => PROTOCOL_VERSION,
38
39
  TextEventSchema: () => TextEventSchema,
39
40
  ThinkingEventSchema: () => ThinkingEventSchema,
40
41
  ToolCallEventSchema: () => ToolCallEventSchema,
41
42
  ToolResultEventSchema: () => ToolResultEventSchema,
42
- UserContentBlockSchema: () => UserContentBlockSchema
43
+ UserAttachmentBlockSchema: () => UserAttachmentBlockSchema,
44
+ UserContentBlockSchema: () => UserContentBlockSchema,
45
+ UserTextBlockSchema: () => UserTextBlockSchema
43
46
  });
44
47
  module.exports = __toCommonJS(core_exports);
45
48
 
46
49
  // src/core/schemas.ts
47
50
  var import_zod = require("zod");
48
- var UserContentBlockSchema = import_zod.z.object({
51
+ var import_meta = {};
52
+ var UserTextBlockSchema = import_zod.z.object({
49
53
  type: import_zod.z.literal("text"),
50
54
  text: import_zod.z.string()
51
55
  });
56
+ var RESTRICTED_NAME = "[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}";
57
+ var MediaTypeSchema = import_zod.z.string().regex(
58
+ new RegExp(`^${RESTRICTED_NAME}/${RESTRICTED_NAME}$`),
59
+ "expected a media type such as image/png"
60
+ );
61
+ var UserAttachmentBlockSchema = import_zod.z.object({
62
+ type: import_zod.z.literal("attachment"),
63
+ attachmentId: import_zod.z.string().min(1),
64
+ mimeType: MediaTypeSchema,
65
+ name: import_zod.z.string().min(1).optional()
66
+ });
67
+ var UserContentBlockSchema = import_zod.z.discriminatedUnion("type", [
68
+ UserTextBlockSchema,
69
+ UserAttachmentBlockSchema
70
+ ]);
52
71
  var AssistantContentBlockSchema = import_zod.z.discriminatedUnion("type", [
53
72
  import_zod.z.object({ type: import_zod.z.literal("text"), text: import_zod.z.string() }),
54
73
  import_zod.z.object({ type: import_zod.z.literal("thinking"), text: import_zod.z.string() }),
@@ -63,7 +82,8 @@ var AssistantContentBlockSchema = import_zod.z.discriminatedUnion("type", [
63
82
  toolCallId: import_zod.z.string(),
64
83
  tool: import_zod.z.string(),
65
84
  status: import_zod.z.enum(["success", "error"]),
66
- summary: import_zod.z.string().optional()
85
+ summary: import_zod.z.string().optional(),
86
+ output: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
67
87
  })
68
88
  ]);
69
89
  var InputMessageSchema = import_zod.z.object({
@@ -92,6 +112,7 @@ var ErrorCodeSchema = import_zod.z.enum([
92
112
  "message_too_large",
93
113
  "rate_limit_exceeded",
94
114
  "stream_timeout",
115
+ "stream_stalled",
95
116
  "agent_error",
96
117
  "tool_error",
97
118
  "internal_error",
@@ -152,6 +173,7 @@ var ToolResultEventSchema = import_zod.z.object({
152
173
  tool: import_zod.z.string().optional(),
153
174
  status: import_zod.z.enum(["success", "error"]).optional(),
154
175
  summary: import_zod.z.string().optional(),
176
+ output: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
155
177
  timestamp: import_zod.z.string()
156
178
  });
157
179
  var DoneEventSchema = import_zod.z.object({
@@ -201,6 +223,92 @@ var AgentEventSchema = import_zod.z.discriminatedUnion("event", [
201
223
  AbortedEventSchema,
202
224
  ContinuationEventSchema
203
225
  ]);
226
+ if (import_meta.vitest) {
227
+ const { describe, it, expect } = import_meta.vitest;
228
+ describe("UserContentBlockSchema", () => {
229
+ it("accepts a text block", () => {
230
+ expect(UserContentBlockSchema.safeParse({ type: "text", text: "hi" }).success).toBe(true);
231
+ });
232
+ it("accepts an attachment of any media type, with or without a name", () => {
233
+ for (const block of [
234
+ { type: "attachment", attachmentId: "att-1", mimeType: "image/png" },
235
+ {
236
+ type: "attachment",
237
+ attachmentId: "att-2",
238
+ mimeType: "application/pdf",
239
+ name: "spec.pdf"
240
+ },
241
+ { type: "attachment", attachmentId: "att-3", mimeType: "text/csv", name: "scrap.csv" }
242
+ ]) {
243
+ expect(UserContentBlockSchema.safeParse(block).success).toBe(true);
244
+ }
245
+ });
246
+ it("rejects an attachment without an id", () => {
247
+ expect(
248
+ UserContentBlockSchema.safeParse({ type: "attachment", mimeType: "image/png" }).success
249
+ ).toBe(false);
250
+ });
251
+ it("rejects a malformed media type", () => {
252
+ expect(
253
+ UserContentBlockSchema.safeParse({
254
+ type: "attachment",
255
+ attachmentId: "att-1",
256
+ mimeType: "png"
257
+ }).success
258
+ ).toBe(false);
259
+ });
260
+ it("follows RFC 6838 restricted names for the media type", () => {
261
+ const ok = (mimeType) => UserContentBlockSchema.safeParse({ type: "attachment", attachmentId: "a", mimeType }).success;
262
+ expect(ok("application/vnd.ms-excel")).toBe(true);
263
+ expect(ok("application/x-foo!#$&^_.+-bar")).toBe(true);
264
+ expect(ok("image/svg+xml")).toBe(true);
265
+ expect(ok(".foo/bar")).toBe(false);
266
+ expect(ok("image/-png")).toBe(false);
267
+ expect(ok("image/png; charset=x")).toBe(false);
268
+ expect(ok(`image/${"a".repeat(127)}`)).toBe(true);
269
+ expect(ok(`image/${"a".repeat(128)}`)).toBe(false);
270
+ });
271
+ it("rejects an unknown block type", () => {
272
+ expect(
273
+ UserContentBlockSchema.safeParse({
274
+ type: "image",
275
+ mimeType: "image/png",
276
+ attachmentId: "a"
277
+ }).success
278
+ ).toBe(false);
279
+ });
280
+ });
281
+ describe("ErrorEventSchema", () => {
282
+ it("accepts a stream_stalled error", () => {
283
+ expect(
284
+ AgentEventSchema.safeParse({
285
+ event: "error",
286
+ requestId: "r",
287
+ message: "The agent stopped responding",
288
+ code: "stream_stalled",
289
+ retryable: true,
290
+ timestamp: "2026-11-04T00:00:00.000Z"
291
+ }).success
292
+ ).toBe(true);
293
+ });
294
+ });
295
+ describe("AgentRequestSchema with attachment blocks", () => {
296
+ it("accepts a message mixing text and attachment blocks", () => {
297
+ const result = AgentRequestSchema.safeParse({
298
+ messages: [
299
+ {
300
+ content: [
301
+ { type: "text", text: "What is this?" },
302
+ { type: "attachment", attachmentId: "a", mimeType: "image/webp", name: "photo.webp" }
303
+ ]
304
+ }
305
+ ],
306
+ threadId: "t"
307
+ });
308
+ expect(result.success).toBe(true);
309
+ });
310
+ });
311
+ }
204
312
 
205
313
  // src/core/constants.ts
206
314
  var PROTOCOL_VERSION = "1.0.0";
@@ -230,12 +338,15 @@ var EVENT_TYPES = [
230
338
  EventStageSchema,
231
339
  FinishReasonSchema,
232
340
  InputMessageSchema,
341
+ MediaTypeSchema,
233
342
  MetadataEventSchema,
234
343
  PROTOCOL_VERSION,
235
344
  TextEventSchema,
236
345
  ThinkingEventSchema,
237
346
  ToolCallEventSchema,
238
347
  ToolResultEventSchema,
239
- UserContentBlockSchema
348
+ UserAttachmentBlockSchema,
349
+ UserContentBlockSchema,
350
+ UserTextBlockSchema
240
351
  });
241
352
  //# sourceMappingURL=core.cjs.map
package/dist/core.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/index.ts","../src/core/schemas.ts","../src/core/constants.ts"],"sourcesContent":["export * from './types.js';\nexport * from './schemas.js';\nexport * from './constants.js';\n","import { z } from 'zod';\n\n/**\n * Zod schema for validating user content blocks.\n * Currently only supports text; extensible for multimodal.\n */\nexport const UserContentBlockSchema = z.object({\n type: z.literal('text'),\n text: z.string(),\n});\n\n/**\n * Zod schema for validating assistant content blocks.\n * Discriminated union supporting text, thinking, tool_use, and tool_result.\n */\nexport const AssistantContentBlockSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('text'), text: z.string() }),\n z.object({ type: z.literal('thinking'), text: z.string() }),\n z.object({\n type: z.literal('tool_use'),\n toolCallId: z.string(),\n tool: z.string(),\n args: z.record(z.string(), z.unknown()),\n }),\n z.object({\n type: z.literal('tool_result'),\n toolCallId: z.string(),\n tool: z.string(),\n status: z.enum(['success', 'error']),\n summary: z.string().optional(),\n }),\n]);\n\n/**\n * Zod schema for validating input messages.\n */\nexport const InputMessageSchema = z.object({\n content: z.array(UserContentBlockSchema),\n});\n\n/**\n * Zod schema for validating action results from continuation events.\n */\nexport const ActionResultSchema = z.object({\n actionId: z.string(),\n kind: z.string(),\n status: z.enum(['success', 'error']),\n data: z.unknown().optional(),\n error: z.string().optional(),\n});\n\n/**\n * Zod schema for validating agent request payloads.\n * Context object uses passthrough() to allow additional fields.\n */\nexport const AgentRequestSchema = z.object({\n messages: z.array(InputMessageSchema),\n threadId: z.string().optional(),\n context: z\n .object({\n actionResults: z.array(ActionResultSchema).optional(),\n })\n .passthrough()\n .optional(),\n});\n\n/**\n * Zod schema for event lifecycle stages.\n */\nexport const EventStageSchema = z.enum(['start', 'delta', 'stop']);\n\n/**\n * Zod schema for protocol error codes.\n */\nexport const ErrorCodeSchema = z.enum([\n 'auth_failed',\n 'thread_not_found',\n 'thread_access_denied',\n 'invalid_message_format',\n 'message_too_large',\n 'rate_limit_exceeded',\n 'stream_timeout',\n 'agent_error',\n 'tool_error',\n 'internal_error',\n 'invalid_action_id',\n]);\n\n/**\n * Zod schema for stream finish reasons.\n */\nexport const FinishReasonSchema = z.enum(['stop', 'length', 'error', 'action_required']);\n\n/**\n * Zod schema for metadata events.\n * First event in every stream, provides identifiers.\n */\nexport const MetadataEventSchema = z.object({\n event: z.literal('metadata'),\n requestId: z.string(),\n threadId: z.string(),\n agentId: z.string(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for text streaming events.\n * Validates the stage lifecycle with appropriate optional fields per stage.\n */\nexport const TextEventSchema = z.object({\n event: z.literal('text'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for thinking/reasoning events.\n * Structure mirrors TextEventSchema.\n */\nexport const ThinkingEventSchema = z.object({\n event: z.literal('thinking'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for tool call events.\n * Args are optional (only present on stop stage).\n */\nexport const ToolCallEventSchema = z.object({\n event: z.literal('tool_call'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n toolCallId: z.string().optional(),\n tool: z.string().optional(),\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n args: z.record(z.string(), z.unknown()).optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for tool result events.\n * Status and summary only present on stop stage.\n */\nexport const ToolResultEventSchema = z.object({\n event: z.literal('tool_result'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n toolCallId: z.string().optional(),\n tool: z.string().optional(),\n status: z.enum(['success', 'error']).optional(),\n summary: z.string().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for done events.\n * Terminal event with complete content array.\n */\nexport const DoneEventSchema = z.object({\n event: z.literal('done'),\n requestId: z.string(),\n messageId: z.string(),\n threadId: z.string(),\n content: z.array(AssistantContentBlockSchema),\n usage: z\n .object({\n promptTokens: z.number(),\n completionTokens: z.number(),\n })\n .optional(),\n finishReason: FinishReasonSchema,\n traceId: z.string().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for error events.\n * Terminal event with error details and retry guidance.\n */\nexport const ErrorEventSchema = z.object({\n event: z.literal('error'),\n requestId: z.string(),\n message: z.string(),\n code: ErrorCodeSchema.optional(),\n retryable: z.boolean().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for aborted events.\n * Terminal event acknowledging client cancellation.\n */\nexport const AbortedEventSchema = z.object({\n event: z.literal('aborted'),\n requestId: z.string(),\n messageId: z.string().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for continuation events.\n * Signals client action required before stream can continue.\n */\nexport const ContinuationEventSchema = z.object({\n event: z.literal('continuation'),\n requestId: z.string(),\n actionId: z.string(),\n kind: z.string(),\n payload: z.record(z.string(), z.unknown()),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for all protocol events.\n * Discriminated union on the `event` field for efficient parsing.\n */\nexport const AgentEventSchema = z.discriminatedUnion('event', [\n MetadataEventSchema,\n TextEventSchema,\n ThinkingEventSchema,\n ToolCallEventSchema,\n ToolResultEventSchema,\n DoneEventSchema,\n ErrorEventSchema,\n AbortedEventSchema,\n ContinuationEventSchema,\n]);\n","/**\n * Current protocol version.\n * Additive changes (new events, optional fields) don't require version bump.\n * Breaking changes require new endpoint version (v2, v3, etc).\n */\nexport const PROTOCOL_VERSION = '1.0.0';\n\n/**\n * All valid event type identifiers in the protocol.\n * Used for discriminated union parsing and validation.\n */\nexport const EVENT_TYPES = [\n 'metadata',\n 'text',\n 'thinking',\n 'tool_call',\n 'tool_result',\n 'done',\n 'error',\n 'aborted',\n 'continuation',\n] as const;\n\n/**\n * Event type identifier.\n * Union of all valid event type strings.\n */\nexport type EventType = (typeof EVENT_TYPES)[number];\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/core/index.ts","../src/core/schemas.ts","../src/core/constants.ts"],"sourcesContent":["export * from './types.js';\nexport * from './schemas.js';\nexport * from './constants.js';\n","import { z } from 'zod';\n\n/**\n * Zod schema for a user text block.\n */\nexport const UserTextBlockSchema = z.object({\n type: z.literal('text'),\n text: z.string(),\n});\n\n/**\n * Zod schema for a media type (`type/subtype`, e.g. `image/png`,\n * `application/pdf`): RFC 6838 restricted names, each starting with a letter\n * or digit and at most 127 characters. Which media types a server accepts is the server's\n * decision, not the protocol's.\n */\nconst RESTRICTED_NAME = '[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}';\n\nexport const MediaTypeSchema = z\n .string()\n .regex(\n new RegExp(`^${RESTRICTED_NAME}/${RESTRICTED_NAME}$`),\n 'expected a media type such as image/png',\n );\n\n/**\n * Zod schema for a user attachment block: a file the user uploaded ahead of\n * the message and now refers to by id. How the file reaches the model (an\n * image, a document, extracted text, a tool) is the server's decision.\n */\nexport const UserAttachmentBlockSchema = z.object({\n type: z.literal('attachment'),\n attachmentId: z.string().min(1),\n mimeType: MediaTypeSchema,\n name: z.string().min(1).optional(),\n});\n\n/**\n * Zod schema for validating user content blocks: text or an attachment.\n */\nexport const UserContentBlockSchema = z.discriminatedUnion('type', [\n UserTextBlockSchema,\n UserAttachmentBlockSchema,\n]);\n\n/**\n * Zod schema for validating assistant content blocks.\n * Discriminated union supporting text, thinking, tool_use, and tool_result.\n */\nexport const AssistantContentBlockSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('text'), text: z.string() }),\n z.object({ type: z.literal('thinking'), text: z.string() }),\n z.object({\n type: z.literal('tool_use'),\n toolCallId: z.string(),\n tool: z.string(),\n args: z.record(z.string(), z.unknown()),\n }),\n z.object({\n type: z.literal('tool_result'),\n toolCallId: z.string(),\n tool: z.string(),\n status: z.enum(['success', 'error']),\n summary: z.string().optional(),\n output: z.record(z.string(), z.unknown()).optional(),\n }),\n]);\n\n/**\n * Zod schema for validating input messages.\n */\nexport const InputMessageSchema = z.object({\n content: z.array(UserContentBlockSchema),\n});\n\n/**\n * Zod schema for validating action results from continuation events.\n */\nexport const ActionResultSchema = z.object({\n actionId: z.string(),\n kind: z.string(),\n status: z.enum(['success', 'error']),\n data: z.unknown().optional(),\n error: z.string().optional(),\n});\n\n/**\n * Zod schema for validating agent request payloads.\n * Context object uses passthrough() to allow additional fields.\n */\nexport const AgentRequestSchema = z.object({\n messages: z.array(InputMessageSchema),\n threadId: z.string().optional(),\n context: z\n .object({\n actionResults: z.array(ActionResultSchema).optional(),\n })\n .passthrough()\n .optional(),\n});\n\n/**\n * Zod schema for event lifecycle stages.\n */\nexport const EventStageSchema = z.enum(['start', 'delta', 'stop']);\n\n/**\n * Zod schema for protocol error codes.\n */\nexport const ErrorCodeSchema = z.enum([\n 'auth_failed',\n 'thread_not_found',\n 'thread_access_denied',\n 'invalid_message_format',\n 'message_too_large',\n 'rate_limit_exceeded',\n 'stream_timeout',\n 'stream_stalled',\n 'agent_error',\n 'tool_error',\n 'internal_error',\n 'invalid_action_id',\n]);\n\n/**\n * Zod schema for stream finish reasons.\n */\nexport const FinishReasonSchema = z.enum(['stop', 'length', 'error', 'action_required']);\n\n/**\n * Zod schema for metadata events.\n * First event in every stream, provides identifiers.\n */\nexport const MetadataEventSchema = z.object({\n event: z.literal('metadata'),\n requestId: z.string(),\n threadId: z.string(),\n agentId: z.string(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for text streaming events.\n * Validates the stage lifecycle with appropriate optional fields per stage.\n */\nexport const TextEventSchema = z.object({\n event: z.literal('text'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for thinking/reasoning events.\n * Structure mirrors TextEventSchema.\n */\nexport const ThinkingEventSchema = z.object({\n event: z.literal('thinking'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for tool call events.\n * Args are optional (only present on stop stage).\n */\nexport const ToolCallEventSchema = z.object({\n event: z.literal('tool_call'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n toolCallId: z.string().optional(),\n tool: z.string().optional(),\n delta: z.string().optional(),\n deltaIndex: z.number().optional(),\n args: z.record(z.string(), z.unknown()).optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for tool result events.\n * Status and summary only present on stop stage.\n */\nexport const ToolResultEventSchema = z.object({\n event: z.literal('tool_result'),\n requestId: z.string(),\n messageId: z.string(),\n blockId: z.string(),\n blockIndex: z.number().optional(),\n stage: EventStageSchema,\n toolCallId: z.string().optional(),\n tool: z.string().optional(),\n status: z.enum(['success', 'error']).optional(),\n summary: z.string().optional(),\n output: z.record(z.string(), z.unknown()).optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for done events.\n * Terminal event with complete content array.\n */\nexport const DoneEventSchema = z.object({\n event: z.literal('done'),\n requestId: z.string(),\n messageId: z.string(),\n threadId: z.string(),\n content: z.array(AssistantContentBlockSchema),\n usage: z\n .object({\n promptTokens: z.number(),\n completionTokens: z.number(),\n })\n .optional(),\n finishReason: FinishReasonSchema,\n traceId: z.string().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for error events.\n * Terminal event with error details and retry guidance.\n */\nexport const ErrorEventSchema = z.object({\n event: z.literal('error'),\n requestId: z.string(),\n message: z.string(),\n code: ErrorCodeSchema.optional(),\n retryable: z.boolean().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for aborted events.\n * Terminal event acknowledging client cancellation.\n */\nexport const AbortedEventSchema = z.object({\n event: z.literal('aborted'),\n requestId: z.string(),\n messageId: z.string().optional(),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for continuation events.\n * Signals client action required before stream can continue.\n */\nexport const ContinuationEventSchema = z.object({\n event: z.literal('continuation'),\n requestId: z.string(),\n actionId: z.string(),\n kind: z.string(),\n payload: z.record(z.string(), z.unknown()),\n timestamp: z.string(),\n});\n\n/**\n * Zod schema for all protocol events.\n * Discriminated union on the `event` field for efficient parsing.\n */\nexport const AgentEventSchema = z.discriminatedUnion('event', [\n MetadataEventSchema,\n TextEventSchema,\n ThinkingEventSchema,\n ToolCallEventSchema,\n ToolResultEventSchema,\n DoneEventSchema,\n ErrorEventSchema,\n AbortedEventSchema,\n ContinuationEventSchema,\n]);\n\nif (import.meta.vitest) {\n const { describe, it, expect } = import.meta.vitest;\n\n describe('UserContentBlockSchema', () => {\n it('accepts a text block', () => {\n expect(UserContentBlockSchema.safeParse({ type: 'text', text: 'hi' }).success).toBe(true);\n });\n\n it('accepts an attachment of any media type, with or without a name', () => {\n for (const block of [\n { type: 'attachment', attachmentId: 'att-1', mimeType: 'image/png' },\n {\n type: 'attachment',\n attachmentId: 'att-2',\n mimeType: 'application/pdf',\n name: 'spec.pdf',\n },\n { type: 'attachment', attachmentId: 'att-3', mimeType: 'text/csv', name: 'scrap.csv' },\n ]) {\n expect(UserContentBlockSchema.safeParse(block).success).toBe(true);\n }\n });\n\n it('rejects an attachment without an id', () => {\n expect(\n UserContentBlockSchema.safeParse({ type: 'attachment', mimeType: 'image/png' }).success,\n ).toBe(false);\n });\n\n it('rejects a malformed media type', () => {\n expect(\n UserContentBlockSchema.safeParse({\n type: 'attachment',\n attachmentId: 'att-1',\n mimeType: 'png',\n }).success,\n ).toBe(false);\n });\n\n it('follows RFC 6838 restricted names for the media type', () => {\n const ok = (mimeType: string) =>\n UserContentBlockSchema.safeParse({ type: 'attachment', attachmentId: 'a', mimeType })\n .success;\n expect(ok('application/vnd.ms-excel')).toBe(true);\n expect(ok('application/x-foo!#$&^_.+-bar')).toBe(true);\n expect(ok('image/svg+xml')).toBe(true);\n expect(ok('.foo/bar')).toBe(false);\n expect(ok('image/-png')).toBe(false);\n expect(ok('image/png; charset=x')).toBe(false);\n expect(ok(`image/${'a'.repeat(127)}`)).toBe(true);\n expect(ok(`image/${'a'.repeat(128)}`)).toBe(false);\n });\n\n it('rejects an unknown block type', () => {\n expect(\n UserContentBlockSchema.safeParse({\n type: 'image',\n mimeType: 'image/png',\n attachmentId: 'a',\n }).success,\n ).toBe(false);\n });\n });\n\n describe('ErrorEventSchema', () => {\n it('accepts a stream_stalled error', () => {\n expect(\n AgentEventSchema.safeParse({\n event: 'error',\n requestId: 'r',\n message: 'The agent stopped responding',\n code: 'stream_stalled',\n retryable: true,\n timestamp: '2026-11-04T00:00:00.000Z',\n }).success,\n ).toBe(true);\n });\n });\n\n describe('AgentRequestSchema with attachment blocks', () => {\n it('accepts a message mixing text and attachment blocks', () => {\n const result = AgentRequestSchema.safeParse({\n messages: [\n {\n content: [\n { type: 'text', text: 'What is this?' },\n { type: 'attachment', attachmentId: 'a', mimeType: 'image/webp', name: 'photo.webp' },\n ],\n },\n ],\n threadId: 't',\n });\n expect(result.success).toBe(true);\n });\n });\n}\n","/**\n * Current protocol version.\n * Additive changes (new events, optional fields) don't require version bump.\n * Breaking changes require new endpoint version (v2, v3, etc).\n */\nexport const PROTOCOL_VERSION = '1.0.0';\n\n/**\n * All valid event type identifiers in the protocol.\n * Used for discriminated union parsing and validation.\n */\nexport const EVENT_TYPES = [\n 'metadata',\n 'text',\n 'thinking',\n 'tool_call',\n 'tool_result',\n 'done',\n 'error',\n 'aborted',\n 'continuation',\n] as const;\n\n/**\n * Event type identifier.\n * Union of all valid event type strings.\n */\nexport type EventType = (typeof EVENT_TYPES)[number];\n"],"mappings":"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","names":[]}