@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.
@@ -1,8 +1,46 @@
1
+ import {
2
+ DEFAULT_TOOL_SELECTOR_MODEL,
3
+ executeTool,
4
+ selectTool
5
+ } from "./chunk-BG7SZT33.mjs";
6
+ import "./chunk-Q6FVPTTV.mjs";
1
7
  import "./chunk-FBCDBTKJ.mjs";
2
8
 
3
9
  // src/react/useChat.ts
4
10
  import { useCallback, useEffect, useRef, useState } from "react";
5
11
 
12
+ // src/lib/polyfills/textDecoderStream.ts
13
+ var needsPolyfill = typeof globalThis.TextDecoderStream === "undefined";
14
+ if (needsPolyfill && typeof globalThis.TransformStream !== "undefined") {
15
+ class TextDecoderStreamPolyfill {
16
+ constructor(label = "utf-8", options) {
17
+ this.decoder = new TextDecoder(label, options);
18
+ const decoder = this.decoder;
19
+ this.transform = new TransformStream({
20
+ transform(chunk, controller) {
21
+ const text = decoder.decode(chunk, { stream: true });
22
+ if (text) {
23
+ controller.enqueue(text);
24
+ }
25
+ },
26
+ flush(controller) {
27
+ const text = decoder.decode();
28
+ if (text) {
29
+ controller.enqueue(text);
30
+ }
31
+ }
32
+ });
33
+ }
34
+ get readable() {
35
+ return this.transform.readable;
36
+ }
37
+ get writable() {
38
+ return this.transform.writable;
39
+ }
40
+ }
41
+ globalThis.TextDecoderStream = TextDecoderStreamPolyfill;
42
+ }
43
+
6
44
  // src/client/core/bodySerializer.gen.ts
