@ragable/sdk 0.6.22 → 0.6.24

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
@@ -58,6 +58,7 @@ __export(index_exports, {
58
58
  asPostgrestResponse: () => asPostgrestResponse,
59
59
  assertPostgrestSuccess: () => assertPostgrestSuccess,
60
60
  bindFetch: () => bindFetch,
61
+ collectAssistantTextFromUiSegments: () => collectAssistantTextFromUiSegments,
61
62
  collectionRecordToRowWithMeta: () => collectionRecordToRowWithMeta,
62
63
  collectionRecordsToRowWithMeta: () => collectionRecordsToRowWithMeta,
63
64
  createBrowserClient: () => createBrowserClient,
@@ -68,14 +69,23 @@ __export(index_exports, {
68
69
  detectStorage: () => detectStorage,
69
70
  effectiveDataAuth: () => effectiveDataAuth,
70
71
  extractErrorMessage: () => extractErrorMessage,
72
+ finalizeAgentChatUiTurn: () => finalizeAgentChatUiTurn,
73
+ foldAgentStreamIntoUiSegments: () => foldAgentStreamIntoUiSegments,
71
74
  formatPostgrestError: () => formatPostgrestError,
72
75
  formatRetrievalContext: () => formatRetrievalContext,
73
76
  formatSdkError: () => formatSdkError,
74
77
  generateIdempotencyKey: () => generateIdempotencyKey,
78
+ isIncompleteAgentStreamError: () => isIncompleteAgentStreamError,
75
79
  normalizeBrowserApiBase: () => normalizeBrowserApiBase,
80
+ parseAgentStreamAgentInfo: () => parseAgentStreamAgentInfo,
81
+ parseAgentStreamDone: () => parseAgentStreamDone,
76
82
  parseSseDataLine: () => parseSseDataLine,
77
83
  parseTransportResponse: () => parseTransportResponse,
78
84
  readSseStream: () => readSseStream,
85
+ resolveRagableApiBase: () => resolveRagableApiBase,
86
+ runAgentChatStream: () => runAgentChatStream,
87
+ runAgentChatStreamForUi: () => runAgentChatStreamForUi,
88
+ runAgentChatStreamLenient: () => runAgentChatStreamLenient,
79
89
  toRagableResult: () => toRagableResult,
80
90
  unwrapPostgrest: () => unwrapPostgrest
81
91
  });
@@ -89,6 +99,10 @@ function bindFetch(custom) {
89
99
  };
90
100
  }
91
101
  var DEFAULT_RAGABLE_API_BASE = "https://ragable-341305259977.asia-southeast1.run.app/api";
102
+ function resolveRagableApiBase(explicitBaseUrl) {
103
+ const raw = typeof explicitBaseUrl === "string" && explicitBaseUrl.trim().length > 0 ? explicitBaseUrl.trim() : DEFAULT_RAGABLE_API_BASE.trim();
104
+ return raw.replace(/\/+$/, "");
105
+ }
92
106
  var RagableSdkError = class extends Error {
93
107
  constructor(message) {
94
108
  super(message);
@@ -217,7 +231,7 @@ var RagableRequestClient = class {
217
231
  __publicField(this, "fetchImpl");
218
232
  __publicField(this, "defaultHeaders");
219
233
  this.apiKey = options.apiKey;
220
- this.baseUrl = DEFAULT_RAGABLE_API_BASE.replace(/\/+$/, "");
234
+ this.baseUrl = resolveRagableApiBase(options.baseUrl);
221
235
  this.fetchImpl = bindFetch(options.fetch);
222
236
  this.defaultHeaders = options.headers;
223
237
  }
@@ -406,6 +420,442 @@ function toArrayBuffer(value) {
406
420
  return copy.buffer;
407
421
  }
408
422
 
423
+ // src/agent-stream.ts
424
+ function assertAborted(signal) {
425
+ if (signal?.aborted) {
426
+ throw new RagableAbortError();
427
+ }
428
+ }
429
+ function asString(v, fallback = "") {
430
+ return typeof v === "string" ? v : fallback;
431
+ }
432
+ function asNumber(v, fallback = 0) {
433
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
434
+ }
435
+ function asUnknownArray(v) {
436
+ return Array.isArray(v) ? v : [];
437
+ }
438
+ function parseAgentStreamDone(e) {
439
+ if (e.type !== "done") return null;
440
+ return {
441
+ response: asString(e["response"]),
442
+ traces: asUnknownArray(e["traces"]),
443
+ totalDurationMs: asNumber(e["totalDurationMs"]),
444
+ ...e["httpResponse"] !== void 0 ? { httpResponse: e["httpResponse"] } : {},
445
+ ...typeof e["inputTokens"] === "number" ? { inputTokens: e["inputTokens"] } : {},
446
+ ...typeof e["outputTokens"] === "number" ? { outputTokens: e["outputTokens"] } : {},
447
+ ...typeof e["cachedPromptTokens"] === "number" ? { cachedPromptTokens: e["cachedPromptTokens"] } : {},
448
+ ...typeof e["cacheCreationInputTokens"] === "number" ? { cacheCreationInputTokens: e["cacheCreationInputTokens"] } : {},
449
+ ...Array.isArray(e["completionProviders"]) ? {
450
+ completionProviders: e["completionProviders"].map((x) => String(x))
451
+ } : {},
452
+ ...typeof e["creditsCharged"] === "number" ? { creditsCharged: e["creditsCharged"] } : {},
453
+ ...typeof e["agentSteps"] === "number" ? { agentSteps: e["agentSteps"] } : {},
454
+ ...e["finishReason"] !== void 0 ? { finishReason: e["finishReason"] } : {},
455
+ ...e["stopReason"] !== void 0 ? { stopReason: e["stopReason"] } : {},
456
+ ...e["turnMessages"] !== void 0 ? { turnMessages: e["turnMessages"] } : {},
457
+ ...typeof e["promptTokensEstimated"] === "number" ? { promptTokensEstimated: e["promptTokensEstimated"] } : {},
458
+ ...typeof e["contextWindow"] === "number" ? { contextWindow: e["contextWindow"] } : {}
459
+ };
460
+ }
461
+ function parseAgentStreamAgentInfo(e) {
462
+ if (e.type !== "agent:info") return null;
463
+ return {
464
+ type: "agent:info",
465
+ name: asString(e["name"]),
466
+ agent_name: asString(e["agent_name"])
467
+ };
468
+ }
469
+ function parseAgentInfo(e) {
470
+ return parseAgentStreamAgentInfo(e);
471
+ }
472
+ async function runAgentChatStream(source, handlers = {}, options = {}) {
473
+ const { signal } = options;
474
+ let assistantText = "";
475
+ let reasoningText = "";
476
+ let donePayload = null;
477
+ try {
478
+ for await (const event of source) {
479
+ assertAborted(signal);
480
+ handlers.onEvent?.(event);
481
+ const info = parseAgentInfo(event);
482
+ if (info) {
483
+ handlers.onAgentInfo?.(info);
484
+ continue;
485
+ }
486
+ switch (event.type) {
487
+ case "ping":
488
+ handlers.onPing?.();
489
+ break;
490
+ case "token": {
491
+ const nodeId = asString(event["nodeId"], "__self__");
492
+ const token = asString(event["token"]);
493
+ assistantText += token;
494
+ handlers.onToken?.(token, { nodeId });
495
+ break;
496
+ }
497
+ case "reasoning_token": {
498
+ const nodeId = asString(event["nodeId"], "__self__");
499
+ const token = asString(event["token"]);
500
+ reasoningText += token;
501
+ handlers.onReasoningToken?.(token, { nodeId });
502
+ break;
503
+ }
504
+ case "tool:call":
505
+ handlers.onToolCall?.({
506
+ nodeId: asString(event["nodeId"]),
507
+ toolName: asString(event["toolName"]),
508
+ args: event["args"]
509
+ });
510
+ break;
511
+ case "tool:args_update": {
512
+ const raw = event["args"];
513
+ const args = raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
514
+ handlers.onToolArgsUpdate?.({
515
+ nodeId: asString(event["nodeId"]),
516
+ args
517
+ });
518
+ break;
519
+ }
520
+ case "tool:result":
521
+ handlers.onToolResult?.({
522
+ nodeId: asString(event["nodeId"]),
523
+ toolName: asString(event["toolName"]),
524
+ durationMs: asNumber(event["durationMs"]),
525
+ ...typeof event["result"] === "string" ? { result: event["result"] } : {}
526
+ });
527
+ break;
528
+ case "node:start":
529
+ handlers.onNodeStart?.({
530
+ nodeId: asString(event["nodeId"]),
531
+ nodeType: asString(event["nodeType"]),
532
+ label: asString(event["label"])
533
+ });
534
+ break;
535
+ case "node:complete":
536
+ handlers.onNodeComplete?.({
537
+ nodeId: asString(event["nodeId"]),
538
+ output: event["output"],
539
+ durationMs: asNumber(event["durationMs"])
540
+ });
541
+ break;
542
+ case "node:error":
543
+ handlers.onNodeError?.({
544
+ nodeId: asString(event["nodeId"]),
545
+ error: asString(event["error"])
546
+ });
547
+ break;
548
+ case "done": {
549
+ const parsed = parseAgentStreamDone(event);
550
+ if (parsed) {
551
+ donePayload = parsed;
552
+ handlers.onDone?.(parsed);
553
+ }
554
+ break;
555
+ }
556
+ default:
557
+ break;
558
+ }
559
+ }
560
+ } catch (err) {
561
+ handlers.onError?.(err);
562
+ throw err;
563
+ }
564
+ if (!donePayload) {
565
+ const err = new RagableError(
566
+ "Agent stream ended without a done event",
567
+ 502,
568
+ { code: "SDK_AGENT_STREAM_INCOMPLETE" }
569
+ );
570
+ handlers.onError?.(err);
571
+ throw err;
572
+ }
573
+ const result = {
574
+ ...donePayload,
575
+ assistantText,
576
+ reasoningText
577
+ };
578
+ handlers.onComplete?.(result);
579
+ return result;
580
+ }
581
+ async function runAgentChatStreamLenient(source, handlers = {}, options = {}) {
582
+ try {
583
+ return await runAgentChatStream(source, handlers, options);
584
+ } catch (e) {
585
+ if (e instanceof RagableError && e.code === "SDK_AGENT_STREAM_INCOMPLETE") {
586
+ return null;
587
+ }
588
+ throw e;
589
+ }
590
+ }
591
+ function isIncompleteAgentStreamError(e) {
592
+ return e instanceof RagableError && e.code === "SDK_AGENT_STREAM_INCOMPLETE";
593
+ }
594
+
595
+ // src/agent-chat-ui.ts
596
+ function asString2(v, fallback = "") {
597
+ return typeof v === "string" ? v : fallback;
598
+ }
599
+ function asNumber2(v, fallback = 0) {
600
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
601
+ }
602
+ function assertAborted2(signal) {
603
+ if (signal?.aborted) {
604
+ throw new RagableAbortError();
605
+ }
606
+ }
607
+ function recordFromUnknown(v) {
608
+ if (v !== null && typeof v === "object" && !Array.isArray(v)) {
609
+ return { ...v };
610
+ }
611
+ return {};
612
+ }
613
+ function lastToolBlocksStream(last) {
614
+ return last?.type === "tool" && last.status === "started";
615
+ }
616
+ function toolSegmentId(event) {
617
+ const nid = event["nodeId"];
618
+ if (typeof nid === "string" && nid.length > 0) return nid;
619
+ const tn = event["toolName"];
620
+ if (typeof tn === "string" && tn.length > 0) return tn;
621
+ return "__tool__";
622
+ }
623
+ function normalizeContextSummarizedMode(m) {
624
+ if (m === "llm" || m === "heuristic" || m === "llm+heuristic" || m === "aggressive") {
625
+ return m;
626
+ }
627
+ return void 0;
628
+ }
629
+ function normalizeContextSummarizedReason(r) {
630
+ if (r === "soft_limit" || r === "forced") return r;
631
+ return void 0;
632
+ }
633
+ function foldContextSummarized(prev, event) {
634
+ const step = asNumber2(event["step"], 0);
635
+ const mode = normalizeContextSummarizedMode(event["mode"]);
636
+ const reason = normalizeContextSummarizedReason(event["reason"]);
637
+ const tro = event["tokensRemovedEstimate"];
638
+ const eta = event["estimatedTokensAfter"];
639
+ return [
640
+ ...prev,
641
+ {
642
+ type: "context_summarized",
643
+ step,
644
+ ...mode ? { mode } : {},
645
+ ...reason ? { reason } : {},
646
+ ...typeof tro === "number" && tro > 0 ? { tokensRemovedEstimate: tro } : {},
647
+ ...typeof eta === "number" && eta > 0 ? { estimatedTokensAfter: eta } : {}
648
+ }
649
+ ];
650
+ }
651
+ function collectAssistantTextFromUiSegments(segments) {
652
+ return segments.filter((s) => s.type === "text").map((s) => s.content).join("");
653
+ }
654
+ function foldAgentStreamIntoUiSegments(prev, event) {
655
+ switch (event.type) {
656
+ case "token": {
657
+ const last = prev[prev.length - 1];
658
+ if (lastToolBlocksStream(last)) return prev;
659
+ const token = asString2(event["token"]);
660
+ if (!token) return prev;
661
+ if (last?.type === "text") {
662
+ return [
663
+ ...prev.slice(0, -1),
664
+ { type: "text", content: last.content + token }
665
+ ];
666
+ }
667
+ return [...prev, { type: "text", content: token }];
668
+ }
669
+ case "reasoning_token": {
670
+ const last = prev[prev.length - 1];
671
+ if (lastToolBlocksStream(last)) return prev;
672
+ const token = asString2(event["token"]);
673
+ if (!token) return prev;
674
+ if (last?.type === "reasoning") {
675
+ return [
676
+ ...prev.slice(0, -1),
677
+ { type: "reasoning", content: last.content + token }
678
+ ];
679
+ }
680
+ return [...prev, { type: "reasoning", content: token }];
681
+ }
682
+ case "tool:call": {
683
+ const id = toolSegmentId(event);
684
+ const toolName = asString2(event["toolName"], "tool");
685
+ const argsRaw = event["args"];
686
+ const args = argsRaw !== null && typeof argsRaw === "object" && !Array.isArray(argsRaw) ? argsRaw : void 0;
687
+ return [
688
+ ...prev,
689
+ {
690
+ type: "tool",
691
+ id,
692
+ toolName,
693
+ status: "started",
694
+ ...args !== void 0 ? { args } : {}
695
+ }
696
+ ];
697
+ }
698
+ case "tool:args_update": {
699
+ const nodeId = asString2(event["nodeId"]);
700
+ const patch = recordFromUnknown(event["args"]);
701
+ return prev.map((seg) => {
702
+ if (seg.type !== "tool" || seg.id !== nodeId) return seg;
703
+ const merged = { ...recordFromUnknown(seg.args), ...patch };
704
+ return {
705
+ ...seg,
706
+ args: merged
707
+ };
708
+ });
709
+ }
710
+ case "tool:result": {
711
+ const nodeId = asString2(event["nodeId"]);
712
+ const toolName = asString2(event["toolName"]) || asString2(event["nodeId"]);
713
+ const durationMs = typeof event["durationMs"] === "number" ? event["durationMs"] : void 0;
714
+ const resultStr = typeof event["result"] === "string" ? event["result"] : void 0;
715
+ let idx = -1;
716
+ if (nodeId) {
717
+ for (let i = prev.length - 1; i >= 0; i--) {
718
+ const s = prev[i];
719
+ if (s.type === "tool" && s.status === "started" && s.id === nodeId) {
720
+ idx = i;
721
+ break;
722
+ }
723
+ }
724
+ }
725
+ if (idx < 0 && toolName) {
726
+ for (let i = prev.length - 1; i >= 0; i--) {
727
+ const s = prev[i];
728
+ if (s.type === "tool" && s.status === "started" && s.toolName === toolName) {
729
+ idx = i;
730
+ break;
731
+ }
732
+ }
733
+ }
734
+ if (idx < 0) return prev;
735
+ const next = [...prev];
736
+ const seg = next[idx];
737
+ if (seg.type !== "tool") return prev;
738
+ next[idx] = {
739
+ ...seg,
740
+ status: "completed",
741
+ ...durationMs !== void 0 ? { durationMs } : {},
742
+ ...resultStr !== void 0 ? { result: resultStr } : {}
743
+ };
744
+ return next;
745
+ }
746
+ case "context_summarized":
747
+ return foldContextSummarized(prev, event);
748
+ case "llm_step": {
749
+ return [
750
+ ...prev,
751
+ {
752
+ type: "llm_step",
753
+ step: Number(event["step"]),
754
+ inputTokens: Number(event["inputTokens"] ?? 0),
755
+ outputTokens: Number(event["outputTokens"] ?? 0),
756
+ ...typeof event["cachedPromptTokens"] === "number" ? { cachedPromptTokens: event["cachedPromptTokens"] } : {},
757
+ ...typeof event["cacheCreationInputTokens"] === "number" ? { cacheCreationInputTokens: event["cacheCreationInputTokens"] } : {},
758
+ creditsEstimated: Number(event["creditsEstimated"] ?? 0),
759
+ ...typeof event["apiCostUsd"] === "number" && Number.isFinite(event["apiCostUsd"]) ? { apiCostUsd: event["apiCostUsd"] } : {},
760
+ ...typeof event["provider"] === "string" && event["provider"] ? { provider: event["provider"] } : {}
761
+ }
762
+ ];
763
+ }
764
+ default:
765
+ return prev;
766
+ }
767
+ }
768
+ function finalizeAgentChatUiTurn(segments, done) {
769
+ let segs = segments.length > 0 ? [...segments] : void 0;
770
+ if (done.stopReason) {
771
+ const stopSeg = {
772
+ type: "stop_reason",
773
+ content: done.stopReason,
774
+ finishReason: done.finishReason ?? "error"
775
+ };
776
+ segs = segs ? [...segs, stopSeg] : [stopSeg];
777
+ }
778
+ const fromText = segs ? collectAssistantTextFromUiSegments(segs) : "";
779
+ const content = done.response || fromText || "No response.";
780
+ const message = {
781
+ role: "ai",
782
+ content,
783
+ ...segs && segs.length > 0 ? { segments: segs } : {},
784
+ finishReason: done.finishReason ?? null,
785
+ ...Array.isArray(done.completionProviders) && done.completionProviders.length > 0 ? { completionProviders: done.completionProviders } : {},
786
+ ...typeof done.agentSteps === "number" && Number.isFinite(done.agentSteps) && done.agentSteps > 0 ? { agentSteps: Math.floor(done.agentSteps) } : {},
787
+ usage: {
788
+ inputTokens: done.inputTokens ?? 0,
789
+ outputTokens: done.outputTokens ?? 0,
790
+ creditsCharged: done.creditsCharged ?? 0,
791
+ ...typeof done.cachedPromptTokens === "number" && done.cachedPromptTokens > 0 ? { cachedPromptTokens: done.cachedPromptTokens } : {},
792
+ ...typeof done.cacheCreationInputTokens === "number" && done.cacheCreationInputTokens > 0 ? { cacheCreationInputTokens: done.cacheCreationInputTokens } : {}
793
+ },
794
+ ...typeof done.totalDurationMs === "number" && done.totalDurationMs > 0 ? { durationMs: done.totalDurationMs } : {}
795
+ };
796
+ return { segments: segs ?? [], message };
797
+ }
798
+ async function runAgentChatStreamForUi(source, handlers = {}, options = {}) {
799
+ const { signal } = options;
800
+ let segments = [];
801
+ let donePayload = null;
802
+ try {
803
+ for await (const event of source) {
804
+ assertAborted2(signal);
805
+ handlers.onEvent?.(event);
806
+ const info = parseAgentStreamAgentInfo(event);
807
+ if (info) {
808
+ handlers.onAgentInfo?.(info);
809
+ continue;
810
+ }
811
+ if (event.type === "ping") continue;
812
+ if (event.type === "done") {
813
+ const parsed = parseAgentStreamDone(event);
814
+ if (parsed) {
815
+ donePayload = parsed;
816
+ handlers.onDone?.(parsed);
817
+ }
818
+ break;
819
+ }
820
+ const next = foldAgentStreamIntoUiSegments(segments, event);
821
+ if (next !== segments) {
822
+ segments = next;
823
+ handlers.onSegments?.(segments);
824
+ if (event.type === "token") {
825
+ handlers.onStreamingText?.(
826
+ collectAssistantTextFromUiSegments(segments)
827
+ );
828
+ }
829
+ }
830
+ }
831
+ } catch (err) {
832
+ handlers.onError?.(err);
833
+ throw err;
834
+ }
835
+ if (!donePayload) {
836
+ const err = new RagableError(
837
+ "Agent stream ended without a done event",
838
+ 502,
839
+ { code: "SDK_AGENT_STREAM_INCOMPLETE" }
840
+ );
841
+ handlers.onError?.(err);
842
+ throw err;
843
+ }
844
+ const segmentsMidTurn = [...segments];
845
+ const { segments: finalSegs, message } = finalizeAgentChatUiTurn(
846
+ segments,
847
+ donePayload
848
+ );
849
+ const result = {
850
+ segmentsMidTurn,
851
+ segments: finalSegs,
852
+ message,
853
+ done: donePayload
854
+ };
855
+ handlers.onComplete?.(result);
856
+ return result;
857
+ }
858
+
409
859
  // src/sse.ts
410
860
  async function parseMaybeJsonBody(response) {
411
861
  const contentType = response.headers.get("content-type") ?? "";
@@ -505,7 +955,8 @@ var AgentsClient = class {
505
955
  body: {
506
956
  message: params.message,
507
957
  ...params.history !== void 0 ? { history: params.history } : {}
508
- }
958
+ },
959
+ ...params.signal !== void 0 ? { signal: params.signal } : {}
509
960
  }
510
961
  );
511
962
  if (!response.ok) {
@@ -519,6 +970,24 @@ var AgentsClient = class {
519
970
  }
520
971
  yield* readSseStream(body);
521
972
  }
973
+ /**
974
+ * Stream an agent turn with callbacks; returns the final `done` payload plus streamed text.
975
+ * Prefer this over manual iteration when building chat UIs against the server API key client.
976
+ */
977
+ async runChatStream(agentId, params, handlers = {}) {
978
+ return runAgentChatStream(this.chatStream(agentId, params), handlers, {
979
+ signal: params.signal
980
+ });
981
+ }
982
+ /**
983
+ * Stream with dashboard-style `AgentChat` ergonomics: {@link AgentChatStreamUiHandlers.onSegments}
984
+ * / `onStreamingText` for live UI; returns a persisted-shaped assistant message on `done`.
985
+ */
986
+ async runChatUi(agentId, params, handlers = {}) {
987
+ return runAgentChatStreamForUi(this.chatStream(agentId, params), handlers, {
988
+ signal: params.signal
989
+ });
990
+ }
522
991
  };
523
992
 
524
993
  // src/transport.ts
@@ -1786,7 +2255,7 @@ var RagableAuth = class {
1786
2255
  __publicField(this, "broadcast", null);
1787
2256
  __publicField(this, "visibilityHandler", null);
1788
2257
  __publicField(this, "initialized", false);
1789
- this.baseUrl = DEFAULT_RAGABLE_API_BASE.replace(/\/+$/, "");
2258
+ this.baseUrl = resolveRagableApiBase(config.baseUrl);
1790
2259
  this.authGroupId = config.authGroupId;
1791
2260
  this.fetchImpl = bindFetch(config.fetch);
1792
2261
  this.defaultHeaders = config.headers;
@@ -2155,8 +2624,8 @@ function decodeJwtExpiry(jwt) {
2155
2624
  }
2156
2625
 
2157
2626
  // src/browser.ts
2158
- function normalizeBrowserApiBase() {
2159
- return DEFAULT_RAGABLE_API_BASE.replace(/\/+$/, "");
2627
+ function normalizeBrowserApiBase(explicitBaseUrl) {
2628
+ return resolveRagableApiBase(explicitBaseUrl);
2160
2629
  }
2161
2630
  function effectiveDataAuth(options) {
2162
2631
  if (options.dataAuth) return options.dataAuth;
@@ -2376,6 +2845,18 @@ var BrowserCollectionApi = class {
2376
2845
  this.databaseInstanceId
2377
2846
  )
2378
2847
  ));
2848
+ /**
2849
+ * Insert multiple rows in one request (server multi-value `INSERT`, single transaction).
2850
+ * Empty **`items`** resolves to an empty array. Max batch size is enforced on the server (500).
2851
+ */
2852
+ __publicField(this, "insertMany", (items) => asPostgrestResponse(
2853
+ () => this.database._requestCollection(
2854
+ "POST",
2855
+ `/${encodeURIComponent(this.name)}/records/batch`,
2856
+ { items },
2857
+ this.databaseInstanceId
2858
+ )
2859
+ ));
2379
2860
  /**
2380
2861
  * Update rows matching `where` (JSON fields, plus envelope `id` / `createdAt` / `updatedAt`).
2381
2862
  */
@@ -2404,6 +2885,21 @@ var BrowserCollectionApi = class {
2404
2885
  this.databaseInstanceId
2405
2886
  )
2406
2887
  ));
