@reverbia/sdk 1.0.0-next.20260109140427 → 1.0.0-next.20260109180912

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.
@@ -1267,6 +1267,36 @@ function finalizeThoughtProcess(thoughtProcess) {
1267
1267
  (phase, idx) => idx === thoughtProcess.length - 1 ? { ...phase, status: "completed" } : phase
1268
1268
  );
1269
1269
  }
1270
+ function extractUserMessageFromMessages(messages) {
1271
+ if (!messages || messages.length === 0) {
1272
+ return null;
1273
+ }
1274
+ const userMessages = messages.filter((m) => m.role === "user");
1275
+ const lastUserMessage = userMessages[userMessages.length - 1];
1276
+ if (!lastUserMessage || !lastUserMessage.content) {
1277
+ return null;
1278
+ }
1279
+ const textParts = [];
1280
+ const files = [];
1281
+ for (const part of lastUserMessage.content) {
1282
+ if (part.type === "text" && part.text) {
1283
+ textParts.push(part.text);
1284
+ } else if (part.type === "image_url" && part.image_url?.url) {
1285
+ files.push({
1286
+ id: `img_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
1287
+ name: "image",
1288
+ type: "image/unknown",
1289
+ size: 0,
1290
+ url: part.image_url.url
1291
+ });
1292
+ }
1293
+ }
1294
+ const content = textParts.join("\n");
1295
+ return {
1296
+ content,
1297
+ files: files.length > 0 ? files : void 0
1298
+ };
1299
+ }
1270
1300
 
1271
1301
  // src/lib/db/chat/operations.ts
1272
1302
  import { Q } from "@nozbe/watermelondb";
@@ -1643,9 +1673,8 @@ function useChatStorage(options) {
1643
1673
  const sendMessage = useCallback2(
1644
1674
  async (args) => {
1645
1675
  const {
1646
- content,
1676
+ messages,
1647
1677
  model,
1648
- messages: providedMessages,
1649
1678
  includeHistory = true,
1650
1679
  maxHistoryMessages = 50,
1651
1680
  files,
@@ -1666,6 +1695,15 @@ function useChatStorage(options) {
1666
1695
  reasoning,
1667
1696
  thinking
1668
1697
  } = args;
1698
+ const extracted = extractUserMessageFromMessages(messages);
1699
+ if (!extracted || !extracted.content) {
1700
+ return {
1701
+ data: null,
1702
+ error: "No user message found in messages array"
1703
+ };
1704
+ }
1705
+ const contentForStorage = extracted.content;
1706
+ const filesForStorage = files ?? extracted.files;
1669
1707
  let convId;
1670
1708
  try {
1671
1709
  convId = await ensureConversation();
@@ -1676,33 +1714,18 @@ function useChatStorage(options) {
1676
1714
  };
1677
1715
  }
1678
1716
  let messagesToSend = [];
1679
- if (includeHistory && !providedMessages) {
1717
+ if (includeHistory) {
1680
1718
  const storedMessages = await getMessages(convId);
1681
1719
  const validMessages = storedMessages.filter((msg) => !msg.error);
1682
1720
  const limitedMessages = validMessages.slice(-maxHistoryMessages);
1683
- messagesToSend = limitedMessages.map(storedToLlmapiMessage);
1684
- } else if (providedMessages) {
1685
- messagesToSend = providedMessages;
1686
- }
1687
- const userMessageContent = [
1688
- { type: "text", text: content }
1689
- ];
1690
- if (files?.length) {
1691
- for (const file of files) {
1692
- if (file.url) {
1693
- userMessageContent.push({
1694
- type: "image_url",
1695
- image_url: { url: file.url }
1696
- });
1697
- }
1698
- }
1721
+ messagesToSend = [
1722
+ ...limitedMessages.map(storedToLlmapiMessage),
1723
+ ...messages
1724
+ ];
1725
+ } else {
1726
+ messagesToSend = [...messages];
1699
1727
  }
1700
- const userMessage = {
1701
- role: "user",
1702
- content: userMessageContent
1703
- };
1704
- messagesToSend.push(userMessage);
1705
- const sanitizedFiles = files?.map((file) => ({
1728
+ const sanitizedFiles = filesForStorage?.map((file) => ({
1706
1729
  id: file.id,
1707
1730
  name: file.name,
1708
1731
  type: file.type,
@@ -1715,7 +1738,7 @@ function useChatStorage(options) {
1715
1738
  storedUserMessage = await createMessageOp(storageCtx, {
1716
1739
  conversationId: convId,
1717
1740
  role: "user",
1718
- content,
1741
+ content: contentForStorage,
1719
1742
  files: sanitizedFiles,
1720
1743
  model
1721
1744
  });
@@ -1569,10 +1569,7 @@ function useChat(options) {
1569
1569
  continue;
1570
1570
  }
1571
1571
  if (chunk && typeof chunk === "object") {
1572
- const { content: contentDelta, thinking: thinkingDelta } = strategy.processStreamChunk(
1573
- chunk,
1574
- accumulator
1575
- );
1572
+ const { content: contentDelta, thinking: thinkingDelta } = strategy.processStreamChunk(chunk, accumulator);
1576
1573
  if (contentDelta) {
1577
1574
  if (onData) onData(contentDelta);
1578
1575
  if (globalOnData) globalOnData(contentDelta);
@@ -1605,7 +1602,11 @@ function useChat(options) {
1605
1602
  }
1606
1603
  const response = strategy.buildFinalResponse(accumulator);
1607
1604
  if (accumulator.toolCalls.size > 0) {
1608
- console.log("[Tool Debug] Found", accumulator.toolCalls.size, "tool calls");
1605
+ console.log(
1606
+ "[Tool Debug] Found",
1607
+ accumulator.toolCalls.size,
1608
+ "tool calls"
1609
+ );
1609
1610
  const executorMap = createToolExecutorMap(tools);
1610
1611
  const toolCallsToExecute = [];
1611
1612
  for (const toolCall of accumulator.toolCalls.values()) {
@@ -1615,7 +1616,10 @@ function useChat(options) {
1615
1616
  console.log("[Tool Debug] Will auto-execute:", toolCall.name);
1616
1617
  toolCallsToExecute.push(toolCall);
1617
1618
  } else {
1618
- console.log("[Tool Debug] Emitting onToolCall event for:", toolCall.name);
1619
+ console.log(
1620
+ "[Tool Debug] Emitting onToolCall event for:",
1621
+ toolCall.name
1622
+ );
1619
1623
  if (onToolCall) {
1620
1624
  onToolCall({
1621
1625
  id: toolCall.id,
@@ -1629,7 +1633,11 @@ function useChat(options) {
1629
1633
  }
1630
1634
  }
1631
1635
  if (toolCallsToExecute.length > 0) {
1632
- console.log("[Tool Debug] Executing", toolCallsToExecute.length, "tools");
1636
+ console.log(
1637
+ "[Tool Debug] Executing",
1638
+ toolCallsToExecute.length,
1639
+ "tools"
1640
+ );
1633
1641
  if (onThinking || globalOnThinking) {
1634
1642
  const toolInfo = toolCallsToExecute.map((tc) => {
1635
1643
  try {
@@ -1659,7 +1667,12 @@ Executing tool: ${toolInfo}
1659
1667
  toolCall,
1660
1668
  executorConfig.executor
1661
1669
  );
1662
- console.log("[Tool Debug] Tool execution result for", toolCall.name, ":", { result, error });
1670
+ console.log(
1671
+ "[Tool Debug] Tool execution result for",
1672
+ toolCall.name,
1673
+ ":",
1674
+ { result, error }
1675
+ );
1663
1676
  return {
1664
1677
  id: toolCall.id,
1665
1678
  name: toolCall.name,
@@ -1668,7 +1681,10 @@ Executing tool: ${toolInfo}
1668
1681
  };
1669
1682
  })
1670
1683
  );
1671
- console.log("[Tool Debug] All tools executed, results:", executionResults.length);
1684
+ console.log(
1685
+ "[Tool Debug] All tools executed, results:",
1686
+ executionResults.length
1687
+ );
1672
1688
  if (onThinking || globalOnThinking) {
1673
1689
  const resultsText = executionResults.map((r) => {
1674
1690
  if (r.error) {
@@ -1704,8 +1720,14 @@ Executing tool: ${toolInfo}
1704
1720
  tool_call_id: execResult.id
1705
1721
  });
1706
1722
  }
1707
- const continuationMessages = [...messagesWithContext, ...toolResultMessages];
1708
- console.log("[Tool Debug] Continuation messages:", JSON.stringify(continuationMessages, null, 2));
1723
+ const continuationMessages = [
1724
+ ...messagesWithContext,
1725
+ ...toolResultMessages
1726
+ ];
1727
+ console.log(
1728
+ "[Tool Debug] Continuation messages:",
1729
+ JSON.stringify(continuationMessages, null, 2)
1730
+ );
1709
1731
  const continuationRequestBody = strategy.buildRequestBody({
1710
1732
  messages: continuationMessages,
1711
1733
  model,
@@ -1742,10 +1764,7 @@ Executing tool: ${toolInfo}
1742
1764
  continue;
1743
1765
  }
1744
1766
  if (chunk && typeof chunk === "object") {
1745
- const { content: contentDelta, thinking: thinkingDelta } = strategy.processStreamChunk(
1746
- chunk,
1747
- continuationAccumulator
1748
- );
1767
+ const { content: contentDelta, thinking: thinkingDelta } = strategy.processStreamChunk(chunk, continuationAccumulator);
1749
1768
  if (contentDelta) {
1750
1769
  if (onData) onData(contentDelta);
1751
1770
  if (globalOnData) globalOnData(contentDelta);
@@ -1756,11 +1775,19 @@ Executing tool: ${toolInfo}
1756
1775
  }
1757
1776
  }
1758
1777
  }
1759
- console.log("[Tool Debug] Continuation stream complete - accumulated content:", continuationAccumulator.content);
1760
- console.log("[Tool Debug] Continuation stream complete - accumulated thinking:", continuationAccumulator.thinking);
1778
+ console.log(
1779
+ "[Tool Debug] Continuation stream complete - accumulated content:",
1780
+ continuationAccumulator.content
1781
+ );
1782
+ console.log(
1783
+ "[Tool Debug] Continuation stream complete - accumulated thinking:",
1784
+ continuationAccumulator.thinking
1785
+ );
1761
1786
  } catch (streamErr) {
1762
1787
  if (isAbortError(streamErr) || abortController.signal.aborted) {
1763
- const partialResponse = strategy.buildFinalResponse(continuationAccumulator);
1788
+ const partialResponse = strategy.buildFinalResponse(
1789
+ continuationAccumulator
1790
+ );
1764
1791
  return {
1765
1792
  data: partialResponse,
1766
1793
  error: "Request aborted"
@@ -1769,7 +1796,9 @@ Executing tool: ${toolInfo}
1769
1796
  throw streamErr;
1770
1797
  }
1771
1798
  if (abortController.signal.aborted) {
1772
- const partialResponse = strategy.buildFinalResponse(continuationAccumulator);
1799
+ const partialResponse = strategy.buildFinalResponse(
1800
+ continuationAccumulator
1801
+ );
1773
1802
  return {
1774
1803
  data: partialResponse,
1775
1804
  error: "Request aborted"
@@ -1778,7 +1807,9 @@ Executing tool: ${toolInfo}
1778
1807
  if (sseError) {
1779
1808
  throw sseError;
1780
1809
  }
1781
- const finalResponse = strategy.buildFinalResponse(continuationAccumulator);
1810
+ const finalResponse = strategy.buildFinalResponse(
1811
+ continuationAccumulator
1812
+ );
1782
1813
  if (onFinish) {
1783
1814
  onFinish(finalResponse);
1784
1815
  }
@@ -1811,7 +1842,16 @@ Executing tool: ${toolInfo}
1811
1842
  }
1812
1843
  }
1813
1844
  },
1814
- [getToken, baseUrl, globalOnData, globalOnThinking, onFinish, onError, onToolCall, defaultApiType]
1845
+ [
1846
+ getToken,
1847
+ baseUrl,
1848
+ globalOnData,
1849
+ globalOnThinking,
1850
+ onFinish,
1851
+ onError,
1852
+ onToolCall,
1853
+ defaultApiType
1854
+ ]
1815
1855
  );
1816
1856
  return {
1817
1857
  isLoading,
@@ -2535,6 +2575,36 @@ function finalizeThoughtProcess(thoughtProcess) {
2535
2575
  (phase, idx) => idx === thoughtProcess.length - 1 ? { ...phase, status: "completed" } : phase
2536
2576
  );
2537
2577
  }
2578
+ function extractUserMessageFromMessages(messages) {
2579
+ if (!messages || messages.length === 0) {
2580
+ return null;
2581
+ }
2582
+ const userMessages = messages.filter((m) => m.role === "user");
2583
+ const lastUserMessage = userMessages[userMessages.length - 1];
2584
+ if (!lastUserMessage || !lastUserMessage.content) {
2585
+ return null;
2586
+ }
2587
+ const textParts = [];
2588
+ const files = [];
2589
+ for (const part of lastUserMessage.content) {
2590
+ if (part.type === "text" && part.text) {
2591
+ textParts.push(part.text);
2592
+ } else if (part.type === "image_url" && part.image_url?.url) {
2593
+ files.push({
2594
+ id: `img_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
2595
+ name: "image",
2596
+ type: "image/unknown",
2597
+ size: 0,
2598
+ url: part.image_url.url
2599
+ });
2600
+ }
2601
+ }
2602
+ const content = textParts.join("\n");
2603
+ return {
2604
+ content,
2605
+ files: files.length > 0 ? files : void 0
2606
+ };
2607
+ }
2538
2608
 
