@ragable/sdk 0.6.22 → 0.6.23

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,22 @@ __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
+ runAgentChatStream: () => runAgentChatStream,
86
+ runAgentChatStreamForUi: () => runAgentChatStreamForUi,
87
+ runAgentChatStreamLenient: () => runAgentChatStreamLenient,
79
88
  toRagableResult: () => toRagableResult,
80
89
  unwrapPostgrest: () => unwrapPostgrest
81
90
  });
@@ -406,6 +415,442 @@ function toArrayBuffer(value) {
406
415
  return copy.buffer;
407
416
  }
408
417
 
418
+ // src/agent-stream.ts
419
+ function assertAborted(signal) {
420
+ if (signal?.aborted) {
421
+ throw new RagableAbortError();
422
+ }
423
+ }
424
+ function asString(v, fallback = "") {
425
+ return typeof v === "string" ? v : fallback;
426
+ }
427
+ function asNumber(v, fallback = 0) {
428
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
429
+ }
430
+ function asUnknownArray(v) {
431
+ return Array.isArray(v) ? v : [];
432
+ }
433
+ function parseAgentStreamDone(e) {
434
+ if (e.type !== "done") return null;
435
+ return {
436
+ response: asString(e["response"]),
437
+ traces: asUnknownArray(e["traces"]),
438
+ totalDurationMs: asNumber(e["totalDurationMs"]),
439
+ ...e["httpResponse"] !== void 0 ? { httpResponse: e["httpResponse"] } : {},
440
+ ...typeof e["inputTokens"] === "number" ? { inputTokens: e["inputTokens"] } : {},
441
+ ...typeof e["outputTokens"] === "number" ? { outputTokens: e["outputTokens"] } : {},
442
+ ...typeof e["cachedPromptTokens"] === "number" ? { cachedPromptTokens: e["cachedPromptTokens"] } : {},
443
+ ...typeof e["cacheCreationInputTokens"] === "number" ? { cacheCreationInputTokens: e["cacheCreationInputTokens"] } : {},
444
+ ...Array.isArray(e["completionProviders"]) ? {
445
+ completionProviders: e["completionProviders"].map((x) => String(x))
446
+ } : {},
447
+ ...typeof e["creditsCharged"] === "number" ? { creditsCharged: e["creditsCharged"] } : {},
448
+ ...typeof e["agentSteps"] === "number" ? { agentSteps: e["agentSteps"] } : {},
449
+ ...e["finishReason"] !== void 0 ? { finishReason: e["finishReason"] } : {},
450
+ ...e["stopReason"] !== void 0 ? { stopReason: e["stopReason"] } : {},
451
+ ...e["turnMessages"] !== void 0 ? { turnMessages: e["turnMessages"] } : {},
452
+ ...typeof e["promptTokensEstimated"] === "number" ? { promptTokensEstimated: e["promptTokensEstimated"] } : {},
453
+ ...typeof e["contextWindow"] === "number" ? { contextWindow: e["contextWindow"] } : {}
454
+ };
455
+ }
456
+ function parseAgentStreamAgentInfo(e) {
457
+ if (e.type !== "agent:info") return null;
458
+ return {
459
+ type: "agent:info",
460
+ name: asString(e["name"]),
461
+ agent_name: asString(e["agent_name"])
462
+ };
463
+ }
464
+ function parseAgentInfo(e) {
465
+ return parseAgentStreamAgentInfo(e);
466
+ }
467
+ async function runAgentChatStream(source, handlers = {}, options = {}) {
468
+ const { signal } = options;
469
+ let assistantText = "";
470
+ let reasoningText = "";
471
+ let donePayload = null;
472
+ try {
473
+ for await (const event of source) {
474
+ assertAborted(signal);
475
+ handlers.onEvent?.(event);
476
+ const info = parseAgentInfo(event);
477
+ if (info) {
478
+ handlers.onAgentInfo?.(info);
479
+ continue;
480
+ }
481
+ switch (event.type) {
482
+ case "ping":
483
+ handlers.onPing?.();
484
+ break;
485
+ case "token": {
486
+ const nodeId = asString(event["nodeId"], "__self__");
487
+ const token = asString(event["token"]);
488
+ assistantText += token;
489
+ handlers.onToken?.(token, { nodeId });
490
+ break;
491
+ }
492
+ case "reasoning_token": {
493
+ const nodeId = asString(event["nodeId"], "__self__");
494
+ const token = asString(event["token"]);
495
+ reasoningText += token;
496
+ handlers.onReasoningToken?.(token, { nodeId });
497
+ break;
498
+ }
499
+ case "tool:call":
500
+ handlers.onToolCall?.({
501
+ nodeId: asString(event["nodeId"]),
502
+ toolName: asString(event["toolName"]),
503
+ args: event["args"]
504
+ });
505
+ break;
506
+ case "tool:args_update": {
507
+ const raw = event["args"];
508
+ const args = raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
509
+ handlers.onToolArgsUpdate?.({
510
+ nodeId: asString(event["nodeId"]),
511
+ args
512
+ });
513
+ break;
514
+ }
515
+ case "tool:result":
516
+ handlers.onToolResult?.({
517
+ nodeId: asString(event["nodeId"]),
518
+ toolName: asString(event["toolName"]),
519
+ durationMs: asNumber(event["durationMs"]),
520
+ ...typeof event["result"] === "string" ? { result: event["result"] } : {}
521
+ });
522
+ break;
523
+ case "node:start":
524
+ handlers.onNodeStart?.({
525
+ nodeId: asString(event["nodeId"]),
526
+ nodeType: asString(event["nodeType"]),
527
+ label: asString(event["label"])
528
+ });
529
+ break;
530
+ case "node:complete":
531
+ handlers.onNodeComplete?.({
532
+ nodeId: asString(event["nodeId"]),
533
+ output: event["output"],
534
+ durationMs: asNumber(event["durationMs"])
535
+ });
536
+ break;
537
+ case "node:error":
538
+ handlers.onNodeError?.({
539
+ nodeId: asString(event["nodeId"]),
540
+ error: asString(event["error"])
541
+ });
542
+ break;
543
+ case "done": {
544
+ const parsed = parseAgentStreamDone(event);
545
+ if (parsed) {
546
+ donePayload = parsed;
547
+ handlers.onDone?.(parsed);
548
+ }
549
+ break;
550
+ }
551
+ default:
552
+ break;
553
+ }
554
+ }
555
+ } catch (err) {
556
+ handlers.onError?.(err);
557
+ throw err;
558
+ }
559
+ if (!donePayload) {
560
+ const err = new RagableError(
561
+ "Agent stream ended without a done event",
562
+ 502,
563
+ { code: "SDK_AGENT_STREAM_INCOMPLETE" }
564
+ );
565
+ handlers.onError?.(err);
566
+ throw err;
567
+ }
568
+ const result = {
569
+ ...donePayload,
570
+ assistantText,
571
+ reasoningText
572
+ };
573
+ handlers.onComplete?.(result);
574
+ return result;
575
+ }
576
+ async function runAgentChatStreamLenient(source, handlers = {}, options = {}) {
577
+ try {
578
+ return await runAgentChatStream(source, handlers, options);
579
+ } catch (e) {
580
+ if (e instanceof RagableError && e.code === "SDK_AGENT_STREAM_INCOMPLETE") {
581
+ return null;
582
+ }
583
+ throw e;
584
+ }
585
+ }
586
+ function isIncompleteAgentStreamError(e) {
587
+ return e instanceof RagableError && e.code === "SDK_AGENT_STREAM_INCOMPLETE";
588
+ }
589
+
590
+ // src/agent-chat-ui.ts
591
+ function asString2(v, fallback = "") {
592
+ return typeof v === "string" ? v : fallback;
593
+ }
594
+ function asNumber2(v, fallback = 0) {
595
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
596
+ }
597
+ function assertAborted2(signal) {
598
+ if (signal?.aborted) {
599
+ throw new RagableAbortError();
600
+ }
601
+ }
602
+ function recordFromUnknown(v) {
603
+ if (v !== null && typeof v === "object" && !Array.isArray(v)) {
604
+ return { ...v };
605
+ }
606
+ return {};
607
+ }
608
+ function lastToolBlocksStream(last) {
609
+ return last?.type === "tool" && last.status === "started";
610
+ }
611
+ function toolSegmentId(event) {
612
+ const nid = event["nodeId"];
613
+ if (typeof nid === "string" && nid.length > 0) return nid;
614
+ const tn = event["toolName"];
615
+ if (typeof tn === "string" && tn.length > 0) return tn;
616
+ return "__tool__";
617
+ }
618
+ function normalizeContextSummarizedMode(m) {
619
+ if (m === "llm" || m === "heuristic" || m === "llm+heuristic" || m === "aggressive") {
620
+ return m;
621
+ }
622
+ return void 0;
623
+ }
624
+ function normalizeContextSummarizedReason(r) {
625
+ if (r === "soft_limit" || r === "forced") return r;
626
+ return void 0;
627
+ }
628
+ function foldContextSummarized(prev, event) {
629
+ const step = asNumber2(event["step"], 0);
630
+ const mode = normalizeContextSummarizedMode(event["mode"]);
631
+ const reason = normalizeContextSummarizedReason(event["reason"]);
632
+ const tro = event["tokensRemovedEstimate"];
633
+ const eta = event["estimatedTokensAfter"];
634
+ return [
635
+ ...prev,
636
+ {
637
+ type: "context_summarized",
638
+ step,
639
+ ...mode ? { mode } : {},
640
+ ...reason ? { reason } : {},
641
+ ...typeof tro === "number" && tro > 0 ? { tokensRemovedEstimate: tro } : {},
642
+ ...typeof eta === "number" && eta > 0 ? { estimatedTokensAfter: eta } : {}
643
+ }
644
+ ];
645
+ }
646
+ function collectAssistantTextFromUiSegments(segments) {
647
+ return segments.filter((s) => s.type === "text").map((s) => s.content).join("");
648
+ }
649
+ function foldAgentStreamIntoUiSegments(prev, event) {
650
+ switch (event.type) {
651
+ case "token": {
652
+ const last = prev[prev.length - 1];
653
+ if (lastToolBlocksStream(last)) return prev;
654
+ const token = asString2(event["token"]);
655
+ if (!token) return prev;
656
+ if (last?.type === "text") {
657
+ return [
658
+ ...prev.slice(0, -1),
659
+ { type: "text", content: last.content + token }
660
+ ];
661
+ }
662
+ return [...prev, { type: "text", content: token }];
663
+ }
664
+ case "reasoning_token": {
665
+ const last = prev[prev.length - 1];
666
+ if (lastToolBlocksStream(last)) return prev;
667
+ const token = asString2(event["token"]);
668
+ if (!token) return prev;
669
+ if (last?.type === "reasoning") {
670
+ return [
671
+ ...prev.slice(0, -1),
672
+ { type: "reasoning", content: last.content + token }
673
+ ];
674
+ }
675
+ return [...prev, { type: "reasoning", content: token }];
676
+ }
677
+ case "tool:call": {
678
+ const id = toolSegmentId(event);
679
+ const toolName = asString2(event["toolName"], "tool");
680
+ const argsRaw = event["args"];
681
+ const args = argsRaw !== null && typeof argsRaw === "object" && !Array.isArray(argsRaw) ? argsRaw : void 0;
682
+ return [
683
+ ...prev,
684
+ {
685
+ type: "tool",
686
+ id,
687
+ toolName,
688
+ status: "started",
689
+ ...args !== void 0 ? { args } : {}
690
+ }
691
+ ];
692
+ }
693
+ case "tool:args_update": {
694
+ const nodeId = asString2(event["nodeId"]);
695
+ const patch = recordFromUnknown(event["args"]);
696
+ return prev.map((seg) => {
697
+ if (seg.type !== "tool" || seg.id !== nodeId) return seg;
698
+ const merged = { ...recordFromUnknown(seg.args), ...patch };
699
+ return {
700
+ ...seg,
701
+ args: merged
702
+ };
703
+ });
704
+ }
705
+ case "tool:result": {
706
+ const nodeId = asString2(event["nodeId"]);
707
+ const toolName = asString2(event["toolName"]) || asString2(event["nodeId"]);
708
+ const durationMs = typeof event["durationMs"] === "number" ? event["durationMs"] : void 0;
709
+ const resultStr = typeof event["result"] === "string" ? event["result"] : void 0;
710
+ let idx = -1;
711
+ if (nodeId) {
712
+ for (let i = prev.length - 1; i >= 0; i--) {
713
+ const s = prev[i];
714
+ if (s.type === "tool" && s.status === "started" && s.id === nodeId) {
715
+ idx = i;
716
+ break;
717
+ }
718
+ }
719
+ }
720
+ if (idx < 0 && toolName) {
721
+ for (let i = prev.length - 1; i >= 0; i--) {
722
+ const s = prev[i];
723
+ if (s.type === "tool" && s.status === "started" && s.toolName === toolName) {
724
+ idx = i;
725
+ break;
726
+ }
727
+ }
728
+ }
729
+ if (idx < 0) return prev;
730
+ const next = [...prev];
731
+ const seg = next[idx];
732
+ if (seg.type !== "tool") return prev;
733
+ next[idx] = {
734
+ ...seg,
735
+ status: "completed",
736
+ ...durationMs !== void 0 ? { durationMs } : {},
737
+ ...resultStr !== void 0 ? { result: resultStr } : {}
738
+ };
739
+ return next;
740
+ }
741
+ case "context_summarized":
742
+ return foldContextSummarized(prev, event);
743
+ case "llm_step": {
744
+ return [
745
+ ...prev,
746
+ {
747
+ type: "llm_step",
748
+ step: Number(event["step"]),
749
+ inputTokens: Number(event["inputTokens"] ?? 0),
750
+ outputTokens: Number(event["outputTokens"] ?? 0),
751
+ ...typeof event["cachedPromptTokens"] === "number" ? { cachedPromptTokens: event["cachedPromptTokens"] } : {},
752
+ ...typeof event["cacheCreationInputTokens"] === "number" ? { cacheCreationInputTokens: event["cacheCreationInputTokens"] } : {},
753
+ creditsEstimated: Number(event["creditsEstimated"] ?? 0),
754
+ ...typeof event["apiCostUsd"] === "number" && Number.isFinite(event["apiCostUsd"]) ? { apiCostUsd: event["apiCostUsd"] } : {},
755
+ ...typeof event["provider"] === "string" && event["provider"] ? { provider: event["provider"] } : {}
756
+ }
757
+ ];
758
+ }
759
+ default:
760
+ return prev;
761
+ }
762
+ }
763
+ function finalizeAgentChatUiTurn(segments, done) {
764
+ let segs = segments.length > 0 ? [...segments] : void 0;
765
+ if (done.stopReason) {
766
+ const stopSeg = {
767
+ type: "stop_reason",
768
+ content: done.stopReason,
769
+ finishReason: done.finishReason ?? "error"
770
+ };
771
+ segs = segs ? [...segs, stopSeg] : [stopSeg];
772
+ }
773
+ const fromText = segs ? collectAssistantTextFromUiSegments(segs) : "";
774
+ const content = done.response || fromText || "No response.";
775
+ const message = {
776
+ role: "ai",
777
+ content,
778
+ ...segs && segs.length > 0 ? { segments: segs } : {},
779
+ finishReason: done.finishReason ?? null,
780
+ ...Array.isArray(done.completionProviders) && done.completionProviders.length > 0 ? { completionProviders: done.completionProviders } : {},
781
+ ...typeof done.agentSteps === "number" && Number.isFinite(done.agentSteps) && done.agentSteps > 0 ? { agentSteps: Math.floor(done.agentSteps) } : {},
782
+ usage: {
783
+ inputTokens: done.inputTokens ?? 0,
784
+ outputTokens: done.outputTokens ?? 0,
785
+ creditsCharged: done.creditsCharged ?? 0,
786
+ ...typeof done.cachedPromptTokens === "number" && done.cachedPromptTokens > 0 ? { cachedPromptTokens: done.cachedPromptTokens } : {},
787
+ ...typeof done.cacheCreationInputTokens === "number" && done.cacheCreationInputTokens > 0 ? { cacheCreationInputTokens: done.cacheCreationInputTokens } : {}
788
+ },
789
+ ...typeof done.totalDurationMs === "number" && done.totalDurationMs > 0 ? { durationMs: done.totalDurationMs } : {}
790
+ };
791
+ return { segments: segs ?? [], message };
792
+ }
793
+ async function runAgentChatStreamForUi(source, handlers = {}, options = {}) {
794
+ const { signal } = options;
795
+ let segments = [];
796
+ let donePayload = null;
797
+ try {
798
+ for await (const event of source) {
799
+ assertAborted2(signal);
800
+ handlers.onEvent?.(event);
801
+ const info = parseAgentStreamAgentInfo(event);
802
+ if (info) {
803
+ handlers.onAgentInfo?.(info);
804
+ continue;
805
+ }
806
+ if (event.type === "ping") continue;
807
+ if (event.type === "done") {
808
+ const parsed = parseAgentStreamDone(event);
809
+ if (parsed) {
810
+ donePayload = parsed;
811
+ handlers.onDone?.(parsed);
812
+ }
813
+ break;
814
+ }
815
+ const next = foldAgentStreamIntoUiSegments(segments, event);
816
+ if (next !== segments) {
817
+ segments = next;
818
+ handlers.onSegments?.(segments);
819
+ if (event.type === "token") {
820
+ handlers.onStreamingText?.(
821
+ collectAssistantTextFromUiSegments(segments)
822
+ );
823
+ }
824
+ }
825
+ }
826
+ } catch (err) {
827
+ handlers.onError?.(err);
828
+ throw err;
829
+ }
830
+ if (!donePayload) {
831
+ const err = new RagableError(
832
+ "Agent stream ended without a done event",
833
+ 502,
834
+ { code: "SDK_AGENT_STREAM_INCOMPLETE" }
835
+ );
836
+ handlers.onError?.(err);
837
+ throw err;
838
+ }
839
+ const segmentsMidTurn = [...segments];
840
+ const { segments: finalSegs, message } = finalizeAgentChatUiTurn(
841
+ segments,
842
+ donePayload
843
+ );
844
+ const result = {
845
+ segmentsMidTurn,
846
+ segments: finalSegs,
847
+ message,
848
+ done: donePayload
849
+ };
850
+ handlers.onComplete?.(result);
851
+ return result;
852
+ }
853
+
409
854
  // src/sse.ts
