vessels-sdk 0.6.0 → 0.9.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/dist/index.cjs +83 -7
- package/dist/index.d.cts +45 -6
- package/dist/index.d.ts +45 -6
- package/dist/index.js +82 -8
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -160,6 +160,8 @@ var WebhookVesselSchema = zod.z.object({
|
|
|
160
160
|
id: zod.z.string(),
|
|
161
161
|
external_id: zod.z.string().nullable(),
|
|
162
162
|
title: zod.z.string().nullable(),
|
|
163
|
+
/** The vessel's type (e.g. "Ticket"). Nullable — agent-created vessels have no type. */
|
|
164
|
+
type: zod.z.string().nullable().optional(),
|
|
163
165
|
metadata: zod.z.record(zod.z.unknown())
|
|
164
166
|
});
|
|
165
167
|
var WebhookContextMessageSchema = zod.z.object({
|
|
@@ -202,9 +204,35 @@ var WebhookUserMessagePayloadSchema = zod.z.object({
|
|
|
202
204
|
context: zod.z.array(WebhookContextMessageSchema)
|
|
203
205
|
})
|
|
204
206
|
});
|
|
207
|
+
var WebhookVesselCreatedPayloadSchema = zod.z.object({
|
|
208
|
+
event: zod.z.literal("vessel.created"),
|
|
209
|
+
vessel_id: zod.z.string(),
|
|
210
|
+
workspace_id: zod.z.string(),
|
|
211
|
+
timestamp: zod.z.string(),
|
|
212
|
+
data: zod.z.object({
|
|
213
|
+
vessel: WebhookVesselSchema,
|
|
214
|
+
message: zod.z.object({
|
|
215
|
+
message_id: zod.z.string(),
|
|
216
|
+
content: zod.z.string().nullable(),
|
|
217
|
+
created_at: zod.z.string()
|
|
218
|
+
})
|
|
219
|
+
})
|
|
220
|
+
});
|
|
221
|
+
var WebhookMessageCancelledPayloadSchema = zod.z.object({
|
|
222
|
+
event: zod.z.literal("message.cancelled"),
|
|
223
|
+
vessel_id: zod.z.string(),
|
|
224
|
+
workspace_id: zod.z.string(),
|
|
225
|
+
timestamp: zod.z.string(),
|
|
226
|
+
data: zod.z.object({
|
|
227
|
+
message_id: zod.z.string(),
|
|
228
|
+
vessel: WebhookVesselSchema
|
|
229
|
+
})
|
|
230
|
+
});
|
|
205
231
|
var WebhookPayloadSchema = zod.z.discriminatedUnion("event", [
|
|
206
232
|
WebhookInteractionResponsePayloadSchema,
|
|
207
|
-
WebhookUserMessagePayloadSchema
|
|
233
|
+
WebhookUserMessagePayloadSchema,
|
|
234
|
+
WebhookVesselCreatedPayloadSchema,
|
|
235
|
+
WebhookMessageCancelledPayloadSchema
|
|
208
236
|
]);
|
|
209
237
|
|
|
210
238
|
// src/index.ts
|
|
@@ -237,6 +265,12 @@ var VesselsRateLimitError = class extends Error {
|
|
|
237
265
|
this.retryAfter = retryAfter;
|
|
238
266
|
}
|
|
239
267
|
};
|
|
268
|
+
var VesselsConflictError = class extends Error {
|
|
269
|
+
constructor(message) {
|
|
270
|
+
super(message);
|
|
271
|
+
this.name = "VesselsConflictError";
|
|
272
|
+
}
|
|
273
|
+
};
|
|
240
274
|
var Vessels = class {
|
|
241
275
|
apiKey;
|
|
242
276
|
baseUrl;
|
|
@@ -270,38 +304,45 @@ var Vessels = class {
|
|
|
270
304
|
return res;
|
|
271
305
|
}
|
|
272
306
|
async push(payload) {
|
|
307
|
+
const { idempotencyKey, ...body } = payload;
|
|
273
308
|
const res = await this._fetch(`${this.baseUrl}/api/v1/push`, {
|
|
274
309
|
method: "POST",
|
|
275
310
|
headers: {
|
|
276
311
|
"Content-Type": "application/json",
|
|
277
|
-
"Authorization": `Bearer ${this.apiKey}
|
|
312
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
313
|
+
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
|
|
278
314
|
},
|
|
279
|
-
body: JSON.stringify(
|
|
315
|
+
body: JSON.stringify(body)
|
|
280
316
|
});
|
|
281
317
|
const data = await res.json();
|
|
282
318
|
if (res.status === 401) throw new VesselsAuthError(data.error ?? "Unauthorized");
|
|
283
319
|
if (res.status === 429) throw new VesselsRateLimitError(data.error ?? "Rate limited", Number(res.headers.get("retry-after")));
|
|
320
|
+
if (res.status === 409) throw new VesselsConflictError(data.error ?? "Idempotent request in progress");
|
|
284
321
|
if (res.status === 400) throw new VesselsValidationError(data.error ?? "Validation failed", data.details);
|
|
285
322
|
if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
|
|
286
323
|
return {
|
|
287
324
|
ok: true,
|
|
288
325
|
messageId: data.message_id,
|
|
289
326
|
vesselId: data.vessel_id,
|
|
290
|
-
createdAt: data.created_at
|
|
327
|
+
createdAt: data.created_at,
|
|
328
|
+
replayed: res.headers.get("Idempotent-Replayed") === "true"
|
|
291
329
|
};
|
|
292
330
|
}
|
|
293
331
|
async pushMany(payload) {
|
|
332
|
+
const { idempotencyKey, ...body } = payload;
|
|
294
333
|
const res = await this._fetch(`${this.baseUrl}/api/v1/push/many`, {
|
|
295
334
|
method: "POST",
|
|
296
335
|
headers: {
|
|
297
336
|
"Content-Type": "application/json",
|
|
298
|
-
"Authorization": `Bearer ${this.apiKey}
|
|
337
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
338
|
+
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
|
|
299
339
|
},
|
|
300
|
-
body: JSON.stringify(
|
|
340
|
+
body: JSON.stringify(body)
|
|
301
341
|
});
|
|
302
342
|
const data = await res.json();
|
|
303
343
|
if (res.status === 401) throw new VesselsAuthError(data.error ?? "Unauthorized");
|
|
304
344
|
if (res.status === 429) throw new VesselsRateLimitError(data.error ?? "Rate limited", Number(res.headers.get("retry-after")));
|
|
345
|
+
if (res.status === 409) throw new VesselsConflictError(data.error ?? "Idempotent request in progress");
|
|
305
346
|
if (res.status === 400) throw new VesselsValidationError(data.error ?? "Validation failed", data.details);
|
|
306
347
|
if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
|
|
307
348
|
return {
|
|
@@ -311,7 +352,8 @@ var Vessels = class {
|
|
|
311
352
|
messageId: r.message_id,
|
|
312
353
|
vesselId: r.vessel_id,
|
|
313
354
|
...r.error ? { error: r.error } : {}
|
|
314
|
-
}))
|
|
355
|
+
})),
|
|
356
|
+
replayed: res.headers.get("Idempotent-Replayed") === "true"
|
|
315
357
|
};
|
|
316
358
|
}
|
|
317
359
|
async editMessage(messageId, patch) {
|
|
@@ -396,9 +438,19 @@ var Vessels = class {
|
|
|
396
438
|
id: e.vessel?.id,
|
|
397
439
|
externalId: e.vessel?.external_id ?? null,
|
|
398
440
|
title: e.vessel?.title ?? null,
|
|
441
|
+
type: e.vessel?.type ?? null,
|
|
399
442
|
metadata: e.vessel?.metadata ?? {},
|
|
400
443
|
labels: e.vessel?.labels ?? []
|
|
401
444
|
};
|
|
445
|
+
if (e.type === "vessel.created") {
|
|
446
|
+
return {
|
|
447
|
+
id: e.id,
|
|
448
|
+
type: "vessel.created",
|
|
449
|
+
timestamp: e.timestamp,
|
|
450
|
+
vessel,
|
|
451
|
+
message: { id: e.message?.id, content: e.message?.content ?? null }
|
|
452
|
+
};
|
|
453
|
+
}
|
|
402
454
|
if (e.type === "interaction.response") {
|
|
403
455
|
return {
|
|
404
456
|
id: e.id,
|
|
@@ -470,9 +522,22 @@ var Vessels = class {
|
|
|
470
522
|
id: v.id,
|
|
471
523
|
externalId: v.external_id ?? null,
|
|
472
524
|
title: v.title ?? null,
|
|
525
|
+
type: v.type ?? null,
|
|
473
526
|
metadata: v.metadata ?? {},
|
|
474
527
|
labels: v.labels ?? []
|
|
475
528
|
};
|
|
529
|
+
if (raw.event === "vessel.created") {
|
|
530
|
+
return {
|
|
531
|
+
id: raw.vessel_id,
|
|
532
|
+
type: "vessel.created",
|
|
533
|
+
timestamp: raw.timestamp,
|
|
534
|
+
vessel,
|
|
535
|
+
message: {
|
|
536
|
+
id: raw.data.message?.message_id,
|
|
537
|
+
content: raw.data.message?.content ?? null
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
}
|
|
476
541
|
if (raw.event === "interaction.response") {
|
|
477
542
|
return {
|
|
478
543
|
id: raw.data.response_id,
|
|
@@ -493,6 +558,15 @@ var Vessels = class {
|
|
|
493
558
|
user: raw.data.user ?? null
|
|
494
559
|
};
|
|
495
560
|
}
|
|
561
|
+
if (raw.event === "message.cancelled") {
|
|
562
|
+
return {
|
|
563
|
+
id: raw.data.message_id,
|
|
564
|
+
type: "message.cancelled",
|
|
565
|
+
timestamp: raw.timestamp,
|
|
566
|
+
vessel,
|
|
567
|
+
messageId: raw.data.message_id
|
|
568
|
+
};
|
|
569
|
+
}
|
|
496
570
|
if (raw.event === "message.user") {
|
|
497
571
|
return {
|
|
498
572
|
id: raw.data.message_id,
|
|
@@ -517,8 +591,10 @@ var Vessels = class {
|
|
|
517
591
|
exports.AgentActivityTypes = AgentActivityTypes;
|
|
518
592
|
exports.Vessels = Vessels;
|
|
519
593
|
exports.VesselsAuthError = VesselsAuthError;
|
|
594
|
+
exports.VesselsConflictError = VesselsConflictError;
|
|
520
595
|
exports.VesselsRateLimitError = VesselsRateLimitError;
|
|
521
596
|
exports.VesselsValidationError = VesselsValidationError;
|
|
522
597
|
exports.WebhookInteractionResponsePayloadSchema = WebhookInteractionResponsePayloadSchema;
|
|
523
598
|
exports.WebhookPayloadSchema = WebhookPayloadSchema;
|
|
524
599
|
exports.WebhookUserMessagePayloadSchema = WebhookUserMessagePayloadSchema;
|
|
600
|
+
exports.WebhookVesselCreatedPayloadSchema = WebhookVesselCreatedPayloadSchema;
|
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, WebhookInteractionResponsePayload, WebhookInteractionResponsePayloadSchema, WebhookPayload, WebhookPayloadSchema, WebhookUserMessagePayload, WebhookUserMessagePayloadSchema } from '@vessels/types';
|
|
2
|
+
export { AgentActivity, AgentActivityType, ApprovalInteraction, Attachment, Card, ChecklistInteraction, ChoiceInteraction, ConfirmPreviewInteraction, Interaction, MessagePatch, PushManyOptions, PushManyPayload, PushOptions, PushPayload, TextInputInteraction, WebhookInteractionResponsePayload, WebhookInteractionResponsePayloadSchema, WebhookPayload, WebhookPayloadSchema, WebhookUserMessagePayload, WebhookUserMessagePayloadSchema, WebhookVesselCreatedPayload, WebhookVesselCreatedPayloadSchema } from '@vessels/types';
|
|
3
3
|
|
|
4
4
|
declare const AgentActivityTypes: {
|
|
5
5
|
readonly thinking: "thinking";
|
|
@@ -19,6 +19,10 @@ declare class VesselsRateLimitError extends Error {
|
|
|
19
19
|
retryAfter?: number;
|
|
20
20
|
constructor(message: string, retryAfter?: number);
|
|
21
21
|
}
|
|
22
|
+
/** Thrown on HTTP 409 — an identical idempotent request is still in flight. Back off and retry. */
|
|
23
|
+
declare class VesselsConflictError extends Error {
|
|
24
|
+
constructor(message: string);
|
|
25
|
+
}
|
|
22
26
|
interface VesselsConfig {
|
|
23
27
|
apiKey: string;
|
|
24
28
|
baseUrl?: string;
|
|
@@ -29,6 +33,8 @@ interface PushResponse {
|
|
|
29
33
|
messageId: string;
|
|
30
34
|
vesselId: string;
|
|
31
35
|
createdAt: string;
|
|
36
|
+
/** True when this response is a replay of an earlier request with the same idempotency key. */
|
|
37
|
+
replayed: boolean;
|
|
32
38
|
}
|
|
33
39
|
interface PushManyResult {
|
|
34
40
|
ok: true;
|
|
@@ -38,6 +44,8 @@ interface PushManyResult {
|
|
|
38
44
|
vesselId: string;
|
|
39
45
|
error?: string;
|
|
40
46
|
}>;
|
|
47
|
+
/** True when this response is a replay of an earlier request with the same idempotency key. */
|
|
48
|
+
replayed: boolean;
|
|
41
49
|
}
|
|
42
50
|
interface PollOptions {
|
|
43
51
|
since?: string;
|
|
@@ -48,6 +56,8 @@ interface VesselContext {
|
|
|
48
56
|
id: string;
|
|
49
57
|
externalId: string | null;
|
|
50
58
|
title: string | null;
|
|
59
|
+
/** The vessel's type (e.g. "Ticket"). Null for agent-created vessels. */
|
|
60
|
+
type: string | null;
|
|
51
61
|
metadata: Record<string, unknown>;
|
|
52
62
|
labels: string[];
|
|
53
63
|
}
|
|
@@ -91,6 +101,35 @@ interface UserMessageEvent {
|
|
|
91
101
|
createdAt: string;
|
|
92
102
|
}>;
|
|
93
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Fired when a human opens a new typed vessel from the app (user-initiated
|
|
106
|
+
* vessels). `message` is the first thing the human typed; `vessel.type` is the
|
|
107
|
+
* vessel's type (e.g. "Ticket").
|
|
108
|
+
*/
|
|
109
|
+
interface VesselCreatedEvent {
|
|
110
|
+
id: string;
|
|
111
|
+
type: 'vessel.created';
|
|
112
|
+
timestamp: string;
|
|
113
|
+
vessel: VesselContext;
|
|
114
|
+
message: {
|
|
115
|
+
id: string;
|
|
116
|
+
content: string | null;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Fired when a human taps "Stop" on an in-progress (working) agent message in
|
|
121
|
+
* the app. Vessels does NOT force-stop anything — you decide what to do (abort
|
|
122
|
+
* a task, stop polling, ignore it). Delivery is synchronous: the app tells the
|
|
123
|
+
* human whether your handler accepted it (return 2xx) so they know cancel is
|
|
124
|
+
* wired up. `messageId` is the working agent message the human wants stopped.
|
|
125
|
+
*/
|
|
126
|
+
interface MessageCancelledEvent {
|
|
127
|
+
id: string;
|
|
128
|
+
type: 'message.cancelled';
|
|
129
|
+
timestamp: string;
|
|
130
|
+
vessel: VesselContext;
|
|
131
|
+
messageId: string;
|
|
132
|
+
}
|
|
94
133
|
/** A message in a vessel, as returned by getMessages — the human-facing record. */
|
|
95
134
|
interface Message {
|
|
96
135
|
id: string;
|
|
@@ -103,7 +142,7 @@ interface Message {
|
|
|
103
142
|
metadata: Record<string, unknown>;
|
|
104
143
|
createdAt: string;
|
|
105
144
|
}
|
|
106
|
-
type PollEvent = InteractionResponseEvent | UserMessageEvent;
|
|
145
|
+
type PollEvent = InteractionResponseEvent | UserMessageEvent | VesselCreatedEvent;
|
|
107
146
|
interface PollResponse {
|
|
108
147
|
ok: true;
|
|
109
148
|
events: PollEvent[];
|
|
@@ -115,8 +154,8 @@ declare class Vessels {
|
|
|
115
154
|
private _debug;
|
|
116
155
|
constructor(config: VesselsConfig);
|
|
117
156
|
private _fetch;
|
|
118
|
-
push(payload: _vessels_types.
|
|
119
|
-
pushMany(payload: _vessels_types.
|
|
157
|
+
push(payload: _vessels_types.PushOptions): Promise<PushResponse>;
|
|
158
|
+
pushMany(payload: _vessels_types.PushManyOptions): Promise<PushManyResult>;
|
|
120
159
|
editMessage(messageId: string, patch: _vessels_types.MessagePatch): Promise<{
|
|
121
160
|
ok: true;
|
|
122
161
|
}>;
|
|
@@ -182,7 +221,7 @@ declare class Vessels {
|
|
|
182
221
|
}): _vessels_types.ConfirmPreviewInteraction;
|
|
183
222
|
poll(options?: PollOptions): Promise<PollResponse>;
|
|
184
223
|
verifyWebhook(body: string, signature: string, webhookSecret: string): Promise<boolean>;
|
|
185
|
-
parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | null>;
|
|
224
|
+
parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | VesselCreatedEvent | MessageCancelledEvent | null>;
|
|
186
225
|
}
|
|
187
226
|
|
|
188
|
-
export { AgentActivityTypes, type InteractionResponseEvent, type Message, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type UserMessageEvent, type VesselContext, Vessels, VesselsAuthError, type VesselsConfig, VesselsRateLimitError, VesselsValidationError };
|
|
227
|
+
export { AgentActivityTypes, type InteractionResponseEvent, type Message, type MessageCancelledEvent, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type UserMessageEvent, type VesselContext, type VesselCreatedEvent, Vessels, VesselsAuthError, type VesselsConfig, VesselsConflictError, 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, WebhookInteractionResponsePayload, WebhookInteractionResponsePayloadSchema, WebhookPayload, WebhookPayloadSchema, WebhookUserMessagePayload, WebhookUserMessagePayloadSchema } from '@vessels/types';
|
|
2
|
+
export { AgentActivity, AgentActivityType, ApprovalInteraction, Attachment, Card, ChecklistInteraction, ChoiceInteraction, ConfirmPreviewInteraction, Interaction, MessagePatch, PushManyOptions, PushManyPayload, PushOptions, PushPayload, TextInputInteraction, WebhookInteractionResponsePayload, WebhookInteractionResponsePayloadSchema, WebhookPayload, WebhookPayloadSchema, WebhookUserMessagePayload, WebhookUserMessagePayloadSchema, WebhookVesselCreatedPayload, WebhookVesselCreatedPayloadSchema } from '@vessels/types';
|
|
3
3
|
|
|
4
4
|
declare const AgentActivityTypes: {
|
|
5
5
|
readonly thinking: "thinking";
|
|
@@ -19,6 +19,10 @@ declare class VesselsRateLimitError extends Error {
|
|
|
19
19
|
retryAfter?: number;
|
|
20
20
|
constructor(message: string, retryAfter?: number);
|
|
21
21
|
}
|
|
22
|
+
/** Thrown on HTTP 409 — an identical idempotent request is still in flight. Back off and retry. */
|
|
23
|
+
declare class VesselsConflictError extends Error {
|
|
24
|
+
constructor(message: string);
|
|
25
|
+
}
|
|
22
26
|
interface VesselsConfig {
|
|
23
27
|
apiKey: string;
|
|
24
28
|
baseUrl?: string;
|
|
@@ -29,6 +33,8 @@ interface PushResponse {
|
|
|
29
33
|
messageId: string;
|
|
30
34
|
vesselId: string;
|
|
31
35
|
createdAt: string;
|
|
36
|
+
/** True when this response is a replay of an earlier request with the same idempotency key. */
|
|
37
|
+
replayed: boolean;
|
|
32
38
|
}
|
|
33
39
|
interface PushManyResult {
|
|
34
40
|
ok: true;
|
|
@@ -38,6 +44,8 @@ interface PushManyResult {
|
|
|
38
44
|
vesselId: string;
|
|
39
45
|
error?: string;
|
|
40
46
|
}>;
|
|
47
|
+
/** True when this response is a replay of an earlier request with the same idempotency key. */
|
|
48
|
+
replayed: boolean;
|
|
41
49
|
}
|
|
42
50
|
interface PollOptions {
|
|
43
51
|
since?: string;
|
|
@@ -48,6 +56,8 @@ interface VesselContext {
|
|
|
48
56
|
id: string;
|
|
49
57
|
externalId: string | null;
|
|
50
58
|
title: string | null;
|
|
59
|
+
/** The vessel's type (e.g. "Ticket"). Null for agent-created vessels. */
|
|
60
|
+
type: string | null;
|
|
51
61
|
metadata: Record<string, unknown>;
|
|
52
62
|
labels: string[];
|
|
53
63
|
}
|
|
@@ -91,6 +101,35 @@ interface UserMessageEvent {
|
|
|
91
101
|
createdAt: string;
|
|
92
102
|
}>;
|
|
93
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Fired when a human opens a new typed vessel from the app (user-initiated
|
|
106
|
+
* vessels). `message` is the first thing the human typed; `vessel.type` is the
|
|
107
|
+
* vessel's type (e.g. "Ticket").
|
|
108
|
+
*/
|
|
109
|
+
interface VesselCreatedEvent {
|
|
110
|
+
id: string;
|
|
111
|
+
type: 'vessel.created';
|
|
112
|
+
timestamp: string;
|
|
113
|
+
vessel: VesselContext;
|
|
114
|
+
message: {
|
|
115
|
+
id: string;
|
|
116
|
+
content: string | null;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Fired when a human taps "Stop" on an in-progress (working) agent message in
|
|
121
|
+
* the app. Vessels does NOT force-stop anything — you decide what to do (abort
|
|
122
|
+
* a task, stop polling, ignore it). Delivery is synchronous: the app tells the
|
|
123
|
+
* human whether your handler accepted it (return 2xx) so they know cancel is
|
|
124
|
+
* wired up. `messageId` is the working agent message the human wants stopped.
|
|
125
|
+
*/
|
|
126
|
+
interface MessageCancelledEvent {
|
|
127
|
+
id: string;
|
|
128
|
+
type: 'message.cancelled';
|
|
129
|
+
timestamp: string;
|
|
130
|
+
vessel: VesselContext;
|
|
131
|
+
messageId: string;
|
|
132
|
+
}
|
|
94
133
|
/** A message in a vessel, as returned by getMessages — the human-facing record. */
|
|
95
134
|
interface Message {
|
|
96
135
|
id: string;
|
|
@@ -103,7 +142,7 @@ interface Message {
|
|
|
103
142
|
metadata: Record<string, unknown>;
|
|
104
143
|
createdAt: string;
|
|
105
144
|
}
|
|
106
|
-
type PollEvent = InteractionResponseEvent | UserMessageEvent;
|
|
145
|
+
type PollEvent = InteractionResponseEvent | UserMessageEvent | VesselCreatedEvent;
|
|
107
146
|
interface PollResponse {
|
|
108
147
|
ok: true;
|
|
109
148
|
events: PollEvent[];
|
|
@@ -115,8 +154,8 @@ declare class Vessels {
|
|
|
115
154
|
private _debug;
|
|
116
155
|
constructor(config: VesselsConfig);
|
|
117
156
|
private _fetch;
|
|
118
|
-
push(payload: _vessels_types.
|
|
119
|
-
pushMany(payload: _vessels_types.
|
|
157
|
+
push(payload: _vessels_types.PushOptions): Promise<PushResponse>;
|
|
158
|
+
pushMany(payload: _vessels_types.PushManyOptions): Promise<PushManyResult>;
|
|
120
159
|
editMessage(messageId: string, patch: _vessels_types.MessagePatch): Promise<{
|
|
121
160
|
ok: true;
|
|
122
161
|
}>;
|
|
@@ -182,7 +221,7 @@ declare class Vessels {
|
|
|
182
221
|
}): _vessels_types.ConfirmPreviewInteraction;
|
|
183
222
|
poll(options?: PollOptions): Promise<PollResponse>;
|
|
184
223
|
verifyWebhook(body: string, signature: string, webhookSecret: string): Promise<boolean>;
|
|
185
|
-
parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | null>;
|
|
224
|
+
parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | VesselCreatedEvent | MessageCancelledEvent | null>;
|
|
186
225
|
}
|
|
187
226
|
|
|
188
|
-
export { AgentActivityTypes, type InteractionResponseEvent, type Message, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type UserMessageEvent, type VesselContext, Vessels, VesselsAuthError, type VesselsConfig, VesselsRateLimitError, VesselsValidationError };
|
|
227
|
+
export { AgentActivityTypes, type InteractionResponseEvent, type Message, type MessageCancelledEvent, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type UserMessageEvent, type VesselContext, type VesselCreatedEvent, Vessels, VesselsAuthError, type VesselsConfig, VesselsConflictError, VesselsRateLimitError, VesselsValidationError };
|
package/dist/index.js
CHANGED
|
@@ -158,6 +158,8 @@ var WebhookVesselSchema = z.object({
|
|
|
158
158
|
id: z.string(),
|
|
159
159
|
external_id: z.string().nullable(),
|
|
160
160
|
title: z.string().nullable(),
|
|
161
|
+
/** The vessel's type (e.g. "Ticket"). Nullable — agent-created vessels have no type. */
|
|
162
|
+
type: z.string().nullable().optional(),
|
|
161
163
|
metadata: z.record(z.unknown())
|
|
162
164
|
});
|
|
163
165
|
var WebhookContextMessageSchema = z.object({
|
|
@@ -200,9 +202,35 @@ var WebhookUserMessagePayloadSchema = z.object({
|
|
|
200
202
|
context: z.array(WebhookContextMessageSchema)
|
|
201
203
|
})
|
|
202
204
|
});
|
|
205
|
+
var WebhookVesselCreatedPayloadSchema = z.object({
|
|
206
|
+
event: z.literal("vessel.created"),
|
|
207
|
+
vessel_id: z.string(),
|
|
208
|
+
workspace_id: z.string(),
|
|
209
|
+
timestamp: z.string(),
|
|
210
|
+
data: z.object({
|
|
211
|
+
vessel: WebhookVesselSchema,
|
|
212
|
+
message: z.object({
|
|
213
|
+
message_id: z.string(),
|
|
214
|
+
content: z.string().nullable(),
|
|
215
|
+
created_at: z.string()
|
|
216
|
+
})
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
var WebhookMessageCancelledPayloadSchema = z.object({
|
|
220
|
+
event: z.literal("message.cancelled"),
|
|
221
|
+
vessel_id: z.string(),
|
|
222
|
+
workspace_id: z.string(),
|
|
223
|
+
timestamp: z.string(),
|
|
224
|
+
data: z.object({
|
|
225
|
+
message_id: z.string(),
|
|
226
|
+
vessel: WebhookVesselSchema
|
|
227
|
+
})
|
|
228
|
+
});
|
|
203
229
|
var WebhookPayloadSchema = z.discriminatedUnion("event", [
|
|
204
230
|
WebhookInteractionResponsePayloadSchema,
|
|
205
|
-
WebhookUserMessagePayloadSchema
|
|
231
|
+
WebhookUserMessagePayloadSchema,
|
|
232
|
+
WebhookVesselCreatedPayloadSchema,
|
|
233
|
+
WebhookMessageCancelledPayloadSchema
|
|
206
234
|
]);
|
|
207
235
|
|
|
208
236
|
// src/index.ts
|
|
@@ -235,6 +263,12 @@ var VesselsRateLimitError = class extends Error {
|
|
|
235
263
|
this.retryAfter = retryAfter;
|
|
236
264
|
}
|
|
237
265
|
};
|
|
266
|
+
var VesselsConflictError = class extends Error {
|
|
267
|
+
constructor(message) {
|
|
268
|
+
super(message);
|
|
269
|
+
this.name = "VesselsConflictError";
|
|
270
|
+
}
|
|
271
|
+
};
|
|
238
272
|
var Vessels = class {
|
|
239
273
|
apiKey;
|
|
240
274
|
baseUrl;
|
|
@@ -268,38 +302,45 @@ var Vessels = class {
|
|
|
268
302
|
return res;
|
|
269
303
|
}
|
|
270
304
|
async push(payload) {
|
|
305
|
+
const { idempotencyKey, ...body } = payload;
|
|
271
306
|
const res = await this._fetch(`${this.baseUrl}/api/v1/push`, {
|
|
272
307
|
method: "POST",
|
|
273
308
|
headers: {
|
|
274
309
|
"Content-Type": "application/json",
|
|
275
|
-
"Authorization": `Bearer ${this.apiKey}
|
|
310
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
311
|
+
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
|
|
276
312
|
},
|
|
277
|
-
body: JSON.stringify(
|
|
313
|
+
body: JSON.stringify(body)
|
|
278
314
|
});
|
|
279
315
|
const data = await res.json();
|
|
280
316
|
if (res.status === 401) throw new VesselsAuthError(data.error ?? "Unauthorized");
|
|
281
317
|
if (res.status === 429) throw new VesselsRateLimitError(data.error ?? "Rate limited", Number(res.headers.get("retry-after")));
|
|
318
|
+
if (res.status === 409) throw new VesselsConflictError(data.error ?? "Idempotent request in progress");
|
|
282
319
|
if (res.status === 400) throw new VesselsValidationError(data.error ?? "Validation failed", data.details);
|
|
283
320
|
if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
|
|
284
321
|
return {
|
|
285
322
|
ok: true,
|
|
286
323
|
messageId: data.message_id,
|
|
287
324
|
vesselId: data.vessel_id,
|
|
288
|
-
createdAt: data.created_at
|
|
325
|
+
createdAt: data.created_at,
|
|
326
|
+
replayed: res.headers.get("Idempotent-Replayed") === "true"
|
|
289
327
|
};
|
|
290
328
|
}
|
|
291
329
|
async pushMany(payload) {
|
|
330
|
+
const { idempotencyKey, ...body } = payload;
|
|
292
331
|
const res = await this._fetch(`${this.baseUrl}/api/v1/push/many`, {
|
|
293
332
|
method: "POST",
|
|
294
333
|
headers: {
|
|
295
334
|
"Content-Type": "application/json",
|
|
296
|
-
"Authorization": `Bearer ${this.apiKey}
|
|
335
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
336
|
+
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
|
|
297
337
|
},
|
|
298
|
-
body: JSON.stringify(
|
|
338
|
+
body: JSON.stringify(body)
|
|
299
339
|
});
|
|
300
340
|
const data = await res.json();
|
|
301
341
|
if (res.status === 401) throw new VesselsAuthError(data.error ?? "Unauthorized");
|
|
302
342
|
if (res.status === 429) throw new VesselsRateLimitError(data.error ?? "Rate limited", Number(res.headers.get("retry-after")));
|
|
343
|
+
if (res.status === 409) throw new VesselsConflictError(data.error ?? "Idempotent request in progress");
|
|
303
344
|
if (res.status === 400) throw new VesselsValidationError(data.error ?? "Validation failed", data.details);
|
|
304
345
|
if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
|
|
305
346
|
return {
|
|
@@ -309,7 +350,8 @@ var Vessels = class {
|
|
|
309
350
|
messageId: r.message_id,
|
|
310
351
|
vesselId: r.vessel_id,
|
|
311
352
|
...r.error ? { error: r.error } : {}
|
|
312
|
-
}))
|
|
353
|
+
})),
|
|
354
|
+
replayed: res.headers.get("Idempotent-Replayed") === "true"
|
|
313
355
|
};
|
|
314
356
|
}
|
|
315
357
|
async editMessage(messageId, patch) {
|
|
@@ -394,9 +436,19 @@ var Vessels = class {
|
|
|
394
436
|
id: e.vessel?.id,
|
|
395
437
|
externalId: e.vessel?.external_id ?? null,
|
|
396
438
|
title: e.vessel?.title ?? null,
|
|
439
|
+
type: e.vessel?.type ?? null,
|
|
397
440
|
metadata: e.vessel?.metadata ?? {},
|
|
398
441
|
labels: e.vessel?.labels ?? []
|
|
399
442
|
};
|
|
443
|
+
if (e.type === "vessel.created") {
|
|
444
|
+
return {
|
|
445
|
+
id: e.id,
|
|
446
|
+
type: "vessel.created",
|
|
447
|
+
timestamp: e.timestamp,
|
|
448
|
+
vessel,
|
|
449
|
+
message: { id: e.message?.id, content: e.message?.content ?? null }
|
|
450
|
+
};
|
|
451
|
+
}
|
|
400
452
|
if (e.type === "interaction.response") {
|
|
401
453
|
return {
|
|
402
454
|
id: e.id,
|
|
@@ -468,9 +520,22 @@ var Vessels = class {
|
|
|
468
520
|
id: v.id,
|
|
469
521
|
externalId: v.external_id ?? null,
|
|
470
522
|
title: v.title ?? null,
|
|
523
|
+
type: v.type ?? null,
|
|
471
524
|
metadata: v.metadata ?? {},
|
|
472
525
|
labels: v.labels ?? []
|
|
473
526
|
};
|
|
527
|
+
if (raw.event === "vessel.created") {
|
|
528
|
+
return {
|
|
529
|
+
id: raw.vessel_id,
|
|
530
|
+
type: "vessel.created",
|
|
531
|
+
timestamp: raw.timestamp,
|
|
532
|
+
vessel,
|
|
533
|
+
message: {
|
|
534
|
+
id: raw.data.message?.message_id,
|
|
535
|
+
content: raw.data.message?.content ?? null
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
}
|
|
474
539
|
if (raw.event === "interaction.response") {
|
|
475
540
|
return {
|
|
476
541
|
id: raw.data.response_id,
|
|
@@ -491,6 +556,15 @@ var Vessels = class {
|
|
|
491
556
|
user: raw.data.user ?? null
|
|
492
557
|
};
|
|
493
558
|
}
|
|
559
|
+
if (raw.event === "message.cancelled") {
|
|
560
|
+
return {
|
|
561
|
+
id: raw.data.message_id,
|
|
562
|
+
type: "message.cancelled",
|
|
563
|
+
timestamp: raw.timestamp,
|
|
564
|
+
vessel,
|
|
565
|
+
messageId: raw.data.message_id
|
|
566
|
+
};
|
|
567
|
+
}
|
|
494
568
|
if (raw.event === "message.user") {
|
|
495
569
|
return {
|
|
496
570
|
id: raw.data.message_id,
|
|
@@ -512,4 +586,4 @@ var Vessels = class {
|
|
|
512
586
|
}
|
|
513
587
|
};
|
|
514
588
|
|
|
515
|
-
export { AgentActivityTypes, Vessels, VesselsAuthError, VesselsRateLimitError, VesselsValidationError, WebhookInteractionResponsePayloadSchema, WebhookPayloadSchema, WebhookUserMessagePayloadSchema };
|
|
589
|
+
export { AgentActivityTypes, Vessels, VesselsAuthError, VesselsConflictError, VesselsRateLimitError, VesselsValidationError, WebhookInteractionResponsePayloadSchema, WebhookPayloadSchema, WebhookUserMessagePayloadSchema, WebhookVesselCreatedPayloadSchema };
|