vessels-sdk 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,5 +1,195 @@
1
1
  'use strict';
2
2
 
3
+ var zod = require('zod');
4
+
5
+ // ../types/src/index.ts
6
+ var ApprovalInteractionSchema = zod.z.object({
7
+ type: zod.z.literal("approval"),
8
+ prompt: zod.z.string().min(1),
9
+ approveLabel: zod.z.string().optional(),
10
+ rejectLabel: zod.z.string().optional(),
11
+ reasonRequired: zod.z.boolean().optional(),
12
+ metadata: zod.z.record(zod.z.unknown()).optional()
13
+ });
14
+ var ChoiceOptionSchema = zod.z.object({
15
+ id: zod.z.string().min(1),
16
+ label: zod.z.string().min(1)
17
+ });
18
+ var ChoiceInteractionSchema = zod.z.object({
19
+ type: zod.z.literal("choice"),
20
+ prompt: zod.z.string().min(1),
21
+ options: zod.z.array(ChoiceOptionSchema).min(1),
22
+ allowCustom: zod.z.boolean().optional(),
23
+ customPlaceholder: zod.z.string().optional(),
24
+ metadata: zod.z.record(zod.z.unknown()).optional()
25
+ });
26
+ var ChecklistOptionSchema = zod.z.object({
27
+ id: zod.z.string().min(1),
28
+ label: zod.z.string().min(1),
29
+ checked: zod.z.boolean().optional()
30
+ });
31
+ var ChecklistInteractionSchema = zod.z.object({
32
+ type: zod.z.literal("checklist"),
33
+ prompt: zod.z.string().min(1),
34
+ options: zod.z.array(ChecklistOptionSchema).min(1),
35
+ minSelections: zod.z.number().int().min(0).optional(),
36
+ submitLabel: zod.z.string().optional(),
37
+ metadata: zod.z.record(zod.z.unknown()).optional()
38
+ });
39
+ var TextInputInteractionSchema = zod.z.object({
40
+ type: zod.z.literal("text_input"),
41
+ prompt: zod.z.string().min(1),
42
+ placeholder: zod.z.string().optional(),
43
+ multiline: zod.z.boolean().optional(),
44
+ submitLabel: zod.z.string().optional(),
45
+ metadata: zod.z.record(zod.z.unknown()).optional()
46
+ });
47
+ var ConfirmPreviewInteractionSchema = zod.z.object({
48
+ type: zod.z.literal("confirm_preview"),
49
+ prompt: zod.z.string().min(1),
50
+ previewUrl: zod.z.string().url(),
51
+ previewLabel: zod.z.string().optional(),
52
+ approveLabel: zod.z.string().optional(),
53
+ rejectLabel: zod.z.string().optional(),
54
+ reasonRequiredOnReject: zod.z.boolean().optional(),
55
+ metadata: zod.z.record(zod.z.unknown()).optional()
56
+ });
57
+ var InteractionSchema = zod.z.discriminatedUnion("type", [
58
+ ApprovalInteractionSchema,
59
+ ChoiceInteractionSchema,
60
+ ChecklistInteractionSchema,
61
+ TextInputInteractionSchema,
62
+ ConfirmPreviewInteractionSchema
63
+ ]);
64
+ var AgentActivityTypeSchema = zod.z.enum(["thinking", "searching", "tool_use", "browsing", "processing"]);
65
+ var AgentActivitySchema = zod.z.object({
66
+ type: AgentActivityTypeSchema,
67
+ label: zod.z.string().max(200).optional()
68
+ });
69
+ var CardFieldSchema = zod.z.object({
70
+ label: zod.z.string().min(1),
71
+ value: zod.z.string()
72
+ });
73
+ var CardSchema = zod.z.object({
74
+ title: zod.z.string().min(1),
75
+ fields: zod.z.array(CardFieldSchema)
76
+ });
77
+ var AttachmentSchema = zod.z.discriminatedUnion("type", [
78
+ zod.z.object({ type: zod.z.literal("image"), url: zod.z.string().url() }),
79
+ zod.z.object({ type: zod.z.literal("file"), url: zod.z.string().url(), filename: zod.z.string().optional() })
80
+ ]);
81
+ var VesselStatusSchema = zod.z.enum(["active", "waiting", "resolved"]);
82
+ zod.z.object({
83
+ message: zod.z.string().min(1).max(1e4).optional(),
84
+ vessel: zod.z.string().optional(),
85
+ vesselTitle: zod.z.string().optional(),
86
+ card: CardSchema.optional(),
87
+ interaction: InteractionSchema.optional(),
88
+ previewUrl: zod.z.string().url().optional(),
89
+ metadata: zod.z.record(zod.z.unknown()).refine(
90
+ (v) => JSON.stringify(v).length < 16e3,
91
+ "metadata exceeds 16KB limit"
92
+ ).optional(),
93
+ pinCard: CardSchema.nullable().optional(),
94
+ vesselStatus: VesselStatusSchema.optional(),
95
+ labels: zod.z.array(zod.z.string().min(1).max(50)).max(10).optional(),
96
+ attachments: zod.z.array(AttachmentSchema).max(10).optional(),
97
+ suggestions: zod.z.array(zod.z.string().min(1).max(500)).max(5).optional(),
98
+ agentActivity: AgentActivitySchema.optional()
99
+ }).refine((d) => d.message || d.agentActivity, {
100
+ message: "Either message or agentActivity is required"
101
+ });
102
+ zod.z.object({
103
+ vessels: zod.z.array(zod.z.string().min(1)).min(1).max(100),
104
+ message: zod.z.string().min(1).max(1e4),
105
+ vesselTitle: zod.z.string().optional(),
106
+ card: CardSchema.optional(),
107
+ interaction: InteractionSchema.optional(),
108
+ pinCard: CardSchema.nullable().optional(),
109
+ vesselStatus: VesselStatusSchema.optional(),
110
+ attachments: zod.z.array(AttachmentSchema).max(10).optional(),
111
+ suggestions: zod.z.array(zod.z.string().min(1).max(500)).max(5).optional(),
112
+ metadata: zod.z.record(zod.z.unknown()).refine(
113
+ (v) => JSON.stringify(v).length < 16e3,
114
+ "metadata exceeds 16KB limit"
115
+ ).optional()
116
+ });
117
+ zod.z.object({
118
+ content: zod.z.string().min(1).max(1e4).optional(),
119
+ card: CardSchema.nullable().optional(),
120
+ attachments: zod.z.array(AttachmentSchema).max(10).nullable().optional(),
121
+ suggestions: zod.z.array(zod.z.string().min(1).max(500)).max(5).nullable().optional(),
122
+ agentActivity: AgentActivitySchema.nullable().optional()
123
+ }).refine((d) => Object.values(d).some((v) => v !== void 0), {
124
+ message: "At least one field required"
125
+ });
126
+ var ApprovalResponseSchema = zod.z.object({
127
+ action: zod.z.enum(["approved", "rejected"]),
128
+ reason: zod.z.string().optional()
129
+ });
130
+ var ChoiceResponseSchema = zod.z.object({
131
+ selected: zod.z.string(),
132
+ customValue: zod.z.string().nullable().optional()
133
+ });
134
+ var ChecklistResponseSchema = zod.z.object({
135
+ selected: zod.z.array(zod.z.string())
136
+ });
137
+ var TextInputResponseSchema = zod.z.object({
138
+ text: zod.z.string()
139
+ });
140
+ var ConfirmPreviewResponseSchema = zod.z.object({
141
+ action: zod.z.enum(["approved", "rejected"]),
142
+ reason: zod.z.string().optional()
143
+ });
144
+ zod.z.discriminatedUnion("interactionType", [
145
+ zod.z.object({ interactionType: zod.z.literal("approval"), response: ApprovalResponseSchema }),
146
+ zod.z.object({ interactionType: zod.z.literal("choice"), response: ChoiceResponseSchema }),
147
+ zod.z.object({ interactionType: zod.z.literal("checklist"), response: ChecklistResponseSchema }),
148
+ zod.z.object({ interactionType: zod.z.literal("text_input"), response: TextInputResponseSchema }),
149
+ zod.z.object({ interactionType: zod.z.literal("confirm_preview"), response: ConfirmPreviewResponseSchema })
150
+ ]);
151
+ var WebhookVesselSchema = zod.z.object({
152
+ id: zod.z.string(),
153
+ external_id: zod.z.string().nullable(),
154
+ title: zod.z.string().nullable(),
155
+ metadata: zod.z.record(zod.z.unknown())
156
+ });
157
+ var WebhookContextMessageSchema = zod.z.object({
158
+ source: zod.z.string(),
159
+ content: zod.z.string().nullable(),
160
+ created_at: zod.z.string()
161
+ });
162
+ var WebhookInteractionResponsePayloadSchema = zod.z.object({
163
+ event: zod.z.literal("interaction.response"),
164
+ vessel_id: zod.z.string(),
165
+ workspace_id: zod.z.string(),
166
+ timestamp: zod.z.string(),
167
+ data: zod.z.object({
168
+ message_id: zod.z.string(),
169
+ interaction_type: zod.z.string(),
170
+ response: zod.z.record(zod.z.unknown()),
171
+ response_id: zod.z.string(),
172
+ metadata: zod.z.record(zod.z.unknown()).optional(),
173
+ vessel: WebhookVesselSchema
174
+ })
175
+ });
176
+ var WebhookUserMessagePayloadSchema = zod.z.object({
177
+ event: zod.z.literal("message.user"),
178
+ vessel_id: zod.z.string(),
179
+ workspace_id: zod.z.string(),
180
+ timestamp: zod.z.string(),
181
+ data: zod.z.object({
182
+ message_id: zod.z.string(),
183
+ content: zod.z.string(),
184
+ vessel: WebhookVesselSchema,
185
+ context: zod.z.array(WebhookContextMessageSchema)
186
+ })
187
+ });
188
+ var WebhookPayloadSchema = zod.z.discriminatedUnion("event", [
189
+ WebhookInteractionResponsePayloadSchema,
190
+ WebhookUserMessagePayloadSchema
191
+ ]);
192
+
3
193
  // src/index.ts
