@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.
- package/dist/expo/index.cjs +263 -0
- package/dist/expo/index.d.mts +199 -0
- package/dist/expo/index.d.ts +199 -0
- package/dist/expo/index.mjs +236 -0
- package/dist/polyfills/index.cjs +61 -0
- package/dist/polyfills/index.d.mts +9 -0
- package/dist/polyfills/index.d.ts +9 -0
- package/dist/polyfills/index.mjs +34 -0
- package/dist/react/chunk-BG7SZT33.mjs +182 -0
- package/dist/react/chunk-LVWIZZZP.mjs +6 -0
- package/dist/react/chunk-Q6FVPTTV.mjs +28 -0
- package/dist/react/constants-WUGUGYE3.mjs +7 -0
- package/dist/react/generation-NG4QVPCR.mjs +52 -0
- package/dist/react/index.cjs +373 -226
- package/dist/react/index.mjs +93 -226
- package/dist/react/selector-XMR5KL3E.mjs +14 -0
- package/package.json +32 -2
package/dist/react/index.cjs
CHANGED
|
@@ -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
|
|
48284
|
+
localModel,
|
|
48165
48285
|
tools,
|
|
48166
|
-
toolSelectorModel
|
|
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
|
-
|
|
48188
|
-
|
|
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
|
-
|
|
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(
|
|
48218
|
-
|
|
48219
|
-
|
|
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,
|