@ragable/sdk 0.6.21 → 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.d.mts +326 -1
- package/dist/index.d.ts +326 -1
- package/dist/index.js +650 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +641 -2
- 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,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(
|
|
@@ -2808,6 +3299,31 @@ var RagableBrowserAgentsClient = class {
|
|
|
2808
3299
|
toUrl(path) {
|
|
2809
3300
|
return `${normalizeBrowserApiBase()}${path.startsWith("/") ? path : `/${path}`}`;
|
|
2810
3301
|
}
|
|
3302
|
+
requireWebsiteId() {
|
|
3303
|
+
const websiteId = this.options.websiteId?.trim();
|
|
3304
|
+
if (!websiteId) {
|
|
3305
|
+
throw new RagableError(
|
|
3306
|
+
"websiteId is required for project agent conversation APIs. Use the generated createWebsiteRagableClient() or pass createBrowserClient({ websiteId, ... }).",
|
|
3307
|
+
400,
|
|
3308
|
+
{ code: "SDK_MISSING_WEBSITE_ID" }
|
|
3309
|
+
);
|
|
3310
|
+
}
|
|
3311
|
+
return websiteId;
|
|
3312
|
+
}
|
|
3313
|
+
websiteAgentPath(path) {
|
|
3314
|
+
const websiteId = this.requireWebsiteId();
|
|
3315
|
+
return `/public/organizations/${this.options.organizationId}/websites/${websiteId}${path}`;
|
|
3316
|
+
}
|
|
3317
|
+
async requestJson(path, init = {}) {
|
|
3318
|
+
const response = await this.fetchImpl(this.toUrl(path), init);
|
|
3319
|
+
const payload = await parseMaybeJsonBody(response);
|
|
3320
|
+
if (!response.ok) {
|
|
3321
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
3322
|
+
throw new RagableError(message, response.status, payload);
|
|
3323
|
+
}
|
|
3324
|
+
return payload;
|
|
3325
|
+
}
|
|
3326
|
+
/** @deprecated Prefer `chatStreamByName(agentName, params)` for project-local `/agents/*.json` agents. */
|
|
2811
3327
|
async *chatStream(agentId, params) {
|
|
2812
3328
|
const orgId = this.options.organizationId;
|
|
2813
3329
|
const body = {
|
|
@@ -2823,7 +3339,8 @@ var RagableBrowserAgentsClient = class {
|
|
|
2823
3339
|
{
|
|
2824
3340
|
method: "POST",
|
|
2825
3341
|
headers,
|
|
2826
|
-
body: JSON.stringify(body)
|
|
3342
|
+
body: JSON.stringify(body),
|
|
3343
|
+
...params.signal !== void 0 ? { signal: params.signal } : {}
|
|
2827
3344
|
}
|
|
2828
3345
|
);
|
|
2829
3346
|
if (!response.ok) {
|
|
@@ -2837,6 +3354,128 @@ var RagableBrowserAgentsClient = class {
|
|
|
2837
3354
|
}
|
|
2838
3355
|
yield* readSseStream(streamBody);
|
|
2839
3356
|
}
|
|
3357
|
+
async *chatStreamByName(agentName, params) {
|
|
3358
|
+
const headers = new Headers(this.options.headers);
|
|
3359
|
+
headers.set("Content-Type", "application/json");
|
|
3360
|
+
const response = await this.fetchImpl(
|
|
3361
|
+
this.toUrl(
|
|
3362
|
+
this.websiteAgentPath(
|
|
3363
|
+
`/agents/${encodeURIComponent(agentName)}/chat/stream`
|
|
3364
|
+
)
|
|
3365
|
+
),
|
|
3366
|
+
{
|
|
3367
|
+
method: "POST",
|
|
3368
|
+
headers,
|
|
3369
|
+
body: JSON.stringify({
|
|
3370
|
+
message: params.message,
|
|
3371
|
+
...params.history !== void 0 ? { history: params.history } : {}
|
|
3372
|
+
}),
|
|
3373
|
+
...params.signal !== void 0 ? { signal: params.signal } : {}
|
|
3374
|
+
}
|
|
3375
|
+
);
|
|
3376
|
+
if (!response.ok) {
|
|
3377
|
+
const payload = await parseMaybeJsonBody(response);
|
|
3378
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
3379
|
+
throw new RagableError(message, response.status, payload);
|
|
3380
|
+
}
|
|
3381
|
+
if (!response.body) return;
|
|
3382
|
+
yield* readSseStream(response.body);
|
|
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
|
+
}
|
|
3404
|
+
createConversation(params) {
|
|
3405
|
+
const headers = new Headers(this.options.headers);
|
|
3406
|
+
headers.set("Content-Type", "application/json");
|
|
3407
|
+
return this.requestJson(
|
|
3408
|
+
this.websiteAgentPath("/agent-conversations"),
|
|
3409
|
+
{
|
|
3410
|
+
method: "POST",
|
|
3411
|
+
headers,
|
|
3412
|
+
body: JSON.stringify(params)
|
|
3413
|
+
}
|
|
3414
|
+
);
|
|
3415
|
+
}
|
|
3416
|
+
listConversations(params = {}) {
|
|
3417
|
+
const agentName = params.agent_name ?? params.agentName;
|
|
3418
|
+
const qs = agentName ? `?agentName=${encodeURIComponent(agentName)}` : "";
|
|
3419
|
+
return this.requestJson(
|
|
3420
|
+
this.websiteAgentPath(`/agent-conversations${qs}`)
|
|
3421
|
+
);
|
|
3422
|
+
}
|
|
3423
|
+
getConversation(conversationId) {
|
|
3424
|
+
return this.requestJson(
|
|
3425
|
+
this.websiteAgentPath(
|
|
3426
|
+
`/agent-conversations/${encodeURIComponent(conversationId)}`
|
|
3427
|
+
)
|
|
3428
|
+
);
|
|
3429
|
+
}
|
|
3430
|
+
updateConversation(conversationId, data) {
|
|
3431
|
+
const headers = new Headers(this.options.headers);
|
|
3432
|
+
headers.set("Content-Type", "application/json");
|
|
3433
|
+
return this.requestJson(
|
|
3434
|
+
this.websiteAgentPath(
|
|
3435
|
+
`/agent-conversations/${encodeURIComponent(conversationId)}`
|
|
3436
|
+
),
|
|
3437
|
+
{
|
|
3438
|
+
method: "PATCH",
|
|
3439
|
+
headers,
|
|
3440
|
+
body: JSON.stringify(data)
|
|
3441
|
+
}
|
|
3442
|
+
);
|
|
3443
|
+
}
|
|
3444
|
+
addMessage(conversationOrId, message) {
|
|
3445
|
+
const conversationId = typeof conversationOrId === "string" ? conversationOrId : conversationOrId.id;
|
|
3446
|
+
const headers = new Headers(this.options.headers);
|
|
3447
|
+
headers.set("Content-Type", "application/json");
|
|
3448
|
+
return this.requestJson(
|
|
3449
|
+
this.websiteAgentPath(
|
|
3450
|
+
`/agent-conversations/${encodeURIComponent(conversationId)}/messages`
|
|
3451
|
+
),
|
|
3452
|
+
{
|
|
3453
|
+
method: "POST",
|
|
3454
|
+
headers,
|
|
3455
|
+
body: JSON.stringify(message)
|
|
3456
|
+
}
|
|
3457
|
+
);
|
|
3458
|
+
}
|
|
3459
|
+
subscribeToConversation(conversationId, callback, options = {}) {
|
|
3460
|
+
let stopped = false;
|
|
3461
|
+
let timer = null;
|
|
3462
|
+
const intervalMs = Math.max(500, options.intervalMs ?? 1500);
|
|
3463
|
+
const tick = async () => {
|
|
3464
|
+
if (stopped) return;
|
|
3465
|
+
try {
|
|
3466
|
+
callback(await this.getConversation(conversationId));
|
|
3467
|
+
} finally {
|
|
3468
|
+
if (!stopped) timer = setTimeout(tick, intervalMs);
|
|
3469
|
+
}
|
|
3470
|
+
};
|
|
3471
|
+
void tick();
|
|
3472
|
+
return {
|
|
3473
|
+
unsubscribe: () => {
|
|
3474
|
+
stopped = true;
|
|
3475
|
+
if (timer) clearTimeout(timer);
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
}
|
|
2840
3479
|
};
|
|
2841
3480
|
var RagableBrowser = class {
|
|
2842
3481
|
constructor(options) {
|
|
@@ -3009,6 +3648,7 @@ function createRagableServerClient(options) {
|
|
|
3009
3648
|
asPostgrestResponse,
|
|
3010
3649
|
assertPostgrestSuccess,
|
|
3011
3650
|
bindFetch,
|
|
3651
|
+
collectAssistantTextFromUiSegments,
|
|
3012
3652
|
collectionRecordToRowWithMeta,
|
|
3013
3653
|
collectionRecordsToRowWithMeta,
|
|
3014
3654
|
createBrowserClient,
|
|
@@ -3019,14 +3659,22 @@ function createRagableServerClient(options) {
|
|
|
3019
3659
|
detectStorage,
|
|
3020
3660
|
effectiveDataAuth,
|
|
3021
3661
|
extractErrorMessage,
|
|
3662
|
+
finalizeAgentChatUiTurn,
|
|
3663
|
+
foldAgentStreamIntoUiSegments,
|
|
3022
3664
|
formatPostgrestError,
|
|
3023
3665
|
formatRetrievalContext,
|
|
3024
3666
|
formatSdkError,
|
|
3025
3667
|
generateIdempotencyKey,
|
|
3668
|
+
isIncompleteAgentStreamError,
|
|
3026
3669
|
normalizeBrowserApiBase,
|
|
3670
|
+
parseAgentStreamAgentInfo,
|
|
3671
|
+
parseAgentStreamDone,
|
|
3027
3672
|
parseSseDataLine,
|
|
3028
3673
|
parseTransportResponse,
|
|
3029
3674
|
readSseStream,
|
|
3675
|
+
runAgentChatStream,
|
|
3676
|
+
runAgentChatStreamForUi,
|
|
3677
|
+
runAgentChatStreamLenient,
|
|
3030
3678
|
toRagableResult,
|
|
3031
3679
|
unwrapPostgrest
|
|
3032
3680
|
});
|