vessels-sdk 0.12.0 → 0.14.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 +69 -7
- package/dist/index.d.cts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.js +69 -7
- package/package.json +8 -2
package/dist/index.cjs
CHANGED
|
@@ -75,7 +75,10 @@ var CardFieldSchema = zod.z.object({
|
|
|
75
75
|
value: zod.z.string()
|
|
76
76
|
});
|
|
77
77
|
var CardSchema = zod.z.object({
|
|
78
|
-
|
|
78
|
+
// Optional: a glance-facts card under a surface takes its heading from the
|
|
79
|
+
// surface `title`, so a card title is redundant there. Still allowed (e.g. a
|
|
80
|
+
// standalone card on a bubble, or a pinned card).
|
|
81
|
+
title: zod.z.string().min(1).optional(),
|
|
79
82
|
fields: zod.z.array(CardFieldSchema)
|
|
80
83
|
});
|
|
81
84
|
var AttachmentSchema = zod.z.discriminatedUnion("type", [
|
|
@@ -83,6 +86,8 @@ var AttachmentSchema = zod.z.discriminatedUnion("type", [
|
|
|
83
86
|
zod.z.object({ type: zod.z.literal("file"), url: zod.z.string().url(), filename: zod.z.string().optional() })
|
|
84
87
|
]);
|
|
85
88
|
var VesselStatusSchema = zod.z.enum(["active", "waiting", "resolved"]);
|
|
89
|
+
var DisplaySchema = zod.z.enum(["bubble", "document"]);
|
|
90
|
+
var KindSchema = zod.z.enum(["bubble", "surface"]);
|
|
86
91
|
var PushPayloadSchema = zod.z.object({
|
|
87
92
|
message: zod.z.string().min(1).max(1e4).optional(),
|
|
88
93
|
vessel: zod.z.string().optional(),
|
|
@@ -107,7 +112,13 @@ var PushPayloadSchema = zod.z.object({
|
|
|
107
112
|
* window, not a transcript: send the tail you want shown (the SDK trims to the
|
|
108
113
|
* last 8000 chars). Plaintext, like agentActivity. Vanishes when cleared.
|
|
109
114
|
*/
|
|
110
|
-
tokenStream: zod.z.string().max(8e3).optional()
|
|
115
|
+
tokenStream: zod.z.string().max(8e3).optional(),
|
|
116
|
+
/** Bubble (chat) vs surface (composed artifact). Defaults from interaction/card. */
|
|
117
|
+
kind: KindSchema.optional(),
|
|
118
|
+
/** Surface heading. Ignored on bubbles. */
|
|
119
|
+
title: zod.z.string().max(200).optional(),
|
|
120
|
+
/** @deprecated legacy presentation hint — use `kind`. 'document' → surface. */
|
|
121
|
+
display: DisplaySchema.optional()
|
|
111
122
|
}).refine((d) => d.message || d.agentActivity || d.tokenStream, {
|
|
112
123
|
message: "One of message, agentActivity, or tokenStream is required"
|
|
113
124
|
});
|
|
@@ -124,7 +135,11 @@ var PushManyPayloadSchema = zod.z.object({
|
|
|
124
135
|
metadata: zod.z.record(zod.z.unknown()).refine(
|
|
125
136
|
(v) => JSON.stringify(v).length < 16e3,
|
|
126
137
|
"metadata exceeds 16KB limit"
|
|
127
|
-
).optional()
|
|
138
|
+
).optional(),
|
|
139
|
+
kind: KindSchema.optional(),
|
|
140
|
+
title: zod.z.string().max(200).optional(),
|
|
141
|
+
/** @deprecated use `kind`. */
|
|
142
|
+
display: DisplaySchema.optional()
|
|
128
143
|
});
|
|
129
144
|
zod.z.object({
|
|
130
145
|
content: zod.z.string().min(1).max(1e4).optional(),
|
|
@@ -133,7 +148,13 @@ zod.z.object({
|
|
|
133
148
|
suggestions: zod.z.array(zod.z.string().min(1).max(500)).max(5).nullable().optional(),
|
|
134
149
|
agentActivity: AgentActivitySchema.nullable().optional(),
|
|
135
150
|
/** Replace the live token-stream window, or `null` to clear it (block vanishes). */
|
|
136
|
-
tokenStream: zod.z.string().max(8e3).nullable().optional()
|
|
151
|
+
tokenStream: zod.z.string().max(8e3).nullable().optional(),
|
|
152
|
+
/** Switch kind: 'surface' = full-width artifact, 'bubble' or null = chat bubble. */
|
|
153
|
+
kind: KindSchema.nullable().optional(),
|
|
154
|
+
/** Update the surface heading, or `null` to clear it. */
|
|
155
|
+
title: zod.z.string().max(200).nullable().optional(),
|
|
156
|
+
/** @deprecated use `kind`. */
|
|
157
|
+
display: DisplaySchema.nullable().optional()
|
|
137
158
|
}).refine((d) => Object.values(d).some((v) => v !== void 0), {
|
|
138
159
|
message: "At least one field required"
|
|
139
160
|
});
|
|
@@ -193,6 +214,11 @@ var WebhookInteractionResponsePayloadSchema = zod.z.object({
|
|
|
193
214
|
vessel: WebhookVesselSchema
|
|
194
215
|
})
|
|
195
216
|
});
|
|
217
|
+
var SupersededInteractionSchema = zod.z.object({
|
|
218
|
+
message_id: zod.z.string(),
|
|
219
|
+
interaction_type: InteractionTypeSchema,
|
|
220
|
+
prompt: zod.z.string().nullable()
|
|
221
|
+
});
|
|
196
222
|
var WebhookUserMessagePayloadSchema = zod.z.object({
|
|
197
223
|
event: zod.z.literal("message.user"),
|
|
198
224
|
vessel_id: zod.z.string(),
|
|
@@ -202,7 +228,8 @@ var WebhookUserMessagePayloadSchema = zod.z.object({
|
|
|
202
228
|
message_id: zod.z.string(),
|
|
203
229
|
content: zod.z.string(),
|
|
204
230
|
vessel: WebhookVesselSchema,
|
|
205
|
-
context: zod.z.array(WebhookContextMessageSchema)
|
|
231
|
+
context: zod.z.array(WebhookContextMessageSchema),
|
|
232
|
+
superseded_interaction: SupersededInteractionSchema.optional()
|
|
206
233
|
})
|
|
207
234
|
});
|
|
208
235
|
var WebhookVesselCreatedPayloadSchema = zod.z.object({
|
|
@@ -361,6 +388,31 @@ var Vessels = class {
|
|
|
361
388
|
replayed: res.headers.get("Idempotent-Replayed") === "true"
|
|
362
389
|
};
|
|
363
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* Create a **surface** — a full-width composed artifact the human reviews and
|
|
393
|
+
* optionally acts on, rendered as one piece: a `title` heading, an optional
|
|
394
|
+
* `card` of glance-facts, a block-markdown `body` (tables, bullet/numbered
|
|
395
|
+
* lists, blockquotes, bold headings, links), and an optional `interaction`
|
|
396
|
+
* (the action bar). Use this for an email/message draft, a quote, an invoice
|
|
397
|
+
* review, a proposal, a report — anything substantial and structured.
|
|
398
|
+
*
|
|
399
|
+
* Sugar over {@link push}: it sets `kind: 'surface'` and maps `body` to the
|
|
400
|
+
* message content. For conversation, status updates and quick questions, use
|
|
401
|
+
* {@link push} instead (a chat **bubble** — the human just replies).
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* await vessels.surface({
|
|
405
|
+
* vessel: 'inv-42',
|
|
406
|
+
* title: 'GreenTurf Invoice #GTL-2025-042',
|
|
407
|
+
* card: { fields: [{ label: 'Amount Due', value: '$7,400' }] },
|
|
408
|
+
* body: 'Invoice is **$1,200 over** the usual rate.\n\n| Item | Amount |\n|---|---:|\n| Overage | +$1,200 |',
|
|
409
|
+
* interaction: vessels.approval({ prompt: 'Approve the $7,400 payment?' }),
|
|
410
|
+
* });
|
|
411
|
+
*/
|
|
412
|
+
async surface(options) {
|
|
413
|
+
const { body, ...rest } = options;
|
|
414
|
+
return this.push({ ...rest, message: body, kind: "surface" });
|
|
415
|
+
}
|
|
364
416
|
async pushMany(payload) {
|
|
365
417
|
const { idempotencyKey, ...body } = payload;
|
|
366
418
|
const check = PushManyPayloadSchema.safeParse(body);
|
|
@@ -623,7 +675,12 @@ var Vessels = class {
|
|
|
623
675
|
timestamp: e.timestamp,
|
|
624
676
|
vessel,
|
|
625
677
|
message: { id: e.message?.id, content: e.message?.content ?? null },
|
|
626
|
-
context: []
|
|
678
|
+
context: [],
|
|
679
|
+
supersededInteraction: e.superseded_interaction ? {
|
|
680
|
+
messageId: e.superseded_interaction.message_id,
|
|
681
|
+
interactionType: e.superseded_interaction.interaction_type,
|
|
682
|
+
prompt: e.superseded_interaction.prompt ?? null
|
|
683
|
+
} : null
|
|
627
684
|
};
|
|
628
685
|
});
|
|
629
686
|
return { ok: true, events, hasMore: data.has_more ?? false };
|
|
@@ -724,7 +781,12 @@ var Vessels = class {
|
|
|
724
781
|
source: m.source,
|
|
725
782
|
content: m.content ?? null,
|
|
726
783
|
createdAt: m.created_at
|
|
727
|
-
}))
|
|
784
|
+
})),
|
|
785
|
+
supersededInteraction: raw.data.superseded_interaction ? {
|
|
786
|
+
messageId: raw.data.superseded_interaction.message_id,
|
|
787
|
+
interactionType: raw.data.superseded_interaction.interaction_type,
|
|
788
|
+
prompt: raw.data.superseded_interaction.prompt ?? null
|
|
789
|
+
} : null
|
|
728
790
|
};
|
|
729
791
|
}
|
|
730
792
|
return null;
|
package/dist/index.d.cts
CHANGED
|
@@ -106,6 +106,14 @@ interface PushResponse {
|
|
|
106
106
|
/** True when this response is a replay of an earlier request with the same idempotency key. */
|
|
107
107
|
replayed: boolean;
|
|
108
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Options for {@link Vessels.surface}. Same as a push, but the artifact text is
|
|
111
|
+
* `body` (not `message`) and `kind` is forced to `'surface'`.
|
|
112
|
+
*/
|
|
113
|
+
type SurfaceOptions = Omit<_vessels_types.PushOptions, 'message' | 'kind'> & {
|
|
114
|
+
/** The artifact body — block markdown (tables, lists, blockquotes, bold headings, links). */
|
|
115
|
+
body: string;
|
|
116
|
+
};
|
|
109
117
|
interface PushManyResult {
|
|
110
118
|
ok: true;
|
|
111
119
|
results: Array<{
|
|
@@ -170,6 +178,16 @@ interface UserMessageEvent {
|
|
|
170
178
|
content: string | null;
|
|
171
179
|
createdAt: string;
|
|
172
180
|
}>;
|
|
181
|
+
/**
|
|
182
|
+
* Set when this message arrived while an agent interaction was still live — it
|
|
183
|
+
* expired that card. The "they ignored what I presented and said this instead"
|
|
184
|
+
* signal; null when the message didn't supersede anything.
|
|
185
|
+
*/
|
|
186
|
+
supersededInteraction: {
|
|
187
|
+
messageId: string;
|
|
188
|
+
interactionType: _vessels_types.InteractionType;
|
|
189
|
+
prompt: string | null;
|
|
190
|
+
} | null;
|
|
173
191
|
}
|
|
174
192
|
/**
|
|
175
193
|
* Fired when a human opens a new typed vessel from the app (user-initiated
|
|
@@ -233,6 +251,28 @@ declare class Vessels {
|
|
|
233
251
|
/** Like {@link validatePush}, but for a `pushMany()` broadcast payload. */
|
|
234
252
|
validatePushMany(payload: _vessels_types.PushManyOptions): ValidationResult;
|
|
235
253
|
push(payload: _vessels_types.PushOptions): Promise<PushResponse>;
|
|
254
|
+
/**
|
|
255
|
+
* Create a **surface** — a full-width composed artifact the human reviews and
|
|
256
|
+
* optionally acts on, rendered as one piece: a `title` heading, an optional
|
|
257
|
+
* `card` of glance-facts, a block-markdown `body` (tables, bullet/numbered
|
|
258
|
+
* lists, blockquotes, bold headings, links), and an optional `interaction`
|
|
259
|
+
* (the action bar). Use this for an email/message draft, a quote, an invoice
|
|
260
|
+
* review, a proposal, a report — anything substantial and structured.
|
|
261
|
+
*
|
|
262
|
+
* Sugar over {@link push}: it sets `kind: 'surface'` and maps `body` to the
|
|
263
|
+
* message content. For conversation, status updates and quick questions, use
|
|
264
|
+
* {@link push} instead (a chat **bubble** — the human just replies).
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* await vessels.surface({
|
|
268
|
+
* vessel: 'inv-42',
|
|
269
|
+
* title: 'GreenTurf Invoice #GTL-2025-042',
|
|
270
|
+
* card: { fields: [{ label: 'Amount Due', value: '$7,400' }] },
|
|
271
|
+
* body: 'Invoice is **$1,200 over** the usual rate.\n\n| Item | Amount |\n|---|---:|\n| Overage | +$1,200 |',
|
|
272
|
+
* interaction: vessels.approval({ prompt: 'Approve the $7,400 payment?' }),
|
|
273
|
+
* });
|
|
274
|
+
*/
|
|
275
|
+
surface(options: SurfaceOptions): Promise<PushResponse>;
|
|
236
276
|
pushMany(payload: _vessels_types.PushManyOptions): Promise<PushManyResult>;
|
|
237
277
|
editMessage(messageId: string, patch: _vessels_types.MessagePatch): Promise<{
|
|
238
278
|
ok: true;
|
|
@@ -315,4 +355,4 @@ declare class Vessels {
|
|
|
315
355
|
parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | VesselCreatedEvent | MessageCancelledEvent | null>;
|
|
316
356
|
}
|
|
317
357
|
|
|
318
|
-
export { type ActivityHandle, AgentActivityTypes, type InteractionResponseEvent, type Message, type MessageCancelledEvent, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type StreamHandle, type UserMessageEvent, type ValidationResult, type VesselContext, type VesselCreatedEvent, Vessels, VesselsAuthError, type VesselsConfig, VesselsConflictError, VesselsRateLimitError, VesselsValidationError };
|
|
358
|
+
export { type ActivityHandle, AgentActivityTypes, type InteractionResponseEvent, type Message, type MessageCancelledEvent, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type StreamHandle, type SurfaceOptions, type UserMessageEvent, type ValidationResult, type VesselContext, type VesselCreatedEvent, Vessels, VesselsAuthError, type VesselsConfig, VesselsConflictError, VesselsRateLimitError, VesselsValidationError };
|
package/dist/index.d.ts
CHANGED
|
@@ -106,6 +106,14 @@ interface PushResponse {
|
|
|
106
106
|
/** True when this response is a replay of an earlier request with the same idempotency key. */
|
|
107
107
|
replayed: boolean;
|
|
108
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Options for {@link Vessels.surface}. Same as a push, but the artifact text is
|
|
111
|
+
* `body` (not `message`) and `kind` is forced to `'surface'`.
|
|
112
|
+
*/
|
|
113
|
+
type SurfaceOptions = Omit<_vessels_types.PushOptions, 'message' | 'kind'> & {
|
|
114
|
+
/** The artifact body — block markdown (tables, lists, blockquotes, bold headings, links). */
|
|
115
|
+
body: string;
|
|
116
|
+
};
|
|
109
117
|
interface PushManyResult {
|
|
110
118
|
ok: true;
|
|
111
119
|
results: Array<{
|
|
@@ -170,6 +178,16 @@ interface UserMessageEvent {
|
|
|
170
178
|
content: string | null;
|
|
171
179
|
createdAt: string;
|
|
172
180
|
}>;
|
|
181
|
+
/**
|
|
182
|
+
* Set when this message arrived while an agent interaction was still live — it
|
|
183
|
+
* expired that card. The "they ignored what I presented and said this instead"
|
|
184
|
+
* signal; null when the message didn't supersede anything.
|
|
185
|
+
*/
|
|
186
|
+
supersededInteraction: {
|
|
187
|
+
messageId: string;
|
|
188
|
+
interactionType: _vessels_types.InteractionType;
|
|
189
|
+
prompt: string | null;
|
|
190
|
+
} | null;
|
|
173
191
|
}
|
|
174
192
|
/**
|
|
175
193
|
* Fired when a human opens a new typed vessel from the app (user-initiated
|
|
@@ -233,6 +251,28 @@ declare class Vessels {
|
|
|
233
251
|
/** Like {@link validatePush}, but for a `pushMany()` broadcast payload. */
|
|
234
252
|
validatePushMany(payload: _vessels_types.PushManyOptions): ValidationResult;
|
|
235
253
|
push(payload: _vessels_types.PushOptions): Promise<PushResponse>;
|
|
254
|
+
/**
|
|
255
|
+
* Create a **surface** — a full-width composed artifact the human reviews and
|
|
256
|
+
* optionally acts on, rendered as one piece: a `title` heading, an optional
|
|
257
|
+
* `card` of glance-facts, a block-markdown `body` (tables, bullet/numbered
|
|
258
|
+
* lists, blockquotes, bold headings, links), and an optional `interaction`
|
|
259
|
+
* (the action bar). Use this for an email/message draft, a quote, an invoice
|
|
260
|
+
* review, a proposal, a report — anything substantial and structured.
|
|
261
|
+
*
|
|
262
|
+
* Sugar over {@link push}: it sets `kind: 'surface'` and maps `body` to the
|
|
263
|
+
* message content. For conversation, status updates and quick questions, use
|
|
264
|
+
* {@link push} instead (a chat **bubble** — the human just replies).
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* await vessels.surface({
|
|
268
|
+
* vessel: 'inv-42',
|
|
269
|
+
* title: 'GreenTurf Invoice #GTL-2025-042',
|
|
270
|
+
* card: { fields: [{ label: 'Amount Due', value: '$7,400' }] },
|
|
271
|
+
* body: 'Invoice is **$1,200 over** the usual rate.\n\n| Item | Amount |\n|---|---:|\n| Overage | +$1,200 |',
|
|
272
|
+
* interaction: vessels.approval({ prompt: 'Approve the $7,400 payment?' }),
|
|
273
|
+
* });
|
|
274
|
+
*/
|
|
275
|
+
surface(options: SurfaceOptions): Promise<PushResponse>;
|
|
236
276
|
pushMany(payload: _vessels_types.PushManyOptions): Promise<PushManyResult>;
|
|
237
277
|
editMessage(messageId: string, patch: _vessels_types.MessagePatch): Promise<{
|
|
238
278
|
ok: true;
|
|
@@ -315,4 +355,4 @@ declare class Vessels {
|
|
|
315
355
|
parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | VesselCreatedEvent | MessageCancelledEvent | null>;
|
|
316
356
|
}
|
|
317
357
|
|
|
318
|
-
export { type ActivityHandle, AgentActivityTypes, type InteractionResponseEvent, type Message, type MessageCancelledEvent, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type StreamHandle, type UserMessageEvent, type ValidationResult, type VesselContext, type VesselCreatedEvent, Vessels, VesselsAuthError, type VesselsConfig, VesselsConflictError, VesselsRateLimitError, VesselsValidationError };
|
|
358
|
+
export { type ActivityHandle, AgentActivityTypes, type InteractionResponseEvent, type Message, type MessageCancelledEvent, type OriginMessage, type PollEvent, type PollOptions, type PollResponse, type PushManyResult, type PushResponse, type StreamHandle, type SurfaceOptions, type UserMessageEvent, type ValidationResult, type VesselContext, type VesselCreatedEvent, Vessels, VesselsAuthError, type VesselsConfig, VesselsConflictError, VesselsRateLimitError, VesselsValidationError };
|
package/dist/index.js
CHANGED
|
@@ -73,7 +73,10 @@ var CardFieldSchema = z.object({
|
|
|
73
73
|
value: z.string()
|
|
74
74
|
});
|
|
75
75
|
var CardSchema = z.object({
|
|
76
|
-
|
|
76
|
+
// Optional: a glance-facts card under a surface takes its heading from the
|
|
77
|
+
// surface `title`, so a card title is redundant there. Still allowed (e.g. a
|
|
78
|
+
// standalone card on a bubble, or a pinned card).
|
|
79
|
+
title: z.string().min(1).optional(),
|
|
77
80
|
fields: z.array(CardFieldSchema)
|
|
78
81
|
});
|
|
79
82
|
var AttachmentSchema = z.discriminatedUnion("type", [
|
|
@@ -81,6 +84,8 @@ var AttachmentSchema = z.discriminatedUnion("type", [
|
|
|
81
84
|
z.object({ type: z.literal("file"), url: z.string().url(), filename: z.string().optional() })
|
|
82
85
|
]);
|
|
83
86
|
var VesselStatusSchema = z.enum(["active", "waiting", "resolved"]);
|
|
87
|
+
var DisplaySchema = z.enum(["bubble", "document"]);
|
|
88
|
+
var KindSchema = z.enum(["bubble", "surface"]);
|
|
84
89
|
var PushPayloadSchema = z.object({
|
|
85
90
|
message: z.string().min(1).max(1e4).optional(),
|
|
86
91
|
vessel: z.string().optional(),
|
|
@@ -105,7 +110,13 @@ var PushPayloadSchema = z.object({
|
|
|
105
110
|
* window, not a transcript: send the tail you want shown (the SDK trims to the
|
|
106
111
|
* last 8000 chars). Plaintext, like agentActivity. Vanishes when cleared.
|
|
107
112
|
*/
|
|
108
|
-
tokenStream: z.string().max(8e3).optional()
|
|
113
|
+
tokenStream: z.string().max(8e3).optional(),
|
|
114
|
+
/** Bubble (chat) vs surface (composed artifact). Defaults from interaction/card. */
|
|
115
|
+
kind: KindSchema.optional(),
|
|
116
|
+
/** Surface heading. Ignored on bubbles. */
|
|
117
|
+
title: z.string().max(200).optional(),
|
|
118
|
+
/** @deprecated legacy presentation hint — use `kind`. 'document' → surface. */
|
|
119
|
+
display: DisplaySchema.optional()
|
|
109
120
|
}).refine((d) => d.message || d.agentActivity || d.tokenStream, {
|
|
110
121
|
message: "One of message, agentActivity, or tokenStream is required"
|
|
111
122
|
});
|
|
@@ -122,7 +133,11 @@ var PushManyPayloadSchema = z.object({
|
|
|
122
133
|
metadata: z.record(z.unknown()).refine(
|
|
123
134
|
(v) => JSON.stringify(v).length < 16e3,
|
|
124
135
|
"metadata exceeds 16KB limit"
|
|
125
|
-
).optional()
|
|
136
|
+
).optional(),
|
|
137
|
+
kind: KindSchema.optional(),
|
|
138
|
+
title: z.string().max(200).optional(),
|
|
139
|
+
/** @deprecated use `kind`. */
|
|
140
|
+
display: DisplaySchema.optional()
|
|
126
141
|
});
|
|
127
142
|
z.object({
|
|
128
143
|
content: z.string().min(1).max(1e4).optional(),
|
|
@@ -131,7 +146,13 @@ z.object({
|
|
|
131
146
|
suggestions: z.array(z.string().min(1).max(500)).max(5).nullable().optional(),
|
|
132
147
|
agentActivity: AgentActivitySchema.nullable().optional(),
|
|
133
148
|
/** Replace the live token-stream window, or `null` to clear it (block vanishes). */
|
|
134
|
-
tokenStream: z.string().max(8e3).nullable().optional()
|
|
149
|
+
tokenStream: z.string().max(8e3).nullable().optional(),
|
|
150
|
+
/** Switch kind: 'surface' = full-width artifact, 'bubble' or null = chat bubble. */
|
|
151
|
+
kind: KindSchema.nullable().optional(),
|
|
152
|
+
/** Update the surface heading, or `null` to clear it. */
|
|
153
|
+
title: z.string().max(200).nullable().optional(),
|
|
154
|
+
/** @deprecated use `kind`. */
|
|
155
|
+
display: DisplaySchema.nullable().optional()
|
|
135
156
|
}).refine((d) => Object.values(d).some((v) => v !== void 0), {
|
|
136
157
|
message: "At least one field required"
|
|
137
158
|
});
|
|
@@ -191,6 +212,11 @@ var WebhookInteractionResponsePayloadSchema = z.object({
|
|
|
191
212
|
vessel: WebhookVesselSchema
|
|
192
213
|
})
|
|
193
214
|
});
|
|
215
|
+
var SupersededInteractionSchema = z.object({
|
|
216
|
+
message_id: z.string(),
|
|
217
|
+
interaction_type: InteractionTypeSchema,
|
|
218
|
+
prompt: z.string().nullable()
|
|
219
|
+
});
|
|
194
220
|
var WebhookUserMessagePayloadSchema = z.object({
|
|
195
221
|
event: z.literal("message.user"),
|
|
196
222
|
vessel_id: z.string(),
|
|
@@ -200,7 +226,8 @@ var WebhookUserMessagePayloadSchema = z.object({
|
|
|
200
226
|
message_id: z.string(),
|
|
201
227
|
content: z.string(),
|
|
202
228
|
vessel: WebhookVesselSchema,
|
|
203
|
-
context: z.array(WebhookContextMessageSchema)
|
|
229
|
+
context: z.array(WebhookContextMessageSchema),
|
|
230
|
+
superseded_interaction: SupersededInteractionSchema.optional()
|
|
204
231
|
})
|
|
205
232
|
});
|
|
206
233
|
var WebhookVesselCreatedPayloadSchema = z.object({
|
|
@@ -359,6 +386,31 @@ var Vessels = class {
|
|
|
359
386
|
replayed: res.headers.get("Idempotent-Replayed") === "true"
|
|
360
387
|
};
|
|
361
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Create a **surface** — a full-width composed artifact the human reviews and
|
|
391
|
+
* optionally acts on, rendered as one piece: a `title` heading, an optional
|
|
392
|
+
* `card` of glance-facts, a block-markdown `body` (tables, bullet/numbered
|
|
393
|
+
* lists, blockquotes, bold headings, links), and an optional `interaction`
|
|
394
|
+
* (the action bar). Use this for an email/message draft, a quote, an invoice
|
|
395
|
+
* review, a proposal, a report — anything substantial and structured.
|
|
396
|
+
*
|
|
397
|
+
* Sugar over {@link push}: it sets `kind: 'surface'` and maps `body` to the
|
|
398
|
+
* message content. For conversation, status updates and quick questions, use
|
|
399
|
+
* {@link push} instead (a chat **bubble** — the human just replies).
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* await vessels.surface({
|
|
403
|
+
* vessel: 'inv-42',
|
|
404
|
+
* title: 'GreenTurf Invoice #GTL-2025-042',
|
|
405
|
+
* card: { fields: [{ label: 'Amount Due', value: '$7,400' }] },
|
|
406
|
+
* body: 'Invoice is **$1,200 over** the usual rate.\n\n| Item | Amount |\n|---|---:|\n| Overage | +$1,200 |',
|
|
407
|
+
* interaction: vessels.approval({ prompt: 'Approve the $7,400 payment?' }),
|
|
408
|
+
* });
|
|
409
|
+
*/
|
|
410
|
+
async surface(options) {
|
|
411
|
+
const { body, ...rest } = options;
|
|
412
|
+
return this.push({ ...rest, message: body, kind: "surface" });
|
|
413
|
+
}
|
|
362
414
|
async pushMany(payload) {
|
|
363
415
|
const { idempotencyKey, ...body } = payload;
|
|
364
416
|
const check = PushManyPayloadSchema.safeParse(body);
|
|
@@ -621,7 +673,12 @@ var Vessels = class {
|
|
|
621
673
|
timestamp: e.timestamp,
|
|
622
674
|
vessel,
|
|
623
675
|
message: { id: e.message?.id, content: e.message?.content ?? null },
|
|
624
|
-
context: []
|
|
676
|
+
context: [],
|
|
677
|
+
supersededInteraction: e.superseded_interaction ? {
|
|
678
|
+
messageId: e.superseded_interaction.message_id,
|
|
679
|
+
interactionType: e.superseded_interaction.interaction_type,
|
|
680
|
+
prompt: e.superseded_interaction.prompt ?? null
|
|
681
|
+
} : null
|
|
625
682
|
};
|
|
626
683
|
});
|
|
627
684
|
return { ok: true, events, hasMore: data.has_more ?? false };
|
|
@@ -722,7 +779,12 @@ var Vessels = class {
|
|
|
722
779
|
source: m.source,
|
|
723
780
|
content: m.content ?? null,
|
|
724
781
|
createdAt: m.created_at
|
|
725
|
-
}))
|
|
782
|
+
})),
|
|
783
|
+
supersededInteraction: raw.data.superseded_interaction ? {
|
|
784
|
+
messageId: raw.data.superseded_interaction.message_id,
|
|
785
|
+
interactionType: raw.data.superseded_interaction.interaction_type,
|
|
786
|
+
prompt: raw.data.superseded_interaction.prompt ?? null
|
|
787
|
+
} : null
|
|
726
788
|
};
|
|
727
789
|
}
|
|
728
790
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vessels-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Let your agent reach you. Official Vessels SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -20,7 +20,13 @@
|
|
|
20
20
|
"build": "tsup",
|
|
21
21
|
"dev": "tsup --watch"
|
|
22
22
|
},
|
|
23
|
-
"keywords": [
|
|
23
|
+
"keywords": [
|
|
24
|
+
"ai",
|
|
25
|
+
"agents",
|
|
26
|
+
"vessels",
|
|
27
|
+
"llm",
|
|
28
|
+
"notifications"
|
|
29
|
+
],
|
|
24
30
|
"license": "MIT",
|
|
25
31
|
"dependencies": {
|
|
26
32
|
"zod": "^3.22"
|