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 +244 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +242 -2
- package/package.json +1 -1
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 };
|