@reverbia/sdk 1.0.0-next.20251202095402 → 1.0.0-next.20251202225102

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.
@@ -1090,15 +1090,12 @@ function useChat(options) {
1090
1090
  const lastUserMessage = [...messages].reverse().find((m) => m.role === "user");
1091
1091
  if (lastUserMessage?.content) {
1092
1092
  setIsSelectingTool(true);
1093
+ const contentString = lastUserMessage.content?.map((part) => part.text || "").join("") || "";
1093
1094
  try {
1094
- const selectionResult = await selectTool(
1095
- lastUserMessage.content,
1096
- tools,
1097
- {
1098
- model: toolSelectorModel,
1099
- signal: abortController.signal
1100
- }
1101
- );
1095
+ const selectionResult = await selectTool(contentString, tools, {
1096
+ model: toolSelectorModel,
1097
+ signal: abortController.signal
1098
+ });
1102
1099
  if (selectionResult.toolSelected && selectionResult.toolName) {
1103
1100
  const selectedTool = tools.find(
1104
1101
  (t) => t.name === selectionResult.toolName
@@ -1120,22 +1117,32 @@ function useChat(options) {
1120
1117
  if (toolExecutionResult.success && toolExecutionResult.result !== void 0) {
1121
1118
  const toolResultContext = {
1122
1119
  role: "system",
1123
- content: `Tool "${toolExecutionResult.toolName}" was executed with the following result:
1120
+ content: [
1121
+ {
1122
+ type: "text",
1123
+ text: `Tool "${toolExecutionResult.toolName}" was executed with the following result:
1124
1124
  ${JSON.stringify(
1125
- toolExecutionResult.result,
1126
- null,
1127
- 2
1128
- )}
1125
+ toolExecutionResult.result,
1126
+ null,
1127
+ 2
1128
+ )}
1129
1129
 
1130
1130
  Use this information to respond to the user's request.`
1131
+ }
1132
+ ]
1131
1133
  };
1132
1134
  messagesWithToolContext = [...messages, toolResultContext];
1133
1135
  } else if (toolExecutionResult.error) {
1134
1136
  const toolErrorContext = {
1135
1137
  role: "system",
1136
- content: `Tool "${toolExecutionResult.toolName}" was executed but encountered an error: ${toolExecutionResult.error}
1138
+ content: [
1139
+ {
1140
+ type: "text",
1141
+ text: `Tool "${toolExecutionResult.toolName}" was executed but encountered an error: ${toolExecutionResult.error}
1137
1142
 
1138
1143
  Please inform the user about this issue and try to help them alternatively.`
1144
+ }
1145
+ ]
1139
1146
  };
1140
1147
  messagesWithToolContext = [...messages, toolErrorContext];
1141
1148
  }
@@ -1154,7 +1161,7 @@ Please inform the user about this issue and try to help them alternatively.`
1154
1161
  const usedModel = localModel;
1155
1162
  const formattedMessages = messagesWithToolContext.map((m) => ({
1156
1163
  role: m.role || "user",
1157
- content: m.content || ""
1164
+ content: m.content?.map((p) => p.text || "").join("") || ""
1158
1165
  }));
1159
1166
  await generateLocalChatCompletion(formattedMessages, {
1160
1167
  model: usedModel,
@@ -1173,7 +1180,7 @@ Please inform the user about this issue and try to help them alternatively.`
1173
1180
  index: 0,
1174
1181
  message: {
1175
1182
  role: "assistant",
1176
- content: accumulatedContent
1183
+ content: [{ type: "text", text: accumulatedContent }]
1177
1184
  },
1178
1185
  finish_reason: "stop"
1179
1186
  }
@@ -1287,7 +1294,7 @@ Please inform the user about this issue and try to help them alternatively.`
1287
1294
  index: 0,
1288
1295
  message: {
1289
1296
  role: "assistant",
1290
- content: accumulatedContent
1297
+ content: [{ type: "text", text: accumulatedContent }]
1291
1298
  },
1292
1299
  finish_reason: finishReason
1293
1300
  }
@@ -1738,6 +1745,16 @@ var postApiV1Embeddings = (options) => {
1738
1745
  }
1739
1746
  });
1740
1747
  };
1748
+ var postApiV1ImagesGenerations = (options) => {
1749
+ return (options.client ?? client).post({
1750
+ url: "/api/v1/images/generations",
1751
+ ...options,
1752
+ headers: {
1753
+ "Content-Type": "application/json",
1754
+ ...options.headers
1755
+ }
1756
+ });
1757
+ };
1741
1758
  var getApiV1Models = (options) => {
1742
1759
  return (options?.client ?? client).get({
1743
1760
  url: "/api/v1/models",
@@ -1908,9 +1925,12 @@ function useMemory(options = {}) {
1908
1925
  messages: [
1909
1926
  {
1910
1927
  role: "system",
1911
- content: FACT_EXTRACTION_PROMPT
1928
+ content: [{ type: "text", text: FACT_EXTRACTION_PROMPT }]
1912
1929
  },
1913
- ...messages
1930
+ ...messages.map((m) => ({
1931
+ role: m.role,
1932
+ content: [{ type: "text", text: m.content }]
1933
+ }))
1914
1934
  ],
1915
1935
  model: model || completionsModel
1916
1936
  },
@@ -1931,7 +1951,13 @@ function useMemory(options = {}) {
1931
1951
  );
1932
1952
  return null;
1933
1953
  }
1934
- const content = completion.data.choices?.[0]?.message?.content?.trim() || "";
1954
+ const messageContent = completion.data.choices?.[0]?.message?.content;
1955
+ let content = "";
1956
+ if (Array.isArray(messageContent)) {
1957
+ content = messageContent.map((p) => p.text || "").join("").trim();
1958
+ } else if (typeof messageContent === "string") {
1959
+ content = messageContent.trim();
1960
+ }
1935
1961
  if (!content) {
1936
1962
  console.error("No content in memory extraction response");
1937
1963
  return null;
@@ -2212,6 +2238,88 @@ function useModels(options = {}) {
2212
2238
  };
2213
2239
  }
2214
2240
 
2241
+ // src/react/useImageGeneration.ts
2242
+ import { useCallback as useCallback4, useEffect as useEffect4, useRef as useRef5, useState as useState3 } from "react";
2243
+ function useImageGeneration(options = {}) {
2244
+ const { getToken, baseUrl = BASE_URL, onFinish, onError } = options;
2245
+ const [isLoading, setIsLoading] = useState3(false);
2246
+ const abortControllerRef = useRef5(null);
2247
+ useEffect4(() => {
2248
+ return () => {
2249
+ if (abortControllerRef.current) {
2250
+ abortControllerRef.current.abort();
2251
+ abortControllerRef.current = null;
2252
+ }
2253
+ };
2254
+ }, []);
2255
+ const stop = useCallback4(() => {
2256
+ if (abortControllerRef.current) {
2257
+ abortControllerRef.current.abort();
2258
+ abortControllerRef.current = null;
2259
+ }
2260
+ }, []);
2261
+ const generateImage = useCallback4(
2262
+ async (args) => {
2263
+ if (abortControllerRef.current) {
2264
+ abortControllerRef.current.abort();
2265
+ }
2266
+ const abortController = new AbortController();
2267
+ abortControllerRef.current = abortController;
2268
+ setIsLoading(true);
2269
+ try {
2270
+ if (!getToken) {
2271
+ throw new Error("Token getter function is required.");
2272
+ }
2273
+ const token = await getToken();
2274
+ if (!token) {
2275
+ throw new Error("No access token available.");
2276
+ }
2277
+ const response = await postApiV1ImagesGenerations({
2278
+ baseUrl,
2279
+ body: args,
2280
+ headers: {
2281
+ Authorization: `Bearer ${token}`
2282
+ },
2283
+ signal: abortController.signal
2284
+ });
2285
+ if (response.error) {
2286
+ const errorMsg = response.error.error || "Failed to generate image";
2287
+ throw new Error(errorMsg);
2288
+ }
2289
+ if (!response.data) {
2290
+ throw new Error("No data received from image generation API");
2291
+ }
2292
+ const result = response.data;
2293
+ if (onFinish) {
2294
+ onFinish(result);
2295
+ }
2296
+ return { data: result, error: null };
2297
+ } catch (err) {
2298
+ if (err instanceof Error && err.name === "AbortError") {
2299
+ return { data: null, error: "Request aborted" };
2300
+ }
2301
+ const errorMsg = err instanceof Error ? err.message : "Failed to generate image.";
2302
+ const errorObj = err instanceof Error ? err : new Error(errorMsg);
2303
+ if (onError) {
2304
+ onError(errorObj);
2305
+ }
2306
+ return { data: null, error: errorMsg };
2307
+ } finally {
2308
+ if (abortControllerRef.current === abortController) {
2309
+ setIsLoading(false);
2310
+ abortControllerRef.current = null;
2311
+ }
2312
+ }
2313
+ },
2314
+ [getToken, baseUrl, onFinish, onError]
2315
+ );
2316
+ return {
2317
+ isLoading,
2318
+ generateImage,
2319
+ stop
2320
+ };
2321
+ }
2322
+
2215
2323
  // src/lib/memory/chat.ts
2216
2324
  var formatMemoriesForChat = (memories, format = "compact") => {
2217
2325
  if (memories.length === 0) {
@@ -2278,6 +2386,7 @@ export {
2278
2386
  selectTool,
2279
2387
  useChat,
2280
2388
  useEncryption,
2389
+ useImageGeneration,
2281
2390
  useMemory,
2282
2391
  useModels
2283
2392
  };
@@ -37,7 +37,7 @@ function mapMessagesToCompletionPayload(messages) {
37
37
  if (!content.length) return null;
38
38
  const llmMessage = {
39
39
  role: message.role,
40
- content
40
+ content: [{ type: "text", text: content }]
41
41
  };
42
42
  return llmMessage;
43
43
  }).filter((m) => m !== null);
@@ -7,9 +7,33 @@ type LlmapiMessage = {
7
7
  /**
8
8
  * Content is the message content
9
9
  */
10
- content?: string;
10
+ content?: Array<LlmapiMessageContentPart>;
11
11
  role?: LlmapiRole;
12
12
  };
13
+ /**
14
+ * ImageURL is used when Type=image_url
15
+ */
16
+ type LlmapiMessageContentImage = {
17
+ /**
18
+ * Detail is the OpenAI detail hint (auto|low|high)
19
+ */
20
+ detail?: string;
21
+ /**
22
+ * URL is the image URL or data URI
23
+ */
24
+ url?: string;
25
+ };
26
+ type LlmapiMessageContentPart = {
27
+ image_url?: LlmapiMessageContentImage;
28
+ /**
29
+ * Text holds the text content when Type=text
30
+ */
31
+ text?: string;
32
+ /**
33
+ * Type is the block type (`text` or `image_url`)
34
+ */
35
+ type?: string;
36
+ };
13
37
  /**
14
38
  * Role is the message role (system, user, assistant)
15
39
  */
@@ -7,9 +7,33 @@ type LlmapiMessage = {
7
7
  /**
8
8
  * Content is the message content
9
9
  */
10
- content?: string;
10
+ content?: Array<LlmapiMessageContentPart>;
11
11
  role?: LlmapiRole;
12
12
  };
13
+ /**
14
+ * ImageURL is used when Type=image_url
15
+ */
16
+ type LlmapiMessageContentImage = {
17
+ /**
18
+ * Detail is the OpenAI detail hint (auto|low|high)
19
+ */
20
+ detail?: string;
21
+ /**
22
+ * URL is the image URL or data URI
23
+ */
24
+ url?: string;
25
+ };
26
+ type LlmapiMessageContentPart = {
27
+ image_url?: LlmapiMessageContentImage;
28
+ /**
29
+ * Text holds the text content when Type=text
30
+ */
31
+ text?: string;
32
+ /**
33
+ * Type is the block type (`text` or `image_url`)
34
+ */
35
+ type?: string;
36
+ };
13
37
  /**
14
38
  * Role is the message role (system, user, assistant)
15
39
  */
@@ -9,7 +9,7 @@ function mapMessagesToCompletionPayload(messages) {
9
9
  if (!content.length) return null;
10
10
  const llmMessage = {
11
11
  role: message.role,
12
- content
12
+ content: [{ type: "text", text: content }]
13
13
  };
14
14
  return llmMessage;
15
15
  }).filter((m) => m !== null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reverbia/sdk",
3
- "version": "1.0.0-next.20251202095402",
3
+ "version": "1.0.0-next.20251202225102",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -57,7 +57,7 @@
57
57
  "homepage": "https://github.com/zeta-chain/ai-sdk#readme",
58
58
  "dependencies": {
59
59
  "@huggingface/transformers": "^3.8.0",
60
- "@reverbia/portal": "1.0.0-next.20251126175613",
60
+ "@reverbia/portal": "1.0.0-next.20251201184846",
61
61
  "ai": "5.0.93"
62
62
  },
63
63
  "devDependencies": {