@reverbia/sdk 1.0.0-next.20251202092727 → 1.0.0-next.20251202130234

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -834,12 +834,32 @@ var postApiV1Embeddings = (options) => {
834
834
  }
835
835
  });
836
836
  };
837
+ var postApiV1ImagesGenerations = (options) => {
838
+ return (options.client ?? client).post({
839
+ url: "/api/v1/images/generations",
840
+ ...options,
841
+ headers: {
842
+ "Content-Type": "application/json",
843
+ ...options.headers
844
+ }
845
+ });
846
+ };
837
847
  var getApiV1Models = (options) => {
838
848
  return (options?.client ?? client).get({
839
849
  url: "/api/v1/models",
840
850
  ...options
841
851
  });
842
852
  };
853
+ var postApiV1Search = (options) => {
854
+ return (options.client ?? client).post({
855
+ url: "/api/v1/search",
856
+ ...options,
857
+ headers: {
858
+ "Content-Type": "application/json",
859
+ ...options.headers
860
+ }
861
+ });
862
+ };
843
863
  var getHealth = (options) => {
844
864
  return (options?.client ?? client).get({
845
865
  url: "/health",
@@ -850,5 +870,7 @@ export {
850
870
  getApiV1Models,
851
871
  getHealth,
852
872
  postApiV1ChatCompletions,
853
- postApiV1Embeddings
873
+ postApiV1Embeddings,
874
+ postApiV1ImagesGenerations,
875
+ postApiV1Search
854
876
  };
@@ -46669,12 +46669,15 @@ ${fake_token_around_image}${global_img_token}` + image_token.repeat(image_seq_le
46669
46669
  // src/react/index.ts
46670
46670
  var index_exports = {};
46671
46671
  __export(index_exports, {
46672
+ DEFAULT_TOOL_SELECTOR_MODEL: () => DEFAULT_TOOL_SELECTOR_MODEL,
46672
46673
  createMemoryContextSystemMessage: () => createMemoryContextSystemMessage,
46673
46674
  decryptData: () => decryptData,
46674
46675
  decryptDataBytes: () => decryptDataBytes,
46675
46676
  encryptData: () => encryptData,
46677
+ executeTool: () => executeTool,
46676
46678
  extractConversationContext: () => extractConversationContext,
46677
46679
  formatMemoriesForChat: () => formatMemoriesForChat,
46680
+ selectTool: () => selectTool,
46678
46681
  useChat: () => useChat,
46679
46682
  useEncryption: () => useEncryption,
46680
46683
  useMemory: () => useMemory,
@@ -47503,9 +47506,32 @@ var client = createClient(createClientConfig(createConfig()));
47503
47506
  // src/lib/chat/constants.ts
47504
47507
  var DEFAULT_LOCAL_CHAT_MODEL = "onnx-community/Qwen2.5-0.5B-Instruct";
47505
47508
 
47506
- // src/lib/chat/generation.ts
47507
- var chatPipeline = null;
47509
+ // src/lib/chat/pipeline.ts
47510
+ var sharedPipeline = null;
47508
47511
  var currentModel = null;
47512
+ var currentDevice = null;
47513
+ async function getTextGenerationPipeline(options) {
47514
+ const { model, device = "wasm", dtype = "q4" } = options;
47515
+ if (sharedPipeline && currentModel === model && currentDevice === device) {
47516
+ return sharedPipeline;
47517
+ }
47518
+ const { pipeline, env: env3 } = await Promise.resolve().then(() => (init_transformers_node(), transformers_node_exports));
47519
+ env3.allowLocalModels = false;
47520
+ if (env3.backends?.onnx) {
47521
+ env3.backends.onnx.logLevel = "fatal";
47522
+ }
47523
+ console.log(`[Pipeline] Loading model: ${model} on ${device}...`);
47524
+ sharedPipeline = await pipeline("text-generation", model, {
47525
+ dtype,
47526
+ device
47527
+ });
47528
+ currentModel = model;
47529
+ currentDevice = device;
47530
+ console.log(`[Pipeline] Model loaded: ${model}`);
47531
+ return sharedPipeline;
47532
+ }
47533
+
47534
+ // src/lib/chat/generation.ts
47509
47535
  async function generateLocalChatCompletion(messages, options = {}) {
47510
47536
  const {
47511
47537
  model = DEFAULT_LOCAL_CHAT_MODEL,
@@ -47515,13 +47541,12 @@ async function generateLocalChatCompletion(messages, options = {}) {
47515
47541
  onToken,
47516
47542
  signal
47517
47543
  } = options;
47518
- const { pipeline, TextStreamer } = await Promise.resolve().then(() => (init_transformers_node(), transformers_node_exports));
47519
- if (!chatPipeline || currentModel !== model) {
47520
- chatPipeline = await pipeline("text-generation", model, {
47521
- dtype: "fp16"
47522
- });
47523
- currentModel = model;
47524
- }
47544
+ const { TextStreamer } = await Promise.resolve().then(() => (init_transformers_node(), transformers_node_exports));
47545
+ const chatPipeline = await getTextGenerationPipeline({
47546
+ model,
47547
+ device: "wasm",
47548
+ dtype: "q4"
47549
+ });
47525
47550
  class CallbackStreamer extends TextStreamer {
47526
47551
  constructor(tokenizer, cb) {
47527
47552
  super(tokenizer, {
@@ -47548,6 +47573,148 @@ async function generateLocalChatCompletion(messages, options = {}) {
47548
47573
  return output;
47549
47574
  }
47550
47575
 
47576
+ // src/lib/tools/selector.ts
47577
+ var DEFAULT_TOOL_SELECTOR_MODEL = "Xenova/LaMini-GPT-124M";
47578
+ function buildToolSelectionPrompt(userMessage, tools) {
47579
+ const toolList = tools.map((t) => `${t.name} (${t.description})`).join("\n");
47580
+ return `Pick the best tool for the task. Reply with ONLY the tool name.
47581
+
47582
+ Available tools:
47583
+ ${toolList}
47584
+ none (no tool needed)
47585
+
47586
+ Task: "${userMessage}"
47587
+
47588
+ Best tool:`;
47589
+ }
47590
+ function extractParams(userMessage, tool) {
47591
+ const params = {};
47592
+ if (!tool.parameters) return params;
47593
+ for (const param of tool.parameters) {
47594
+ if (param.name === "expression" || param.name === "query") {
47595
+ params[param.name] = userMessage;
47596
+ } else if (param.name === "location" || param.name === "city") {
47597
+ const words = userMessage.split(/\s+/);
47598
+ const capitalizedWords = words.filter(
47599
+ (w) => w.length > 1 && w[0] === w[0].toUpperCase()
47600
+ );
47601
+ params[param.name] = capitalizedWords.length > 0 ? capitalizedWords.join(" ") : userMessage;
47602
+ } else if (param.name === "text" || param.name === "input") {
47603
+ params[param.name] = userMessage;
47604
+ } else {
47605
+ params[param.name] = userMessage;
47606
+ }
47607
+ }
47608
+ return params;
47609
+ }
47610
+ function parseToolSelectionResponse(response, tools, userMessage) {
47611
+ console.log("[Tool Selector] Raw response:", response);
47612
+ const cleaned = response.toLowerCase().trim().split(/[\s\n,.]+/)[0].replace(/[^a-z0-9_-]/g, "");
47613
+ console.log("[Tool Selector] Parsed tool name:", cleaned);
47614
+ if (cleaned === "none" || cleaned === "null" || cleaned === "") {
47615
+ console.log("[Tool Selector] No tool selected");
47616
+ return { toolSelected: false };
47617
+ }
47618
+ const selectedTool = tools.find((t) => t.name.toLowerCase() === cleaned);
47619
+ if (!selectedTool) {
47620
+ const fuzzyTool = tools.find(
47621
+ (t) => t.name.toLowerCase().includes(cleaned) || cleaned.includes(t.name.toLowerCase())
47622
+ );
47623
+ if (fuzzyTool) {
47624
+ console.log(`[Tool Selector] Fuzzy matched tool: ${fuzzyTool.name}`);
47625
+ const params2 = extractParams(userMessage, fuzzyTool);
47626
+ return {
47627
+ toolSelected: true,
47628
+ toolName: fuzzyTool.name,
47629
+ parameters: params2,
47630
+ confidence: 0.6
47631
+ };
47632
+ }
47633
+ console.warn(`[Tool Selector] Unknown tool: ${cleaned}`);
47634
+ return { toolSelected: false };
47635
+ }
47636
+ const params = extractParams(userMessage, selectedTool);
47637
+ console.log(`[Tool Selector] Selected tool: ${selectedTool.name}`, params);
47638
+ return {
47639
+ toolSelected: true,
47640
+ toolName: selectedTool.name,
47641
+ parameters: params,
47642
+ confidence: 0.9
47643
+ };
47644
+ }
47645
+ async function selectTool(userMessage, tools, options = {}) {
47646
+ const {
47647
+ model = DEFAULT_TOOL_SELECTOR_MODEL,
47648
+ signal,
47649
+ device = "wasm"
47650
+ } = options;
47651
+ if (!tools.length) {
47652
+ return { toolSelected: false };
47653
+ }
47654
+ console.log(
47655
+ `[Tool Selector] analyzing message: "${userMessage}" with model ${model}`
47656
+ );
47657
+ try {
47658
+ const selectorPipeline = await getTextGenerationPipeline({
47659
+ model,
47660
+ device,
47661
+ dtype: "q4"
47662
+ // Aggressive quantization for speed
47663
+ });
47664
+ const prompt = buildToolSelectionPrompt(userMessage, tools);
47665
+ const output = await selectorPipeline(prompt, {
47666
+ max_new_tokens: 4,
47667
+ // Just need the tool name
47668
+ temperature: 0,
47669
+ // Deterministic
47670
+ do_sample: false,
47671
+ return_full_text: false
47672
+ });
47673
+ if (signal?.aborted) {
47674
+ return { toolSelected: false };
47675
+ }
47676
+ const generatedText = output?.[0]?.generated_text || output?.generated_text || "";
47677
+ return parseToolSelectionResponse(generatedText, tools, userMessage);
47678
+ } catch (error) {
47679
+ console.error("[Tool Selector] Error:", error);
47680
+ return { toolSelected: false };
47681
+ }
47682
+ }
47683
+ var preloadPromise = null;
47684
+ async function preloadToolSelectorModel(options = {}) {
47685
+ if (preloadPromise) {
47686
+ return preloadPromise;
47687
+ }
47688
+ const { model = DEFAULT_TOOL_SELECTOR_MODEL, device = "wasm" } = options;
47689
+ console.log(`[Tool Selector] Preloading model: ${model}`);
47690
+ preloadPromise = getTextGenerationPipeline({
47691
+ model,
47692
+ device,
47693
+ dtype: "q4"
47694
+ }).then(() => {
47695
+ console.log(`[Tool Selector] Model preloaded: ${model}`);
47696
+ }).catch((error) => {
47697
+ console.warn("[Tool Selector] Failed to preload model:", error);
47698
+ preloadPromise = null;
47699
+ });
47700
+ return preloadPromise;
47701
+ }
47702
+ async function executeTool(tool, params) {
47703
+ try {
47704
+ console.log(
47705
+ `[Tool Selector] Executing tool ${tool.name} with params:`,
47706
+ params
47707
+ );
47708
+ const result = await tool.execute(params);
47709
+ console.log(`[Tool Selector] Tool ${tool.name} execution result:`, result);
47710
+ return { success: true, result };
47711
+ } catch (error) {
47712
+ const errorMessage = error instanceof Error ? error.message : "Tool execution failed";
47713
+ console.error(`[Tool Selector] Tool ${tool.name} failed:`, errorMessage);
47714
+ return { success: false, error: errorMessage };
47715
+ }
47716
+ }
47717
+
47551
47718
  // src/react/useChat.ts
47552
47719
  function useChat(options) {
47553
47720
  const {
@@ -47557,9 +47724,13 @@ function useChat(options) {
47557
47724
  onFinish,
47558
47725
  onError,
47559
47726
  chatProvider = "api",
47560
- localModel = DEFAULT_LOCAL_CHAT_MODEL
47727
+ localModel = DEFAULT_LOCAL_CHAT_MODEL,
47728
+ tools,
47729
+ toolSelectorModel = DEFAULT_TOOL_SELECTOR_MODEL,
47730
+ onToolExecution
47561
47731
  } = options || {};
47562
47732
  const [isLoading, setIsLoading] = (0, import_react.useState)(false);
47733
+ const [isSelectingTool, setIsSelectingTool] = (0, import_react.useState)(false);
47563
47734
  const abortControllerRef = (0, import_react.useRef)(null);
47564
47735
  const stop = (0, import_react.useCallback)(() => {
47565
47736
  if (abortControllerRef.current) {
@@ -47575,11 +47746,17 @@ function useChat(options) {
47575
47746
  }
47576
47747
  };
47577
47748
  }, []);
47749
+ (0, import_react.useEffect)(() => {
47750
+ if (tools && tools.length > 0) {
47751
+ preloadToolSelectorModel({ model: toolSelectorModel });
47752
+ }
47753
+ }, [tools, toolSelectorModel]);
47578
47754
  const sendMessage = (0, import_react.useCallback)(
47579
47755
  async ({
47580
47756
  messages,
47581
47757
  model,
47582
- onData
47758
+ onData,
47759
+ runTools = true
47583
47760
  }) => {
47584
47761
  if (!messages?.length) {
47585
47762
  const errorMsg = "messages are required to call sendMessage.";
@@ -47592,13 +47769,84 @@ function useChat(options) {
47592
47769
  const abortController = new AbortController();
47593
47770
  abortControllerRef.current = abortController;
47594
47771
  setIsLoading(true);
47772
+ let toolExecutionResult;
47773
+ let messagesWithToolContext = messages;
47774
+ if (runTools && tools && tools.length > 0) {
47775
+ const lastUserMessage = [...messages].reverse().find((m) => m.role === "user");
47776
+ if (lastUserMessage?.content) {
47777
+ setIsSelectingTool(true);
47778
+ const contentString = lastUserMessage.content?.map((part) => part.text || "").join("") || "";
47779
+ try {
47780
+ const selectionResult = await selectTool(contentString, tools, {
47781
+ model: toolSelectorModel,
47782
+ signal: abortController.signal
47783
+ });
47784
+ if (selectionResult.toolSelected && selectionResult.toolName) {
47785
+ const selectedTool = tools.find(
47786
+ (t) => t.name === selectionResult.toolName
47787
+ );
47788
+ if (selectedTool) {
47789
+ const execResult = await executeTool(
47790
+ selectedTool,
47791
+ selectionResult.parameters || {}
47792
+ );
47793
+ toolExecutionResult = {
47794
+ toolName: selectionResult.toolName,
47795
+ success: execResult.success,
47796
+ result: execResult.result,
47797
+ error: execResult.error
47798
+ };
47799
+ if (onToolExecution) {
47800
+ onToolExecution(toolExecutionResult);
47801
+ }
47802
+ if (toolExecutionResult.success && toolExecutionResult.result !== void 0) {
47803
+ const toolResultContext = {
47804
+ role: "system",
47805
+ content: [
47806
+ {
47807
+ type: "text",
47808
+ text: `Tool "${toolExecutionResult.toolName}" was executed with the following result:
47809
+ ${JSON.stringify(
47810
+ toolExecutionResult.result,
47811
+ null,
47812
+ 2
47813
+ )}
47814
+
47815
+ Use this information to respond to the user's request.`
47816
+ }
47817
+ ]
47818
+ };
47819
+ messagesWithToolContext = [...messages, toolResultContext];
47820
+ } else if (toolExecutionResult.error) {
47821
+ const toolErrorContext = {
47822
+ role: "system",
47823
+ content: [
47824
+ {
47825
+ type: "text",
47826
+ text: `Tool "${toolExecutionResult.toolName}" was executed but encountered an error: ${toolExecutionResult.error}
47827
+
47828
+ Please inform the user about this issue and try to help them alternatively.`
47829
+ }
47830
+ ]
47831
+ };
47832
+ messagesWithToolContext = [...messages, toolErrorContext];
47833
+ }
47834
+ }
47835
+ }
47836
+ } catch (err) {
47837
+ console.warn("Tool selection error:", err);
47838
+ } finally {
47839
+ setIsSelectingTool(false);
47840
+ }
47841
+ }
47842
+ }
47595
47843
  try {
47596
47844
  if (chatProvider === "local") {
47597
47845
  let accumulatedContent = "";
47598
47846
  const usedModel = localModel;
47599
- const formattedMessages = messages.map((m) => ({
47847
+ const formattedMessages = messagesWithToolContext.map((m) => ({
47600
47848
  role: m.role || "user",
47601
- content: m.content || ""
47849
+ content: m.content?.map((p) => p.text || "").join("") || ""
47602
47850
  }));
47603
47851
  await generateLocalChatCompletion(formattedMessages, {
47604
47852
  model: usedModel,
@@ -47617,7 +47865,7 @@ function useChat(options) {
47617
47865
  index: 0,
47618
47866
  message: {
47619
47867
  role: "assistant",
47620
- content: accumulatedContent
47868
+ content: [{ type: "text", text: accumulatedContent }]
47621
47869
  },
47622
47870
  finish_reason: "stop"
47623
47871
  }
@@ -47633,30 +47881,46 @@ function useChat(options) {
47633
47881
  if (onFinish) {
47634
47882
  onFinish(completion);
47635
47883
  }
47636
- return { data: completion, error: null };
47884
+ return {
47885
+ data: completion,
47886
+ error: null,
47887
+ toolExecution: toolExecutionResult
47888
+ };
47637
47889
  } else {
47638
47890
  if (!model) {
47639
47891
  const errorMsg = "model is required to call sendMessage.";
47640
47892
  if (onError) onError(new Error(errorMsg));
47641
- return { data: null, error: errorMsg };
47893
+ return {
47894
+ data: null,
47895
+ error: errorMsg,
47896
+ toolExecution: toolExecutionResult
47897
+ };
47642
47898
  }
47643
47899
  if (!getToken) {
47644
47900
  const errorMsg = "Token getter function is required.";
47645
47901
  if (onError) onError(new Error(errorMsg));
47646
- return { data: null, error: errorMsg };
47902
+ return {
47903
+ data: null,
47904
+ error: errorMsg,
47905
+ toolExecution: toolExecutionResult
47906
+ };
47647
47907
  }
47648
47908
  const token = await getToken();
47649
47909
  if (!token) {
47650
47910
  const errorMsg = "No access token available.";
47651
47911
  setIsLoading(false);
47652
47912
  if (onError) onError(new Error(errorMsg));
47653
- return { data: null, error: errorMsg };
47913
+ return {
47914
+ data: null,
47915
+ error: errorMsg,
47916
+ toolExecution: toolExecutionResult
47917
+ };
47654
47918
  }
47655
47919
  const sseResult = await client.sse.post({
47656
47920
  baseUrl,
47657
47921
  url: "/api/v1/chat/completions",
47658
47922
  body: {
47659
- messages,
47923
+ messages: messagesWithToolContext,
47660
47924
  model,
47661
47925
  stream: true
47662
47926
  },
@@ -47715,7 +47979,7 @@ function useChat(options) {
47715
47979
  index: 0,
47716
47980
  message: {
47717
47981
  role: "assistant",
47718
- content: accumulatedContent
47982
+ content: [{ type: "text", text: accumulatedContent }]
47719
47983
  },
47720
47984
  finish_reason: finishReason
47721
47985
  }
@@ -47726,12 +47990,20 @@ function useChat(options) {
47726
47990
  if (onFinish) {
47727
47991
  onFinish(completion);
47728
47992
  }
47729
- return { data: completion, error: null };
47993
+ return {
47994
+ data: completion,
47995
+ error: null,
47996
+ toolExecution: toolExecutionResult
47997
+ };
47730
47998
  }
47731
47999
  } catch (err) {
47732
48000
  if (err instanceof Error && err.name === "AbortError") {
47733
48001
  setIsLoading(false);
47734
- return { data: null, error: "Request aborted" };
48002
+ return {
48003
+ data: null,
48004
+ error: "Request aborted",
48005
+ toolExecution: toolExecutionResult
48006
+ };
47735
48007
  }
47736
48008
  const errorMsg = err instanceof Error ? err.message : "Failed to send message.";
47737
48009
  const errorObj = err instanceof Error ? err : new Error(errorMsg);
@@ -47739,7 +48011,11 @@ function useChat(options) {
47739
48011
  if (onError) {
47740
48012
  onError(errorObj);
47741
48013
  }
47742
- return { data: null, error: errorMsg };
48014
+ return {
48015
+ data: null,
48016
+ error: errorMsg,
48017
+ toolExecution: toolExecutionResult
48018
+ };
47743
48019
  } finally {
47744
48020
  if (abortControllerRef.current === abortController) {
47745
48021
  abortControllerRef.current = null;
@@ -47753,11 +48029,15 @@ function useChat(options) {
47753
48029
  onFinish,
47754
48030
  onError,
47755
48031
  chatProvider,
47756
- localModel
48032
+ localModel,
48033
+ tools,
48034
+ toolSelectorModel,
48035
+ onToolExecution
47757
48036
  ]
47758
48037
  );
47759
48038
  return {
47760
48039
  isLoading,
48040
+ isSelectingTool,
47761
48041
  sendMessage,
47762
48042
  stop
47763
48043
  };
@@ -48320,9 +48600,12 @@ function useMemory(options = {}) {
48320
48600
  messages: [
48321
48601
  {
48322
48602
  role: "system",
48323
- content: FACT_EXTRACTION_PROMPT
48603
+ content: [{ type: "text", text: FACT_EXTRACTION_PROMPT }]
48324
48604
  },
48325
- ...messages
48605
+ ...messages.map((m) => ({
48606
+ role: m.role,
48607
+ content: [{ type: "text", text: m.content }]
48608
+ }))
48326
48609
  ],
48327
48610
  model: model || completionsModel
48328
48611
  },
@@ -48343,7 +48626,13 @@ function useMemory(options = {}) {
48343
48626
  );
48344
48627
  return null;
48345
48628
  }
48346
- const content = completion.data.choices?.[0]?.message?.content?.trim() || "";
48629
+ const messageContent = completion.data.choices?.[0]?.message?.content;
48630
+ let content = "";
48631
+ if (Array.isArray(messageContent)) {
48632
+ content = messageContent.map((p) => p.text || "").join("").trim();
48633
+ } else if (typeof messageContent === "string") {
48634
+ content = messageContent.trim();
48635
+ }
48347
48636
  if (!content) {
48348
48637
  console.error("No content in memory extraction response");
48349
48638
  return null;
@@ -48680,12 +48969,15 @@ var extractConversationContext = (messages, maxMessages = 3) => {
48680
48969
  };
48681
48970
  // Annotate the CommonJS export names for ESM import in node:
48682
48971
  0 && (module.exports = {
48972
+ DEFAULT_TOOL_SELECTOR_MODEL,
48683
48973
  createMemoryContextSystemMessage,
48684
48974
  decryptData,
48685
48975
  decryptDataBytes,
48686
48976
  encryptData,
48977
+ executeTool,
48687
48978
  extractConversationContext,
48688
48979
  formatMemoriesForChat,
48980
+ selectTool,
48689
48981
  useChat,
48690
48982
  useEncryption,
48691
48983
  useMemory,