4
194
  var AgentActivityTypes = {
5
195
  thinking: "thinking",
@@ -178,7 +368,8 @@ var Vessels = class {
178
368
  type: "message.user",
179
369
  timestamp: e.timestamp,
180
370
  vessel,
181
- message: { id: e.message?.id, content: e.message?.content ?? null }
371
+ message: { id: e.message?.id, content: e.message?.content ?? null },
372
+ context: []
182
373
  };
183
374
  });
184
375
  return { ok: true, events, hasMore: data.has_more ?? false };
@@ -209,6 +400,55 @@ var Vessels = class {
209
400
  return false;
210
401
  }
211
402
  }
403
+ // Verify + parse in one call. Returns a typed event or null (invalid signature or unknown type).
404
+ // body: raw request body string (before JSON.parse)
405
+ // signature: X-Vessels-Signature header value
406
+ // webhookSecret: the secret shown when you created the webhook endpoint in Settings
407
+ async parseWebhookEvent(body, signature, webhookSecret) {
408
+ const valid = await this.verifyWebhook(body, signature, webhookSecret);
409
+ if (!valid) return null;
410
+ try {
411
+ const raw = JSON.parse(body);
412
+ const v = raw.data?.vessel ?? {};
413
+ const vessel = {
414
+ id: v.id,
415
+ externalId: v.external_id ?? null,
416
+ title: v.title ?? null,
417
+ metadata: v.metadata ?? {},
418
+ labels: v.labels ?? []
419
+ };
420
+ if (raw.event === "interaction.response") {
421
+ return {
422
+ id: raw.data.response_id,
423
+ type: "interaction.response",
424
+ timestamp: raw.timestamp,
425
+ vessel,
426
+ messageId: raw.data.message_id,
427
+ interactionType: raw.data.interaction_type,
428
+ response: raw.data.response,
429
+ interactionMetadata: raw.data.metadata ?? null,
430
+ user: raw.data.user ?? null
431
+ };
432
+ }
433
+ if (raw.event === "message.user") {
434
+ return {
435
+ id: raw.data.message_id,
436
+ type: "message.user",
437
+ timestamp: raw.timestamp,
438
+ vessel,
439
+ message: { id: raw.data.message_id, content: raw.data.content ?? null },
440
+ context: (raw.data.context ?? []).map((m) => ({
441
+ source: m.source,
442
+ content: m.content ?? null,
443
+ createdAt: m.created_at
444
+ }))
445
+ };
446
+ }
447
+ return null;
448
+ } catch {
449
+ return null;
450
+ }
451
+ }
212
452
  };