7
45
  var jsonBodySerializer = {
8
46
  bodySerializer: (body) => JSON.stringify(
@@ -818,219 +856,24 @@ var createClientConfig = (config) => ({
818
856
  // src/client/client.gen.ts
819
857
  var client = createClient(createClientConfig(createConfig()));
820
858
 
821
- // src/lib/chat/constants.ts
822
- var DEFAULT_LOCAL_CHAT_MODEL = "onnx-community/Qwen2.5-0.5B-Instruct";
823
-
824
- // src/lib/chat/pipeline.ts
825
- var sharedPipeline = null;
826
- var currentModel = null;
827
- var currentDevice = null;
828
- async function getTextGenerationPipeline(options) {
829
- const { model, device = "wasm", dtype = "q4" } = options;
830
- if (sharedPipeline && currentModel === model && currentDevice === device) {
831
- return sharedPipeline;
832
- }
833
- const { pipeline, env } = await import("./transformers.node-LUTOZWVQ.mjs");
834
- env.allowLocalModels = false;
835
- if (env.backends?.onnx) {
836
- env.backends.onnx.logLevel = "fatal";
837
- }
838
- console.log(`[Pipeline] Loading model: ${model} on ${device}...`);
839
- sharedPipeline = await pipeline("text-generation", model, {
840
- dtype,
841
- device
842
- });
843
- currentModel = model;
844
- currentDevice = device;
845
- console.log(`[Pipeline] Model loaded: ${model}`);
846
- return sharedPipeline;
847
- }
848
-
849
- // src/lib/chat/generation.ts
850
- async function generateLocalChatCompletion(messages, options = {}) {
851
- const {
852
- model = DEFAULT_LOCAL_CHAT_MODEL,
853
- temperature = 0.7,
854
- max_tokens = 1024,
855
- top_p = 0.9,
856
- onToken,
857
- signal
858
- } = options;
859
- const { TextStreamer } = await import("./transformers.node-LUTOZWVQ.mjs");
860
- const chatPipeline = await getTextGenerationPipeline({
861
- model,
862
- device: "wasm",
863
- dtype: "q4"
864
- });
865
- class CallbackStreamer extends TextStreamer {
866
- constructor(tokenizer, cb) {
867
- super(tokenizer, {
868
- skip_prompt: true,
869
- skip_special_tokens: true
870
- });
871
- this.cb = cb;
872
- }
873
- on_finalized_text(text) {
874
- if (signal?.aborted) {
875
- throw new Error("AbortError");
876
- }
877
- this.cb(text);
878
- }
879
- }
880
- const streamer = onToken ? new CallbackStreamer(chatPipeline.tokenizer, onToken) : void 0;
881
- const output = await chatPipeline(messages, {
882
- max_new_tokens: max_tokens,
883
- temperature,
884
- top_p,
885
- streamer,
886
- return_full_text: false
887
- });
888
- return output;
889
- }
890
-
891
- // src/lib/tools/selector.ts
892
- var DEFAULT_TOOL_SELECTOR_MODEL = "Xenova/LaMini-GPT-124M";
893
- function buildToolSelectionPrompt(userMessage, tools) {
894
- const toolList = tools.map((t) => `${t.name} (${t.description})`).join("\n");
895
- return `Pick the best tool for the task. Reply with ONLY the tool name.
896
-
897
- Available tools:
898
- ${toolList}
899
- none (no tool needed)
900
-
901
- Task: "${userMessage}"
902
-
903
- Best tool:`;
904
- }
905
- function extractParams(userMessage, tool) {
906
- const params = {};
907
- if (!tool.parameters) return params;
908
- for (const param of tool.parameters) {
909
- if (param.name === "expression" || param.name === "query") {
910
- params[param.name] = userMessage;
911
- } else if (param.name === "location" || param.name === "city") {
912
- const words = userMessage.split(/\s+/);
913
- const capitalizedWords = words.filter(
914
- (w) => w.length > 1 && w[0] === w[0].toUpperCase()
915
- );
916
- params[param.name] = capitalizedWords.length > 0 ? capitalizedWords.join(" ") : userMessage;
917
- } else if (param.name === "text" || param.name === "input") {
918
- params[param.name] = userMessage;
919
- } else {
920
- params[param.name] = userMessage;
921
- }
922
- }
923
- return params;
924
- }
925
- function parseToolSelectionResponse(response, tools, userMessage) {
926
- console.log("[Tool Selector] Raw response:", response);
927
- const cleaned = response.toLowerCase().trim().split(/[\s\n,.]+/)[0].replace(/[^a-z0-9_-]/g, "");
928
- console.log("[Tool Selector] Parsed tool name:", cleaned);
929
- if (cleaned === "none" || cleaned === "null" || cleaned === "") {
930
- console.log("[Tool Selector] No tool selected");
931
- return { toolSelected: false };
932
- }
933
- const selectedTool = tools.find((t) => t.name.toLowerCase() === cleaned);
934
- if (!selectedTool) {
935
- const fuzzyTool = tools.find(
936
- (t) => t.name.toLowerCase().includes(cleaned) || cleaned.includes(t.name.toLowerCase())
937
- );
938
- if (fuzzyTool) {
939
- console.log(`[Tool Selector] Fuzzy matched tool: ${fuzzyTool.name}`);
940
- const params2 = extractParams(userMessage, fuzzyTool);
941
- return {
942
- toolSelected: true,
943
- toolName: fuzzyTool.name,
944
- parameters: params2,
945
- confidence: 0.6
946
- };
947
- }
948
- console.warn(`[Tool Selector] Unknown tool: ${cleaned}`);
949
- return { toolSelected: false };
950
- }
951
- const params = extractParams(userMessage, selectedTool);
952
- console.log(`[Tool Selector] Selected tool: ${selectedTool.name}`, params);
953
- return {
954
- toolSelected: true,
955
- toolName: selectedTool.name,
956
- parameters: params,
957
- confidence: 0.9
958
- };
959
- }
960
- async function selectTool(userMessage, tools, options = {}) {
961
- const {
962
- model = DEFAULT_TOOL_SELECTOR_MODEL,
963
- signal,
964
- device = "wasm"
965
- } = options;
966
- if (!tools.length) {
967
- return { toolSelected: false };
968
- }
969
- console.log(
970
- `[Tool Selector] analyzing message: "${userMessage}" with model ${model}`
971
- );
972
- try {
973
- const selectorPipeline = await getTextGenerationPipeline({
974
- model,
975
- device,
976
- dtype: "q4"
977
- // Aggressive quantization for speed
978
- });
979
- const prompt = buildToolSelectionPrompt(userMessage, tools);
980
- const output = await selectorPipeline(prompt, {
981
- max_new_tokens: 4,
982
- // Just need the tool name
983
- temperature: 0,
984
- // Deterministic
985
- do_sample: false,
986
- return_full_text: false
987
- });
988
- if (signal?.aborted) {
989
- return { toolSelected: false };
990
- }
991
- const generatedText = output?.[0]?.generated_text || output?.generated_text || "";
992
- return parseToolSelectionResponse(generatedText, tools, userMessage);
993
- } catch (error) {
994
- console.error("[Tool Selector] Error:", error);
995
- return { toolSelected: false };
996
- }
997
- }
998
- var preloadPromise = null;
999
- async function preloadToolSelectorModel(options = {}) {
1000
- if (preloadPromise) {
1001
- return preloadPromise;
1002
- }
1003
- const { model = DEFAULT_TOOL_SELECTOR_MODEL, device = "wasm" } = options;
1004
- console.log(`[Tool Selector] Preloading model: ${model}`);
1005
- preloadPromise = getTextGenerationPipeline({
1006
- model,
1007
- device,
1008
- dtype: "q4"
1009
- }).then(() => {
1010
- console.log(`[Tool Selector] Model preloaded: ${model}`);
1011
- }).catch((error) => {
1012
- console.warn("[Tool Selector] Failed to preload model:", error);
1013
- preloadPromise = null;
1014
- });
1015
- return preloadPromise;
1016
- }
1017
- async function executeTool(tool, params) {
1018
- try {
1019
- console.log(
1020
- `[Tool Selector] Executing tool ${tool.name} with params:`,
1021
- params
1022
- );
1023
- const result = await tool.execute(params);
1024
- console.log(`[Tool Selector] Tool ${tool.name} execution result:`, result);
1025
- return { success: true, result };
1026
- } catch (error) {
1027
- const errorMessage = error instanceof Error ? error.message : "Tool execution failed";
1028
- console.error(`[Tool Selector] Tool ${tool.name} failed:`, errorMessage);
1029
- return { success: false, error: errorMessage };
1030
- }
1031
- }
1032
-
1033
859
  // src/react/useChat.ts
860
+ var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
861
+ var webFeatures = null;
862
+ var webFeaturesPromise = isReactNative ? Promise.resolve(null) : Promise.all([
863
+ import("./generation-NG4QVPCR.mjs"),
864
+ import("./constants-WUGUGYE3.mjs"),
865
+ import("./selector-XMR5KL3E.mjs")
866
+ ]).then(([generation, constants, selector]) => {
867
+ webFeatures = {
868
+ generateLocalChatCompletion: generation.generateLocalChatCompletion,
869
+ DEFAULT_LOCAL_CHAT_MODEL: constants.DEFAULT_LOCAL_CHAT_MODEL,
870
+ selectTool: selector.selectTool,
871
+ executeTool: selector.executeTool,
872
+ preloadToolSelectorModel: selector.preloadToolSelectorModel,
873
+ DEFAULT_TOOL_SELECTOR_MODEL: selector.DEFAULT_TOOL_SELECTOR_MODEL
874
+ };
875
+ return webFeatures;
876
+ });
1034
877
  function useChat(options) {
1035
878
  const {
1036
879
  getToken,
@@ -1039,13 +882,14 @@ function useChat(options) {
1039
882
  onFinish,
1040
883
  onError,
1041
884
  chatProvider = "api",
1042
- localModel = DEFAULT_LOCAL_CHAT_MODEL,
885
+ localModel,
1043
886
  tools,
1044
- toolSelectorModel = DEFAULT_TOOL_SELECTOR_MODEL,
887
+ toolSelectorModel,
1045
888
  onToolExecution
1046
889
  } = options || {};
1047
890
  const [isLoading, setIsLoading] = useState(false);
1048
891
  const [isSelectingTool, setIsSelectingTool] = useState(false);
892
+ const [webFeaturesLoaded, setWebFeaturesLoaded] = useState(false);
1049
893
  const abortControllerRef = useRef(null);
1050
894
  const stop = useCallback(() => {
1051
895
  if (abortControllerRef.current) {
@@ -1062,10 +906,17 @@ function useChat(options) {
1062
906
  };
1063
907
  }, []);
1064
908
  useEffect(() => {
1065
- if (tools && tools.length > 0) {
1066
- preloadToolSelectorModel({ model: toolSelectorModel });
909
+ webFeaturesPromise?.then((loaded) => {
910
+ if (loaded) setWebFeaturesLoaded(true);
911
+ });
912
+ }, []);
913
+ useEffect(() => {
914
+ if (!isReactNative && webFeaturesLoaded && webFeatures && tools && tools.length > 0) {
915
+ webFeatures.preloadToolSelectorModel({
916
+ model: toolSelectorModel || webFeatures.DEFAULT_TOOL_SELECTOR_MODEL
917
+ });
1067
918
  }
1068
- }, [tools, toolSelectorModel]);
919
+ }, [tools, toolSelectorModel, webFeaturesLoaded]);
1069
920
  const sendMessage = useCallback(
1070
921
  async ({
1071
922
  messages,
@@ -1086,22 +937,27 @@ function useChat(options) {
1086
937
  setIsLoading(true);
1087
938
  let toolExecutionResult;
1088
939
  let messagesWithToolContext = messages;
1089
- if (runTools && tools && tools.length > 0) {
940
+ const canRunTools = !isReactNative && webFeaturesLoaded && webFeatures !== null && runTools && tools && tools.length > 0;
941
+ if (canRunTools && webFeatures) {
1090
942
  const lastUserMessage = [...messages].reverse().find((m) => m.role === "user");
1091
943
  if (lastUserMessage?.content) {
1092
944
  setIsSelectingTool(true);
1093
945
  const contentString = lastUserMessage.content?.map((part) => part.text || "").join("") || "";
1094
946
  try {
1095
- const selectionResult = await selectTool(contentString, tools, {
1096
- model: toolSelectorModel,
1097
- signal: abortController.signal
1098
- });
947
+ const selectionResult = await webFeatures.selectTool(
948
+ contentString,
949
+ tools,
950
+ {
951
+ model: toolSelectorModel || webFeatures.DEFAULT_TOOL_SELECTOR_MODEL,
952
+ signal: abortController.signal
953
+ }
954
+ );
1099
955
  if (selectionResult.toolSelected && selectionResult.toolName) {
1100
956
  const selectedTool = tools.find(
1101
957
  (t) => t.name === selectionResult.toolName
1102
958
  );
1103
959
  if (selectedTool) {
1104
- const execResult = await executeTool(
960
+ const execResult = await webFeatures.executeTool(
1105
961
  selectedTool,
1106
962
  selectionResult.parameters || {}
1107
963
  );
@@ -1157,13 +1013,23 @@ Please inform the user about this issue and try to help them alternatively.`
1157
1013
  }
1158
1014
  try {
1159
1015
  if (chatProvider === "local") {
1016
+ if (isReactNative || !webFeaturesLoaded || !webFeatures) {
1017
+ const errorMsg = 'Local chat provider is not available in React Native. Use chatProvider: "api" instead.';
1018
+ setIsLoading(false);
1019
+ if (onError) onError(new Error(errorMsg));
1020
+ return {
1021
+ data: null,
1022
+ error: errorMsg,
1023
+ toolExecution: toolExecutionResult
1024
+ };
1025
+ }
1160
1026
  let accumulatedContent = "";
1161
- const usedModel = localModel;
1027
+ const usedModel = localModel || webFeatures.DEFAULT_LOCAL_CHAT_MODEL;
1162
1028
  const formattedMessages = messagesWithToolContext.map((m) => ({
1163
1029
  role: m.role || "user",
1164
1030
  content: m.content?.map((p) => p.text || "").join("") || ""
1165
1031
  }));
1166
- await generateLocalChatCompletion(formattedMessages, {
1032
+ await webFeatures.generateLocalChatCompletion(formattedMessages, {
1167
1033
  model: usedModel,
1168
1034
  signal: abortController.signal,
1169
1035
  onToken: (token) => {
@@ -1347,7 +1213,8 @@ Please inform the user about this issue and try to help them alternatively.`
1347
1213
  localModel,
1348
1214
  tools,
1349
1215
  toolSelectorModel,
1350
- onToolExecution
1216
+ onToolExecution,
1217
+ webFeaturesLoaded
1351
1218
  ]
1352
1219
  );
1353
1220
  return {
@@ -0,0 +1,14 @@
1
+ import {
2
+ DEFAULT_TOOL_SELECTOR_MODEL,
3
+ executeTool,
4
+ preloadToolSelectorModel,
5
+ selectTool
6
+ } from "./chunk-BG7SZT33.mjs";
7
+ import "./chunk-Q6FVPTTV.mjs";
8
+ import "./chunk-FBCDBTKJ.mjs";
9
+ export {
10
+ DEFAULT_TOOL_SELECTOR_MODEL,
11
+ executeTool,
12
+ preloadToolSelectorModel,
13
+ selectTool
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reverbia/sdk",
3
- "version": "1.0.0-next.20251205183506",
3
+ "version": "1.0.0-next.20251208094446",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -15,10 +15,25 @@
15
15
  },
16
16
  "./react": {
17
17
  "types": "./dist/react/index.d.ts",
18
+ "react-native": "./dist/react/index.mjs",
18
19
  "import": "./dist/react/index.mjs",
19
20
  "require": "./dist/react/index.cjs",
20
21
  "default": "./dist/react/index.cjs"
21
22
  },
23
+ "./expo": {
24
+ "types": "./dist/expo/index.d.ts",
25
+ "react-native": "./dist/expo/index.mjs",
26
+ "import": "./dist/expo/index.mjs",
27
+ "require": "./dist/expo/index.cjs",
28
+ "default": "./dist/expo/index.cjs"
29
+ },
30
+ "./polyfills": {
31
+ "types": "./dist/polyfills/index.d.ts",
32
+ "react-native": "./dist/polyfills/index.mjs",
33
+ "import": "./dist/polyfills/index.mjs",
34
+ "require": "./dist/polyfills/index.cjs",
35
+ "default": "./dist/polyfills/index.cjs"
36
+ },
22
37
  "./vercel": {
23
38
  "types": "./dist/vercel/index.d.ts",
24
39
  "react-server": "./dist/vercel/index.mjs",
@@ -80,7 +95,22 @@
80
95
  "@privy-io/react-auth": "^3.7.0",
81
96
  "dexie": "^4.2.1",
82
97
  "react": "^18.0.0 || ^19.0.0",
83
- "react-dom": "^18.0.0 || ^19.0.0"
98
+ "react-dom": "^18.0.0 || ^19.0.0",
99
+ "react-native": ">=0.70.0"
100
+ },
101
+ "peerDependenciesMeta": {
102
+ "react-dom": {
103
+ "optional": true
104
+ },
105
+ "react-native": {
106
+ "optional": true
107
+ },
108
+ "@privy-io/react-auth": {
109
+ "optional": true
110
+ },
111
+ "dexie": {
112
+ "optional": true
113
+ }
84
114
  },
85
115
  "pnpm": {
86
116
  "overrides": {