@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.mjs
CHANGED
|
@@ -327,6 +327,442 @@ function toArrayBuffer(value) {
|
|
|
327
327
|
return copy.buffer;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
// src/agent-stream.ts
|
|
331
|
+
function assertAborted(signal) {
|
|
332
|
+
if (signal?.aborted) {
|
|
333
|
+
throw new RagableAbortError();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
function asString(v, fallback = "") {
|
|
337
|
+
return typeof v === "string" ? v : fallback;
|
|
338
|
+
}
|
|
339
|
+
function asNumber(v, fallback = 0) {
|
|
340
|
+
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
341
|
+
}
|
|
342
|
+
function asUnknownArray(v) {
|
|
343
|
+
return Array.isArray(v) ? v : [];
|
|
344
|
+
}
|
|
345
|
+
function parseAgentStreamDone(e) {
|
|
346
|
+
if (e.type !== "done") return null;
|
|
347
|
+
return {
|
|
348
|
+
response: asString(e["response"]),
|
|
349
|
+
traces: asUnknownArray(e["traces"]),
|
|
350
|
+
totalDurationMs: asNumber(e["totalDurationMs"]),
|
|
351
|
+
...e["httpResponse"] !== void 0 ? { httpResponse: e["httpResponse"] } : {},
|
|
352
|
+
...typeof e["inputTokens"] === "number" ? { inputTokens: e["inputTokens"] } : {},
|
|
353
|
+
...typeof e["outputTokens"] === "number" ? { outputTokens: e["outputTokens"] } : {},
|
|
354
|
+
...typeof e["cachedPromptTokens"] === "number" ? { cachedPromptTokens: e["cachedPromptTokens"] } : {},
|
|
355
|
+
...typeof e["cacheCreationInputTokens"] === "number" ? { cacheCreationInputTokens: e["cacheCreationInputTokens"] } : {},
|
|
356
|
+
...Array.isArray(e["completionProviders"]) ? {
|
|
357
|
+
completionProviders: e["completionProviders"].map((x) => String(x))
|
|
358
|
+
} : {},
|
|
359
|
+
...typeof e["creditsCharged"] === "number" ? { creditsCharged: e["creditsCharged"] } : {},
|
|
360
|
+
...typeof e["agentSteps"] === "number" ? { agentSteps: e["agentSteps"] } : {},
|
|
361
|
+
...e["finishReason"] !== void 0 ? { finishReason: e["finishReason"] } : {},
|
|
362
|
+
...e["stopReason"] !== void 0 ? { stopReason: e["stopReason"] } : {},
|
|
363
|
+
...e["turnMessages"] !== void 0 ? { turnMessages: e["turnMessages"] } : {},
|
|
364
|
+
...typeof e["promptTokensEstimated"] === "number" ? { promptTokensEstimated: e["promptTokensEstimated"] } : {},
|
|
365
|
+
...typeof e["contextWindow"] === "number" ? { contextWindow: e["contextWindow"] } : {}
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function parseAgentStreamAgentInfo(e) {
|
|
369
|
+
if (e.type !== "agent:info") return null;
|
|
370
|
+
return {
|
|
371
|
+
type: "agent:info",
|
|
372
|
+
name: asString(e["name"]),
|
|
373
|
+
agent_name: asString(e["agent_name"])
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function parseAgentInfo(e) {
|
|
377
|
+
return parseAgentStreamAgentInfo(e);
|
|
378
|
+
}
|
|
379
|
+
async function runAgentChatStream(source, handlers = {}, options = {}) {
|
|
380
|
+
const { signal } = options;
|
|
381
|
+
let assistantText = "";
|
|
382
|
+
let reasoningText = "";
|
|
383
|
+
let donePayload = null;
|
|
384
|
+
try {
|
|
385
|
+
for await (const event of source) {
|
|
386
|
+
assertAborted(signal);
|
|
387
|
+
handlers.onEvent?.(event);
|
|
388
|
+
const info = parseAgentInfo(event);
|
|
389
|
+
if (info) {
|
|
390
|
+
handlers.onAgentInfo?.(info);
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
switch (event.type) {
|
|
394
|
+
case "ping":
|
|
395
|
+
handlers.onPing?.();
|
|
396
|
+
break;
|
|
397
|
+
case "token": {
|
|
398
|
+
const nodeId = asString(event["nodeId"], "__self__");
|
|
399
|
+
const token = asString(event["token"]);
|
|
400
|
+
assistantText += token;
|
|
401
|
+
handlers.onToken?.(token, { nodeId });
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
case "reasoning_token": {
|
|
405
|
+
const nodeId = asString(event["nodeId"], "__self__");
|
|
406
|
+
const token = asString(event["token"]);
|
|
407
|
+
reasoningText += token;
|
|
408
|
+
handlers.onReasoningToken?.(token, { nodeId });
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
case "tool:call":
|
|
412
|
+
handlers.onToolCall?.({
|
|
413
|
+
nodeId: asString(event["nodeId"]),
|
|
414
|
+
toolName: asString(event["toolName"]),
|
|
415
|
+
args: event["args"]
|
|
416
|
+
});
|
|
417
|
+
break;
|
|
418
|
+
case "tool:args_update": {
|
|
419
|
+
const raw = event["args"];
|
|
420
|
+
const args = raw !== null && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
421
|
+
handlers.onToolArgsUpdate?.({
|
|
422
|
+
nodeId: asString(event["nodeId"]),
|
|
423
|
+
args
|
|
424
|
+
});
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
case "tool:result":
|
|
428
|
+
handlers.onToolResult?.({
|
|
429
|
+
nodeId: asString(event["nodeId"]),
|
|
430
|
+
toolName: asString(event["toolName"]),
|
|
431
|
+
durationMs: asNumber(event["durationMs"]),
|
|
432
|
+
...typeof event["result"] === "string" ? { result: event["result"] } : {}
|
|
433
|
+
});
|
|
434
|
+
break;
|
|
435
|
+
case "node:start":
|
|
436
|
+
handlers.onNodeStart?.({
|
|
437
|
+
nodeId: asString(event["nodeId"]),
|
|
438
|
+
nodeType: asString(event["nodeType"]),
|
|
439
|
+
label: asString(event["label"])
|
|
440
|
+
});
|
|
441
|
+
break;
|
|
442
|
+
case "node:complete":
|
|
443
|
+
handlers.onNodeComplete?.({
|
|
444
|
+
nodeId: asString(event["nodeId"]),
|
|
445
|
+
output: event["output"],
|
|
446
|
+
durationMs: asNumber(event["durationMs"])
|
|
447
|
+
});
|
|
448
|
+
break;
|
|
449
|
+
case "node:error":
|
|
450
|
+
handlers.onNodeError?.({
|
|
451
|
+
nodeId: asString(event["nodeId"]),
|
|
452
|
+
error: asString(event["error"])
|
|
453
|
+
});
|
|
454
|
+
break;
|
|
455
|
+
case "done": {
|
|
456
|
+
const parsed = parseAgentStreamDone(event);
|
|
457
|
+
if (parsed) {
|
|
458
|
+
donePayload = parsed;
|
|
459
|
+
handlers.onDone?.(parsed);
|
|
460
|
+
}
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
default:
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
} catch (err) {
|
|
468
|
+
handlers.onError?.(err);
|
|
469
|
+
throw err;
|
|
470
|
+
}
|
|
471
|
+
if (!donePayload) {
|
|
472
|
+
const err = new RagableError(
|
|
473
|
+
"Agent stream ended without a done event",
|
|
474
|
+
502,
|
|
475
|
+
{ code: "SDK_AGENT_STREAM_INCOMPLETE" }
|
|
476
|
+
);
|
|
477
|
+
handlers.onError?.(err);
|
|
478
|
+
throw err;
|
|
479
|
+
}
|
|
480
|
+
const result = {
|
|
481
|
+
...donePayload,
|
|
482
|
+
assistantText,
|
|
483
|
+
reasoningText
|
|
484
|
+
};
|
|
485
|
+
handlers.onComplete?.(result);
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
488
|
+
async function runAgentChatStreamLenient(source, handlers = {}, options = {}) {
|
|
489
|
+
try {
|
|
490
|
+
return await runAgentChatStream(source, handlers, options);
|
|
491
|
+
} catch (e) {
|
|
492
|
+
if (e instanceof RagableError && e.code === "SDK_AGENT_STREAM_INCOMPLETE") {
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
495
|
+
throw e;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
function isIncompleteAgentStreamError(e) {
|
|
499
|
+
return e instanceof RagableError && e.code === "SDK_AGENT_STREAM_INCOMPLETE";
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// src/agent-chat-ui.ts
|
|
503
|
+
function asString2(v, fallback = "") {
|
|
504
|
+
return typeof v === "string" ? v : fallback;
|
|
505
|
+
}
|
|
506
|
+
function asNumber2(v, fallback = 0) {
|
|
507
|
+
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
508
|
+
}
|
|
509
|
+
function assertAborted2(signal) {
|
|
510
|
+
if (signal?.aborted) {
|
|
511
|
+
throw new RagableAbortError();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
function recordFromUnknown(v) {
|
|
515
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v)) {
|
|
516
|
+
return { ...v };
|
|
517
|
+
}
|
|
518
|
+
return {};
|
|
519
|
+
}
|
|
520
|
+
function lastToolBlocksStream(last) {
|
|
521
|
+
return last?.type === "tool" && last.status === "started";
|
|
522
|
+
}
|
|
523
|
+
function toolSegmentId(event) {
|
|
524
|
+
const nid = event["nodeId"];
|
|
525
|
+
if (typeof nid === "string" && nid.length > 0) return nid;
|
|
526
|
+
const tn = event["toolName"];
|
|
527
|
+
if (typeof tn === "string" && tn.length > 0) return tn;
|
|
528
|
+
return "__tool__";
|
|
529
|
+
}
|
|
530
|
+
function normalizeContextSummarizedMode(m) {
|
|
531
|
+
if (m === "llm" || m === "heuristic" || m === "llm+heuristic" || m === "aggressive") {
|
|
532
|
+
return m;
|
|
533
|
+
}
|
|
534
|
+
return void 0;
|
|
535
|
+
}
|
|
536
|
+
function normalizeContextSummarizedReason(r) {
|
|
537
|
+
if (r === "soft_limit" || r === "forced") return r;
|
|
538
|
+
return void 0;
|
|
539
|
+
}
|
|
540
|
+
function foldContextSummarized(prev, event) {
|
|
541
|
+
const step = asNumber2(event["step"], 0);
|
|
542
|
+
const mode = normalizeContextSummarizedMode(event["mode"]);
|
|
543
|
+
const reason = normalizeContextSummarizedReason(event["reason"]);
|
|
544
|
+
const tro = event["tokensRemovedEstimate"];
|
|
545
|
+
const eta = event["estimatedTokensAfter"];
|
|
546
|
+
return [
|
|
547
|
+
...prev,
|
|
548
|
+
{
|
|
549
|
+
type: "context_summarized",
|
|
550
|
+
step,
|
|
551
|
+
...mode ? { mode } : {},
|
|
552
|
+
...reason ? { reason } : {},
|
|
553
|
+
...typeof tro === "number" && tro > 0 ? { tokensRemovedEstimate: tro } : {},
|
|
554
|
+
...typeof eta === "number" && eta > 0 ? { estimatedTokensAfter: eta } : {}
|
|
555
|
+
}
|
|
556
|
+
];
|
|
557
|
+
}
|
|
558
|
+
function collectAssistantTextFromUiSegments(segments) {
|
|
559
|
+
return segments.filter((s) => s.type === "text").map((s) => s.content).join("");
|
|
560
|
+
}
|
|
561
|
+
function foldAgentStreamIntoUiSegments(prev, event) {
|
|
562
|
+
switch (event.type) {
|
|
563
|
+
case "token": {
|
|
564
|
+
const last = prev[prev.length - 1];
|
|
565
|
+
if (lastToolBlocksStream(last)) return prev;
|
|
566
|
+
const token = asString2(event["token"]);
|
|
567
|
+
if (!token) return prev;
|
|
568
|
+
if (last?.type === "text") {
|
|
569
|
+
return [
|
|
570
|
+
...prev.slice(0, -1),
|
|
571
|
+
{ type: "text", content: last.content + token }
|
|
572
|
+
];
|
|
573
|
+
}
|
|
574
|
+
return [...prev, { type: "text", content: token }];
|
|
575
|
+
}
|
|
576
|
+
case "reasoning_token": {
|
|
577
|
+
const last = prev[prev.length - 1];
|
|
578
|
+
if (lastToolBlocksStream(last)) return prev;
|
|
579
|
+
const token = asString2(event["token"]);
|
|
580
|
+
if (!token) return prev;
|
|
581
|
+
if (last?.type === "reasoning") {
|
|
582
|
+
return [
|
|
583
|
+
...prev.slice(0, -1),
|
|
584
|
+
{ type: "reasoning", content: last.content + token }
|
|
585
|
+
];
|
|
586
|
+
}
|
|
587
|
+
return [...prev, { type: "reasoning", content: token }];
|
|
588
|
+
}
|
|
589
|
+
case "tool:call": {
|
|
590
|
+
const id = toolSegmentId(event);
|
|
591
|
+
const toolName = asString2(event["toolName"], "tool");
|
|
592
|
+
const argsRaw = event["args"];
|
|
593
|
+
const args = argsRaw !== null && typeof argsRaw === "object" && !Array.isArray(argsRaw) ? argsRaw : void 0;
|
|
594
|
+
return [
|
|
595
|
+
...prev,
|
|
596
|
+
{
|
|
597
|
+
type: "tool",
|
|
598
|
+
id,
|
|
599
|
+
toolName,
|
|
600
|
+
status: "started",
|
|
601
|
+
...args !== void 0 ? { args } : {}
|
|
602
|
+
}
|
|
603
|
+
];
|
|
604
|
+
}
|
|
605
|
+
case "tool:args_update": {
|
|
606
|
+
const nodeId = asString2(event["nodeId"]);
|
|
607
|
+
const patch = recordFromUnknown(event["args"]);
|
|
608
|
+
return prev.map((seg) => {
|
|
609
|
+
if (seg.type !== "tool" || seg.id !== nodeId) return seg;
|
|
610
|
+
const merged = { ...recordFromUnknown(seg.args), ...patch };
|
|
611
|
+
return {
|
|
612
|
+
...seg,
|
|
613
|
+
args: merged
|
|
614
|
+
};
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
case "tool:result": {
|
|
618
|
+
const nodeId = asString2(event["nodeId"]);
|
|
619
|
+
const toolName = asString2(event["toolName"]) || asString2(event["nodeId"]);
|
|
620
|
+
const durationMs = typeof event["durationMs"] === "number" ? event["durationMs"] : void 0;
|
|
621
|
+
const resultStr = typeof event["result"] === "string" ? event["result"] : void 0;
|
|
622
|
+
let idx = -1;
|
|
623
|
+
if (nodeId) {
|
|
624
|
+
for (let i = prev.length - 1; i >= 0; i--) {
|
|
625
|
+
const s = prev[i];
|
|
626
|
+
if (s.type === "tool" && s.status === "started" && s.id === nodeId) {
|
|
627
|
+
idx = i;
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (idx < 0 && toolName) {
|
|
633
|
+
for (let i = prev.length - 1; i >= 0; i--) {
|
|
634
|
+
const s = prev[i];
|
|
635
|
+
if (s.type === "tool" && s.status === "started" && s.toolName === toolName) {
|
|
636
|
+
idx = i;
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
if (idx < 0) return prev;
|
|
642
|
+
const next = [...prev];
|
|
643
|
+
const seg = next[idx];
|
|
644
|
+
if (seg.type !== "tool") return prev;
|
|
645
|
+
next[idx] = {
|
|
646
|
+
...seg,
|
|
647
|
+
status: "completed",
|
|
648
|
+
...durationMs !== void 0 ? { durationMs } : {},
|
|
649
|
+
...resultStr !== void 0 ? { result: resultStr } : {}
|
|
650
|
+
};
|
|
651
|
+
return next;
|
|
652
|
+
}
|
|
653
|
+
case "context_summarized":
|
|
654
|
+
return foldContextSummarized(prev, event);
|
|
655
|
+
case "llm_step": {
|
|
656
|
+
return [
|
|
657
|
+
...prev,
|
|
658
|
+
{
|
|
659
|
+
type: "llm_step",
|
|
660
|
+
step: Number(event["step"]),
|
|
661
|
+
inputTokens: Number(event["inputTokens"] ?? 0),
|
|
662
|
+
outputTokens: Number(event["outputTokens"] ?? 0),
|
|
663
|
+
...typeof event["cachedPromptTokens"] === "number" ? { cachedPromptTokens: event["cachedPromptTokens"] } : {},
|
|
664
|
+
...typeof event["cacheCreationInputTokens"] === "number" ? { cacheCreationInputTokens: event["cacheCreationInputTokens"] } : {},
|
|
665
|
+
creditsEstimated: Number(event["creditsEstimated"] ?? 0),
|
|
666
|
+
...typeof event["apiCostUsd"] === "number" && Number.isFinite(event["apiCostUsd"]) ? { apiCostUsd: event["apiCostUsd"] } : {},
|
|
667
|
+
...typeof event["provider"] === "string" && event["provider"] ? { provider: event["provider"] } : {}
|
|
668
|
+
}
|
|
669
|
+
];
|
|
670
|
+
}
|
|
671
|
+
default:
|
|
672
|
+
return prev;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
function finalizeAgentChatUiTurn(segments, done) {
|
|
676
|
+
let segs = segments.length > 0 ? [...segments] : void 0;
|
|
677
|
+
if (done.stopReason) {
|
|
678
|
+
const stopSeg = {
|
|
679
|
+
type: "stop_reason",
|
|
680
|
+
content: done.stopReason,
|
|
681
|
+
finishReason: done.finishReason ?? "error"
|
|
682
|
+
};
|
|
683
|
+
segs = segs ? [...segs, stopSeg] : [stopSeg];
|
|
684
|
+
}
|
|
685
|
+
const fromText = segs ? collectAssistantTextFromUiSegments(segs) : "";
|
|
686
|
+
const content = done.response || fromText || "No response.";
|
|
687
|
+
const message = {
|
|
688
|
+
role: "ai",
|
|
689
|
+
content,
|
|
690
|
+
...segs && segs.length > 0 ? { segments: segs } : {},
|
|
691
|
+
finishReason: done.finishReason ?? null,
|
|
692
|
+
...Array.isArray(done.completionProviders) && done.completionProviders.length > 0 ? { completionProviders: done.completionProviders } : {},
|
|
693
|
+
...typeof done.agentSteps === "number" && Number.isFinite(done.agentSteps) && done.agentSteps > 0 ? { agentSteps: Math.floor(done.agentSteps) } : {},
|
|
694
|
+
usage: {
|
|
695
|
+
inputTokens: done.inputTokens ?? 0,
|
|
696
|
+
outputTokens: done.outputTokens ?? 0,
|
|
697
|
+
creditsCharged: done.creditsCharged ?? 0,
|
|
698
|
+
...typeof done.cachedPromptTokens === "number" && done.cachedPromptTokens > 0 ? { cachedPromptTokens: done.cachedPromptTokens } : {},
|
|
699
|
+
...typeof done.cacheCreationInputTokens === "number" && done.cacheCreationInputTokens > 0 ? { cacheCreationInputTokens: done.cacheCreationInputTokens } : {}
|
|
700
|
+
},
|
|
701
|
+
...typeof done.totalDurationMs === "number" && done.totalDurationMs > 0 ? { durationMs: done.totalDurationMs } : {}
|
|
702
|
+
};
|
|
703
|
+
return { segments: segs ?? [], message };
|
|
704
|
+
}
|
|
705
|
+
async function runAgentChatStreamForUi(source, handlers = {}, options = {}) {
|
|
706
|
+
const { signal } = options;
|
|
707
|
+
let segments = [];
|
|
708
|
+
let donePayload = null;
|
|
709
|
+
try {
|
|
710
|
+
for await (const event of source) {
|
|
711
|
+
assertAborted2(signal);
|
|
712
|
+
handlers.onEvent?.(event);
|
|
713
|
+
const info = parseAgentStreamAgentInfo(event);
|
|
714
|
+
if (info) {
|
|
715
|
+
handlers.onAgentInfo?.(info);
|
|
716
|
+
continue;
|
|
717
|
+
}
|
|
718
|
+
if (event.type === "ping") continue;
|
|
719
|
+
if (event.type === "done") {
|
|
720
|
+
const parsed = parseAgentStreamDone(event);
|
|
721
|
+
if (parsed) {
|
|
722
|
+
donePayload = parsed;
|
|
723
|
+
handlers.onDone?.(parsed);
|
|
724
|
+
}
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
const next = foldAgentStreamIntoUiSegments(segments, event);
|
|
728
|
+
if (next !== segments) {
|
|
729
|
+
segments = next;
|
|
730
|
+
handlers.onSegments?.(segments);
|
|
731
|
+
if (event.type === "token") {
|
|
732
|
+
handlers.onStreamingText?.(
|
|
733
|
+
collectAssistantTextFromUiSegments(segments)
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
} catch (err) {
|
|
739
|
+
handlers.onError?.(err);
|
|
740
|
+
throw err;
|
|
741
|
+
}
|
|
742
|
+
if (!donePayload) {
|
|
743
|
+
const err = new RagableError(
|
|
744
|
+
"Agent stream ended without a done event",
|
|
745
|
+
502,
|
|
746
|
+
{ code: "SDK_AGENT_STREAM_INCOMPLETE" }
|
|
747
|
+
);
|
|
748
|
+
handlers.onError?.(err);
|
|
749
|
+
throw err;
|
|
750
|
+
}
|
|
751
|
+
const segmentsMidTurn = [...segments];
|
|
752
|
+
const { segments: finalSegs, message } = finalizeAgentChatUiTurn(
|
|
753
|
+
segments,
|
|
754
|
+
donePayload
|
|
755
|
+
);
|
|
756
|
+
const result = {
|
|
757
|
+
segmentsMidTurn,
|
|
758
|
+
segments: finalSegs,
|
|
759
|
+
message,
|
|
760
|
+
done: donePayload
|
|
761
|
+
};
|
|
762
|
+
handlers.onComplete?.(result);
|
|
763
|
+
return result;
|
|
764
|
+
}
|
|
765
|
+
|
|
330
766
|
// src/sse.ts
|
|
331
767
|
async function parseMaybeJsonBody(response) {
|
|
332
768
|
const contentType = response.headers.get("content-type") ?? "";
|
|
@@ -426,7 +862,8 @@ var AgentsClient = class {
|
|
|
426
862
|
body: {
|
|
427
863
|
message: params.message,
|
|
428
864
|
...params.history !== void 0 ? { history: params.history } : {}
|
|
429
|
-
}
|
|
865
|
+
},
|
|
866
|
+
...params.signal !== void 0 ? { signal: params.signal } : {}
|
|
430
867
|
}
|
|
431
868
|
);
|
|
432
869
|
if (!response.ok) {
|
|
@@ -440,6 +877,24 @@ var AgentsClient = class {
|
|
|
440
877
|
}
|
|
441
878
|
yield* readSseStream(body);
|
|
442
879
|
}
|
|
880
|
+
/**
|
|
881
|
+
* Stream an agent turn with callbacks; returns the final `done` payload plus streamed text.
|
|
882
|
+
* Prefer this over manual iteration when building chat UIs against the server API key client.
|
|
883
|
+
*/
|
|
884
|
+
async runChatStream(agentId, params, handlers = {}) {
|
|
885
|
+
return runAgentChatStream(this.chatStream(agentId, params), handlers, {
|
|
886
|
+
signal: params.signal
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Stream with dashboard-style `AgentChat` ergonomics: {@link AgentChatStreamUiHandlers.onSegments}
|
|
891
|
+
* / `onStreamingText` for live UI; returns a persisted-shaped assistant message on `done`.
|
|
892
|
+
*/
|
|
893
|
+
async runChatUi(agentId, params, handlers = {}) {
|
|
894
|
+
return runAgentChatStreamForUi(this.chatStream(agentId, params), handlers, {
|
|
895
|
+
signal: params.signal
|
|
896
|
+
});
|
|
897
|
+
}
|
|
443
898
|
};
|
|
444
899
|
|
|
445
900
|
// src/transport.ts
|
|
@@ -2297,6 +2752,18 @@ var BrowserCollectionApi = class {
|
|
|
2297
2752
|
this.databaseInstanceId
|
|
2298
2753
|
)
|
|
2299
2754
|
));
|
|
2755
|
+
/**
|
|
2756
|
+
* Insert multiple rows in one request (server multi-value `INSERT`, single transaction).
|
|
2757
|
+
* Empty **`items`** resolves to an empty array. Max batch size is enforced on the server (500).
|
|
2758
|
+
*/
|
|
2759
|
+
__publicField(this, "insertMany", (items) => asPostgrestResponse(
|
|
2760
|
+
() => this.database._requestCollection(
|
|
2761
|
+
"POST",
|
|
2762
|
+
`/${encodeURIComponent(this.name)}/records/batch`,
|
|
2763
|
+
{ items },
|
|
2764
|
+
this.databaseInstanceId
|
|
2765
|
+
)
|
|
2766
|
+
));
|
|
2300
2767
|
/**
|
|
2301
2768
|
* Update rows matching `where` (JSON fields, plus envelope `id` / `createdAt` / `updatedAt`).
|
|
2302
2769
|
*/
|
|
@@ -2325,6 +2792,21 @@ var BrowserCollectionApi = class {
|
|
|
2325
2792
|
this.databaseInstanceId
|
|
2326
2793
|
)
|
|
2327
2794
|
));
|
|
2795
|
+
/**
|
|
2796
|
+
* Like {@link BrowserCollectionApi.delete} but the success payload includes **`meta.count`**
|
|
2797
|
+
* (number of deleted rows), matching {@link BrowserCollectionApi.updateMany}.
|
|
2798
|
+
*/
|
|
2799
|
+
__publicField(this, "deleteMany", async (where, options) => {
|
|
2800
|
+
const r = await this.delete(where, options);
|
|
2801
|
+
if (r.error) return r;
|
|
2802
|
+
return {
|
|
2803
|
+
data: {
|
|
2804
|
+
records: r.data.records,
|
|
2805
|
+
meta: { count: r.data.deleted }
|
|
2806
|
+
},
|
|
2807
|
+
error: null
|
|
2808
|
+
};
|
|
2809
|
+
});
|
|
2328
2810
|
}
|
|
2329
2811
|
normalizeFindArgs(whereOrParams) {
|
|
2330
2812
|
const hasQueryKeys = typeof whereOrParams === "object" && whereOrParams !== null && FIND_QUERY_KEYS.some(
|
|
@@ -2729,6 +3211,31 @@ var RagableBrowserAgentsClient = class {
|
|
|
2729
3211
|
toUrl(path) {
|
|
2730
3212
|
return `${normalizeBrowserApiBase()}${path.startsWith("/") ? path : `/${path}`}`;
|
|
2731
3213
|
}
|
|
3214
|
+
requireWebsiteId() {
|
|
3215
|
+
const websiteId = this.options.websiteId?.trim();
|
|
3216
|
+
if (!websiteId) {
|
|
3217
|
+
throw new RagableError(
|
|
3218
|
+
"websiteId is required for project agent conversation APIs. Use the generated createWebsiteRagableClient() or pass createBrowserClient({ websiteId, ... }).",
|
|
3219
|
+
400,
|
|
3220
|
+
{ code: "SDK_MISSING_WEBSITE_ID" }
|
|
3221
|
+
);
|
|
3222
|
+
}
|
|
3223
|
+
return websiteId;
|
|
3224
|
+
}
|
|
3225
|
+
websiteAgentPath(path) {
|
|
3226
|
+
const websiteId = this.requireWebsiteId();
|
|
3227
|
+
return `/public/organizations/${this.options.organizationId}/websites/${websiteId}${path}`;
|
|
3228
|
+
}
|
|
3229
|
+
async requestJson(path, init = {}) {
|
|
3230
|
+
const response = await this.fetchImpl(this.toUrl(path), init);
|
|
3231
|
+
const payload = await parseMaybeJsonBody(response);
|
|
3232
|
+
if (!response.ok) {
|
|
3233
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
3234
|
+
throw new RagableError(message, response.status, payload);
|
|
3235
|
+
}
|
|
3236
|
+
return payload;
|
|
3237
|
+
}
|
|
3238
|
+
/** @deprecated Prefer `chatStreamByName(agentName, params)` for project-local `/agents/*.json` agents. */
|
|
2732
3239
|
async *chatStream(agentId, params) {
|
|
2733
3240
|
const orgId = this.options.organizationId;
|
|
2734
3241
|
const body = {
|
|
@@ -2744,7 +3251,8 @@ var RagableBrowserAgentsClient = class {
|
|
|
2744
3251
|
{
|
|
2745
3252
|
method: "POST",
|
|
2746
3253
|
headers,
|
|
2747
|
-
body: JSON.stringify(body)
|
|
3254
|
+
body: JSON.stringify(body),
|
|
3255
|
+
...params.signal !== void 0 ? { signal: params.signal } : {}
|
|
2748
3256
|
}
|
|
2749
3257
|
);
|
|
2750
3258
|
if (!response.ok) {
|
|
@@ -2758,6 +3266,128 @@ var RagableBrowserAgentsClient = class {
|
|
|
2758
3266
|
}
|
|
2759
3267
|
yield* readSseStream(streamBody);
|
|
2760
3268
|
}
|
|
3269
|
+
async *chatStreamByName(agentName, params) {
|
|
3270
|
+
const headers = new Headers(this.options.headers);
|
|
3271
|
+
headers.set("Content-Type", "application/json");
|
|
3272
|
+
const response = await this.fetchImpl(
|
|
3273
|
+
this.toUrl(
|
|
3274
|
+
this.websiteAgentPath(
|
|
3275
|
+
`/agents/${encodeURIComponent(agentName)}/chat/stream`
|
|
3276
|
+
)
|
|
3277
|
+
),
|
|
3278
|
+
{
|
|
3279
|
+
method: "POST",
|
|
3280
|
+
headers,
|
|
3281
|
+
body: JSON.stringify({
|
|
3282
|
+
message: params.message,
|
|
3283
|
+
...params.history !== void 0 ? { history: params.history } : {}
|
|
3284
|
+
}),
|
|
3285
|
+
...params.signal !== void 0 ? { signal: params.signal } : {}
|
|
3286
|
+
}
|
|
3287
|
+
);
|
|
3288
|
+
if (!response.ok) {
|
|
3289
|
+
const payload = await parseMaybeJsonBody(response);
|
|
3290
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
3291
|
+
throw new RagableError(message, response.status, payload);
|
|
3292
|
+
}
|
|
3293
|
+
if (!response.body) return;
|
|
3294
|
+
yield* readSseStream(response.body);
|
|
3295
|
+
}
|
|
3296
|
+
/**
|
|
3297
|
+
* Stream a project agent (`/agents/*.json`) with callbacks; returns the final `done` payload
|
|
3298
|
+
* plus streamed assistant text. Prefer this over manual `for await` when building chat UIs.
|
|
3299
|
+
*/
|
|
3300
|
+
async runChatStreamByName(agentName, params, handlers = {}) {
|
|
3301
|
+
return runAgentChatStream(this.chatStreamByName(agentName, params), handlers, {
|
|
3302
|
+
signal: params.signal
|
|
3303
|
+
});
|
|
3304
|
+
}
|
|
3305
|
+
/**
|
|
3306
|
+
* Same as {@link runChatStreamByName} but folds events into `AgentChat`-style segments
|
|
3307
|
+
* (`onSegments` / `onStreamingText`) and returns a history-ready assistant message.
|
|
3308
|
+
*/
|
|
3309
|
+
async runChatUiByName(agentName, params, handlers = {}) {
|
|
3310
|
+
return runAgentChatStreamForUi(
|
|
3311
|
+
this.chatStreamByName(agentName, params),
|
|
3312
|
+
handlers,
|
|
3313
|
+
{ signal: params.signal }
|
|
3314
|
+
);
|
|
3315
|
+
}
|
|
3316
|
+
createConversation(params) {
|
|
3317
|
+
const headers = new Headers(this.options.headers);
|
|
3318
|
+
headers.set("Content-Type", "application/json");
|
|
3319
|
+
return this.requestJson(
|
|
3320
|
+
this.websiteAgentPath("/agent-conversations"),
|
|
3321
|
+
{
|
|
3322
|
+
method: "POST",
|
|
3323
|
+
headers,
|
|
3324
|
+
body: JSON.stringify(params)
|
|
3325
|
+
}
|
|
3326
|
+
);
|
|
3327
|
+
}
|
|
3328
|
+
listConversations(params = {}) {
|
|
3329
|
+
const agentName = params.agent_name ?? params.agentName;
|
|
3330
|
+
const qs = agentName ? `?agentName=${encodeURIComponent(agentName)}` : "";
|
|
3331
|
+
return this.requestJson(
|
|
3332
|
+
this.websiteAgentPath(`/agent-conversations${qs}`)
|
|
3333
|
+
);
|
|
3334
|
+
}
|
|
3335
|
+
getConversation(conversationId) {
|
|
3336
|
+
return this.requestJson(
|
|
3337
|
+
this.websiteAgentPath(
|
|
3338
|
+
`/agent-conversations/${encodeURIComponent(conversationId)}`
|
|
3339
|
+
)
|
|
3340
|
+
);
|
|
3341
|
+
}
|
|
3342
|
+
updateConversation(conversationId, data) {
|
|
3343
|
+
const headers = new Headers(this.options.headers);
|
|
3344
|
+
headers.set("Content-Type", "application/json");
|
|
3345
|
+
return this.requestJson(
|
|
3346
|
+
this.websiteAgentPath(
|
|
3347
|
+
`/agent-conversations/${encodeURIComponent(conversationId)}`
|
|
3348
|
+
),
|
|
3349
|
+
{
|
|
3350
|
+
method: "PATCH",
|
|
3351
|
+
headers,
|
|
3352
|
+
body: JSON.stringify(data)
|
|
3353
|
+
}
|
|
3354
|
+
);
|
|
3355
|
+
}
|
|
3356
|
+
addMessage(conversationOrId, message) {
|
|
3357
|
+
const conversationId = typeof conversationOrId === "string" ? conversationOrId : conversationOrId.id;
|
|
3358
|
+
const headers = new Headers(this.options.headers);
|
|
3359
|
+
headers.set("Content-Type", "application/json");
|
|
3360
|
+
return this.requestJson(
|
|
3361
|
+
this.websiteAgentPath(
|
|
3362
|
+
`/agent-conversations/${encodeURIComponent(conversationId)}/messages`
|
|
3363
|
+
),
|
|
3364
|
+
{
|
|
3365
|
+
method: "POST",
|
|
3366
|
+
headers,
|
|
3367
|
+
body: JSON.stringify(message)
|
|
3368
|
+
}
|
|
3369
|
+
);
|
|
3370
|
+
}
|
|
3371
|
+
subscribeToConversation(conversationId, callback, options = {}) {
|
|
3372
|
+
let stopped = false;
|
|
3373
|
+
let timer = null;
|
|
3374
|
+
const intervalMs = Math.max(500, options.intervalMs ?? 1500);
|
|
3375
|
+
const tick = async () => {
|
|
3376
|
+
if (stopped) return;
|
|
3377
|
+
try {
|
|
3378
|
+
callback(await this.getConversation(conversationId));
|
|
3379
|
+
} finally {
|
|
3380
|
+
if (!stopped) timer = setTimeout(tick, intervalMs);
|
|
3381
|
+
}
|
|
3382
|
+
};
|
|
3383
|
+
void tick();
|
|
3384
|
+
return {
|
|
3385
|
+
unsubscribe: () => {
|
|
3386
|
+
stopped = true;
|
|
3387
|
+
if (timer) clearTimeout(timer);
|
|
3388
|
+
}
|
|
3389
|
+
};
|
|
3390
|
+
}
|
|
2761
3391
|
};
|
|
2762
3392
|
var RagableBrowser = class {
|
|
2763
3393
|
constructor(options) {
|
|
@@ -2929,6 +3559,7 @@ export {
|
|
|
2929
3559
|
asPostgrestResponse,
|
|
2930
3560
|
assertPostgrestSuccess,
|
|
2931
3561
|
bindFetch,
|
|
3562
|
+
collectAssistantTextFromUiSegments,
|
|
2932
3563
|
collectionRecordToRowWithMeta,
|
|
2933
3564
|
collectionRecordsToRowWithMeta,
|
|
2934
3565
|
createBrowserClient,
|
|
@@ -2939,14 +3570,22 @@ export {
|
|
|
2939
3570
|
detectStorage,
|
|
2940
3571
|
effectiveDataAuth,
|
|
2941
3572
|
extractErrorMessage,
|
|
3573
|
+
finalizeAgentChatUiTurn,
|
|
3574
|
+
foldAgentStreamIntoUiSegments,
|
|
2942
3575
|
formatPostgrestError,
|
|
2943
3576
|
formatRetrievalContext,
|
|
2944
3577
|
formatSdkError,
|
|
2945
3578
|
generateIdempotencyKey,
|
|
3579
|
+
isIncompleteAgentStreamError,
|
|
2946
3580
|
normalizeBrowserApiBase,
|
|
3581
|
+
parseAgentStreamAgentInfo,
|
|
3582
|
+
parseAgentStreamDone,
|
|
2947
3583
|
parseSseDataLine,
|
|
2948
3584
|
parseTransportResponse,
|
|
2949
3585
|
readSseStream,
|
|
3586
|
+
runAgentChatStream,
|
|
3587
|
+
runAgentChatStreamForUi,
|
|
3588
|
+
runAgentChatStreamLenient,
|
|
2950
3589
|
toRagableResult,
|
|
2951
3590
|
unwrapPostgrest
|
|
2952
3591
|
};
|