@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.d.mts +309 -4
- package/dist/index.d.ts +309 -4
- package/dist/index.js +544 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +534 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 `${
|
|
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
|
-
`${
|
|
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 `${
|
|
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
|
});
|