2539
2609
  // src/lib/db/chat/operations.ts
2540
2610
  var import_watermelondb3 = require("@nozbe/watermelondb");
@@ -3057,9 +3127,8 @@ function useChatStorage(options) {
3057
3127
  const sendMessage = (0, import_react2.useCallback)(
3058
3128
  async (args) => {
3059
3129
  const {
3060
- content,
3130
+ messages,
3061
3131
  model,
3062
- messages: providedMessages,
3063
3132
  includeHistory = true,
3064
3133
  maxHistoryMessages = 50,
3065
3134
  files,
@@ -3083,6 +3152,15 @@ function useChatStorage(options) {
3083
3152
  apiType: requestApiType,
3084
3153
  writeFile
3085
3154
  } = args;
3155
+ const extracted = extractUserMessageFromMessages(messages);
3156
+ if (!extracted || !extracted.content) {
3157
+ return {
3158
+ data: null,
3159
+ error: "No user message found in messages array"
3160
+ };
3161
+ }
3162
+ const contentForStorage = extracted.content;
3163
+ const filesForStorage = files ?? extracted.files;
3086
3164
  let convId;
3087
3165
  try {
3088
3166
  convId = await ensureConversation();
@@ -3093,33 +3171,18 @@ function useChatStorage(options) {
3093
3171
  };
3094
3172
  }
3095
3173
  let messagesToSend = [];
3096
- if (includeHistory && !providedMessages) {
3174
+ if (includeHistory) {
3097
3175
  const storedMessages = await getMessages(convId);
3098
3176
  const validMessages = storedMessages.filter((msg) => !msg.error);
3099
3177
  const limitedMessages = validMessages.slice(-maxHistoryMessages);
3100
- messagesToSend = limitedMessages.map(storedToLlmapiMessage);
3101
- } else if (providedMessages) {
3102
- messagesToSend = providedMessages;
3103
- }
3104
- const userMessageContent = [
3105
- { type: "text", text: content }
3106
- ];
3107
- if (files && files.length > 0) {
3108
- for (const file of files) {
3109
- if (file.url && file.type.startsWith("image/")) {
3110
- userMessageContent.push({
3111
- type: "image_url",
3112
- image_url: { url: file.url }
3113
- });
3114
- }
3115
- }
3178
+ messagesToSend = [
3179
+ ...limitedMessages.map(storedToLlmapiMessage),
3180
+ ...messages
3181
+ ];
3182
+ } else {
3183
+ messagesToSend = [...messages];
3116
3184
  }
3117
- const userMessage = {
3118
- role: "user",
3119
- content: userMessageContent
3120
- };
3121
- messagesToSend.push(userMessage);
3122
- const sanitizedFiles = files?.map((file) => ({
3185
+ const sanitizedFiles = filesForStorage?.map((file) => ({
3123
3186
  id: file.id,
3124
3187
  name: file.name,
3125
3188
  type: file.type,
@@ -3132,7 +3195,7 @@ function useChatStorage(options) {
3132
3195
  storedUserMessage = await createMessageOp(storageCtx, {
3133
3196
  conversationId: convId,
3134
3197
  role: "user",
3135
- content,
3198
+ content: contentForStorage,
3136
3199
  files: sanitizedFiles,
3137
3200
  model
3138
3201
  });
@@ -6593,11 +6656,17 @@ function DropboxAuthProvider({
6593
6656
  if (!isConfigured) return;
6594
6657
  const handleCallback = async () => {
6595
6658
  if (isDropboxCallback()) {
6596
- const result = await handleDropboxCallback(callbackPath, apiClient, walletAddress);
6659
+ const result = await handleDropboxCallback(
6660
+ callbackPath,
6661
+ apiClient,
6662
+ walletAddress
6663
+ );
6597
6664
  if (result.ok) {
6598
6665
  setAccessToken(result.data);
6599
6666
  } else {
6600
- console.error(`Dropbox OAuth failed: ${result.error.code} - ${result.error.message}`);
6667
+ console.error(
6668
+ `Dropbox OAuth failed: ${result.error.code} - ${result.error.message}`
6669
+ );
6601
6670
  }
6602
6671
  }
6603
6672
  };
@@ -6623,7 +6692,14 @@ function DropboxAuthProvider({
6623
6692
  return storedToken;
6624
6693
  }
6625
6694
  return startDropboxAuth(appKey, callbackPath);
6626
- }, [accessToken, appKey, callbackPath, isConfigured, apiClient, walletAddress]);
6695
+ }, [
6696
+ accessToken,
6697
+ appKey,
6698
+ callbackPath,
6699
+ isConfigured,
6700
+ apiClient,
6701
+ walletAddress
6702
+ ]);
6627
6703
  const logout = (0, import_react10.useCallback)(async () => {
6628
6704
  await revokeDropboxToken(apiClient, walletAddress);
6629
6705
  setAccessToken(null);
@@ -6993,11 +7069,17 @@ function GoogleDriveAuthProvider({
6993
7069
  if (!isConfigured) return;
6994
7070
  const handleCallback = async () => {
6995
7071
  if (isGoogleDriveCallback()) {
6996
- const result = await handleGoogleDriveCallback(callbackPath, apiClient, walletAddress);
7072
+ const result = await handleGoogleDriveCallback(
7073
+ callbackPath,
7074
+ apiClient,
7075
+ walletAddress
7076
+ );
6997
7077
  if (result.ok) {
6998
7078
  setAccessToken(result.data);
6999
7079
  } else {
7000
- console.error(`Google Drive OAuth failed: ${result.error.code} - ${result.error.message}`);
7080
+ console.error(
7081
+ `Google Drive OAuth failed: ${result.error.code} - ${result.error.message}`
7082
+ );
7001
7083
  }
7002
7084
  }
7003
7085
  };
@@ -7017,13 +7099,23 @@ function GoogleDriveAuthProvider({
7017
7099
  if (accessToken) {
7018
7100
  return accessToken;
7019
7101
  }
7020
- const storedToken = await getGoogleDriveAccessToken(apiClient, walletAddress);
7102
+ const storedToken = await getGoogleDriveAccessToken(
7103
+ apiClient,
7104
+ walletAddress
7105
+ );
7021
7106
  if (storedToken) {
7022
7107
  setAccessToken(storedToken);
7023
7108
  return storedToken;
7024
7109
  }
7025
7110
  return startGoogleDriveAuth(clientId, callbackPath);
7026
- }, [accessToken, clientId, callbackPath, isConfigured, apiClient, walletAddress]);
7111
+ }, [
7112
+ accessToken,
7113
+ clientId,
7114
+ callbackPath,
7115
+ isConfigured,
7116
+ apiClient,
7117
+ walletAddress
7118
+ ]);
7027
7119
  const logout = (0, import_react12.useCallback)(async () => {
7028
7120
  await revokeGoogleDriveToken(apiClient, walletAddress);
7029
7121
  setAccessToken(null);
@@ -8095,7 +8187,9 @@ function BackupAuthProvider({
8095
8187
  if (result.ok) {
8096
8188
  setDropboxToken(result.data);
8097
8189
  } else {
8098
- console.error(`Dropbox OAuth failed: ${result.error.code} - ${result.error.message}`);
8190
+ console.error(
8191
+ `Dropbox OAuth failed: ${result.error.code} - ${result.error.message}`
8192
+ );
8099
8193
  }
8100
8194
  }
8101
8195
  };
@@ -8113,7 +8207,9 @@ function BackupAuthProvider({
8113
8207
  if (result.ok) {
8114
8208
  setGoogleToken(result.data);
8115
8209
  } else {
8116
- console.error(`Google Drive OAuth failed: ${result.error.code} - ${result.error.message}`);
8210
+ console.error(
8211
+ `Google Drive OAuth failed: ${result.error.code} - ${result.error.message}`
8212
+ );
8117
8213
  }
8118
8214
  }
8119
8215
  };
@@ -8136,7 +8232,13 @@ function BackupAuthProvider({
8136
8232
  return storedToken;
8137
8233
  }
8138
8234
  return startDropboxAuth(dropboxAppKey, dropboxCallbackPath);
8139
- }, [dropboxAppKey, dropboxCallbackPath, isDropboxConfigured, apiClient, walletAddress]);
8235
+ }, [
8236
+ dropboxAppKey,
8237
+ dropboxCallbackPath,
8238
+ isDropboxConfigured,
8239
+ apiClient,
8240
+ walletAddress
8241
+ ]);
8140
8242
  const logoutDropbox = (0, import_react16.useCallback)(async () => {
8141
8243
  await revokeDropboxToken(apiClient, walletAddress);
8142
8244
  setDropboxToken(null);
@@ -8152,13 +8254,22 @@ function BackupAuthProvider({
8152
8254
  if (!isGoogleConfigured || !googleClientId) {
8153
8255
  throw new Error("Google Drive is not configured");
8154
8256
  }
8155
- const storedToken = await getGoogleDriveAccessToken(apiClient, walletAddress);
8257
+ const storedToken = await getGoogleDriveAccessToken(
8258
+ apiClient,
8259
+ walletAddress
8260
+ );
8156
8261
  if (storedToken) {
8157
8262
  setGoogleToken(storedToken);
8158
8263
  return storedToken;
8159
8264
  }
8160
8265
  return startGoogleDriveAuth(googleClientId, googleCallbackPath);
8161
- }, [googleClientId, googleCallbackPath, isGoogleConfigured, apiClient, walletAddress]);
8266
+ }, [
8267
+ googleClientId,
8268
+ googleCallbackPath,
8269
+ isGoogleConfigured,
8270
+ apiClient,
8271
+ walletAddress
8272
+ ]);
8162
8273
  const logoutGoogle = (0, import_react16.useCallback)(async () => {
8163
8274
  await revokeGoogleDriveToken(apiClient, walletAddress);
8164
8275
  setGoogleToken(null);
@@ -8203,7 +8314,14 @@ function BackupAuthProvider({
8203
8314
  isGoogleConfigured ? logoutGoogle() : Promise.resolve(),
8204
8315
  isIcloudConfigured ? logoutIcloud() : Promise.resolve()
8205
8316
  ]);
8206
- }, [isDropboxConfigured, isGoogleConfigured, isIcloudConfigured, logoutDropbox, logoutGoogle, logoutIcloud]);
8317
+ }, [
8318
+ isDropboxConfigured,
8319
+ isGoogleConfigured,
8320
+ isIcloudConfigured,
8321
+ logoutDropbox,
8322
+ logoutGoogle,
8323
+ logoutIcloud
8324
+ ]);
8207
8325
  const dropboxState = {
8208
8326
  accessToken: dropboxToken,
8209
8327
  isAuthenticated: !!dropboxToken,