410
855
  async function parseMaybeJsonBody(response) {
411
856
  const contentType = response.headers.get("content-type") ?? "";
@@ -505,7 +950,8 @@ var AgentsClient = class {
505
950
  body: {
506
951
  message: params.message,
507
952
  ...params.history !== void 0 ? { history: params.history } : {}
508
- }
953
+ },
954
+ ...params.signal !== void 0 ? { signal: params.signal } : {}
509
955
  }
510
956
  );
511
957
  if (!response.ok) {
@@ -519,6 +965,24 @@ var AgentsClient = class {
519
965
  }
520
966
  yield* readSseStream(body);
521
967
  }
968
+ /**
969
+ * Stream an agent turn with callbacks; returns the final `done` payload plus streamed text.
970
+ * Prefer this over manual iteration when building chat UIs against the server API key client.
971
+ */
972
+ async runChatStream(agentId, params, handlers = {}) {
973
+ return runAgentChatStream(this.chatStream(agentId, params), handlers, {
974
+ signal: params.signal
975
+ });
976
+ }
977
+ /**
978
+ * Stream with dashboard-style `AgentChat` ergonomics: {@link AgentChatStreamUiHandlers.onSegments}
979
+ * / `onStreamingText` for live UI; returns a persisted-shaped assistant message on `done`.
980
+ */
981
+ async runChatUi(agentId, params, handlers = {}) {
982
+ return runAgentChatStreamForUi(this.chatStream(agentId, params), handlers, {
983
+ signal: params.signal
984
+ });
985
+ }
522
986
  };
