@agno-hq/chat-react 0.1.0 → 0.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/index.js CHANGED
@@ -1,1928 +1,6 @@
1
1
  'use client';
2
- import { useMemo, useState, useRef, useEffect, useCallback } from 'react';
3
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
-
5
- // src/useAgnoChat.ts
6
-
7
- // src/stream.ts
8
- function isEnvelope(data) {
9
- return typeof data === "object" && data !== null && "event" in data && "data" in data && typeof data.event === "string";
10
- }
11
- function isFlatEvent(data) {
12
- return typeof data === "object" && data !== null && "event" in data && !("data" in data) && typeof data.event === "string";
13
- }
14
- function normaliseEnvelope(env) {
15
- let parsed = {};
16
- if (typeof env.data === "string") {
17
- try {
18
- parsed = JSON.parse(env.data);
19
- } catch {
20
- parsed = {};
21
- }
22
- } else if (env.data && typeof env.data === "object") {
23
- parsed = env.data;
24
- }
25
- return { event: env.event, ...parsed };
26
- }
27
- function drainBuffer(buffer, onEvent) {
28
- let start = buffer.indexOf("{");
29
- while (start !== -1 && start < buffer.length) {
30
- let depth = 0;
31
- let inString = false;
32
- let escape = false;
33
- let end = -1;
34
- for (let i = start; i < buffer.length; i++) {
35
- const ch = buffer[i];
36
- if (inString) {
37
- if (escape) escape = false;
38
- else if (ch === "\\") escape = true;
39
- else if (ch === '"') inString = false;
40
- } else if (ch === '"') {
41
- inString = true;
42
- } else if (ch === "{") {
43
- depth++;
44
- } else if (ch === "}") {
45
- depth--;
46
- if (depth === 0) {
47
- end = i;
48
- break;
49
- }
50
- }
51
- }
52
- if (end === -1) break;
53
- const slice = buffer.slice(start, end + 1);
54
- try {
55
- const parsed = JSON.parse(slice);
56
- if (isEnvelope(parsed)) onEvent(normaliseEnvelope(parsed));
57
- else if (isFlatEvent(parsed)) onEvent(parsed);
58
- } catch {
59
- start = buffer.indexOf("{", start + 1);
60
- continue;
61
- }
62
- buffer = buffer.slice(end + 1).trim();
63
- start = buffer.indexOf("{");
64
- }
65
- return buffer;
66
- }
67
- async function streamRun(options) {
68
- const { url, body, headers = {}, signal, onEvent, onError, onComplete } = options;
69
- let buffer = "";
70
- try {
71
- const response = await fetch(url, {
72
- method: "POST",
73
- headers: {
74
- ...!(body instanceof FormData) && { "Content-Type": "application/json" },
75
- ...headers
76
- },
77
- body: body instanceof FormData ? body : JSON.stringify(body),
78
- signal
79
- });
80
- if (!response.ok) {
81
- let detail;
82
- try {
83
- const err = await response.json();
84
- detail = err?.detail ? String(err.detail) : `${response.status} ${response.statusText}`;
85
- } catch {
86
- detail = `${response.status} ${response.statusText}`;
87
- }
88
- throw new Error(detail);
89
- }
90
- if (!response.body) throw new Error("No response body");
91
- const reader = response.body.getReader();
92
- const decoder = new TextDecoder();
93
- for (; ; ) {
94
- const { done, value } = await reader.read();
95
- if (done) {
96
- buffer = drainBuffer(buffer, onEvent);
97
- onComplete();
98
- return;
99
- }
100
- buffer += decoder.decode(value, { stream: true });
101
- buffer = drainBuffer(buffer, onEvent);
102
- }
103
- } catch (error) {
104
- if (error instanceof DOMException && error.name === "AbortError") {
105
- onComplete();
106
- return;
107
- }
108
- onError(error instanceof Error ? error : new Error(String(error)));
109
- }
110
- }
111
-
112
- // src/client.ts
113
- function normaliseBaseUrl(value) {
114
- if (!value) return "";
115
- let url = value.trim();
116
- if (!/^https?:\/\//.test(url)) {
117
- const isLocal = url.startsWith("localhost") || /^\d{1,3}(\.\d{1,3}){3}/.test(url);
118
- url = `${isLocal ? "http" : "https"}://${url}`;
119
- }
120
- return url.replace(/\/+$/, "");
121
- }
122
- var RUN_PATH = {
123
- agent: "agents",
124
- team: "teams",
125
- workflow: "workflows"
126
- };
127
- var AgnoClient = class {
128
- constructor(options) {
129
- this.baseUrl = normaliseBaseUrl(options.baseUrl);
130
- this.headers = options.headers ?? {};
131
- this.dbId = options.dbId;
132
- }
133
- async getJson(path) {
134
- const res = await fetch(`${this.baseUrl}${path}`, { headers: this.headers });
135
- if (!res.ok) throw new Error(`GET ${path} failed: ${res.status} ${res.statusText}`);
136
- return res.json();
137
- }
138
- /** Liveness check against /health. Returns the HTTP status code. */
139
- async health() {
140
- try {
141
- const res = await fetch(`${this.baseUrl}/health`, { headers: this.headers });
142
- return res.status;
143
- } catch {
144
- return 0;
145
- }
146
- }
147
- /* ----------------------------- discovery ----------------------------- */
148
- async getAgents() {
149
- const data = await this.getJson("/agents").catch(() => []);
150
- return data.map((a) => ({
151
- type: "agent",
152
- id: a.agent_id ?? a.id,
153
- name: a.name ?? a.agent_id ?? a.id,
154
- description: a.description,
155
- model: a.model,
156
- db_id: a.db_id
157
- }));
158
- }
159
- async getTeams() {
160
- const data = await this.getJson("/teams").catch(() => []);
161
- return data.map((t) => ({
162
- type: "team",
163
- id: t.team_id ?? t.id,
164
- name: t.name ?? t.team_id ?? t.id,
165
- description: t.description,
166
- model: t.model,
167
- db_id: t.db_id
168
- }));
169
- }
170
- async getWorkflows() {
171
- const data = await this.getJson("/workflows").catch(() => []);
172
- return data.map((w) => ({
173
- type: "workflow",
174
- id: w.workflow_id ?? w.id,
175
- name: w.name ?? w.workflow_id ?? w.id,
176
- description: w.description,
177
- model: w.model,
178
- db_id: w.db_id
179
- }));
180
- }
181
- /** All runnable entities (agents, teams, workflows) in one list. */
182
- async getEntities() {
183
- const [agents, teams, workflows] = await Promise.all([
184
- this.getAgents(),
185
- this.getTeams(),
186
- this.getWorkflows()
187
- ]);
188
- return [...agents, ...teams, ...workflows];
189
- }
190
- /* ------------------------------ sessions ----------------------------- */
191
- async getSessions(type, componentId, dbId) {
192
- const url = new URL(`${this.baseUrl}/sessions`);
193
- url.searchParams.set("type", type);
194
- url.searchParams.set("component_id", componentId);
195
- const db = dbId ?? this.dbId;
196
- if (db) url.searchParams.set("db_id", db);
197
- try {
198
- const res = await fetch(url.toString(), { headers: this.headers });
199
- if (!res.ok) return { data: [] };
200
- return await res.json();
201
- } catch {
202
- return { data: [] };
203
- }
204
- }
205
- /** Runs (with messages/tools/events) for a session — used to rehydrate chat history. */
206
- async getSessionRuns(type, sessionId, dbId) {
207
- const url = new URL(`${this.baseUrl}/sessions/${sessionId}/runs`);
208
- url.searchParams.set("type", type);
209
- const db = dbId ?? this.dbId;
210
- if (db) url.searchParams.set("db_id", db);
211
- const res = await fetch(url.toString(), { headers: this.headers });
212
- if (!res.ok) throw new Error(`Failed to load session: ${res.statusText}`);
213
- return res.json();
214
- }
215
- async deleteSession(sessionId, dbId) {
216
- const url = new URL(`${this.baseUrl}/sessions/${sessionId}`);
217
- const db = dbId ?? this.dbId;
218
- if (db) url.searchParams.set("db_id", db);
219
- const res = await fetch(url.toString(), { method: "DELETE", headers: this.headers });
220
- return res.ok;
221
- }
222
- /* -------------------------------- runs ------------------------------- */
223
- /** Start a streaming run for an agent, team or workflow. */
224
- async run(args) {
225
- const form = new FormData();
226
- if (args.message != null) form.append("message", args.message);
227
- form.append("stream", "true");
228
- if (args.sessionId) form.append("session_id", args.sessionId);
229
- if (args.userId) form.append("user_id", args.userId);
230
- for (const file of args.files ?? []) form.append("files", file);
231
- for (const [k, v] of Object.entries(args.extra ?? {})) form.append(k, v);
232
- const url = `${this.baseUrl}/${RUN_PATH[args.type]}/${args.id}/runs`;
233
- return streamRun({
234
- url,
235
- body: form,
236
- headers: this.headers,
237
- signal: args.signal,
238
- onEvent: (e) => args.onEvent(e),
239
- onError: args.onError,
240
- onComplete: args.onComplete
241
- });
242
- }
243
- /** Continue a paused run (resolving a human-in-the-loop requirement). */
244
- async continueRun(args) {
245
- const form = new FormData();
246
- form.append("stream", "true");
247
- if (args.sessionId) form.append("session_id", args.sessionId);
248
- if (args.userId) form.append("user_id", args.userId);
249
- if (args.type === "workflow") {
250
- if (args.stepRequirements) form.append("step_requirements", JSON.stringify(args.stepRequirements));
251
- } else if (args.tools) {
252
- form.append("tools", JSON.stringify(args.tools));
253
- }
254
- const url = `${this.baseUrl}/${RUN_PATH[args.type]}/${args.id}/runs/${args.runId}/continue`;
255
- return streamRun({
256
- url,
257
- body: form,
258
- headers: this.headers,
259
- signal: args.signal,
260
- onEvent: (e) => args.onEvent(e),
261
- onError: args.onError,
262
- onComplete: args.onComplete
263
- });
264
- }
265
- /** Cancel an in-flight run. */
266
- async cancelRun(type, id2, runId, sessionId) {
267
- const url = new URL(`${this.baseUrl}/${RUN_PATH[type]}/${id2}/runs/${runId}/cancel`);
268
- if (sessionId) url.searchParams.set("session_id", sessionId);
269
- try {
270
- const res = await fetch(url.toString(), { method: "POST", headers: this.headers });
271
- return res.ok;
272
- } catch {
273
- return false;
274
- }
275
- }
276
- };
277
-
278
- // src/events.ts
279
- var name = (e) => String(e.event ?? "");
280
- var isStartedEvent = (e) => name(e) === "RunStarted" || name(e) === "TeamRunStarted" || name(e) === "WorkflowStarted" || name(e) === "ReasoningStarted" || name(e) === "TeamReasoningStarted";
281
- var isContentEvent = (e) => name(e) === "RunContent" || name(e) === "TeamRunContent" || name(e) === "WorkflowAgentCompleted";
282
- var isCompletedEvent = (e) => name(e) === "RunCompleted" || name(e) === "TeamRunCompleted" || name(e) === "WorkflowCompleted";
283
- var isErrorEvent = (e) => name(e) === "RunError" || name(e) === "TeamRunError" || name(e) === "WorkflowError" || name(e) === "StepError" || name(e) === "ToolCallError" || name(e) === "TeamToolCallError";
284
- var isCancelledEvent = (e) => name(e) === "RunCancelled" || name(e) === "TeamRunCancelled" || name(e) === "WorkflowCancelled";
285
- var isPausedEvent = (e) => name(e) === "RunPaused" || name(e) === "TeamRunPaused" || name(e) === "WorkflowPaused" || name(e) === "StepPaused" || name(e) === "RouterPaused" || name(e) === "ConditionPaused";
286
- var isToolStartedEvent = (e) => name(e) === "ToolCallStarted" || name(e) === "TeamToolCallStarted";
287
- var isToolCompletedEvent = (e) => name(e) === "ToolCallCompleted" || name(e) === "TeamToolCallCompleted";
288
- var isToolEvent = (e) => isToolStartedEvent(e) || isToolCompletedEvent(e) || name(e) === "ToolCallError" || name(e) === "TeamToolCallError";
289
- var isReasoningStepEvent = (e) => name(e) === "ReasoningStep" || name(e) === "TeamReasoningStep";
290
- var isReasoningCompletedEvent = (e) => name(e) === "ReasoningCompleted" || name(e) === "TeamReasoningCompleted";
291
- function isSubRunEvent(e) {
292
- if (!e.parent_run_id) return false;
293
- const ev = name(e);
294
- return isContentEvent(e) || isToolEvent(e) || isCompletedEvent(e) || isErrorEvent(e) || ev === "RunStarted" || ev === "TeamRunStarted";
295
- }
296
- function isStepEvent(e) {
297
- const ev = name(e);
298
- return ev === "StepStarted" || ev === "StepCompleted" || ev === "StepOutput" || ev === "StepError";
299
- }
300
- function toolsFromEvent(e) {
301
- const out = [];
302
- if (e.tool) out.push(e.tool);
303
- if (Array.isArray(e.tools)) out.push(...e.tools);
304
- return out;
305
- }
306
- function activityLabel(e) {
307
- const ev = name(e);
308
- switch (ev) {
309
- case "RunStarted":
310
- case "TeamRunStarted":
311
- case "WorkflowStarted":
312
- return "Thinking";
313
- case "ModelRequestStarted":
314
- case "TeamModelRequestStarted":
315
- return "Generating";
316
- case "ReasoningStarted":
317
- case "TeamReasoningStarted":
318
- case "ReasoningStep":
319
- case "TeamReasoningStep":
320
- case "ReasoningContentDelta":
321
- case "TeamReasoningContentDelta":
322
- return "Reasoning";
323
- case "MemoryUpdateStarted":
324
- case "TeamMemoryUpdateStarted":
325
- return "Updating memory";
326
- case "SessionSummaryStarted":
327
- case "TeamSessionSummaryStarted":
328
- return "Summarising session";
329
- case "CompressionStarted":
330
- return "Compressing context";
331
- case "ToolCallStarted":
332
- case "TeamToolCallStarted": {
333
- const tool = e.tool?.tool_name;
334
- return tool ? `Calling ${tool}` : "Calling tool";
335
- }
336
- case "ToolCallCompleted":
337
- case "TeamToolCallCompleted":
338
- return "Generating";
339
- case "StepStarted":
340
- return e.step_name ? `Running step: ${e.step_name}` : "Running step";
341
- case "LoopIterationStarted":
342
- return `Loop iteration ${e.iteration ?? ""}`.trim();
343
- case "ParallelExecutionStarted":
344
- return "Running parallel steps";
345
- case "RouterExecutionStarted":
346
- return "Routing";
347
- case "ConditionExecutionStarted":
348
- return "Evaluating condition";
349
- default:
350
- return null;
351
- }
352
- }
353
- function textOf(value) {
354
- if (typeof value === "string") return value;
355
- if (value && typeof value === "object") return "```json\n" + JSON.stringify(value, null, 2) + "\n```";
356
- return void 0;
357
- }
358
- function applySubRunEvent(message, e, kind) {
359
- const rid = e.run_id || e.parent_run_id || "sub";
360
- const members = message.members ? [...message.members] : [];
361
- const idx = members.findIndex((s) => s.run_id === rid);
362
- const base = idx >= 0 ? { ...members[idx] } : { run_id: rid, kind, content: "", status: "running" };
363
- base.name = base.name || e.agent_name || e.team_name || e.agent_id;
364
- const tools = toolsFromEvent(e);
365
- if (tools.length) {
366
- let tc = base.tool_calls ?? [];
367
- for (const t of tools) tc = mergeTool(tc, t);
368
- base.tool_calls = tc;
369
- }
370
- if (isErrorEvent(e)) {
371
- base.status = "error";
372
- } else if (isCompletedEvent(e)) {
373
- base.status = "completed";
374
- const final = textOf(e.content);
375
- if (final) base.content = final;
376
- } else if (isContentEvent(e)) {
377
- const delta = typeof e.content === "string" ? e.content : "";
378
- if (delta) base.content += delta;
379
- }
380
- if (idx >= 0) members[idx] = base;
381
- else members.push(base);
382
- return { ...message, members };
383
- }
384
- function applyStepEvent(message, e) {
385
- const ev = name(e);
386
- const key = e.step_name || `step-${JSON.stringify(e.step_index ?? "")}`;
387
- const steps = message.steps ? [...message.steps] : [];
388
- const idx = steps.findIndex((s) => s.key === key);
389
- const step = idx >= 0 ? { ...steps[idx] } : { key, name: e.step_name, index: e.step_index, status: "running" };
390
- if (ev === "StepStarted") {
391
- step.status = "running";
392
- } else if (ev === "StepError") {
393
- step.status = "error";
394
- step.error = e.error || (typeof e.content === "string" ? e.content : void 0);
395
- } else {
396
- step.status = "completed";
397
- const stepResponse = e.step_response ?? e.step_output;
398
- const content = textOf(e.content) ?? textOf(stepResponse?.content);
399
- if (content) step.content = content;
400
- }
401
- if (idx >= 0) steps[idx] = step;
402
- else steps.push(step);
403
- return { ...message, steps };
404
- }
405
- function mergeTool(list, tool) {
406
- const key = tool.tool_call_id || `${tool.tool_name}-${tool.created_at}`;
407
- const idx = list.findIndex((t) => {
408
- if (t.tool_call_id && tool.tool_call_id) return t.tool_call_id === tool.tool_call_id;
409
- return `${t.tool_name}-${t.created_at}` === key;
410
- });
411
- if (idx >= 0) {
412
- const next = [...list];
413
- next[idx] = { ...next[idx], ...tool };
414
- return next;
415
- }
416
- return [...list, tool];
417
- }
418
-
419
- // src/session.ts
420
- function toText(value) {
421
- if (value == null) return "";
422
- if (typeof value === "string") return value;
423
- if (Array.isArray(value)) {
424
- return value.map(
425
- (part) => part && typeof part === "object" && "text" in part ? String(part.text) : ""
426
- ).filter(Boolean).join(" ");
427
- }
428
- if (typeof value === "object") {
429
- const obj = value;
430
- if (typeof obj.input_content === "string") return obj.input_content;
431
- if (typeof obj.message === "string") return obj.message;
432
- if (typeof obj.content === "string") return obj.content;
433
- return "```json\n" + JSON.stringify(value, null, 2) + "\n```";
434
- }
435
- return String(value);
436
- }
437
- var seq = 0;
438
- var id = (prefix) => `${prefix}-${seq++}`;
439
- function sessionRunsToMessages(runs) {
440
- if (!Array.isArray(runs)) return [];
441
- const messages = [];
442
- for (const run of runs) {
443
- const created = run.created_at ?? Math.floor(Date.now() / 1e3);
444
- const userContent = toText(run.run_input);
445
- if (userContent) {
446
- messages.push({
447
- id: id("hist-u"),
448
- role: "user",
449
- content: userContent,
450
- created_at: created
451
- });
452
- }
453
- messages.push({
454
- id: id("hist-a"),
455
- role: "agent",
456
- content: toText(run.content),
457
- created_at: created,
458
- status: "completed",
459
- run_id: run.run_id,
460
- session_id: run.session_id,
461
- tool_calls: run.tools && run.tools.length ? run.tools : void 0,
462
- reasoning_steps: run.reasoning_steps ?? run.extra_data?.reasoning_steps,
463
- references: run.references ?? run.extra_data?.references,
464
- images: run.images,
465
- videos: run.videos,
466
- audio: run.audio,
467
- response_audio: run.response_audio
468
- });
469
- }
470
- return messages;
471
- }
472
-
473
- // src/useAgnoChat.ts
474
- var messageCounter = 0;
475
- var nextId = () => `m${Date.now().toString(36)}-${(messageCounter++).toString(36)}`;
476
- var nowSeconds = () => Math.floor(Date.now() / 1e3);
477
- function useAgnoChat(options) {
478
- const { entity, userId, onEvent, onSessionId } = options;
479
- const client = useMemo(() => {
480
- if (options.client) return options.client;
481
- return new AgnoClient({ baseUrl: options.baseUrl ?? "", headers: options.headers });
482
- }, [options.client, options.baseUrl, JSON.stringify(options.headers)]);
483
- const [messages, setMessages] = useState(options.initialMessages ?? []);
484
- const [events, setEvents] = useState([]);
485
- const [currentEvent, setCurrentEvent] = useState(null);
486
- const [status, setStatus] = useState("idle");
487
- const [activity, setActivity] = useState(null);
488
- const [error, setError] = useState(null);
489
- const [sessionId, setSessionId] = useState(options.sessionId);
490
- const [sessions, setSessions] = useState([]);
491
- const [sessionsLoading, setSessionsLoading] = useState(false);
492
- const abortRef = useRef(null);
493
- const activeMsgIdRef = useRef(null);
494
- const lastContentRef = useRef("");
495
- const runIdRef = useRef(void 0);
496
- const entityRef = useRef(entity);
497
- const sessionIdRef = useRef(options.sessionId);
498
- useEffect(() => {
499
- entityRef.current = entity;
500
- }, [entity]);
501
- useEffect(() => {
502
- sessionIdRef.current = sessionId;
503
- }, [sessionId]);
504
- const patchActive = useCallback((patch) => {
505
- const id2 = activeMsgIdRef.current;
506
- if (!id2) return;
507
- setMessages((prev) => prev.map((m) => m.id === id2 ? patch(m) : m));
508
- }, []);
509
- const applyEvent = useCallback(
510
- (e) => {
511
- setEvents((prev) => [...prev, e]);
512
- setCurrentEvent(e);
513
- onEvent?.(e);
514
- const label2 = activityLabel(e);
515
- if (label2) setActivity(label2);
516
- if (e.session_id && e.session_id !== sessionIdRef.current) {
517
- sessionIdRef.current = e.session_id;
518
- setSessionId(e.session_id);
519
- onSessionId?.(e.session_id);
520
- }
521
- if (e.run_id && !e.parent_run_id) runIdRef.current = e.run_id;
522
- if (isSubRunEvent(e)) {
523
- const kind = entityRef.current?.type === "workflow" ? "executor" : "member";
524
- patchActive((m) => applySubRunEvent(m, e, kind));
525
- return;
526
- }
527
- if (isStepEvent(e)) {
528
- patchActive((m) => applyStepEvent(m, e));
529
- return;
530
- }
531
- if (isStartedEvent(e)) {
532
- patchActive((m) => ({ ...m, run_id: e.run_id ?? m.run_id, session_id: e.session_id ?? m.session_id, status: "streaming" }));
533
- return;
534
- }
535
- if (isToolEvent(e)) {
536
- const incoming = toolsFromEvent(e);
537
- if (incoming.length) {
538
- patchActive((m) => {
539
- let tool_calls = m.tool_calls ?? [];
540
- for (const t of incoming) tool_calls = mergeTool(tool_calls, t);
541
- return { ...m, tool_calls };
542
- });
543
- }
544
- return;
545
- }
546
- if (isContentEvent(e)) {
547
- patchActive((m) => {
548
- const next = { ...m };
549
- if (typeof e.content === "string" && e.content) {
550
- const unique = e.content.startsWith(lastContentRef.current) ? e.content.slice(lastContentRef.current.length) : e.content;
551
- next.content = (m.content ?? "") + unique;
552
- lastContentRef.current = e.content.length >= lastContentRef.current.length ? e.content : lastContentRef.current;
553
- } else if (e.content && typeof e.content === "object") {
554
- next.content = (m.content ?? "") + "\n```json\n" + JSON.stringify(e.content, null, 2) + "\n```\n";
555
- }
556
- if (e.reasoning_steps?.length) next.reasoning_steps = e.reasoning_steps;
557
- if (e.extra_data?.reasoning_steps?.length) next.reasoning_steps = e.extra_data.reasoning_steps;
558
- if (e.references?.length) next.references = e.references;
559
- if (e.extra_data?.references?.length) next.references = e.extra_data.references;
560
- if (e.citations) next.citations = e.citations;
561
- const tools = toolsFromEvent(e);
562
- if (tools.length) {
563
- let tc = m.tool_calls ?? [];
564
- for (const t of tools) tc = mergeTool(tc, t);
565
- next.tool_calls = tc;
566
- }
567
- if (e.images?.length) next.images = e.images;
568
- if (e.videos?.length) next.videos = e.videos;
569
- if (e.audio?.length) next.audio = e.audio;
570
- if (e.response_audio?.transcript) {
571
- next.response_audio = {
572
- ...m.response_audio,
573
- transcript: (m.response_audio?.transcript ?? "") + e.response_audio.transcript
574
- };
575
- }
576
- return next;
577
- });
578
- return;
579
- }
580
- if (isReasoningStepEvent(e)) {
581
- const incoming = e.reasoning_steps ?? e.extra_data?.reasoning_steps ?? [];
582
- if (incoming.length) {
583
- patchActive((m) => ({
584
- ...m,
585
- reasoning_steps: [...m.reasoning_steps ?? [], ...incoming]
586
- }));
587
- }
588
- return;
589
- }
590
- if (isReasoningCompletedEvent(e)) {
591
- const steps = e.reasoning_steps ?? e.extra_data?.reasoning_steps;
592
- if (steps?.length) patchActive((m) => ({ ...m, reasoning_steps: steps }));
593
- return;
594
- }
595
- if (isPausedEvent(e)) {
596
- const requirements = e.requirements ?? [];
597
- const pausedTools2 = toolsFromEvent(e);
598
- setStatus("paused");
599
- setActivity("Waiting for input");
600
- patchActive((m) => {
601
- let tool_calls = m.tool_calls ?? [];
602
- for (const t of pausedTools2) tool_calls = mergeTool(tool_calls, t);
603
- return { ...m, status: "paused", streaming: false, requirements, tool_calls };
604
- });
605
- return;
606
- }
607
- if (isCompletedEvent(e)) {
608
- patchActive((m) => {
609
- const next = { ...m, streaming: false, status: "completed" };
610
- if (typeof e.content === "string" && e.content) next.content = e.content;
611
- const tools = toolsFromEvent(e);
612
- if (tools.length) {
613
- let tc = m.tool_calls ?? [];
614
- for (const t of tools) tc = mergeTool(tc, t);
615
- next.tool_calls = tc;
616
- }
617
- if (e.reasoning_steps?.length) next.reasoning_steps = e.reasoning_steps;
618
- if (e.references?.length) next.references = e.references;
619
- if (e.images?.length) next.images = e.images;
620
- if (e.videos?.length) next.videos = e.videos;
621
- if (e.audio?.length) next.audio = e.audio;
622
- if (e.response_audio) next.response_audio = e.response_audio;
623
- return next;
624
- });
625
- return;
626
- }
627
- if (isCancelledEvent(e)) {
628
- patchActive((m) => ({ ...m, streaming: false, status: "cancelled" }));
629
- setStatus("cancelled");
630
- return;
631
- }
632
- if (isErrorEvent(e)) {
633
- const msg = typeof e.content === "string" ? e.content : e.error || "Error during run";
634
- patchActive((m) => ({ ...m, streaming: false, status: "error", error: msg }));
635
- setError(msg);
636
- setStatus("error");
637
- return;
638
- }
639
- },
640
- [onEvent, onSessionId, patchActive]
641
- );
642
- const drive = useCallback(
643
- async (starter) => {
644
- const controller = new AbortController();
645
- abortRef.current = controller;
646
- setError(null);
647
- setStatus("streaming");
648
- lastContentRef.current = "";
649
- await starter({
650
- signal: controller.signal,
651
- onEvent: applyEvent,
652
- onError: (err) => {
653
- patchActive((m) => ({ ...m, streaming: false, status: "error", error: err.message }));
654
- setError(err.message);
655
- setStatus("error");
656
- },
657
- onComplete: () => {
658
- setActivity(null);
659
- patchActive((m) => m.streaming ? { ...m, streaming: false } : m);
660
- setStatus((s) => s === "streaming" ? "completed" : s);
661
- }
662
- });
663
- abortRef.current = null;
664
- },
665
- [applyEvent, patchActive]
666
- );
667
- const sendMessage = useCallback(
668
- async (message, sendOptions) => {
669
- const ent = entityRef.current;
670
- if (!ent) {
671
- setError("No agent, team or workflow selected.");
672
- return;
673
- }
674
- const userMsg = {
675
- id: nextId(),
676
- role: "user",
677
- content: message,
678
- created_at: nowSeconds()
679
- };
680
- const agentMsg = {
681
- id: nextId(),
682
- role: "agent",
683
- content: "",
684
- created_at: nowSeconds() + 1,
685
- streaming: true,
686
- status: "streaming",
687
- tool_calls: [],
688
- events: []
689
- };
690
- activeMsgIdRef.current = agentMsg.id;
691
- setEvents([]);
692
- setCurrentEvent(null);
693
- setMessages((prev) => [...prev, userMsg, agentMsg]);
694
- await drive(
695
- (cb) => client.run({
696
- type: ent.type,
697
- id: ent.id,
698
- message,
699
- sessionId: sessionIdRef.current,
700
- userId,
701
- files: sendOptions?.files,
702
- ...cb
703
- })
704
- );
705
- },
706
- [client, drive, userId]
707
- );
708
- const continueRun = useCallback(
709
- async (resolution) => {
710
- const ent = entityRef.current;
711
- const runId = runIdRef.current;
712
- if (!ent || !runId) {
713
- setError("No paused run to continue.");
714
- return;
715
- }
716
- patchActive((m) => ({ ...m, streaming: true, status: "streaming", requirements: void 0 }));
717
- await drive(
718
- (cb) => client.continueRun({
719
- type: ent.type,
720
- id: ent.id,
721
- runId,
722
- sessionId: sessionIdRef.current,
723
- userId,
724
- tools: resolution.tools,
725
- stepRequirements: resolution.stepRequirements,
726
- ...cb
727
- })
728
- );
729
- },
730
- [client, drive, patchActive, userId]
731
- );
732
- const activeMessage = useMemo(
733
- () => messages.find((m) => m.id === activeMsgIdRef.current) ?? null,
734
- [messages]
735
- );
736
- const pausedTools = useMemo(
737
- () => (activeMessage?.tool_calls ?? []).filter((t) => t.requires_confirmation || t.requires_user_input),
738
- [activeMessage]
739
- );
740
- const respondToConfirmation = useCallback(
741
- async (approve) => {
742
- const ent = entityRef.current;
743
- if (ent?.type === "workflow") {
744
- const reqs = (activeMessage?.requirements ?? []).map((r) => ({ ...r, confirmation: approve }));
745
- await continueRun({ stepRequirements: reqs });
746
- return;
747
- }
748
- const resolved = pausedTools.map((t) => ({ ...t, confirmed: approve }));
749
- await continueRun({ tools: resolved });
750
- },
751
- [activeMessage, continueRun, pausedTools]
752
- );
753
- const submitUserInput = useCallback(
754
- async (values) => {
755
- const ent = entityRef.current;
756
- if (ent?.type === "workflow") {
757
- const reqs = (activeMessage?.requirements ?? []).map((r) => ({
758
- ...r,
759
- user_input_schema: (r.user_input_schema ?? []).map((f) => ({
760
- ...f,
761
- value: f.name in values ? values[f.name] : f.value
762
- }))
763
- }));
764
- await continueRun({ stepRequirements: reqs });
765
- return;
766
- }
767
- const resolved = pausedTools.map((t) => ({
768
- ...t,
769
- confirmed: true,
770
- user_input_schema: (t.user_input_schema ?? []).map((f) => ({
771
- ...f,
772
- value: f.name in values ? values[f.name] : f.value
773
- }))
774
- }));
775
- await continueRun({ tools: resolved });
776
- },
777
- [activeMessage, continueRun, pausedTools]
778
- );
779
- const cancel = useCallback(async () => {
780
- abortRef.current?.abort();
781
- const ent = entityRef.current;
782
- const runId = runIdRef.current;
783
- setStatus("cancelled");
784
- setActivity(null);
785
- patchActive((m) => m.streaming ? { ...m, streaming: false, status: "cancelled" } : m);
786
- if (ent && runId) await client.cancelRun(ent.type, ent.id, runId, sessionIdRef.current);
787
- }, [client, patchActive]);
788
- const refreshSessions = useCallback(async () => {
789
- const ent = entityRef.current;
790
- if (!ent) {
791
- setSessions([]);
792
- return;
793
- }
794
- setSessionsLoading(true);
795
- try {
796
- const res = await client.getSessions(ent.type, ent.id, ent.db_id);
797
- setSessions(res.data ?? []);
798
- } finally {
799
- setSessionsLoading(false);
800
- }
801
- }, [client]);
802
- const loadSession = useCallback(
803
- async (id2) => {
804
- const ent = entityRef.current;
805
- if (!ent) return;
806
- abortRef.current?.abort();
807
- activeMsgIdRef.current = null;
808
- runIdRef.current = void 0;
809
- lastContentRef.current = "";
810
- setEvents([]);
811
- setCurrentEvent(null);
812
- setStatus("idle");
813
- setActivity(null);
814
- setError(null);
815
- sessionIdRef.current = id2;
816
- setSessionId(id2);
817
- onSessionId?.(id2);
818
- try {
819
- const runs = await client.getSessionRuns(ent.type, id2, ent.db_id);
820
- setMessages(sessionRunsToMessages(runs));
821
- } catch (err) {
822
- setError(err instanceof Error ? err.message : String(err));
823
- }
824
- },
825
- [client, onSessionId]
826
- );
827
- const deleteSession = useCallback(
828
- async (id2) => {
829
- const ent = entityRef.current;
830
- const ok = await client.deleteSession(id2, ent?.db_id);
831
- if (ok) {
832
- setSessions((prev) => prev.filter((s) => s.session_id !== id2));
833
- if (sessionIdRef.current === id2) {
834
- sessionIdRef.current = void 0;
835
- setSessionId(void 0);
836
- setMessages([]);
837
- }
838
- }
839
- },
840
- [client]
841
- );
842
- const reset = useCallback(() => {
843
- abortRef.current?.abort();
844
- abortRef.current = null;
845
- activeMsgIdRef.current = null;
846
- runIdRef.current = void 0;
847
- lastContentRef.current = "";
848
- sessionIdRef.current = void 0;
849
- setMessages([]);
850
- setEvents([]);
851
- setCurrentEvent(null);
852
- setStatus("idle");
853
- setActivity(null);
854
- setError(null);
855
- setSessionId(void 0);
856
- }, []);
857
- useEffect(() => () => abortRef.current?.abort(), []);
858
- const streamingMessage = useMemo(
859
- () => messages.find((m) => m.role === "agent" && m.streaming) ?? null,
860
- [messages]
861
- );
862
- return {
863
- messages,
864
- streamingMessage,
865
- events,
866
- currentEvent,
867
- status,
868
- activity,
869
- isStreaming: status === "streaming",
870
- isPaused: status === "paused",
871
- error,
872
- sessionId,
873
- entityType: entity?.type,
874
- tools: activeMessage?.tool_calls ?? [],
875
- reasoning: activeMessage?.reasoning_steps,
876
- pendingRequirements: activeMessage?.requirements ?? [],
877
- sessions,
878
- sessionsLoading,
879
- sendMessage,
880
- cancel,
881
- continueRun,
882
- respondToConfirmation,
883
- submitUserInput,
884
- refreshSessions,
885
- loadSession,
886
- deleteSession,
887
- reset,
888
- setMessages,
889
- client
890
- };
891
- }
892
- function ChatInput({
893
- onSend,
894
- onStop,
895
- disabled,
896
- busy,
897
- placeholder = "Ask anything",
898
- allowFiles = false
899
- }) {
900
- const [value, setValue] = useState("");
901
- const [files, setFiles] = useState([]);
902
- const fileRef = useRef(null);
903
- const submit = () => {
904
- const text = value.trim();
905
- if (!text && files.length === 0) return;
906
- onSend(text, files.length ? files : void 0);
907
- setValue("");
908
- setFiles([]);
909
- };
910
- return /* @__PURE__ */ jsxs("div", { className: "agno-input", children: [
911
- files.length > 0 && /* @__PURE__ */ jsx("div", { className: "agno-input__files", children: files.map((f, i) => /* @__PURE__ */ jsxs("span", { className: "agno-input__file", children: [
912
- f.name,
913
- /* @__PURE__ */ jsx("button", { type: "button", onClick: () => setFiles((prev) => prev.filter((_, j) => j !== i)), "aria-label": "Remove", children: "\xD7" })
914
- ] }, i)) }),
915
- /* @__PURE__ */ jsxs("div", { className: "agno-input__row", children: [
916
- allowFiles && /* @__PURE__ */ jsxs(Fragment, { children: [
917
- /* @__PURE__ */ jsx(
918
- "button",
919
- {
920
- type: "button",
921
- className: "agno-input__attach",
922
- onClick: () => fileRef.current?.click(),
923
- disabled,
924
- "aria-label": "Attach files",
925
- children: "\u{1F4CE}"
926
- }
927
- ),
928
- /* @__PURE__ */ jsx(
929
- "input",
930
- {
931
- ref: fileRef,
932
- type: "file",
933
- multiple: true,
934
- hidden: true,
935
- onChange: (e) => setFiles((prev) => [...prev, ...Array.from(e.target.files ?? [])])
936
- }
937
- )
938
- ] }),
939
- /* @__PURE__ */ jsx(
940
- "textarea",
941
- {
942
- className: "agno-input__textarea",
943
- value,
944
- placeholder,
945
- disabled,
946
- rows: 1,
947
- onChange: (e) => setValue(e.target.value),
948
- onKeyDown: (e) => {
949
- if (e.key === "Enter" && !e.shiftKey) {
950
- e.preventDefault();
951
- submit();
952
- }
953
- }
954
- }
955
- ),
956
- busy && onStop ? /* @__PURE__ */ jsx("button", { type: "button", className: "agno-input__send agno-input__send--stop", onClick: onStop, "aria-label": "Stop", children: /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u25A0" }) }) : /* @__PURE__ */ jsx(
957
- "button",
958
- {
959
- type: "button",
960
- className: "agno-input__send",
961
- onClick: submit,
962
- disabled: disabled || !value.trim() && files.length === 0,
963
- "aria-label": "Send",
964
- children: /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u27A4" })
965
- }
966
- )
967
- ] })
968
- ] });
969
- }
970
- var isBoolField = (f) => f.field_type === "bool" || f.field_type === "boolean";
971
- function buildAsks(message, entityType) {
972
- const fromTools = (message.tool_calls ?? []).filter((t) => t.requires_confirmation || t.requires_user_input).map((t) => ({
973
- id: t.tool_call_id ?? `${t.tool_name}`,
974
- name: t.tool_name,
975
- args: t.tool_args,
976
- needsConfirmation: Boolean(t.requires_confirmation) && t.confirmed == null,
977
- fields: t.requires_user_input ? t.user_input_schema ?? [] : [],
978
- tool: t
979
- }));
980
- const fromReqs = (message.requirements ?? []).map((r) => ({
981
- id: r.id,
982
- name: r.tool_execution?.tool_name,
983
- args: r.tool_execution?.tool_args,
984
- needsConfirmation: Boolean(r.tool_execution?.requires_confirmation) || r.confirmation == null,
985
- fields: r.user_input_schema ?? r.tool_execution?.user_input_schema ?? [],
986
- requirement: r
987
- }));
988
- if (entityType === "workflow") return fromReqs.length ? fromReqs : fromTools;
989
- return fromTools.length ? fromTools : fromReqs;
990
- }
991
- function HumanInput({ message, entityType, busy, onResolve }) {
992
- const asks = useMemo(() => buildAsks(message, entityType), [message, entityType]);
993
- const [choices, setChoices] = useState({});
994
- const [values, setValues] = useState({});
995
- const [reasons, setReasons] = useState({});
996
- const [openArgs, setOpenArgs] = useState({});
997
- if (asks.length === 0) return null;
998
- const setValue = (id2, name2, value) => setValues((v) => ({ ...v, [id2]: { ...v[id2] ?? {}, [name2]: value } }));
999
- const valueFor = (ask, field) => values[ask.id]?.[field.name] ?? field.value ?? (isBoolField(field) ? false : "");
1000
- const fillFields = (ask) => ask.fields.map((f) => ({ ...f, value: valueFor(ask, f) }));
1001
- const ready = asks.every((a) => !a.needsConfirmation || choices[a.id]);
1002
- const submit = () => {
1003
- if (entityType === "workflow") {
1004
- const stepRequirements = asks.map((a) => {
1005
- const approved = a.needsConfirmation ? choices[a.id] === "confirm" : true;
1006
- return {
1007
- id: a.id,
1008
- confirmation: approved,
1009
- ...a.fields.length ? { user_input_schema: fillFields(a) } : {},
1010
- tool_execution: a.requirement?.tool_execution,
1011
- ...reasons[a.id] ? { confirmation_note: reasons[a.id] } : {}
1012
- };
1013
- });
1014
- onResolve({ stepRequirements });
1015
- return;
1016
- }
1017
- const tools = asks.map((a) => {
1018
- const base = a.tool ?? { tool_call_id: a.id, tool_name: a.name };
1019
- const approved = a.needsConfirmation ? choices[a.id] === "confirm" : true;
1020
- return {
1021
- ...base,
1022
- ...a.needsConfirmation ? { confirmed: approved } : {},
1023
- ...a.fields.length ? { answered: true, user_input_schema: fillFields(a) } : {},
1024
- ...reasons[a.id] ? { confirmation_note: reasons[a.id] } : {}
1025
- };
1026
- });
1027
- onResolve({ tools });
1028
- };
1029
- return /* @__PURE__ */ jsxs("div", { className: "agno-hitl", children: [
1030
- /* @__PURE__ */ jsxs("div", { className: "agno-hitl__title", children: [
1031
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u270B" }),
1032
- " Your input is needed"
1033
- ] }),
1034
- asks.map((ask) => {
1035
- const choice = choices[ask.id];
1036
- const hasArgs = ask.args && Object.keys(ask.args).length > 0;
1037
- const argsOpen = openArgs[ask.id] ?? true;
1038
- return /* @__PURE__ */ jsxs("div", { className: "agno-hitl-card", children: [
1039
- /* @__PURE__ */ jsxs("div", { className: "agno-hitl-card__head", children: [
1040
- /* @__PURE__ */ jsxs("span", { className: "agno-hitl-card__tool", children: [
1041
- /* @__PURE__ */ jsx("span", { className: "agno-hitl-card__icon", "aria-hidden": true, children: "\u{1F527}" }),
1042
- ask.name ?? "tool"
1043
- ] }),
1044
- ask.needsConfirmation && /* @__PURE__ */ jsxs("span", { className: "agno-hitl-card__choices", children: [
1045
- /* @__PURE__ */ jsx(
1046
- "button",
1047
- {
1048
- type: "button",
1049
- className: `agno-hitl-card__choice ${choice === "reject" ? "is-active is-reject" : ""}`,
1050
- "aria-label": "Reject",
1051
- disabled: busy,
1052
- onClick: () => setChoices((c) => ({ ...c, [ask.id]: "reject" })),
1053
- children: "\u2715"
1054
- }
1055
- ),
1056
- /* @__PURE__ */ jsx(
1057
- "button",
1058
- {
1059
- type: "button",
1060
- className: `agno-hitl-card__choice ${choice === "confirm" ? "is-active is-confirm" : ""}`,
1061
- "aria-label": "Approve",
1062
- disabled: busy,
1063
- onClick: () => setChoices((c) => ({ ...c, [ask.id]: "confirm" })),
1064
- children: "\u2713"
1065
- }
1066
- )
1067
- ] })
1068
- ] }),
1069
- hasArgs && /* @__PURE__ */ jsxs("div", { className: "agno-hitl-card__args", children: [
1070
- /* @__PURE__ */ jsxs(
1071
- "button",
1072
- {
1073
- type: "button",
1074
- className: "agno-hitl-card__args-head",
1075
- onClick: () => setOpenArgs((o) => ({ ...o, [ask.id]: !argsOpen })),
1076
- children: [
1077
- "Arguments",
1078
- /* @__PURE__ */ jsx("span", { className: "agno-hitl-card__chev", children: argsOpen ? "\u25B2" : "\u25BC" })
1079
- ]
1080
- }
1081
- ),
1082
- argsOpen && /* @__PURE__ */ jsx("div", { className: "agno-hitl-card__args-body", children: Object.entries(ask.args ?? {}).map(([k, v]) => /* @__PURE__ */ jsxs("div", { className: "agno-hitl-card__arg", children: [
1083
- /* @__PURE__ */ jsx("span", { className: "agno-hitl-card__arg-key", children: k }),
1084
- /* @__PURE__ */ jsx("span", { className: "agno-hitl-card__arg-val", children: typeof v === "object" ? JSON.stringify(v) : String(v) })
1085
- ] }, k)) })
1086
- ] }),
1087
- choice === "reject" && /* @__PURE__ */ jsx(
1088
- "textarea",
1089
- {
1090
- className: "agno-hitl-card__reason",
1091
- placeholder: "Reason for rejection (optional)\u2026",
1092
- rows: 2,
1093
- value: reasons[ask.id] ?? "",
1094
- disabled: busy,
1095
- onChange: (e) => setReasons((r) => ({ ...r, [ask.id]: e.target.value }))
1096
- }
1097
- ),
1098
- ask.fields.length > 0 && /* @__PURE__ */ jsx("div", { className: "agno-hitl-card__fields", children: ask.fields.map((field) => /* @__PURE__ */ jsxs("label", { className: `agno-hitl-card__field ${isBoolField(field) ? "is-bool" : ""}`, children: [
1099
- /* @__PURE__ */ jsx("span", { className: "agno-hitl-card__field-name", children: field.description || field.name }),
1100
- isBoolField(field) ? /* @__PURE__ */ jsx(
1101
- "input",
1102
- {
1103
- type: "checkbox",
1104
- checked: Boolean(valueFor(ask, field)),
1105
- disabled: busy,
1106
- onChange: (e) => setValue(ask.id, field.name, e.target.checked)
1107
- }
1108
- ) : /* @__PURE__ */ jsx(
1109
- "input",
1110
- {
1111
- className: "agno-hitl-card__input",
1112
- value: String(valueFor(ask, field) ?? ""),
1113
- placeholder: field.field_type ?? "text",
1114
- disabled: busy,
1115
- onChange: (e) => setValue(ask.id, field.name, e.target.value)
1116
- }
1117
- )
1118
- ] }, field.name)) })
1119
- ] }, ask.id);
1120
- }),
1121
- /* @__PURE__ */ jsx("div", { className: "agno-hitl__actions", children: /* @__PURE__ */ jsx("button", { type: "button", className: "agno-btn agno-btn--primary", disabled: busy || !ready, onClick: submit, children: "Continue" }) })
1122
- ] });
1123
- }
1124
- function Citations({
1125
- references,
1126
- citations
1127
- }) {
1128
- const [open, setOpen] = useState(false);
1129
- const refCount = references?.reduce((n, r) => n + (r.references?.length ?? 0), 0) ?? 0;
1130
- const urls = citations?.urls ?? [];
1131
- const total = refCount + urls.length;
1132
- if (total === 0) return null;
1133
- return /* @__PURE__ */ jsxs("div", { className: "agno-citations", children: [
1134
- /* @__PURE__ */ jsxs("button", { type: "button", className: "agno-citations__toggle", onClick: () => setOpen((v) => !v), children: [
1135
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u{1F4DA}" }),
1136
- " ",
1137
- total,
1138
- " source",
1139
- total > 1 ? "s" : "",
1140
- /* @__PURE__ */ jsx("span", { className: "agno-citations__chev", children: open ? "\u25B2" : "\u25BC" })
1141
- ] }),
1142
- open && /* @__PURE__ */ jsxs("div", { className: "agno-citations__body", children: [
1143
- references?.map(
1144
- (group, gi) => (group.references ?? []).map((ref, ri) => /* @__PURE__ */ jsxs("div", { className: "agno-citations__item", children: [
1145
- /* @__PURE__ */ jsx("div", { className: "agno-citations__name", children: ref.name ?? "reference" }),
1146
- /* @__PURE__ */ jsx("div", { className: "agno-citations__snippet", children: ref.content })
1147
- ] }, `r-${gi}-${ri}`))
1148
- ),
1149
- urls.map((u, i) => /* @__PURE__ */ jsx(
1150
- "a",
1151
- {
1152
- className: "agno-citations__url",
1153
- href: u.url,
1154
- target: "_blank",
1155
- rel: "noreferrer noopener",
1156
- children: u.title ?? u.url
1157
- },
1158
- `u-${i}`
1159
- ))
1160
- ] })
1161
- ] });
1162
- }
1163
- function renderInline(text, keyPrefix) {
1164
- const nodes = [];
1165
- const regex = /(`[^`]+`)|(\*\*[^*]+\*\*)|(\*[^*]+\*)|(\[[^\]]+\]\([^)]+\))/g;
1166
- let last = 0;
1167
- let match;
1168
- let i = 0;
1169
- while ((match = regex.exec(text)) !== null) {
1170
- if (match.index > last) nodes.push(text.slice(last, match.index));
1171
- const token = match[0];
1172
- const key = `${keyPrefix}-${i++}`;
1173
- if (token.startsWith("`")) {
1174
- nodes.push(/* @__PURE__ */ jsx("code", { className: "agno-md-code", children: token.slice(1, -1) }, key));
1175
- } else if (token.startsWith("**")) {
1176
- nodes.push(/* @__PURE__ */ jsx("strong", { children: token.slice(2, -2) }, key));
1177
- } else if (token.startsWith("*")) {
1178
- nodes.push(/* @__PURE__ */ jsx("em", { children: token.slice(1, -1) }, key));
1179
- } else {
1180
- const m = /\[([^\]]+)\]\(([^)]+)\)/.exec(token);
1181
- if (m) {
1182
- nodes.push(
1183
- /* @__PURE__ */ jsx("a", { href: m[2], target: "_blank", rel: "noreferrer noopener", children: m[1] }, key)
1184
- );
1185
- } else {
1186
- nodes.push(token);
1187
- }
1188
- }
1189
- last = match.index + token.length;
1190
- }
1191
- if (last < text.length) nodes.push(text.slice(last));
1192
- return nodes;
1193
- }
1194
- function Markdown({ content, className }) {
1195
- const blocks = [];
1196
- const segments = content.split(/(```[\s\S]*?```)/g);
1197
- segments.forEach((segment, si) => {
1198
- if (segment.startsWith("```")) {
1199
- const body = segment.replace(/^```[^\n]*\n?/, "").replace(/```$/, "");
1200
- blocks.push(
1201
- /* @__PURE__ */ jsx("pre", { className: "agno-md-pre", children: /* @__PURE__ */ jsx("code", { children: body }) }, `pre-${si}`)
1202
- );
1203
- return;
1204
- }
1205
- const lines = segment.split("\n");
1206
- let listBuffer = [];
1207
- const flushList = (key) => {
1208
- if (!listBuffer.length) return;
1209
- blocks.push(
1210
- /* @__PURE__ */ jsx("ul", { className: "agno-md-list", children: listBuffer.map((item, ii) => /* @__PURE__ */ jsx("li", { children: renderInline(item, `${key}-${ii}`) }, ii)) }, key)
1211
- );
1212
- listBuffer = [];
1213
- };
1214
- lines.forEach((line, li) => {
1215
- const key = `${si}-${li}`;
1216
- const heading = /^(#{1,4})\s+(.*)$/.exec(line);
1217
- const listItem = /^\s*[-*]\s+(.*)$/.exec(line);
1218
- if (listItem) {
1219
- listBuffer.push(listItem[1]);
1220
- return;
1221
- }
1222
- flushList(`ul-${key}`);
1223
- if (heading) {
1224
- const level = heading[1].length;
1225
- const Tag = `h${Math.min(level + 1, 6)}`;
1226
- blocks.push(
1227
- /* @__PURE__ */ jsx(Tag, { className: "agno-md-heading", children: renderInline(heading[2], `h-${key}`) }, `h-${key}`)
1228
- );
1229
- } else if (line.trim() === "") ; else {
1230
- blocks.push(
1231
- /* @__PURE__ */ jsx("p", { className: "agno-md-p", children: renderInline(line, `p-${key}`) }, `p-${key}`)
1232
- );
1233
- }
1234
- });
1235
- flushList(`ul-end-${si}`);
1236
- });
1237
- return /* @__PURE__ */ jsx("div", { className: ["agno-md", className].filter(Boolean).join(" "), children: blocks });
1238
- }
1239
- function statusOf(tool) {
1240
- if (tool.tool_call_error) return { label: "error", cls: "error" };
1241
- if (tool.requires_confirmation && tool.confirmed == null) return { label: "awaiting approval", cls: "paused" };
1242
- if (tool.requires_user_input && !tool.answered) return { label: "awaiting input", cls: "paused" };
1243
- if (tool.result != null) return { label: "done", cls: "done" };
1244
- return { label: "running", cls: "running" };
1245
- }
1246
- function ToolCall({ tool }) {
1247
- const [open, setOpen] = useState(false);
1248
- const status = statusOf(tool);
1249
- const hasDetail = Boolean(tool.tool_args && Object.keys(tool.tool_args).length) || tool.result != null;
1250
- return /* @__PURE__ */ jsxs("div", { className: `agno-tool agno-tool--${status.cls}`, children: [
1251
- /* @__PURE__ */ jsxs(
1252
- "button",
1253
- {
1254
- type: "button",
1255
- className: "agno-tool__head",
1256
- onClick: () => hasDetail && setOpen((v) => !v),
1257
- "aria-expanded": open,
1258
- children: [
1259
- /* @__PURE__ */ jsx("span", { className: "agno-tool__icon", "aria-hidden": true, children: "\u{1F527}" }),
1260
- /* @__PURE__ */ jsx("span", { className: "agno-tool__name", children: tool.tool_name ?? "tool" }),
1261
- /* @__PURE__ */ jsx("span", { className: `agno-tool__status agno-tool__status--${status.cls}`, children: status.label }),
1262
- hasDetail && /* @__PURE__ */ jsx("span", { className: "agno-tool__chev", children: open ? "\u25B2" : "\u25BC" })
1263
- ]
1264
- }
1265
- ),
1266
- open && hasDetail && /* @__PURE__ */ jsxs("div", { className: "agno-tool__body", children: [
1267
- tool.tool_args && Object.keys(tool.tool_args).length > 0 && /* @__PURE__ */ jsxs("div", { className: "agno-tool__section", children: [
1268
- /* @__PURE__ */ jsx("div", { className: "agno-tool__label", children: "Arguments" }),
1269
- /* @__PURE__ */ jsx("pre", { className: "agno-tool__pre", children: JSON.stringify(tool.tool_args, null, 2) })
1270
- ] }),
1271
- tool.result != null && /* @__PURE__ */ jsxs("div", { className: "agno-tool__section", children: [
1272
- /* @__PURE__ */ jsx("div", { className: "agno-tool__label", children: "Result" }),
1273
- /* @__PURE__ */ jsx("pre", { className: "agno-tool__pre", children: String(tool.result) })
1274
- ] })
1275
- ] })
1276
- ] });
1277
- }
1278
- function ToolCalls({ tools }) {
1279
- if (!tools || tools.length === 0) return null;
1280
- return /* @__PURE__ */ jsx("div", { className: "agno-tools", children: tools.map((tool, i) => /* @__PURE__ */ jsx(ToolCall, { tool }, tool.tool_call_id ?? `${tool.tool_name}-${i}`)) });
1281
- }
1282
- function statusDot(status) {
1283
- if (status === "error") return "error";
1284
- if (status === "completed") return "done";
1285
- return "running";
1286
- }
1287
- function MemberCard({ member, renderMarkdown }) {
1288
- const [open, setOpen] = useState(true);
1289
- const label2 = member.kind === "executor" ? "Step executor" : "Member";
1290
- return /* @__PURE__ */ jsxs("div", { className: "agno-member", children: [
1291
- /* @__PURE__ */ jsxs("button", { type: "button", className: "agno-member__head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
1292
- /* @__PURE__ */ jsx("span", { className: `agno-member__dot agno-member__dot--${statusDot(member.status)}`, "aria-hidden": true }),
1293
- /* @__PURE__ */ jsx("span", { className: "agno-member__name", children: member.name ?? member.agent_id ?? label2 }),
1294
- /* @__PURE__ */ jsx("span", { className: "agno-member__kind", children: label2 }),
1295
- /* @__PURE__ */ jsx("span", { className: "agno-member__chev", children: open ? "\u25B2" : "\u25BC" })
1296
- ] }),
1297
- open && /* @__PURE__ */ jsxs("div", { className: "agno-member__body", children: [
1298
- /* @__PURE__ */ jsx(ToolCalls, { tools: member.tool_calls }),
1299
- member.content && /* @__PURE__ */ jsx("div", { className: "agno-member__content", children: renderMarkdown ? renderMarkdown(member.content) : /* @__PURE__ */ jsx(Markdown, { content: member.content }) })
1300
- ] })
1301
- ] });
1302
- }
1303
- function MemberResponses({
1304
- members,
1305
- renderMarkdown,
1306
- title = "Member responses"
1307
- }) {
1308
- if (!members || members.length === 0) return null;
1309
- return /* @__PURE__ */ jsxs("div", { className: "agno-members", children: [
1310
- /* @__PURE__ */ jsxs("div", { className: "agno-members__title", children: [
1311
- title,
1312
- " (",
1313
- members.length,
1314
- ")"
1315
- ] }),
1316
- members.map((m) => /* @__PURE__ */ jsx(MemberCard, { member: m, renderMarkdown }, m.run_id))
1317
- ] });
1318
- }
1319
- function audioSrc(a) {
1320
- if (a.url) return a.url;
1321
- if (a.base64_audio) return `data:${a.mime_type ?? "audio/mpeg"};base64,${a.base64_audio}`;
1322
- if (a.content) return `data:${a.mime_type ?? "audio/wav"};base64,${a.content}`;
1323
- return void 0;
1324
- }
1325
- function Multimedia({
1326
- images,
1327
- videos,
1328
- audio,
1329
- responseAudio
1330
- }) {
1331
- const audios = [...audio ?? [], ...responseAudio ? [responseAudio] : []];
1332
- if (!images?.length && !videos?.length && !audios.length) return null;
1333
- return /* @__PURE__ */ jsxs("div", { className: "agno-media", children: [
1334
- images?.map(
1335
- (img, i) => img.url ? /* @__PURE__ */ jsx("img", { className: "agno-media__img", src: img.url, alt: img.revised_prompt ?? "image" }, `img-${i}`) : null
1336
- ),
1337
- videos?.map(
1338
- (v, i) => v.url ? /* @__PURE__ */ jsx("video", { className: "agno-media__video", src: v.url, controls: true }, `vid-${i}`) : null
1339
- ),
1340
- audios.map((a, i) => {
1341
- const src = audioSrc(a);
1342
- return src ? /* @__PURE__ */ jsx("audio", { className: "agno-media__audio", src, controls: true }, `aud-${i}`) : null;
1343
- })
1344
- ] });
1345
- }
1346
- function Reasoning({
1347
- steps,
1348
- defaultOpen = false
1349
- }) {
1350
- const [open, setOpen] = useState(defaultOpen);
1351
- if (!steps || steps.length === 0) return null;
1352
- return /* @__PURE__ */ jsxs("div", { className: "agno-reasoning", children: [
1353
- /* @__PURE__ */ jsxs("button", { type: "button", className: "agno-reasoning__toggle", onClick: () => setOpen((v) => !v), children: [
1354
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u{1F4AD}" }),
1355
- " Reasoning (",
1356
- steps.length,
1357
- " step",
1358
- steps.length > 1 ? "s" : "",
1359
- ")",
1360
- /* @__PURE__ */ jsx("span", { className: "agno-reasoning__chev", children: open ? "\u25B2" : "\u25BC" })
1361
- ] }),
1362
- open && /* @__PURE__ */ jsx("ol", { className: "agno-reasoning__list", children: steps.map((step, i) => /* @__PURE__ */ jsxs("li", { className: "agno-reasoning__step", children: [
1363
- step.title && /* @__PURE__ */ jsx("div", { className: "agno-reasoning__title", children: step.title }),
1364
- step.reasoning && /* @__PURE__ */ jsx("div", { className: "agno-reasoning__text", children: step.reasoning }),
1365
- step.action && /* @__PURE__ */ jsxs("div", { className: "agno-reasoning__meta", children: [
1366
- "Action: ",
1367
- step.action
1368
- ] }),
1369
- step.result && /* @__PURE__ */ jsxs("div", { className: "agno-reasoning__meta", children: [
1370
- "Result: ",
1371
- step.result
1372
- ] }),
1373
- typeof step.confidence === "number" && /* @__PURE__ */ jsxs("div", { className: "agno-reasoning__meta", children: [
1374
- "Confidence: ",
1375
- Math.round(step.confidence * 100),
1376
- "%"
1377
- ] })
1378
- ] }, i)) })
1379
- ] });
1380
- }
1381
- function StepRow({ step, renderMarkdown }) {
1382
- const [open, setOpen] = useState(false);
1383
- const hasBody = Boolean(step.content || step.error);
1384
- return /* @__PURE__ */ jsxs("div", { className: `agno-step agno-step--${step.status}`, children: [
1385
- /* @__PURE__ */ jsxs(
1386
- "button",
1387
- {
1388
- type: "button",
1389
- className: "agno-step__head",
1390
- onClick: () => hasBody && setOpen((v) => !v),
1391
- "aria-expanded": open,
1392
- children: [
1393
- /* @__PURE__ */ jsx("span", { className: `agno-step__icon agno-step__icon--${step.status}`, "aria-hidden": true, children: step.status === "completed" ? "\u2713" : step.status === "error" ? "!" : "\u25CF" }),
1394
- /* @__PURE__ */ jsx("span", { className: "agno-step__name", children: step.name ?? step.key }),
1395
- hasBody && /* @__PURE__ */ jsx("span", { className: "agno-step__chev", children: open ? "\u25B2" : "\u25BC" })
1396
- ]
1397
- }
1398
- ),
1399
- open && hasBody && /* @__PURE__ */ jsx("div", { className: "agno-step__body", children: step.error ? /* @__PURE__ */ jsx("div", { className: "agno-step__error", children: step.error }) : step.content ? renderMarkdown ? renderMarkdown(step.content) : /* @__PURE__ */ jsx(Markdown, { content: step.content }) : null })
1400
- ] });
1401
- }
1402
- function WorkflowSteps({
1403
- steps,
1404
- renderMarkdown,
1405
- title = "Steps"
1406
- }) {
1407
- if (!steps || steps.length === 0) return null;
1408
- return /* @__PURE__ */ jsxs("div", { className: "agno-steps", children: [
1409
- /* @__PURE__ */ jsxs("div", { className: "agno-steps__title", children: [
1410
- title,
1411
- " (",
1412
- steps.length,
1413
- ")"
1414
- ] }),
1415
- /* @__PURE__ */ jsx("div", { className: "agno-steps__list", children: steps.map((s) => /* @__PURE__ */ jsx(StepRow, { step: s, renderMarkdown }, s.key)) })
1416
- ] });
1417
- }
1418
- function Message({ message, renderMarkdown, activity, hideReasoning, hideTools }) {
1419
- const isUser = message.role === "user";
1420
- const isAgent = message.role === "agent";
1421
- const hasActivity = !message.content && !message.tool_calls?.length && !message.steps?.length && !message.members?.length && !message.reasoning_steps?.length;
1422
- return /* @__PURE__ */ jsxs("div", { className: `agno-msg agno-msg--${message.role}`, "data-status": message.status, children: [
1423
- /* @__PURE__ */ jsx("div", { className: "agno-msg__avatar", "aria-hidden": true, children: isUser ? "\u{1F464}" : isAgent ? "A" : "\u2699" }),
1424
- /* @__PURE__ */ jsxs("div", { className: "agno-msg__body", children: [
1425
- isAgent && !hideReasoning && /* @__PURE__ */ jsx(Reasoning, { steps: message.reasoning_steps }),
1426
- isAgent && /* @__PURE__ */ jsx(WorkflowSteps, { steps: message.steps, renderMarkdown }),
1427
- isAgent && /* @__PURE__ */ jsx(MemberResponses, { members: message.members, renderMarkdown }),
1428
- isAgent && !hideTools && /* @__PURE__ */ jsx(ToolCalls, { tools: message.tool_calls }),
1429
- message.content ? /* @__PURE__ */ jsxs("div", { className: "agno-msg__content", children: [
1430
- renderMarkdown ? renderMarkdown(message.content) : /* @__PURE__ */ jsx(Markdown, { content: message.content }),
1431
- message.streaming && /* @__PURE__ */ jsx("span", { className: "agno-msg__caret", "aria-hidden": true })
1432
- ] }) : isAgent && message.streaming && hasActivity && /* @__PURE__ */ jsxs("div", { className: "agno-msg__activity", role: "status", "aria-live": "polite", children: [
1433
- /* @__PURE__ */ jsxs("span", { className: "agno-status__dots", "aria-hidden": true, children: [
1434
- /* @__PURE__ */ jsx("span", {}),
1435
- /* @__PURE__ */ jsx("span", {}),
1436
- /* @__PURE__ */ jsx("span", {})
1437
- ] }),
1438
- /* @__PURE__ */ jsx("span", { className: "agno-msg__activity-label", children: activity ?? "Working" })
1439
- ] }),
1440
- /* @__PURE__ */ jsx(
1441
- Multimedia,
1442
- {
1443
- images: message.images,
1444
- videos: message.videos,
1445
- audio: message.audio,
1446
- responseAudio: message.response_audio
1447
- }
1448
- ),
1449
- isAgent && /* @__PURE__ */ jsx(Citations, { references: message.references, citations: message.citations }),
1450
- message.error && /* @__PURE__ */ jsx("div", { className: "agno-msg__error", children: message.error })
1451
- ] })
1452
- ] });
1453
- }
1454
- function MessageList({
1455
- messages,
1456
- status,
1457
- activity,
1458
- renderMarkdown,
1459
- emptyState,
1460
- footer
1461
- }) {
1462
- const endRef = useRef(null);
1463
- const stick = useRef(true);
1464
- const containerRef = useRef(null);
1465
- const onScroll = () => {
1466
- const el = containerRef.current;
1467
- if (!el) return;
1468
- stick.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
1469
- };
1470
- useEffect(() => {
1471
- if (stick.current) endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
1472
- }, [messages, activity, status]);
1473
- return /* @__PURE__ */ jsxs("div", { className: "agno-list", ref: containerRef, onScroll, children: [
1474
- messages.length === 0 && /* @__PURE__ */ jsx("div", { className: "agno-list__empty", children: emptyState ?? "Start the conversation." }),
1475
- messages.map((m) => /* @__PURE__ */ jsx(
1476
- Message,
1477
- {
1478
- message: m,
1479
- renderMarkdown,
1480
- activity: m.streaming && status === "streaming" ? activity : void 0
1481
- },
1482
- m.id
1483
- )),
1484
- footer,
1485
- /* @__PURE__ */ jsx("div", { ref: endRef })
1486
- ] });
1487
- }
1488
- function ChatWindow({
1489
- chat,
1490
- placeholder,
1491
- emptyState,
1492
- allowFiles,
1493
- disabled,
1494
- renderMarkdown,
1495
- className
1496
- }) {
1497
- const pausedMessage = chat.isPaused ? [...chat.messages].reverse().find((m) => m.status === "paused") : void 0;
1498
- return /* @__PURE__ */ jsxs("div", { className: ["agno-chat", className].filter(Boolean).join(" "), children: [
1499
- /* @__PURE__ */ jsx(
1500
- MessageList,
1501
- {
1502
- messages: chat.messages,
1503
- status: chat.status,
1504
- activity: chat.activity,
1505
- renderMarkdown,
1506
- emptyState,
1507
- footer: pausedMessage ? /* @__PURE__ */ jsx(
1508
- HumanInput,
1509
- {
1510
- message: pausedMessage,
1511
- entityType: chat.entityType,
1512
- busy: chat.isStreaming,
1513
- onResolve: chat.continueRun
1514
- }
1515
- ) : null
1516
- }
1517
- ),
1518
- chat.error && !chat.isPaused && /* @__PURE__ */ jsx("div", { className: "agno-chat__error", children: chat.error }),
1519
- /* @__PURE__ */ jsx(
1520
- ChatInput,
1521
- {
1522
- onSend: (message, files) => chat.sendMessage(message, files ? { files } : void 0),
1523
- onStop: chat.cancel,
1524
- busy: chat.isStreaming,
1525
- disabled: disabled || chat.isPaused,
1526
- placeholder,
1527
- allowFiles
1528
- }
1529
- )
1530
- ] });
1531
- }
1532
- var TYPE_LABEL = {
1533
- agent: "Agents",
1534
- team: "Teams",
1535
- workflow: "Workflows"
1536
- };
1537
- var ORDER = ["agent", "team", "workflow"];
1538
- function EntitySelector({
1539
- entities,
1540
- value,
1541
- onChange,
1542
- disabled,
1543
- placeholder = "Select an agent, team or workflow"
1544
- }) {
1545
- const [open, setOpen] = useState(false);
1546
- const rootRef = useRef(null);
1547
- const key = (e) => `${e.type}:${e.id}`;
1548
- useEffect(() => {
1549
- if (!open) return;
1550
- const onDocClick = (e) => {
1551
- if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
1552
- };
1553
- const onKey = (e) => {
1554
- if (e.key === "Escape") setOpen(false);
1555
- };
1556
- document.addEventListener("mousedown", onDocClick);
1557
- document.addEventListener("keydown", onKey);
1558
- return () => {
1559
- document.removeEventListener("mousedown", onDocClick);
1560
- document.removeEventListener("keydown", onKey);
1561
- };
1562
- }, [open]);
1563
- return /* @__PURE__ */ jsxs("div", { className: "agno-select", ref: rootRef, children: [
1564
- /* @__PURE__ */ jsxs(
1565
- "button",
1566
- {
1567
- type: "button",
1568
- className: "agno-select__trigger",
1569
- disabled,
1570
- "aria-haspopup": "listbox",
1571
- "aria-expanded": open,
1572
- onClick: () => setOpen((v) => !v),
1573
- children: [
1574
- /* @__PURE__ */ jsx("span", { className: "agno-select__value", children: value ? value.name : placeholder }),
1575
- /* @__PURE__ */ jsx("span", { className: `agno-select__chev ${open ? "is-open" : ""}`, "aria-hidden": true, children: "\u2304" })
1576
- ]
1577
- }
1578
- ),
1579
- open && /* @__PURE__ */ jsxs("div", { className: "agno-select__panel", role: "listbox", children: [
1580
- entities.length === 0 && /* @__PURE__ */ jsx("div", { className: "agno-select__empty", children: "Nothing available" }),
1581
- ORDER.map((type) => {
1582
- const items = entities.filter((e) => e.type === type);
1583
- if (items.length === 0) return null;
1584
- return /* @__PURE__ */ jsxs("div", { className: "agno-select__group", children: [
1585
- /* @__PURE__ */ jsx("div", { className: "agno-select__group-label", children: TYPE_LABEL[type] }),
1586
- items.map((ent) => {
1587
- const selected = value ? key(value) === key(ent) : false;
1588
- return /* @__PURE__ */ jsxs(
1589
- "button",
1590
- {
1591
- type: "button",
1592
- role: "option",
1593
- "aria-selected": selected,
1594
- className: `agno-select__option ${selected ? "is-selected" : ""}`,
1595
- onClick: () => {
1596
- onChange(ent);
1597
- setOpen(false);
1598
- },
1599
- children: [
1600
- /* @__PURE__ */ jsx("span", { className: "agno-select__check", "aria-hidden": true, children: selected ? "\u2713" : "" }),
1601
- /* @__PURE__ */ jsx("span", { className: "agno-select__label", children: ent.name }),
1602
- ent.model?.model && /* @__PURE__ */ jsx("span", { className: "agno-select__model", children: ent.model.model })
1603
- ]
1604
- },
1605
- key(ent)
1606
- );
1607
- })
1608
- ] }, type);
1609
- })
1610
- ] })
1611
- ] });
1612
- }
1613
- function sourceOf(e) {
1614
- return e.agent_name || e.team_name || e.workflow_name || e.agent_id || e.team_id || e.workflow_id || void 0;
1615
- }
1616
- function fold(events) {
1617
- const rows = [];
1618
- for (const e of events) {
1619
- const name2 = String(e.event);
1620
- const source = sourceOf(e);
1621
- const last = rows[rows.length - 1];
1622
- if (last && last.event === name2 && last.source === source) {
1623
- last.count += 1;
1624
- last.created_at = e.created_at ?? last.created_at;
1625
- continue;
1626
- }
1627
- rows.push({ event: name2, source, count: 1, created_at: e.created_at, detail: activityLabel(e) });
1628
- }
1629
- return rows;
1630
- }
1631
- function EventLog({
1632
- events,
1633
- autoScroll = true,
1634
- maxHeight = 240
1635
- }) {
1636
- const ref = useRef(null);
1637
- const rows = useMemo(() => fold(events), [events]);
1638
- useEffect(() => {
1639
- if (autoScroll && ref.current) ref.current.scrollTop = ref.current.scrollHeight;
1640
- }, [rows, autoScroll]);
1641
- return /* @__PURE__ */ jsxs("div", { className: "agno-eventlog", ref, style: { maxHeight }, children: [
1642
- rows.length === 0 && /* @__PURE__ */ jsx("div", { className: "agno-eventlog__empty", children: "No events yet." }),
1643
- rows.map((row, i) => /* @__PURE__ */ jsxs("div", { className: "agno-eventlog__row", children: [
1644
- /* @__PURE__ */ jsx("span", { className: "agno-eventlog__name", children: row.event }),
1645
- row.count > 1 && /* @__PURE__ */ jsxs("span", { className: "agno-eventlog__count", children: [
1646
- "\xD7",
1647
- row.count
1648
- ] }),
1649
- row.source && /* @__PURE__ */ jsx("span", { className: "agno-eventlog__source", children: row.source }),
1650
- row.created_at && /* @__PURE__ */ jsx("span", { className: "agno-eventlog__time", children: new Date(row.created_at * 1e3).toLocaleTimeString() })
1651
- ] }, i))
1652
- ] });
1653
- }
1654
- function label(session) {
1655
- return session.session_name?.trim() || session.session_id;
1656
- }
1657
- function formatDate(value) {
1658
- if (value == null) return "";
1659
- let date;
1660
- if (typeof value === "number") {
1661
- date = new Date(value < 1e12 ? value * 1e3 : value);
1662
- } else {
1663
- date = new Date(value);
1664
- }
1665
- if (Number.isNaN(date.getTime())) return "";
1666
- return date.toLocaleDateString();
1667
- }
1668
- function SessionList({
1669
- sessions,
1670
- activeSessionId,
1671
- loading,
1672
- onSelect,
1673
- onDelete,
1674
- onNew,
1675
- title = "Sessions"
1676
- }) {
1677
- return /* @__PURE__ */ jsxs("div", { className: "agno-sessions", children: [
1678
- onNew && /* @__PURE__ */ jsxs("button", { type: "button", className: "agno-sessions__new", onClick: onNew, "aria-label": "New chat", children: [
1679
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "+" }),
1680
- " New Chat"
1681
- ] }),
1682
- /* @__PURE__ */ jsx("div", { className: "agno-sessions__head", children: /* @__PURE__ */ jsx("span", { className: "agno-sessions__title", children: title }) }),
1683
- loading && /* @__PURE__ */ jsx("div", { className: "agno-sessions__empty", children: "Loading\u2026" }),
1684
- !loading && sessions.length === 0 && /* @__PURE__ */ jsx("div", { className: "agno-sessions__empty", children: "No past sessions." }),
1685
- /* @__PURE__ */ jsx("ul", { className: "agno-sessions__list", children: sessions.map((session) => /* @__PURE__ */ jsxs(
1686
- "li",
1687
- {
1688
- className: `agno-sessions__item ${session.session_id === activeSessionId ? "is-active" : ""}`,
1689
- children: [
1690
- /* @__PURE__ */ jsxs("button", { type: "button", className: "agno-sessions__select", onClick: () => onSelect(session.session_id), children: [
1691
- /* @__PURE__ */ jsx("span", { className: "agno-sessions__name", children: label(session) }),
1692
- formatDate(session.created_at) && /* @__PURE__ */ jsx("span", { className: "agno-sessions__date", children: formatDate(session.created_at) })
1693
- ] }),
1694
- onDelete && /* @__PURE__ */ jsx(
1695
- "button",
1696
- {
1697
- type: "button",
1698
- className: "agno-sessions__delete",
1699
- "aria-label": "Delete session",
1700
- onClick: () => onDelete(session.session_id),
1701
- children: "\u{1F5D1}"
1702
- }
1703
- )
1704
- ]
1705
- },
1706
- session.session_id
1707
- )) })
1708
- ] });
1709
- }
1710
- function AgnoChat(props) {
1711
- const client = useMemo(
1712
- () => props.client ?? new AgnoClient({ baseUrl: props.baseUrl ?? "", headers: props.headers }),
1713
- [props.client, props.baseUrl, props.headers]
1714
- );
1715
- const [discovered, setDiscovered] = useState(props.entities ?? []);
1716
- const [selected, setSelected] = useState(props.entity ?? null);
1717
- const [showLog, setShowLog] = useState(false);
1718
- const [discoveryDone, setDiscoveryDone] = useState(Boolean(props.entity || props.entities));
1719
- useEffect(() => {
1720
- if (props.entity || props.entities) return;
1721
- let cancelled = false;
1722
- setDiscoveryDone(false);
1723
- client.getEntities().then((list) => {
1724
- if (cancelled) return;
1725
- setDiscovered(list);
1726
- setSelected((cur) => cur ?? list[0] ?? null);
1727
- setDiscoveryDone(true);
1728
- });
1729
- return () => {
1730
- cancelled = true;
1731
- };
1732
- }, [client, props.entity, props.entities]);
1733
- const entity = props.entity ?? selected;
1734
- const chat = useAgnoChat({ client, entity, userId: props.userId });
1735
- const { refreshSessions } = chat;
1736
- useEffect(() => {
1737
- if (props.showSessions && entity) refreshSessions();
1738
- }, [props.showSessions, entity?.type, entity?.id, refreshSessions]);
1739
- useEffect(() => {
1740
- if (props.showSessions && entity && chat.status === "completed") refreshSessions();
1741
- }, [chat.status]);
1742
- const onSelect = (e) => {
1743
- setSelected(e);
1744
- chat.reset();
1745
- };
1746
- const showSelector = !props.entity;
1747
- const entities = props.entities ?? discovered;
1748
- const noEntities = showSelector && discoveryDone && entities.length === 0;
1749
- return /* @__PURE__ */ jsxs(
1750
- "div",
1751
- {
1752
- className: ["agno-root", props.className].filter(Boolean).join(" "),
1753
- style: { height: props.height ?? 560 },
1754
- children: [
1755
- /* @__PURE__ */ jsxs("div", { className: "agno-header", children: [
1756
- /* @__PURE__ */ jsxs("div", { className: "agno-header__brand", children: [
1757
- /* @__PURE__ */ jsx("span", { className: "agno-logo", "aria-hidden": true, children: "A" }),
1758
- /* @__PURE__ */ jsx("span", { className: "agno-header__title", children: props.title ?? entity?.name ?? "Agent UI" })
1759
- ] }),
1760
- /* @__PURE__ */ jsxs("div", { className: "agno-header__controls", children: [
1761
- showSelector && /* @__PURE__ */ jsx(EntitySelector, { entities, value: entity, onChange: onSelect, disabled: chat.isStreaming }),
1762
- props.showEventLog && /* @__PURE__ */ jsx(
1763
- "button",
1764
- {
1765
- type: "button",
1766
- className: `agno-btn agno-btn--ghost ${showLog ? "is-active" : ""}`,
1767
- onClick: () => setShowLog((v) => !v),
1768
- children: "Events"
1769
- }
1770
- ),
1771
- /* @__PURE__ */ jsx("button", { type: "button", className: "agno-btn agno-btn--ghost", onClick: chat.reset, disabled: chat.isStreaming, children: "New chat" })
1772
- ] })
1773
- ] }),
1774
- noEntities && /* @__PURE__ */ jsxs("div", { className: "agno-banner", children: [
1775
- "No agents, teams or workflows found at ",
1776
- /* @__PURE__ */ jsx("code", { children: client.baseUrl || "(no URL)" }),
1777
- ". Check the URL is correct, that AgentOS is running, and that this origin is in its CORS allowlist (",
1778
- /* @__PURE__ */ jsx("code", { children: "cors_allowed_origins" }),
1779
- ")."
1780
- ] }),
1781
- /* @__PURE__ */ jsxs("div", { className: "agno-main", children: [
1782
- props.showSessions && /* @__PURE__ */ jsx("div", { className: "agno-sidebar agno-sidebar--left", children: /* @__PURE__ */ jsx(
1783
- SessionList,
1784
- {
1785
- sessions: chat.sessions,
1786
- activeSessionId: chat.sessionId,
1787
- loading: chat.sessionsLoading,
1788
- onSelect: chat.loadSession,
1789
- onDelete: chat.deleteSession,
1790
- onNew: chat.reset
1791
- }
1792
- ) }),
1793
- /* @__PURE__ */ jsx(
1794
- ChatWindow,
1795
- {
1796
- chat,
1797
- placeholder: props.placeholder,
1798
- allowFiles: props.allowFiles,
1799
- disabled: !entity,
1800
- renderMarkdown: props.renderMarkdown,
1801
- emptyState: entity ? `Chat with ${entity.name}.` : "Select an agent, team or workflow to begin."
1802
- }
1803
- ),
1804
- props.showEventLog && showLog && /* @__PURE__ */ jsxs("div", { className: "agno-sidebar", children: [
1805
- /* @__PURE__ */ jsx("div", { className: "agno-sidebar__title", children: "Event stream" }),
1806
- /* @__PURE__ */ jsx(EventLog, { events: chat.events })
1807
- ] })
1808
- ] })
1809
- ]
1810
- }
1811
- );
1812
- }
1813
- function StatusIndicator({
1814
- status,
1815
- activity
1816
- }) {
1817
- if (status !== "streaming" && status !== "paused") return null;
1818
- const label2 = activity ?? (status === "paused" ? "Waiting for input" : "Working");
1819
- return /* @__PURE__ */ jsxs("div", { className: `agno-status agno-status--${status}`, role: "status", "aria-live": "polite", children: [
1820
- /* @__PURE__ */ jsxs("span", { className: "agno-status__dots", "aria-hidden": true, children: [
1821
- /* @__PURE__ */ jsx("span", {}),
1822
- /* @__PURE__ */ jsx("span", {}),
1823
- /* @__PURE__ */ jsx("span", {})
1824
- ] }),
1825
- /* @__PURE__ */ jsx("span", { className: "agno-status__label", children: label2 })
1826
- ] });
1827
- }
1828
-
1829
- // src/types.ts
1830
- var RunEvent = /* @__PURE__ */ ((RunEvent2) => {
1831
- RunEvent2["RunStarted"] = "RunStarted";
1832
- RunEvent2["RunContent"] = "RunContent";
1833
- RunEvent2["RunContentCompleted"] = "RunContentCompleted";
1834
- RunEvent2["RunIntermediateContent"] = "RunIntermediateContent";
1835
- RunEvent2["RunCompleted"] = "RunCompleted";
1836
- RunEvent2["RunError"] = "RunError";
1837
- RunEvent2["RunCancelled"] = "RunCancelled";
1838
- RunEvent2["RunPaused"] = "RunPaused";
1839
- RunEvent2["RunContinued"] = "RunContinued";
1840
- RunEvent2["PreHookStarted"] = "PreHookStarted";
1841
- RunEvent2["PreHookCompleted"] = "PreHookCompleted";
1842
- RunEvent2["PostHookStarted"] = "PostHookStarted";
1843
- RunEvent2["PostHookCompleted"] = "PostHookCompleted";
1844
- RunEvent2["ToolCallStarted"] = "ToolCallStarted";
1845
- RunEvent2["ToolCallCompleted"] = "ToolCallCompleted";
1846
- RunEvent2["ToolCallError"] = "ToolCallError";
1847
- RunEvent2["ReasoningStarted"] = "ReasoningStarted";
1848
- RunEvent2["ReasoningStep"] = "ReasoningStep";
1849
- RunEvent2["ReasoningContentDelta"] = "ReasoningContentDelta";
1850
- RunEvent2["ReasoningCompleted"] = "ReasoningCompleted";
1851
- RunEvent2["MemoryUpdateStarted"] = "MemoryUpdateStarted";
1852
- RunEvent2["MemoryUpdateCompleted"] = "MemoryUpdateCompleted";
1853
- RunEvent2["SessionSummaryStarted"] = "SessionSummaryStarted";
1854
- RunEvent2["SessionSummaryCompleted"] = "SessionSummaryCompleted";
1855
- RunEvent2["ParserModelResponseStarted"] = "ParserModelResponseStarted";
1856
- RunEvent2["ParserModelResponseCompleted"] = "ParserModelResponseCompleted";
1857
- RunEvent2["OutputModelResponseStarted"] = "OutputModelResponseStarted";
1858
- RunEvent2["OutputModelResponseCompleted"] = "OutputModelResponseCompleted";
1859
- RunEvent2["ModelRequestStarted"] = "ModelRequestStarted";
1860
- RunEvent2["ModelRequestCompleted"] = "ModelRequestCompleted";
1861
- RunEvent2["CompressionStarted"] = "CompressionStarted";
1862
- RunEvent2["CompressionCompleted"] = "CompressionCompleted";
1863
- RunEvent2["FollowupsStarted"] = "FollowupsStarted";
1864
- RunEvent2["FollowupsCompleted"] = "FollowupsCompleted";
1865
- RunEvent2["CustomEvent"] = "CustomEvent";
1866
- return RunEvent2;
1867
- })(RunEvent || {});
1868
- var TeamRunEvent = /* @__PURE__ */ ((TeamRunEvent2) => {
1869
- TeamRunEvent2["TeamRunStarted"] = "TeamRunStarted";
1870
- TeamRunEvent2["TeamRunContent"] = "TeamRunContent";
1871
- TeamRunEvent2["TeamRunIntermediateContent"] = "TeamRunIntermediateContent";
1872
- TeamRunEvent2["TeamRunContentCompleted"] = "TeamRunContentCompleted";
1873
- TeamRunEvent2["TeamRunCompleted"] = "TeamRunCompleted";
1874
- TeamRunEvent2["TeamRunError"] = "TeamRunError";
1875
- TeamRunEvent2["TeamRunCancelled"] = "TeamRunCancelled";
1876
- TeamRunEvent2["TeamRunPaused"] = "TeamRunPaused";
1877
- TeamRunEvent2["TeamRunContinued"] = "TeamRunContinued";
1878
- TeamRunEvent2["TeamToolCallStarted"] = "TeamToolCallStarted";
1879
- TeamRunEvent2["TeamToolCallCompleted"] = "TeamToolCallCompleted";
1880
- TeamRunEvent2["TeamToolCallError"] = "TeamToolCallError";
1881
- TeamRunEvent2["TeamReasoningStarted"] = "TeamReasoningStarted";
1882
- TeamRunEvent2["TeamReasoningStep"] = "TeamReasoningStep";
1883
- TeamRunEvent2["TeamReasoningContentDelta"] = "TeamReasoningContentDelta";
1884
- TeamRunEvent2["TeamReasoningCompleted"] = "TeamReasoningCompleted";
1885
- TeamRunEvent2["TeamMemoryUpdateStarted"] = "TeamMemoryUpdateStarted";
1886
- TeamRunEvent2["TeamMemoryUpdateCompleted"] = "TeamMemoryUpdateCompleted";
1887
- TeamRunEvent2["TeamTaskIterationStarted"] = "TeamTaskIterationStarted";
1888
- TeamRunEvent2["TeamTaskIterationCompleted"] = "TeamTaskIterationCompleted";
1889
- TeamRunEvent2["TeamTaskStateUpdated"] = "TeamTaskStateUpdated";
1890
- TeamRunEvent2["TeamTaskCreated"] = "TeamTaskCreated";
1891
- TeamRunEvent2["TeamTaskUpdated"] = "TeamTaskUpdated";
1892
- return TeamRunEvent2;
1893
- })(TeamRunEvent || {});
1894
- var WorkflowRunEvent = /* @__PURE__ */ ((WorkflowRunEvent2) => {
1895
- WorkflowRunEvent2["WorkflowStarted"] = "WorkflowStarted";
1896
- WorkflowRunEvent2["WorkflowCompleted"] = "WorkflowCompleted";
1897
- WorkflowRunEvent2["WorkflowPaused"] = "WorkflowPaused";
1898
- WorkflowRunEvent2["WorkflowCancelled"] = "WorkflowCancelled";
1899
- WorkflowRunEvent2["WorkflowError"] = "WorkflowError";
1900
- WorkflowRunEvent2["WorkflowAgentStarted"] = "WorkflowAgentStarted";
1901
- WorkflowRunEvent2["WorkflowAgentCompleted"] = "WorkflowAgentCompleted";
1902
- WorkflowRunEvent2["StepStarted"] = "StepStarted";
1903
- WorkflowRunEvent2["StepCompleted"] = "StepCompleted";
1904
- WorkflowRunEvent2["StepPaused"] = "StepPaused";
1905
- WorkflowRunEvent2["StepContinued"] = "StepContinued";
1906
- WorkflowRunEvent2["StepError"] = "StepError";
1907
- WorkflowRunEvent2["StepOutput"] = "StepOutput";
1908
- WorkflowRunEvent2["StepOutputReview"] = "StepOutputReview";
1909
- WorkflowRunEvent2["LoopExecutionStarted"] = "LoopExecutionStarted";
1910
- WorkflowRunEvent2["LoopIterationStarted"] = "LoopIterationStarted";
1911
- WorkflowRunEvent2["LoopIterationCompleted"] = "LoopIterationCompleted";
1912
- WorkflowRunEvent2["LoopExecutionCompleted"] = "LoopExecutionCompleted";
1913
- WorkflowRunEvent2["ParallelExecutionStarted"] = "ParallelExecutionStarted";
1914
- WorkflowRunEvent2["ParallelExecutionCompleted"] = "ParallelExecutionCompleted";
1915
- WorkflowRunEvent2["ConditionExecutionStarted"] = "ConditionExecutionStarted";
1916
- WorkflowRunEvent2["ConditionExecutionCompleted"] = "ConditionExecutionCompleted";
1917
- WorkflowRunEvent2["ConditionPaused"] = "ConditionPaused";
1918
- WorkflowRunEvent2["RouterExecutionStarted"] = "RouterExecutionStarted";
1919
- WorkflowRunEvent2["RouterExecutionCompleted"] = "RouterExecutionCompleted";
1920
- WorkflowRunEvent2["RouterPaused"] = "RouterPaused";
1921
- WorkflowRunEvent2["StepsExecutionStarted"] = "StepsExecutionStarted";
1922
- WorkflowRunEvent2["StepsExecutionCompleted"] = "StepsExecutionCompleted";
1923
- return WorkflowRunEvent2;
1924
- })(WorkflowRunEvent || {});
1925
-
1926
- export { AgnoChat, AgnoClient, ChatInput, ChatWindow, Citations, EntitySelector, EventLog, HumanInput, Markdown, MemberResponses, Message, MessageList, Multimedia, Reasoning, RunEvent, SessionList, StatusIndicator, TeamRunEvent, ToolCalls, WorkflowRunEvent, WorkflowSteps, activityLabel, applyStepEvent, applySubRunEvent, isCompletedEvent, isContentEvent, isErrorEvent, isPausedEvent, isReasoningStepEvent, isStepEvent, isSubRunEvent, isToolEvent, mergeTool, normaliseBaseUrl, sessionRunsToMessages, streamRun, toolsFromEvent, useAgnoChat };
2
+ export { AgnoChat, AgnoMark, ArrowUp, BehindTheScenes, BookOpen, Box, Brain, ChatBubble, ChatInput, ChatLauncher, ChatProvider, ChatWindow, Check, ChevronDown, Citations, Close, Copy, EntityBadge, EntitySelector, EventLog, Favicon, FileAudio, FileIcon, FilePreview, FileVideo, Followups, Globe, GridLoader, HoverPreview, HumanInput, LinkPreviewCard, Markdown, MemberResponses, Memory, Message, MessageList, Multimedia, Paperclip, Plus, Pulse, QuickPrompts, Reasoning, Rerun, SessionList, SourceCard, SourcesProvider, Spinner, StatusIndicator, Stop, TeamGlyph, ToolCalls, Trash, WorkflowSteps, Wrench, behindTheScenesItems, behindTheScenesLabel, collectSources, cx, displayUrl, faviconUrl, getProviderIcon, hasBehindTheScenes, linkCitations, normalizeFollowups, quickPromptLabel, quickPromptText, sourceHost, sourcesFromMarkdown, useAgnoChat, useChatContext, useLinkPreview, useOptionalChatContext, useResolvedChat, useResolvedClassNames, useSources, withoutSourcesLine, writeClipboard } from './chunk-MUOMZG4V.js';
3
+ export { RunEvent, TeamRunEvent, WorkflowRunEvent } from './chunk-RE7ZT73K.js';
4
+ export { AgnoClient, activityLabel, applyStepEvent, applySubRunEvent, isCompletedEvent, isContentEvent, isErrorEvent, isFollowupsCompletedEvent, isPausedEvent, isReasoningStepEvent, isStepEvent, isSubRunEvent, isToolEvent, mergeTool, normaliseBaseUrl, sessionRunsToMessages, streamRun, toolsFromEvent } from './chunk-62IEW2HM.js';
1927
5
  //# sourceMappingURL=index.js.map
1928
6
  //# sourceMappingURL=index.js.map