213
453
 
214
454
  exports.AgentActivityTypes = AgentActivityTypes;
@@ -216,3 +456,6 @@ exports.Vessels = Vessels;
216
456
  exports.VesselsAuthError = VesselsAuthError;
217
457
  exports.VesselsRateLimitError = VesselsRateLimitError;
218
458
  exports.VesselsValidationError = VesselsValidationError;
459
+ exports.WebhookInteractionResponsePayloadSchema = WebhookInteractionResponsePayloadSchema;
460
+ exports.WebhookPayloadSchema = WebhookPayloadSchema;
461
+ exports.WebhookUserMessagePayloadSchema = WebhookUserMessagePayloadSchema;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _vessels_types from '@vessels/types';
2
- export { AgentActivity, AgentActivityType, ApprovalInteraction, Attachment, Card, ChecklistInteraction, ChoiceInteraction, ConfirmPreviewInteraction, Interaction, MessagePatch, PushManyPayload, PushPayload, TextInputInteraction } from '@vessels/types';
2
+ export { AgentActivity, AgentActivityType, ApprovalInteraction, Attachment, Card, ChecklistInteraction, ChoiceInteraction, ConfirmPreviewInteraction, Interaction, MessagePatch, PushManyPayload, PushPayload, TextInputInteraction, WebhookInteractionResponsePayload, WebhookInteractionResponsePayloadSchema, WebhookPayload, WebhookPayloadSchema, WebhookUserMessagePayload, WebhookUserMessagePayloadSchema } from '@vessels/types';
3
3
 
