@alquimia-ai/tools 1.13.2 → 2.1.0

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.
Files changed (75) hide show
  1. package/dist/actions/index.d.mts +2 -17
  2. package/dist/actions/index.d.ts +2 -17
  3. package/dist/actions/index.js +47 -152
  4. package/dist/actions/index.js.map +1 -1
  5. package/dist/actions/index.mjs +47 -152
  6. package/dist/actions/index.mjs.map +1 -1
  7. package/dist/adapters/fetch.d.mts +12 -0
  8. package/dist/adapters/fetch.d.ts +12 -0
  9. package/dist/adapters/fetch.js +44 -0
  10. package/dist/adapters/fetch.js.map +1 -0
  11. package/dist/adapters/fetch.mjs +23 -0
  12. package/dist/adapters/fetch.mjs.map +1 -0
  13. package/dist/adapters/index.d.mts +11 -0
  14. package/dist/adapters/index.d.ts +11 -0
  15. package/dist/adapters/index.js +19 -0
  16. package/dist/adapters/index.js.map +1 -0
  17. package/dist/adapters/index.mjs +1 -0
  18. package/dist/adapters/index.mjs.map +1 -0
  19. package/dist/adapters/next.d.mts +10 -0
  20. package/dist/adapters/next.d.ts +10 -0
  21. package/dist/adapters/next.js +42 -0
  22. package/dist/adapters/next.js.map +1 -0
  23. package/dist/adapters/next.mjs +21 -0
  24. package/dist/adapters/next.mjs.map +1 -0
  25. package/dist/hooks/index.d.mts +23 -4
  26. package/dist/hooks/index.d.ts +23 -4
  27. package/dist/hooks/index.js +292 -57
  28. package/dist/hooks/index.js.map +1 -1
  29. package/dist/hooks/index.mjs +283 -58
  30. package/dist/hooks/index.mjs.map +1 -1
  31. package/dist/next/index.d.mts +46 -0
  32. package/dist/next/index.d.ts +46 -0
  33. package/dist/next/index.js +337 -0
  34. package/dist/next/index.js.map +1 -0
  35. package/dist/next/index.mjs +314 -0
  36. package/dist/next/index.mjs.map +1 -0
  37. package/dist/providers/index.d.mts +7 -3
  38. package/dist/providers/index.d.ts +7 -3
  39. package/dist/providers/index.js +15 -14
  40. package/dist/providers/index.js.map +1 -1
  41. package/dist/providers/index.mjs +15 -14
  42. package/dist/providers/index.mjs.map +1 -1
  43. package/dist/proxy.d.mts +15 -0
  44. package/dist/proxy.d.ts +15 -0
  45. package/dist/proxy.js +170 -0
  46. package/dist/proxy.js.map +1 -0
  47. package/dist/proxy.mjs +149 -0
  48. package/dist/proxy.mjs.map +1 -0
  49. package/dist/sdk/index.d.mts +22 -20
  50. package/dist/sdk/index.d.ts +22 -20
  51. package/dist/sdk/index.js +85 -66
  52. package/dist/sdk/index.js.map +1 -1
  53. package/dist/sdk/index.mjs +85 -66
  54. package/dist/sdk/index.mjs.map +1 -1
  55. package/dist/services/index.d.mts +25 -3
  56. package/dist/services/index.d.ts +25 -3
  57. package/dist/session.action-DirvOWt0.d.mts +3 -0
  58. package/dist/session.action-DirvOWt0.d.ts +3 -0
  59. package/dist/types/index.d.mts +79 -18
  60. package/dist/types/index.d.ts +79 -18
  61. package/dist/types/index.js.map +1 -1
  62. package/dist/types/index.mjs.map +1 -1
  63. package/package.json +35 -5
  64. package/dist/providers/elastic/index.d.mts +0 -23
  65. package/dist/providers/elastic/index.d.ts +0 -23
  66. package/dist/providers/elastic/index.js +0 -102
  67. package/dist/providers/elastic/index.js.map +0 -1
  68. package/dist/providers/elastic/index.mjs +0 -69
  69. package/dist/providers/elastic/index.mjs.map +0 -1
  70. package/dist/services/apm/index.d.mts +0 -26
  71. package/dist/services/apm/index.d.ts +0 -26
  72. package/dist/services/apm/index.js +0 -86
  73. package/dist/services/apm/index.js.map +0 -1
  74. package/dist/services/apm/index.mjs +0 -63
  75. package/dist/services/apm/index.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/next.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface NextJsAdapterOptions {\n inferRoute?: string; // default: '/api/chat'\n streamRoute?: string; // default: '/api/stream'\n blobUploadRoute?: string; // default: '/api/blob/upload'\n}\n\nexport function createNextJsAdapter(options?: NextJsAdapterOptions): AlquimiaAdapter {\n const inferRoute = options?.inferRoute ?? '/api/chat';\n const streamRoute = options?.streamRoute ?? '/api/stream';\n const blobUploadRoute = options?.blobUploadRoute ?? '/api/blob/upload';\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${inferRoute.replace(/\\/$/, '')}/${encodeURIComponent(assistantId)}`;\n },\n resolveStreamUrl(streamId: string): string {\n return `${streamRoute}/${streamId}`;\n },\n resolveBlobUploadUrl(): string {\n return blobUploadRoute;\n },\n };\n}\n"],"mappings":";AAQO,SAAS,oBAAoB,SAAiD;AACnF,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,cAAc,SAAS,eAAe;AAC5C,QAAM,kBAAkB,SAAS,mBAAmB;AAEpD,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,WAAW,QAAQ,OAAO,EAAE,CAAC,IAAI,mBAAmB,WAAW,CAAC;AAAA,IAC5E;AAAA,IACA,iBAAiB,UAA0B;AACzC,aAAO,GAAG,WAAW,IAAI,QAAQ;AAAA,IACnC;AAAA,IACA,uBAA+B;AAC7B,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -1,12 +1,30 @@
1
1
  import * as react from 'react';
2
2
  import { AlquimiaSDK } from '../sdk/index.mjs';
3
+ import { AlquimiaAdapter } from '../adapters/index.mjs';
4
+ import { W as WhisperProvider, S as StableDiffusionProvider, C as CharacterizationProvider, R as RatingsProvider, L as LoggerProvider } from '../providers-0Gi78uNQ.mjs';
3
5
  import { AlquimiaMessage, ToolEvent, AIMessageChunk, RatingData } from '../types/index.mjs';
4
6
  import { createMessageId } from '../utils/index.mjs';
5
- import '../providers-0Gi78uNQ.mjs';
6
7
  import '@elastic/apm-rum';
7
8
  import 'ai';
8
9
 
9
- declare function useAlquimia(sdk: AlquimiaSDK): {
10
+ interface UseAlquimiaConfig {
11
+ assistantId: string;
12
+ adapter: AlquimiaAdapter;
13
+ providers?: {
14
+ whisper?: WhisperProvider;
15
+ stableDiffusion?: StableDiffusionProvider;
16
+ characterization?: CharacterizationProvider;
17
+ ratings?: RatingsProvider;
18
+ logger?: LoggerProvider;
19
+ };
20
+ options?: {
21
+ enforceCharacterization?: boolean;
22
+ userId?: string;
23
+ extraInstructions?: Record<string, string>;
24
+ };
25
+ }
26
+ declare function useAlquimia(config: UseAlquimiaConfig): {
27
+ sdk: AlquimiaSDK;
10
28
  activeTool: any;
11
29
  cleanMessages: () => void;
12
30
  createMessageId: typeof createMessageId;
@@ -22,20 +40,21 @@ declare function useAlquimia(sdk: AlquimiaSDK): {
22
40
  handleLoadingCancel: () => void;
23
41
  input: string;
24
42
  isLoading: boolean;
43
+ isMessageLoading: boolean;
25
44
  isMessageStreaming: boolean;
45
+ isStreamingLoading: boolean;
26
46
  streamingMessageId: string | null;
27
47
  isAudioRecording: boolean;
28
48
  lastRequest: string | null;
29
49
  messages: AlquimiaMessage[];
30
50
  populateMessages: (messages: AlquimiaMessage[]) => void;
31
- processMessageChunk: (messageId: string, chunk: string, error_code?: string, error_detail?: string, stream_id?: string, additionalInfo?: string, loading?: boolean, tooler?: ToolEvent[], thinkings?: any[]) => void;
51
+ processMessageChunk: (messageId: string, chunk: string, error_code?: string, error_detail?: string, taskid?: string, additionalInfo?: string, loading?: boolean, tooler?: ToolEvent[], thinkings?: any[]) => void;
32
52
  sendMessage: (message: string, callBack: (chunk: AIMessageChunk) => void, traceParentId?: string, sessionId?: string) => Promise<void>;
33
53
  sessionId: string | null;
34
54
  setActiveTool: react.Dispatch<any>;
35
55
  setSessionId: react.Dispatch<react.SetStateAction<string | null>>;
36
56
  setLastRequest: react.Dispatch<react.SetStateAction<string | null>>;
37
57
  setIsAudioRecording: react.Dispatch<react.SetStateAction<boolean>>;
38
- evaluationStrategy: string;
39
58
  hasThinkings: boolean;
40
59
  attachments: File[];
41
60
  addAttachment: (file: File) => void;
@@ -1,12 +1,30 @@
1
1
  import * as react from 'react';
2
2
  import { AlquimiaSDK } from '../sdk/index.js';
3
+ import { AlquimiaAdapter } from '../adapters/index.js';
4
+ import { W as WhisperProvider, S as StableDiffusionProvider, C as CharacterizationProvider, R as RatingsProvider, L as LoggerProvider } from '../providers-BJTXCtI3.js';
3
5
  import { AlquimiaMessage, ToolEvent, AIMessageChunk, RatingData } from '../types/index.js';
4
6
  import { createMessageId } from '../utils/index.js';
5
- import '../providers-BJTXCtI3.js';
6
7
  import '@elastic/apm-rum';
7
8
  import 'ai';
8
9
 
9
- declare function useAlquimia(sdk: AlquimiaSDK): {
10
+ interface UseAlquimiaConfig {
11
+ assistantId: string;
12
+ adapter: AlquimiaAdapter;
13
+ providers?: {
14
+ whisper?: WhisperProvider;
15
+ stableDiffusion?: StableDiffusionProvider;
16
+ characterization?: CharacterizationProvider;
17
+ ratings?: RatingsProvider;
18
+ logger?: LoggerProvider;
19
+ };
20
+ options?: {
21
+ enforceCharacterization?: boolean;
22
+ userId?: string;
23
+ extraInstructions?: Record<string, string>;
24
+ };
25
+ }
26
+ declare function useAlquimia(config: UseAlquimiaConfig): {
27
+ sdk: AlquimiaSDK;
10
28
  activeTool: any;
11
29
  cleanMessages: () => void;
12
30
  createMessageId: typeof createMessageId;
@@ -22,20 +40,21 @@ declare function useAlquimia(sdk: AlquimiaSDK): {
22
40
  handleLoadingCancel: () => void;
23
41
  input: string;
24
42
  isLoading: boolean;
43
+ isMessageLoading: boolean;
25
44
  isMessageStreaming: boolean;
45
+ isStreamingLoading: boolean;
26
46
  streamingMessageId: string | null;
27
47
  isAudioRecording: boolean;
28
48
  lastRequest: string | null;
29
49
  messages: AlquimiaMessage[];
30
50
  populateMessages: (messages: AlquimiaMessage[]) => void;
31
- processMessageChunk: (messageId: string, chunk: string, error_code?: string, error_detail?: string, stream_id?: string, additionalInfo?: string, loading?: boolean, tooler?: ToolEvent[], thinkings?: any[]) => void;
51
+ processMessageChunk: (messageId: string, chunk: string, error_code?: string, error_detail?: string, taskid?: string, additionalInfo?: string, loading?: boolean, tooler?: ToolEvent[], thinkings?: any[]) => void;
32
52
  sendMessage: (message: string, callBack: (chunk: AIMessageChunk) => void, traceParentId?: string, sessionId?: string) => Promise<void>;
33
53
  sessionId: string | null;
34
54
  setActiveTool: react.Dispatch<any>;
35
55
  setSessionId: react.Dispatch<react.SetStateAction<string | null>>;
36
56
  setLastRequest: react.Dispatch<react.SetStateAction<string | null>>;
37
57
  setIsAudioRecording: react.Dispatch<react.SetStateAction<boolean>>;
38
- evaluationStrategy: string;
39
58
  hasThinkings: boolean;
40
59
  attachments: File[];
41
60
  addAttachment: (file: File) => void;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/hooks/index.ts
@@ -28,6 +38,224 @@ module.exports = __toCommonJS(hooks_exports);
28
38
  // src/hooks/alquimia.hook.tsx
29
39
  var import_react = require("react");
30
40
 
41
+ // src/sdk/alquimia-sdk.ts
42
+ var import_axios = __toESM(require("axios"));
43
+ var AlquimiaSDK = class {
44
+ constructor(assistantId, adapter, options = {}) {
45
+ this.conversationId = null;
46
+ this.sessionId = null;
47
+ // Internal subscription id from infer (`taskid` on the wire).
48
+ this.streamId = null;
49
+ this.tools = [];
50
+ this.extraInstructions = null;
51
+ this.assistantConfig = null;
52
+ this.userId = null;
53
+ this.attachments = [];
54
+ this.attachmentResponses = [];
55
+ if (!assistantId) {
56
+ throw new Error("AlquimiaSDK: assistantId is required");
57
+ }
58
+ if (!adapter) {
59
+ throw new Error(
60
+ "AlquimiaSDK: adapter is required. Use createNextJsAdapter() or createFetchAdapter()"
61
+ );
62
+ }
63
+ this.assistantId = assistantId;
64
+ this.adapter = adapter;
65
+ this.enforceCharacterization = options.enforceCharacterization ?? true;
66
+ this.axiosInstance = import_axios.default.create();
67
+ this.axiosInstance.interceptors.response.use(
68
+ (response) => response,
69
+ async (error) => {
70
+ if (error.response?.status && this.loggerProvider) {
71
+ await this.loggerProvider.logError("Server Error", error, {
72
+ url: error.config.url,
73
+ method: error.config.method,
74
+ data: error.config.data,
75
+ status: error.response.status,
76
+ responseData: error.response.data
77
+ });
78
+ }
79
+ return Promise.reject(error);
80
+ }
81
+ );
82
+ this.textToSpeech = this.textToSpeech.bind(this);
83
+ this.speechToText = this.speechToText.bind(this);
84
+ }
85
+ withConversationId(conversationId) {
86
+ this.conversationId = conversationId;
87
+ return this;
88
+ }
89
+ withAttachments(attachments) {
90
+ this.attachments = attachments;
91
+ return this;
92
+ }
93
+ withWhisperProvider(provider) {
94
+ this.whisperProvider = provider;
95
+ return this;
96
+ }
97
+ withStableDiffusionProvider(provider) {
98
+ this.stableDiffusionProvider = provider;
99
+ return this;
100
+ }
101
+ withAnalyzeCharacterizationProvider(provider) {
102
+ this.analyzeCharacterizationProvider = provider;
103
+ return this;
104
+ }
105
+ withRatingsProvider(provider) {
106
+ this.ratingsProvider = provider;
107
+ return this;
108
+ }
109
+ withLoggerProvider(provider) {
110
+ this.loggerProvider = provider;
111
+ return this;
112
+ }
113
+ withTools(tools) {
114
+ this.tools = tools;
115
+ return this;
116
+ }
117
+ withExtraInstructions(extraInstructions) {
118
+ this.extraInstructions = extraInstructions;
119
+ return this;
120
+ }
121
+ withAssistantConfig(assistantConfig) {
122
+ this.assistantConfig = assistantConfig;
123
+ return this;
124
+ }
125
+ withUserId(userId) {
126
+ this.userId = userId;
127
+ return this;
128
+ }
129
+ getEnforceCharacterization() {
130
+ return this.enforceCharacterization ?? true;
131
+ }
132
+ textToSpeech(text) {
133
+ if (!this.whisperProvider) {
134
+ throw new Error("Whisper provider not initialized");
135
+ }
136
+ return this.whisperProvider.textToSpeech(text);
137
+ }
138
+ speechToText(audio) {
139
+ if (!this.whisperProvider) {
140
+ throw new Error("Whisper provider not initialized");
141
+ }
142
+ return this.whisperProvider.speechToText(audio);
143
+ }
144
+ async sendMessage(query, traceParent) {
145
+ if (!this.conversationId) {
146
+ throw new Error(
147
+ "Conversation not initialized. Call withConversationId() before sendMessage()"
148
+ );
149
+ }
150
+ const inferUrl = this.adapter.resolveInferUrl(this.assistantId);
151
+ const adapterHeaders = this.adapter.getHeaders?.() ?? {};
152
+ const hasClientTools = Array.isArray(this.tools) && this.tools.length > 0;
153
+ const initMessage = {
154
+ query,
155
+ session_id: this.conversationId,
156
+ user_id: this.userId,
157
+ ...this.extraInstructions && { extra_instructions: this.extraInstructions },
158
+ ...this.assistantConfig && { config: this.assistantConfig },
159
+ ...hasClientTools && {
160
+ evaluation_strategy: {
161
+ evaluation_strategy_id: "native",
162
+ tool_schemas: this.tools
163
+ }
164
+ }
165
+ };
166
+ const result = (await this.axiosInstance.post(inferUrl, initMessage, {
167
+ headers: {
168
+ "Content-Type": "application/json",
169
+ "x-trace-parent": traceParent || "",
170
+ ...adapterHeaders,
171
+ ...this.buildIdentityHeaders()
172
+ }
173
+ })).data;
174
+ this.streamId = result.taskid ?? null;
175
+ this.attachmentResponses = result.attachments ?? [];
176
+ this.attachments = [];
177
+ return this;
178
+ }
179
+ async generateImage(query) {
180
+ if (!this.stableDiffusionProvider) {
181
+ throw new Error("Stable Diffusion provider not initialized");
182
+ }
183
+ return this.stableDiffusionProvider.generateImage(query);
184
+ }
185
+ async analyzeCharacterization(text) {
186
+ if (!this.analyzeCharacterizationProvider) {
187
+ throw new Error("Analyze characterization provider not initialized");
188
+ }
189
+ return this.analyzeCharacterizationProvider.analyzeCharacterization(text);
190
+ }
191
+ async rate(data) {
192
+ if (!this.ratingsProvider) {
193
+ throw new Error("Ratings provider not initialized");
194
+ }
195
+ return this.ratingsProvider.rate(data);
196
+ }
197
+ async logInfo(message, data) {
198
+ if (!this.loggerProvider) {
199
+ throw new Error("Logger provider not initialized");
200
+ }
201
+ return this.loggerProvider.logInfo(message, data);
202
+ }
203
+ async logError(message, error, data) {
204
+ if (!this.loggerProvider) {
205
+ throw new Error("Logger provider not initialized");
206
+ }
207
+ return this.loggerProvider.logError(message, error, data);
208
+ }
209
+ /**
210
+ * @deprecated The runtime no longer returns attachment IDs from the infer
211
+ * response — attachments are uploaded as standalone blobs and linked to the
212
+ * session via headers. Always returns `[]`; kept for source compatibility.
213
+ */
214
+ getAttachmentResponses() {
215
+ return this.attachmentResponses;
216
+ }
217
+ async uploadAttachment(file, _attachmentId) {
218
+ const url = this.adapter.resolveBlobUploadUrl();
219
+ const adapterHeaders = this.adapter.getHeaders?.() ?? {};
220
+ const formData = new FormData();
221
+ formData.append("file", file);
222
+ await this.axiosInstance.post(url, formData, {
223
+ headers: {
224
+ "Content-Type": "multipart/form-data",
225
+ ...adapterHeaders,
226
+ ...this.buildIdentityHeaders()
227
+ }
228
+ });
229
+ }
230
+ /**
231
+ * Identity headers (kebab-case) required by `/context/blob/upload` and
232
+ * the rest of the runtime's internal endpoints introduced in v0.2.0→next.
233
+ */
234
+ buildIdentityHeaders() {
235
+ const headers = {
236
+ "assistant-id": this.assistantId
237
+ };
238
+ if (this.conversationId) headers["session-id"] = this.conversationId;
239
+ if (this.userId) headers["user-id"] = this.userId;
240
+ if (this.streamId) headers["task-id"] = this.streamId;
241
+ return headers;
242
+ }
243
+ getUrlStream() {
244
+ if (!this.streamId) {
245
+ throw new Error("Stream ID not initialized. Call sendMessage() first");
246
+ }
247
+ return this.adapter.resolveStreamUrl(this.streamId);
248
+ }
249
+ getStreamId() {
250
+ return this.streamId;
251
+ }
252
+ /** Alias for {@link getStreamId} — same value as infer `taskid`. */
253
+ getTaskId() {
254
+ return this.streamId;
255
+ }
256
+ };
257
+ var alquimia_sdk_default = AlquimiaSDK;
258
+
31
259
  // src/utils/utils.ts
32
260
  function getCookies(name) {
33
261
  if (typeof document === "undefined") return void 0;
@@ -111,7 +339,20 @@ function mergeToolEvents(initial, toolEvents) {
111
339
  }
112
340
 
113
341
  // src/hooks/alquimia.hook.tsx
114
- function useAlquimia(sdk) {
342
+ function useAlquimia(config) {
343
+ const sdk = (0, import_react.useMemo)(() => {
344
+ const instance = new alquimia_sdk_default(config.assistantId, config.adapter, {
345
+ enforceCharacterization: config.options?.enforceCharacterization
346
+ });
347
+ if (config.providers?.whisper) instance.withWhisperProvider(config.providers.whisper);
348
+ if (config.providers?.stableDiffusion) instance.withStableDiffusionProvider(config.providers.stableDiffusion);
349
+ if (config.providers?.characterization) instance.withAnalyzeCharacterizationProvider(config.providers.characterization);
350
+ if (config.providers?.ratings) instance.withRatingsProvider(config.providers.ratings);
351
+ if (config.providers?.logger) instance.withLoggerProvider(config.providers.logger);
352
+ if (config.options?.userId) instance.withUserId(config.options.userId);
353
+ if (config.options?.extraInstructions) instance.withExtraInstructions(config.options.extraInstructions);
354
+ return instance;
355
+ }, [config.assistantId, config.adapter]);
115
356
  const [input, setInput] = (0, import_react.useState)("");
116
357
  const [isMessageLoading, setIsMessageLoading] = (0, import_react.useState)(false);
117
358
  const [isStreamingLoading, setIsStreamingLoading] = (0, import_react.useState)(false);
@@ -120,10 +361,10 @@ function useAlquimia(sdk) {
120
361
  const [isAudioRecording, setIsAudioRecording] = (0, import_react.useState)(false);
121
362
  const [messages, setMessages] = (0, import_react.useState)([]);
122
363
  const eventSourceRef = (0, import_react.useRef)(null);
364
+ const streamUserCancelledRef = (0, import_react.useRef)(false);
123
365
  const [sessionId, setSessionId] = (0, import_react.useState)(null);
124
366
  const [activeTool, setActiveTool] = (0, import_react.useState)(null);
125
367
  const [lastRequest, setLastRequest] = (0, import_react.useState)(null);
126
- const [evaluationStrategy, setEvaluationStrategy] = (0, import_react.useState)("");
127
368
  const [hasThinkings, setHasThinkings] = (0, import_react.useState)(false);
128
369
  const [attachments, setAttachments] = (0, import_react.useState)([]);
129
370
  const [isUploadingAttachments, setIsUploadingAttachments] = (0, import_react.useState)(false);
@@ -144,11 +385,9 @@ function useAlquimia(sdk) {
144
385
  function clearAttachments() {
145
386
  setAttachments([]);
146
387
  }
147
- function processMessageChunk(messageId, chunk, error_code, error_detail, stream_id, additionalInfo, loading, tooler, thinkings) {
388
+ function processMessageChunk(messageId, chunk, error_code, error_detail, taskid, additionalInfo, loading, tooler, thinkings) {
148
389
  setMessages((currentMessages) => {
149
- const messageIndex = currentMessages.findIndex(
150
- (message) => message?.id === messageId
151
- );
390
+ const messageIndex = currentMessages.findIndex((message) => message?.id === messageId);
152
391
  if (messageIndex !== -1) {
153
392
  const updatedMessages = [...currentMessages];
154
393
  const updatedMessage = {
@@ -158,14 +397,11 @@ function useAlquimia(sdk) {
158
397
  role: updatedMessages[messageIndex]?.role || "assistant",
159
398
  error_code,
160
399
  error_detail,
161
- stream_id,
400
+ taskid,
162
401
  additionalInfo,
163
402
  created_at: (/* @__PURE__ */ new Date()).getTime().toString(),
164
403
  loading,
165
- tooler: mergeToolEvents(
166
- updatedMessages[messageIndex]?.tooler || [],
167
- tooler
168
- ),
404
+ tooler: mergeToolEvents(updatedMessages[messageIndex]?.tooler || [], tooler),
169
405
  thinkings: mergeThinkingsByControlId(
170
406
  updatedMessages[messageIndex]?.thinkings || [],
171
407
  thinkings || []
@@ -182,7 +418,7 @@ function useAlquimia(sdk) {
182
418
  id: messageId,
183
419
  error_code,
184
420
  error_detail,
185
- stream_id,
421
+ taskid,
186
422
  created_at: (/* @__PURE__ */ new Date()).getTime().toString(),
187
423
  loading,
188
424
  tooler: mergeToolEvents([], tooler),
@@ -204,7 +440,7 @@ function useAlquimia(sdk) {
204
440
  chunk?.answer || "",
205
441
  chunk?.error_code,
206
442
  chunk?.error_detail,
207
- chunk?.stream_id,
443
+ chunk?.taskid,
208
444
  options?.additionalInfo,
209
445
  chunk?.loading,
210
446
  chunk?.tooler,
@@ -220,11 +456,7 @@ function useAlquimia(sdk) {
220
456
  setIsMessageLoading(true);
221
457
  event.preventDefault();
222
458
  if (input) {
223
- await processAndSendMessage(input, {
224
- traceParentId,
225
- sessionId: sessionId2,
226
- additionalInfo
227
- });
459
+ await processAndSendMessage(input, { traceParentId, sessionId: sessionId2, additionalInfo });
228
460
  }
229
461
  setIsMessageLoading(false);
230
462
  }
@@ -248,6 +480,7 @@ function useAlquimia(sdk) {
248
480
  setMessages(messages2);
249
481
  }
250
482
  function handleLoadingCancel() {
483
+ streamUserCancelledRef.current = true;
251
484
  eventSourceRef.current?.close();
252
485
  eventSourceRef.current = null;
253
486
  setIsMessageLoading(false);
@@ -271,7 +504,7 @@ function useAlquimia(sdk) {
271
504
  }
272
505
  function getCookie(name) {
273
506
  const cookies = document.cookie.split(";");
274
- for (let cookie of cookies) {
507
+ for (const cookie of cookies) {
275
508
  const [cookieName, cookieValue] = cookie.trim().split("=");
276
509
  if (cookieName === name) {
277
510
  return decodeURIComponent(cookieValue);
@@ -287,23 +520,22 @@ function useAlquimia(sdk) {
287
520
  }
288
521
  async function sendMessage(message, callBack, traceParentId, sessionId2) {
289
522
  setIsStreamingLoading(true);
290
- callBack({
291
- type: "loading",
292
- loading: true
293
- });
523
+ callBack({ type: "loading", loading: true });
294
524
  const conversationId = sessionId2 || getCookie("alquimia-session");
295
525
  setIsMessageStreaming(true);
296
526
  setActiveTool(null);
297
527
  setLastRequest(message);
298
528
  try {
299
529
  const hasAttachments = attachments.length > 0;
300
- const sdkCall = sdk.widthConversationId(conversationId || "");
530
+ const sdkCall = sdk.withConversationId(conversationId || "");
301
531
  if (hasAttachments) {
302
- sdkCall.withAttachments(attachments.map((f) => ({
303
- filename: f.name,
304
- content_type: f.type,
305
- content_size: f.size
306
- })));
532
+ sdkCall.withAttachments(
533
+ attachments.map((f) => ({
534
+ filename: f.name,
535
+ content_type: f.type,
536
+ content_size: f.size
537
+ }))
538
+ );
307
539
  }
308
540
  const response = await sdkCall.sendMessage(message, traceParentId);
309
541
  if (hasAttachments) {
@@ -311,9 +543,7 @@ function useAlquimia(sdk) {
311
543
  try {
312
544
  const attachmentResponses = response.getAttachmentResponses();
313
545
  await Promise.all(
314
- attachments.map(
315
- (file, i) => response.uploadAttachment(file, attachmentResponses[i])
316
- )
546
+ attachments.map((file, i) => response.uploadAttachment(file, attachmentResponses[i]))
317
547
  );
318
548
  } catch (uploadError) {
319
549
  setIsUploadingAttachments(false);
@@ -332,6 +562,7 @@ function useAlquimia(sdk) {
332
562
  }
333
563
  const streamUrl = response.getUrlStream();
334
564
  const streamId = response.getStreamId() || "";
565
+ streamUserCancelledRef.current = false;
335
566
  const streamState = {
336
567
  streamId,
337
568
  connectedAt: Date.now(),
@@ -342,8 +573,6 @@ function useAlquimia(sdk) {
342
573
  };
343
574
  const eventSource = new EventSource(streamUrl);
344
575
  eventSourceRef.current = eventSource;
345
- const evaluationStrategy2 = response.getEvaluationStrategy();
346
- setEvaluationStrategy(evaluationStrategy2);
347
576
  eventSource.onopen = () => {
348
577
  streamState.openedAt = Date.now();
349
578
  };
@@ -354,23 +583,37 @@ function useAlquimia(sdk) {
354
583
  };
355
584
  eventSource.onerror = () => {
356
585
  if (streamState.closedByClient) return;
586
+ if (streamUserCancelledRef.current) {
587
+ streamUserCancelledRef.current = false;
588
+ return;
589
+ }
357
590
  streamState.closedByClient = true;
358
591
  const elapsed = Date.now() - streamState.connectedAt;
359
592
  const sinceLastMessage = streamState.lastMessageAt ? Date.now() - streamState.lastMessageAt : null;
360
593
  cleanup(false, eventSource);
361
594
  let errorDetail;
362
595
  if (!streamState.openedAt) {
363
- errorDetail = `Stream failed to connect (after ${elapsed}ms). URL: ${streamUrl}`;
596
+ errorDetail = "Could not open the live response. Check your connection and try again.";
364
597
  } else if (streamState.messagesReceived === 0) {
365
- errorDetail = `Stream connected but received no messages before error (open for ${elapsed}ms).`;
598
+ errorDetail = "No response was received. Try again in a moment.";
366
599
  } else {
367
- errorDetail = `Stream dropped after ${streamState.messagesReceived} message(s), ${sinceLastMessage}ms since last message (total ${elapsed}ms). Possible timeout.`;
600
+ errorDetail = "The response was interrupted. Try again.";
601
+ }
602
+ if (typeof console !== "undefined" && console.debug) {
603
+ console.debug("[Alquimia] SSE transport error", {
604
+ streamUrl,
605
+ taskId: streamId,
606
+ opened: Boolean(streamState.openedAt),
607
+ messagesReceived: streamState.messagesReceived,
608
+ elapsedMs: elapsed,
609
+ sinceLastMessageMs: sinceLastMessage
610
+ });
368
611
  }
369
612
  callBack({
370
613
  type: "error",
371
614
  error_code: "STREAM_ERROR",
372
615
  error_detail: errorDetail,
373
- stream_id: streamId
616
+ taskid: streamId
374
617
  });
375
618
  };
376
619
  } catch (error) {
@@ -381,13 +624,14 @@ function useAlquimia(sdk) {
381
624
  setStreamingMessageId(null);
382
625
  callBack({
383
626
  type: "error",
384
- error_code: error.status?.toString() || "REQUEST_ERROR",
627
+ error_code: error.response?.status != null ? String(error.response.status) : "REQUEST_ERROR",
385
628
  error_detail: errMessage
386
629
  });
387
630
  }
388
631
  }
389
632
  function handleMessageEvent(event, callBack, eventSource, streamState) {
390
633
  const data = JSON.parse(event.data);
634
+ const eventTaskId = data.taskid || "";
391
635
  if (data.errors?.length) {
392
636
  for (const error of data.errors) {
393
637
  const detail = error.error_detail || (error.data != null ? `${error.data} (controlId: ${error.control_id})` : "Unknown error");
@@ -395,7 +639,7 @@ function useAlquimia(sdk) {
395
639
  type: "error",
396
640
  error_code: error.event_class || error.status || "UNKNOWN_ERROR",
397
641
  error_detail: detail,
398
- stream_id: data.stream_id || ""
642
+ taskid: eventTaskId
399
643
  });
400
644
  }
401
645
  if (streamState) streamState.closedByClient = true;
@@ -403,31 +647,21 @@ function useAlquimia(sdk) {
403
647
  return;
404
648
  }
405
649
  if (data.tools_output?.length) {
406
- callBack({
407
- type: "answer",
408
- answer: "",
409
- tooler: data.tools_output
410
- });
650
+ callBack({ type: "answer", answer: "", tooler: data.tools_output });
411
651
  }
412
652
  if (data.thinkings?.length) {
413
653
  setHasThinkings(true);
414
- callBack({
415
- type: "answer",
416
- thinkings: data.thinkings
417
- });
654
+ callBack({ type: "answer", thinkings: data.thinkings });
418
655
  }
419
- const response = data.response;
420
- const content = response?.event_class === "AssistantInferenceResponse" && typeof response.data === "string" ? response.data : null;
421
- if (content) {
422
- callBack({
423
- type: "answer",
424
- answer: content
425
- });
656
+ if (data.event_class === "AssistantInferenceResponse") {
657
+ const final = data;
658
+ callBack({ type: "answer", answer: final.data });
426
659
  if (streamState) streamState.closedByClient = true;
427
660
  cleanup(false, eventSource);
428
661
  }
429
662
  }
430
663
  return {
664
+ sdk,
431
665
  activeTool,
432
666
  cleanMessages,
433
667
  createMessageId,
@@ -438,7 +672,9 @@ function useAlquimia(sdk) {
438
672
  handleLoadingCancel,
439
673
  input,
440
674
  isLoading,
675
+ isMessageLoading,
441
676
  isMessageStreaming,
677
+ isStreamingLoading,
442
678
  streamingMessageId,
443
679
  isAudioRecording,
444
680
  lastRequest,
@@ -451,7 +687,6 @@ function useAlquimia(sdk) {
451
687
  setSessionId,
452
688
  setLastRequest,
453
689
  setIsAudioRecording,
454
- evaluationStrategy,
455
690
  hasThinkings,
456
691
  attachments,
457
692
  addAttachment,