2888
+ /**
2889
+ * Like {@link BrowserCollectionApi.delete} but the success payload includes **`meta.count`**
2890
+ * (number of deleted rows), matching {@link BrowserCollectionApi.updateMany}.
2891
+ */
2892
+ __publicField(this, "deleteMany", async (where, options) => {
2893
+ const r = await this.delete(where, options);
2894
+ if (r.error) return r;
2895
+ return {
2896
+ data: {
2897
+ records: r.data.records,
2898
+ meta: { count: r.data.deleted }
2899
+ },
2900
+ error: null
2901
+ };
2902
+ });
2407
2903
  }
2408
2904
  normalizeFindArgs(whereOrParams) {
2409
2905
  const hasQueryKeys = typeof whereOrParams === "object" && whereOrParams !== null && FIND_QUERY_KEYS.some(
@@ -2420,6 +2916,7 @@ var RagableBrowserDatabaseClient = class {
2420
2916
  this.options = options;
2421
2917
  this.ragableAuth = ragableAuth;
2422
2918
  __publicField(this, "fetchImpl");
2919
+ __publicField(this, "apiBase");
2423
2920
  __publicField(this, "_transport", null);
2424
2921
  __publicField(this, "collections");
2425
2922
  __publicField(this, "collection");
@@ -2443,7 +2940,7 @@ var RagableBrowserDatabaseClient = class {
2443
2940
  }
2444
2941
  const gid = requireAuthGroupId(opts);
2445
2942
  const token = await resolveDatabaseAuthBearer(opts, ragableAuth);
2446
- const apiBase = normalizeBrowserApiBase();
2943
+ const apiBase = this.apiBase;
2447
2944
  const qs = params.searchParams.toString();
2448
2945
  const url = `${apiBase}/auth-groups/${gid}/data/rest/${params.table}${qs ? `?${qs}` : ""}`;
2449
2946
  const headers = new Headers(opts.headers);
@@ -2558,6 +3055,7 @@ var RagableBrowserDatabaseClient = class {
2558
3055
  )
2559
3056
  });
2560
3057
  this.fetchImpl = bindFetch(options.fetch);
3058
+ this.apiBase = resolveRagableApiBase(options.baseUrl);
2561
3059
  this.collections = new Proxy(
2562
3060
  {},
2563
3061
  {
@@ -2579,7 +3077,7 @@ var RagableBrowserDatabaseClient = class {
2579
3077
  this._transport = transport;
2580
3078
  }
2581
3079
  toUrl(path) {
2582
- return `${normalizeBrowserApiBase()}${path.startsWith("/") ? path : `/${path}`}`;
3080
+ return `${this.apiBase}${path.startsWith("/") ? path : `/${path}`}`;
2583
3081
  }
2584
3082
  async _requestCollection(method, path, body, databaseInstanceId) {
2585
3083
  const gid = requireAuthGroupId(this.options);
@@ -2670,7 +3168,7 @@ async function subscribeBrowserRealtime(options, ragableAuth, fetchImpl, params)
2670
3168
  headers.set("Authorization", `Bearer ${token}`);
2671
3169
  headers.set("Content-Type", "application/json");
2672
3170
  const response = await fetchImpl(
2673
- `${normalizeBrowserApiBase()}/auth-groups/${gid}/data/realtime/stream`,
3171
+ `${resolveRagableApiBase(options.baseUrl)}/auth-groups/${gid}/data/realtime/stream`,
2674
3172
  {
2675
3173
  method: "POST",
2676
3174
  headers,
@@ -2803,10 +3301,12 @@ var RagableBrowserAgentsClient = class {
2803
3301
  constructor(options) {
2804
3302
  this.options = options;
2805
3303
  __publicField(this, "fetchImpl");
3304
+ __publicField(this, "apiBase");
2806
3305
  this.fetchImpl = bindFetch(options.fetch);
3306
+ this.apiBase = resolveRagableApiBase(options.baseUrl);
2807
3307
  }
2808
3308
  toUrl(path) {
2809
- return `${normalizeBrowserApiBase()}${path.startsWith("/") ? path : `/${path}`}`;
3309
+ return `${this.apiBase}${path.startsWith("/") ? path : `/${path}`}`;
2810
3310
  }
2811
3311
  requireWebsiteId() {
2812
3312
  const websiteId = this.options.websiteId?.trim();
@@ -2848,7 +3348,8 @@ var RagableBrowserAgentsClient = class {
2848
3348
  {
2849
3349
  method: "POST",
2850
3350
  headers,
2851
- body: JSON.stringify(body)
3351
+ body: JSON.stringify(body),
3352
+ ...params.signal !== void 0 ? { signal: params.signal } : {}
2852
3353
  }
2853
3354
  );
2854
3355
  if (!response.ok) {
@@ -2877,7 +3378,8 @@ var RagableBrowserAgentsClient = class {
2877
3378
  body: JSON.stringify({
2878
3379
  message: params.message,
2879
3380
  ...params.history !== void 0 ? { history: params.history } : {}
2880
- })
3381
+ }),
3382
+ ...params.signal !== void 0 ? { signal: params.signal } : {}
2881
3383
  }
2882
3384
  );
2883
3385
  if (!response.ok) {
@@ -2888,6 +3390,26 @@ var RagableBrowserAgentsClient = class {
2888
3390
  if (!response.body) return;
2889
3391
  yield* readSseStream(response.body);
2890
3392
  }
3393
+ /**
3394
+ * Stream a project agent (`/agents/*.json`) with callbacks; returns the final `done` payload
3395
+ * plus streamed assistant text. Prefer this over manual `for await` when building chat UIs.
3396
+ */
3397
+ async runChatStreamByName(agentName, params, handlers = {}) {
3398
+ return runAgentChatStream(this.chatStreamByName(agentName, params), handlers, {
3399
+ signal: params.signal
3400
+ });
3401
+ }
3402
+ /**
3403
+ * Same as {@link runChatStreamByName} but folds events into `AgentChat`-style segments
3404
+ * (`onSegments` / `onStreamingText`) and returns a history-ready assistant message.
3405
+ */
3406
+ async runChatUiByName(agentName, params, handlers = {}) {
3407
+ return runAgentChatStreamForUi(
3408
+ this.chatStreamByName(agentName, params),
3409
+ handlers,
3410
+ { signal: params.signal }
3411
+ );
3412
+ }
2891
3413
  createConversation(params) {
2892
3414
  const headers = new Headers(this.options.headers);
2893
3415
  headers.set("Content-Type", "application/json");
@@ -2984,6 +3506,7 @@ var RagableBrowser = class {
2984
3506
  if (options.authGroupId) {
2985
3507
  this._ragableAuth = new RagableAuth({
2986
3508
  authGroupId: options.authGroupId,
3509
+ baseUrl: options.baseUrl,
2987
3510
  fetch: options.fetch,
2988
3511
  headers: options.headers,
2989
3512
  auth: options.auth
@@ -3135,6 +3658,7 @@ function createRagableServerClient(options) {
3135
3658
  asPostgrestResponse,
3136
3659
  assertPostgrestSuccess,
3137
3660
  bindFetch,
3661
+ collectAssistantTextFromUiSegments,
3138
3662
  collectionRecordToRowWithMeta,
3139
3663
  collectionRecordsToRowWithMeta,
3140
3664
  createBrowserClient,
@@ -3145,14 +3669,23 @@ function createRagableServerClient(options) {
3145
3669
  detectStorage,
3146
3670
  effectiveDataAuth,
3147
3671
  extractErrorMessage,
3672
+ finalizeAgentChatUiTurn,
3673
+ foldAgentStreamIntoUiSegments,
3148
3674
  formatPostgrestError,
3149
3675
  formatRetrievalContext,
3150
3676
  formatSdkError,
3151
3677
  generateIdempotencyKey,
3678
+ isIncompleteAgentStreamError,
3152
3679
  normalizeBrowserApiBase,
3680
+ parseAgentStreamAgentInfo,
3681
+ parseAgentStreamDone,
3153
3682
  parseSseDataLine,
3154
3683
  parseTransportResponse,
3155
3684
  readSseStream,
3685
+ resolveRagableApiBase,
3686
+ runAgentChatStream,
3687
+ runAgentChatStreamForUi,
3688
+ runAgentChatStreamLenient,
3156
3689
  toRagableResult,
3157
3690
  unwrapPostgrest
3158
3691
  });