@anuma/sdk 3.0.0 → 3.1.0

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.
@@ -75,1113 +75,73 @@ var init_clientConfig = __esm({
75
75
  }
76
76
  });
77
77
 
78
- // src/client/core/serverSentEvents.gen.ts
79
- var createSseClient;
80
- var init_serverSentEvents_gen = __esm({
81
- "src/client/core/serverSentEvents.gen.ts"() {
82
- "use strict";
83
- createSseClient = ({
84
- onRequest,
85
- onSseError,
86
- onSseEvent,
87
- responseTransformer,
88
- responseValidator,
89
- sseDefaultRetryDelay,
90
- sseMaxRetryAttempts,
91
- sseMaxRetryDelay,
92
- sseSleepFn,
93
- url,
94
- ...options
95
- }) => {
96
- let lastEventId;
97
- const sleep4 = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
98
- const createStream = async function* () {
99
- let retryDelay = sseDefaultRetryDelay ?? 3e3;
100
- let attempt = 0;
101
- const signal = options.signal ?? new AbortController().signal;
102
- while (true) {
103
- if (signal.aborted) break;
104
- attempt++;
105
- const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
106
- if (lastEventId !== void 0) {
107
- headers.set("Last-Event-ID", lastEventId);
108
- }
109
- try {
110
- const requestInit = {
111
- redirect: "follow",
112
- ...options,
113
- body: options.serializedBody,
114
- headers,
115
- signal
116
- };
117
- let request = new Request(url, requestInit);
118
- if (onRequest) {
119
- request = await onRequest(url, requestInit);
120
- }
121
- const _fetch = options.fetch ?? globalThis.fetch;
122
- const response = await _fetch(request);
123
- if (!response.ok)
124
- throw new Error(
125
- `SSE failed: ${response.status} ${response.statusText}`
126
- );
127
- if (!response.body) throw new Error("No body in SSE response");
128
- const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
129
- let buffer = "";
130
- const abortHandler = () => {
131
- try {
132
- reader.cancel();
133
- } catch {
134
- }
135
- };
136
- signal.addEventListener("abort", abortHandler);
137
- try {
138
- while (true) {
139
- const { done, value } = await reader.read();
140
- if (done) break;
141
- buffer += value;
142
- const chunks = buffer.split("\n\n");
143
- buffer = chunks.pop() ?? "";
144
- for (const chunk of chunks) {
145
- const lines = chunk.split("\n");
146
- const dataLines = [];
147
- let eventName;
148
- for (const line of lines) {
149
- if (line.startsWith("data:")) {
150
- dataLines.push(line.replace(/^data:\s*/, ""));
151
- } else if (line.startsWith("event:")) {
152
- eventName = line.replace(/^event:\s*/, "");
153
- } else if (line.startsWith("id:")) {
154
- lastEventId = line.replace(/^id:\s*/, "");
155
- } else if (line.startsWith("retry:")) {
156
- const parsed = Number.parseInt(
157
- line.replace(/^retry:\s*/, ""),
158
- 10
159
- );
160
- if (!Number.isNaN(parsed)) {
161
- retryDelay = parsed;
162
- }
163
- }
164
- }
165
- let data;
166
- let parsedJson = false;
167
- if (dataLines.length) {
168
- const rawData = dataLines.join("\n");
169
- try {
170
- data = JSON.parse(rawData);
171
- parsedJson = true;
172
- } catch {
173
- data = rawData;
174
- }
175
- }
176
- if (parsedJson) {
177
- if (responseValidator) {
178
- await responseValidator(data);
179
- }
180
- if (responseTransformer) {
181
- data = await responseTransformer(data);
182
- }
183
- }
184
- onSseEvent?.({
185
- data,
186
- event: eventName,
187
- id: lastEventId,
188
- retry: retryDelay
189
- });
190
- if (dataLines.length) {
191
- yield data;
192
- }
193
- }
194
- }
195
- } finally {
196
- signal.removeEventListener("abort", abortHandler);
197
- reader.releaseLock();
198
- }
199
- break;
200
- } catch (error) {
201
- onSseError?.(error);
202
- if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
203
- break;
204
- }
205
- const backoff = Math.min(
206
- retryDelay * 2 ** (attempt - 1),
207
- sseMaxRetryDelay ?? 3e4
208
- );
209
- await sleep4(backoff);
210
- }
211
- }
212
- };
213
- const stream = createStream();
214
- return { stream };
215
- };
216
- }
217
- });
218
-
219
- // src/client/core/bodySerializer.gen.ts
220
- var jsonBodySerializer;
221
- var init_bodySerializer_gen = __esm({
222
- "src/client/core/bodySerializer.gen.ts"() {
223
- "use strict";
224
- jsonBodySerializer = {
225
- bodySerializer: (body) => JSON.stringify(
226
- body,
227
- (_key, value) => typeof value === "bigint" ? value.toString() : value
228
- )
229
- };
230
- }
231
- });
232
-
233
- // src/client/core/pathSerializer.gen.ts
234
- var separatorArrayExplode, separatorArrayNoExplode, separatorObjectExplode, serializeArrayParam, serializePrimitiveParam, serializeObjectParam;
235
- var init_pathSerializer_gen = __esm({
236
- "src/client/core/pathSerializer.gen.ts"() {
78
+ // src/lib/logger.ts
79
+ function setLogger(logger) {
80
+ currentLogger = logger;
81
+ }
82
+ function getLogger() {
83
+ return currentLogger;
84
+ }
85
+ var consoleLogger, noopLogger, currentLogger;
86
+ var init_logger = __esm({
87
+ "src/lib/logger.ts"() {
237
88
  "use strict";
238
- separatorArrayExplode = (style) => {
239
- switch (style) {
240
- case "label":
241
- return ".";
242
- case "matrix":
243
- return ";";
244
- case "simple":
245
- return ",";
246
- default:
247
- return "&";
248
- }
249
- };
250
- separatorArrayNoExplode = (style) => {
251
- switch (style) {
252
- case "form":
253
- return ",";
254
- case "pipeDelimited":
255
- return "|";
256
- case "spaceDelimited":
257
- return "%20";
258
- default:
259
- return ",";
260
- }
261
- };
262
- separatorObjectExplode = (style) => {
263
- switch (style) {
264
- case "label":
265
- return ".";
266
- case "matrix":
267
- return ";";
268
- case "simple":
269
- return ",";
270
- default:
271
- return "&";
272
- }
273
- };
274
- serializeArrayParam = ({
275
- allowReserved,
276
- explode,
277
- name,
278
- style,
279
- value
280
- }) => {
281
- if (!explode) {
282
- const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
283
- switch (style) {
284
- case "label":
285
- return `.${joinedValues2}`;
286
- case "matrix":
287
- return `;${name}=${joinedValues2}`;
288
- case "simple":
289
- return joinedValues2;
290
- default:
291
- return `${name}=${joinedValues2}`;
292
- }
293
- }
294
- const separator = separatorArrayExplode(style);
295
- const joinedValues = value.map((v) => {
296
- if (style === "label" || style === "simple") {
297
- return allowReserved ? v : encodeURIComponent(v);
298
- }
299
- return serializePrimitiveParam({
300
- allowReserved,
301
- name,
302
- value: v
303
- });
304
- }).join(separator);
305
- return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
306
- };
307
- serializePrimitiveParam = ({
308
- allowReserved,
309
- name,
310
- value
311
- }) => {
312
- if (value === void 0 || value === null) {
313
- return "";
314
- }
315
- if (typeof value === "object") {
316
- throw new Error(
317
- "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
318
- );
319
- }
320
- return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
89
+ consoleLogger = {
90
+ debug: console.log.bind(console),
91
+ info: console.info.bind(console),
92
+ warn: console.warn.bind(console),
93
+ error: console.error.bind(console)
321
94
  };
322
- serializeObjectParam = ({
323
- allowReserved,
324
- explode,
325
- name,
326
- style,
327
- value,
328
- valueOnly
329
- }) => {
330
- if (value instanceof Date) {
331
- return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
332
- }
333
- if (style !== "deepObject" && !explode) {
334
- let values = [];
335
- Object.entries(value).forEach(([key, v]) => {
336
- values = [
337
- ...values,
338
- key,
339
- allowReserved ? v : encodeURIComponent(v)
340
- ];
341
- });
342
- const joinedValues2 = values.join(",");
343
- switch (style) {
344
- case "form":
345
- return `${name}=${joinedValues2}`;
346
- case "label":
347
- return `.${joinedValues2}`;
348
- case "matrix":
349
- return `;${name}=${joinedValues2}`;
350
- default:
351
- return joinedValues2;
352
- }
95
+ noopLogger = {
96
+ debug: () => {
97
+ },
98
+ info: () => {
99
+ },
100
+ warn: () => {
101
+ },
102
+ error: () => {
353
103
  }
354
- const separator = separatorObjectExplode(style);
355
- const joinedValues = Object.entries(value).map(
356
- ([key, v]) => serializePrimitiveParam({
357
- allowReserved,
358
- name: style === "deepObject" ? `${name}[${key}]` : key,
359
- value: v
360
- })
361
- ).join(separator);
362
- return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
363
104
  };
105
+ currentLogger = consoleLogger;
364
106
  }
365
107
  });
366
108
 
367
- // src/client/core/utils.gen.ts
368
- function getValidRequestBody(options) {
369
- const hasBody = options.body !== void 0;
370
- const isSerializedBody = hasBody && options.bodySerializer;
371
- if (isSerializedBody) {
372
- if ("serializedBody" in options) {
373
- const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
374
- return hasSerializedBody ? options.serializedBody : null;
109
+ // src/react/useEncryption.ts
110
+ function onClearAllEncryptionState(callback) {
111
+ clearAllEncryptionStateCallbacks.add(callback);
112
+ return () => {
113
+ clearAllEncryptionStateCallbacks.delete(callback);
114
+ };
115
+ }
116
+ function onKeyAvailable(address, callback) {
117
+ if (encryptionKeyStore.has(address)) {
118
+ try {
119
+ callback();
120
+ } catch {
375
121
  }
376
- return options.body !== "" ? options.body : null;
377
122
  }
378
- if (hasBody) {
379
- return options.body;
123
+ let callbacks = keyAvailableCallbacks.get(address);
124
+ if (!callbacks) {
125
+ callbacks = /* @__PURE__ */ new Set();
126
+ keyAvailableCallbacks.set(address, callbacks);
380
127
  }
381
- return void 0;
128
+ callbacks.add(callback);
129
+ return () => {
130
+ callbacks.delete(callback);
131
+ if (callbacks.size === 0) {
132
+ keyAvailableCallbacks.delete(address);
133
+ }
134
+ };
382
135
  }
383
- var init_utils_gen = __esm({
384
- "src/client/core/utils.gen.ts"() {
385
- "use strict";
386
- }
387
- });
388
-
389
- // src/client/core/auth.gen.ts
390
- var getAuthToken;
391
- var init_auth_gen = __esm({
392
- "src/client/core/auth.gen.ts"() {
393
- "use strict";
394
- getAuthToken = async (auth, callback) => {
395
- const token = typeof callback === "function" ? await callback(auth) : callback;
396
- if (!token) {
397
- return;
398
- }
399
- if (auth.scheme === "bearer") {
400
- return `Bearer ${token}`;
401
- }
402
- if (auth.scheme === "basic") {
403
- return `Basic ${btoa(token)}`;
136
+ function notifyKeyAvailable(address) {
137
+ const callbacks = keyAvailableCallbacks.get(address);
138
+ if (callbacks) {
139
+ for (const cb of callbacks) {
140
+ try {
141
+ cb();
142
+ } catch {
404
143
  }
405
- return token;
406
- };
407
- }
408
- });
409
-
410
- // src/client/client/utils.gen.ts
411
- var PATH_PARAM_RE, defaultPathSerializer, createQuerySerializer, getParseAs, checkForExistence, setAuthParams, buildUrl, getUrl, mergeConfigs, headersEntries, mergeHeaders, Interceptors, createInterceptors, defaultQuerySerializer, defaultHeaders, createConfig;
412
- var init_utils_gen2 = __esm({
413
- "src/client/client/utils.gen.ts"() {
414
- "use strict";
415
- init_auth_gen();
416
- init_bodySerializer_gen();
417
- init_pathSerializer_gen();
418
- PATH_PARAM_RE = /\{[^{}]+\}/g;
419
- defaultPathSerializer = ({ path, url: _url }) => {
420
- let url = _url;
421
- const matches = _url.match(PATH_PARAM_RE);
422
- if (matches) {
423
- for (const match of matches) {
424
- let explode = false;
425
- let name = match.substring(1, match.length - 1);
426
- let style = "simple";
427
- if (name.endsWith("*")) {
428
- explode = true;
429
- name = name.substring(0, name.length - 1);
430
- }
431
- if (name.startsWith(".")) {
432
- name = name.substring(1);
433
- style = "label";
434
- } else if (name.startsWith(";")) {
435
- name = name.substring(1);
436
- style = "matrix";
437
- }
438
- const value = path[name];
439
- if (value === void 0 || value === null) {
440
- continue;
441
- }
442
- if (Array.isArray(value)) {
443
- url = url.replace(
444
- match,
445
- serializeArrayParam({ explode, name, style, value })
446
- );
447
- continue;
448
- }
449
- if (typeof value === "object") {
450
- url = url.replace(
451
- match,
452
- serializeObjectParam({
453
- explode,
454
- name,
455
- style,
456
- value,
457
- valueOnly: true
458
- })
459
- );
460
- continue;
461
- }
462
- if (style === "matrix") {
463
- url = url.replace(
464
- match,
465
- `;${serializePrimitiveParam({
466
- name,
467
- value
468
- })}`
469
- );
470
- continue;
471
- }
472
- const replaceValue = encodeURIComponent(
473
- style === "label" ? `.${value}` : value
474
- );
475
- url = url.replace(match, replaceValue);
476
- }
477
- }
478
- return url;
479
- };
480
- createQuerySerializer = ({
481
- parameters = {},
482
- ...args
483
- } = {}) => {
484
- const querySerializer = (queryParams) => {
485
- const search = [];
486
- if (queryParams && typeof queryParams === "object") {
487
- for (const name in queryParams) {
488
- const value = queryParams[name];
489
- if (value === void 0 || value === null) {
490
- continue;
491
- }
492
- const options = parameters[name] || args;
493
- if (Array.isArray(value)) {
494
- const serializedArray = serializeArrayParam({
495
- allowReserved: options.allowReserved,
496
- explode: true,
497
- name,
498
- style: "form",
499
- value,
500
- ...options.array
501
- });
502
- if (serializedArray) search.push(serializedArray);
503
- } else if (typeof value === "object") {
504
- const serializedObject = serializeObjectParam({
505
- allowReserved: options.allowReserved,
506
- explode: true,
507
- name,
508
- style: "deepObject",
509
- value,
510
- ...options.object
511
- });
512
- if (serializedObject) search.push(serializedObject);
513
- } else {
514
- const serializedPrimitive = serializePrimitiveParam({
515
- allowReserved: options.allowReserved,
516
- name,
517
- value
518
- });
519
- if (serializedPrimitive) search.push(serializedPrimitive);
520
- }
521
- }
522
- }
523
- return search.join("&");
524
- };
525
- return querySerializer;
526
- };
527
- getParseAs = (contentType) => {
528
- if (!contentType) {
529
- return "stream";
530
- }
531
- const cleanContent = contentType.split(";")[0]?.trim();
532
- if (!cleanContent) {
533
- return;
534
- }
535
- if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
536
- return "json";
537
- }
538
- if (cleanContent === "multipart/form-data") {
539
- return "formData";
540
- }
541
- if (["application/", "audio/", "image/", "video/"].some(
542
- (type) => cleanContent.startsWith(type)
543
- )) {
544
- return "blob";
545
- }
546
- if (cleanContent.startsWith("text/")) {
547
- return "text";
548
- }
549
- return;
550
- };
551
- checkForExistence = (options, name) => {
552
- if (!name) {
553
- return false;
554
- }
555
- if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
556
- return true;
557
- }
558
- return false;
559
- };
560
- setAuthParams = async ({
561
- security,
562
- ...options
563
- }) => {
564
- for (const auth of security) {
565
- if (checkForExistence(options, auth.name)) {
566
- continue;
567
- }
568
- const token = await getAuthToken(auth, options.auth);
569
- if (!token) {
570
- continue;
571
- }
572
- const name = auth.name ?? "Authorization";
573
- switch (auth.in) {
574
- case "query":
575
- if (!options.query) {
576
- options.query = {};
577
- }
578
- options.query[name] = token;
579
- break;
580
- case "cookie":
581
- options.headers.append("Cookie", `${name}=${token}`);
582
- break;
583
- case "header":
584
- default:
585
- options.headers.set(name, token);
586
- break;
587
- }
588
- }
589
- };
590
- buildUrl = (options) => {
591
- const url = getUrl({
592
- baseUrl: options.baseUrl,
593
- path: options.path,
594
- query: options.query,
595
- querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
596
- url: options.url
597
- });
598
- return url;
599
- };
600
- getUrl = ({
601
- baseUrl,
602
- path,
603
- query,
604
- querySerializer,
605
- url: _url
606
- }) => {
607
- const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
608
- let url = (baseUrl ?? "") + pathUrl;
609
- if (path) {
610
- url = defaultPathSerializer({ path, url });
611
- }
612
- let search = query ? querySerializer(query) : "";
613
- if (search.startsWith("?")) {
614
- search = search.substring(1);
615
- }
616
- if (search) {
617
- url += `?${search}`;
618
- }
619
- return url;
620
- };
621
- mergeConfigs = (a, b) => {
622
- const config = { ...a, ...b };
623
- if (config.baseUrl?.endsWith("/")) {
624
- config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
625
- }
626
- config.headers = mergeHeaders(a.headers, b.headers);
627
- return config;
628
- };
629
- headersEntries = (headers) => {
630
- const entries = [];
631
- headers.forEach((value, key) => {
632
- entries.push([key, value]);
633
- });
634
- return entries;
635
- };
636
- mergeHeaders = (...headers) => {
637
- const mergedHeaders = new Headers();
638
- for (const header of headers) {
639
- if (!header || typeof header !== "object") {
640
- continue;
641
- }
642
- const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
643
- for (const [key, value] of iterator) {
644
- if (value === null) {
645
- mergedHeaders.delete(key);
646
- } else if (Array.isArray(value)) {
647
- for (const v of value) {
648
- mergedHeaders.append(key, v);
649
- }
650
- } else if (value !== void 0) {
651
- mergedHeaders.set(
652
- key,
653
- typeof value === "object" ? JSON.stringify(value) : value
654
- );
655
- }
656
- }
657
- }
658
- return mergedHeaders;
659
- };
660
- Interceptors = class {
661
- constructor() {
662
- this.fns = [];
663
- }
664
- clear() {
665
- this.fns = [];
666
- }
667
- eject(id) {
668
- const index = this.getInterceptorIndex(id);
669
- if (this.fns[index]) {
670
- this.fns[index] = null;
671
- }
672
- }
673
- exists(id) {
674
- const index = this.getInterceptorIndex(id);
675
- return Boolean(this.fns[index]);
676
- }
677
- getInterceptorIndex(id) {
678
- if (typeof id === "number") {
679
- return this.fns[id] ? id : -1;
680
- }
681
- return this.fns.indexOf(id);
682
- }
683
- update(id, fn) {
684
- const index = this.getInterceptorIndex(id);
685
- if (this.fns[index]) {
686
- this.fns[index] = fn;
687
- return id;
688
- }
689
- return false;
690
- }
691
- use(fn) {
692
- this.fns.push(fn);
693
- return this.fns.length - 1;
694
- }
695
- };
696
- createInterceptors = () => ({
697
- error: new Interceptors(),
698
- request: new Interceptors(),
699
- response: new Interceptors()
700
- });
701
- defaultQuerySerializer = createQuerySerializer({
702
- allowReserved: false,
703
- array: {
704
- explode: true,
705
- style: "form"
706
- },
707
- object: {
708
- explode: true,
709
- style: "deepObject"
710
- }
711
- });
712
- defaultHeaders = {
713
- "Content-Type": "application/json"
714
- };
715
- createConfig = (override = {}) => ({
716
- ...jsonBodySerializer,
717
- headers: defaultHeaders,
718
- parseAs: "auto",
719
- querySerializer: defaultQuerySerializer,
720
- ...override
721
- });
722
- }
723
- });
724
-
725
- // src/client/client/client.gen.ts
726
- var createClient;
727
- var init_client_gen = __esm({
728
- "src/client/client/client.gen.ts"() {
729
- "use strict";
730
- init_serverSentEvents_gen();
731
- init_utils_gen();
732
- init_utils_gen2();
733
- createClient = (config = {}) => {
734
- let _config = mergeConfigs(createConfig(), config);
735
- const getConfig = () => ({ ..._config });
736
- const setConfig = (config2) => {
737
- _config = mergeConfigs(_config, config2);
738
- return getConfig();
739
- };
740
- const interceptors = createInterceptors();
741
- const beforeRequest = async (options) => {
742
- const opts = {
743
- ..._config,
744
- ...options,
745
- fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
746
- headers: mergeHeaders(_config.headers, options.headers),
747
- serializedBody: void 0
748
- };
749
- if (opts.security) {
750
- await setAuthParams({
751
- ...opts,
752
- security: opts.security
753
- });
754
- }
755
- if (opts.requestValidator) {
756
- await opts.requestValidator(opts);
757
- }
758
- if (opts.body !== void 0 && opts.bodySerializer) {
759
- opts.serializedBody = opts.bodySerializer(opts.body);
760
- }
761
- if (opts.body === void 0 || opts.serializedBody === "") {
762
- opts.headers.delete("Content-Type");
763
- }
764
- const url = buildUrl(opts);
765
- return { opts, url };
766
- };
767
- const request = async (options) => {
768
- const { opts, url } = await beforeRequest(options);
769
- for (const fn of interceptors.request.fns) {
770
- if (fn) {
771
- await fn(opts);
772
- }
773
- }
774
- const _fetch = opts.fetch;
775
- const requestInit = {
776
- ...opts,
777
- body: getValidRequestBody(opts)
778
- };
779
- let response = await _fetch(url, requestInit);
780
- for (const fn of interceptors.response.fns) {
781
- if (fn) {
782
- response = await fn(response, opts);
783
- }
784
- }
785
- const result = {
786
- response
787
- };
788
- if (response.ok) {
789
- const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
790
- if (response.status === 204 || response.headers.get("Content-Length") === "0") {
791
- let emptyData;
792
- switch (parseAs) {
793
- case "arrayBuffer":
794
- case "blob":
795
- case "text":
796
- emptyData = await response[parseAs]();
797
- break;
798
- case "formData":
799
- emptyData = new FormData();
800
- break;
801
- case "stream":
802
- emptyData = response.body;
803
- break;
804
- case "json":
805
- default:
806
- emptyData = {};
807
- break;
808
- }
809
- return {
810
- data: emptyData,
811
- ...result
812
- };
813
- }
814
- let data;
815
- switch (parseAs) {
816
- case "arrayBuffer":
817
- case "blob":
818
- case "formData":
819
- case "json":
820
- case "text":
821
- data = await response[parseAs]();
822
- break;
823
- case "stream":
824
- return {
825
- data: response.body,
826
- ...result
827
- };
828
- }
829
- if (parseAs === "json") {
830
- if (opts.responseValidator) {
831
- await opts.responseValidator(data);
832
- }
833
- if (opts.responseTransformer) {
834
- data = await opts.responseTransformer(data);
835
- }
836
- }
837
- return {
838
- data,
839
- ...result
840
- };
841
- }
842
- const textError = await response.text();
843
- let jsonError;
844
- try {
845
- jsonError = JSON.parse(textError);
846
- } catch {
847
- }
848
- const error = jsonError ?? textError;
849
- let finalError = error;
850
- for (const fn of interceptors.error.fns) {
851
- if (fn) {
852
- finalError = await fn(error, response, opts);
853
- }
854
- }
855
- finalError = finalError || {};
856
- if (opts.throwOnError) {
857
- throw finalError;
858
- }
859
- return {
860
- error: finalError,
861
- ...result
862
- };
863
- };
864
- const makeMethodFn = (method) => (options) => request({ ...options, method });
865
- const makeSseFn = (method) => async (options) => {
866
- const { opts, url } = await beforeRequest(options);
867
- return createSseClient({
868
- ...opts,
869
- body: opts.body,
870
- headers: opts.headers,
871
- method,
872
- onRequest: async (url2, init) => {
873
- let request2 = new Request(url2, init);
874
- const requestInit = {
875
- ...init,
876
- method: init.method,
877
- url: url2
878
- };
879
- for (const fn of interceptors.request.fns) {
880
- if (fn) {
881
- await fn(requestInit);
882
- request2 = new Request(requestInit.url, requestInit);
883
- }
884
- }
885
- return request2;
886
- },
887
- url
888
- });
889
- };
890
- return {
891
- buildUrl,
892
- connect: makeMethodFn("CONNECT"),
893
- delete: makeMethodFn("DELETE"),
894
- get: makeMethodFn("GET"),
895
- getConfig,
896
- head: makeMethodFn("HEAD"),
897
- interceptors,
898
- options: makeMethodFn("OPTIONS"),
899
- patch: makeMethodFn("PATCH"),
900
- post: makeMethodFn("POST"),
901
- put: makeMethodFn("PUT"),
902
- request,
903
- setConfig,
904
- sse: {
905
- connect: makeSseFn("CONNECT"),
906
- delete: makeSseFn("DELETE"),
907
- get: makeSseFn("GET"),
908
- head: makeSseFn("HEAD"),
909
- options: makeSseFn("OPTIONS"),
910
- patch: makeSseFn("PATCH"),
911
- post: makeSseFn("POST"),
912
- put: makeSseFn("PUT"),
913
- trace: makeSseFn("TRACE")
914
- },
915
- trace: makeMethodFn("TRACE")
916
- };
917
- };
918
- }
919
- });
920
-
921
- // src/client/client/index.ts
922
- var init_client = __esm({
923
- "src/client/client/index.ts"() {
924
- "use strict";
925
- init_client_gen();
926
- init_utils_gen2();
927
- }
928
- });
929
-
930
- // src/client/client.gen.ts
931
- var client;
932
- var init_client_gen2 = __esm({
933
- "src/client/client.gen.ts"() {
934
- "use strict";
935
- init_client();
936
- init_clientConfig();
937
- client = createClient(createClientConfig(createConfig()));
938
- }
939
- });
940
-
941
- // src/client/sdk.gen.ts
942
- var getApiV1Config, getApiV1CreditsBalance, getApiV1CreditsPacks, postApiV1CreditsPurchase, postApiV1Embeddings, getApiV1Models, postApiV1PhoneCalls, getApiV1PhoneCallsByCallId, postApiV1SubscriptionsCancel, postApiV1SubscriptionsCreateCheckoutSession, postApiV1SubscriptionsCustomerPortal, postApiV1SubscriptionsRenew, getApiV1SubscriptionsStatus, getApiV1WalletsBinding, postApiV1WalletsBinding, postApiV1WalletsBindingNonce, deleteApiV1WalletsBindingByAddress, postAuthOauthByProviderExchange, postAuthOauthByProviderRefresh, postAuthOauthByProviderRevoke;
943
- var init_sdk_gen = __esm({
944
- "src/client/sdk.gen.ts"() {
945
- "use strict";
946
- init_client_gen2();
947
- getApiV1Config = (options) => {
948
- return (options?.client ?? client).get({
949
- url: "/api/v1/config",
950
- ...options
951
- });
952
- };
953
- getApiV1CreditsBalance = (options) => {
954
- return (options?.client ?? client).get({
955
- url: "/api/v1/credits/balance",
956
- ...options
957
- });
958
- };
959
- getApiV1CreditsPacks = (options) => {
960
- return (options?.client ?? client).get({
961
- url: "/api/v1/credits/packs",
962
- ...options
963
- });
964
- };
965
- postApiV1CreditsPurchase = (options) => {
966
- return (options.client ?? client).post({
967
- url: "/api/v1/credits/purchase",
968
- ...options,
969
- headers: {
970
- "Content-Type": "application/json",
971
- ...options.headers
972
- }
973
- });
974
- };
975
- postApiV1Embeddings = (options) => {
976
- return (options.client ?? client).post({
977
- url: "/api/v1/embeddings",
978
- ...options,
979
- headers: {
980
- "Content-Type": "application/json",
981
- ...options.headers
982
- }
983
- });
984
- };
985
- getApiV1Models = (options) => {
986
- return (options?.client ?? client).get({
987
- url: "/api/v1/models",
988
- ...options
989
- });
990
- };
991
- postApiV1PhoneCalls = (options) => {
992
- return (options.client ?? client).post({
993
- url: "/api/v1/phone-calls",
994
- ...options,
995
- headers: {
996
- "Content-Type": "application/json",
997
- ...options.headers
998
- }
999
- });
1000
- };
1001
- getApiV1PhoneCallsByCallId = (options) => {
1002
- return (options.client ?? client).get({
1003
- url: "/api/v1/phone-calls/{call_id}",
1004
- ...options
1005
- });
1006
- };
1007
- postApiV1SubscriptionsCancel = (options) => {
1008
- return (options?.client ?? client).post({
1009
- url: "/api/v1/subscriptions/cancel",
1010
- ...options,
1011
- headers: {
1012
- "Content-Type": "application/json",
1013
- ...options?.headers
1014
- }
1015
- });
1016
- };
1017
- postApiV1SubscriptionsCreateCheckoutSession = (options) => {
1018
- return (options.client ?? client).post({
1019
- url: "/api/v1/subscriptions/create-checkout-session",
1020
- ...options,
1021
- headers: {
1022
- "Content-Type": "application/json",
1023
- ...options.headers
1024
- }
1025
- });
1026
- };
1027
- postApiV1SubscriptionsCustomerPortal = (options) => {
1028
- return (options.client ?? client).post({
1029
- url: "/api/v1/subscriptions/customer-portal",
1030
- ...options,
1031
- headers: {
1032
- "Content-Type": "application/json",
1033
- ...options.headers
1034
- }
1035
- });
1036
- };
1037
- postApiV1SubscriptionsRenew = (options) => {
1038
- return (options?.client ?? client).post({
1039
- url: "/api/v1/subscriptions/renew",
1040
- ...options
1041
- });
1042
- };
1043
- getApiV1SubscriptionsStatus = (options) => {
1044
- return (options?.client ?? client).get({
1045
- url: "/api/v1/subscriptions/status",
1046
- ...options
1047
- });
1048
- };
1049
- getApiV1WalletsBinding = (options) => {
1050
- return (options?.client ?? client).get({
1051
- url: "/api/v1/wallets/binding",
1052
- ...options
1053
- });
1054
- };
1055
- postApiV1WalletsBinding = (options) => {
1056
- return (options.client ?? client).post({
1057
- url: "/api/v1/wallets/binding",
1058
- ...options,
1059
- headers: {
1060
- "Content-Type": "application/json",
1061
- ...options.headers
1062
- }
1063
- });
1064
- };
1065
- postApiV1WalletsBindingNonce = (options) => {
1066
- return (options?.client ?? client).post({
1067
- url: "/api/v1/wallets/binding/nonce",
1068
- ...options
1069
- });
1070
- };
1071
- deleteApiV1WalletsBindingByAddress = (options) => {
1072
- return (options.client ?? client).delete({
1073
- url: "/api/v1/wallets/binding/{address}",
1074
- ...options
1075
- });
1076
- };
1077
- postAuthOauthByProviderExchange = (options) => {
1078
- return (options.client ?? client).post({
1079
- url: "/auth/oauth/{provider}/exchange",
1080
- ...options,
1081
- headers: {
1082
- "Content-Type": "application/json",
1083
- ...options.headers
1084
- }
1085
- });
1086
- };
1087
- postAuthOauthByProviderRefresh = (options) => {
1088
- return (options.client ?? client).post({
1089
- url: "/auth/oauth/{provider}/refresh",
1090
- ...options,
1091
- headers: {
1092
- "Content-Type": "application/json",
1093
- ...options.headers
1094
- }
1095
- });
1096
- };
1097
- postAuthOauthByProviderRevoke = (options) => {
1098
- return (options.client ?? client).post({
1099
- url: "/auth/oauth/{provider}/revoke",
1100
- ...options,
1101
- headers: {
1102
- "Content-Type": "application/json",
1103
- ...options.headers
1104
- }
1105
- });
1106
- };
1107
- }
1108
- });
1109
-
1110
- // src/client/index.ts
1111
- var init_client2 = __esm({
1112
- "src/client/index.ts"() {
1113
- "use strict";
1114
- init_sdk_gen();
1115
- }
1116
- });
1117
-
1118
- // src/lib/logger.ts
1119
- function setLogger(logger) {
1120
- currentLogger = logger;
1121
- }
1122
- function getLogger() {
1123
- return currentLogger;
1124
- }
1125
- var consoleLogger, noopLogger, currentLogger;
1126
- var init_logger = __esm({
1127
- "src/lib/logger.ts"() {
1128
- "use strict";
1129
- consoleLogger = {
1130
- debug: console.log.bind(console),
1131
- info: console.info.bind(console),
1132
- warn: console.warn.bind(console),
1133
- error: console.error.bind(console)
1134
- };
1135
- noopLogger = {
1136
- debug: () => {
1137
- },
1138
- info: () => {
1139
- },
1140
- warn: () => {
1141
- },
1142
- error: () => {
1143
- }
1144
- };
1145
- currentLogger = consoleLogger;
1146
- }
1147
- });
1148
-
1149
- // src/react/useEncryption.ts
1150
- function onClearAllEncryptionState(callback) {
1151
- clearAllEncryptionStateCallbacks.add(callback);
1152
- return () => {
1153
- clearAllEncryptionStateCallbacks.delete(callback);
1154
- };
1155
- }
1156
- function onKeyAvailable(address, callback) {
1157
- if (encryptionKeyStore.has(address)) {
1158
- try {
1159
- callback();
1160
- } catch {
1161
- }
1162
- }
1163
- let callbacks = keyAvailableCallbacks.get(address);
1164
- if (!callbacks) {
1165
- callbacks = /* @__PURE__ */ new Set();
1166
- keyAvailableCallbacks.set(address, callbacks);
1167
- }
1168
- callbacks.add(callback);
1169
- return () => {
1170
- callbacks.delete(callback);
1171
- if (callbacks.size === 0) {
1172
- keyAvailableCallbacks.delete(address);
1173
- }
1174
- };
1175
- }
1176
- function notifyKeyAvailable(address) {
1177
- const callbacks = keyAvailableCallbacks.get(address);
1178
- if (callbacks) {
1179
- for (const cb of callbacks) {
1180
- try {
1181
- cb();
1182
- } catch {
1183
- }
1184
- }
144
+ }
1185
145
  }
1186
146
  }
1187
147
  function getStoredKey(address) {
@@ -3236,7 +2196,7 @@ var init_constants = __esm({
3236
2196
  }
3237
2197
  });
3238
2198
 
3239
- // src/lib/memoryEngine/embeddings.ts
2199
+ // src/lib/memoryEngine/generate.ts
3240
2200
  async function withEmbeddingRetry(call) {
3241
2201
  let last;
3242
2202
  let lastThrown;
@@ -3287,7 +2247,7 @@ async function generateEmbedding(text12, options) {
3287
2247
  throw new Error("Either apiKey or getToken must be provided");
3288
2248
  }
3289
2249
  const response = await withEmbeddingRetry(
3290
- () => postApiV1Embeddings({
2250
+ () => (0, import_client.postApiV1Embeddings)({
3291
2251
  baseUrl,
3292
2252
  body: {
3293
2253
  // Mask PII from the request body only — the cache above still keys on
@@ -3319,7 +2279,7 @@ async function generateEmbedding(text12, options) {
3319
2279
  }
3320
2280
  async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput) {
3321
2281
  const response = await withEmbeddingRetry(
3322
- () => postApiV1Embeddings({
2282
+ () => (0, import_client.postApiV1Embeddings)({
3323
2283
  baseUrl,
3324
2284
  // Mask PII from the request body only; cache/order still key on originals.
3325
2285
  body: { input: maskInput ? texts.map(maskInput) : texts, model },
@@ -3420,6 +2380,27 @@ async function generateEmbeddings(texts, options) {
3420
2380
  }
3421
2381
  return results;
3422
2382
  }
2383
+ var import_client, EMBED_MAX_ATTEMPTS, EmbeddingHttpError, DEFAULT_EMBEDDING_BATCH_SIZE, DEFAULT_EMBEDDING_BATCH_CONCURRENCY;
2384
+ var init_generate = __esm({
2385
+ "src/lib/memoryEngine/generate.ts"() {
2386
+ "use strict";
2387
+ import_client = require("@anuma/sdk");
2388
+ init_clientConfig();
2389
+ init_constants();
2390
+ EMBED_MAX_ATTEMPTS = 4;
2391
+ EmbeddingHttpError = class extends Error {
2392
+ constructor(message, status) {
2393
+ super(message);
2394
+ this.name = "EmbeddingHttpError";
2395
+ this.status = status;
2396
+ }
2397
+ };
2398
+ DEFAULT_EMBEDDING_BATCH_SIZE = 100;
2399
+ DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
2400
+ }
2401
+ });
2402
+
2403
+ // src/lib/memoryEngine/embeddings.ts
3423
2404
  async function embedMessage(ctx, messageId, options) {
3424
2405
  let message;
3425
2406
  const conversations = await getConversationsOp(ctx);
@@ -3575,27 +2556,17 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
3575
2556
  }
3576
2557
  return embeddedCount;
3577
2558
  }
3578
- var DEFAULT_MIN_CONTENT_LENGTH, EMBED_MAX_ATTEMPTS, EmbeddingHttpError, DEFAULT_EMBEDDING_BATCH_SIZE, DEFAULT_EMBEDDING_BATCH_CONCURRENCY;
2559
+ var DEFAULT_MIN_CONTENT_LENGTH;
3579
2560
  var init_embeddings = __esm({
3580
2561
  "src/lib/memoryEngine/embeddings.ts"() {
3581
2562
  "use strict";
3582
- init_client2();
3583
- init_clientConfig();
3584
2563
  init_operations();
3585
2564
  init_logger();
3586
2565
  init_chunking();
3587
2566
  init_constants();
2567
+ init_generate();
2568
+ init_generate();
3588
2569
  DEFAULT_MIN_CONTENT_LENGTH = 10;
3589
- EMBED_MAX_ATTEMPTS = 4;
3590
- EmbeddingHttpError = class extends Error {
3591
- constructor(message, status) {
3592
- super(message);
3593
- this.name = "EmbeddingHttpError";
3594
- this.status = status;
3595
- }
3596
- };
3597
- DEFAULT_EMBEDDING_BATCH_SIZE = 100;
3598
- DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
3599
2570
  }
3600
2571
  });
3601
2572
 
@@ -7899,17 +6870,151 @@ module.exports = __toCommonJS(index_exports);
7899
6870
  // src/lib/chat/resumeStream.ts
7900
6871
  init_clientConfig();
7901
6872
 
7902
- // src/lib/chat/toolLoop.ts
7903
- init_serverSentEvents_gen();
7904
- init_clientConfig();
7905
- init_embeddings();
7906
- init_redactor();
7907
-
7908
- // src/lib/chat/runHooks.ts
7909
- function composeHooks(hooks) {
7910
- const handlers = hooks.filter((h) => h !== void 0 && h !== null);
7911
- const fan = (get) => async (e) => {
7912
- await Promise.allSettled(handlers.map((h) => Promise.resolve().then(() => get(h)?.(e))));
6873
+ // src/client/core/serverSentEvents.gen.ts
6874
+ var createSseClient = ({
6875
+ onRequest,
6876
+ onSseError,
6877
+ onSseEvent,
6878
+ responseTransformer,
6879
+ responseValidator,
6880
+ sseDefaultRetryDelay,
6881
+ sseMaxRetryAttempts,
6882
+ sseMaxRetryDelay,
6883
+ sseSleepFn,
6884
+ url,
6885
+ ...options
6886
+ }) => {
6887
+ let lastEventId;
6888
+ const sleep4 = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
6889
+ const createStream = async function* () {
6890
+ let retryDelay = sseDefaultRetryDelay ?? 3e3;
6891
+ let attempt = 0;
6892
+ const signal = options.signal ?? new AbortController().signal;
6893
+ while (true) {
6894
+ if (signal.aborted) break;
6895
+ attempt++;
6896
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
6897
+ if (lastEventId !== void 0) {
6898
+ headers.set("Last-Event-ID", lastEventId);
6899
+ }
6900
+ try {
6901
+ const requestInit = {
6902
+ redirect: "follow",
6903
+ ...options,
6904
+ body: options.serializedBody,
6905
+ headers,
6906
+ signal
6907
+ };
6908
+ let request = new Request(url, requestInit);
6909
+ if (onRequest) {
6910
+ request = await onRequest(url, requestInit);
6911
+ }
6912
+ const _fetch = options.fetch ?? globalThis.fetch;
6913
+ const response = await _fetch(request);
6914
+ if (!response.ok)
6915
+ throw new Error(
6916
+ `SSE failed: ${response.status} ${response.statusText}`
6917
+ );
6918
+ if (!response.body) throw new Error("No body in SSE response");
6919
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
6920
+ let buffer = "";
6921
+ const abortHandler = () => {
6922
+ try {
6923
+ reader.cancel();
6924
+ } catch {
6925
+ }
6926
+ };
6927
+ signal.addEventListener("abort", abortHandler);
6928
+ try {
6929
+ while (true) {
6930
+ const { done, value } = await reader.read();
6931
+ if (done) break;
6932
+ buffer += value;
6933
+ const chunks = buffer.split("\n\n");
6934
+ buffer = chunks.pop() ?? "";
6935
+ for (const chunk of chunks) {
6936
+ const lines = chunk.split("\n");
6937
+ const dataLines = [];
6938
+ let eventName;
6939
+ for (const line of lines) {
6940
+ if (line.startsWith("data:")) {
6941
+ dataLines.push(line.replace(/^data:\s*/, ""));
6942
+ } else if (line.startsWith("event:")) {
6943
+ eventName = line.replace(/^event:\s*/, "");
6944
+ } else if (line.startsWith("id:")) {
6945
+ lastEventId = line.replace(/^id:\s*/, "");
6946
+ } else if (line.startsWith("retry:")) {
6947
+ const parsed = Number.parseInt(
6948
+ line.replace(/^retry:\s*/, ""),
6949
+ 10
6950
+ );
6951
+ if (!Number.isNaN(parsed)) {
6952
+ retryDelay = parsed;
6953
+ }
6954
+ }
6955
+ }
6956
+ let data;
6957
+ let parsedJson = false;
6958
+ if (dataLines.length) {
6959
+ const rawData = dataLines.join("\n");
6960
+ try {
6961
+ data = JSON.parse(rawData);
6962
+ parsedJson = true;
6963
+ } catch {
6964
+ data = rawData;
6965
+ }
6966
+ }
6967
+ if (parsedJson) {
6968
+ if (responseValidator) {
6969
+ await responseValidator(data);
6970
+ }
6971
+ if (responseTransformer) {
6972
+ data = await responseTransformer(data);
6973
+ }
6974
+ }
6975
+ onSseEvent?.({
6976
+ data,
6977
+ event: eventName,
6978
+ id: lastEventId,
6979
+ retry: retryDelay
6980
+ });
6981
+ if (dataLines.length) {
6982
+ yield data;
6983
+ }
6984
+ }
6985
+ }
6986
+ } finally {
6987
+ signal.removeEventListener("abort", abortHandler);
6988
+ reader.releaseLock();
6989
+ }
6990
+ break;
6991
+ } catch (error) {
6992
+ onSseError?.(error);
6993
+ if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
6994
+ break;
6995
+ }
6996
+ const backoff = Math.min(
6997
+ retryDelay * 2 ** (attempt - 1),
6998
+ sseMaxRetryDelay ?? 3e4
6999
+ );
7000
+ await sleep4(backoff);
7001
+ }
7002
+ }
7003
+ };
7004
+ const stream = createStream();
7005
+ return { stream };
7006
+ };
7007
+
7008
+ // src/lib/chat/toolLoop.ts
7009
+ init_clientConfig();
7010
+ init_embeddings();
7011
+ init_redactor();
7012
+
7013
+ // src/lib/chat/runHooks.ts
7014
+ function composeHooks(hooks) {
7015
+ const handlers = hooks.filter((h) => h !== void 0 && h !== null);
7016
+ const fan = (get) => async (e) => {
7017
+ await Promise.allSettled(handlers.map((h) => Promise.resolve().then(() => get(h)?.(e))));
7913
7018
  };
7914
7019
  return {
7915
7020
  onRunStart: fan((h) => h.onRunStart),
@@ -15312,8 +14417,12 @@ init_recall();
15312
14417
 
15313
14418
  // src/lib/memory/recallTool.ts
15314
14419
  init_recall();
14420
+
14421
+ // src/lib/memory/recallConstants.ts
15315
14422
  var RECALL_TOOL_NAME = "recall_memory";
15316
14423
  var RECALL_MAX_LIMIT = 50;
14424
+
14425
+ // src/lib/memory/recallTool.ts
15317
14426
  var DEFAULT_LIMIT2 = 8;
15318
14427
  var DEFAULT_BUDGET2 = "low";
15319
14428
  function formatEventTime(start, end, kind) {
@@ -16882,6 +15991,9 @@ async function preprocessFiles(files, options = {}) {
16882
15991
  };
16883
15992
  }
16884
15993
 
15994
+ // src/lib/tools/clientToolSelection.ts
15995
+ init_generate();
15996
+
16885
15997
  // src/tools/appBuilderPrompt.ts
16886
15998
  var APP_BUILDER_PROMPT = `App Builder tools (create_file, patch_file, and the rest described below) are available this turn, but they are OPTIONAL \u2014 having them does not mean you should build anything.
16887
15999
 
@@ -16986,7 +16098,7 @@ WORKFLOW:
16986
16098
 
16987
16099
  // src/lib/tools/serverTools.ts
16988
16100
  init_logger();
16989
- init_embeddings();
16101
+ init_generate();
16990
16102
  init_vector();
16991
16103
  var DEFAULT_CACHE_EXPIRATION_MS = 24 * 60 * 60 * 1e3;
16992
16104
  var SERVER_TOOLS_CACHE_KEY = "sdk_server_tools_cache";
@@ -17054,7 +16166,7 @@ function getCachedServerTools() {
17054
16166
  if (!cached) return null;
17055
16167
  const parsed = JSON.parse(cached);
17056
16168
  if (parsed.version !== CACHE_VERSION) {
17057
- clearServerToolsCache();
16169
+ removeLocalStorageCache();
17058
16170
  return null;
17059
16171
  }
17060
16172
  return parsed;
@@ -17066,37 +16178,45 @@ function isCacheExpired(cache, expirationMs = DEFAULT_CACHE_EXPIRATION_MS) {
17066
16178
  if (!cache) return true;
17067
16179
  return Date.now() - cache.timestamp > expirationMs;
17068
16180
  }
17069
- function cacheServerTools(tools, checksum) {
17070
- if (typeof localStorage === "undefined") return;
17071
- const cacheData = {
16181
+ function buildCacheEntry(tools, checksum) {
16182
+ return {
17072
16183
  tools,
17073
16184
  timestamp: Date.now(),
17074
16185
  version: CACHE_VERSION,
17075
16186
  ...checksum && { checksum }
17076
16187
  };
16188
+ }
16189
+ function writeLocalStorageCache(entry) {
16190
+ if (typeof localStorage === "undefined") return;
17077
16191
  try {
17078
- localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(cacheData));
16192
+ localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(entry));
17079
16193
  } catch (error) {
17080
16194
  getLogger().warn("[serverTools] Failed to cache tools:", error);
17081
16195
  }
17082
16196
  }
17083
- function clearServerToolsCache() {
16197
+ function removeLocalStorageCache() {
17084
16198
  if (typeof localStorage === "undefined") return;
17085
16199
  localStorage.removeItem(SERVER_TOOLS_CACHE_KEY);
17086
16200
  }
17087
- function getToolsChecksum2() {
17088
- const cached = getCachedServerTools();
17089
- return cached?.checksum;
16201
+ var localStorageToolsCache = {
16202
+ get: getCachedServerTools,
16203
+ set: writeLocalStorageCache,
16204
+ clear: removeLocalStorageCache
16205
+ };
16206
+ function clearServerToolsCache(cache = localStorageToolsCache) {
16207
+ return cache.clear?.();
16208
+ }
16209
+ function getToolsChecksum2(cache = localStorageToolsCache) {
16210
+ const cached = cache.get();
16211
+ return cached instanceof Promise ? cached.then((c) => c?.checksum) : cached?.checksum;
17090
16212
  }
17091
- function shouldRefreshTools(responseChecksum) {
16213
+ function shouldRefreshTools(responseChecksum, cache = localStorageToolsCache) {
17092
16214
  if (!responseChecksum) {
17093
16215
  return false;
17094
16216
  }
17095
- const cachedChecksum = getToolsChecksum2();
17096
- if (!cachedChecksum) {
17097
- return true;
17098
- }
17099
- return cachedChecksum !== responseChecksum;
16217
+ const decide = (cachedChecksum2) => !cachedChecksum2 || cachedChecksum2 !== responseChecksum;
16218
+ const cachedChecksum = getToolsChecksum2(cache);
16219
+ return cachedChecksum instanceof Promise ? cachedChecksum.then(decide) : decide(cachedChecksum);
17100
16220
  }
17101
16221
  async function fetchServerToolsFromApi(baseUrl, token) {
17102
16222
  const response = await fetch(`${baseUrl}/api/v1/tools`, {
@@ -17118,9 +16238,23 @@ async function getServerTools(options) {
17118
16238
  cacheExpirationMs = DEFAULT_CACHE_EXPIRATION_MS,
17119
16239
  forceRefresh = false,
17120
16240
  getToken,
17121
- apiKey
16241
+ apiKey,
16242
+ cache = localStorageToolsCache
17122
16243
  } = options;
17123
- const cached = getCachedServerTools();
16244
+ const persistCache = async (entry) => {
16245
+ try {
16246
+ await cache.set(entry);
16247
+ } catch (error) {
16248
+ getLogger().warn("[serverTools] Cache write failed (non-fatal):", error);
16249
+ }
16250
+ };
16251
+ let rawCached = null;
16252
+ try {
16253
+ rawCached = await cache.get();
16254
+ } catch (error) {
16255
+ getLogger().warn("[serverTools] Cache read failed; falling through to server fetch:", error);
16256
+ }
16257
+ const cached = rawCached && rawCached.version === CACHE_VERSION ? rawCached : null;
17124
16258
  const cacheValid = !isCacheExpired(cached, cacheExpirationMs);
17125
16259
  if (cached && cacheValid && !forceRefresh) {
17126
16260
  return cached.tools;
@@ -17141,7 +16275,7 @@ async function getServerTools(options) {
17141
16275
  }
17142
16276
  const data = await response.json();
17143
16277
  const { tools: tools2, checksum: checksum2 } = convertServerToolsResponse(data);
17144
- cacheServerTools(tools2, checksum2);
16278
+ await persistCache(buildCacheEntry(tools2, checksum2));
17145
16279
  return tools2;
17146
16280
  }
17147
16281
  if (!getToken) {
@@ -17154,7 +16288,7 @@ async function getServerTools(options) {
17154
16288
  return cached?.tools ?? [];
17155
16289
  }
17156
16290
  const { tools, checksum } = await fetchServerToolsFromApi(effectiveBaseUrl, token);
17157
- cacheServerTools(tools, checksum);
16291
+ await persistCache(buildCacheEntry(tools, checksum));
17158
16292
  return tools;
17159
16293
  } catch (error) {
17160
16294
  getLogger().error("[serverTools] Failed to fetch server tools:", error);
@@ -17659,13 +16793,14 @@ async function selectServerToolsForPrompt(options) {
17659
16793
  baseUrl,
17660
16794
  embeddingModel,
17661
16795
  cacheExpirationMs,
16796
+ cache,
17662
16797
  deferLoading
17663
16798
  } = options;
17664
16799
  if (serverToolsFilter === void 0) return [];
17665
16800
  if (Array.isArray(serverToolsFilter) && serverToolsFilter.length === 0) return [];
17666
16801
  let allServerTools;
17667
16802
  try {
17668
- allServerTools = await getServerTools({ baseUrl, cacheExpirationMs, getToken });
16803
+ allServerTools = await getServerTools({ baseUrl, cacheExpirationMs, getToken, cache });
17669
16804
  } catch {
17670
16805
  return [];
17671
16806
  }
@@ -17689,6 +16824,123 @@ async function selectServerToolsForPrompt(options) {
17689
16824
  return filterServerTools(allServerTools, serverToolsFilter);
17690
16825
  }
17691
16826
 
16827
+ // src/lib/tools/clientToolSelection.ts
16828
+ function getToolName2(t) {
16829
+ const fn = t.function;
16830
+ return fn?.name || t.name || "";
16831
+ }
16832
+ function getToolDescription(t) {
16833
+ const fn = t.function;
16834
+ return fn?.description || t.description || getToolName2(t);
16835
+ }
16836
+ function computeToolGuidance(selectedServerTools, selectedClientTools, extraToolSets, activatedSetNames) {
16837
+ const names = [
16838
+ ...selectedServerTools.map((t) => t.name),
16839
+ ...(selectedClientTools ?? []).map(getToolName2)
16840
+ ].filter(Boolean);
16841
+ const toolSets = extraToolSets.length > 0 ? [...BUILT_IN_TOOL_SETS, ...extraToolSets] : BUILT_IN_TOOL_SETS;
16842
+ const prompts = toolSetSystemPrompts(names, toolSets, activatedSetNames);
16843
+ return prompts.length > 0 ? prompts.join("\n\n") : void 0;
16844
+ }
16845
+ async function autoFilterClientTools(clientTools, promptEmbeddings, cache, embeddingOptions, extraToolSets = [], activeToolSets = [], noEmbeddingsReason = "short-prompt") {
16846
+ const isMemoryTool = (t) => {
16847
+ const name = getToolName2(t);
16848
+ return name.startsWith("memory_vault_") || name === RECALL_TOOL_NAME;
16849
+ };
16850
+ const alwaysInclude = clientTools.filter(isMemoryTool);
16851
+ const filterCandidates = clientTools.filter((t) => !isMemoryTool(t));
16852
+ if (filterCandidates.length === 0) {
16853
+ return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
16854
+ }
16855
+ if (!promptEmbeddings && noEmbeddingsReason === "error") {
16856
+ return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
16857
+ }
16858
+ if (!promptEmbeddings) {
16859
+ if (activeToolSets.length === 0) {
16860
+ return { tools: [], activatedSetNames: /* @__PURE__ */ new Set() };
16861
+ }
16862
+ const allSets = extraToolSets.length > 0 ? [...BUILT_IN_TOOL_SETS, ...extraToolSets] : BUILT_IN_TOOL_SETS;
16863
+ const activeSets = allSets.filter((s) => activeToolSets.includes(s.name));
16864
+ const stickyMembers = new Set(activeSets.flatMap((s) => s.members));
16865
+ return {
16866
+ tools: [
16867
+ ...alwaysInclude,
16868
+ ...filterCandidates.filter((t) => stickyMembers.has(getToolName2(t)))
16869
+ ],
16870
+ activatedSetNames: new Set(activeSets.map((s) => s.name))
16871
+ };
16872
+ }
16873
+ const toolsNeedingEmbeddings = [];
16874
+ for (const t of filterCandidates) {
16875
+ const name = getToolName2(t);
16876
+ if (name && !cache.has(name)) {
16877
+ toolsNeedingEmbeddings.push({ name, description: getToolDescription(t) });
16878
+ }
16879
+ }
16880
+ if (toolsNeedingEmbeddings.length > 0) {
16881
+ try {
16882
+ const descriptions = toolsNeedingEmbeddings.map((t) => t.description);
16883
+ const embeddings = await generateEmbeddings(descriptions, embeddingOptions);
16884
+ for (let i = 0; i < toolsNeedingEmbeddings.length; i++) {
16885
+ cache.set(toolsNeedingEmbeddings[i].name, embeddings[i]);
16886
+ }
16887
+ } catch {
16888
+ return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
16889
+ }
16890
+ }
16891
+ const pseudoServerTools = [];
16892
+ for (const t of filterCandidates) {
16893
+ const name = getToolName2(t);
16894
+ const embedding = cache.get(name);
16895
+ if (!embedding) continue;
16896
+ const fn = t.function;
16897
+ const params = fn?.parameters || fn?.arguments || {
16898
+ type: "object",
16899
+ properties: {},
16900
+ required: []
16901
+ };
16902
+ pseudoServerTools.push({
16903
+ type: "function",
16904
+ name,
16905
+ description: getToolDescription(t),
16906
+ parameters: params,
16907
+ embedding
16908
+ });
16909
+ }
16910
+ const matches = findMatchingTools(promptEmbeddings, pseudoServerTools, {
16911
+ limit: MAX_CLIENT_TOOLS_AFTER_FILTER,
16912
+ minSimilarity: CLIENT_TOOLS_MIN_SIMILARITY,
16913
+ filterAmbiguous: true,
16914
+ // See CLIENT_TOOLS_RELEVANCE_RATIO: 0.75 admits the second intent of a
16915
+ // multi-intent prompt (which lands ~75-80% of the dominant match), while
16916
+ // still trimming the loose tail. The earlier 0.9 made a second intent
16917
+ // structurally unselectable; the anchorMinSimilarity gates (0.53-0.55)
16918
+ // remain the guard against borderline anchors activating a whole set.
16919
+ relevanceRatio: CLIENT_TOOLS_RELEVANCE_RATIO
16920
+ });
16921
+ const matchedNames = new Set(matches.map((m) => m.tool.name));
16922
+ const scores = scoreTools(promptEmbeddings, pseudoServerTools);
16923
+ const availableNames = new Set(filterCandidates.map(getToolName2));
16924
+ const toolSets = extraToolSets.length > 0 ? [...BUILT_IN_TOOL_SETS, ...extraToolSets] : BUILT_IN_TOOL_SETS;
16925
+ const activeSetNames = activeToolSets.length > 0 ? new Set(activeToolSets) : void 0;
16926
+ const finalNames = expandToolSetsAdditive(
16927
+ matchedNames,
16928
+ availableNames,
16929
+ scores,
16930
+ toolSets,
16931
+ activeSetNames
16932
+ );
16933
+ const activatedSetNames = activatedToolSetNames(scores, toolSets, activeSetNames);
16934
+ if (finalNames.size === 0) {
16935
+ return { tools: alwaysInclude, activatedSetNames };
16936
+ }
16937
+ const filtered = filterCandidates.filter((t) => {
16938
+ const name = getToolName2(t);
16939
+ return name && finalNames.has(name);
16940
+ });
16941
+ return { tools: [...alwaysInclude, ...filtered], activatedSetNames };
16942
+ }
16943
+
17692
16944
  // src/react/useChatMedia.ts
17693
16945
  var import_react4 = require("react");
17694
16946
  init_logger();
@@ -17942,142 +17194,27 @@ function useChatMedia(options) {
17942
17194
  // src/react/useChatStorage.ts
17943
17195
  init_useEncryption();
17944
17196
  init_useEncryption();
17945
- function getToolName2(t) {
17946
- const fn = t.function;
17947
- return fn?.name || t.name || "";
17948
- }
17949
- function getToolDescription(t) {
17950
- const fn = t.function;
17951
- return fn?.description || t.description || getToolName2(t);
17952
- }
17953
- function computeToolGuidance(selectedServerTools, selectedClientTools, extraToolSets, activatedSetNames) {
17954
- const names = [
17955
- ...selectedServerTools.map((t) => t.name),
17956
- ...(selectedClientTools ?? []).map(getToolName2)
17957
- ].filter(Boolean);
17958
- const toolSets = extraToolSets.length > 0 ? [...BUILT_IN_TOOL_SETS, ...extraToolSets] : BUILT_IN_TOOL_SETS;
17959
- const prompts = toolSetSystemPrompts(names, toolSets, activatedSetNames);
17960
- return prompts.length > 0 ? prompts.join("\n\n") : void 0;
17961
- }
17962
- async function autoFilterClientTools(clientTools, promptEmbeddings, cache, embeddingOptions, extraToolSets = [], activeToolSets = [], noEmbeddingsReason = "short-prompt") {
17963
- const isMemoryTool = (t) => {
17964
- const name = getToolName2(t);
17965
- return name.startsWith("memory_vault_") || name === RECALL_TOOL_NAME;
17966
- };
17967
- const alwaysInclude = clientTools.filter(isMemoryTool);
17968
- const filterCandidates = clientTools.filter((t) => !isMemoryTool(t));
17969
- if (filterCandidates.length === 0) {
17970
- return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
17971
- }
17972
- if (!promptEmbeddings && noEmbeddingsReason === "error") {
17973
- return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
17197
+ async function previewToolSelection(options) {
17198
+ const {
17199
+ prompt,
17200
+ clientTools = [],
17201
+ serverToolsFilter,
17202
+ serverToolsConfig,
17203
+ getToken,
17204
+ apiKey,
17205
+ baseUrl,
17206
+ embeddingModel = DEFAULT_API_EMBEDDING_MODEL,
17207
+ extraToolSets,
17208
+ activeToolSets,
17209
+ clientToolEmbeddingsCache
17210
+ } = options;
17211
+ if (!getToken && !apiKey) {
17212
+ throw new Error(
17213
+ "previewToolSelection requires either `getToken` (Bearer auth) or `apiKey` (X-API-Key auth) \u2014 without one, embeddings and the server tool catalog cannot be fetched."
17214
+ );
17974
17215
  }
17975
- if (!promptEmbeddings) {
17976
- if (activeToolSets.length === 0) {
17977
- return { tools: [], activatedSetNames: /* @__PURE__ */ new Set() };
17978
- }
17979
- const allSets = extraToolSets.length > 0 ? [...BUILT_IN_TOOL_SETS, ...extraToolSets] : BUILT_IN_TOOL_SETS;
17980
- const activeSets = allSets.filter((s) => activeToolSets.includes(s.name));
17981
- const stickyMembers = new Set(activeSets.flatMap((s) => s.members));
17982
- return {
17983
- tools: [
17984
- ...alwaysInclude,
17985
- ...filterCandidates.filter((t) => stickyMembers.has(getToolName2(t)))
17986
- ],
17987
- activatedSetNames: new Set(activeSets.map((s) => s.name))
17988
- };
17989
- }
17990
- const toolsNeedingEmbeddings = [];
17991
- for (const t of filterCandidates) {
17992
- const name = getToolName2(t);
17993
- if (name && !cache.has(name)) {
17994
- toolsNeedingEmbeddings.push({ name, description: getToolDescription(t) });
17995
- }
17996
- }
17997
- if (toolsNeedingEmbeddings.length > 0) {
17998
- try {
17999
- const descriptions = toolsNeedingEmbeddings.map((t) => t.description);
18000
- const embeddings = await generateEmbeddings(descriptions, embeddingOptions);
18001
- for (let i = 0; i < toolsNeedingEmbeddings.length; i++) {
18002
- cache.set(toolsNeedingEmbeddings[i].name, embeddings[i]);
18003
- }
18004
- } catch {
18005
- return { tools: clientTools, activatedSetNames: /* @__PURE__ */ new Set() };
18006
- }
18007
- }
18008
- const pseudoServerTools = [];
18009
- for (const t of filterCandidates) {
18010
- const name = getToolName2(t);
18011
- const embedding = cache.get(name);
18012
- if (!embedding) continue;
18013
- const fn = t.function;
18014
- const params = fn?.parameters || fn?.arguments || {
18015
- type: "object",
18016
- properties: {},
18017
- required: []
18018
- };
18019
- pseudoServerTools.push({
18020
- type: "function",
18021
- name,
18022
- description: getToolDescription(t),
18023
- parameters: params,
18024
- embedding
18025
- });
18026
- }
18027
- const matches = findMatchingTools(promptEmbeddings, pseudoServerTools, {
18028
- limit: MAX_CLIENT_TOOLS_AFTER_FILTER,
18029
- minSimilarity: CLIENT_TOOLS_MIN_SIMILARITY,
18030
- filterAmbiguous: true,
18031
- // See CLIENT_TOOLS_RELEVANCE_RATIO: 0.75 admits the second intent of a
18032
- // multi-intent prompt (which lands ~75-80% of the dominant match), while
18033
- // still trimming the loose tail. The earlier 0.9 made a second intent
18034
- // structurally unselectable; the anchorMinSimilarity gates (0.53-0.55)
18035
- // remain the guard against borderline anchors activating a whole set.
18036
- relevanceRatio: CLIENT_TOOLS_RELEVANCE_RATIO
18037
- });
18038
- const matchedNames = new Set(matches.map((m) => m.tool.name));
18039
- const scores = scoreTools(promptEmbeddings, pseudoServerTools);
18040
- const availableNames = new Set(filterCandidates.map(getToolName2));
18041
- const toolSets = extraToolSets.length > 0 ? [...BUILT_IN_TOOL_SETS, ...extraToolSets] : BUILT_IN_TOOL_SETS;
18042
- const activeSetNames = activeToolSets.length > 0 ? new Set(activeToolSets) : void 0;
18043
- const finalNames = expandToolSetsAdditive(
18044
- matchedNames,
18045
- availableNames,
18046
- scores,
18047
- toolSets,
18048
- activeSetNames
18049
- );
18050
- const activatedSetNames = activatedToolSetNames(scores, toolSets, activeSetNames);
18051
- if (finalNames.size === 0) {
18052
- return { tools: alwaysInclude, activatedSetNames };
18053
- }
18054
- const filtered = filterCandidates.filter((t) => {
18055
- const name = getToolName2(t);
18056
- return name && finalNames.has(name);
18057
- });
18058
- return { tools: [...alwaysInclude, ...filtered], activatedSetNames };
18059
- }
18060
- async function previewToolSelection(options) {
18061
- const {
18062
- prompt,
18063
- clientTools = [],
18064
- serverToolsFilter,
18065
- serverToolsConfig,
18066
- getToken,
18067
- apiKey,
18068
- baseUrl,
18069
- embeddingModel = DEFAULT_API_EMBEDDING_MODEL,
18070
- extraToolSets,
18071
- activeToolSets,
18072
- clientToolEmbeddingsCache
18073
- } = options;
18074
- if (!getToken && !apiKey) {
18075
- throw new Error(
18076
- "previewToolSelection requires either `getToken` (Bearer auth) or `apiKey` (X-API-Key auth) \u2014 without one, embeddings and the server tool catalog cannot be fetched."
18077
- );
18078
- }
18079
- if (!prompt.trim()) {
18080
- return { clientToolNames: [], serverToolNames: [] };
17216
+ if (!prompt.trim()) {
17217
+ return { clientToolNames: [], serverToolNames: [] };
18081
17218
  }
18082
17219
  if (prompt.length < MIN_CONTENT_LENGTH_FOR_TOOLS) {
18083
17220
  const { tools: gatedTools } = await autoFilterClientTools(
@@ -18095,7 +17232,8 @@ async function previewToolSelection(options) {
18095
17232
  baseUrl,
18096
17233
  cacheExpirationMs: serverToolsConfig?.cacheExpirationMs,
18097
17234
  getToken,
18098
- apiKey
17235
+ apiKey,
17236
+ cache: serverToolsConfig?.cache
18099
17237
  });
18100
17238
  const allow = new Set(serverToolsFilter);
18101
17239
  gatedServerNames = allServerTools.filter((t) => allow.has(t.name)).map((t) => t.name);
@@ -18143,7 +17281,8 @@ async function previewToolSelection(options) {
18143
17281
  baseUrl,
18144
17282
  cacheExpirationMs: serverToolsConfig?.cacheExpirationMs,
18145
17283
  getToken,
18146
- apiKey
17284
+ apiKey,
17285
+ cache: serverToolsConfig?.cache
18147
17286
  });
18148
17287
  if (serverToolsConfig?.deferLoading?.enabled) {
18149
17288
  serverToolNames = allServerTools.map((t) => t.name);
@@ -19136,7 +18275,8 @@ function useChatStorage(options) {
19136
18275
  const allServerTools = await getServerTools({
19137
18276
  baseUrl,
19138
18277
  cacheExpirationMs: serverToolsConfig?.cacheExpirationMs,
19139
- getToken
18278
+ getToken,
18279
+ cache: serverToolsConfig?.cache
19140
18280
  });
19141
18281
  if (serverToolsConfig?.deferLoading?.enabled) {
19142
18282
  filteredServerTools2 = allServerTools;
@@ -19154,12 +18294,14 @@ function useChatStorage(options) {
19154
18294
  let filteredClientTools2 = clientTools;
19155
18295
  let clientActivatedSetNames2;
19156
18296
  if (clientToolsFilter && clientTools?.length) {
19157
- const clientToolNames = clientToolsFilter(skipStorageEmbeddings, clientTools);
19158
- filteredClientTools2 = clientTools.filter((t) => {
19159
- const fn = t.function;
19160
- const name = fn?.name || t.name;
19161
- return clientToolNames.includes(name);
19162
- });
18297
+ if (!skipStorageEmbeddingsFailed) {
18298
+ const clientToolNames = clientToolsFilter(skipStorageEmbeddings, clientTools);
18299
+ filteredClientTools2 = clientTools.filter((t) => {
18300
+ const fn = t.function;
18301
+ const name = fn?.name || t.name;
18302
+ return clientToolNames.includes(name);
18303
+ });
18304
+ }
19163
18305
  } else if (clientTools?.length && getToken) {
19164
18306
  const clientFilterResult = await autoFilterClientTools(
19165
18307
  clientTools,
@@ -19226,8 +18368,20 @@ function useChatStorage(options) {
19226
18368
  error: result2.error || "Unknown error"
19227
18369
  };
19228
18370
  }
19229
- if (getToken && shouldRefreshTools(getToolsChecksum(result2.data))) {
19230
- getServerTools({ baseUrl, getToken, forceRefresh: true }).catch((err) => {
18371
+ const refreshResponse = result2.data;
18372
+ if (getToken) {
18373
+ Promise.resolve().then(
18374
+ () => shouldRefreshTools(getToolsChecksum(refreshResponse), serverToolsConfig?.cache)
18375
+ ).then((refresh) => {
18376
+ if (refresh) {
18377
+ return getServerTools({
18378
+ baseUrl,
18379
+ getToken,
18380
+ forceRefresh: true,
18381
+ cache: serverToolsConfig?.cache
18382
+ });
18383
+ }
18384
+ }).catch((err) => {
19231
18385
  getLogger().warn("[useChatStorage] Failed to refresh server tools cache:", err);
19232
18386
  });
19233
18387
  }
@@ -19494,7 +18648,8 @@ function useChatStorage(options) {
19494
18648
  const allServerTools = await getServerTools({
19495
18649
  baseUrl,
19496
18650
  cacheExpirationMs: serverToolsConfig?.cacheExpirationMs,
19497
- getToken
18651
+ getToken,
18652
+ cache: serverToolsConfig?.cache
19498
18653
  });
19499
18654
  if (serverToolsConfig?.deferLoading?.enabled && effectiveApiType === "responses") {
19500
18655
  filteredServerTools = allServerTools;
@@ -19512,12 +18667,14 @@ function useChatStorage(options) {
19512
18667
  let filteredClientTools = clientTools;
19513
18668
  let clientActivatedSetNames;
19514
18669
  if (clientToolsFilter && clientTools?.length) {
19515
- const clientToolNames = clientToolsFilter(userMessageEmbeddings ?? null, clientTools);
19516
- filteredClientTools = clientTools.filter((t) => {
19517
- const fn = t.function;
19518
- const name = fn?.name || t.name;
19519
- return clientToolNames.includes(name);
19520
- });
18670
+ if (!userMessageEmbeddingsFailed) {
18671
+ const clientToolNames = clientToolsFilter(userMessageEmbeddings ?? null, clientTools);
18672
+ filteredClientTools = clientTools.filter((t) => {
18673
+ const fn = t.function;
18674
+ const name = fn?.name || t.name;
18675
+ return clientToolNames.includes(name);
18676
+ });
18677
+ }
19521
18678
  } else if (clientTools?.length && getToken) {
19522
18679
  const clientFilterResult = await autoFilterClientTools(
19523
18680
  clientTools,
@@ -19837,8 +18994,17 @@ Based on these results, continue with the task.`;
19837
18994
  } catch {
19838
18995
  }
19839
18996
  }
19840
- if (getToken && shouldRefreshTools(getToolsChecksum(responseData))) {
19841
- getServerTools({ baseUrl, getToken, forceRefresh: true }).catch((err) => {
18997
+ if (getToken) {
18998
+ Promise.resolve().then(() => shouldRefreshTools(getToolsChecksum(responseData), serverToolsConfig?.cache)).then((refresh) => {
18999
+ if (refresh) {
19000
+ return getServerTools({
19001
+ baseUrl,
19002
+ getToken,
19003
+ forceRefresh: true,
19004
+ cache: serverToolsConfig?.cache
19005
+ });
19006
+ }
19007
+ }).catch((err) => {
19842
19008
  getLogger().warn("[useChatStorage] Failed to refresh server tools cache:", err);
19843
19009
  });
19844
19010
  }
@@ -23407,452 +22573,1270 @@ function useExportPdf() {
23407
22573
  const canvas = await renderElementToCanvas(element, { onProgress: setProgress });
23408
22574
  return canvas;
23409
22575
  } catch (err) {
23410
- const processed = toError(err);
23411
- setError(processed);
23412
- throw processed;
22576
+ const processed = toError(err);
22577
+ setError(processed);
22578
+ throw processed;
22579
+ } finally {
22580
+ setIsExporting(false);
22581
+ }
22582
+ },
22583
+ []
22584
+ );
22585
+ return {
22586
+ exportElementToPdf: wrappedExportElement,
22587
+ exportMarkdownToPdf: wrappedExportMarkdown,
22588
+ downloadElementAsPdf,
22589
+ downloadMarkdownAsPdf,
22590
+ renderElementToCanvas: wrappedRenderToCanvas,
22591
+ isExporting,
22592
+ progress,
22593
+ error
22594
+ };
22595
+ }
22596
+
22597
+ // src/react/useOCR.ts
22598
+ var import_react11 = require("react");
22599
+ var import_tesseract = __toESM(require("tesseract.js"));
22600
+ init_logger();
22601
+ function useOCR() {
22602
+ const [isProcessing, setIsProcessing] = (0, import_react11.useState)(false);
22603
+ const [error, setError] = (0, import_react11.useState)(null);
22604
+ const extractOCRContext = (0, import_react11.useCallback)(async (files) => {
22605
+ setIsProcessing(true);
22606
+ setError(null);
22607
+ try {
22608
+ if (files.length === 0) {
22609
+ return null;
22610
+ }
22611
+ const contexts = await Promise.all(
22612
+ files.map(async (file) => {
22613
+ try {
22614
+ let imagesToProcess = [];
22615
+ const language = file.language || "eng";
22616
+ const filename = file.filename || (file.url instanceof File ? file.url.name : "");
22617
+ let isPdf = false;
22618
+ if (typeof file.url === "string") {
22619
+ isPdf = file.url.toLowerCase().endsWith(".pdf") || (filename?.toLowerCase().endsWith(".pdf") ?? false);
22620
+ } else if (file.url instanceof Blob) {
22621
+ isPdf = file.url.type === "application/pdf" || (filename?.toLowerCase().endsWith(".pdf") ?? false);
22622
+ }
22623
+ if (isPdf) {
22624
+ let pdfUrl;
22625
+ let shouldRevoke = false;
22626
+ if (typeof file.url === "string") {
22627
+ pdfUrl = file.url;
22628
+ } else {
22629
+ pdfUrl = URL.createObjectURL(file.url);
22630
+ shouldRevoke = true;
22631
+ }
22632
+ try {
22633
+ const pdfImages = await convertPdfToImages(pdfUrl);
22634
+ imagesToProcess = pdfImages;
22635
+ } catch (e) {
22636
+ getLogger().error("Failed to convert PDF to images", e);
22637
+ throw e;
22638
+ } finally {
22639
+ if (shouldRevoke) {
22640
+ URL.revokeObjectURL(pdfUrl);
22641
+ }
22642
+ }
22643
+ } else {
22644
+ imagesToProcess = [file.url];
22645
+ }
22646
+ const pageTexts = [];
22647
+ for (const image of imagesToProcess) {
22648
+ const result = await import_tesseract.default.recognize(image, language);
22649
+ pageTexts.push(result.data.text);
22650
+ }
22651
+ const text12 = pageTexts.join("\n\n");
22652
+ if (!text12.trim()) {
22653
+ getLogger().warn(`No text found in OCR source ${filename || "unknown"}`);
22654
+ return null;
22655
+ }
22656
+ return `[Context from OCR attachment ${filename || "unknown"}]:
22657
+ ${text12}`;
22658
+ } catch (err) {
22659
+ getLogger().error(`Failed to process OCR for ${file.filename || "unknown"}:`, err);
22660
+ return null;
22661
+ }
22662
+ })
22663
+ );
22664
+ const mergedContext = contexts.filter(Boolean).join("\n\n");
22665
+ return mergedContext || null;
22666
+ } catch (err) {
22667
+ const processedError = err instanceof Error ? err : new Error(String(err));
22668
+ setError(processedError);
22669
+ throw processedError;
22670
+ } finally {
22671
+ setIsProcessing(false);
22672
+ }
22673
+ }, []);
22674
+ return {
22675
+ extractOCRContext,
22676
+ isProcessing,
22677
+ error
22678
+ };
22679
+ }
22680
+
22681
+ // src/react/usePdf.ts
22682
+ var import_react12 = require("react");
22683
+ init_logger();
22684
+ var PDF_MIME_TYPE = "application/pdf";
22685
+ function usePdf() {
22686
+ const [isProcessing, setIsProcessing] = (0, import_react12.useState)(false);
22687
+ const [error, setError] = (0, import_react12.useState)(null);
22688
+ const extractPdfContext = (0, import_react12.useCallback)(async (files) => {
22689
+ setIsProcessing(true);
22690
+ setError(null);
22691
+ try {
22692
+ const pdfFiles = files.filter(
22693
+ (file) => file.mediaType === PDF_MIME_TYPE || file.filename?.toLowerCase().endsWith(".pdf")
22694
+ );
22695
+ if (pdfFiles.length === 0) {
22696
+ return null;
22697
+ }
22698
+ const contexts = await Promise.all(
22699
+ pdfFiles.map(async (file) => {
22700
+ try {
22701
+ const text12 = await extractTextFromPdf(file.url);
22702
+ if (!text12.trim()) {
22703
+ getLogger().warn(`No text found in PDF ${file.filename}`);
22704
+ return null;
22705
+ }
22706
+ return `[Context from PDF attachment ${file.filename}]:
22707
+ ${text12}`;
22708
+ } catch (err) {
22709
+ getLogger().error(`Failed to process PDF ${file.filename}:`, err);
22710
+ return null;
22711
+ }
22712
+ })
22713
+ );
22714
+ const mergedContext = contexts.filter(Boolean).join("\n\n");
22715
+ return mergedContext || null;
22716
+ } catch (err) {
22717
+ const processedError = err instanceof Error ? err : new Error(String(err));
22718
+ setError(processedError);
22719
+ throw processedError;
22720
+ } finally {
22721
+ setIsProcessing(false);
22722
+ }
22723
+ }, []);
22724
+ return {
22725
+ extractPdfContext,
22726
+ isProcessing,
22727
+ error
22728
+ };
22729
+ }
22730
+
22731
+ // src/react/useVoice.ts
22732
+ var import_react13 = require("react");
22733
+ function getOnDeviceSpeechRecognition() {
22734
+ if (typeof window === "undefined") return null;
22735
+ if (!/iPhone|iPad|iPod/.test(navigator.userAgent)) return null;
22736
+ const SR = window.SpeechRecognition ?? window.webkitSpeechRecognition;
22737
+ return SR ?? null;
22738
+ }
22739
+ var SUPPORTED_MIME_TYPES = [
22740
+ "audio/webm;codecs=opus",
22741
+ "audio/webm",
22742
+ "audio/mp4",
22743
+ "audio/ogg;codecs=opus",
22744
+ "audio/ogg"
22745
+ ];
22746
+ function getSupportedMimeType() {
22747
+ if (typeof MediaRecorder === "undefined") {
22748
+ return "audio/webm";
22749
+ }
22750
+ for (const type of SUPPORTED_MIME_TYPES) {
22751
+ if (MediaRecorder.isTypeSupported(type)) {
22752
+ return type;
22753
+ }
22754
+ }
22755
+ return "audio/webm";
22756
+ }
22757
+ var SAMPLE_RATE = 16e3;
22758
+ async function audioToFloat32(blob) {
22759
+ const arrayBuffer = await blob.arrayBuffer();
22760
+ const audioContext = new AudioContext({ sampleRate: SAMPLE_RATE });
22761
+ try {
22762
+ const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
22763
+ if (audioBuffer.numberOfChannels === 1) {
22764
+ return audioBuffer.getChannelData(0);
22765
+ }
22766
+ const length = audioBuffer.length;
22767
+ const mono = new Float32Array(length);
22768
+ const channels = audioBuffer.numberOfChannels;
22769
+ for (let ch = 0; ch < channels; ch++) {
22770
+ const data = audioBuffer.getChannelData(ch);
22771
+ for (let i = 0; i < length; i++) {
22772
+ mono[i] += data[i];
22773
+ }
22774
+ }
22775
+ for (let i = 0; i < length; i++) {
22776
+ mono[i] /= channels;
22777
+ }
22778
+ return mono;
22779
+ } finally {
22780
+ await audioContext.close();
22781
+ }
22782
+ }
22783
+ function useVoice(options) {
22784
+ const [isRecording, setIsRecording] = (0, import_react13.useState)(false);
22785
+ const [isTranscribing, setIsTranscribing] = (0, import_react13.useState)(false);
22786
+ const [isModelLoaded, setIsModelLoaded] = (0, import_react13.useState)(false);
22787
+ const [isLoadingModel, setIsLoadingModel] = (0, import_react13.useState)(false);
22788
+ const [recording, setRecording] = (0, import_react13.useState)(null);
22789
+ const [transcription, setTranscription] = (0, import_react13.useState)(null);
22790
+ const [error, setError] = (0, import_react13.useState)(null);
22791
+ const mediaRecorderRef = (0, import_react13.useRef)(null);
22792
+ const mediaStreamRef = (0, import_react13.useRef)(null);
22793
+ const chunksRef = (0, import_react13.useRef)([]);
22794
+ const startTimeRef = (0, import_react13.useRef)(0);
22795
+ const pipelineRef = (0, import_react13.useRef)(null);
22796
+ const modelNameRef = (0, import_react13.useRef)(null);
22797
+ const getModelName = (0, import_react13.useCallback)(() => {
22798
+ const model = options?.model ?? "whisper-tiny";
22799
+ return `onnx-community/${model}`;
22800
+ }, [options?.model]);
22801
+ const loadPipeline = (0, import_react13.useCallback)(async () => {
22802
+ const modelName = getModelName();
22803
+ if (pipelineRef.current && modelNameRef.current === modelName) {
22804
+ return pipelineRef.current;
22805
+ }
22806
+ setIsLoadingModel(true);
22807
+ setError(null);
22808
+ try {
22809
+ const { pipeline } = await import("@huggingface/transformers");
22810
+ const transcriber = await pipeline("automatic-speech-recognition", modelName, {
22811
+ dtype: "q4",
22812
+ device: "wasm",
22813
+ progress_callback: options?.onModelProgress ? (progress) => {
22814
+ if (progress.file && progress.progress !== null && progress.progress !== void 0) {
22815
+ options.onModelProgress({
22816
+ file: progress.file,
22817
+ progress: progress.progress / 100,
22818
+ loaded: progress.loaded ?? 0,
22819
+ total: progress.total ?? 0
22820
+ });
22821
+ }
22822
+ } : void 0
22823
+ });
22824
+ pipelineRef.current = transcriber;
22825
+ modelNameRef.current = modelName;
22826
+ setIsModelLoaded(true);
22827
+ return pipelineRef.current;
22828
+ } catch (err) {
22829
+ const processedError = err instanceof Error ? err : new Error("Failed to load Whisper model");
22830
+ setError(processedError);
22831
+ throw processedError;
22832
+ } finally {
22833
+ setIsLoadingModel(false);
22834
+ }
22835
+ }, [getModelName, options?.onModelProgress]);
22836
+ const preloadModel = (0, import_react13.useCallback)(async () => {
22837
+ await loadPipeline();
22838
+ }, [loadPipeline]);
22839
+ const disposeModel = (0, import_react13.useCallback)(async () => {
22840
+ const pipe = pipelineRef.current;
22841
+ if (pipe?.dispose) {
22842
+ await pipe.dispose();
22843
+ }
22844
+ pipelineRef.current = null;
22845
+ modelNameRef.current = null;
22846
+ setIsModelLoaded(false);
22847
+ }, []);
22848
+ const startRecording = (0, import_react13.useCallback)(async () => {
22849
+ setError(null);
22850
+ setRecording(null);
22851
+ setTranscription(null);
22852
+ try {
22853
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
22854
+ mediaStreamRef.current = stream;
22855
+ const mimeType = getSupportedMimeType();
22856
+ const recorder = new MediaRecorder(stream, { mimeType });
22857
+ mediaRecorderRef.current = recorder;
22858
+ chunksRef.current = [];
22859
+ recorder.ondataavailable = (e) => {
22860
+ if (e.data.size > 0) {
22861
+ chunksRef.current.push(e.data);
22862
+ }
22863
+ };
22864
+ recorder.start();
22865
+ startTimeRef.current = Date.now();
22866
+ setIsRecording(true);
22867
+ } catch (err) {
22868
+ const processedError = err instanceof Error ? err : new Error("Failed to start recording");
22869
+ setError(processedError);
22870
+ throw processedError;
22871
+ }
22872
+ }, []);
22873
+ const stopRecording = (0, import_react13.useCallback)(async () => {
22874
+ return new Promise((resolve, reject) => {
22875
+ const recorder = mediaRecorderRef.current;
22876
+ if (!recorder || recorder.state === "inactive") {
22877
+ const err = new Error("No active recording");
22878
+ setError(err);
22879
+ reject(err);
22880
+ return;
22881
+ }
22882
+ recorder.onstop = () => {
22883
+ const mimeType = recorder.mimeType || "audio/webm";
22884
+ const blob = new Blob(chunksRef.current, { type: mimeType });
22885
+ const duration = Date.now() - startTimeRef.current;
22886
+ mediaStreamRef.current?.getTracks().forEach((t) => t.stop());
22887
+ mediaStreamRef.current = null;
22888
+ mediaRecorderRef.current = null;
22889
+ const result = { blob, duration, mimeType };
22890
+ setRecording(result);
22891
+ setIsRecording(false);
22892
+ resolve(result);
22893
+ };
22894
+ recorder.onerror = () => {
22895
+ const err = new Error("Recording failed");
22896
+ setError(err);
22897
+ setIsRecording(false);
22898
+ reject(err);
22899
+ };
22900
+ recorder.stop();
22901
+ });
22902
+ }, []);
22903
+ const transcribe = (0, import_react13.useCallback)(
22904
+ async (rec) => {
22905
+ const target = rec ?? recording;
22906
+ if (!target) {
22907
+ const err = new Error("No recording to transcribe");
22908
+ setError(err);
22909
+ throw err;
22910
+ }
22911
+ setIsTranscribing(true);
22912
+ setError(null);
22913
+ try {
22914
+ const pipe = await loadPipeline();
22915
+ const audio = await audioToFloat32(target.blob);
22916
+ const result = await pipe(audio, {
22917
+ language: options?.language,
22918
+ return_timestamps: true
22919
+ });
22920
+ const transcriptionResult = {
22921
+ text: result.text.trim(),
22922
+ chunks: result.chunks
22923
+ };
22924
+ setTranscription(transcriptionResult);
22925
+ return transcriptionResult;
22926
+ } catch (err) {
22927
+ const processedError = err instanceof Error ? err : new Error("Transcription failed");
22928
+ setError(processedError);
22929
+ throw processedError;
23413
22930
  } finally {
23414
- setIsExporting(false);
22931
+ setIsTranscribing(false);
23415
22932
  }
23416
22933
  },
23417
- []
22934
+ [recording, loadPipeline, options?.language]
23418
22935
  );
23419
- return {
23420
- exportElementToPdf: wrappedExportElement,
23421
- exportMarkdownToPdf: wrappedExportMarkdown,
23422
- downloadElementAsPdf,
23423
- downloadMarkdownAsPdf,
23424
- renderElementToCanvas: wrappedRenderToCanvas,
23425
- isExporting,
23426
- progress,
23427
- error
23428
- };
23429
- }
23430
-
23431
- // src/react/useOCR.ts
23432
- var import_react11 = require("react");
23433
- var import_tesseract = __toESM(require("tesseract.js"));
23434
- init_logger();
23435
- function useOCR() {
23436
- const [isProcessing, setIsProcessing] = (0, import_react11.useState)(false);
23437
- const [error, setError] = (0, import_react11.useState)(null);
23438
- const extractOCRContext = (0, import_react11.useCallback)(async (files) => {
23439
- setIsProcessing(true);
22936
+ const nativeSpeechAvailable = (0, import_react13.useMemo)(() => getOnDeviceSpeechRecognition() !== null, []);
22937
+ const [isNativeListening, setIsNativeListening] = (0, import_react13.useState)(false);
22938
+ const nativeRecognitionRef = (0, import_react13.useRef)(null);
22939
+ const nativeTextRef = (0, import_react13.useRef)("");
22940
+ const nativeResolveRef = (0, import_react13.useRef)(null);
22941
+ const startNativeTranscription = (0, import_react13.useCallback)(() => {
22942
+ const SR = getOnDeviceSpeechRecognition();
22943
+ if (!SR) return;
22944
+ nativeTextRef.current = "";
23440
22945
  setError(null);
23441
- try {
23442
- if (files.length === 0) {
23443
- return null;
22946
+ const recognition = new SR();
22947
+ recognition.continuous = true;
22948
+ recognition.interimResults = false;
22949
+ recognition.lang = options?.language ?? "";
22950
+ recognition.onresult = (event) => {
22951
+ let text12 = "";
22952
+ for (let i = 0; i < event.results.length; i++) {
22953
+ const result = event.results[i];
22954
+ if (result && result.isFinal && result[0]) {
22955
+ text12 += result[0].transcript + " ";
22956
+ }
23444
22957
  }
23445
- const contexts = await Promise.all(
23446
- files.map(async (file) => {
23447
- try {
23448
- let imagesToProcess = [];
23449
- const language = file.language || "eng";
23450
- const filename = file.filename || (file.url instanceof File ? file.url.name : "");
23451
- let isPdf = false;
23452
- if (typeof file.url === "string") {
23453
- isPdf = file.url.toLowerCase().endsWith(".pdf") || (filename?.toLowerCase().endsWith(".pdf") ?? false);
23454
- } else if (file.url instanceof Blob) {
23455
- isPdf = file.url.type === "application/pdf" || (filename?.toLowerCase().endsWith(".pdf") ?? false);
23456
- }
23457
- if (isPdf) {
23458
- let pdfUrl;
23459
- let shouldRevoke = false;
23460
- if (typeof file.url === "string") {
23461
- pdfUrl = file.url;
23462
- } else {
23463
- pdfUrl = URL.createObjectURL(file.url);
23464
- shouldRevoke = true;
23465
- }
23466
- try {
23467
- const pdfImages = await convertPdfToImages(pdfUrl);
23468
- imagesToProcess = pdfImages;
23469
- } catch (e) {
23470
- getLogger().error("Failed to convert PDF to images", e);
23471
- throw e;
23472
- } finally {
23473
- if (shouldRevoke) {
23474
- URL.revokeObjectURL(pdfUrl);
23475
- }
23476
- }
23477
- } else {
23478
- imagesToProcess = [file.url];
23479
- }
23480
- const pageTexts = [];
23481
- for (const image of imagesToProcess) {
23482
- const result = await import_tesseract.default.recognize(image, language);
23483
- pageTexts.push(result.data.text);
23484
- }
23485
- const text12 = pageTexts.join("\n\n");
23486
- if (!text12.trim()) {
23487
- getLogger().warn(`No text found in OCR source ${filename || "unknown"}`);
23488
- return null;
23489
- }
23490
- return `[Context from OCR attachment ${filename || "unknown"}]:
23491
- ${text12}`;
23492
- } catch (err) {
23493
- getLogger().error(`Failed to process OCR for ${file.filename || "unknown"}:`, err);
23494
- return null;
23495
- }
23496
- })
23497
- );
23498
- const mergedContext = contexts.filter(Boolean).join("\n\n");
23499
- return mergedContext || null;
23500
- } catch (err) {
23501
- const processedError = err instanceof Error ? err : new Error(String(err));
23502
- setError(processedError);
23503
- throw processedError;
23504
- } finally {
23505
- setIsProcessing(false);
22958
+ nativeTextRef.current = text12.trim();
22959
+ };
22960
+ recognition.onerror = (event) => {
22961
+ if (event.error !== "aborted" && event.error !== "no-speech") {
22962
+ setError(new Error(`Speech recognition error: ${event.error}`));
22963
+ }
22964
+ };
22965
+ recognition.onend = () => {
22966
+ setIsNativeListening(false);
22967
+ nativeRecognitionRef.current = null;
22968
+ const resolve = nativeResolveRef.current;
22969
+ if (resolve) {
22970
+ nativeResolveRef.current = null;
22971
+ resolve({ text: nativeTextRef.current });
22972
+ }
22973
+ };
22974
+ nativeRecognitionRef.current = recognition;
22975
+ recognition.start();
22976
+ setIsNativeListening(true);
22977
+ }, [options?.language]);
22978
+ const stopNativeTranscription = (0, import_react13.useCallback)(() => {
22979
+ return new Promise((resolve) => {
22980
+ const recognition = nativeRecognitionRef.current;
22981
+ if (!recognition) {
22982
+ resolve({ text: nativeTextRef.current || "" });
22983
+ return;
22984
+ }
22985
+ nativeResolveRef.current = resolve;
22986
+ recognition.stop();
22987
+ });
22988
+ }, []);
22989
+ const abortNativeTranscription = (0, import_react13.useCallback)(() => {
22990
+ const recognition = nativeRecognitionRef.current;
22991
+ if (recognition) {
22992
+ nativeResolveRef.current = null;
22993
+ recognition.abort();
22994
+ nativeRecognitionRef.current = null;
22995
+ setIsNativeListening(false);
23506
22996
  }
23507
22997
  }, []);
23508
22998
  return {
23509
- extractOCRContext,
23510
- isProcessing,
23511
- error
22999
+ isRecording,
23000
+ startRecording,
23001
+ stopRecording,
23002
+ isTranscribing,
23003
+ transcribe,
23004
+ preloadModel,
23005
+ disposeModel,
23006
+ isModelLoaded,
23007
+ isLoadingModel,
23008
+ recording,
23009
+ transcription,
23010
+ error,
23011
+ nativeSpeechAvailable,
23012
+ startNativeTranscription,
23013
+ stopNativeTranscription,
23014
+ abortNativeTranscription,
23015
+ isNativeListening
23512
23016
  };
23513
23017
  }
23514
23018
 
23515
- // src/react/usePdf.ts
23516
- var import_react12 = require("react");
23517
- init_logger();
23518
- var PDF_MIME_TYPE = "application/pdf";
23519
- function usePdf() {
23520
- const [isProcessing, setIsProcessing] = (0, import_react12.useState)(false);
23521
- const [error, setError] = (0, import_react12.useState)(null);
23522
- const extractPdfContext = (0, import_react12.useCallback)(async (files) => {
23523
- setIsProcessing(true);
23524
- setError(null);
23525
- try {
23526
- const pdfFiles = files.filter(
23527
- (file) => file.mediaType === PDF_MIME_TYPE || file.filename?.toLowerCase().endsWith(".pdf")
23528
- );
23529
- if (pdfFiles.length === 0) {
23530
- return null;
23019
+ // src/react/useCredits.ts
23020
+ var import_react14 = require("react");
23021
+
23022
+ // src/client/core/bodySerializer.gen.ts
23023
+ var jsonBodySerializer = {
23024
+ bodySerializer: (body) => JSON.stringify(
23025
+ body,
23026
+ (_key, value) => typeof value === "bigint" ? value.toString() : value
23027
+ )
23028
+ };
23029
+
23030
+ // src/client/core/pathSerializer.gen.ts
23031
+ var separatorArrayExplode = (style) => {
23032
+ switch (style) {
23033
+ case "label":
23034
+ return ".";
23035
+ case "matrix":
23036
+ return ";";
23037
+ case "simple":
23038
+ return ",";
23039
+ default:
23040
+ return "&";
23041
+ }
23042
+ };
23043
+ var separatorArrayNoExplode = (style) => {
23044
+ switch (style) {
23045
+ case "form":
23046
+ return ",";
23047
+ case "pipeDelimited":
23048
+ return "|";
23049
+ case "spaceDelimited":
23050
+ return "%20";
23051
+ default:
23052
+ return ",";
23053
+ }
23054
+ };
23055
+ var separatorObjectExplode = (style) => {
23056
+ switch (style) {
23057
+ case "label":
23058
+ return ".";
23059
+ case "matrix":
23060
+ return ";";
23061
+ case "simple":
23062
+ return ",";
23063
+ default:
23064
+ return "&";
23065
+ }
23066
+ };
23067
+ var serializeArrayParam = ({
23068
+ allowReserved,
23069
+ explode,
23070
+ name,
23071
+ style,
23072
+ value
23073
+ }) => {
23074
+ if (!explode) {
23075
+ const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
23076
+ switch (style) {
23077
+ case "label":
23078
+ return `.${joinedValues2}`;
23079
+ case "matrix":
23080
+ return `;${name}=${joinedValues2}`;
23081
+ case "simple":
23082
+ return joinedValues2;
23083
+ default:
23084
+ return `${name}=${joinedValues2}`;
23085
+ }
23086
+ }
23087
+ const separator = separatorArrayExplode(style);
23088
+ const joinedValues = value.map((v) => {
23089
+ if (style === "label" || style === "simple") {
23090
+ return allowReserved ? v : encodeURIComponent(v);
23091
+ }
23092
+ return serializePrimitiveParam({
23093
+ allowReserved,
23094
+ name,
23095
+ value: v
23096
+ });
23097
+ }).join(separator);
23098
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
23099
+ };
23100
+ var serializePrimitiveParam = ({
23101
+ allowReserved,
23102
+ name,
23103
+ value
23104
+ }) => {
23105
+ if (value === void 0 || value === null) {
23106
+ return "";
23107
+ }
23108
+ if (typeof value === "object") {
23109
+ throw new Error(
23110
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
23111
+ );
23112
+ }
23113
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
23114
+ };
23115
+ var serializeObjectParam = ({
23116
+ allowReserved,
23117
+ explode,
23118
+ name,
23119
+ style,
23120
+ value,
23121
+ valueOnly
23122
+ }) => {
23123
+ if (value instanceof Date) {
23124
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
23125
+ }
23126
+ if (style !== "deepObject" && !explode) {
23127
+ let values = [];
23128
+ Object.entries(value).forEach(([key, v]) => {
23129
+ values = [
23130
+ ...values,
23131
+ key,
23132
+ allowReserved ? v : encodeURIComponent(v)
23133
+ ];
23134
+ });
23135
+ const joinedValues2 = values.join(",");
23136
+ switch (style) {
23137
+ case "form":
23138
+ return `${name}=${joinedValues2}`;
23139
+ case "label":
23140
+ return `.${joinedValues2}`;
23141
+ case "matrix":
23142
+ return `;${name}=${joinedValues2}`;
23143
+ default:
23144
+ return joinedValues2;
23145
+ }
23146
+ }
23147
+ const separator = separatorObjectExplode(style);
23148
+ const joinedValues = Object.entries(value).map(
23149
+ ([key, v]) => serializePrimitiveParam({
23150
+ allowReserved,
23151
+ name: style === "deepObject" ? `${name}[${key}]` : key,
23152
+ value: v
23153
+ })
23154
+ ).join(separator);
23155
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
23156
+ };
23157
+
23158
+ // src/client/core/utils.gen.ts
23159
+ function getValidRequestBody(options) {
23160
+ const hasBody = options.body !== void 0;
23161
+ const isSerializedBody = hasBody && options.bodySerializer;
23162
+ if (isSerializedBody) {
23163
+ if ("serializedBody" in options) {
23164
+ const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
23165
+ return hasSerializedBody ? options.serializedBody : null;
23166
+ }
23167
+ return options.body !== "" ? options.body : null;
23168
+ }
23169
+ if (hasBody) {
23170
+ return options.body;
23171
+ }
23172
+ return void 0;
23173
+ }
23174
+
23175
+ // src/client/core/auth.gen.ts
23176
+ var getAuthToken = async (auth, callback) => {
23177
+ const token = typeof callback === "function" ? await callback(auth) : callback;
23178
+ if (!token) {
23179
+ return;
23180
+ }
23181
+ if (auth.scheme === "bearer") {
23182
+ return `Bearer ${token}`;
23183
+ }
23184
+ if (auth.scheme === "basic") {
23185
+ return `Basic ${btoa(token)}`;
23186
+ }
23187
+ return token;
23188
+ };
23189
+
23190
+ // src/client/client/utils.gen.ts
23191
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
23192
+ var defaultPathSerializer = ({ path, url: _url }) => {
23193
+ let url = _url;
23194
+ const matches = _url.match(PATH_PARAM_RE);
23195
+ if (matches) {
23196
+ for (const match of matches) {
23197
+ let explode = false;
23198
+ let name = match.substring(1, match.length - 1);
23199
+ let style = "simple";
23200
+ if (name.endsWith("*")) {
23201
+ explode = true;
23202
+ name = name.substring(0, name.length - 1);
23203
+ }
23204
+ if (name.startsWith(".")) {
23205
+ name = name.substring(1);
23206
+ style = "label";
23207
+ } else if (name.startsWith(";")) {
23208
+ name = name.substring(1);
23209
+ style = "matrix";
23210
+ }
23211
+ const value = path[name];
23212
+ if (value === void 0 || value === null) {
23213
+ continue;
23531
23214
  }
23532
- const contexts = await Promise.all(
23533
- pdfFiles.map(async (file) => {
23534
- try {
23535
- const text12 = await extractTextFromPdf(file.url);
23536
- if (!text12.trim()) {
23537
- getLogger().warn(`No text found in PDF ${file.filename}`);
23538
- return null;
23539
- }
23540
- return `[Context from PDF attachment ${file.filename}]:
23541
- ${text12}`;
23542
- } catch (err) {
23543
- getLogger().error(`Failed to process PDF ${file.filename}:`, err);
23544
- return null;
23545
- }
23546
- })
23215
+ if (Array.isArray(value)) {
23216
+ url = url.replace(
23217
+ match,
23218
+ serializeArrayParam({ explode, name, style, value })
23219
+ );
23220
+ continue;
23221
+ }
23222
+ if (typeof value === "object") {
23223
+ url = url.replace(
23224
+ match,
23225
+ serializeObjectParam({
23226
+ explode,
23227
+ name,
23228
+ style,
23229
+ value,
23230
+ valueOnly: true
23231
+ })
23232
+ );
23233
+ continue;
23234
+ }
23235
+ if (style === "matrix") {
23236
+ url = url.replace(
23237
+ match,
23238
+ `;${serializePrimitiveParam({
23239
+ name,
23240
+ value
23241
+ })}`
23242
+ );
23243
+ continue;
23244
+ }
23245
+ const replaceValue = encodeURIComponent(
23246
+ style === "label" ? `.${value}` : value
23547
23247
  );
23548
- const mergedContext = contexts.filter(Boolean).join("\n\n");
23549
- return mergedContext || null;
23550
- } catch (err) {
23551
- const processedError = err instanceof Error ? err : new Error(String(err));
23552
- setError(processedError);
23553
- throw processedError;
23554
- } finally {
23555
- setIsProcessing(false);
23248
+ url = url.replace(match, replaceValue);
23556
23249
  }
23557
- }, []);
23558
- return {
23559
- extractPdfContext,
23560
- isProcessing,
23561
- error
23250
+ }
23251
+ return url;
23252
+ };
23253
+ var createQuerySerializer = ({
23254
+ parameters = {},
23255
+ ...args
23256
+ } = {}) => {
23257
+ const querySerializer = (queryParams) => {
23258
+ const search = [];
23259
+ if (queryParams && typeof queryParams === "object") {
23260
+ for (const name in queryParams) {
23261
+ const value = queryParams[name];
23262
+ if (value === void 0 || value === null) {
23263
+ continue;
23264
+ }
23265
+ const options = parameters[name] || args;
23266
+ if (Array.isArray(value)) {
23267
+ const serializedArray = serializeArrayParam({
23268
+ allowReserved: options.allowReserved,
23269
+ explode: true,
23270
+ name,
23271
+ style: "form",
23272
+ value,
23273
+ ...options.array
23274
+ });
23275
+ if (serializedArray) search.push(serializedArray);
23276
+ } else if (typeof value === "object") {
23277
+ const serializedObject = serializeObjectParam({
23278
+ allowReserved: options.allowReserved,
23279
+ explode: true,
23280
+ name,
23281
+ style: "deepObject",
23282
+ value,
23283
+ ...options.object
23284
+ });
23285
+ if (serializedObject) search.push(serializedObject);
23286
+ } else {
23287
+ const serializedPrimitive = serializePrimitiveParam({
23288
+ allowReserved: options.allowReserved,
23289
+ name,
23290
+ value
23291
+ });
23292
+ if (serializedPrimitive) search.push(serializedPrimitive);
23293
+ }
23294
+ }
23295
+ }
23296
+ return search.join("&");
23562
23297
  };
23563
- }
23564
-
23565
- // src/react/useVoice.ts
23566
- var import_react13 = require("react");
23567
- function getOnDeviceSpeechRecognition() {
23568
- if (typeof window === "undefined") return null;
23569
- if (!/iPhone|iPad|iPod/.test(navigator.userAgent)) return null;
23570
- const SR = window.SpeechRecognition ?? window.webkitSpeechRecognition;
23571
- return SR ?? null;
23572
- }
23573
- var SUPPORTED_MIME_TYPES = [
23574
- "audio/webm;codecs=opus",
23575
- "audio/webm",
23576
- "audio/mp4",
23577
- "audio/ogg;codecs=opus",
23578
- "audio/ogg"
23579
- ];
23580
- function getSupportedMimeType() {
23581
- if (typeof MediaRecorder === "undefined") {
23582
- return "audio/webm";
23298
+ return querySerializer;
23299
+ };
23300
+ var getParseAs = (contentType) => {
23301
+ if (!contentType) {
23302
+ return "stream";
23583
23303
  }
23584
- for (const type of SUPPORTED_MIME_TYPES) {
23585
- if (MediaRecorder.isTypeSupported(type)) {
23586
- return type;
23304
+ const cleanContent = contentType.split(";")[0]?.trim();
23305
+ if (!cleanContent) {
23306
+ return;
23307
+ }
23308
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
23309
+ return "json";
23310
+ }
23311
+ if (cleanContent === "multipart/form-data") {
23312
+ return "formData";
23313
+ }
23314
+ if (["application/", "audio/", "image/", "video/"].some(
23315
+ (type) => cleanContent.startsWith(type)
23316
+ )) {
23317
+ return "blob";
23318
+ }
23319
+ if (cleanContent.startsWith("text/")) {
23320
+ return "text";
23321
+ }
23322
+ return;
23323
+ };
23324
+ var checkForExistence = (options, name) => {
23325
+ if (!name) {
23326
+ return false;
23327
+ }
23328
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
23329
+ return true;
23330
+ }
23331
+ return false;
23332
+ };
23333
+ var setAuthParams = async ({
23334
+ security,
23335
+ ...options
23336
+ }) => {
23337
+ for (const auth of security) {
23338
+ if (checkForExistence(options, auth.name)) {
23339
+ continue;
23340
+ }
23341
+ const token = await getAuthToken(auth, options.auth);
23342
+ if (!token) {
23343
+ continue;
23344
+ }
23345
+ const name = auth.name ?? "Authorization";
23346
+ switch (auth.in) {
23347
+ case "query":
23348
+ if (!options.query) {
23349
+ options.query = {};
23350
+ }
23351
+ options.query[name] = token;
23352
+ break;
23353
+ case "cookie":
23354
+ options.headers.append("Cookie", `${name}=${token}`);
23355
+ break;
23356
+ case "header":
23357
+ default:
23358
+ options.headers.set(name, token);
23359
+ break;
23587
23360
  }
23588
23361
  }
23589
- return "audio/webm";
23590
- }
23591
- var SAMPLE_RATE = 16e3;
23592
- async function audioToFloat32(blob) {
23593
- const arrayBuffer = await blob.arrayBuffer();
23594
- const audioContext = new AudioContext({ sampleRate: SAMPLE_RATE });
23595
- try {
23596
- const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
23597
- if (audioBuffer.numberOfChannels === 1) {
23598
- return audioBuffer.getChannelData(0);
23362
+ };
23363
+ var buildUrl = (options) => {
23364
+ const url = getUrl({
23365
+ baseUrl: options.baseUrl,
23366
+ path: options.path,
23367
+ query: options.query,
23368
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
23369
+ url: options.url
23370
+ });
23371
+ return url;
23372
+ };
23373
+ var getUrl = ({
23374
+ baseUrl,
23375
+ path,
23376
+ query,
23377
+ querySerializer,
23378
+ url: _url
23379
+ }) => {
23380
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
23381
+ let url = (baseUrl ?? "") + pathUrl;
23382
+ if (path) {
23383
+ url = defaultPathSerializer({ path, url });
23384
+ }
23385
+ let search = query ? querySerializer(query) : "";
23386
+ if (search.startsWith("?")) {
23387
+ search = search.substring(1);
23388
+ }
23389
+ if (search) {
23390
+ url += `?${search}`;
23391
+ }
23392
+ return url;
23393
+ };
23394
+ var mergeConfigs = (a, b) => {
23395
+ const config = { ...a, ...b };
23396
+ if (config.baseUrl?.endsWith("/")) {
23397
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
23398
+ }
23399
+ config.headers = mergeHeaders(a.headers, b.headers);
23400
+ return config;
23401
+ };
23402
+ var headersEntries = (headers) => {
23403
+ const entries = [];
23404
+ headers.forEach((value, key) => {
23405
+ entries.push([key, value]);
23406
+ });
23407
+ return entries;
23408
+ };
23409
+ var mergeHeaders = (...headers) => {
23410
+ const mergedHeaders = new Headers();
23411
+ for (const header of headers) {
23412
+ if (!header || typeof header !== "object") {
23413
+ continue;
23599
23414
  }
23600
- const length = audioBuffer.length;
23601
- const mono = new Float32Array(length);
23602
- const channels = audioBuffer.numberOfChannels;
23603
- for (let ch = 0; ch < channels; ch++) {
23604
- const data = audioBuffer.getChannelData(ch);
23605
- for (let i = 0; i < length; i++) {
23606
- mono[i] += data[i];
23415
+ const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
23416
+ for (const [key, value] of iterator) {
23417
+ if (value === null) {
23418
+ mergedHeaders.delete(key);
23419
+ } else if (Array.isArray(value)) {
23420
+ for (const v of value) {
23421
+ mergedHeaders.append(key, v);
23422
+ }
23423
+ } else if (value !== void 0) {
23424
+ mergedHeaders.set(
23425
+ key,
23426
+ typeof value === "object" ? JSON.stringify(value) : value
23427
+ );
23607
23428
  }
23608
23429
  }
23609
- for (let i = 0; i < length; i++) {
23610
- mono[i] /= channels;
23430
+ }
23431
+ return mergedHeaders;
23432
+ };
23433
+ var Interceptors = class {
23434
+ constructor() {
23435
+ this.fns = [];
23436
+ }
23437
+ clear() {
23438
+ this.fns = [];
23439
+ }
23440
+ eject(id) {
23441
+ const index = this.getInterceptorIndex(id);
23442
+ if (this.fns[index]) {
23443
+ this.fns[index] = null;
23611
23444
  }
23612
- return mono;
23613
- } finally {
23614
- await audioContext.close();
23615
23445
  }
23616
- }
23617
- function useVoice(options) {
23618
- const [isRecording, setIsRecording] = (0, import_react13.useState)(false);
23619
- const [isTranscribing, setIsTranscribing] = (0, import_react13.useState)(false);
23620
- const [isModelLoaded, setIsModelLoaded] = (0, import_react13.useState)(false);
23621
- const [isLoadingModel, setIsLoadingModel] = (0, import_react13.useState)(false);
23622
- const [recording, setRecording] = (0, import_react13.useState)(null);
23623
- const [transcription, setTranscription] = (0, import_react13.useState)(null);
23624
- const [error, setError] = (0, import_react13.useState)(null);
23625
- const mediaRecorderRef = (0, import_react13.useRef)(null);
23626
- const mediaStreamRef = (0, import_react13.useRef)(null);
23627
- const chunksRef = (0, import_react13.useRef)([]);
23628
- const startTimeRef = (0, import_react13.useRef)(0);
23629
- const pipelineRef = (0, import_react13.useRef)(null);
23630
- const modelNameRef = (0, import_react13.useRef)(null);
23631
- const getModelName = (0, import_react13.useCallback)(() => {
23632
- const model = options?.model ?? "whisper-tiny";
23633
- return `onnx-community/${model}`;
23634
- }, [options?.model]);
23635
- const loadPipeline = (0, import_react13.useCallback)(async () => {
23636
- const modelName = getModelName();
23637
- if (pipelineRef.current && modelNameRef.current === modelName) {
23638
- return pipelineRef.current;
23446
+ exists(id) {
23447
+ const index = this.getInterceptorIndex(id);
23448
+ return Boolean(this.fns[index]);
23449
+ }
23450
+ getInterceptorIndex(id) {
23451
+ if (typeof id === "number") {
23452
+ return this.fns[id] ? id : -1;
23639
23453
  }
23640
- setIsLoadingModel(true);
23641
- setError(null);
23642
- try {
23643
- const { pipeline } = await import("@huggingface/transformers");
23644
- const transcriber = await pipeline("automatic-speech-recognition", modelName, {
23645
- dtype: "q4",
23646
- device: "wasm",
23647
- progress_callback: options?.onModelProgress ? (progress) => {
23648
- if (progress.file && progress.progress !== null && progress.progress !== void 0) {
23649
- options.onModelProgress({
23650
- file: progress.file,
23651
- progress: progress.progress / 100,
23652
- loaded: progress.loaded ?? 0,
23653
- total: progress.total ?? 0
23654
- });
23655
- }
23656
- } : void 0
23657
- });
23658
- pipelineRef.current = transcriber;
23659
- modelNameRef.current = modelName;
23660
- setIsModelLoaded(true);
23661
- return pipelineRef.current;
23662
- } catch (err) {
23663
- const processedError = err instanceof Error ? err : new Error("Failed to load Whisper model");
23664
- setError(processedError);
23665
- throw processedError;
23666
- } finally {
23667
- setIsLoadingModel(false);
23454
+ return this.fns.indexOf(id);
23455
+ }
23456
+ update(id, fn) {
23457
+ const index = this.getInterceptorIndex(id);
23458
+ if (this.fns[index]) {
23459
+ this.fns[index] = fn;
23460
+ return id;
23668
23461
  }
23669
- }, [getModelName, options?.onModelProgress]);
23670
- const preloadModel = (0, import_react13.useCallback)(async () => {
23671
- await loadPipeline();
23672
- }, [loadPipeline]);
23673
- const disposeModel = (0, import_react13.useCallback)(async () => {
23674
- const pipe = pipelineRef.current;
23675
- if (pipe?.dispose) {
23676
- await pipe.dispose();
23462
+ return false;
23463
+ }
23464
+ use(fn) {
23465
+ this.fns.push(fn);
23466
+ return this.fns.length - 1;
23467
+ }
23468
+ };
23469
+ var createInterceptors = () => ({
23470
+ error: new Interceptors(),
23471
+ request: new Interceptors(),
23472
+ response: new Interceptors()
23473
+ });
23474
+ var defaultQuerySerializer = createQuerySerializer({
23475
+ allowReserved: false,
23476
+ array: {
23477
+ explode: true,
23478
+ style: "form"
23479
+ },
23480
+ object: {
23481
+ explode: true,
23482
+ style: "deepObject"
23483
+ }
23484
+ });
23485
+ var defaultHeaders = {
23486
+ "Content-Type": "application/json"
23487
+ };
23488
+ var createConfig = (override = {}) => ({
23489
+ ...jsonBodySerializer,
23490
+ headers: defaultHeaders,
23491
+ parseAs: "auto",
23492
+ querySerializer: defaultQuerySerializer,
23493
+ ...override
23494
+ });
23495
+
23496
+ // src/client/client/client.gen.ts
23497
+ var createClient = (config = {}) => {
23498
+ let _config = mergeConfigs(createConfig(), config);
23499
+ const getConfig = () => ({ ..._config });
23500
+ const setConfig = (config2) => {
23501
+ _config = mergeConfigs(_config, config2);
23502
+ return getConfig();
23503
+ };
23504
+ const interceptors = createInterceptors();
23505
+ const beforeRequest = async (options) => {
23506
+ const opts = {
23507
+ ..._config,
23508
+ ...options,
23509
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
23510
+ headers: mergeHeaders(_config.headers, options.headers),
23511
+ serializedBody: void 0
23512
+ };
23513
+ if (opts.security) {
23514
+ await setAuthParams({
23515
+ ...opts,
23516
+ security: opts.security
23517
+ });
23677
23518
  }
23678
- pipelineRef.current = null;
23679
- modelNameRef.current = null;
23680
- setIsModelLoaded(false);
23681
- }, []);
23682
- const startRecording = (0, import_react13.useCallback)(async () => {
23683
- setError(null);
23684
- setRecording(null);
23685
- setTranscription(null);
23686
- try {
23687
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
23688
- mediaStreamRef.current = stream;
23689
- const mimeType = getSupportedMimeType();
23690
- const recorder = new MediaRecorder(stream, { mimeType });
23691
- mediaRecorderRef.current = recorder;
23692
- chunksRef.current = [];
23693
- recorder.ondataavailable = (e) => {
23694
- if (e.data.size > 0) {
23695
- chunksRef.current.push(e.data);
23696
- }
23697
- };
23698
- recorder.start();
23699
- startTimeRef.current = Date.now();
23700
- setIsRecording(true);
23701
- } catch (err) {
23702
- const processedError = err instanceof Error ? err : new Error("Failed to start recording");
23703
- setError(processedError);
23704
- throw processedError;
23519
+ if (opts.requestValidator) {
23520
+ await opts.requestValidator(opts);
23705
23521
  }
23706
- }, []);
23707
- const stopRecording = (0, import_react13.useCallback)(async () => {
23708
- return new Promise((resolve, reject) => {
23709
- const recorder = mediaRecorderRef.current;
23710
- if (!recorder || recorder.state === "inactive") {
23711
- const err = new Error("No active recording");
23712
- setError(err);
23713
- reject(err);
23714
- return;
23522
+ if (opts.body !== void 0 && opts.bodySerializer) {
23523
+ opts.serializedBody = opts.bodySerializer(opts.body);
23524
+ }
23525
+ if (opts.body === void 0 || opts.serializedBody === "") {
23526
+ opts.headers.delete("Content-Type");
23527
+ }
23528
+ const url = buildUrl(opts);
23529
+ return { opts, url };
23530
+ };
23531
+ const request = async (options) => {
23532
+ const { opts, url } = await beforeRequest(options);
23533
+ for (const fn of interceptors.request.fns) {
23534
+ if (fn) {
23535
+ await fn(opts);
23715
23536
  }
23716
- recorder.onstop = () => {
23717
- const mimeType = recorder.mimeType || "audio/webm";
23718
- const blob = new Blob(chunksRef.current, { type: mimeType });
23719
- const duration = Date.now() - startTimeRef.current;
23720
- mediaStreamRef.current?.getTracks().forEach((t) => t.stop());
23721
- mediaStreamRef.current = null;
23722
- mediaRecorderRef.current = null;
23723
- const result = { blob, duration, mimeType };
23724
- setRecording(result);
23725
- setIsRecording(false);
23726
- resolve(result);
23727
- };
23728
- recorder.onerror = () => {
23729
- const err = new Error("Recording failed");
23730
- setError(err);
23731
- setIsRecording(false);
23732
- reject(err);
23733
- };
23734
- recorder.stop();
23735
- });
23736
- }, []);
23737
- const transcribe = (0, import_react13.useCallback)(
23738
- async (rec) => {
23739
- const target = rec ?? recording;
23740
- if (!target) {
23741
- const err = new Error("No recording to transcribe");
23742
- setError(err);
23743
- throw err;
23537
+ }
23538
+ const _fetch = opts.fetch;
23539
+ const requestInit = {
23540
+ ...opts,
23541
+ body: getValidRequestBody(opts)
23542
+ };
23543
+ let response = await _fetch(url, requestInit);
23544
+ for (const fn of interceptors.response.fns) {
23545
+ if (fn) {
23546
+ response = await fn(response, opts);
23744
23547
  }
23745
- setIsTranscribing(true);
23746
- setError(null);
23747
- try {
23748
- const pipe = await loadPipeline();
23749
- const audio = await audioToFloat32(target.blob);
23750
- const result = await pipe(audio, {
23751
- language: options?.language,
23752
- return_timestamps: true
23753
- });
23754
- const transcriptionResult = {
23755
- text: result.text.trim(),
23756
- chunks: result.chunks
23548
+ }
23549
+ const result = {
23550
+ response
23551
+ };
23552
+ if (response.ok) {
23553
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
23554
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
23555
+ let emptyData;
23556
+ switch (parseAs) {
23557
+ case "arrayBuffer":
23558
+ case "blob":
23559
+ case "text":
23560
+ emptyData = await response[parseAs]();
23561
+ break;
23562
+ case "formData":
23563
+ emptyData = new FormData();
23564
+ break;
23565
+ case "stream":
23566
+ emptyData = response.body;
23567
+ break;
23568
+ case "json":
23569
+ default:
23570
+ emptyData = {};
23571
+ break;
23572
+ }
23573
+ return {
23574
+ data: emptyData,
23575
+ ...result
23757
23576
  };
23758
- setTranscription(transcriptionResult);
23759
- return transcriptionResult;
23760
- } catch (err) {
23761
- const processedError = err instanceof Error ? err : new Error("Transcription failed");
23762
- setError(processedError);
23763
- throw processedError;
23764
- } finally {
23765
- setIsTranscribing(false);
23766
23577
  }
23767
- },
23768
- [recording, loadPipeline, options?.language]
23769
- );
23770
- const nativeSpeechAvailable = (0, import_react13.useMemo)(() => getOnDeviceSpeechRecognition() !== null, []);
23771
- const [isNativeListening, setIsNativeListening] = (0, import_react13.useState)(false);
23772
- const nativeRecognitionRef = (0, import_react13.useRef)(null);
23773
- const nativeTextRef = (0, import_react13.useRef)("");
23774
- const nativeResolveRef = (0, import_react13.useRef)(null);
23775
- const startNativeTranscription = (0, import_react13.useCallback)(() => {
23776
- const SR = getOnDeviceSpeechRecognition();
23777
- if (!SR) return;
23778
- nativeTextRef.current = "";
23779
- setError(null);
23780
- const recognition = new SR();
23781
- recognition.continuous = true;
23782
- recognition.interimResults = false;
23783
- recognition.lang = options?.language ?? "";
23784
- recognition.onresult = (event) => {
23785
- let text12 = "";
23786
- for (let i = 0; i < event.results.length; i++) {
23787
- const result = event.results[i];
23788
- if (result && result.isFinal && result[0]) {
23789
- text12 += result[0].transcript + " ";
23790
- }
23578
+ let data;
23579
+ switch (parseAs) {
23580
+ case "arrayBuffer":
23581
+ case "blob":
23582
+ case "formData":
23583
+ case "json":
23584
+ case "text":
23585
+ data = await response[parseAs]();
23586
+ break;
23587
+ case "stream":
23588
+ return {
23589
+ data: response.body,
23590
+ ...result
23591
+ };
23791
23592
  }
23792
- nativeTextRef.current = text12.trim();
23793
- };
23794
- recognition.onerror = (event) => {
23795
- if (event.error !== "aborted" && event.error !== "no-speech") {
23796
- setError(new Error(`Speech recognition error: ${event.error}`));
23593
+ if (parseAs === "json") {
23594
+ if (opts.responseValidator) {
23595
+ await opts.responseValidator(data);
23596
+ }
23597
+ if (opts.responseTransformer) {
23598
+ data = await opts.responseTransformer(data);
23599
+ }
23797
23600
  }
23798
- };
23799
- recognition.onend = () => {
23800
- setIsNativeListening(false);
23801
- nativeRecognitionRef.current = null;
23802
- const resolve = nativeResolveRef.current;
23803
- if (resolve) {
23804
- nativeResolveRef.current = null;
23805
- resolve({ text: nativeTextRef.current });
23601
+ return {
23602
+ data,
23603
+ ...result
23604
+ };
23605
+ }
23606
+ const textError = await response.text();
23607
+ let jsonError;
23608
+ try {
23609
+ jsonError = JSON.parse(textError);
23610
+ } catch {
23611
+ }
23612
+ const error = jsonError ?? textError;
23613
+ let finalError = error;
23614
+ for (const fn of interceptors.error.fns) {
23615
+ if (fn) {
23616
+ finalError = await fn(error, response, opts);
23806
23617
  }
23618
+ }
23619
+ finalError = finalError || {};
23620
+ if (opts.throwOnError) {
23621
+ throw finalError;
23622
+ }
23623
+ return {
23624
+ error: finalError,
23625
+ ...result
23807
23626
  };
23808
- nativeRecognitionRef.current = recognition;
23809
- recognition.start();
23810
- setIsNativeListening(true);
23811
- }, [options?.language]);
23812
- const stopNativeTranscription = (0, import_react13.useCallback)(() => {
23813
- return new Promise((resolve) => {
23814
- const recognition = nativeRecognitionRef.current;
23815
- if (!recognition) {
23816
- resolve({ text: nativeTextRef.current || "" });
23817
- return;
23818
- }
23819
- nativeResolveRef.current = resolve;
23820
- recognition.stop();
23627
+ };
23628
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
23629
+ const makeSseFn = (method) => async (options) => {
23630
+ const { opts, url } = await beforeRequest(options);
23631
+ return createSseClient({
23632
+ ...opts,
23633
+ body: opts.body,
23634
+ headers: opts.headers,
23635
+ method,
23636
+ onRequest: async (url2, init) => {
23637
+ let request2 = new Request(url2, init);
23638
+ const requestInit = {
23639
+ ...init,
23640
+ method: init.method,
23641
+ url: url2
23642
+ };
23643
+ for (const fn of interceptors.request.fns) {
23644
+ if (fn) {
23645
+ await fn(requestInit);
23646
+ request2 = new Request(requestInit.url, requestInit);
23647
+ }
23648
+ }
23649
+ return request2;
23650
+ },
23651
+ url
23821
23652
  });
23822
- }, []);
23823
- const abortNativeTranscription = (0, import_react13.useCallback)(() => {
23824
- const recognition = nativeRecognitionRef.current;
23825
- if (recognition) {
23826
- nativeResolveRef.current = null;
23827
- recognition.abort();
23828
- nativeRecognitionRef.current = null;
23829
- setIsNativeListening(false);
23830
- }
23831
- }, []);
23653
+ };
23832
23654
  return {
23833
- isRecording,
23834
- startRecording,
23835
- stopRecording,
23836
- isTranscribing,
23837
- transcribe,
23838
- preloadModel,
23839
- disposeModel,
23840
- isModelLoaded,
23841
- isLoadingModel,
23842
- recording,
23843
- transcription,
23844
- error,
23845
- nativeSpeechAvailable,
23846
- startNativeTranscription,
23847
- stopNativeTranscription,
23848
- abortNativeTranscription,
23849
- isNativeListening
23655
+ buildUrl,
23656
+ connect: makeMethodFn("CONNECT"),
23657
+ delete: makeMethodFn("DELETE"),
23658
+ get: makeMethodFn("GET"),
23659
+ getConfig,
23660
+ head: makeMethodFn("HEAD"),
23661
+ interceptors,
23662
+ options: makeMethodFn("OPTIONS"),
23663
+ patch: makeMethodFn("PATCH"),
23664
+ post: makeMethodFn("POST"),
23665
+ put: makeMethodFn("PUT"),
23666
+ request,
23667
+ setConfig,
23668
+ sse: {
23669
+ connect: makeSseFn("CONNECT"),
23670
+ delete: makeSseFn("DELETE"),
23671
+ get: makeSseFn("GET"),
23672
+ head: makeSseFn("HEAD"),
23673
+ options: makeSseFn("OPTIONS"),
23674
+ patch: makeSseFn("PATCH"),
23675
+ post: makeSseFn("POST"),
23676
+ put: makeSseFn("PUT"),
23677
+ trace: makeSseFn("TRACE")
23678
+ },
23679
+ trace: makeMethodFn("TRACE")
23850
23680
  };
23851
- }
23681
+ };
23682
+
23683
+ // src/client/client.gen.ts
23684
+ init_clientConfig();
23685
+ var client = createClient(createClientConfig(createConfig()));
23686
+
23687
+ // src/client/sdk.gen.ts
23688
+ var getApiV1Config = (options) => {
23689
+ return (options?.client ?? client).get({
23690
+ url: "/api/v1/config",
23691
+ ...options
23692
+ });
23693
+ };
23694
+ var getApiV1CreditsBalance = (options) => {
23695
+ return (options?.client ?? client).get({
23696
+ url: "/api/v1/credits/balance",
23697
+ ...options
23698
+ });
23699
+ };
23700
+ var getApiV1CreditsPacks = (options) => {
23701
+ return (options?.client ?? client).get({
23702
+ url: "/api/v1/credits/packs",
23703
+ ...options
23704
+ });
23705
+ };
23706
+ var postApiV1CreditsPurchase = (options) => {
23707
+ return (options.client ?? client).post({
23708
+ url: "/api/v1/credits/purchase",
23709
+ ...options,
23710
+ headers: {
23711
+ "Content-Type": "application/json",
23712
+ ...options.headers
23713
+ }
23714
+ });
23715
+ };
23716
+ var getApiV1Models = (options) => {
23717
+ return (options?.client ?? client).get({
23718
+ url: "/api/v1/models",
23719
+ ...options
23720
+ });
23721
+ };
23722
+ var postApiV1PhoneCalls = (options) => {
23723
+ return (options.client ?? client).post({
23724
+ url: "/api/v1/phone-calls",
23725
+ ...options,
23726
+ headers: {
23727
+ "Content-Type": "application/json",
23728
+ ...options.headers
23729
+ }
23730
+ });
23731
+ };
23732
+ var getApiV1PhoneCallsByCallId = (options) => {
23733
+ return (options.client ?? client).get({
23734
+ url: "/api/v1/phone-calls/{call_id}",
23735
+ ...options
23736
+ });
23737
+ };
23738
+ var postApiV1SubscriptionsCancel = (options) => {
23739
+ return (options?.client ?? client).post({
23740
+ url: "/api/v1/subscriptions/cancel",
23741
+ ...options,
23742
+ headers: {
23743
+ "Content-Type": "application/json",
23744
+ ...options?.headers
23745
+ }
23746
+ });
23747
+ };
23748
+ var postApiV1SubscriptionsCreateCheckoutSession = (options) => {
23749
+ return (options.client ?? client).post({
23750
+ url: "/api/v1/subscriptions/create-checkout-session",
23751
+ ...options,
23752
+ headers: {
23753
+ "Content-Type": "application/json",
23754
+ ...options.headers
23755
+ }
23756
+ });
23757
+ };
23758
+ var postApiV1SubscriptionsCustomerPortal = (options) => {
23759
+ return (options.client ?? client).post({
23760
+ url: "/api/v1/subscriptions/customer-portal",
23761
+ ...options,
23762
+ headers: {
23763
+ "Content-Type": "application/json",
23764
+ ...options.headers
23765
+ }
23766
+ });
23767
+ };
23768
+ var postApiV1SubscriptionsRenew = (options) => {
23769
+ return (options?.client ?? client).post({
23770
+ url: "/api/v1/subscriptions/renew",
23771
+ ...options
23772
+ });
23773
+ };
23774
+ var getApiV1SubscriptionsStatus = (options) => {
23775
+ return (options?.client ?? client).get({
23776
+ url: "/api/v1/subscriptions/status",
23777
+ ...options
23778
+ });
23779
+ };
23780
+ var getApiV1WalletsBinding = (options) => {
23781
+ return (options?.client ?? client).get({
23782
+ url: "/api/v1/wallets/binding",
23783
+ ...options
23784
+ });
23785
+ };
23786
+ var postApiV1WalletsBinding = (options) => {
23787
+ return (options.client ?? client).post({
23788
+ url: "/api/v1/wallets/binding",
23789
+ ...options,
23790
+ headers: {
23791
+ "Content-Type": "application/json",
23792
+ ...options.headers
23793
+ }
23794
+ });
23795
+ };
23796
+ var postApiV1WalletsBindingNonce = (options) => {
23797
+ return (options?.client ?? client).post({
23798
+ url: "/api/v1/wallets/binding/nonce",
23799
+ ...options
23800
+ });
23801
+ };
23802
+ var deleteApiV1WalletsBindingByAddress = (options) => {
23803
+ return (options.client ?? client).delete({
23804
+ url: "/api/v1/wallets/binding/{address}",
23805
+ ...options
23806
+ });
23807
+ };
23808
+ var postAuthOauthByProviderExchange = (options) => {
23809
+ return (options.client ?? client).post({
23810
+ url: "/auth/oauth/{provider}/exchange",
23811
+ ...options,
23812
+ headers: {
23813
+ "Content-Type": "application/json",
23814
+ ...options.headers
23815
+ }
23816
+ });
23817
+ };
23818
+ var postAuthOauthByProviderRefresh = (options) => {
23819
+ return (options.client ?? client).post({
23820
+ url: "/auth/oauth/{provider}/refresh",
23821
+ ...options,
23822
+ headers: {
23823
+ "Content-Type": "application/json",
23824
+ ...options.headers
23825
+ }
23826
+ });
23827
+ };
23828
+ var postAuthOauthByProviderRevoke = (options) => {
23829
+ return (options.client ?? client).post({
23830
+ url: "/auth/oauth/{provider}/revoke",
23831
+ ...options,
23832
+ headers: {
23833
+ "Content-Type": "application/json",
23834
+ ...options.headers
23835
+ }
23836
+ });
23837
+ };
23852
23838
 
23853
23839
  // src/react/useCredits.ts
23854
- var import_react14 = require("react");
23855
- init_sdk_gen();
23856
23840
  init_clientConfig();
23857
23841
  function useCredits(options = {}) {
23858
23842
  const { getToken, baseUrl = BASE_URL, autoFetch = true, onError } = options;
@@ -24011,7 +23995,6 @@ function useCredits(options = {}) {
24011
23995
 
24012
23996
  // src/react/useModels.ts
24013
23997
  var import_react15 = require("react");
24014
- init_sdk_gen();
24015
23998
  init_clientConfig();
24016
23999
  function useModels(options = {}) {
24017
24000
  const { getToken, baseUrl = BASE_URL, provider, autoFetch = true } = options;
@@ -24117,7 +24100,6 @@ function useModels(options = {}) {
24117
24100
 
24118
24101
  // src/react/usePhoneCalls.ts
24119
24102
  var import_react16 = require("react");
24120
- init_sdk_gen();
24121
24103
  init_clientConfig();
24122
24104
  var DEFAULT_POLL_INTERVAL_MS = 5e3;
24123
24105
  var DEFAULT_POLL_MAX_ATTEMPTS = 60;
@@ -24417,7 +24399,6 @@ function usePhoneCalls(options = {}) {
24417
24399
 
24418
24400
  // src/react/useSubscription.ts
24419
24401
  var import_react17 = require("react");
24420
- init_sdk_gen();
24421
24402
  init_clientConfig();
24422
24403
  function useSubscription(options = {}) {
24423
24404
  const { getToken, baseUrl = BASE_URL, autoFetch = true, onError } = options;
@@ -24623,7 +24604,6 @@ function useSubscription(options = {}) {
24623
24604
 
24624
24605
  // src/react/useWalletBinding.ts
24625
24606
  var import_react18 = require("react");
24626
- init_sdk_gen();
24627
24607
  init_clientConfig();
24628
24608
  function useWalletBinding(options = {}) {
24629
24609
  const { getToken, baseUrl = BASE_URL, autoFetch = true, onError } = options;
@@ -24807,7 +24787,6 @@ function useWalletBinding(options = {}) {
24807
24787
  var import_react19 = require("react");
24808
24788
 
24809
24789
  // src/lib/backup/dropbox/auth.ts
24810
- init_sdk_gen();
24811
24790
  init_logger();
24812
24791
 
24813
24792
  // src/lib/backup/oauth/storage.ts
@@ -25564,7 +25543,6 @@ function useDropboxBackup(options) {
25564
25543
  var import_react21 = require("react");
25565
25544
 
25566
25545
  // src/lib/backup/google/auth.ts
25567
- init_sdk_gen();
25568
25546
  init_logger();
25569
25547
  var PROVIDER2 = "google-drive";
25570
25548
  var CODE_STORAGE_KEY = "google_oauth_state";
@@ -27363,7 +27341,6 @@ function useBackup(options) {
27363
27341
  }
27364
27342
 
27365
27343
  // src/lib/auth/google-calendar.ts
27366
- init_sdk_gen();
27367
27344
  init_useEncryption();
27368
27345
  init_logger();
27369
27346
  var PROVIDER3 = "google-drive";
@@ -27689,7 +27666,6 @@ async function migrateCalendarToken(walletAddress) {
27689
27666
  }
27690
27667
 
27691
27668
  // src/lib/auth/google-drive.ts
27692
- init_sdk_gen();
27693
27669
  init_useEncryption();
27694
27670
  init_logger();
27695
27671
  var PROVIDER4 = "google-drive";
@@ -28566,7 +28542,6 @@ function getNotionMCPUrl() {
28566
28542
  }
28567
28543
 
28568
28544
  // src/lib/auth/github.ts
28569
- init_sdk_gen();
28570
28545
  init_useEncryption();
28571
28546
  init_logger();
28572
28547
  var PROVIDER5 = "github";