523
987
 
524
988
  // src/transport.ts
@@ -2376,6 +2840,18 @@ var BrowserCollectionApi = class {
2376
2840
  this.databaseInstanceId
2377
2841
  )
2378
2842
  ));
2843
+ /**
2844
+ * Insert multiple rows in one request (server multi-value `INSERT`, single transaction).
2845
+ * Empty **`items`** resolves to an empty array. Max batch size is enforced on the server (500).
2846
+ */
2847
+ __publicField(this, "insertMany", (items) => asPostgrestResponse(
2848
+ () => this.database._requestCollection(
2849
+ "POST",
2850
+ `/${encodeURIComponent(this.name)}/records/batch`,
2851
+ { items },
2852
+ this.databaseInstanceId
2853
+ )
2854
+ ));
2379
2855
  /**
2380
2856
  * Update rows matching `where` (JSON fields, plus envelope `id` / `createdAt` / `updatedAt`).
2381
2857
  */
@@ -2404,6 +2880,21 @@ var BrowserCollectionApi = class {
2404
2880
  this.databaseInstanceId
2405
2881
  )
2406
2882
  ));
2883
+ /**
2884
+ * Like {@link BrowserCollectionApi.delete} but the success payload includes **`meta.count`**
2885
+ * (number of deleted rows), matching {@link BrowserCollectionApi.updateMany}.
2886
+ */
2887
+ __publicField(this, "deleteMany", async (where, options) => {
2888
+ const r = await this.delete(where, options);
2889
+ if (r.error) return r;
2890
+ return {
2891
+ data: {
2892
+ records: r.data.records,
2893
+ meta: { count: r.data.deleted }
2894
+ },
2895
+ error: null
2896
+ };
2897
+ });
2407
2898
  }
