@agno-hq/chat-react 0.1.1 → 0.3.1

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