@ragable/sdk 0.7.7 → 0.7.9
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 +277 -2
- package/dist/index.d.ts +277 -2
- package/dist/index.js +471 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +465 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47,6 +47,7 @@ __export(index_exports, {
|
|
|
47
47
|
RagableBrowserAiClient: () => RagableBrowserAiClient,
|
|
48
48
|
RagableBrowserAuthClient: () => RagableBrowserAuthClient,
|
|
49
49
|
RagableBrowserDatabaseClient: () => RagableBrowserDatabaseClient,
|
|
50
|
+
RagableBrowserMailClient: () => RagableBrowserMailClient,
|
|
50
51
|
RagableBrowserStorageClient: () => RagableBrowserStorageClient,
|
|
51
52
|
RagableError: () => RagableError,
|
|
52
53
|
RagableNetworkError: () => RagableNetworkError,
|
|
@@ -58,6 +59,7 @@ __export(index_exports, {
|
|
|
58
59
|
assertPostgrestSuccess: () => assertPostgrestSuccess,
|
|
59
60
|
bindFetch: () => bindFetch,
|
|
60
61
|
buildInferenceRequestBody: () => buildInferenceRequestBody,
|
|
62
|
+
buildResponseFormat: () => buildResponseFormat,
|
|
61
63
|
collectAssistantTextFromUiSegments: () => collectAssistantTextFromUiSegments,
|
|
62
64
|
collectionRecordToRowWithMeta: () => collectionRecordToRowWithMeta,
|
|
63
65
|
collectionRecordsToRowWithMeta: () => collectionRecordsToRowWithMeta,
|
|
@@ -85,8 +87,11 @@ __export(index_exports, {
|
|
|
85
87
|
runAgentChatStream: () => runAgentChatStream,
|
|
86
88
|
runAgentChatStreamForUi: () => runAgentChatStreamForUi,
|
|
87
89
|
runAgentChatStreamLenient: () => runAgentChatStreamLenient,
|
|
90
|
+
streamObjectFromContext: () => streamObjectFromContext,
|
|
88
91
|
toRagableResult: () => toRagableResult,
|
|
89
|
-
|
|
92
|
+
tryParsePartialJson: () => tryParsePartialJson,
|
|
93
|
+
unwrapPostgrest: () => unwrapPostgrest,
|
|
94
|
+
wrapStreamTextAsObject: () => wrapStreamTextAsObject
|
|
90
95
|
});
|
|
91
96
|
module.exports = __toCommonJS(index_exports);
|
|
92
97
|
|
|
@@ -2357,6 +2362,72 @@ function decodeJwtExpiry(jwt) {
|
|
|
2357
2362
|
}
|
|
2358
2363
|
}
|
|
2359
2364
|
|
|
2365
|
+
// src/partial-json.ts
|
|
2366
|
+
function tryParsePartialJson(text) {
|
|
2367
|
+
const trimmed = text.trim();
|
|
2368
|
+
if (!trimmed) return void 0;
|
|
2369
|
+
try {
|
|
2370
|
+
return JSON.parse(trimmed);
|
|
2371
|
+
} catch {
|
|
2372
|
+
}
|
|
2373
|
+
const repaired = repairOpenStructures(trimmed);
|
|
2374
|
+
if (!repaired) return void 0;
|
|
2375
|
+
try {
|
|
2376
|
+
return JSON.parse(repaired);
|
|
2377
|
+
} catch {
|
|
2378
|
+
const noTrailingComma = stripTrailingCommas(trimmed);
|
|
2379
|
+
const repaired2 = repairOpenStructures(noTrailingComma);
|
|
2380
|
+
if (!repaired2) return void 0;
|
|
2381
|
+
try {
|
|
2382
|
+
return JSON.parse(repaired2);
|
|
2383
|
+
} catch {
|
|
2384
|
+
return void 0;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
function repairOpenStructures(text) {
|
|
2389
|
+
const first = text[0];
|
|
2390
|
+
if (first !== "{" && first !== "[") {
|
|
2391
|
+
return text;
|
|
2392
|
+
}
|
|
2393
|
+
const stack = [];
|
|
2394
|
+
let inString = false;
|
|
2395
|
+
let escaped = false;
|
|
2396
|
+
for (let i = 0; i < text.length; i++) {
|
|
2397
|
+
const ch = text[i];
|
|
2398
|
+
if (escaped) {
|
|
2399
|
+
escaped = false;
|
|
2400
|
+
continue;
|
|
2401
|
+
}
|
|
2402
|
+
if (ch === "\\") {
|
|
2403
|
+
escaped = true;
|
|
2404
|
+
continue;
|
|
2405
|
+
}
|
|
2406
|
+
if (ch === '"') {
|
|
2407
|
+
inString = !inString;
|
|
2408
|
+
continue;
|
|
2409
|
+
}
|
|
2410
|
+
if (inString) continue;
|
|
2411
|
+
if (ch === "{") stack.push("}");
|
|
2412
|
+
else if (ch === "[") stack.push("]");
|
|
2413
|
+
else if (ch === "}" || ch === "]") {
|
|
2414
|
+
if (stack.length === 0) return null;
|
|
2415
|
+
stack.pop();
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
let safe = text;
|
|
2419
|
+
if (inString) {
|
|
2420
|
+
safe += '"';
|
|
2421
|
+
}
|
|
2422
|
+
safe = safe.replace(/,\s*$/, "").replace(/:\s*$/, ": null");
|
|
2423
|
+
let suffix = "";
|
|
2424
|
+
for (let i = stack.length - 1; i >= 0; i--) suffix += stack[i];
|
|
2425
|
+
return safe + suffix;
|
|
2426
|
+
}
|
|
2427
|
+
function stripTrailingCommas(text) {
|
|
2428
|
+
return text.replace(/,(\s*[}\]])/g, "$1").replace(/,\s*$/, "");
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2360
2431
|
// src/stream-parts.ts
|
|
2361
2432
|
function normalizeFinishReason(raw) {
|
|
2362
2433
|
switch (raw) {
|
|
@@ -2566,7 +2637,7 @@ var ZERO_USAGE = {
|
|
|
2566
2637
|
completionTokens: 0,
|
|
2567
2638
|
totalTokens: 0
|
|
2568
2639
|
};
|
|
2569
|
-
function buildInferenceRequestBody(params) {
|
|
2640
|
+
function buildInferenceRequestBody(params, responseFormat) {
|
|
2570
2641
|
const body = {
|
|
2571
2642
|
model: params.model,
|
|
2572
2643
|
messages: params.messages
|
|
@@ -2577,8 +2648,18 @@ function buildInferenceRequestBody(params) {
|
|
|
2577
2648
|
if (typeof params.maxTokens === "number") body.max_tokens = params.maxTokens;
|
|
2578
2649
|
if (typeof params.topP === "number") body.top_p = params.topP;
|
|
2579
2650
|
if (params.reasoningEffort) body.reasoning_effort = params.reasoningEffort;
|
|
2651
|
+
if (responseFormat) body.response_format = responseFormat;
|
|
2580
2652
|
return body;
|
|
2581
2653
|
}
|
|
2654
|
+
function buildResponseFormat(params) {
|
|
2655
|
+
const json_schema = {
|
|
2656
|
+
name: params.name ?? "Output",
|
|
2657
|
+
schema: params.schema,
|
|
2658
|
+
strict: params.strict ?? true
|
|
2659
|
+
};
|
|
2660
|
+
if (params.description) json_schema.description = params.description;
|
|
2661
|
+
return { type: "json_schema", json_schema };
|
|
2662
|
+
}
|
|
2582
2663
|
async function consumeInferenceStream(body, broadcast, deferreds) {
|
|
2583
2664
|
const reader = body.getReader();
|
|
2584
2665
|
const decoder = new TextDecoder();
|
|
@@ -2829,6 +2910,190 @@ var RagableBrowserAiClient = class {
|
|
|
2829
2910
|
);
|
|
2830
2911
|
return { text, reasoning, usage, finishReason, toolCalls };
|
|
2831
2912
|
}
|
|
2913
|
+
/**
|
|
2914
|
+
* Stream a JSON-Schema-constrained response. Matches Vercel AI SDK's
|
|
2915
|
+
* `streamObject` shape — returns a synchronous result with `partialObjectStream`
|
|
2916
|
+
* (best-effort incremental parses) and `object` (the final parsed JSON).
|
|
2917
|
+
*
|
|
2918
|
+
* ```ts
|
|
2919
|
+
* const { partialObjectStream, object } = client.ai.streamObject({
|
|
2920
|
+
* model: "accounts/fireworks/models/kimi-k2p5",
|
|
2921
|
+
* schema: {
|
|
2922
|
+
* type: "object",
|
|
2923
|
+
* properties: {
|
|
2924
|
+
* title: { type: "string" },
|
|
2925
|
+
* tags: { type: "array", items: { type: "string" } },
|
|
2926
|
+
* },
|
|
2927
|
+
* required: ["title", "tags"],
|
|
2928
|
+
* },
|
|
2929
|
+
* messages: [{ role: "user", content: "Give me a blog post idea about AI." }],
|
|
2930
|
+
* });
|
|
2931
|
+
* for await (const partial of partialObjectStream) renderPreview(partial);
|
|
2932
|
+
* const final = await object;
|
|
2933
|
+
* ```
|
|
2934
|
+
*/
|
|
2935
|
+
streamObject(params) {
|
|
2936
|
+
return streamObjectFromContext(this.buildContext(), params);
|
|
2937
|
+
}
|
|
2938
|
+
/**
|
|
2939
|
+
* Non-streaming variant of {@link streamObject}. Resolves once the model
|
|
2940
|
+
* finishes; rejects if the final text isn't valid JSON for the schema.
|
|
2941
|
+
*/
|
|
2942
|
+
async generateObject(params) {
|
|
2943
|
+
const result = this.streamObject(params);
|
|
2944
|
+
for await (const _ of result.partialObjectStream) {
|
|
2945
|
+
void _;
|
|
2946
|
+
}
|
|
2947
|
+
const [object, usage, finishReason, toolCalls] = await Promise.all([
|
|
2948
|
+
result.object,
|
|
2949
|
+
result.usage,
|
|
2950
|
+
result.finishReason,
|
|
2951
|
+
result.toolCalls
|
|
2952
|
+
]);
|
|
2953
|
+
return { object, usage, finishReason, toolCalls };
|
|
2954
|
+
}
|
|
2955
|
+
};
|
|
2956
|
+
function streamObjectFromContext(ctx, params) {
|
|
2957
|
+
const textParams = {
|
|
2958
|
+
model: params.model,
|
|
2959
|
+
messages: params.messages,
|
|
2960
|
+
...params.system !== void 0 ? { system: params.system } : {},
|
|
2961
|
+
...typeof params.temperature === "number" ? { temperature: params.temperature } : {},
|
|
2962
|
+
...typeof params.maxTokens === "number" ? { maxTokens: params.maxTokens } : {},
|
|
2963
|
+
...typeof params.topP === "number" ? { topP: params.topP } : {},
|
|
2964
|
+
...params.signal !== void 0 ? { signal: params.signal } : {}
|
|
2965
|
+
};
|
|
2966
|
+
const responseFormat = buildResponseFormat({
|
|
2967
|
+
schema: params.schema,
|
|
2968
|
+
...params.schemaName !== void 0 ? { name: params.schemaName } : {},
|
|
2969
|
+
...params.schemaDescription !== void 0 ? { description: params.schemaDescription } : {}
|
|
2970
|
+
});
|
|
2971
|
+
const overrideCtx = {
|
|
2972
|
+
...ctx,
|
|
2973
|
+
// Wrap fetch to substitute the body. We can't change buildInferenceRequestBody
|
|
2974
|
+
// signature on the call site cleanly, so intercept here.
|
|
2975
|
+
fetch: ((input, init) => {
|
|
2976
|
+
if (init && typeof init.body === "string") {
|
|
2977
|
+
const parsed = JSON.parse(init.body);
|
|
2978
|
+
parsed.response_format = responseFormat;
|
|
2979
|
+
const newInit = { ...init, body: JSON.stringify(parsed) };
|
|
2980
|
+
return ctx.fetch(input, newInit);
|
|
2981
|
+
}
|
|
2982
|
+
return ctx.fetch(input, init);
|
|
2983
|
+
})
|
|
2984
|
+
};
|
|
2985
|
+
const inner = streamInferenceFromContext(overrideCtx, textParams);
|
|
2986
|
+
return wrapStreamTextAsObject(inner);
|
|
2987
|
+
}
|
|
2988
|
+
function wrapStreamTextAsObject(inner) {
|
|
2989
|
+
const partialBroadcast = new PartialObjectBroadcast();
|
|
2990
|
+
const objectDeferred = defer();
|
|
2991
|
+
void (async () => {
|
|
2992
|
+
let acc = "";
|
|
2993
|
+
let lastEmitted = /* @__PURE__ */ Symbol("none");
|
|
2994
|
+
try {
|
|
2995
|
+
for await (const delta of inner.textStream) {
|
|
2996
|
+
acc += delta;
|
|
2997
|
+
const candidate = tryParsePartialJson(acc);
|
|
2998
|
+
if (candidate !== void 0 && !sameSnapshot(candidate, lastEmitted)) {
|
|
2999
|
+
lastEmitted = candidate;
|
|
3000
|
+
partialBroadcast.push(candidate);
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
const finalText = await inner.text;
|
|
3004
|
+
let finalObj;
|
|
3005
|
+
try {
|
|
3006
|
+
finalObj = JSON.parse(finalText);
|
|
3007
|
+
} catch (e) {
|
|
3008
|
+
const err = new RagableError(
|
|
3009
|
+
`Model output is not valid JSON: ${e.message}`,
|
|
3010
|
+
502,
|
|
3011
|
+
{
|
|
3012
|
+
code: "SDK_OBJECT_PARSE_FAILED",
|
|
3013
|
+
raw: finalText.slice(0, 1e3)
|
|
3014
|
+
}
|
|
3015
|
+
);
|
|
3016
|
+
partialBroadcast.fail(err);
|
|
3017
|
+
objectDeferred.reject(err);
|
|
3018
|
+
return;
|
|
3019
|
+
}
|
|
3020
|
+
if (!sameSnapshot(finalObj, lastEmitted)) {
|
|
3021
|
+
partialBroadcast.push(finalObj);
|
|
3022
|
+
}
|
|
3023
|
+
partialBroadcast.end();
|
|
3024
|
+
objectDeferred.resolve(finalObj);
|
|
3025
|
+
} catch (err) {
|
|
3026
|
+
partialBroadcast.fail(err);
|
|
3027
|
+
objectDeferred.reject(err);
|
|
3028
|
+
}
|
|
3029
|
+
})();
|
|
3030
|
+
return {
|
|
3031
|
+
textStream: inner.textStream,
|
|
3032
|
+
partialObjectStream: partialBroadcast.consume(),
|
|
3033
|
+
object: objectDeferred.promise,
|
|
3034
|
+
text: inner.text,
|
|
3035
|
+
usage: inner.usage,
|
|
3036
|
+
finishReason: inner.finishReason,
|
|
3037
|
+
toolCalls: inner.toolCalls
|
|
3038
|
+
};
|
|
3039
|
+
}
|
|
3040
|
+
function sameSnapshot(a, b) {
|
|
3041
|
+
if (a === b) return true;
|
|
3042
|
+
try {
|
|
3043
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
3044
|
+
} catch {
|
|
3045
|
+
return false;
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
var PartialObjectBroadcast = class {
|
|
3049
|
+
constructor() {
|
|
3050
|
+
__publicField(this, "items", []);
|
|
3051
|
+
__publicField(this, "resolved", false);
|
|
3052
|
+
__publicField(this, "error", null);
|
|
3053
|
+
__publicField(this, "waiters", []);
|
|
3054
|
+
}
|
|
3055
|
+
push(item) {
|
|
3056
|
+
this.items.push(item);
|
|
3057
|
+
this.notify();
|
|
3058
|
+
}
|
|
3059
|
+
end() {
|
|
3060
|
+
if (this.resolved) return;
|
|
3061
|
+
this.resolved = true;
|
|
3062
|
+
this.notify();
|
|
3063
|
+
}
|
|
3064
|
+
fail(error) {
|
|
3065
|
+
if (this.resolved) return;
|
|
3066
|
+
this.error = error;
|
|
3067
|
+
this.resolved = true;
|
|
3068
|
+
this.notify();
|
|
3069
|
+
}
|
|
3070
|
+
notify() {
|
|
3071
|
+
const w = this.waiters;
|
|
3072
|
+
this.waiters = [];
|
|
3073
|
+
for (const fn of w) fn();
|
|
3074
|
+
}
|
|
3075
|
+
consume() {
|
|
3076
|
+
const self = this;
|
|
3077
|
+
return {
|
|
3078
|
+
[Symbol.asyncIterator]: () => {
|
|
3079
|
+
let idx = 0;
|
|
3080
|
+
return {
|
|
3081
|
+
next: async () => {
|
|
3082
|
+
while (true) {
|
|
3083
|
+
if (idx < self.items.length) {
|
|
3084
|
+
return { value: self.items[idx++], done: false };
|
|
3085
|
+
}
|
|
3086
|
+
if (self.resolved) {
|
|
3087
|
+
if (self.error) throw self.error;
|
|
3088
|
+
return { value: void 0, done: true };
|
|
3089
|
+
}
|
|
3090
|
+
await new Promise((res) => self.waiters.push(res));
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
2832
3097
|
};
|
|
2833
3098
|
|
|
2834
3099
|
// src/browser.ts
|
|
@@ -3610,6 +3875,120 @@ var RagableBrowserStorageClient = class {
|
|
|
3610
3875
|
return new BrowserStorageBucketClient(this.options, this.fetchImpl, bucketId);
|
|
3611
3876
|
}
|
|
3612
3877
|
};
|
|
3878
|
+
var RagableBrowserMailClient = class {
|
|
3879
|
+
constructor(options, auth) {
|
|
3880
|
+
this.options = options;
|
|
3881
|
+
this.auth = auth;
|
|
3882
|
+
__publicField(this, "fetchImpl");
|
|
3883
|
+
this.fetchImpl = bindFetch(options.fetch);
|
|
3884
|
+
}
|
|
3885
|
+
requireWebsiteId() {
|
|
3886
|
+
const websiteId = this.options.websiteId?.trim();
|
|
3887
|
+
if (!websiteId) {
|
|
3888
|
+
throw new RagableError(
|
|
3889
|
+
"websiteId is required for mail operations. Use createWebsiteRagableClient() or pass createBrowserClient({ websiteId, ... }).",
|
|
3890
|
+
400,
|
|
3891
|
+
{ code: "SDK_MISSING_WEBSITE_ID" }
|
|
3892
|
+
);
|
|
3893
|
+
}
|
|
3894
|
+
return websiteId;
|
|
3895
|
+
}
|
|
3896
|
+
pathTo(p) {
|
|
3897
|
+
const websiteId = this.requireWebsiteId();
|
|
3898
|
+
const orgId = this.options.organizationId;
|
|
3899
|
+
return `${normalizeBrowserApiBase()}/public/organizations/${orgId}/websites/${websiteId}/mail${p.startsWith("/") ? p : `/${p}`}`;
|
|
3900
|
+
}
|
|
3901
|
+
/**
|
|
3902
|
+
* Get the Bearer token used to authenticate the call:
|
|
3903
|
+
* 1. End-user access token (preferred when an auth group is configured
|
|
3904
|
+
* and the user has signed in)
|
|
3905
|
+
* 2. `dataStaticKey` from createBrowserClient options
|
|
3906
|
+
* 3. Caller-supplied `getAccessToken()`
|
|
3907
|
+
*
|
|
3908
|
+
* If none is available, throws — server-side use should pass the
|
|
3909
|
+
* data-admin key as `dataStaticKey`.
|
|
3910
|
+
*/
|
|
3911
|
+
async getBearerToken() {
|
|
3912
|
+
if (this.auth) {
|
|
3913
|
+
const token = await this.auth.getValidAccessToken().catch(() => null);
|
|
3914
|
+
if (token) return token;
|
|
3915
|
+
}
|
|
3916
|
+
const callerProvided = await this.options.getAccessToken?.();
|
|
3917
|
+
if (typeof callerProvided === "string" && callerProvided.length > 0) {
|
|
3918
|
+
return callerProvided;
|
|
3919
|
+
}
|
|
3920
|
+
if (this.options.dataStaticKey?.trim()) {
|
|
3921
|
+
return this.options.dataStaticKey.trim();
|
|
3922
|
+
}
|
|
3923
|
+
throw new RagableError(
|
|
3924
|
+
"Mail requests need authentication: either sign in via client.auth.signIn(...) or pass dataStaticKey (the auth group data-admin key) when creating the client.",
|
|
3925
|
+
401,
|
|
3926
|
+
{ code: "SDK_MAIL_NOT_AUTHENTICATED" }
|
|
3927
|
+
);
|
|
3928
|
+
}
|
|
3929
|
+
async request(path, init = {}) {
|
|
3930
|
+
const token = await this.getBearerToken();
|
|
3931
|
+
const headers = new Headers(init.headers ?? this.options.headers);
|
|
3932
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
3933
|
+
if (init.body && !headers.has("Content-Type")) {
|
|
3934
|
+
headers.set("Content-Type", "application/json");
|
|
3935
|
+
}
|
|
3936
|
+
const response = await this.fetchImpl(this.pathTo(path), {
|
|
3937
|
+
...init,
|
|
3938
|
+
headers
|
|
3939
|
+
});
|
|
3940
|
+
const payload = await parseMaybeJsonBody(response);
|
|
3941
|
+
if (!response.ok) {
|
|
3942
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
3943
|
+
throw new RagableError(message, response.status, payload);
|
|
3944
|
+
}
|
|
3945
|
+
return payload;
|
|
3946
|
+
}
|
|
3947
|
+
/** Send an email from this website's linked Gmail account. */
|
|
3948
|
+
async send(params) {
|
|
3949
|
+
if (!params.to?.length) {
|
|
3950
|
+
throw new RagableError(
|
|
3951
|
+
"`to` must contain at least one recipient.",
|
|
3952
|
+
400,
|
|
3953
|
+
{ code: "SDK_MAIL_NO_RECIPIENTS" }
|
|
3954
|
+
);
|
|
3955
|
+
}
|
|
3956
|
+
if (!params.bodyText && !params.bodyHtml) {
|
|
3957
|
+
throw new RagableError(
|
|
3958
|
+
"Provide at least one of `bodyText` or `bodyHtml`.",
|
|
3959
|
+
400,
|
|
3960
|
+
{ code: "SDK_MAIL_NO_BODY" }
|
|
3961
|
+
);
|
|
3962
|
+
}
|
|
3963
|
+
return this.request("/send", {
|
|
3964
|
+
method: "POST",
|
|
3965
|
+
body: JSON.stringify(params)
|
|
3966
|
+
});
|
|
3967
|
+
}
|
|
3968
|
+
/** Search messages with Gmail query syntax. */
|
|
3969
|
+
async search(params = {}) {
|
|
3970
|
+
const qs = new URLSearchParams();
|
|
3971
|
+
if (params.query) qs.set("q", params.query);
|
|
3972
|
+
if (params.maxResults) qs.set("maxResults", String(params.maxResults));
|
|
3973
|
+
if (params.pageToken) qs.set("pageToken", params.pageToken);
|
|
3974
|
+
if (params.labelIds?.length) qs.set("labelIds", params.labelIds.join(","));
|
|
3975
|
+
const suffix = qs.toString() ? `?${qs.toString()}` : "";
|
|
3976
|
+
return this.request(`/search${suffix}`, { method: "GET" });
|
|
3977
|
+
}
|
|
3978
|
+
/** Fetch a single message in full (headers + decoded text/html body). */
|
|
3979
|
+
async getMessage(messageId) {
|
|
3980
|
+
if (!messageId) {
|
|
3981
|
+
throw new RagableError("`messageId` is required.", 400, {
|
|
3982
|
+
code: "SDK_MAIL_NO_MESSAGE_ID"
|
|
3983
|
+
});
|
|
3984
|
+
}
|
|
3985
|
+
const { message } = await this.request(
|
|
3986
|
+
`/messages/${encodeURIComponent(messageId)}`,
|
|
3987
|
+
{ method: "GET" }
|
|
3988
|
+
);
|
|
3989
|
+
return message;
|
|
3990
|
+
}
|
|
3991
|
+
};
|
|
3613
3992
|
var RagableBrowserAgentsClient = class {
|
|
3614
3993
|
constructor(options) {
|
|
3615
3994
|
this.options = options;
|
|
@@ -3691,6 +4070,63 @@ var RagableBrowserAgentsClient = class {
|
|
|
3691
4070
|
const source = this.runStreamParts(agentName, params);
|
|
3692
4071
|
return createStreamResultFromParts(source);
|
|
3693
4072
|
}
|
|
4073
|
+
/**
|
|
4074
|
+
* Same agent, same tools/instructions/RAG — but constrain the final output
|
|
4075
|
+
* to a JSON Schema. Matches `client.ai.streamObject` exactly so callers can
|
|
4076
|
+
* swap between raw inference and an agent without changing call shape.
|
|
4077
|
+
*
|
|
4078
|
+
* Tool calling and structured output are **compatible**: the model may call
|
|
4079
|
+
* the agent's tools as usual; the final assistant message is the schema-
|
|
4080
|
+
* conformant JSON. The agent's `agents/<name>.json` is unchanged — whether
|
|
4081
|
+
* the run is conversational or structured is decided by the call site.
|
|
4082
|
+
*
|
|
4083
|
+
* ```ts
|
|
4084
|
+
* const { partialObjectStream, object } = client.agents.runObject<Plan>(
|
|
4085
|
+
* "planner",
|
|
4086
|
+
* {
|
|
4087
|
+
* messages: [{ role: "user", content: "Plan a 3-day trip to Kyoto." }],
|
|
4088
|
+
* schema: {
|
|
4089
|
+
* type: "object",
|
|
4090
|
+
* properties: {
|
|
4091
|
+
* days: {
|
|
4092
|
+
* type: "array",
|
|
4093
|
+
* items: { type: "object", properties: { date: { type: "string" }, activities: { type: "array", items: { type: "string" } } } },
|
|
4094
|
+
* },
|
|
4095
|
+
* },
|
|
4096
|
+
* required: ["days"],
|
|
4097
|
+
* },
|
|
4098
|
+
* },
|
|
4099
|
+
* );
|
|
4100
|
+
* for await (const p of partialObjectStream) renderPreview(p);
|
|
4101
|
+
* console.log(await object);
|
|
4102
|
+
* ```
|
|
4103
|
+
*/
|
|
4104
|
+
runObject(agentName, params) {
|
|
4105
|
+
const responseFormat = buildResponseFormat({
|
|
4106
|
+
schema: params.schema,
|
|
4107
|
+
...params.schemaName !== void 0 ? { name: params.schemaName } : {},
|
|
4108
|
+
...params.schemaDescription !== void 0 ? { description: params.schemaDescription } : {}
|
|
4109
|
+
});
|
|
4110
|
+
const sourceParts = this.runStreamParts(agentName, {
|
|
4111
|
+
messages: params.messages,
|
|
4112
|
+
...params.signal !== void 0 ? { signal: params.signal } : {},
|
|
4113
|
+
responseFormat
|
|
4114
|
+
});
|
|
4115
|
+
const inner = createStreamResultFromParts(sourceParts);
|
|
4116
|
+
return wrapStreamTextAsObject(inner);
|
|
4117
|
+
}
|
|
4118
|
+
/** Non-streaming variant of {@link runObject}. */
|
|
4119
|
+
async generateObject(agentName, params) {
|
|
4120
|
+
const result = this.runObject(agentName, params);
|
|
4121
|
+
for await (const _ of result.partialObjectStream) void _;
|
|
4122
|
+
const [object, usage, finishReason, toolCalls] = await Promise.all([
|
|
4123
|
+
result.object,
|
|
4124
|
+
result.usage,
|
|
4125
|
+
result.finishReason,
|
|
4126
|
+
result.toolCalls
|
|
4127
|
+
]);
|
|
4128
|
+
return { object, usage, finishReason, toolCalls };
|
|
4129
|
+
}
|
|
3694
4130
|
async *runStreamParts(agentName, params) {
|
|
3695
4131
|
const { messages } = params;
|
|
3696
4132
|
if (!Array.isArray(messages) || messages.length === 0) {
|
|
@@ -3712,12 +4148,33 @@ var RagableBrowserAgentsClient = class {
|
|
|
3712
4148
|
role: m.role,
|
|
3713
4149
|
content: m.content
|
|
3714
4150
|
}));
|
|
3715
|
-
const
|
|
4151
|
+
const headers = new Headers(this.options.headers);
|
|
4152
|
+
headers.set("Content-Type", "application/json");
|
|
4153
|
+
const body = {
|
|
3716
4154
|
message: last.content,
|
|
3717
4155
|
...history.length > 0 ? { history } : {},
|
|
3718
|
-
...params.
|
|
3719
|
-
}
|
|
3720
|
-
|
|
4156
|
+
...params.responseFormat ? { response_format: params.responseFormat } : {}
|
|
4157
|
+
};
|
|
4158
|
+
const response = await this.fetchImpl(
|
|
4159
|
+
this.toUrl(
|
|
4160
|
+
this.websiteAgentPath(
|
|
4161
|
+
`/agents/${encodeURIComponent(agentName)}/chat/stream`
|
|
4162
|
+
)
|
|
4163
|
+
),
|
|
4164
|
+
{
|
|
4165
|
+
method: "POST",
|
|
4166
|
+
headers,
|
|
4167
|
+
body: JSON.stringify(body),
|
|
4168
|
+
...params.signal !== void 0 ? { signal: params.signal } : {}
|
|
4169
|
+
}
|
|
4170
|
+
);
|
|
4171
|
+
if (!response.ok) {
|
|
4172
|
+
const payload = await parseMaybeJsonBody(response);
|
|
4173
|
+
const message = extractErrorMessage(payload, response.statusText);
|
|
4174
|
+
throw new RagableError(message, response.status, payload);
|
|
4175
|
+
}
|
|
4176
|
+
if (!response.body) return;
|
|
4177
|
+
for await (const event of readSseStream(response.body)) {
|
|
3721
4178
|
const mapped = mapAgentEvent(event);
|
|
3722
4179
|
if (mapped) yield mapped;
|
|
3723
4180
|
}
|
|
@@ -3858,6 +4315,7 @@ var RagableBrowser = class {
|
|
|
3858
4315
|
__publicField(this, "database");
|
|
3859
4316
|
__publicField(this, "db");
|
|
3860
4317
|
__publicField(this, "storage");
|
|
4318
|
+
__publicField(this, "mail");
|
|
3861
4319
|
__publicField(this, "transport");
|
|
3862
4320
|
__publicField(this, "_ragableAuth");
|
|
3863
4321
|
/** Delegates to `database.from()`. Kept for back-compat — prefer `database.from()`. */
|
|
@@ -3903,6 +4361,7 @@ var RagableBrowser = class {
|
|
|
3903
4361
|
this.database._setTransport(this.transport);
|
|
3904
4362
|
this.db = this.database;
|
|
3905
4363
|
this.storage = new RagableBrowserStorageClient(options, bindFetch(options.fetch));
|
|
4364
|
+
this.mail = new RagableBrowserMailClient(options, this._ragableAuth);
|
|
3906
4365
|
}
|
|
3907
4366
|
destroy() {
|
|
3908
4367
|
this._ragableAuth?.destroy();
|
|
@@ -3944,6 +4403,7 @@ function createClient(options) {
|
|
|
3944
4403
|
RagableBrowserAiClient,
|
|
3945
4404
|
RagableBrowserAuthClient,
|
|
3946
4405
|
RagableBrowserDatabaseClient,
|
|
4406
|
+
RagableBrowserMailClient,
|
|
3947
4407
|
RagableBrowserStorageClient,
|
|
3948
4408
|
RagableError,
|
|
3949
4409
|
RagableNetworkError,
|
|
@@ -3955,6 +4415,7 @@ function createClient(options) {
|
|
|
3955
4415
|
assertPostgrestSuccess,
|
|
3956
4416
|
bindFetch,
|
|
3957
4417
|
buildInferenceRequestBody,
|
|
4418
|
+
buildResponseFormat,
|
|
3958
4419
|
collectAssistantTextFromUiSegments,
|
|
3959
4420
|
collectionRecordToRowWithMeta,
|
|
3960
4421
|
collectionRecordsToRowWithMeta,
|
|
@@ -3982,7 +4443,10 @@ function createClient(options) {
|
|
|
3982
4443
|
runAgentChatStream,
|
|
3983
4444
|
runAgentChatStreamForUi,
|
|
3984
4445
|
runAgentChatStreamLenient,
|
|
4446
|
+
streamObjectFromContext,
|
|
3985
4447
|
toRagableResult,
|
|
3986
|
-
|
|
4448
|
+
tryParsePartialJson,
|
|
4449
|
+
unwrapPostgrest,
|
|
4450
|
+
wrapStreamTextAsObject
|
|
3987
4451
|
});
|
|
3988
4452
|
//# sourceMappingURL=index.js.map
|