2408
2899
  normalizeFindArgs(whereOrParams) {
2409
2900
  const hasQueryKeys = typeof whereOrParams === "object" && whereOrParams !== null && FIND_QUERY_KEYS.some(
@@ -2848,7 +3339,8 @@ var RagableBrowserAgentsClient = class {
2848
3339
  {
2849
3340
  method: "POST",
2850
3341
  headers,
2851
- body: JSON.stringify(body)
3342
+ body: JSON.stringify(body),
3343
+ ...params.signal !== void 0 ? { signal: params.signal } : {}
2852
3344
  }
2853
3345
  );
2854
3346
  if (!response.ok) {
@@ -2877,7 +3369,8 @@ var RagableBrowserAgentsClient = class {
2877
3369
  body: JSON.stringify({
2878
3370
  message: params.message,
2879
3371
  ...params.history !== void 0 ? { history: params.history } : {}
2880
- })
3372
+ }),
3373
+ ...params.signal !== void 0 ? { signal: params.signal } : {}
2881
3374
  }
2882
3375
  );
2883
3376
  if (!response.ok) {
@@ -2888,6 +3381,26 @@ var RagableBrowserAgentsClient = class {
2888
3381
  if (!response.body) return;
2889
3382
  yield* readSseStream(response.body);
2890
3383
  }
3384
+ /**
3385
+ * Stream a project agent (`/agents/*.json`) with callbacks; returns the final `done` payload
3386
+ * plus streamed assistant text. Prefer this over manual `for await` when building chat UIs.
3387
+ */
3388
+ async runChatStreamByName(agentName, params, handlers = {}) {
3389
+ return runAgentChatStream(this.chatStreamByName(agentName, params), handlers, {
3390
+ signal: params.signal
3391
+ });
3392
+ }
3393
+ /**
3394
+ * Same as {@link runChatStreamByName} but folds events into `AgentChat`-style segments
3395
+ * (`onSegments` / `onStreamingText`) and returns a history-ready assistant message.
3396
+ */
3397
+ async runChatUiByName(agentName, params, handlers = {}) {
3398
+ return runAgentChatStreamForUi(
3399
+ this.chatStreamByName(agentName, params),
3400
+ handlers,
3401
+ { signal: params.signal }
3402
+ );
3403
+ }
2891
3404
  createConversation(params) {
2892
3405
  const headers = new Headers(this.options.headers);
2893
3406
  headers.set("Content-Type", "application/json");
@@ -3135,6 +3648,7 @@ function createRagableServerClient(options) {
3135
3648
  asPostgrestResponse,
3136
3649
  assertPostgrestSuccess,
3137
3650
  bindFetch,
3651
+ collectAssistantTextFromUiSegments,
3138
3652
  collectionRecordToRowWithMeta,
3139
3653
  collectionRecordsToRowWithMeta,
3140
3654
  createBrowserClient,
@@ -3145,14 +3659,22 @@ function createRagableServerClient(options) {
3145
3659
  detectStorage,
3146
3660
  effectiveDataAuth,
3147
3661
  extractErrorMessage,
3662
+ finalizeAgentChatUiTurn,
3663
+ foldAgentStreamIntoUiSegments,
3148
3664
  formatPostgrestError,
3149
3665
  formatRetrievalContext,
3150
3666
  formatSdkError,
3151
3667
  generateIdempotencyKey,
3668
+ isIncompleteAgentStreamError,
3152
3669
  normalizeBrowserApiBase,
3670
+ parseAgentStreamAgentInfo,
3671
+ parseAgentStreamDone,
3153
3672
  parseSseDataLine,
3154
3673
  parseTransportResponse,
3155
3674
  readSseStream,
3675
+ runAgentChatStream,
3676
+ runAgentChatStreamForUi,
3677
+ runAgentChatStreamLenient,
3156
3678
  toRagableResult,
3157
3679
  unwrapPostgrest
3158
3680
  });