vessels-sdk 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,14 +38,20 @@ const { messageId, vesselId } = await vessels.push({
38
38
  });
39
39
  ```
40
40
 
41
- Get your API key from Settings API Keys in the [Vessels app](https://vessels.app), or via the CLI:
41
+ Get your API key via the CLI (Claude Code / AI assistants fully non-interactive):
42
42
 
43
43
  ```bash
44
44
  npm install -g vessels
45
- vessels login
46
- vessels keys create
45
+
46
+ # Step 1: send OTP to your email
47
+ vessels init --email me@example.com
48
+
49
+ # Step 2: verify with the code from your inbox — prints VESSELS_API_KEY=vsl_xxx
50
+ vessels init --email me@example.com --otp 847293
47
51
  ```
48
52
 
53
+ Or sign in at [vessels.app](https://vessels.app) → Settings → API Keys.
54
+
49
55
  ---
50
56
 
51
57
  ## API reference
package/dist/index.cjs CHANGED
@@ -3,6 +3,14 @@
3
3
  var zod = require('zod');
4
4
 
5
5
  // ../types/src/index.ts
6
+ var SourceSchema = zod.z.enum(["agent", "user", "system"]);
7
+ var InteractionTypeSchema = zod.z.enum([
8
+ "approval",
9
+ "choice",
10
+ "checklist",
11
+ "text_input",
12
+ "confirm_preview"
13
+ ]);
6
14
  var ApprovalInteractionSchema = zod.z.object({
7
15
  type: zod.z.literal("approval"),
8
16
  prompt: zod.z.string().min(1),
@@ -155,8 +163,15 @@ var WebhookVesselSchema = zod.z.object({
155
163
  metadata: zod.z.record(zod.z.unknown())
156
164
  });
157
165
  var WebhookContextMessageSchema = zod.z.object({
158
- source: zod.z.string(),
166
+ source: SourceSchema,
167
+ content: zod.z.string().nullable(),
168
+ created_at: zod.z.string()
169
+ });
170
+ var WebhookOriginMessageSchema = zod.z.object({
171
+ id: zod.z.string(),
159
172
  content: zod.z.string().nullable(),
173
+ interaction: zod.z.record(zod.z.unknown()).nullable(),
174
+ metadata: zod.z.record(zod.z.unknown()),
160
175
  created_at: zod.z.string()
161
176
  });
162
177
  var WebhookInteractionResponsePayloadSchema = zod.z.object({
@@ -166,10 +181,12 @@ var WebhookInteractionResponsePayloadSchema = zod.z.object({
166
181
  timestamp: zod.z.string(),
167
182
  data: zod.z.object({
168
183
  message_id: zod.z.string(),
169
- interaction_type: zod.z.string(),
184
+ interaction_type: InteractionTypeSchema,
170
185
  response: zod.z.record(zod.z.unknown()),
171
186
  response_id: zod.z.string(),
172
187
  metadata: zod.z.record(zod.z.unknown()).optional(),
188
+ /** The agent message that carried the interaction (prompt, content, metadata). */
189
+ message: WebhookOriginMessageSchema,
173
190
  vessel: WebhookVesselSchema
174
191
  })
175
192
  });
@@ -314,6 +331,38 @@ var Vessels = class {
314
331
  if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
315
332
  return { ok: true };
316
333
  }
334
+ /**
335
+ * Read a vessel's message history — the human-facing record, for re-reading
336
+ * the channel (e.g. a stateless or just-restarted worker reconciling state).
337
+ * This is NOT your agent's memory; keep your canonical history in your own
338
+ * system. `vessel` is your own external_id string by default; pass
339
+ * { byUuid: true } if you hold a Vessels UUID. Newest-last, paginate with `before`.
340
+ */
341
+ async getMessages(opts) {
342
+ const params = new URLSearchParams();
343
+ if (opts.limit != null) params.set("limit", String(opts.limit));
344
+ if (opts.before) params.set("before", opts.before);
345
+ const path = opts.byUuid ? `/api/v1/vessels/${encodeURIComponent(opts.vessel)}/messages` : `/api/v1/vessels/by-external/${encodeURIComponent(opts.vessel)}/messages`;
346
+ const res = await this._fetch(`${this.baseUrl}${path}?${params}`, {
347
+ headers: { "Authorization": `Bearer ${this.apiKey}` }
348
+ });
349
+ const data = await res.json();
350
+ if (res.status === 401) throw new VesselsAuthError(data.error ?? "Unauthorized");
351
+ if (res.status === 404) throw new Error(data.error ?? "Vessel not found");
352
+ if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
353
+ const messages = (data.messages ?? []).map((m) => ({
354
+ id: m.id,
355
+ source: m.source,
356
+ content: m.content ?? null,
357
+ card: m.card ?? null,
358
+ interaction: m.interaction ?? null,
359
+ attachments: m.attachments ?? [],
360
+ suggestions: m.suggestions ?? [],
361
+ metadata: m.metadata ?? {},
362
+ createdAt: m.created_at
363
+ }));
364
+ return { messages, hasMore: data.has_more ?? false };
365
+ }
317
366
  // Interaction helpers
318
367
  approval(opts) {
319
368
  return { type: "approval", ...opts };
@@ -360,6 +409,13 @@ var Vessels = class {
360
409
  interactionType: e.interaction_type,
361
410
  response: e.response,
362
411
  interactionMetadata: e.interaction_metadata ?? null,
412
+ originMessage: e.message ? {
413
+ id: e.message.id,
414
+ content: e.message.content ?? null,
415
+ interaction: e.message.interaction ?? null,
416
+ metadata: e.message.metadata ?? {},
417
+ createdAt: e.message.created_at
418
+ } : null,
363
419
  user: e.user ?? null
364
420
  };
365
421
  }
@@ -427,6 +483,13 @@ var Vessels = class {
427
483
  interactionType: raw.data.interaction_type,
428
484
  response: raw.data.response,
429
485
  interactionMetadata: raw.data.metadata ?? null,
486
+ originMessage: raw.data.message ? {
487
+ id: raw.data.message.id,
488
+ content: raw.data.message.content ?? null,
489
+ interaction: raw.data.message.interaction ?? null,
490
+ metadata: raw.data.message.metadata ?? {},
491
+ createdAt: raw.data.message.created_at
492
+ } : null,
430
493
  user: raw.data.user ?? null
431
494
  };
432
495
  }
package/dist/index.d.cts CHANGED
@@ -51,15 +51,26 @@ interface VesselContext {
51
51
  metadata: Record<string, unknown>;
52
52
  labels: string[];
53
53
  }
54
+ /** The agent message an interaction was attached to. */
55
+ interface OriginMessage {
56
+ id: string;
57
+ content: string | null;
58
+ /** The interaction object you originally pushed (type, prompt, options, labels…). */
59
+ interaction: Record<string, unknown> | null;
60
+ metadata: Record<string, unknown>;
61
+ createdAt: string;
62
+ }
54
63
  interface InteractionResponseEvent {
55
64
  id: string;
56
65
  type: 'interaction.response';
57
66
  timestamp: string;
58
67
  vessel: VesselContext;
59
68
  messageId: string;
60
- interactionType: string;
69
+ interactionType: _vessels_types.InteractionType;
61
70
  response: Record<string, unknown>;
62
71
  interactionMetadata: Record<string, unknown> | null;
72
+ /** The message that carried the interaction — so you know WHAT was responded to. */
73
+ originMessage: OriginMessage | null;
63
74
  user: {
64
75
  id: string;
65
76
  email: string;
@@ -75,11 +86,23 @@ interface UserMessageEvent {
75
86
  content: string | null;
76
87
  };
77
88
  context: Array<{
78
- source: string;
89
+ source: _vessels_types.Source;
79
90
  content: string | null;
80
91
  createdAt: string;
81
92
  }>;
82
93
  }
94
+ /** A message in a vessel, as returned by getMessages — the human-facing record. */
95
+ interface Message {
96
+ id: string;
97
+ source: _vessels_types.Source;
98
+ content: string | null;
99
+ card: Record<string, unknown> | null;
100
+ interaction: Record<string, unknown> | null;
101
+ attachments: Array<Record<string, unknown>>;
102
+ suggestions: string[];
103
+ metadata: Record<string, unknown>;
104
+ createdAt: string;
105
+ }
83
106
  type PollEvent = InteractionResponseEvent | UserMessageEvent;
84
107
  interface PollResponse {
85
108
  ok: true;
@@ -97,6 +120,22 @@ declare class Vessels {
97
120
  editMessage(messageId: string, patch: _vessels_types.MessagePatch): Promise<{
98
121
  ok: true;
99
122
  }>;
123
+ /**
124
+ * Read a vessel's message history — the human-facing record, for re-reading
125
+ * the channel (e.g. a stateless or just-restarted worker reconciling state).
126
+ * This is NOT your agent's memory; keep your canonical history in your own
127
+ * system. `vessel` is your own external_id string by default; pass
128
+ * { byUuid: true } if you hold a Vessels UUID. Newest-last, paginate with `before`.
129
+ */
130
+ getMessages(opts: {
131
+ vessel: string;
132
+ byUuid?: boolean;
133
+ limit?: number;
134
+ before?: string;
135
+ }): Promise<{
136
+ messages: Message[];
137
+ hasMore: boolean;
138
+ }>;
100
139
  approval(opts: {
101
140
  prompt: string;
102
141
  approveLabel?: string;
@@ -146,4 +185,4 @@ declare class Vessels {
146
185
  parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | null>;
147
186
  }
148
187
 
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 };
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 };
package/dist/index.d.ts CHANGED
@@ -51,15 +51,26 @@ interface VesselContext {
51
51
  metadata: Record<string, unknown>;
52
52
  labels: string[];
53
53
  }
54
+ /** The agent message an interaction was attached to. */
55
+ interface OriginMessage {
56
+ id: string;
57
+ content: string | null;
58
+ /** The interaction object you originally pushed (type, prompt, options, labels…). */
59
+ interaction: Record<string, unknown> | null;
60
+ metadata: Record<string, unknown>;
61
+ createdAt: string;
62
+ }
54
63
  interface InteractionResponseEvent {
55
64
  id: string;
56
65
  type: 'interaction.response';
57
66
  timestamp: string;
58
67
  vessel: VesselContext;
59
68
  messageId: string;
60
- interactionType: string;
69
+ interactionType: _vessels_types.InteractionType;
61
70
  response: Record<string, unknown>;
62
71
  interactionMetadata: Record<string, unknown> | null;
72
+ /** The message that carried the interaction — so you know WHAT was responded to. */
73
+ originMessage: OriginMessage | null;
63
74
  user: {
64
75
  id: string;
65
76
  email: string;
@@ -75,11 +86,23 @@ interface UserMessageEvent {
75
86
  content: string | null;
76
87
  };
77
88
  context: Array<{
78
- source: string;
89
+ source: _vessels_types.Source;
79
90
  content: string | null;
80
91
  createdAt: string;
81
92
  }>;
82
93
  }
94
+ /** A message in a vessel, as returned by getMessages — the human-facing record. */
95
+ interface Message {
96
+ id: string;
97
+ source: _vessels_types.Source;
98
+ content: string | null;
99
+ card: Record<string, unknown> | null;
100
+ interaction: Record<string, unknown> | null;
101
+ attachments: Array<Record<string, unknown>>;
102
+ suggestions: string[];
103
+ metadata: Record<string, unknown>;
104
+ createdAt: string;
105
+ }
83
106
  type PollEvent = InteractionResponseEvent | UserMessageEvent;
84
107
  interface PollResponse {
85
108
  ok: true;
@@ -97,6 +120,22 @@ declare class Vessels {
97
120
  editMessage(messageId: string, patch: _vessels_types.MessagePatch): Promise<{
98
121
  ok: true;
99
122
  }>;
123
+ /**
124
+ * Read a vessel's message history — the human-facing record, for re-reading
125
+ * the channel (e.g. a stateless or just-restarted worker reconciling state).
126
+ * This is NOT your agent's memory; keep your canonical history in your own
127
+ * system. `vessel` is your own external_id string by default; pass
128
+ * { byUuid: true } if you hold a Vessels UUID. Newest-last, paginate with `before`.
129
+ */
130
+ getMessages(opts: {
131
+ vessel: string;
132
+ byUuid?: boolean;
133
+ limit?: number;
134
+ before?: string;
135
+ }): Promise<{
136
+ messages: Message[];
137
+ hasMore: boolean;
138
+ }>;
100
139
  approval(opts: {
101
140
  prompt: string;
102
141
  approveLabel?: string;
@@ -146,4 +185,4 @@ declare class Vessels {
146
185
  parseWebhookEvent(body: string, signature: string, webhookSecret: string): Promise<InteractionResponseEvent | UserMessageEvent | null>;
147
186
  }
148
187
 
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 };
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 };
package/dist/index.js CHANGED
@@ -1,6 +1,14 @@
1
1
  import { z } from 'zod';
2
2
 
3
3
  // ../types/src/index.ts
4
+ var SourceSchema = z.enum(["agent", "user", "system"]);
5
+ var InteractionTypeSchema = z.enum([
6
+ "approval",
7
+ "choice",
8
+ "checklist",
9
+ "text_input",
10
+ "confirm_preview"
11
+ ]);
4
12
  var ApprovalInteractionSchema = z.object({
5
13
  type: z.literal("approval"),
6
14
  prompt: z.string().min(1),
@@ -153,8 +161,15 @@ var WebhookVesselSchema = z.object({
153
161
  metadata: z.record(z.unknown())
154
162
  });
155
163
  var WebhookContextMessageSchema = z.object({
156
- source: z.string(),
164
+ source: SourceSchema,
165
+ content: z.string().nullable(),
166
+ created_at: z.string()
167
+ });
168
+ var WebhookOriginMessageSchema = z.object({
169
+ id: z.string(),
157
170
  content: z.string().nullable(),
171
+ interaction: z.record(z.unknown()).nullable(),
172
+ metadata: z.record(z.unknown()),
158
173
  created_at: z.string()
159
174
  });
160
175
  var WebhookInteractionResponsePayloadSchema = z.object({
@@ -164,10 +179,12 @@ var WebhookInteractionResponsePayloadSchema = z.object({
164
179
  timestamp: z.string(),
165
180
  data: z.object({
166
181
  message_id: z.string(),
167
- interaction_type: z.string(),
182
+ interaction_type: InteractionTypeSchema,
168
183
  response: z.record(z.unknown()),
169
184
  response_id: z.string(),
170
185
  metadata: z.record(z.unknown()).optional(),
186
+ /** The agent message that carried the interaction (prompt, content, metadata). */
187
+ message: WebhookOriginMessageSchema,
171
188
  vessel: WebhookVesselSchema
172
189
  })
173
190
  });
@@ -312,6 +329,38 @@ var Vessels = class {
312
329
  if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
313
330
  return { ok: true };
314
331
  }
332
+ /**
333
+ * Read a vessel's message history — the human-facing record, for re-reading
334
+ * the channel (e.g. a stateless or just-restarted worker reconciling state).
335
+ * This is NOT your agent's memory; keep your canonical history in your own
336
+ * system. `vessel` is your own external_id string by default; pass
337
+ * { byUuid: true } if you hold a Vessels UUID. Newest-last, paginate with `before`.
338
+ */
339
+ async getMessages(opts) {
340
+ const params = new URLSearchParams();
341
+ if (opts.limit != null) params.set("limit", String(opts.limit));
342
+ if (opts.before) params.set("before", opts.before);
343
+ const path = opts.byUuid ? `/api/v1/vessels/${encodeURIComponent(opts.vessel)}/messages` : `/api/v1/vessels/by-external/${encodeURIComponent(opts.vessel)}/messages`;
344
+ const res = await this._fetch(`${this.baseUrl}${path}?${params}`, {
345
+ headers: { "Authorization": `Bearer ${this.apiKey}` }
346
+ });
347
+ const data = await res.json();
348
+ if (res.status === 401) throw new VesselsAuthError(data.error ?? "Unauthorized");
349
+ if (res.status === 404) throw new Error(data.error ?? "Vessel not found");
350
+ if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
351
+ const messages = (data.messages ?? []).map((m) => ({
352
+ id: m.id,
353
+ source: m.source,
354
+ content: m.content ?? null,
355
+ card: m.card ?? null,
356
+ interaction: m.interaction ?? null,
357
+ attachments: m.attachments ?? [],
358
+ suggestions: m.suggestions ?? [],
359
+ metadata: m.metadata ?? {},
360
+ createdAt: m.created_at
361
+ }));
362
+ return { messages, hasMore: data.has_more ?? false };
363
+ }
315
364
  // Interaction helpers
316
365
  approval(opts) {
317
366
  return { type: "approval", ...opts };
@@ -358,6 +407,13 @@ var Vessels = class {
358
407
  interactionType: e.interaction_type,
359
408
  response: e.response,
360
409
  interactionMetadata: e.interaction_metadata ?? null,
410
+ originMessage: e.message ? {
411
+ id: e.message.id,
412
+ content: e.message.content ?? null,
413
+ interaction: e.message.interaction ?? null,
414
+ metadata: e.message.metadata ?? {},
415
+ createdAt: e.message.created_at
416
+ } : null,
361
417
  user: e.user ?? null
362
418
  };
363
419
  }
@@ -425,6 +481,13 @@ var Vessels = class {
425
481
  interactionType: raw.data.interaction_type,
426
482
  response: raw.data.response,
427
483
  interactionMetadata: raw.data.metadata ?? null,
484
+ originMessage: raw.data.message ? {
485
+ id: raw.data.message.id,
486
+ content: raw.data.message.content ?? null,
487
+ interaction: raw.data.message.interaction ?? null,
488
+ metadata: raw.data.message.metadata ?? {},
489
+ createdAt: raw.data.message.created_at
490
+ } : null,
428
491
  user: raw.data.user ?? null
429
492
  };
430
493
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vessels-sdk",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Let your agent reach you. Official Vessels SDK.",
5
5
  "type": "module",
6
6
  "exports": {