4
4
  declare const AgentActivityTypes: {
5
5
  readonly thinking: "thinking";
@@ -74,6 +74,11 @@ interface UserMessageEvent {
74
74
  id: string;
75
75
  content: string | null;
76
76
  };
77
+ context: Array<{
78
+ source: string;
79
+ content: string | null;
80
+ createdAt: string;
81
+ }>;
77
82
  }
78
83
  type PollEvent = InteractionResponseEvent | UserMessageEvent;
79
84
  interface PollResponse {
@@ -138,6 +143,7 @@ declare class Vessels {
138
143
  }): _vessels_types.ConfirmPreviewInteraction;
139
144
  poll(options?: PollOptions): Promise<PollResponse>;
140
145
  verifyWebhook(body: string, signature: string, webhookSecret: string): Promise<boolean>;
146
+ parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | null>;
141
147
  }
142
148
 
143
149
  export { AgentActivityTypes, type InteractionResponseEvent, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type UserMessageEvent, type VesselContext, Vessels, VesselsAuthError, type VesselsConfig, VesselsRateLimitError, VesselsValidationError };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _vessels_types from '@vessels/types';
2
- export { AgentActivity, AgentActivityType, ApprovalInteraction, Attachment, Card, ChecklistInteraction, ChoiceInteraction, ConfirmPreviewInteraction, Interaction, MessagePatch, PushManyPayload, PushPayload, TextInputInteraction } from '@vessels/types';
2
+ export { AgentActivity, AgentActivityType, ApprovalInteraction, Attachment, Card, ChecklistInteraction, ChoiceInteraction, ConfirmPreviewInteraction, Interaction, MessagePatch, PushManyPayload, PushPayload, TextInputInteraction, WebhookInteractionResponsePayload, WebhookInteractionResponsePayloadSchema, WebhookPayload, WebhookPayloadSchema, WebhookUserMessagePayload, WebhookUserMessagePayloadSchema } from '@vessels/types';
3
3
 
4
4
  declare const AgentActivityTypes: {
5
5
  readonly thinking: "thinking";
@@ -74,6 +74,11 @@ interface UserMessageEvent {
74
74
  id: string;
75
75
  content: string | null;
76
76
  };
77
+ context: Array<{
78
+ source: string;
79
+ content: string | null;
80
+ createdAt: string;
81
+ }>;
77
82
  }
78
83
  type PollEvent = InteractionResponseEvent | UserMessageEvent;
79
84
  interface PollResponse {
@@ -138,6 +143,7 @@ declare class Vessels {
138
143
  }): _vessels_types.ConfirmPreviewInteraction;
