@reverbia/sdk 1.0.0-next.20251205183506 → 1.0.0-next.20251208094446

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.
@@ -40,6 +40,19 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
40
40
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
41
41
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
42
42
 
43
+ // src/lib/chat/constants.ts
44
+ var constants_exports = {};
45
+ __export(constants_exports, {
46
+ DEFAULT_LOCAL_CHAT_MODEL: () => DEFAULT_LOCAL_CHAT_MODEL
47
+ });
48
+ var DEFAULT_LOCAL_CHAT_MODEL;
49
+ var init_constants = __esm({
50
+ "src/lib/chat/constants.ts"() {
51
+ "use strict";
52
+ DEFAULT_LOCAL_CHAT_MODEL = "onnx-community/Qwen2.5-0.5B-Instruct";
53
+ }
54
+ });
55
+
43
56
  // node_modules/.pnpm/onnxruntime-common@1.21.0/node_modules/onnxruntime-common/dist/esm/backend-impl.js
44
57
  var backends, backendsSortedByPriority, registerBackend, tryResolveAndInitializeBackend, resolveBackendAndExecutionProviders;
45
58
  var init_backend_impl = __esm({
@@ -47098,6 +47111,276 @@ ${fake_token_around_image}${global_img_token}` + image_token.repeat(image_seq_le
47098
47111
  }
47099
47112
  });
47100
47113
 
47114
+ // src/lib/chat/pipeline.ts
47115
+ async function getTextGenerationPipeline(options) {
47116
+ const { model, device = "wasm", dtype = "q4" } = options;
47117
+ if (sharedPipeline && currentModel === model && currentDevice === device) {
47118
+ return sharedPipeline;
47119
+ }
47120
+ const { pipeline, env: env3 } = await Promise.resolve().then(() => (init_transformers_node(), transformers_node_exports));
47121
+ env3.allowLocalModels = false;
47122
+ if (env3.backends?.onnx) {
47123
+ env3.backends.onnx.logLevel = "fatal";
47124
+ }
47125
+ console.log(`[Pipeline] Loading model: ${model} on ${device}...`);
47126
+ sharedPipeline = await pipeline("text-generation", model, {
47127
+ dtype,
47128
+ device
47129
+ });
47130
+ currentModel = model;
47131
+ currentDevice = device;
47132
+ console.log(`[Pipeline] Model loaded: ${model}`);
47133
+ return sharedPipeline;
47134
+ }
47135
+ var sharedPipeline, currentModel, currentDevice;
47136
+ var init_pipeline = __esm({
47137
+ "src/lib/chat/pipeline.ts"() {
47138
+ "use strict";
47139
+ sharedPipeline = null;
47140
+ currentModel = null;
47141
+ currentDevice = null;
47142
+ }
47143
+ });
47144
+
47145
+ // src/lib/chat/generation.ts
47146
+ var generation_exports = {};
47147
+ __export(generation_exports, {
47148
+ generateLocalChatCompletion: () => generateLocalChatCompletion
47149
+ });
47150
+ async function generateLocalChatCompletion(messages, options = {}) {
47151
+ const {
47152
+ model = DEFAULT_LOCAL_CHAT_MODEL,
47153
+ temperature = 0.7,
47154
+ max_tokens = 1024,
47155
+ top_p = 0.9,
47156
+ onToken,
47157
+ signal
47158
+ } = options;
47159
+ const { TextStreamer } = await Promise.resolve().then(() => (init_transformers_node(), transformers_node_exports));
47160
+ const chatPipeline = await getTextGenerationPipeline({
47161
+ model,
47162
+ device: "wasm",
47163
+ dtype: "q4"
47164
+ });
47165
+ class CallbackStreamer extends TextStreamer {
47166
+ constructor(tokenizer, cb) {
47167
+ super(tokenizer, {
47168
+ skip_prompt: true,
47169
+ skip_special_tokens: true
47170
+ });
47171
+ this.cb = cb;
47172
+ }
47173
+ on_finalized_text(text) {
47174
+ if (signal?.aborted) {
47175
+ throw new Error("AbortError");
47176
+ }
47177
+ this.cb(text);
47178
+ }
47179
+ }
47180
+ const streamer = onToken ? new CallbackStreamer(chatPipeline.tokenizer, onToken) : void 0;
47181
+ const output = await chatPipeline(messages, {
47182
+ max_new_tokens: max_tokens,
47183
+ temperature,
47184
+ top_p,
47185
+ streamer,
47186
+ return_full_text: false
47187
+ });
47188
+ return output;
47189
+ }
47190
+ var init_generation = __esm({
47191
+ "src/lib/chat/generation.ts"() {
47192
+ "use strict";
47193
+ init_constants();
47194
+ init_pipeline();
47195
+ }
47196
+ });
47197
+
47198
+ // src/lib/tools/selector.ts
47199
+ var selector_exports = {};
47200
+ __export(selector_exports, {
47201
+ DEFAULT_TOOL_SELECTOR_MODEL: () => DEFAULT_TOOL_SELECTOR_MODEL,
47202
+ executeTool: () => executeTool,
47203
+ preloadToolSelectorModel: () => preloadToolSelectorModel,
47204
+ selectTool: () => selectTool
47205
+ });
47206
+ function buildToolSelectionPrompt(userMessage, tools) {
47207
+ const toolList = tools.map((t) => `${t.name} (${t.description})`).join("\n");
47208
+ return `Pick the best tool for the task. Reply with ONLY the tool name.
47209
+
47210
+ Available tools:
47211
+ ${toolList}
47212
+ none (no tool needed)
47213
+
47214
+ Task: "${userMessage}"
47215
+
47216
+ Best tool:`;
47217
+ }
47218
+ function buildParamExtractionPrompt(userMessage, paramName, paramDescription) {
47219
+ const desc = paramDescription ? ` (${paramDescription})` : "";
47220
+ return `Extract the value for "${paramName}"${desc} from the user message. Reply with ONLY the extracted value, nothing else.
47221
+
47222
+ User message: "${userMessage}"
47223
+
47224
+ Value for ${paramName}:`;
47225
+ }
47226
+ async function extractParams(userMessage, tool, options) {
47227
+ const params = {};
47228
+ if (!tool.parameters || tool.parameters.length === 0) return params;
47229
+ const { model, device } = options;
47230
+ try {
47231
+ const pipeline = await getTextGenerationPipeline({
47232
+ model,
47233
+ device,
47234
+ dtype: "q4"
47235
+ });
47236
+ for (const param of tool.parameters) {
47237
+ const prompt = buildParamExtractionPrompt(
47238
+ userMessage,
47239
+ param.name,
47240
+ param.description
47241
+ );
47242
+ const output = await pipeline(prompt, {
47243
+ max_new_tokens: 32,
47244
+ // Allow reasonable length for parameter values
47245
+ temperature: 0,
47246
+ do_sample: false,
47247
+ return_full_text: false
47248
+ });
47249
+ const generatedText = output?.[0]?.generated_text || output?.generated_text || "";
47250
+ const extractedValue = generatedText.trim().split("\n")[0].trim();
47251
+ console.log(
47252
+ `[Tool Selector] Extracted param "${param.name}":`,
47253
+ extractedValue
47254
+ );
47255
+ params[param.name] = extractedValue || userMessage;
47256
+ }
47257
+ } catch (error) {
47258
+ console.error("[Tool Selector] Error extracting params:", error);
47259
+ for (const param of tool.parameters) {
47260
+ params[param.name] = userMessage;
47261
+ }
47262
+ }
47263
+ return params;
47264
+ }
47265
+ async function parseToolSelectionResponse(response, tools, userMessage, options) {
47266
+ console.log("[Tool Selector] Raw response:", response);
47267
+ const cleaned = response.toLowerCase().trim().split(/[\s\n,.]+/)[0].replace(/[^a-z0-9_-]/g, "");
47268
+ console.log("[Tool Selector] Parsed tool name:", cleaned);
47269
+ if (cleaned === "none" || cleaned === "null" || cleaned === "") {
47270
+ console.log("[Tool Selector] No tool selected");
47271
+ return { toolSelected: false };
47272
+ }
47273
+ const selectedTool = tools.find((t) => t.name.toLowerCase() === cleaned);
47274
+ if (!selectedTool) {
47275
+ const fuzzyTool = tools.find(
47276
+ (t) => t.name.toLowerCase().includes(cleaned) || cleaned.includes(t.name.toLowerCase())
47277
+ );
47278
+ if (fuzzyTool) {
47279
+ console.log(`[Tool Selector] Fuzzy matched tool: ${fuzzyTool.name}`);
47280
+ const params2 = await extractParams(userMessage, fuzzyTool, options);
47281
+ return {
47282
+ toolSelected: true,
47283
+ toolName: fuzzyTool.name,
47284
+ parameters: params2,
47285
+ confidence: 0.6
47286
+ };
47287
+ }
47288
+ console.warn(`[Tool Selector] Unknown tool: ${cleaned}`);
47289
+ return { toolSelected: false };
47290
+ }
47291
+ const params = await extractParams(userMessage, selectedTool, options);
47292
+ console.log(`[Tool Selector] Selected tool: ${selectedTool.name}`, params);
47293
+ return {
47294
+ toolSelected: true,
47295
+ toolName: selectedTool.name,
47296
+ parameters: params,
47297
+ confidence: 0.9
47298
+ };
47299
+ }
47300
+ async function selectTool(userMessage, tools, options = {}) {
47301
+ const {
47302
+ model = DEFAULT_TOOL_SELECTOR_MODEL,
47303
+ signal,
47304
+ device = "wasm"
47305
+ } = options;
47306
+ if (!tools.length) {
47307
+ return { toolSelected: false };
47308
+ }
47309
+ console.log(
47310
+ `[Tool Selector] analyzing message: "${userMessage}" with model ${model}`
47311
+ );
47312
+ try {
47313
+ const selectorPipeline = await getTextGenerationPipeline({
47314
+ model,
47315
+ device,
47316
+ dtype: "q4"
47317
+ // Aggressive quantization for speed
47318
+ });
47319
+ const prompt = buildToolSelectionPrompt(userMessage, tools);
47320
+ const output = await selectorPipeline(prompt, {
47321
+ max_new_tokens: 4,
47322
+ // Just need the tool name
47323
+ temperature: 0,
47324
+ // Deterministic
47325
+ do_sample: false,
47326
+ return_full_text: false
47327
+ });
47328
+ if (signal?.aborted) {
47329
+ return { toolSelected: false };
47330
+ }
47331
+ const generatedText = output?.[0]?.generated_text || output?.generated_text || "";
47332
+ return await parseToolSelectionResponse(generatedText, tools, userMessage, {
47333
+ model,
47334
+ device
47335
+ });
47336
+ } catch (error) {
47337
+ console.error("[Tool Selector] Error:", error);
47338
+ return { toolSelected: false };
47339
+ }
47340
+ }
47341
+ async function preloadToolSelectorModel(options = {}) {
47342
+ if (preloadPromise) {
47343
+ return preloadPromise;
47344
+ }
47345
+ const { model = DEFAULT_TOOL_SELECTOR_MODEL, device = "wasm" } = options;
47346
+ console.log(`[Tool Selector] Preloading model: ${model}`);
47347
+ preloadPromise = getTextGenerationPipeline({
47348
+ model,
47349
+ device,
47350
+ dtype: "q4"
47351
+ }).then(() => {
47352
+ console.log(`[Tool Selector] Model preloaded: ${model}`);
47353
+ }).catch((error) => {
47354
+ console.warn("[Tool Selector] Failed to preload model:", error);
47355
+ preloadPromise = null;
47356
+ });
47357
+ return preloadPromise;
47358
+ }
47359
+ async function executeTool(tool, params) {
47360
+ try {
47361
+ console.log(
47362
+ `[Tool Selector] Executing tool ${tool.name} with params:`,
47363
+ params
47364
+ );
47365
+ const result = await tool.execute(params);
47366
+ console.log(`[Tool Selector] Tool ${tool.name} execution result:`, result);
47367
+ return { success: true, result };
47368
+ } catch (error) {
47369
+ const errorMessage = error instanceof Error ? error.message : "Tool execution failed";
47370
+ console.error(`[Tool Selector] Tool ${tool.name} failed:`, errorMessage);
47371
+ return { success: false, error: errorMessage };
47372
+ }
47373
+ }
47374
+ var DEFAULT_TOOL_SELECTOR_MODEL, preloadPromise;
47375
+ var init_selector = __esm({
47376
+ "src/lib/tools/selector.ts"() {
47377
+ "use strict";
47378
+ init_pipeline();
47379
+ DEFAULT_TOOL_SELECTOR_MODEL = "Xenova/LaMini-GPT-124M";
47380
+ preloadPromise = null;
47381
+ }
47382
+ });
47383
+
47101
47384
  // src/react/index.ts
47102
47385
  var index_exports = {};
47103
47386
  __export(index_exports, {
@@ -47125,6 +47408,38 @@ module.exports = __toCommonJS(index_exports);
47125
47408
  // src/react/useChat.ts
47126
47409
  var import_react = require("react");
47127
47410
 
47411
+ // src/lib/polyfills/textDecoderStream.ts
47412
+ var needsPolyfill = typeof globalThis.TextDecoderStream === "undefined";
47413
+ if (needsPolyfill && typeof globalThis.TransformStream !== "undefined") {
47414
+ class TextDecoderStreamPolyfill {
47415
+ constructor(label = "utf-8", options) {
47416
+ this.decoder = new TextDecoder(label, options);
47417
+ const decoder = this.decoder;
47418
+ this.transform = new TransformStream({
47419
+ transform(chunk, controller) {
47420
+ const text = decoder.decode(chunk, { stream: true });
47421
+ if (text) {
47422
+ controller.enqueue(text);
47423
+ }
47424
+ },
47425
+ flush(controller) {
47426
+ const text = decoder.decode();
47427
+ if (text) {
47428
+ controller.enqueue(text);
47429
+ }
47430
+ }
47431
+ });
47432
+ }
47433
+ get readable() {
47434
+ return this.transform.readable;
47435
+ }
47436
+ get writable() {
47437
+ return this.transform.writable;
47438
+ }
47439
+ }
47440
+ globalThis.TextDecoderStream = TextDecoderStreamPolyfill;
47441
+ }
47442
+
47128
47443
  // src/client/core/bodySerializer.gen.ts
47129
47444
  var jsonBodySerializer = {
47130
47445
  bodySerializer: (body) => JSON.stringify(
@@ -47940,219 +48255,24 @@ var createClientConfig = (config) => ({
47940
48255
  // src/client/client.gen.ts
47941
48256
  var client = createClient(createClientConfig(createConfig()));
47942
48257
 
47943
- // src/lib/chat/constants.ts
47944
- var DEFAULT_LOCAL_CHAT_MODEL = "onnx-community/Qwen2.5-0.5B-Instruct";
47945
-
47946
- // src/lib/chat/pipeline.ts
47947
- var sharedPipeline = null;
47948
- var currentModel = null;
47949
- var currentDevice = null;
47950
- async function getTextGenerationPipeline(options) {
47951
- const { model, device = "wasm", dtype = "q4" } = options;
47952
- if (sharedPipeline && currentModel === model && currentDevice === device) {
47953
- return sharedPipeline;
47954
- }
47955
- const { pipeline, env: env3 } = await Promise.resolve().then(() => (init_transformers_node(), transformers_node_exports));
47956
- env3.allowLocalModels = false;
47957
- if (env3.backends?.onnx) {
47958
- env3.backends.onnx.logLevel = "fatal";
47959
- }
47960
- console.log(`[Pipeline] Loading model: ${model} on ${device}...`);
47961
- sharedPipeline = await pipeline("text-generation", model, {
47962
- dtype,
47963
- device
47964
- });
47965
- currentModel = model;
47966
- currentDevice = device;
47967
- console.log(`[Pipeline] Model loaded: ${model}`);
47968
- return sharedPipeline;
47969
- }
47970
-
47971
- // src/lib/chat/generation.ts
47972
- async function generateLocalChatCompletion(messages, options = {}) {
47973
- const {
47974
- model = DEFAULT_LOCAL_CHAT_MODEL,
47975
- temperature = 0.7,
47976
- max_tokens = 1024,
47977
- top_p = 0.9,
47978
- onToken,
47979
- signal
47980
- } = options;
47981
- const { TextStreamer } = await Promise.resolve().then(() => (init_transformers_node(), transformers_node_exports));
47982
- const chatPipeline = await getTextGenerationPipeline({
47983
- model,
47984
- device: "wasm",
47985
- dtype: "q4"
47986
- });
47987
- class CallbackStreamer extends TextStreamer {
47988
- constructor(tokenizer, cb) {
47989
- super(tokenizer, {
47990
- skip_prompt: true,
47991
- skip_special_tokens: true
47992
- });
47993
- this.cb = cb;
47994
- }
47995
- on_finalized_text(text) {
47996
- if (signal?.aborted) {
47997
- throw new Error("AbortError");
47998
- }
47999
- this.cb(text);
48000
- }
48001
- }
48002
- const streamer = onToken ? new CallbackStreamer(chatPipeline.tokenizer, onToken) : void 0;
48003
- const output = await chatPipeline(messages, {
48004
- max_new_tokens: max_tokens,
48005
- temperature,
48006
- top_p,
48007
- streamer,
48008
- return_full_text: false
48009
- });
48010
- return output;
48011
- }
48012
-
48013
- // src/lib/tools/selector.ts
48014
- var DEFAULT_TOOL_SELECTOR_MODEL = "Xenova/LaMini-GPT-124M";
48015
- function buildToolSelectionPrompt(userMessage, tools) {
48016
- const toolList = tools.map((t) => `${t.name} (${t.description})`).join("\n");
48017
- return `Pick the best tool for the task. Reply with ONLY the tool name.
48018
-
48019
- Available tools:
48020
- ${toolList}
48021
- none (no tool needed)
48022
-
48023
- Task: "${userMessage}"
48024
-
48025
- Best tool:`;
48026
- }
48027
- function extractParams(userMessage, tool) {
48028
- const params = {};
48029
- if (!tool.parameters) return params;
48030
- for (const param of tool.parameters) {
48031
- if (param.name === "expression" || param.name === "query") {
48032
- params[param.name] = userMessage;
48033
- } else if (param.name === "location" || param.name === "city") {
48034
- const words = userMessage.split(/\s+/);
48035
- const capitalizedWords = words.filter(
48036
- (w) => w.length > 1 && w[0] === w[0].toUpperCase()
48037
- );
48038
- params[param.name] = capitalizedWords.length > 0 ? capitalizedWords.join(" ") : userMessage;
48039
- } else if (param.name === "text" || param.name === "input") {
48040
- params[param.name] = userMessage;
48041
- } else {
48042
- params[param.name] = userMessage;
48043
- }
48044
- }
48045
- return params;
48046
- }
48047
- function parseToolSelectionResponse(response, tools, userMessage) {
48048
- console.log("[Tool Selector] Raw response:", response);
48049
- const cleaned = response.toLowerCase().trim().split(/[\s\n,.]+/)[0].replace(/[^a-z0-9_-]/g, "");
48050
- console.log("[Tool Selector] Parsed tool name:", cleaned);
48051
- if (cleaned === "none" || cleaned === "null" || cleaned === "") {
48052
- console.log("[Tool Selector] No tool selected");
48053
- return { toolSelected: false };
48054
- }
48055
- const selectedTool = tools.find((t) => t.name.toLowerCase() === cleaned);
48056
- if (!selectedTool) {
48057
- const fuzzyTool = tools.find(
48058
- (t) => t.name.toLowerCase().includes(cleaned) || cleaned.includes(t.name.toLowerCase())
48059
- );
48060
- if (fuzzyTool) {
48061
- console.log(`[Tool Selector] Fuzzy matched tool: ${fuzzyTool.name}`);
48062
- const params2 = extractParams(userMessage, fuzzyTool);
48063
- return {
48064
- toolSelected: true,
48065
- toolName: fuzzyTool.name,
48066
- parameters: params2,
48067
- confidence: 0.6
48068
- };
48069
- }
48070
- console.warn(`[Tool Selector] Unknown tool: ${cleaned}`);
48071
- return { toolSelected: false };
48072
- }
48073
- const params = extractParams(userMessage, selectedTool);
48074
- console.log(`[Tool Selector] Selected tool: ${selectedTool.name}`, params);
48075
- return {
48076
- toolSelected: true,
48077
- toolName: selectedTool.name,
48078
- parameters: params,
48079
- confidence: 0.9
48080
- };
48081
- }
48082
- async function selectTool(userMessage, tools, options = {}) {
48083
- const {
48084
- model = DEFAULT_TOOL_SELECTOR_MODEL,
48085
- signal,
48086
- device = "wasm"
48087
- } = options;
48088
- if (!tools.length) {
48089
- return { toolSelected: false };
48090
- }
48091
- console.log(
48092
- `[Tool Selector] analyzing message: "${userMessage}" with model ${model}`
48093
- );
48094
- try {
48095
- const selectorPipeline = await getTextGenerationPipeline({
48096
- model,
48097
- device,
48098
- dtype: "q4"
48099
- // Aggressive quantization for speed
48100
- });
48101
- const prompt = buildToolSelectionPrompt(userMessage, tools);
48102
- const output = await selectorPipeline(prompt, {
48103
- max_new_tokens: 4,
48104
- // Just need the tool name
48105
- temperature: 0,
48106
- // Deterministic
48107
- do_sample: false,
48108
- return_full_text: false
48109
- });
48110
- if (signal?.aborted) {
48111
- return { toolSelected: false };
48112
- }
48113
- const generatedText = output?.[0]?.generated_text || output?.generated_text || "";
48114
- return parseToolSelectionResponse(generatedText, tools, userMessage);
48115
- } catch (error) {
48116
- console.error("[Tool Selector] Error:", error);
48117
- return { toolSelected: false };
48118
- }
48119
- }
48120
- var preloadPromise = null;
48121
- async function preloadToolSelectorModel(options = {}) {
48122
- if (preloadPromise) {
48123
- return preloadPromise;
48124
- }
48125
- const { model = DEFAULT_TOOL_SELECTOR_MODEL, device = "wasm" } = options;
48126
- console.log(`[Tool Selector] Preloading model: ${model}`);
48127
- preloadPromise = getTextGenerationPipeline({
48128
- model,
48129
- device,
48130
- dtype: "q4"
48131
- }).then(() => {
48132
- console.log(`[Tool Selector] Model preloaded: ${model}`);
48133
- }).catch((error) => {
48134
- console.warn("[Tool Selector] Failed to preload model:", error);
48135
- preloadPromise = null;
48136
- });
48137
- return preloadPromise;
48138
- }
48139
- async function executeTool(tool, params) {
48140
- try {
48141
- console.log(
48142
- `[Tool Selector] Executing tool ${tool.name} with params:`,
48143
- params
48144
- );
48145
- const result = await tool.execute(params);
48146
- console.log(`[Tool Selector] Tool ${tool.name} execution result:`, result);
48147
- return { success: true, result };
48148
- } catch (error) {
48149
- const errorMessage = error instanceof Error ? error.message : "Tool execution failed";
48150
- console.error(`[Tool Selector] Tool ${tool.name} failed:`, errorMessage);
48151
- return { success: false, error: errorMessage };
48152
- }
48153
- }
48154
-
48155
48258
  // src/react/useChat.ts
48259
+ var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
48260
+ var webFeatures = null;
48261
+ var webFeaturesPromise = isReactNative ? Promise.resolve(null) : Promise.all([
48262
+ Promise.resolve().then(() => (init_generation(), generation_exports)),
48263
+ Promise.resolve().then(() => (init_constants(), constants_exports)),
48264
+ Promise.resolve().then(() => (init_selector(), selector_exports))
48265
+ ]).then(([generation, constants, selector]) => {
48266
+ webFeatures = {
48267
+ generateLocalChatCompletion: generation.generateLocalChatCompletion,
48268
+ DEFAULT_LOCAL_CHAT_MODEL: constants.DEFAULT_LOCAL_CHAT_MODEL,
48269
+ selectTool: selector.selectTool,
48270
+ executeTool: selector.executeTool,
48271
+ preloadToolSelectorModel: selector.preloadToolSelectorModel,
48272
+ DEFAULT_TOOL_SELECTOR_MODEL: selector.DEFAULT_TOOL_SELECTOR_MODEL
48273
+ };
48274
+ return webFeatures;
48275
+ });
48156
48276
  function useChat(options) {
48157
48277
  const {
48158
48278
  getToken,
@@ -48161,13 +48281,14 @@ function useChat(options) {
48161
48281
  onFinish,
48162
48282
  onError,
48163
48283
  chatProvider = "api",
48164
- localModel = DEFAULT_LOCAL_CHAT_MODEL,
48284
+ localModel,
48165
48285
  tools,
48166
- toolSelectorModel = DEFAULT_TOOL_SELECTOR_MODEL,
48286
+ toolSelectorModel,
48167
48287
  onToolExecution
48168
48288
  } = options || {};
48169
48289
  const [isLoading, setIsLoading] = (0, import_react.useState)(false);
48170
48290
  const [isSelectingTool, setIsSelectingTool] = (0, import_react.useState)(false);
48291
+ const [webFeaturesLoaded, setWebFeaturesLoaded] = (0, import_react.useState)(false);
48171
48292
  const abortControllerRef = (0, import_react.useRef)(null);
48172
48293
  const stop = (0, import_react.useCallback)(() => {
48173
48294
  if (abortControllerRef.current) {
@@ -48184,10 +48305,17 @@ function useChat(options) {
48184
48305
  };
48185
48306
  }, []);
48186
48307
  (0, import_react.useEffect)(() => {
48187
- if (tools && tools.length > 0) {
48188
- preloadToolSelectorModel({ model: toolSelectorModel });
48308
+ webFeaturesPromise?.then((loaded) => {
48309
+ if (loaded) setWebFeaturesLoaded(true);
48310
+ });
48311
+ }, []);
48312
+ (0, import_react.useEffect)(() => {
48313
+ if (!isReactNative && webFeaturesLoaded && webFeatures && tools && tools.length > 0) {
48314
+ webFeatures.preloadToolSelectorModel({
48315
+ model: toolSelectorModel || webFeatures.DEFAULT_TOOL_SELECTOR_MODEL
48316
+ });
48189
48317
  }
48190
- }, [tools, toolSelectorModel]);
48318
+ }, [tools, toolSelectorModel, webFeaturesLoaded]);
48191
48319
  const sendMessage = (0, import_react.useCallback)(
48192
48320
  async ({
48193
48321
  messages,
@@ -48208,22 +48336,27 @@ function useChat(options) {
48208
48336
  setIsLoading(true);
48209
48337
  let toolExecutionResult;
48210
48338
  let messagesWithToolContext = messages;
48211
- if (runTools && tools && tools.length > 0) {
48339
+ const canRunTools = !isReactNative && webFeaturesLoaded && webFeatures !== null && runTools && tools && tools.length > 0;
48340
+ if (canRunTools && webFeatures) {
48212
48341
  const lastUserMessage = [...messages].reverse().find((m) => m.role === "user");
48213
48342
  if (lastUserMessage?.content) {
48214
48343
  setIsSelectingTool(true);
48215
48344
  const contentString = lastUserMessage.content?.map((part) => part.text || "").join("") || "";
48216
48345
  try {
48217
- const selectionResult = await selectTool(contentString, tools, {
48218
- model: toolSelectorModel,
48219
- signal: abortController.signal
48220
- });
48346
+ const selectionResult = await webFeatures.selectTool(
48347
+ contentString,
48348
+ tools,
48349
+ {
48350
+ model: toolSelectorModel || webFeatures.DEFAULT_TOOL_SELECTOR_MODEL,
48351
+ signal: abortController.signal
48352
+ }
48353
+ );
48221
48354
  if (selectionResult.toolSelected && selectionResult.toolName) {
48222
48355
  const selectedTool = tools.find(
48223
48356
  (t) => t.name === selectionResult.toolName
48224
48357
  );
48225
48358
  if (selectedTool) {
48226
- const execResult = await executeTool(
48359
+ const execResult = await webFeatures.executeTool(
48227
48360
  selectedTool,
48228
48361
  selectionResult.parameters || {}
48229
48362
  );
@@ -48279,13 +48412,23 @@ Please inform the user about this issue and try to help them alternatively.`
48279
48412
  }
48280
48413
  try {
48281
48414
  if (chatProvider === "local") {
48415
+ if (isReactNative || !webFeaturesLoaded || !webFeatures) {
48416
+ const errorMsg = 'Local chat provider is not available in React Native. Use chatProvider: "api" instead.';
48417
+ setIsLoading(false);
48418
+ if (onError) onError(new Error(errorMsg));
48419
+ return {
48420
+ data: null,
48421
+ error: errorMsg,
48422
+ toolExecution: toolExecutionResult
48423
+ };
48424
+ }
48282
48425
  let accumulatedContent = "";
48283
- const usedModel = localModel;
48426
+ const usedModel = localModel || webFeatures.DEFAULT_LOCAL_CHAT_MODEL;
48284
48427
  const formattedMessages = messagesWithToolContext.map((m) => ({
48285
48428
  role: m.role || "user",
48286
48429
  content: m.content?.map((p) => p.text || "").join("") || ""
48287
48430
  }));
48288
- await generateLocalChatCompletion(formattedMessages, {
48431
+ await webFeatures.generateLocalChatCompletion(formattedMessages, {
48289
48432
  model: usedModel,
48290
48433
  signal: abortController.signal,
48291
48434
  onToken: (token) => {
@@ -48469,7 +48612,8 @@ Please inform the user about this issue and try to help them alternatively.`
48469
48612
  localModel,
48470
48613
  tools,
48471
48614
  toolSelectorModel,
48472
- onToolExecution
48615
+ onToolExecution,
48616
+ webFeaturesLoaded
48473
48617
  ]
48474
48618
  );
48475
48619
  return {
@@ -49671,6 +49815,9 @@ var extractConversationContext = (messages, maxMessages = 3) => {
49671
49815
  const userMessages = messages.filter((msg) => msg.role === "user").slice(-maxMessages).map((msg) => msg.content).join(" ");
49672
49816
  return userMessages.trim();
49673
49817
  };
49818
+
49819
+ // src/react/index.ts
49820
+ init_selector();
49674
49821
  // Annotate the CommonJS export names for ESM import in node:
49675
49822
  0 && (module.exports = {
49676
49823
  DEFAULT_TOOL_SELECTOR_MODEL,