@ragable/sdk 0.7.8 → 0.7.10

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.js CHANGED
@@ -47,6 +47,7 @@ __export(index_exports, {
47
47
  RagableBrowserAiClient: () => RagableBrowserAiClient,
48
48
  RagableBrowserAuthClient: () => RagableBrowserAuthClient,
49
49
  RagableBrowserDatabaseClient: () => RagableBrowserDatabaseClient,
50
+ RagableBrowserMailClient: () => RagableBrowserMailClient,
50
51
  RagableBrowserStorageClient: () => RagableBrowserStorageClient,
51
52
  RagableError: () => RagableError,
52
53
  RagableNetworkError: () => RagableNetworkError,
@@ -59,6 +60,7 @@ __export(index_exports, {
59
60
  bindFetch: () => bindFetch,
60
61
  buildInferenceRequestBody: () => buildInferenceRequestBody,
61
62
  buildResponseFormat: () => buildResponseFormat,
63
+ bytesToBase64: () => bytesToBase64,
62
64
  collectAssistantTextFromUiSegments: () => collectAssistantTextFromUiSegments,
63
65
  collectionRecordToRowWithMeta: () => collectionRecordToRowWithMeta,
64
66
  collectionRecordsToRowWithMeta: () => collectionRecordsToRowWithMeta,
@@ -74,6 +76,7 @@ __export(index_exports, {
74
76
  formatPostgrestError: () => formatPostgrestError,
75
77
  formatSdkError: () => formatSdkError,
76
78
  generateIdempotencyKey: () => generateIdempotencyKey,
79
+ imagePartToUrl: () => imagePartToUrl,
77
80
  isIncompleteAgentStreamError: () => isIncompleteAgentStreamError,
78
81
  mapAgentEvent: () => mapAgentEvent,
79
82
  mapFireworksChunk: () => mapFireworksChunk,
@@ -88,6 +91,7 @@ __export(index_exports, {
88
91
  runAgentChatStreamLenient: () => runAgentChatStreamLenient,
89
92
  streamObjectFromContext: () => streamObjectFromContext,
90
93
  toRagableResult: () => toRagableResult,
94
+ toWireUserContent: () => toWireUserContent,
91
95
  tryParsePartialJson: () => tryParsePartialJson,
92
96
  unwrapPostgrest: () => unwrapPostgrest,
93
97
  wrapStreamTextAsObject: () => wrapStreamTextAsObject
@@ -2427,6 +2431,95 @@ function stripTrailingCommas(text) {
2427
2431
  return text.replace(/,(\s*[}\]])/g, "$1").replace(/,\s*$/, "");
2428
2432
  }
2429
2433
 
2434
+ // src/content.ts
2435
+ var MAX_IMAGE_BYTES = 5 * 1024 * 1024;
2436
+ function toWireUserContent(content) {
2437
+ if (typeof content === "string") return content;
2438
+ const out = [];
2439
+ for (const part of content) {
2440
+ if (!part) continue;
2441
+ if (part.type === "text") {
2442
+ out.push(toWireTextPart(part));
2443
+ } else if (part.type === "image") {
2444
+ out.push(toWireImagePart(part));
2445
+ }
2446
+ }
2447
+ return out;
2448
+ }
2449
+ function toWireTextPart(part) {
2450
+ return { type: "text", text: part.text };
2451
+ }
2452
+ function toWireImagePart(part) {
2453
+ const url = imagePartToUrl(part);
2454
+ const detail = part.detail;
2455
+ return {
2456
+ type: "image_url",
2457
+ image_url: detail ? { url, detail } : { url }
2458
+ };
2459
+ }
2460
+ function imagePartToUrl(part) {
2461
+ const img = part.image;
2462
+ if (img instanceof URL) return img.href;
2463
+ if (typeof img === "string") {
2464
+ if (img.startsWith("http://") || img.startsWith("https://")) return img;
2465
+ if (img.startsWith("data:")) return img;
2466
+ const mediaType = requireMediaType(part, "raw base64 string");
2467
+ assertBase64SizeOk(img);
2468
+ return `data:${mediaType};base64,${img}`;
2469
+ }
2470
+ if (img instanceof Uint8Array || img instanceof ArrayBuffer) {
2471
+ const bytes = img instanceof Uint8Array ? img : new Uint8Array(img);
2472
+ assertBinarySizeOk(bytes);
2473
+ const mediaType = requireMediaType(part, "binary image data");
2474
+ const b64 = bytesToBase64(bytes);
2475
+ return `data:${mediaType};base64,${b64}`;
2476
+ }
2477
+ throw new RagableError(
2478
+ "ImagePart.image must be a string, URL, Uint8Array, or ArrayBuffer",
2479
+ 400,
2480
+ { code: "SDK_INVALID_IMAGE_PART" }
2481
+ );
2482
+ }
2483
+ function requireMediaType(part, what) {
2484
+ const m = part.mediaType?.trim();
2485
+ if (!m) {
2486
+ throw new RagableError(
2487
+ `ImagePart.mediaType is required for ${what} (e.g. "image/png")`,
2488
+ 400,
2489
+ { code: "SDK_IMAGE_MEDIA_TYPE_REQUIRED" }
2490
+ );
2491
+ }
2492
+ return m;
2493
+ }
2494
+ function assertBinarySizeOk(bytes) {
2495
+ if (bytes.byteLength > MAX_IMAGE_BYTES) {
2496
+ throw new RagableError(
2497
+ `Image exceeds 5MB limit (${bytes.byteLength} bytes)`,
2498
+ 400,
2499
+ { code: "SDK_IMAGE_TOO_LARGE" }
2500
+ );
2501
+ }
2502
+ }
2503
+ function assertBase64SizeOk(b64) {
2504
+ const approxBytes = Math.floor(b64.length * 3 / 4);
2505
+ if (approxBytes > MAX_IMAGE_BYTES) {
2506
+ throw new RagableError(
2507
+ `Image exceeds 5MB limit (~${approxBytes} bytes decoded)`,
2508
+ 400,
2509
+ { code: "SDK_IMAGE_TOO_LARGE" }
2510
+ );
2511
+ }
2512
+ }
2513
+ function bytesToBase64(bytes) {
2514
+ const CHUNK = 32768;
2515
+ let binary = "";
2516
+ for (let i = 0; i < bytes.length; i += CHUNK) {
2517
+ const slice = bytes.subarray(i, i + CHUNK);
2518
+ binary += String.fromCharCode(...slice);
2519
+ }
2520
+ return btoa(binary);
2521
+ }
2522
+
2430
2523
  // src/stream-parts.ts
2431
2524
  function normalizeFinishReason(raw) {
2432
2525
  switch (raw) {
@@ -2639,7 +2732,9 @@ var ZERO_USAGE = {
2639
2732
  function buildInferenceRequestBody(params, responseFormat) {
2640
2733
  const body = {
2641
2734
  model: params.model,
2642
- messages: params.messages
2735
+ messages: params.messages.map(
2736
+ (m) => m.role === "user" ? { role: "user", content: toWireUserContent(m.content) } : m
2737
+ )
2643
2738
  };
2644
2739
  if (params.system !== void 0) body.system = params.system;
2645
2740
  if (typeof params.temperature === "number")
@@ -3874,6 +3969,120 @@ var RagableBrowserStorageClient = class {
3874
3969
  return new BrowserStorageBucketClient(this.options, this.fetchImpl, bucketId);
3875
3970
  }
3876
3971
  };
3972
+ var RagableBrowserMailClient = class {
3973
+ constructor(options, auth) {
3974
+ this.options = options;
3975
+ this.auth = auth;
3976
+ __publicField(this, "fetchImpl");
3977
+ this.fetchImpl = bindFetch(options.fetch);
3978
+ }
3979
+ requireWebsiteId() {
3980
+ const websiteId = this.options.websiteId?.trim();
3981
+ if (!websiteId) {
3982
+ throw new RagableError(
3983
+ "websiteId is required for mail operations. Use createWebsiteRagableClient() or pass createBrowserClient({ websiteId, ... }).",
3984
+ 400,
3985
+ { code: "SDK_MISSING_WEBSITE_ID" }
3986
+ );
3987
+ }
3988
+ return websiteId;
3989
+ }
3990
+ pathTo(p) {
3991
+ const websiteId = this.requireWebsiteId();
3992
+ const orgId = this.options.organizationId;
3993
+ return `${normalizeBrowserApiBase()}/public/organizations/${orgId}/websites/${websiteId}/mail${p.startsWith("/") ? p : `/${p}`}`;
3994
+ }
3995
+ /**
3996
+ * Get the Bearer token used to authenticate the call:
3997
+ * 1. End-user access token (preferred when an auth group is configured
3998
+ * and the user has signed in)
3999
+ * 2. `dataStaticKey` from createBrowserClient options
4000
+ * 3. Caller-supplied `getAccessToken()`
4001
+ *
4002
+ * If none is available, throws — server-side use should pass the
4003
+ * data-admin key as `dataStaticKey`.
4004
+ */
4005
+ async getBearerToken() {
4006
+ if (this.auth) {
4007
+ const token = await this.auth.getValidAccessToken().catch(() => null);
4008
+ if (token) return token;
4009
+ }
4010
+ const callerProvided = await this.options.getAccessToken?.();
4011
+ if (typeof callerProvided === "string" && callerProvided.length > 0) {
4012
+ return callerProvided;
4013
+ }
4014
+ if (this.options.dataStaticKey?.trim()) {
4015
+ return this.options.dataStaticKey.trim();
4016
+ }
4017
+ throw new RagableError(
4018
+ "Mail requests need authentication: either sign in via client.auth.signIn(...) or pass dataStaticKey (the auth group data-admin key) when creating the client.",
4019
+ 401,
4020
+ { code: "SDK_MAIL_NOT_AUTHENTICATED" }
4021
+ );
4022
+ }
4023
+ async request(path, init = {}) {
4024
+ const token = await this.getBearerToken();
4025
+ const headers = new Headers(init.headers ?? this.options.headers);
4026
+ headers.set("Authorization", `Bearer ${token}`);
4027
+ if (init.body && !headers.has("Content-Type")) {
4028
+ headers.set("Content-Type", "application/json");
4029
+ }
4030
+ const response = await this.fetchImpl(this.pathTo(path), {
4031
+ ...init,
4032
+ headers
4033
+ });
4034
+ const payload = await parseMaybeJsonBody(response);
4035
+ if (!response.ok) {
4036
+ const message = extractErrorMessage(payload, response.statusText);
4037
+ throw new RagableError(message, response.status, payload);
4038
+ }
4039
+ return payload;
4040
+ }
4041
+ /** Send an email from this website's linked Gmail account. */
4042
+ async send(params) {
4043
+ if (!params.to?.length) {
4044
+ throw new RagableError(
4045
+ "`to` must contain at least one recipient.",
4046
+ 400,
4047
+ { code: "SDK_MAIL_NO_RECIPIENTS" }
4048
+ );
4049
+ }
4050
+ if (!params.bodyText && !params.bodyHtml) {
4051
+ throw new RagableError(
4052
+ "Provide at least one of `bodyText` or `bodyHtml`.",
4053
+ 400,
4054
+ { code: "SDK_MAIL_NO_BODY" }
4055
+ );
4056
+ }
4057
+ return this.request("/send", {
4058
+ method: "POST",
4059
+ body: JSON.stringify(params)
4060
+ });
4061
+ }
4062
+ /** Search messages with Gmail query syntax. */
4063
+ async search(params = {}) {
4064
+ const qs = new URLSearchParams();
4065
+ if (params.query) qs.set("q", params.query);
4066
+ if (params.maxResults) qs.set("maxResults", String(params.maxResults));
4067
+ if (params.pageToken) qs.set("pageToken", params.pageToken);
4068
+ if (params.labelIds?.length) qs.set("labelIds", params.labelIds.join(","));
4069
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
4070
+ return this.request(`/search${suffix}`, { method: "GET" });
4071
+ }
4072
+ /** Fetch a single message in full (headers + decoded text/html body). */
4073
+ async getMessage(messageId) {
4074
+ if (!messageId) {
4075
+ throw new RagableError("`messageId` is required.", 400, {
4076
+ code: "SDK_MAIL_NO_MESSAGE_ID"
4077
+ });
4078
+ }
4079
+ const { message } = await this.request(
4080
+ `/messages/${encodeURIComponent(messageId)}`,
4081
+ { method: "GET" }
4082
+ );
4083
+ return message;
4084
+ }
4085
+ };
3877
4086
  var RagableBrowserAgentsClient = class {
3878
4087
  constructor(options) {
3879
4088
  this.options = options;
@@ -4200,6 +4409,7 @@ var RagableBrowser = class {
4200
4409
  __publicField(this, "database");
4201
4410
  __publicField(this, "db");
4202
4411
  __publicField(this, "storage");
4412
+ __publicField(this, "mail");
4203
4413
  __publicField(this, "transport");
4204
4414
  __publicField(this, "_ragableAuth");
4205
4415
  /** Delegates to `database.from()`. Kept for back-compat — prefer `database.from()`. */
@@ -4245,6 +4455,7 @@ var RagableBrowser = class {
4245
4455
  this.database._setTransport(this.transport);
4246
4456
  this.db = this.database;
4247
4457
  this.storage = new RagableBrowserStorageClient(options, bindFetch(options.fetch));
4458
+ this.mail = new RagableBrowserMailClient(options, this._ragableAuth);
4248
4459
  }
4249
4460
  destroy() {
4250
4461
  this._ragableAuth?.destroy();
@@ -4286,6 +4497,7 @@ function createClient(options) {
4286
4497
  RagableBrowserAiClient,
4287
4498
  RagableBrowserAuthClient,
4288
4499
  RagableBrowserDatabaseClient,
4500
+ RagableBrowserMailClient,
4289
4501
  RagableBrowserStorageClient,
4290
4502
  RagableError,
4291
4503
  RagableNetworkError,
@@ -4298,6 +4510,7 @@ function createClient(options) {
4298
4510
  bindFetch,
4299
4511
  buildInferenceRequestBody,
4300
4512
  buildResponseFormat,
4513
+ bytesToBase64,
4301
4514
  collectAssistantTextFromUiSegments,
4302
4515
  collectionRecordToRowWithMeta,
4303
4516
  collectionRecordsToRowWithMeta,
@@ -4313,6 +4526,7 @@ function createClient(options) {
4313
4526
  formatPostgrestError,
4314
4527
  formatSdkError,
4315
4528
  generateIdempotencyKey,
4529
+ imagePartToUrl,
4316
4530
  isIncompleteAgentStreamError,
4317
4531
  mapAgentEvent,
4318
4532
  mapFireworksChunk,
@@ -4327,6 +4541,7 @@ function createClient(options) {
4327
4541
  runAgentChatStreamLenient,
4328
4542
  streamObjectFromContext,
4329
4543
  toRagableResult,
4544
+ toWireUserContent,
4330
4545
  tryParsePartialJson,
4331
4546
  unwrapPostgrest,
4332
4547
  wrapStreamTextAsObject