139
144
  poll(options?: PollOptions): Promise<PollResponse>;
140
145
  verifyWebhook(body: string, signature: string, webhookSecret: string): Promise<boolean>;
146
+ parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | null>;
141
147
  }
142
148
 
143
149
  export { AgentActivityTypes, type InteractionResponseEvent, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type UserMessageEvent, type VesselContext, Vessels, VesselsAuthError, type VesselsConfig, VesselsRateLimitError, VesselsValidationError };
package/dist/index.js CHANGED
@@ -1,3 +1,193 @@
1
+ import { z } from 'zod';
2
+
3
+ // ../types/src/index.ts
4
+ var ApprovalInteractionSchema = z.object({
5
+ type: z.literal("approval"),
6
+ prompt: z.string().min(1),
7
+ approveLabel: z.string().optional(),
8
+ rejectLabel: z.string().optional(),
9
+ reasonRequired: z.boolean().optional(),
10
+ metadata: z.record(z.unknown()).optional()
11
+ });
12
+ var ChoiceOptionSchema = z.object({
13
+ id: z.string().min(1),
14
+ label: z.string().min(1)
15
+ });
16
+ var ChoiceInteractionSchema = z.object({
17
+ type: z.literal("choice"),
18
+ prompt: z.string().min(1),
19
+ options: z.array(ChoiceOptionSchema).min(1),
20
+ allowCustom: z.boolean().optional(),
21
+ customPlaceholder: z.string().optional(),
22
+ metadata: z.record(z.unknown()).optional()
23
+ });
24
+ var ChecklistOptionSchema = z.object({
25
+ id: z.string().min(1),
26
+ label: z.string().min(1),
27
+ checked: z.boolean().optional()
28
+ });
29
+ var ChecklistInteractionSchema = z.object({
30
+ type: z.literal("checklist"),
31
+ prompt: z.string().min(1),
32
+ options: z.array(ChecklistOptionSchema).min(1),
33
+ minSelections: z.number().int().min(0).optional(),
34
+ submitLabel: z.string().optional(),
35
+ metadata: z.record(z.unknown()).optional()
36
+ });
37
+ var TextInputInteractionSchema = z.object({
38
+ type: z.literal("text_input"),
39
+ prompt: z.string().min(1),
40
+ placeholder: z.string().optional(),
41
+ multiline: z.boolean().optional(),
42
+ submitLabel: z.string().optional(),
43
+ metadata: z.record(z.unknown()).optional()
44
+ });
45
+ var ConfirmPreviewInteractionSchema = z.object({
46
+ type: z.literal("confirm_preview"),
47
+ prompt: z.string().min(1),
48
+ previewUrl: z.string().url(),
49
+ previewLabel: z.string().optional(),
50
+ approveLabel: z.string().optional(),
51
+ rejectLabel: z.string().optional(),
52
+ reasonRequiredOnReject: z.boolean().optional(),
53
+ metadata: z.record(z.unknown()).optional()
54
+ });
55
+ var InteractionSchema = z.discriminatedUnion("type", [
56
+ ApprovalInteractionSchema,
57
+ ChoiceInteractionSchema,
58
+ ChecklistInteractionSchema,
59
+ TextInputInteractionSchema,
60
+ ConfirmPreviewInteractionSchema
61
+ ]);
62
+ var AgentActivityTypeSchema = z.enum(["thinking", "searching", "tool_use", "browsing", "processing"]);
63
+ var AgentActivitySchema = z.object({
64
+ type: AgentActivityTypeSchema,
65
+ label: z.string().max(200).optional()
66
+ });
67
+ var CardFieldSchema = z.object({
68
+ label: z.string().min(1),
69
+ value: z.string()
70
+ });
71
+ var CardSchema = z.object({
72
+ title: z.string().min(1),
73
+ fields: z.array(CardFieldSchema)
74
+ });
75
+ var AttachmentSchema = z.discriminatedUnion("type", [
76
+ z.object({ type: z.literal("image"), url: z.string().url() }),
77
+ z.object({ type: z.literal("file"), url: z.string().url(), filename: z.string().optional() })
78
+ ]);
79
+ var VesselStatusSchema = z.enum(["active", "waiting", "resolved"]);
80
+ z.object({
81
+ message: z.string().min(1).max(1e4).optional(),
82
+ vessel: z.string().optional(),
83
+ vesselTitle: z.string().optional(),
84
+ card: CardSchema.optional(),
85
+ interaction: InteractionSchema.optional(),
86
+ previewUrl: z.string().url().optional(),
87
+ metadata: z.record(z.unknown()).refine(
88
+ (v) => JSON.stringify(v).length < 16e3,
89
+ "metadata exceeds 16KB limit"
90
+ ).optional(),
91
+ pinCard: CardSchema.nullable().optional(),
92
+ vesselStatus: VesselStatusSchema.optional(),
93
+ labels: z.array(z.string().min(1).max(50)).max(10).optional(),
94
+ attachments: z.array(AttachmentSchema).max(10).optional(),
95
+ suggestions: z.array(z.string().min(1).max(500)).max(5).optional(),
96
+ agentActivity: AgentActivitySchema.optional()
97
+ }).refine((d) => d.message || d.agentActivity, {
98
+ message: "Either message or agentActivity is required"
99
+ });
100
+ z.object({
101
+ vessels: z.array(z.string().min(1)).min(1).max(100),
102
+ message: z.string().min(1).max(1e4),
103
+ vesselTitle: z.string().optional(),
104
+ card: CardSchema.optional(),
105
+ interaction: InteractionSchema.optional(),
106
+ pinCard: CardSchema.nullable().optional(),
107
+ vesselStatus: VesselStatusSchema.optional(),
108
+ attachments: z.array(AttachmentSchema).max(10).optional(),
109
+ suggestions: z.array(z.string().min(1).max(500)).max(5).optional(),
110
+ metadata: z.record(z.unknown()).refine(
111
+ (v) => JSON.stringify(v).length < 16e3,
112
+ "metadata exceeds 16KB limit"
113
+ ).optional()
114
+ });
115
+ z.object({
116
+ content: z.string().min(1).max(1e4).optional(),
117
+ card: CardSchema.nullable().optional(),
118
+ attachments: z.array(AttachmentSchema).max(10).nullable().optional(),
119
+ suggestions: z.array(z.string().min(1).max(500)).max(5).nullable().optional(),
120
+ agentActivity: AgentActivitySchema.nullable().optional()
121
+ }).refine((d) => Object.values(d).some((v) => v !== void 0), {
122
+ message: "At least one field required"
123
+ });
124
+ var ApprovalResponseSchema = z.object({
125
+ action: z.enum(["approved", "rejected"]),
126
+ reason: z.string().optional()
127
+ });
128
+ var ChoiceResponseSchema = z.object({
129
+ selected: z.string(),
130
+ customValue: z.string().nullable().optional()
131
+ });
132
+ var ChecklistResponseSchema = z.object({
133
+ selected: z.array(z.string())
134
+ });
135
+ var TextInputResponseSchema = z.object({
136
+ text: z.string()
137
+ });
138
+ var ConfirmPreviewResponseSchema = z.object({
139
+ action: z.enum(["approved", "rejected"]),
140
+ reason: z.string().optional()
141
+ });
142
+ z.discriminatedUnion("interactionType", [
143
+ z.object({ interactionType: z.literal("approval"), response: ApprovalResponseSchema }),
144
+ z.object({ interactionType: z.literal("choice"), response: ChoiceResponseSchema }),
145
+ z.object({ interactionType: z.literal("checklist"), response: ChecklistResponseSchema }),
146
+ z.object({ interactionType: z.literal("text_input"), response: TextInputResponseSchema }),
147
+ z.object({ interactionType: z.literal("confirm_preview"), response: ConfirmPreviewResponseSchema })
148
+ ]);
149
+ var WebhookVesselSchema = z.object({
150
+ id: z.string(),
151
+ external_id: z.string().nullable(),
152
+ title: z.string().nullable(),
153
+ metadata: z.record(z.unknown())
154
+ });
155
+ var WebhookContextMessageSchema = z.object({
156
+ source: z.string(),
157
+ content: z.string().nullable(),
158
+ created_at: z.string()
159
+ });
160
+ var WebhookInteractionResponsePayloadSchema = z.object({
161
+ event: z.literal("interaction.response"),
162
+ vessel_id: z.string(),
163
+ workspace_id: z.string(),
164
+ timestamp: z.string(),
165
+ data: z.object({
166
+ message_id: z.string(),
167
+ interaction_type: z.string(),
168
+ response: z.record(z.unknown()),
169
+ response_id: z.string(),
170
+ metadata: z.record(z.unknown()).optional(),
171
+ vessel: WebhookVesselSchema
172
+ })
173
+ });
174
+ var WebhookUserMessagePayloadSchema = z.object({
175
+ event: z.literal("message.user"),
176
+ vessel_id: z.string(),
177
+ workspace_id: z.string(),
178
+ timestamp: z.string(),
179
+ data: z.object({
180
+ message_id: z.string(),
181
+ content: z.string(),
182
+ vessel: WebhookVesselSchema,
183
+ context: z.array(WebhookContextMessageSchema)
184
+ })
185
+ });
186
+ var WebhookPayloadSchema = z.discriminatedUnion("event", [
187
+ WebhookInteractionResponsePayloadSchema,
188
+ WebhookUserMessagePayloadSchema
189
+ ]);
190
+
1
191
  // src/index.ts
