@alquimia-ai/tools 2.0.1 → 2.2.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.
- package/dist/actions/index.d.mts +2 -7
- package/dist/actions/index.d.ts +2 -7
- package/dist/actions/index.js +10 -8
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/index.mjs +10 -8
- package/dist/actions/index.mjs.map +1 -1
- package/dist/adapters/fetch.d.mts +2 -1
- package/dist/adapters/fetch.d.ts +2 -1
- package/dist/adapters/fetch.js +6 -4
- package/dist/adapters/fetch.js.map +1 -1
- package/dist/adapters/fetch.mjs +6 -4
- package/dist/adapters/fetch.mjs.map +1 -1
- package/dist/adapters/index.d.mts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/next.d.mts +2 -1
- package/dist/adapters/next.d.ts +2 -1
- package/dist/adapters/next.js +7 -5
- package/dist/adapters/next.js.map +1 -1
- package/dist/adapters/next.mjs +7 -5
- package/dist/adapters/next.mjs.map +1 -1
- package/dist/hooks/index.d.mts +5 -3
- package/dist/hooks/index.d.ts +5 -3
- package/dist/hooks/index.js +266 -65
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +248 -47
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/next/index.d.mts +6 -9
- package/dist/next/index.d.ts +6 -9
- package/dist/next/index.js +69 -64
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +69 -64
- package/dist/next/index.mjs.map +1 -1
- package/dist/proxy.d.mts +2 -2
- package/dist/proxy.d.ts +2 -2
- package/dist/proxy.js +32 -9
- package/dist/proxy.js.map +1 -1
- package/dist/proxy.mjs +32 -9
- package/dist/proxy.mjs.map +1 -1
- package/dist/sdk/index.d.mts +15 -7
- package/dist/sdk/index.d.ts +15 -7
- package/dist/sdk/index.js +45 -26
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/index.mjs +45 -26
- package/dist/sdk/index.mjs.map +1 -1
- package/dist/session.action-DirvOWt0.d.mts +3 -0
- package/dist/session.action-DirvOWt0.d.ts +3 -0
- package/dist/types/index.d.mts +79 -18
- package/dist/types/index.d.ts +79 -18
- package/dist/types/index.js.map +1 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/types-CIqszY3g.d.mts +53 -0
- package/dist/types-CIqszY3g.d.ts +53 -0
- package/dist/worklog/index.d.mts +29 -0
- package/dist/worklog/index.d.ts +29 -0
- package/dist/worklog/index.js +218 -0
- package/dist/worklog/index.js.map +1 -0
- package/dist/worklog/index.mjs +195 -0
- package/dist/worklog/index.mjs.map +1 -0
- package/package.json +6 -1
package/dist/hooks/index.mjs
CHANGED
|
@@ -7,12 +7,11 @@ var AlquimiaSDK = class {
|
|
|
7
7
|
constructor(assistantId, adapter, options = {}) {
|
|
8
8
|
this.conversationId = null;
|
|
9
9
|
this.sessionId = null;
|
|
10
|
+
// Internal subscription id from infer (`taskid` on the wire).
|
|
10
11
|
this.streamId = null;
|
|
11
|
-
this.evaluationStrategy = null;
|
|
12
12
|
this.tools = [];
|
|
13
|
-
this.
|
|
13
|
+
this.extraInstructions = null;
|
|
14
14
|
this.assistantConfig = null;
|
|
15
|
-
this.forceProfile = {};
|
|
16
15
|
this.userId = null;
|
|
17
16
|
this.attachments = [];
|
|
18
17
|
this.attachmentResponses = [];
|
|
@@ -78,12 +77,8 @@ var AlquimiaSDK = class {
|
|
|
78
77
|
this.tools = tools;
|
|
79
78
|
return this;
|
|
80
79
|
}
|
|
81
|
-
|
|
82
|
-
this.
|
|
83
|
-
return this;
|
|
84
|
-
}
|
|
85
|
-
withForceProfile(forceProfile) {
|
|
86
|
-
this.forceProfile = forceProfile;
|
|
80
|
+
withExtraInstructions(extraInstructions) {
|
|
81
|
+
this.extraInstructions = extraInstructions;
|
|
87
82
|
return this;
|
|
88
83
|
}
|
|
89
84
|
withAssistantConfig(assistantConfig) {
|
|
@@ -97,9 +92,6 @@ var AlquimiaSDK = class {
|
|
|
97
92
|
getEnforceCharacterization() {
|
|
98
93
|
return this.enforceCharacterization ?? true;
|
|
99
94
|
}
|
|
100
|
-
getEvaluationStrategy() {
|
|
101
|
-
return this.evaluationStrategy;
|
|
102
|
-
}
|
|
103
95
|
textToSpeech(text) {
|
|
104
96
|
if (!this.whisperProvider) {
|
|
105
97
|
throw new Error("Whisper provider not initialized");
|
|
@@ -120,25 +112,29 @@ var AlquimiaSDK = class {
|
|
|
120
112
|
}
|
|
121
113
|
const inferUrl = this.adapter.resolveInferUrl(this.assistantId);
|
|
122
114
|
const adapterHeaders = this.adapter.getHeaders?.() ?? {};
|
|
115
|
+
const hasClientTools = Array.isArray(this.tools) && this.tools.length > 0;
|
|
123
116
|
const initMessage = {
|
|
124
117
|
query,
|
|
125
118
|
session_id: this.conversationId,
|
|
126
|
-
...this.extraData && { extra_data: this.extraData },
|
|
127
|
-
force_profile: this.forceProfile,
|
|
128
|
-
...this.assistantConfig && { config: this.assistantConfig },
|
|
129
|
-
tools: this.tools,
|
|
130
119
|
user_id: this.userId,
|
|
131
|
-
|
|
120
|
+
...this.extraInstructions && { extra_instructions: this.extraInstructions },
|
|
121
|
+
...this.assistantConfig && { config: this.assistantConfig },
|
|
122
|
+
...hasClientTools && {
|
|
123
|
+
evaluation_strategy: {
|
|
124
|
+
evaluation_strategy_id: "native",
|
|
125
|
+
tool_schemas: this.tools
|
|
126
|
+
}
|
|
127
|
+
}
|
|
132
128
|
};
|
|
133
129
|
const result = (await this.axiosInstance.post(inferUrl, initMessage, {
|
|
134
130
|
headers: {
|
|
135
131
|
"Content-Type": "application/json",
|
|
136
132
|
"x-trace-parent": traceParent || "",
|
|
137
|
-
...adapterHeaders
|
|
133
|
+
...adapterHeaders,
|
|
134
|
+
...this.buildIdentityHeaders()
|
|
138
135
|
}
|
|
139
136
|
})).data;
|
|
140
|
-
this.
|
|
141
|
-
this.streamId = result.stream_id;
|
|
137
|
+
this.streamId = result.taskid ?? null;
|
|
142
138
|
this.attachmentResponses = result.attachments ?? [];
|
|
143
139
|
this.attachments = [];
|
|
144
140
|
return this;
|
|
@@ -173,21 +169,40 @@ var AlquimiaSDK = class {
|
|
|
173
169
|
}
|
|
174
170
|
return this.loggerProvider.logError(message, error, data);
|
|
175
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* @deprecated The runtime no longer returns attachment IDs from the infer
|
|
174
|
+
* response — attachments are uploaded as standalone blobs and linked to the
|
|
175
|
+
* session via headers. Always returns `[]`; kept for source compatibility.
|
|
176
|
+
*/
|
|
176
177
|
getAttachmentResponses() {
|
|
177
178
|
return this.attachmentResponses;
|
|
178
179
|
}
|
|
179
|
-
async uploadAttachment(file,
|
|
180
|
-
|
|
181
|
-
throw new Error("Stream or attachment ID not initialized");
|
|
182
|
-
}
|
|
183
|
-
const url = this.adapter.resolveAttachmentUrl(this.streamId, attachmentId);
|
|
180
|
+
async uploadAttachment(file, _attachmentId) {
|
|
181
|
+
const url = this.adapter.resolveBlobUploadUrl();
|
|
184
182
|
const adapterHeaders = this.adapter.getHeaders?.() ?? {};
|
|
185
183
|
const formData = new FormData();
|
|
186
184
|
formData.append("file", file);
|
|
187
185
|
await this.axiosInstance.post(url, formData, {
|
|
188
|
-
headers: {
|
|
186
|
+
headers: {
|
|
187
|
+
"Content-Type": "multipart/form-data",
|
|
188
|
+
...adapterHeaders,
|
|
189
|
+
...this.buildIdentityHeaders()
|
|
190
|
+
}
|
|
189
191
|
});
|
|
190
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Identity headers (kebab-case) required by `/context/blob/upload` and
|
|
195
|
+
* the rest of the runtime's internal endpoints introduced in v0.2.0→next.
|
|
196
|
+
*/
|
|
197
|
+
buildIdentityHeaders() {
|
|
198
|
+
const headers = {
|
|
199
|
+
"assistant-id": this.assistantId
|
|
200
|
+
};
|
|
201
|
+
if (this.conversationId) headers["session-id"] = this.conversationId;
|
|
202
|
+
if (this.userId) headers["user-id"] = this.userId;
|
|
203
|
+
if (this.streamId) headers["task-id"] = this.streamId;
|
|
204
|
+
return headers;
|
|
205
|
+
}
|
|
191
206
|
getUrlStream() {
|
|
192
207
|
if (!this.streamId) {
|
|
193
208
|
throw new Error("Stream ID not initialized. Call sendMessage() first");
|
|
@@ -197,6 +212,10 @@ var AlquimiaSDK = class {
|
|
|
197
212
|
getStreamId() {
|
|
198
213
|
return this.streamId;
|
|
199
214
|
}
|
|
215
|
+
/** Alias for {@link getStreamId} — same value as infer `taskid`. */
|
|
216
|
+
getTaskId() {
|
|
217
|
+
return this.streamId;
|
|
218
|
+
}
|
|
200
219
|
};
|
|
201
220
|
var alquimia_sdk_default = AlquimiaSDK;
|
|
202
221
|
|
|
@@ -282,6 +301,166 @@ function mergeToolEvents(initial, toolEvents) {
|
|
|
282
301
|
);
|
|
283
302
|
}
|
|
284
303
|
|
|
304
|
+
// src/worklog/types.ts
|
|
305
|
+
function initialWorklogState(taskId = null) {
|
|
306
|
+
return { taskId, status: "idle", answer: null, nodes: [], index: {}, raw: [] };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// src/worklog/registry.ts
|
|
310
|
+
var asRecord = (data) => data && typeof data === "object" ? data : {};
|
|
311
|
+
var toolTitle = (r) => {
|
|
312
|
+
const name = asRecord(r.data).name;
|
|
313
|
+
return typeof name === "string" && name.length > 0 ? `Tool: ${name}` : "Tool";
|
|
314
|
+
};
|
|
315
|
+
var agentTitle = (r) => {
|
|
316
|
+
const name = asRecord(r.data).name;
|
|
317
|
+
return typeof name === "string" && name.length > 0 ? `Agent: ${name}` : "Agent-to-agent";
|
|
318
|
+
};
|
|
319
|
+
var constTitle = (label) => () => label;
|
|
320
|
+
var EVENT_REGISTRY = {
|
|
321
|
+
// Run envelope
|
|
322
|
+
AssistantInference: { kind: "answer", role: "run-open", title: constTitle("Inference started") },
|
|
323
|
+
AssistantInferenceResponse: { kind: "answer", role: "run-close", title: constTitle("Answer") },
|
|
324
|
+
// Safeguard
|
|
325
|
+
ShieldInference: { kind: "safeguard", role: "open", title: constTitle("Safeguard") },
|
|
326
|
+
ShieldInferenceResponse: { kind: "safeguard", role: "close", title: constTitle("Safeguard") },
|
|
327
|
+
// Reasoning
|
|
328
|
+
ResponseInference: { kind: "reasoning", role: "open", title: constTitle("Reasoning") },
|
|
329
|
+
ResponseInferenceResponse: { kind: "reasoning", role: "close", title: constTitle("Reasoning") },
|
|
330
|
+
// Tools (server + subclasses) and their responses
|
|
331
|
+
ServerToolExecution: { kind: "tool", role: "open", title: toolTitle },
|
|
332
|
+
BuiltinToolExecution: { kind: "tool", role: "open", title: toolTitle },
|
|
333
|
+
UnknownToolExecution: { kind: "tool", role: "open", title: toolTitle },
|
|
334
|
+
ClientToolExecution: { kind: "tool", role: "open", title: toolTitle, pending: true },
|
|
335
|
+
ToolExecutionResponse: { kind: "tool", role: "close", title: toolTitle },
|
|
336
|
+
BuiltinToolExecutionResponse: { kind: "tool", role: "close", title: toolTitle },
|
|
337
|
+
// Tool schema discovery
|
|
338
|
+
ToolSchema: { kind: "tool", role: "open", title: constTitle("Tool schema") },
|
|
339
|
+
ToolSchemaResponse: { kind: "tool", role: "close", title: constTitle("Tool schema") },
|
|
340
|
+
// Agent-to-agent
|
|
341
|
+
A2AInference: { kind: "a2a", role: "open", title: agentTitle },
|
|
342
|
+
AgentDiscovery: { kind: "a2a", role: "open", title: constTitle("Agent discovery") },
|
|
343
|
+
AgentDiscoveryResponse: { kind: "a2a", role: "close", title: constTitle("Agent discovery") },
|
|
344
|
+
// Memory / persistence
|
|
345
|
+
ContextPersistence: { kind: "memory", role: "open", title: constTitle("Memory persistence") },
|
|
346
|
+
ContextFlush: { kind: "memory", role: "open", title: constTitle("Memory flush") },
|
|
347
|
+
ContextFlushResponse: { kind: "memory", role: "close", title: constTitle("Memory flush") },
|
|
348
|
+
// Human approval
|
|
349
|
+
HumanApprovalRequired: {
|
|
350
|
+
kind: "tool",
|
|
351
|
+
role: "open",
|
|
352
|
+
title: constTitle("Human approval required"),
|
|
353
|
+
pending: true
|
|
354
|
+
},
|
|
355
|
+
HumanApprovalRequiredResponse: { kind: "tool", role: "close", title: constTitle("Human approval") }
|
|
356
|
+
};
|
|
357
|
+
function resolveInterpreter(eventClass) {
|
|
358
|
+
if (Object.prototype.hasOwnProperty.call(EVENT_REGISTRY, eventClass)) {
|
|
359
|
+
return EVENT_REGISTRY[eventClass];
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
kind: "unknown",
|
|
363
|
+
role: "open",
|
|
364
|
+
title: (r) => r.event_class
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// src/worklog/reducer.ts
|
|
369
|
+
var asString = (v) => typeof v === "string" ? v : v == null ? "" : JSON.stringify(v);
|
|
370
|
+
var nodeDepth = (record) => {
|
|
371
|
+
const d = record.data && typeof record.data === "object" ? record.data.depth : void 0;
|
|
372
|
+
return typeof d === "number" ? d : 0;
|
|
373
|
+
};
|
|
374
|
+
var makeOpenNode = (record, interp, id) => ({
|
|
375
|
+
id,
|
|
376
|
+
kind: interp.kind,
|
|
377
|
+
eventClass: record.event_class,
|
|
378
|
+
status: interp.pending ? "pending" : "running",
|
|
379
|
+
title: interp.title(record),
|
|
380
|
+
startedAt: record.date_submitted,
|
|
381
|
+
depth: nodeDepth(record),
|
|
382
|
+
children: [],
|
|
383
|
+
command: record.data,
|
|
384
|
+
raw: [record]
|
|
385
|
+
});
|
|
386
|
+
var makeClosedNode = (record, interp, id) => ({
|
|
387
|
+
id,
|
|
388
|
+
kind: interp.kind,
|
|
389
|
+
eventClass: record.event_class,
|
|
390
|
+
status: record.status === "error" ? "failed" : "completed",
|
|
391
|
+
title: interp.title(record),
|
|
392
|
+
startedAt: record.date_submitted,
|
|
393
|
+
endedAt: record.date_submitted,
|
|
394
|
+
depth: nodeDepth(record),
|
|
395
|
+
children: [],
|
|
396
|
+
response: record.data,
|
|
397
|
+
error: record.status === "error" ? asString(record.data) : void 0,
|
|
398
|
+
raw: [record]
|
|
399
|
+
});
|
|
400
|
+
function reduceWorklog(state, record) {
|
|
401
|
+
const interp = resolveInterpreter(record.event_class);
|
|
402
|
+
const next = {
|
|
403
|
+
...state,
|
|
404
|
+
nodes: state.nodes.slice(),
|
|
405
|
+
index: { ...state.index },
|
|
406
|
+
raw: [...state.raw, record]
|
|
407
|
+
};
|
|
408
|
+
if (interp.role === "ignore") return next;
|
|
409
|
+
if (interp.role === "run-open") {
|
|
410
|
+
next.status = "running";
|
|
411
|
+
return next;
|
|
412
|
+
}
|
|
413
|
+
if (interp.role === "run-close") {
|
|
414
|
+
next.answer = asString(record.data) || null;
|
|
415
|
+
next.status = record.status === "error" ? "error" : "success";
|
|
416
|
+
return next;
|
|
417
|
+
}
|
|
418
|
+
const key = record.control_id ?? `${record.event_class}-${next.raw.length}`;
|
|
419
|
+
if (interp.role === "close") {
|
|
420
|
+
const pos2 = Object.prototype.hasOwnProperty.call(next.index, key) ? next.index[key] : void 0;
|
|
421
|
+
if (pos2 != null) {
|
|
422
|
+
const existing = next.nodes[pos2];
|
|
423
|
+
next.nodes[pos2] = {
|
|
424
|
+
...existing,
|
|
425
|
+
status: record.status === "error" ? "failed" : "completed",
|
|
426
|
+
endedAt: record.date_submitted,
|
|
427
|
+
response: record.data,
|
|
428
|
+
error: record.status === "error" ? asString(record.data) : existing.error,
|
|
429
|
+
raw: [...existing.raw, record]
|
|
430
|
+
};
|
|
431
|
+
} else {
|
|
432
|
+
next.index[key] = next.nodes.length;
|
|
433
|
+
next.nodes.push(makeClosedNode(record, interp, key));
|
|
434
|
+
}
|
|
435
|
+
if (record.status === "error") next.status = "error";
|
|
436
|
+
return next;
|
|
437
|
+
}
|
|
438
|
+
const pos = Object.prototype.hasOwnProperty.call(next.index, key) ? next.index[key] : void 0;
|
|
439
|
+
if (pos != null) {
|
|
440
|
+
const existing = next.nodes[pos];
|
|
441
|
+
next.nodes[pos] = { ...existing, raw: [...existing.raw, record] };
|
|
442
|
+
} else {
|
|
443
|
+
next.index[key] = next.nodes.length;
|
|
444
|
+
next.nodes.push(makeOpenNode(record, interp, key));
|
|
445
|
+
}
|
|
446
|
+
return next;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// src/worklog/use-worklog.ts
|
|
450
|
+
import { useCallback, useReducer } from "react";
|
|
451
|
+
|
|
452
|
+
// src/worklog/from-frame.ts
|
|
453
|
+
function frameToRecord(frame) {
|
|
454
|
+
const status = frame.status === "success" || frame.status === "error" ? frame.status : null;
|
|
455
|
+
return {
|
|
456
|
+
event_class: typeof frame.event_class === "string" && frame.event_class.length > 0 ? frame.event_class : "Unknown",
|
|
457
|
+
control_id: frame.control_id ?? null,
|
|
458
|
+
data: frame.data,
|
|
459
|
+
status,
|
|
460
|
+
date_submitted: typeof frame.date_submitted === "string" ? frame.date_submitted : ""
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
285
464
|
// src/hooks/alquimia.hook.tsx
|
|
286
465
|
function useAlquimia(config) {
|
|
287
466
|
const sdk = useMemo(() => {
|
|
@@ -294,7 +473,7 @@ function useAlquimia(config) {
|
|
|
294
473
|
if (config.providers?.ratings) instance.withRatingsProvider(config.providers.ratings);
|
|
295
474
|
if (config.providers?.logger) instance.withLoggerProvider(config.providers.logger);
|
|
296
475
|
if (config.options?.userId) instance.withUserId(config.options.userId);
|
|
297
|
-
if (config.options?.
|
|
476
|
+
if (config.options?.extraInstructions) instance.withExtraInstructions(config.options.extraInstructions);
|
|
298
477
|
return instance;
|
|
299
478
|
}, [config.assistantId, config.adapter]);
|
|
300
479
|
const [input, setInput] = useState("");
|
|
@@ -305,11 +484,15 @@ function useAlquimia(config) {
|
|
|
305
484
|
const [isAudioRecording, setIsAudioRecording] = useState(false);
|
|
306
485
|
const [messages, setMessages] = useState([]);
|
|
307
486
|
const eventSourceRef = useRef(null);
|
|
487
|
+
const streamUserCancelledRef = useRef(false);
|
|
308
488
|
const [sessionId, setSessionId] = useState(null);
|
|
309
489
|
const [activeTool, setActiveTool] = useState(null);
|
|
310
490
|
const [lastRequest, setLastRequest] = useState(null);
|
|
311
|
-
const [evaluationStrategy, setEvaluationStrategy] = useState("");
|
|
312
491
|
const [hasThinkings, setHasThinkings] = useState(false);
|
|
492
|
+
const worklogEnabled = config.options?.worklog ?? false;
|
|
493
|
+
const [worklog, setWorklog] = useState(
|
|
494
|
+
worklogEnabled ? initialWorklogState() : void 0
|
|
495
|
+
);
|
|
313
496
|
const [attachments, setAttachments] = useState([]);
|
|
314
497
|
const [isUploadingAttachments, setIsUploadingAttachments] = useState(false);
|
|
315
498
|
const isLoading = isMessageLoading || isStreamingLoading || isUploadingAttachments;
|
|
@@ -329,7 +512,7 @@ function useAlquimia(config) {
|
|
|
329
512
|
function clearAttachments() {
|
|
330
513
|
setAttachments([]);
|
|
331
514
|
}
|
|
332
|
-
function processMessageChunk(messageId, chunk, error_code, error_detail,
|
|
515
|
+
function processMessageChunk(messageId, chunk, error_code, error_detail, taskid, additionalInfo, loading, tooler, thinkings) {
|
|
333
516
|
setMessages((currentMessages) => {
|
|
334
517
|
const messageIndex = currentMessages.findIndex((message) => message?.id === messageId);
|
|
335
518
|
if (messageIndex !== -1) {
|
|
@@ -341,7 +524,7 @@ function useAlquimia(config) {
|
|
|
341
524
|
role: updatedMessages[messageIndex]?.role || "assistant",
|
|
342
525
|
error_code,
|
|
343
526
|
error_detail,
|
|
344
|
-
|
|
527
|
+
taskid,
|
|
345
528
|
additionalInfo,
|
|
346
529
|
created_at: (/* @__PURE__ */ new Date()).getTime().toString(),
|
|
347
530
|
loading,
|
|
@@ -362,7 +545,7 @@ function useAlquimia(config) {
|
|
|
362
545
|
id: messageId,
|
|
363
546
|
error_code,
|
|
364
547
|
error_detail,
|
|
365
|
-
|
|
548
|
+
taskid,
|
|
366
549
|
created_at: (/* @__PURE__ */ new Date()).getTime().toString(),
|
|
367
550
|
loading,
|
|
368
551
|
tooler: mergeToolEvents([], tooler),
|
|
@@ -384,7 +567,7 @@ function useAlquimia(config) {
|
|
|
384
567
|
chunk?.answer || "",
|
|
385
568
|
chunk?.error_code,
|
|
386
569
|
chunk?.error_detail,
|
|
387
|
-
chunk?.
|
|
570
|
+
chunk?.taskid,
|
|
388
571
|
options?.additionalInfo,
|
|
389
572
|
chunk?.loading,
|
|
390
573
|
chunk?.tooler,
|
|
@@ -424,6 +607,7 @@ function useAlquimia(config) {
|
|
|
424
607
|
setMessages(messages2);
|
|
425
608
|
}
|
|
426
609
|
function handleLoadingCancel() {
|
|
610
|
+
streamUserCancelledRef.current = true;
|
|
427
611
|
eventSourceRef.current?.close();
|
|
428
612
|
eventSourceRef.current = null;
|
|
429
613
|
setIsMessageLoading(false);
|
|
@@ -505,6 +689,7 @@ function useAlquimia(config) {
|
|
|
505
689
|
}
|
|
506
690
|
const streamUrl = response.getUrlStream();
|
|
507
691
|
const streamId = response.getStreamId() || "";
|
|
692
|
+
streamUserCancelledRef.current = false;
|
|
508
693
|
const streamState = {
|
|
509
694
|
streamId,
|
|
510
695
|
connectedAt: Date.now(),
|
|
@@ -513,10 +698,9 @@ function useAlquimia(config) {
|
|
|
513
698
|
lastMessageAt: null,
|
|
514
699
|
closedByClient: false
|
|
515
700
|
};
|
|
701
|
+
if (worklogEnabled) setWorklog(initialWorklogState());
|
|
516
702
|
const eventSource = new EventSource(streamUrl);
|
|
517
703
|
eventSourceRef.current = eventSource;
|
|
518
|
-
const evaluationStrategy2 = response.getEvaluationStrategy();
|
|
519
|
-
setEvaluationStrategy(evaluationStrategy2);
|
|
520
704
|
eventSource.onopen = () => {
|
|
521
705
|
streamState.openedAt = Date.now();
|
|
522
706
|
};
|
|
@@ -527,23 +711,37 @@ function useAlquimia(config) {
|
|
|
527
711
|
};
|
|
528
712
|
eventSource.onerror = () => {
|
|
529
713
|
if (streamState.closedByClient) return;
|
|
714
|
+
if (streamUserCancelledRef.current) {
|
|
715
|
+
streamUserCancelledRef.current = false;
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
530
718
|
streamState.closedByClient = true;
|
|
531
719
|
const elapsed = Date.now() - streamState.connectedAt;
|
|
532
720
|
const sinceLastMessage = streamState.lastMessageAt ? Date.now() - streamState.lastMessageAt : null;
|
|
533
721
|
cleanup(false, eventSource);
|
|
534
722
|
let errorDetail;
|
|
535
723
|
if (!streamState.openedAt) {
|
|
536
|
-
errorDetail =
|
|
724
|
+
errorDetail = "Could not open the live response. Check your connection and try again.";
|
|
537
725
|
} else if (streamState.messagesReceived === 0) {
|
|
538
|
-
errorDetail =
|
|
726
|
+
errorDetail = "No response was received. Try again in a moment.";
|
|
539
727
|
} else {
|
|
540
|
-
errorDetail =
|
|
728
|
+
errorDetail = "The response was interrupted. Try again.";
|
|
729
|
+
}
|
|
730
|
+
if (typeof console !== "undefined" && console.debug) {
|
|
731
|
+
console.debug("[Alquimia] SSE transport error", {
|
|
732
|
+
streamUrl,
|
|
733
|
+
taskId: streamId,
|
|
734
|
+
opened: Boolean(streamState.openedAt),
|
|
735
|
+
messagesReceived: streamState.messagesReceived,
|
|
736
|
+
elapsedMs: elapsed,
|
|
737
|
+
sinceLastMessageMs: sinceLastMessage
|
|
738
|
+
});
|
|
541
739
|
}
|
|
542
740
|
callBack({
|
|
543
741
|
type: "error",
|
|
544
742
|
error_code: "STREAM_ERROR",
|
|
545
743
|
error_detail: errorDetail,
|
|
546
|
-
|
|
744
|
+
taskid: streamId
|
|
547
745
|
});
|
|
548
746
|
};
|
|
549
747
|
} catch (error) {
|
|
@@ -554,13 +752,17 @@ function useAlquimia(config) {
|
|
|
554
752
|
setStreamingMessageId(null);
|
|
555
753
|
callBack({
|
|
556
754
|
type: "error",
|
|
557
|
-
error_code: error.status
|
|
755
|
+
error_code: error.response?.status != null ? String(error.response.status) : "REQUEST_ERROR",
|
|
558
756
|
error_detail: errMessage
|
|
559
757
|
});
|
|
560
758
|
}
|
|
561
759
|
}
|
|
562
760
|
function handleMessageEvent(event, callBack, eventSource, streamState) {
|
|
563
761
|
const data = JSON.parse(event.data);
|
|
762
|
+
if (worklogEnabled) {
|
|
763
|
+
setWorklog((prev) => reduceWorklog(prev ?? initialWorklogState(), frameToRecord(data)));
|
|
764
|
+
}
|
|
765
|
+
const eventTaskId = data.taskid || "";
|
|
564
766
|
if (data.errors?.length) {
|
|
565
767
|
for (const error of data.errors) {
|
|
566
768
|
const detail = error.error_detail || (error.data != null ? `${error.data} (controlId: ${error.control_id})` : "Unknown error");
|
|
@@ -568,7 +770,7 @@ function useAlquimia(config) {
|
|
|
568
770
|
type: "error",
|
|
569
771
|
error_code: error.event_class || error.status || "UNKNOWN_ERROR",
|
|
570
772
|
error_detail: detail,
|
|
571
|
-
|
|
773
|
+
taskid: eventTaskId
|
|
572
774
|
});
|
|
573
775
|
}
|
|
574
776
|
if (streamState) streamState.closedByClient = true;
|
|
@@ -582,10 +784,9 @@ function useAlquimia(config) {
|
|
|
582
784
|
setHasThinkings(true);
|
|
583
785
|
callBack({ type: "answer", thinkings: data.thinkings });
|
|
584
786
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
callBack({ type: "answer", answer: content });
|
|
787
|
+
if (data.event_class === "AssistantInferenceResponse") {
|
|
788
|
+
const final = data;
|
|
789
|
+
callBack({ type: "answer", answer: final.data });
|
|
589
790
|
if (streamState) streamState.closedByClient = true;
|
|
590
791
|
cleanup(false, eventSource);
|
|
591
792
|
}
|
|
@@ -617,8 +818,8 @@ function useAlquimia(config) {
|
|
|
617
818
|
setSessionId,
|
|
618
819
|
setLastRequest,
|
|
619
820
|
setIsAudioRecording,
|
|
620
|
-
evaluationStrategy,
|
|
621
821
|
hasThinkings,
|
|
822
|
+
worklog,
|
|
622
823
|
attachments,
|
|
623
824
|
addAttachment,
|
|
624
825
|
addAttachments,
|
|
@@ -629,7 +830,7 @@ function useAlquimia(config) {
|
|
|
629
830
|
}
|
|
630
831
|
|
|
631
832
|
// src/hooks/useRatings.ts
|
|
632
|
-
import { useState as useState2, useReducer } from "react";
|
|
833
|
+
import { useState as useState2, useReducer as useReducer2 } from "react";
|
|
633
834
|
var initialState = {
|
|
634
835
|
ratingStars: 0,
|
|
635
836
|
ratingThumbs: "",
|
|
@@ -650,7 +851,7 @@ function ratingReducer(state, action) {
|
|
|
650
851
|
function useRatings({ assistantId, sendRating, topicId }) {
|
|
651
852
|
const [isLoading, setIsLoading] = useState2(false);
|
|
652
853
|
const [hasReviewed, setHasReviewed] = useState2(false);
|
|
653
|
-
const [state, dispatch] =
|
|
854
|
+
const [state, dispatch] = useReducer2(ratingReducer, initialState);
|
|
654
855
|
const setRatingStars = (rating) => {
|
|
655
856
|
dispatch({ type: "SET_RATING_STARS", payload: rating });
|
|
656
857
|
};
|