@alquimia-ai/tools 2.1.0 → 2.3.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 +1 -0
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/index.mjs.map +1 -1
- package/dist/actions-BebMyGqF.d.ts +16 -0
- package/dist/actions-Ca3ro-hX.d.mts +16 -0
- package/dist/adapters/fetch.d.mts +2 -0
- package/dist/adapters/fetch.d.ts +2 -0
- package/dist/adapters/fetch.js +7 -1
- package/dist/adapters/fetch.js.map +1 -1
- package/dist/adapters/fetch.mjs +7 -1
- package/dist/adapters/fetch.mjs.map +1 -1
- package/dist/adapters/index.d.mts +1 -0
- package/dist/adapters/index.d.ts +1 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/next.d.mts +2 -0
- package/dist/adapters/next.d.ts +2 -0
- package/dist/adapters/next.js +7 -1
- package/dist/adapters/next.js.map +1 -1
- package/dist/adapters/next.mjs +7 -1
- package/dist/adapters/next.mjs.map +1 -1
- package/dist/genui/index.d.mts +3027 -0
- package/dist/genui/index.d.ts +3027 -0
- package/dist/genui/index.js +3344 -0
- package/dist/genui/index.js.map +1 -0
- package/dist/genui/index.mjs +3321 -0
- package/dist/genui/index.mjs.map +1 -0
- package/dist/hooks/index.d.mts +26 -1
- package/dist/hooks/index.d.ts +26 -1
- package/dist/hooks/index.js +650 -21
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +632 -3
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/next/index.d.mts +7 -0
- package/dist/next/index.d.ts +7 -0
- package/dist/next/index.js +50 -0
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +50 -0
- package/dist/next/index.mjs.map +1 -1
- package/dist/providers/index.d.mts +3 -2
- package/dist/providers/index.d.ts +3 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/index.mjs.map +1 -1
- package/dist/proxy.d.mts +2 -0
- package/dist/proxy.d.ts +2 -0
- package/dist/proxy.js +41 -0
- package/dist/proxy.js.map +1 -1
- package/dist/proxy.mjs +41 -0
- package/dist/proxy.mjs.map +1 -1
- package/dist/registry-Bcu_ZYL1.d.mts +19 -0
- package/dist/registry-Bcu_ZYL1.d.ts +19 -0
- package/dist/sdk/index.d.mts +10 -0
- package/dist/sdk/index.d.ts +10 -0
- package/dist/sdk/index.js +26 -0
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/index.mjs +26 -0
- package/dist/sdk/index.mjs.map +1 -1
- package/dist/services/index.d.mts +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/types/index.d.mts +10 -1
- package/dist/types/index.d.ts +10 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/types-DnfWUE9V.d.mts +56 -0
- package/dist/types-DnfWUE9V.d.ts +56 -0
- package/dist/types-Dvu9y4WM.d.mts +53 -0
- package/dist/types-Dvu9y4WM.d.ts +53 -0
- package/dist/utils/index.d.mts +6 -2
- package/dist/utils/index.d.ts +6 -2
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +4 -0
- package/dist/utils/index.mjs.map +1 -1
- 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 +24 -7
package/dist/hooks/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/hooks/alquimia.hook.tsx
|
|
2
|
-
import { useMemo, useRef, useState } from "react";
|
|
2
|
+
import { useCallback as useCallback2, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
|
|
4
4
|
// src/sdk/alquimia-sdk.ts
|
|
5
5
|
import axios from "axios";
|
|
@@ -139,6 +139,32 @@ var AlquimiaSDK = class {
|
|
|
139
139
|
this.attachments = [];
|
|
140
140
|
return this;
|
|
141
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Complete a pending client-tool execution (the missing "submit half" of the
|
|
144
|
+
* client-tool loop). POSTs a {@link ToolExecutionResponse} to the runtime's
|
|
145
|
+
* `/event/tool-completion`. For interactive `render_ui` surfaces `result` is
|
|
146
|
+
* the user's data; for display-only surfaces the SDK sends `{ shown: true }`.
|
|
147
|
+
* The pending call is correlated by `control_id` in the body + the
|
|
148
|
+
* `context-metadata` header (taskid + sessionid).
|
|
149
|
+
*/
|
|
150
|
+
async submitToolResult(response) {
|
|
151
|
+
const url = this.adapter.resolveToolCompletionUrl?.();
|
|
152
|
+
if (!url) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
"AlquimiaSDK: adapter does not support tool completion (resolveToolCompletionUrl missing)"
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const adapterHeaders = this.adapter.getHeaders?.() ?? {};
|
|
158
|
+
const headers = {
|
|
159
|
+
"Content-Type": "application/json",
|
|
160
|
+
assistantid: this.assistantId,
|
|
161
|
+
...this.streamId && { taskid: this.streamId },
|
|
162
|
+
...this.conversationId && { sessionid: this.conversationId },
|
|
163
|
+
...this.userId && { userid: this.userId },
|
|
164
|
+
...adapterHeaders
|
|
165
|
+
};
|
|
166
|
+
await this.axiosInstance.post(url, response, { headers });
|
|
167
|
+
}
|
|
142
168
|
async generateImage(query) {
|
|
143
169
|
if (!this.stableDiffusionProvider) {
|
|
144
170
|
throw new Error("Stable Diffusion provider not initialized");
|
|
@@ -300,6 +326,501 @@ function mergeToolEvents(initial, toolEvents) {
|
|
|
300
326
|
initial
|
|
301
327
|
);
|
|
302
328
|
}
|
|
329
|
+
function resolveGenuiAllow(catalog, allow) {
|
|
330
|
+
return !allow || allow === "all" ? Object.keys(catalog.components) : allow;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/worklog/types.ts
|
|
334
|
+
function initialWorklogState(taskId = null) {
|
|
335
|
+
return { taskId, status: "idle", answer: null, nodes: [], index: {}, raw: [] };
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/worklog/registry.ts
|
|
339
|
+
var asRecord = (data) => data && typeof data === "object" ? data : {};
|
|
340
|
+
var toolTitle = (r) => {
|
|
341
|
+
const name = asRecord(r.data).name;
|
|
342
|
+
return typeof name === "string" && name.length > 0 ? `Tool: ${name}` : "Tool";
|
|
343
|
+
};
|
|
344
|
+
var agentTitle = (r) => {
|
|
345
|
+
const name = asRecord(r.data).name;
|
|
346
|
+
return typeof name === "string" && name.length > 0 ? `Agent: ${name}` : "Agent-to-agent";
|
|
347
|
+
};
|
|
348
|
+
var constTitle = (label) => () => label;
|
|
349
|
+
var EVENT_REGISTRY = {
|
|
350
|
+
// Run envelope
|
|
351
|
+
AssistantInference: { kind: "answer", role: "run-open", title: constTitle("Inference started") },
|
|
352
|
+
AssistantInferenceResponse: { kind: "answer", role: "run-close", title: constTitle("Answer") },
|
|
353
|
+
// Safeguard
|
|
354
|
+
ShieldInference: { kind: "safeguard", role: "open", title: constTitle("Safeguard") },
|
|
355
|
+
ShieldInferenceResponse: { kind: "safeguard", role: "close", title: constTitle("Safeguard") },
|
|
356
|
+
// Reasoning
|
|
357
|
+
ResponseInference: { kind: "reasoning", role: "open", title: constTitle("Reasoning") },
|
|
358
|
+
ResponseInferenceResponse: { kind: "reasoning", role: "close", title: constTitle("Reasoning") },
|
|
359
|
+
// Tools (server + subclasses) and their responses
|
|
360
|
+
ServerToolExecution: { kind: "tool", role: "open", title: toolTitle },
|
|
361
|
+
BuiltinToolExecution: { kind: "tool", role: "open", title: toolTitle },
|
|
362
|
+
UnknownToolExecution: { kind: "tool", role: "open", title: toolTitle },
|
|
363
|
+
ClientToolExecution: { kind: "tool", role: "open", title: toolTitle, pending: true },
|
|
364
|
+
ToolExecutionResponse: { kind: "tool", role: "close", title: toolTitle },
|
|
365
|
+
BuiltinToolExecutionResponse: { kind: "tool", role: "close", title: toolTitle },
|
|
366
|
+
// Tool schema discovery
|
|
367
|
+
ToolSchema: { kind: "tool", role: "open", title: constTitle("Tool schema") },
|
|
368
|
+
ToolSchemaResponse: { kind: "tool", role: "close", title: constTitle("Tool schema") },
|
|
369
|
+
// Agent-to-agent
|
|
370
|
+
A2AInference: { kind: "a2a", role: "open", title: agentTitle },
|
|
371
|
+
AgentDiscovery: { kind: "a2a", role: "open", title: constTitle("Agent discovery") },
|
|
372
|
+
AgentDiscoveryResponse: { kind: "a2a", role: "close", title: constTitle("Agent discovery") },
|
|
373
|
+
// Memory / persistence
|
|
374
|
+
ContextPersistence: { kind: "memory", role: "open", title: constTitle("Memory persistence") },
|
|
375
|
+
ContextFlush: { kind: "memory", role: "open", title: constTitle("Memory flush") },
|
|
376
|
+
ContextFlushResponse: { kind: "memory", role: "close", title: constTitle("Memory flush") },
|
|
377
|
+
// Human approval
|
|
378
|
+
HumanApprovalRequired: {
|
|
379
|
+
kind: "tool",
|
|
380
|
+
role: "open",
|
|
381
|
+
title: constTitle("Human approval required"),
|
|
382
|
+
pending: true
|
|
383
|
+
},
|
|
384
|
+
HumanApprovalRequiredResponse: { kind: "tool", role: "close", title: constTitle("Human approval") }
|
|
385
|
+
};
|
|
386
|
+
function resolveInterpreter(eventClass) {
|
|
387
|
+
if (Object.prototype.hasOwnProperty.call(EVENT_REGISTRY, eventClass)) {
|
|
388
|
+
return EVENT_REGISTRY[eventClass];
|
|
389
|
+
}
|
|
390
|
+
return {
|
|
391
|
+
kind: "unknown",
|
|
392
|
+
role: "open",
|
|
393
|
+
title: (r) => r.event_class
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// src/worklog/reducer.ts
|
|
398
|
+
var asString = (v) => typeof v === "string" ? v : v == null ? "" : JSON.stringify(v);
|
|
399
|
+
var nodeDepth = (record) => {
|
|
400
|
+
const d = record.data && typeof record.data === "object" ? record.data.depth : void 0;
|
|
401
|
+
return typeof d === "number" ? d : 0;
|
|
402
|
+
};
|
|
403
|
+
var makeOpenNode = (record, interp, id) => ({
|
|
404
|
+
id,
|
|
405
|
+
kind: interp.kind,
|
|
406
|
+
eventClass: record.event_class,
|
|
407
|
+
status: interp.pending ? "pending" : "running",
|
|
408
|
+
title: interp.title(record),
|
|
409
|
+
startedAt: record.date_submitted,
|
|
410
|
+
depth: nodeDepth(record),
|
|
411
|
+
children: [],
|
|
412
|
+
command: record.data,
|
|
413
|
+
raw: [record]
|
|
414
|
+
});
|
|
415
|
+
var makeClosedNode = (record, interp, id) => ({
|
|
416
|
+
id,
|
|
417
|
+
kind: interp.kind,
|
|
418
|
+
eventClass: record.event_class,
|
|
419
|
+
status: record.status === "error" ? "failed" : "completed",
|
|
420
|
+
title: interp.title(record),
|
|
421
|
+
startedAt: record.date_submitted,
|
|
422
|
+
endedAt: record.date_submitted,
|
|
423
|
+
depth: nodeDepth(record),
|
|
424
|
+
children: [],
|
|
425
|
+
response: record.data,
|
|
426
|
+
error: record.status === "error" ? asString(record.data) : void 0,
|
|
427
|
+
raw: [record]
|
|
428
|
+
});
|
|
429
|
+
function reduceWorklog(state, record) {
|
|
430
|
+
const interp = resolveInterpreter(record.event_class);
|
|
431
|
+
const next = {
|
|
432
|
+
...state,
|
|
433
|
+
nodes: state.nodes.slice(),
|
|
434
|
+
index: { ...state.index },
|
|
435
|
+
raw: [...state.raw, record]
|
|
436
|
+
};
|
|
437
|
+
if (interp.role === "ignore") return next;
|
|
438
|
+
if (interp.role === "run-open") {
|
|
439
|
+
next.status = "running";
|
|
440
|
+
return next;
|
|
441
|
+
}
|
|
442
|
+
if (interp.role === "run-close") {
|
|
443
|
+
next.answer = asString(record.data) || null;
|
|
444
|
+
next.status = record.status === "error" ? "error" : "success";
|
|
445
|
+
return next;
|
|
446
|
+
}
|
|
447
|
+
const key = record.control_id ?? `${record.event_class}-${next.raw.length}`;
|
|
448
|
+
if (interp.role === "close") {
|
|
449
|
+
const pos2 = Object.prototype.hasOwnProperty.call(next.index, key) ? next.index[key] : void 0;
|
|
450
|
+
if (pos2 != null) {
|
|
451
|
+
const existing = next.nodes[pos2];
|
|
452
|
+
next.nodes[pos2] = {
|
|
453
|
+
...existing,
|
|
454
|
+
status: record.status === "error" ? "failed" : "completed",
|
|
455
|
+
endedAt: record.date_submitted,
|
|
456
|
+
response: record.data,
|
|
457
|
+
error: record.status === "error" ? asString(record.data) : existing.error,
|
|
458
|
+
raw: [...existing.raw, record]
|
|
459
|
+
};
|
|
460
|
+
} else {
|
|
461
|
+
next.index[key] = next.nodes.length;
|
|
462
|
+
next.nodes.push(makeClosedNode(record, interp, key));
|
|
463
|
+
}
|
|
464
|
+
if (record.status === "error") next.status = "error";
|
|
465
|
+
return next;
|
|
466
|
+
}
|
|
467
|
+
const pos = Object.prototype.hasOwnProperty.call(next.index, key) ? next.index[key] : void 0;
|
|
468
|
+
if (pos != null) {
|
|
469
|
+
const existing = next.nodes[pos];
|
|
470
|
+
next.nodes[pos] = { ...existing, raw: [...existing.raw, record] };
|
|
471
|
+
} else {
|
|
472
|
+
next.index[key] = next.nodes.length;
|
|
473
|
+
next.nodes.push(makeOpenNode(record, interp, key));
|
|
474
|
+
}
|
|
475
|
+
return next;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// src/worklog/use-worklog.ts
|
|
479
|
+
import { useCallback, useReducer } from "react";
|
|
480
|
+
|
|
481
|
+
// src/worklog/from-frame.ts
|
|
482
|
+
function frameToRecord(frame) {
|
|
483
|
+
const status = frame.status === "success" || frame.status === "error" ? frame.status : null;
|
|
484
|
+
return {
|
|
485
|
+
event_class: typeof frame.event_class === "string" && frame.event_class.length > 0 ? frame.event_class : "Unknown",
|
|
486
|
+
control_id: frame.control_id ?? null,
|
|
487
|
+
data: frame.data,
|
|
488
|
+
status,
|
|
489
|
+
date_submitted: typeof frame.date_submitted === "string" ? frame.date_submitted : ""
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/hooks/pending-client-tool.ts
|
|
494
|
+
function extractPendingClientTool(frame) {
|
|
495
|
+
if (!frame || typeof frame !== "object") return null;
|
|
496
|
+
const f = frame;
|
|
497
|
+
if (f.event_class !== "ClientToolExecution") return null;
|
|
498
|
+
const name = f.data?.name;
|
|
499
|
+
const parameters = f.data?.parameters;
|
|
500
|
+
const controlId = f.control_id;
|
|
501
|
+
if (typeof name !== "string" || parameters === void 0 || typeof controlId !== "string") return null;
|
|
502
|
+
return { controlId, toolName: name, parameters };
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// src/genui/style.ts
|
|
506
|
+
import { z } from "zod";
|
|
507
|
+
var TONES = ["default", "muted", "primary", "success", "warning", "danger"];
|
|
508
|
+
var SIZES = ["sm", "md", "lg"];
|
|
509
|
+
var EMPHASES = ["low", "medium", "high"];
|
|
510
|
+
var ALIGNS = ["start", "center", "end"];
|
|
511
|
+
var DENSITIES = ["compact", "comfortable"];
|
|
512
|
+
var styleSchemaShape = {
|
|
513
|
+
tone: z.enum(TONES).optional(),
|
|
514
|
+
size: z.enum(SIZES).optional(),
|
|
515
|
+
emphasis: z.enum(EMPHASES).optional(),
|
|
516
|
+
align: z.enum(ALIGNS).optional(),
|
|
517
|
+
density: z.enum(DENSITIES).optional()
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
// src/genui/registry.ts
|
|
521
|
+
function resolveComponent(manifest, name) {
|
|
522
|
+
if (!name || typeof name !== "string") return null;
|
|
523
|
+
return manifest.components[name] ?? null;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// src/genui/catalog.ts
|
|
527
|
+
import { z as z2 } from "zod";
|
|
528
|
+
var CORE_CATALOG_ID = "https://alquimia.ai/catalogs/core/v1/catalog.json";
|
|
529
|
+
var def = (name, own, opts) => ({
|
|
530
|
+
name,
|
|
531
|
+
schema: z2.object({
|
|
532
|
+
...styleSchemaShape,
|
|
533
|
+
...opts?.variant ? { variant: z2.enum(opts.variant).optional() } : {},
|
|
534
|
+
...own
|
|
535
|
+
}).passthrough(),
|
|
536
|
+
allowedActions: opts?.allowedActions
|
|
537
|
+
});
|
|
538
|
+
var option = z2.object({ label: z2.string(), value: z2.union([z2.string(), z2.number()]) });
|
|
539
|
+
var coreCatalog = {
|
|
540
|
+
id: CORE_CATALOG_ID,
|
|
541
|
+
components: {
|
|
542
|
+
// ---- layout ----
|
|
543
|
+
Stack: def("Stack", {
|
|
544
|
+
direction: z2.enum(["vertical", "horizontal"]).optional(),
|
|
545
|
+
gap: z2.enum(["sm", "md", "lg"]).optional()
|
|
546
|
+
}),
|
|
547
|
+
Grid: def("Grid", {
|
|
548
|
+
columns: z2.number().int().min(1).max(6).optional(),
|
|
549
|
+
gap: z2.enum(["sm", "md", "lg"]).optional()
|
|
550
|
+
}),
|
|
551
|
+
Row: def("Row", { gap: z2.enum(["sm", "md", "lg"]).optional(), wrap: z2.boolean().optional() }),
|
|
552
|
+
Column: def("Column", { gap: z2.enum(["sm", "md", "lg"]).optional() }),
|
|
553
|
+
Divider: def("Divider", { label: z2.string().optional() }),
|
|
554
|
+
Spacer: def("Spacer", { size: z2.enum(["sm", "md", "lg"]).optional() }),
|
|
555
|
+
Card: def("Card", { title: z2.string().optional(), description: z2.string().optional() }, {
|
|
556
|
+
variant: ["elevated", "outline", "ghost"]
|
|
557
|
+
}),
|
|
558
|
+
Accordion: def("Accordion", {
|
|
559
|
+
items: z2.array(z2.object({ title: z2.string(), value: z2.string() })).optional()
|
|
560
|
+
}),
|
|
561
|
+
Tabs: def("Tabs", { tabs: z2.array(z2.object({ label: z2.string(), value: z2.string() })).min(1) }),
|
|
562
|
+
// ---- content ----
|
|
563
|
+
Text: def("Text", { text: z2.string() }, { variant: ["body", "muted", "caption", "lead"] }),
|
|
564
|
+
Heading: def("Heading", { text: z2.string(), level: z2.number().int().min(1).max(4).optional() }),
|
|
565
|
+
Markdown: def("Markdown", { text: z2.string() }),
|
|
566
|
+
Image: def("Image", { src: z2.string(), alt: z2.string().optional() }),
|
|
567
|
+
Icon: def("Icon", { name: z2.string() }),
|
|
568
|
+
Badge: def("Badge", { text: z2.string() }, { variant: ["solid", "outline", "subtle"] }),
|
|
569
|
+
Avatar: def("Avatar", { src: z2.string().optional(), fallback: z2.string().optional() }),
|
|
570
|
+
Alert: def("Alert", { text: z2.string(), title: z2.string().optional() }, {
|
|
571
|
+
variant: ["info", "success", "warning", "danger"]
|
|
572
|
+
}),
|
|
573
|
+
Stat: def("Stat", { label: z2.string(), value: z2.union([z2.string(), z2.number()]), delta: z2.string().optional() }),
|
|
574
|
+
KeyValue: def("KeyValue", {}),
|
|
575
|
+
List: def("List", { ordered: z2.boolean().optional() }),
|
|
576
|
+
Quote: def("Quote", { text: z2.string(), cite: z2.string().optional() }),
|
|
577
|
+
// ---- inputs ----
|
|
578
|
+
TextField: def("TextField", { label: z2.string().optional(), placeholder: z2.string().optional() }),
|
|
579
|
+
TextArea: def("TextArea", {
|
|
580
|
+
label: z2.string().optional(),
|
|
581
|
+
placeholder: z2.string().optional(),
|
|
582
|
+
rows: z2.number().int().optional()
|
|
583
|
+
}),
|
|
584
|
+
NumberField: def("NumberField", {
|
|
585
|
+
label: z2.string().optional(),
|
|
586
|
+
min: z2.number().optional(),
|
|
587
|
+
max: z2.number().optional(),
|
|
588
|
+
step: z2.number().optional()
|
|
589
|
+
}),
|
|
590
|
+
Select: def("Select", {
|
|
591
|
+
label: z2.string().optional(),
|
|
592
|
+
placeholder: z2.string().optional(),
|
|
593
|
+
options: z2.array(option).min(1)
|
|
594
|
+
}),
|
|
595
|
+
MultiSelect: def("MultiSelect", { label: z2.string().optional(), options: z2.array(option).min(1) }),
|
|
596
|
+
Combobox: def("Combobox", {
|
|
597
|
+
label: z2.string().optional(),
|
|
598
|
+
placeholder: z2.string().optional(),
|
|
599
|
+
options: z2.array(option).min(1)
|
|
600
|
+
}),
|
|
601
|
+
Checkbox: def("Checkbox", { label: z2.string().optional() }),
|
|
602
|
+
CheckboxGroup: def("CheckboxGroup", { label: z2.string().optional(), options: z2.array(option).min(1) }),
|
|
603
|
+
Radio: def("Radio", { label: z2.string().optional(), options: z2.array(option).min(1) }),
|
|
604
|
+
Switch: def("Switch", { label: z2.string().optional() }),
|
|
605
|
+
Slider: def("Slider", {
|
|
606
|
+
label: z2.string().optional(),
|
|
607
|
+
min: z2.number().optional(),
|
|
608
|
+
max: z2.number().optional(),
|
|
609
|
+
step: z2.number().optional()
|
|
610
|
+
}),
|
|
611
|
+
DatePicker: def("DatePicker", { label: z2.string().optional() }),
|
|
612
|
+
DateRange: def("DateRange", { label: z2.string().optional() }),
|
|
613
|
+
FileUpload: def("FileUpload", {
|
|
614
|
+
label: z2.string().optional(),
|
|
615
|
+
accept: z2.string().optional(),
|
|
616
|
+
multiple: z2.boolean().optional()
|
|
617
|
+
}),
|
|
618
|
+
Rating: def("Rating", { label: z2.string().optional(), max: z2.number().int().optional() }),
|
|
619
|
+
// ---- data ----
|
|
620
|
+
Table: def("Table", {
|
|
621
|
+
columns: z2.array(z2.object({ key: z2.string(), header: z2.string().optional() })).min(1),
|
|
622
|
+
sortable: z2.boolean().optional()
|
|
623
|
+
}, { allowedActions: ["sort", "filter"] }),
|
|
624
|
+
Chart: def("Chart", {
|
|
625
|
+
kind: z2.enum(["bar", "line", "area", "pie"]),
|
|
626
|
+
x: z2.string().optional(),
|
|
627
|
+
series: z2.array(z2.object({ key: z2.string(), label: z2.string().optional() })).min(1),
|
|
628
|
+
title: z2.string().optional()
|
|
629
|
+
}),
|
|
630
|
+
Progress: def("Progress", { value: z2.number(), max: z2.number().optional(), label: z2.string().optional() }),
|
|
631
|
+
Timeline: def("Timeline", {
|
|
632
|
+
items: z2.array(z2.object({ title: z2.string(), description: z2.string().optional(), timestamp: z2.string().optional() })).min(1)
|
|
633
|
+
}),
|
|
634
|
+
// ---- actions ----
|
|
635
|
+
Button: def("Button", { text: z2.string() }, {
|
|
636
|
+
variant: ["solid", "outline", "ghost", "link"],
|
|
637
|
+
allowedActions: ["submit", "cancel", "reset", "select", "confirm"]
|
|
638
|
+
}),
|
|
639
|
+
ButtonGroup: def("ButtonGroup", {}),
|
|
640
|
+
Link: def("Link", { text: z2.string(), href: z2.string().optional() })
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
// src/genui/actions.ts
|
|
645
|
+
var URL_LIKE = /^\s*([a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
646
|
+
function assertSafeActionName(name) {
|
|
647
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
648
|
+
throw new Error("action.name must be a non-empty string");
|
|
649
|
+
}
|
|
650
|
+
if (URL_LIKE.test(name)) {
|
|
651
|
+
throw new Error(`action.name must be a semantic name, not a URL: ${name}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// src/genui/validate.ts
|
|
656
|
+
import { z as z3 } from "zod";
|
|
657
|
+
var surfaceShape = z3.object({
|
|
658
|
+
surfaceId: z3.string().min(1),
|
|
659
|
+
// Tier 2 canonical id (versioned URI); `catalog` is the legacy alias. Both optional on the
|
|
660
|
+
// wire — the SDK stamps `catalogId` if the agent omits it.
|
|
661
|
+
catalogId: z3.string().min(1).optional(),
|
|
662
|
+
catalog: z3.string().min(1).optional(),
|
|
663
|
+
// Legacy explicit root. A2UI uses the component with id "root"; kept optional for back-compat.
|
|
664
|
+
root: z3.string().min(1).optional(),
|
|
665
|
+
components: z3.array(
|
|
666
|
+
z3.object({
|
|
667
|
+
id: z3.string().min(1),
|
|
668
|
+
component: z3.string().min(1),
|
|
669
|
+
children: z3.array(z3.string()).optional(),
|
|
670
|
+
child: z3.string().optional(),
|
|
671
|
+
binding: z3.string().optional(),
|
|
672
|
+
action: z3.object({ name: z3.string(), wantResponse: z3.boolean().optional() }).optional()
|
|
673
|
+
}).passthrough()
|
|
674
|
+
),
|
|
675
|
+
dataModel: z3.record(z3.unknown()).optional()
|
|
676
|
+
});
|
|
677
|
+
var UAX31_ID = /^[\p{XID_Start}_][\p{XID_Continue}]*$/u;
|
|
678
|
+
function validateProps(node, def2) {
|
|
679
|
+
const { id, component, children, child, binding, action, ...props } = node;
|
|
680
|
+
const parsed = def2.schema.safeParse(props);
|
|
681
|
+
if (parsed.success) return { ok: true, value: parsed.data, errors: [] };
|
|
682
|
+
return {
|
|
683
|
+
ok: false,
|
|
684
|
+
errors: parsed.error.issues.map((i) => ({ path: `${id}.${i.path.join(".")}`, message: i.message }))
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
function validateSurface(input, manifest) {
|
|
688
|
+
const shape = surfaceShape.safeParse(input);
|
|
689
|
+
if (!shape.success) {
|
|
690
|
+
return { ok: false, errors: shape.error.issues.map((i) => ({ path: i.path.join("."), message: i.message })) };
|
|
691
|
+
}
|
|
692
|
+
const surface = shape.data;
|
|
693
|
+
const errors = [];
|
|
694
|
+
const warnings = [];
|
|
695
|
+
const ids = new Set(surface.components.map((c) => c.id));
|
|
696
|
+
const rootId = ids.has("root") ? "root" : surface.root;
|
|
697
|
+
if (!rootId || !ids.has(rootId)) {
|
|
698
|
+
errors.push({ path: "root", message: `no root component (expected a component with id "root")` });
|
|
699
|
+
}
|
|
700
|
+
if (!surface.catalogId && !surface.catalog) {
|
|
701
|
+
warnings.push({ path: "catalogId", message: "surface has no catalogId (SDK will stamp the active catalog)" });
|
|
702
|
+
}
|
|
703
|
+
for (const node of surface.components) {
|
|
704
|
+
if (!UAX31_ID.test(node.id)) {
|
|
705
|
+
warnings.push({ path: node.id, message: `id "${node.id}" is not a valid UAX#31 identifier` });
|
|
706
|
+
}
|
|
707
|
+
const def2 = resolveComponent(manifest, node.component);
|
|
708
|
+
if (!def2) {
|
|
709
|
+
warnings.push({ path: node.id, message: `unknown component "${node.component}" (renders as text)` });
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
warnings.push(...validateProps(node, def2).errors);
|
|
713
|
+
for (const childId of node.children ?? []) {
|
|
714
|
+
if (!ids.has(childId)) {
|
|
715
|
+
warnings.push({ path: node.id, message: `child "${childId}" does not exist (skipped)` });
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (node.child && !ids.has(node.child)) {
|
|
719
|
+
warnings.push({ path: node.id, message: `child "${node.child}" does not exist (skipped)` });
|
|
720
|
+
}
|
|
721
|
+
if (node.action) {
|
|
722
|
+
try {
|
|
723
|
+
assertSafeActionName(node.action.name);
|
|
724
|
+
} catch (e) {
|
|
725
|
+
errors.push({ path: `${node.id}.action`, message: e.message });
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return errors.length === 0 ? { ok: true, value: surface, errors: [], warnings } : { ok: false, errors, warnings };
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// src/genui/tool-schema.ts
|
|
733
|
+
var DESCRIPTION = 'Render a UI using A2UI. The arguments are a UI surface, NOT free-form. Shape: { surfaceId, root, components, dataModel? }. `components` is a FLAT array; every item is { id, component, children?, ...props } where `component` is one of the allowed names (use `component`, never `type`) and `children` is an array of string ids referencing other items (never nested objects). Inputs bind to the data model via `binding` (a JSON Pointer like "/name"). To collect input, include a Button with action { name, wantResponse: true } \u2014 its result (the data model) is returned to you; a surface with no such button is display-only. Example: { "surfaceId": "signup", "root": "root", "components": [ { "id": "root", "component": "Stack", "children": ["name", "desc", "submit"] }, { "id": "name", "component": "TextField", "label": "Username", "binding": "/name" }, { "id": "desc", "component": "TextField", "label": "Description", "binding": "/description" }, { "id": "submit", "component": "Button", "text": "Save", "action": { "name": "save", "wantResponse": true } } ], "dataModel": { "name": "", "description": "" } }. IMPORTANT: when you call render_ui, the rendered surface IS your reply \u2014 do NOT also reproduce its content as text, markdown, or ASCII. Any accompanying message must be a brief one-line intro at most, never a duplicate of the UI.';
|
|
734
|
+
function buildRenderUiSchema(manifest, allowlist) {
|
|
735
|
+
const allowed = allowlist.filter((name) => name in manifest.components);
|
|
736
|
+
return {
|
|
737
|
+
title: "render_ui",
|
|
738
|
+
name: "render_ui",
|
|
739
|
+
description: DESCRIPTION,
|
|
740
|
+
type: "object",
|
|
741
|
+
properties: {
|
|
742
|
+
surfaceId: { type: "string" },
|
|
743
|
+
// A2UI catalog id — a versioned URI. `const` nudges the model to echo it; the SDK
|
|
744
|
+
// also stamps it if omitted, so the client always knows which catalog version to render.
|
|
745
|
+
catalogId: { type: "string", const: manifest.id },
|
|
746
|
+
catalog: { type: "string" },
|
|
747
|
+
// legacy alias (accepted, ignored)
|
|
748
|
+
root: { type: "string" },
|
|
749
|
+
// legacy explicit root (accepted; A2UI uses the id:"root" component)
|
|
750
|
+
components: {
|
|
751
|
+
type: "array",
|
|
752
|
+
items: {
|
|
753
|
+
type: "object",
|
|
754
|
+
properties: {
|
|
755
|
+
id: { type: "string" },
|
|
756
|
+
component: { type: "string", enum: allowed },
|
|
757
|
+
children: { type: "array", items: { type: "string" } },
|
|
758
|
+
child: { type: "string" },
|
|
759
|
+
binding: { type: "string" },
|
|
760
|
+
action: {
|
|
761
|
+
type: "object",
|
|
762
|
+
properties: {
|
|
763
|
+
name: { type: "string" },
|
|
764
|
+
wantResponse: { type: "boolean" }
|
|
765
|
+
},
|
|
766
|
+
required: ["name"]
|
|
767
|
+
},
|
|
768
|
+
tone: { type: "string", enum: [...TONES] },
|
|
769
|
+
size: { type: "string", enum: [...SIZES] },
|
|
770
|
+
emphasis: { type: "string", enum: [...EMPHASES] },
|
|
771
|
+
align: { type: "string", enum: [...ALIGNS] },
|
|
772
|
+
density: { type: "string", enum: [...DENSITIES] },
|
|
773
|
+
variant: { type: "string" },
|
|
774
|
+
text: { type: "string" },
|
|
775
|
+
label: { type: "string" },
|
|
776
|
+
placeholder: { type: "string" },
|
|
777
|
+
title: { type: "string" },
|
|
778
|
+
direction: { type: "string" },
|
|
779
|
+
gap: { type: "string" },
|
|
780
|
+
// Data props for data components. Several are legitimately polymorphic across
|
|
781
|
+
// components — type them as their real unions so the runtime doesn't reject
|
|
782
|
+
// valid output (adapters normalize each shape):
|
|
783
|
+
// data: array (Chart/Table rows) | object (KeyValue)
|
|
784
|
+
// rows: array (Table) | number (TextArea row count)
|
|
785
|
+
// columns: array (Table col defs) | number (Grid column count)
|
|
786
|
+
data: { type: ["array", "object"] },
|
|
787
|
+
rows: { type: ["array", "number"] },
|
|
788
|
+
items: { type: "array" },
|
|
789
|
+
// Accept string OR object items — models routinely emit the terse string
|
|
790
|
+
// form (e.g. series:["revenue"], options:["A","B"]); adapters normalize.
|
|
791
|
+
columns: { type: ["array", "number"], items: { type: ["object", "string"] } },
|
|
792
|
+
series: { type: "array", items: { type: ["object", "string"] } },
|
|
793
|
+
options: { type: "array", items: { type: ["object", "string"] } },
|
|
794
|
+
kind: { type: "string" },
|
|
795
|
+
x: { type: "string" },
|
|
796
|
+
value: {}
|
|
797
|
+
},
|
|
798
|
+
required: ["id", "component"]
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
dataModel: { type: "object" }
|
|
802
|
+
},
|
|
803
|
+
required: ["surfaceId", "root", "components"],
|
|
804
|
+
additionalProperties: false
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// src/genui/clause.ts
|
|
809
|
+
function buildGenuiClause(manifest, allowlist) {
|
|
810
|
+
const names = allowlist.filter((n) => n in manifest.components);
|
|
811
|
+
return [
|
|
812
|
+
"You can render UI by calling render_ui with an A2UI surface (a flat components array; each item is { id, component, children?, ...props }; component is one of the allowed names; children are string ids referencing other items).",
|
|
813
|
+
`Components: ${names.join(", ")}.`,
|
|
814
|
+
`Style each component via the semantic vocabulary (never CSS, colors, or HTML): tone (${TONES.join("/")}), size (${SIZES.join("/")}), emphasis (low/medium/high), align (start/center/end), density (compact/comfortable), plus a component-specific variant where offered.`,
|
|
815
|
+
"Data components MUST carry their data: Chart takes `data` (an array of row objects) + `series` (keys to plot) + `x` (the category key); Table takes `rows` (array of row objects) + `columns` ([{ key, header }] matching the row keys); List takes `items` (array); Stat takes `label`+`value`; KeyValue takes `data` (an object). Put the data inline on the component (or in dataModel referenced via `binding`).",
|
|
816
|
+
"To collect input, add a Button with an action { name, wantResponse: true }; its result (the data model) is returned to you. A surface with no such button is display-only.",
|
|
817
|
+
"IMPORTANT: the rendered surface IS your reply \u2014 do NOT reproduce its content as text, markdown, or ASCII; a one-line intro at most.",
|
|
818
|
+
"Prefer plain text for simple replies."
|
|
819
|
+
].join(" ");
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// src/genui/emit.ts
|
|
823
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
303
824
|
|
|
304
825
|
// src/hooks/alquimia.hook.tsx
|
|
305
826
|
function useAlquimia(config) {
|
|
@@ -314,6 +835,15 @@ function useAlquimia(config) {
|
|
|
314
835
|
if (config.providers?.logger) instance.withLoggerProvider(config.providers.logger);
|
|
315
836
|
if (config.options?.userId) instance.withUserId(config.options.userId);
|
|
316
837
|
if (config.options?.extraInstructions) instance.withExtraInstructions(config.options.extraInstructions);
|
|
838
|
+
if (config.genui && (config.genui.source ?? "client") === "client") {
|
|
839
|
+
const cat = config.genui.catalog ?? coreCatalog;
|
|
840
|
+
const allow = resolveGenuiAllow(cat, config.genui.allow);
|
|
841
|
+
instance.withTools([buildRenderUiSchema(cat, allow)]);
|
|
842
|
+
instance.withExtraInstructions({
|
|
843
|
+
...config.options?.extraInstructions ?? {},
|
|
844
|
+
genui: buildGenuiClause(cat, allow)
|
|
845
|
+
});
|
|
846
|
+
}
|
|
317
847
|
return instance;
|
|
318
848
|
}, [config.assistantId, config.adapter]);
|
|
319
849
|
const [input, setInput] = useState("");
|
|
@@ -329,8 +859,29 @@ function useAlquimia(config) {
|
|
|
329
859
|
const [activeTool, setActiveTool] = useState(null);
|
|
330
860
|
const [lastRequest, setLastRequest] = useState(null);
|
|
331
861
|
const [hasThinkings, setHasThinkings] = useState(false);
|
|
862
|
+
const worklogEnabled = config.options?.worklog ?? false;
|
|
863
|
+
const [worklog, setWorklog] = useState(
|
|
864
|
+
worklogEnabled ? initialWorklogState() : void 0
|
|
865
|
+
);
|
|
332
866
|
const [attachments, setAttachments] = useState([]);
|
|
333
867
|
const [isUploadingAttachments, setIsUploadingAttachments] = useState(false);
|
|
868
|
+
const [pendingClientTool, setPendingClientTool] = useState(null);
|
|
869
|
+
const completedToolsRef = useRef(/* @__PURE__ */ new Set());
|
|
870
|
+
const genuiCatalog = config.genui?.catalog ?? coreCatalog;
|
|
871
|
+
const [genuiSurfaces, setGenuiSurfaces] = useState([]);
|
|
872
|
+
const messagesLenRef = useRef(0);
|
|
873
|
+
messagesLenRef.current = messages.length;
|
|
874
|
+
const genuiAnchorRef = useRef(0);
|
|
875
|
+
{
|
|
876
|
+
let anchor = messages.length;
|
|
877
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
878
|
+
if (messages[i].role === "user") {
|
|
879
|
+
anchor = i + 1;
|
|
880
|
+
break;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
genuiAnchorRef.current = anchor;
|
|
884
|
+
}
|
|
334
885
|
const isLoading = isMessageLoading || isStreamingLoading || isUploadingAttachments;
|
|
335
886
|
function cleanMessages() {
|
|
336
887
|
setMessages([]);
|
|
@@ -534,6 +1085,7 @@ function useAlquimia(config) {
|
|
|
534
1085
|
lastMessageAt: null,
|
|
535
1086
|
closedByClient: false
|
|
536
1087
|
};
|
|
1088
|
+
if (worklogEnabled) setWorklog(initialWorklogState());
|
|
537
1089
|
const eventSource = new EventSource(streamUrl);
|
|
538
1090
|
eventSourceRef.current = eventSource;
|
|
539
1091
|
eventSource.onopen = () => {
|
|
@@ -594,6 +1146,14 @@ function useAlquimia(config) {
|
|
|
594
1146
|
}
|
|
595
1147
|
function handleMessageEvent(event, callBack, eventSource, streamState) {
|
|
596
1148
|
const data = JSON.parse(event.data);
|
|
1149
|
+
if (worklogEnabled) {
|
|
1150
|
+
setWorklog((prev) => reduceWorklog(prev ?? initialWorklogState(), frameToRecord(data)));
|
|
1151
|
+
}
|
|
1152
|
+
const pending = extractPendingClientTool(data);
|
|
1153
|
+
if (pending) {
|
|
1154
|
+
setPendingClientTool(pending);
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
597
1157
|
const eventTaskId = data.taskid || "";
|
|
598
1158
|
if (data.errors?.length) {
|
|
599
1159
|
for (const error of data.errors) {
|
|
@@ -623,9 +1183,77 @@ function useAlquimia(config) {
|
|
|
623
1183
|
cleanup(false, eventSource);
|
|
624
1184
|
}
|
|
625
1185
|
}
|
|
1186
|
+
const completeToolExecution = useCallback2(
|
|
1187
|
+
async (controlId, result) => {
|
|
1188
|
+
if (completedToolsRef.current.has(controlId)) return;
|
|
1189
|
+
completedToolsRef.current.add(controlId);
|
|
1190
|
+
try {
|
|
1191
|
+
await sdk.submitToolResult({ ...result, control_id: controlId });
|
|
1192
|
+
setPendingClientTool((cur) => cur?.controlId === controlId ? null : cur);
|
|
1193
|
+
} catch (err) {
|
|
1194
|
+
completedToolsRef.current.delete(controlId);
|
|
1195
|
+
throw err;
|
|
1196
|
+
}
|
|
1197
|
+
},
|
|
1198
|
+
[sdk]
|
|
1199
|
+
);
|
|
1200
|
+
useEffect(() => {
|
|
1201
|
+
if (!config.genui) return;
|
|
1202
|
+
if (!pendingClientTool || pendingClientTool.toolName !== "render_ui") return;
|
|
1203
|
+
const { controlId } = pendingClientTool;
|
|
1204
|
+
const parameters = pendingClientTool.parameters && typeof pendingClientTool.parameters === "object" ? { catalogId: genuiCatalog.id, ...pendingClientTool.parameters } : pendingClientTool.parameters;
|
|
1205
|
+
const res = validateSurface(parameters, genuiCatalog);
|
|
1206
|
+
if (!res.ok || !res.value) {
|
|
1207
|
+
void completeToolExecution(controlId, {
|
|
1208
|
+
control_id: controlId,
|
|
1209
|
+
tool_name: "render_ui",
|
|
1210
|
+
status: "error",
|
|
1211
|
+
message: "Surface failed client validation: " + res.errors.map((e) => `${e.path} ${e.message}`).join("; "),
|
|
1212
|
+
result: { errors: res.errors }
|
|
1213
|
+
});
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
const surface = res.value;
|
|
1217
|
+
setGenuiSurfaces(
|
|
1218
|
+
(prev) => prev.some((s) => s.controlId === controlId) ? prev : [...prev, { controlId, surface, afterCount: genuiAnchorRef.current }]
|
|
1219
|
+
);
|
|
1220
|
+
const interactive = surface.components.some((c) => c.action?.wantResponse === true);
|
|
1221
|
+
if (!interactive) {
|
|
1222
|
+
void completeToolExecution(controlId, {
|
|
1223
|
+
control_id: controlId,
|
|
1224
|
+
tool_name: "render_ui",
|
|
1225
|
+
status: "success",
|
|
1226
|
+
result: {
|
|
1227
|
+
shown: true,
|
|
1228
|
+
instruction: "The UI is rendered and visible to the user. Do NOT restate it as text/markdown/ASCII; reply with at most one short sentence."
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
}, [pendingClientTool, completeToolExecution, config.genui]);
|
|
1233
|
+
const genuiOnAgentAction = useCallback2(
|
|
1234
|
+
(controlId) => (action) => {
|
|
1235
|
+
setGenuiSurfaces(
|
|
1236
|
+
(prev) => prev.map((s) => s.controlId === controlId ? { ...s, submitted: true } : s)
|
|
1237
|
+
);
|
|
1238
|
+
void completeToolExecution(controlId, {
|
|
1239
|
+
control_id: controlId,
|
|
1240
|
+
tool_name: "render_ui",
|
|
1241
|
+
status: "success",
|
|
1242
|
+
result: { action: action.action, surfaceId: action.surfaceId, data: action.payload }
|
|
1243
|
+
});
|
|
1244
|
+
},
|
|
1245
|
+
[completeToolExecution]
|
|
1246
|
+
);
|
|
1247
|
+
const genuiAwaitingUser = !!(pendingClientTool && pendingClientTool.toolName === "render_ui" && genuiSurfaces.some(
|
|
1248
|
+
(s) => s.controlId === pendingClientTool.controlId && s.surface.components.some((c) => c.action?.wantResponse === true)
|
|
1249
|
+
));
|
|
1250
|
+
const genui = config.genui ? { surfaces: genuiSurfaces, onAgentAction: genuiOnAgentAction, awaitingUser: genuiAwaitingUser } : void 0;
|
|
626
1251
|
return {
|
|
627
1252
|
sdk,
|
|
628
1253
|
activeTool,
|
|
1254
|
+
pendingClientTool,
|
|
1255
|
+
completeToolExecution,
|
|
1256
|
+
genui,
|
|
629
1257
|
cleanMessages,
|
|
630
1258
|
createMessageId,
|
|
631
1259
|
handleInputChange,
|
|
@@ -651,6 +1279,7 @@ function useAlquimia(config) {
|
|
|
651
1279
|
setLastRequest,
|
|
652
1280
|
setIsAudioRecording,
|
|
653
1281
|
hasThinkings,
|
|
1282
|
+
worklog,
|
|
654
1283
|
attachments,
|
|
655
1284
|
addAttachment,
|
|
656
1285
|
addAttachments,
|
|
@@ -661,7 +1290,7 @@ function useAlquimia(config) {
|
|
|
661
1290
|
}
|
|
662
1291
|
|
|
663
1292
|
// src/hooks/useRatings.ts
|
|
664
|
-
import { useState as useState2, useReducer } from "react";
|
|
1293
|
+
import { useState as useState2, useReducer as useReducer2 } from "react";
|
|
665
1294
|
var initialState = {
|
|
666
1295
|
ratingStars: 0,
|
|
667
1296
|
ratingThumbs: "",
|
|
@@ -682,7 +1311,7 @@ function ratingReducer(state, action) {
|
|
|
682
1311
|
function useRatings({ assistantId, sendRating, topicId }) {
|
|
683
1312
|
const [isLoading, setIsLoading] = useState2(false);
|
|
684
1313
|
const [hasReviewed, setHasReviewed] = useState2(false);
|
|
685
|
-
const [state, dispatch] =
|
|
1314
|
+
const [state, dispatch] = useReducer2(ratingReducer, initialState);
|
|
686
1315
|
const setRatingStars = (rating) => {
|
|
687
1316
|
dispatch({ type: "SET_RATING_STARS", payload: rating });
|
|
688
1317
|
};
|