2
192
  var AgentActivityTypes = {
3
193
  thinking: "thinking",
@@ -176,7 +366,8 @@ var Vessels = class {
176
366
  type: "message.user",
177
367
  timestamp: e.timestamp,
178
368
  vessel,
179
- message: { id: e.message?.id, content: e.message?.content ?? null }
369
+ message: { id: e.message?.id, content: e.message?.content ?? null },
370
+ context: []
180
371
  };
181
372
  });
182
373
  return { ok: true, events, hasMore: data.has_more ?? false };
@@ -207,6 +398,55 @@ var Vessels = class {
207
398
  return false;
208
399
  }
209
400
  }
401
+ // Verify + parse in one call. Returns a typed event or null (invalid signature or unknown type).
402
+ // body: raw request body string (before JSON.parse)
403
+ // signature: X-Vessels-Signature header value
404
+ // webhookSecret: the secret shown when you created the webhook endpoint in Settings
405
+ async parseWebhookEvent(body, signature, webhookSecret) {
406
+ const valid = await this.verifyWebhook(body, signature, webhookSecret);
407
+ if (!valid) return null;
408
+ try {
409
+ const raw = JSON.parse(body);
410
+ const v = raw.data?.vessel ?? {};
411
+ const vessel = {
412
+ id: v.id,
413
+ externalId: v.external_id ?? null,
414
+ title: v.title ?? null,
415
+ metadata: v.metadata ?? {},
416
+ labels: v.labels ?? []
417
+ };
418
+ if (raw.event === "interaction.response") {
419
+ return {
420
+ id: raw.data.response_id,
421
+ type: "interaction.response",
422
+ timestamp: raw.timestamp,
423
+ vessel,
424
+ messageId: raw.data.message_id,
425
+ interactionType: raw.data.interaction_type,
426
+ response: raw.data.response,
427
+ interactionMetadata: raw.data.metadata ?? null,
428
+ user: raw.data.user ?? null
429
+ };
430
+ }
431
+ if (raw.event === "message.user") {
432
+ return {
433
+ id: raw.data.message_id,
434
+ type: "message.user",
435
+ timestamp: raw.timestamp,
436
+ vessel,
437
+ message: { id: raw.data.message_id, content: raw.data.content ?? null },
438
+ context: (raw.data.context ?? []).map((m) => ({
439
+ source: m.source,
440
+ content: m.content ?? null,
441
+ createdAt: m.created_at
442
+ }))
443
+ };
444
+ }
445
+ return null;
446
+ } catch {
447
+ return null;
448
+ }
449
+ }
210
450
  };
211
451
 
212
- export { AgentActivityTypes, Vessels, VesselsAuthError, VesselsRateLimitError, VesselsValidationError };
452
+ export { AgentActivityTypes, Vessels, VesselsAuthError, VesselsRateLimitError, VesselsValidationError, WebhookInteractionResponsePayloadSchema, WebhookPayloadSchema, WebhookUserMessagePayloadSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vessels-sdk",
3
- "version": "0.4.1",
3
+ "version": "0.5.1",
4
4
  "description": "Let your agent reach you. Official Vessels SDK.",
5
5
  "type": "module",
6
6
  "exports": {