@apteva/apteva-kit 0.1.7 → 0.1.10
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.d.mts +84 -6
- package/dist/index.d.ts +84 -6
- package/dist/index.js +1479 -139
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1572 -232
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2
5
|
|
|
3
6
|
// src/components/Chat/Chat.tsx
|
|
4
7
|
import { useState as useState2, useEffect as useEffect3 } from "react";
|
|
@@ -182,6 +185,237 @@ function generateMockStreamingResponse(text, onChunk, typingSpeed = 30) {
|
|
|
182
185
|
}, typingSpeed);
|
|
183
186
|
});
|
|
184
187
|
}
|
|
188
|
+
function generateMockPlan(command) {
|
|
189
|
+
const lowerCommand = command.toLowerCase();
|
|
190
|
+
if (lowerCommand.includes("analyze") || lowerCommand.includes("analysis")) {
|
|
191
|
+
return `**Plan:**
|
|
192
|
+
|
|
193
|
+
1. Fetch data from the analytics database
|
|
194
|
+
2. Apply filters and aggregations
|
|
195
|
+
3. Calculate key metrics and trends
|
|
196
|
+
4. Generate visualization data
|
|
197
|
+
5. Compile insights and recommendations`;
|
|
198
|
+
}
|
|
199
|
+
if (lowerCommand.includes("sales") || lowerCommand.includes("revenue")) {
|
|
200
|
+
return `**Plan:**
|
|
201
|
+
|
|
202
|
+
1. Query sales records for the specified period
|
|
203
|
+
2. Calculate total revenue and growth rates
|
|
204
|
+
3. Break down performance by product category
|
|
205
|
+
4. Analyze regional distribution
|
|
206
|
+
5. Present findings in charts and summary`;
|
|
207
|
+
}
|
|
208
|
+
if (lowerCommand.includes("report") || lowerCommand.includes("summary")) {
|
|
209
|
+
return `**Plan:**
|
|
210
|
+
|
|
211
|
+
1. Gather data from all relevant sources
|
|
212
|
+
2. Aggregate metrics across categories
|
|
213
|
+
3. Identify key trends and anomalies
|
|
214
|
+
4. Generate executive summary
|
|
215
|
+
5. Create detailed breakdowns with visualizations`;
|
|
216
|
+
}
|
|
217
|
+
if (lowerCommand.includes("customer") || lowerCommand.includes("user")) {
|
|
218
|
+
return `**Plan:**
|
|
219
|
+
|
|
220
|
+
1. Pull customer data from CRM
|
|
221
|
+
2. Calculate engagement metrics
|
|
222
|
+
3. Segment users by behavior patterns
|
|
223
|
+
4. Analyze satisfaction scores
|
|
224
|
+
5. Generate customer insights report`;
|
|
225
|
+
}
|
|
226
|
+
if (lowerCommand.includes("task") || lowerCommand.includes("todo") || lowerCommand.includes("work") || lowerCommand.includes("completed")) {
|
|
227
|
+
return `**Plan:**
|
|
228
|
+
|
|
229
|
+
1. Retrieve task records from the database
|
|
230
|
+
2. Filter by status and date range
|
|
231
|
+
3. Organize by priority and category
|
|
232
|
+
4. Calculate completion metrics
|
|
233
|
+
5. Display in interactive list format`;
|
|
234
|
+
}
|
|
235
|
+
return `**Plan:**
|
|
236
|
+
|
|
237
|
+
1. Parse and understand the command requirements
|
|
238
|
+
2. Gather necessary data from available sources
|
|
239
|
+
3. Process and analyze the information
|
|
240
|
+
4. Format results for optimal presentation
|
|
241
|
+
5. Return response with any relevant visualizations`;
|
|
242
|
+
}
|
|
243
|
+
function generateMockCommandResponse(command) {
|
|
244
|
+
const lowerCommand = command.toLowerCase();
|
|
245
|
+
if (lowerCommand.includes("analyze") || lowerCommand.includes("analysis")) {
|
|
246
|
+
return `Analysis complete for "${command}". Found 247 records with an average value of $1,234. The data shows a 23% increase compared to last quarter. Key insights: Revenue is up, customer satisfaction improved by 15%, and operational costs decreased by 8%.`;
|
|
247
|
+
}
|
|
248
|
+
if (lowerCommand.includes("sales") || lowerCommand.includes("revenue")) {
|
|
249
|
+
return `Sales data processed: Q4 2024 revenue reached $2.4M, representing 18% growth year-over-year. Top performing products: Enterprise Plan (+45%), Pro Plan (+32%), Basic Plan (+12%). Regional breakdown: North America (52%), Europe (31%), APAC (17%).`;
|
|
250
|
+
}
|
|
251
|
+
if (lowerCommand.includes("report") || lowerCommand.includes("summary")) {
|
|
252
|
+
return `Report generated successfully. Executive Summary: Overall performance exceeded targets by 12%. Marketing ROI improved to 3.2x, customer acquisition cost reduced by 18%, and lifetime value increased by 24%. Detailed breakdown available in attached widgets.`;
|
|
253
|
+
}
|
|
254
|
+
if (lowerCommand.includes("data") || lowerCommand.includes("metrics")) {
|
|
255
|
+
return `Data metrics retrieved: 1,847 active users, 12,394 sessions this month, 94.2% uptime, average response time 127ms. Performance is within acceptable parameters. No critical issues detected.`;
|
|
256
|
+
}
|
|
257
|
+
if (lowerCommand.includes("customer") || lowerCommand.includes("user")) {
|
|
258
|
+
return `Customer analysis complete: 523 new customers this month, 89% retention rate, average satisfaction score 4.6/5. Top feedback themes: excellent support (87%), easy to use (72%), good value (68%). 3 support tickets pending review.`;
|
|
259
|
+
}
|
|
260
|
+
return `This is a mock response showing how your agent would process and respond to commands. The actual response would be generated by your AI agent based on real data and context.`;
|
|
261
|
+
}
|
|
262
|
+
function generateMockCommandWithWidgets(command) {
|
|
263
|
+
const message = generateMockCommandResponse(command);
|
|
264
|
+
const lowerCommand = command.toLowerCase();
|
|
265
|
+
let widgets = [];
|
|
266
|
+
let action;
|
|
267
|
+
if (lowerCommand.includes("sales") || lowerCommand.includes("revenue") || lowerCommand.includes("analyze")) {
|
|
268
|
+
widgets.push({
|
|
269
|
+
type: "card",
|
|
270
|
+
id: `widget-${Date.now()}-1`,
|
|
271
|
+
props: {
|
|
272
|
+
title: "Q4 2024 Performance",
|
|
273
|
+
description: "Revenue: $2.4M (+18% YoY)",
|
|
274
|
+
footer: "Updated: " + (/* @__PURE__ */ new Date()).toLocaleDateString()
|
|
275
|
+
},
|
|
276
|
+
actions: [
|
|
277
|
+
{
|
|
278
|
+
type: "view_details",
|
|
279
|
+
label: "View Details",
|
|
280
|
+
handler: "client",
|
|
281
|
+
payload: { reportId: "q4-2024" }
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
if (lowerCommand.includes("customer") || lowerCommand.includes("user")) {
|
|
287
|
+
widgets.push({
|
|
288
|
+
type: "list",
|
|
289
|
+
id: `widget-${Date.now()}-2`,
|
|
290
|
+
props: {
|
|
291
|
+
items: [
|
|
292
|
+
{
|
|
293
|
+
id: "metric-1",
|
|
294
|
+
title: "Active Users",
|
|
295
|
+
subtitle: "1,847 users",
|
|
296
|
+
description: "+12% from last month"
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
id: "metric-2",
|
|
300
|
+
title: "Retention Rate",
|
|
301
|
+
subtitle: "89%",
|
|
302
|
+
description: "Above industry average"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: "metric-3",
|
|
306
|
+
title: "Satisfaction Score",
|
|
307
|
+
subtitle: "4.6/5",
|
|
308
|
+
description: "Based on 234 reviews"
|
|
309
|
+
}
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
if (lowerCommand.includes("task") || lowerCommand.includes("todo") || lowerCommand.includes("work") || lowerCommand.includes("completed")) {
|
|
315
|
+
widgets.push({
|
|
316
|
+
type: "list",
|
|
317
|
+
id: `widget-${Date.now()}-tasks`,
|
|
318
|
+
props: {
|
|
319
|
+
items: [
|
|
320
|
+
{
|
|
321
|
+
id: "task-1",
|
|
322
|
+
title: "Implement user authentication",
|
|
323
|
+
subtitle: "Created just now",
|
|
324
|
+
description: "Added OAuth 2.0 support with Google and GitHub providers",
|
|
325
|
+
backgroundColor: "rgba(59, 130, 246, 0.15)",
|
|
326
|
+
metadata: {
|
|
327
|
+
status: "created",
|
|
328
|
+
priority: "high",
|
|
329
|
+
tags: ["backend", "security"]
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
id: "task-2",
|
|
334
|
+
title: "Update API documentation",
|
|
335
|
+
subtitle: "Modified 2 minutes ago",
|
|
336
|
+
description: "Changed endpoint descriptions and added new examples",
|
|
337
|
+
backgroundColor: "rgba(234, 179, 8, 0.15)",
|
|
338
|
+
metadata: {
|
|
339
|
+
status: "modified",
|
|
340
|
+
priority: "medium",
|
|
341
|
+
tags: ["docs"]
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
id: "task-3",
|
|
346
|
+
title: "Fix login redirect bug",
|
|
347
|
+
subtitle: "Completed 5 minutes ago",
|
|
348
|
+
description: "Users now properly redirected after successful login",
|
|
349
|
+
backgroundColor: "rgba(34, 197, 94, 0.15)",
|
|
350
|
+
metadata: {
|
|
351
|
+
status: "completed",
|
|
352
|
+
priority: "urgent",
|
|
353
|
+
tags: ["bugfix", "auth"]
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
]
|
|
357
|
+
},
|
|
358
|
+
actions: [
|
|
359
|
+
{
|
|
360
|
+
type: "view_task",
|
|
361
|
+
label: "View",
|
|
362
|
+
handler: "client",
|
|
363
|
+
payload: {}
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
type: "undo",
|
|
367
|
+
label: "Undo",
|
|
368
|
+
handler: "server",
|
|
369
|
+
payload: {}
|
|
370
|
+
}
|
|
371
|
+
]
|
|
372
|
+
});
|
|
373
|
+
action = {
|
|
374
|
+
type: "update_database",
|
|
375
|
+
payload: {
|
|
376
|
+
table: "tasks",
|
|
377
|
+
operation: "mark_as_viewed",
|
|
378
|
+
taskIds: ["task-1", "task-2", "task-3"],
|
|
379
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
if (lowerCommand.includes("analyze") || lowerCommand.includes("analysis")) {
|
|
384
|
+
action = {
|
|
385
|
+
type: "send_notification",
|
|
386
|
+
payload: {
|
|
387
|
+
recipient: "team@company.com",
|
|
388
|
+
subject: "Analysis Complete",
|
|
389
|
+
message: "Your requested analysis has been completed and is ready for review."
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return { message, widgets, action };
|
|
394
|
+
}
|
|
395
|
+
function generateMockCommandStream(command, onChunk, onComplete, onError, typingSpeed = 30) {
|
|
396
|
+
const { message, widgets } = generateMockCommandWithWidgets(command);
|
|
397
|
+
const words = message.split(" ");
|
|
398
|
+
let currentIndex = 0;
|
|
399
|
+
const interval = setInterval(() => {
|
|
400
|
+
try {
|
|
401
|
+
if (currentIndex < words.length) {
|
|
402
|
+
onChunk({ type: "token", content: words[currentIndex] + " " });
|
|
403
|
+
currentIndex++;
|
|
404
|
+
} else {
|
|
405
|
+
clearInterval(interval);
|
|
406
|
+
widgets.forEach((widget) => {
|
|
407
|
+
onChunk({ type: "widget", widget });
|
|
408
|
+
});
|
|
409
|
+
const threadId = `mock_thread_${Date.now()}`;
|
|
410
|
+
onChunk({ type: "complete" });
|
|
411
|
+
onComplete(threadId);
|
|
412
|
+
}
|
|
413
|
+
} catch (error) {
|
|
414
|
+
clearInterval(interval);
|
|
415
|
+
onError(error instanceof Error ? error : new Error("Mock streaming error"));
|
|
416
|
+
}
|
|
417
|
+
}, typingSpeed);
|
|
418
|
+
}
|
|
185
419
|
|
|
186
420
|
// src/components/Widgets/Widgets.tsx
|
|
187
421
|
import { useEffect } from "react";
|
|
@@ -223,7 +457,8 @@ function List({ widget, onAction }) {
|
|
|
223
457
|
return /* @__PURE__ */ jsx2("div", { className: "border border-gray-200 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-900 overflow-hidden", children: items.map((item, index) => /* @__PURE__ */ jsxs2(
|
|
224
458
|
"div",
|
|
225
459
|
{
|
|
226
|
-
className: `flex items-center p-4
|
|
460
|
+
className: `flex items-center p-4 transition-colors ${index !== items.length - 1 ? "border-b border-gray-200 dark:border-gray-700" : ""} ${!item.backgroundColor ? "hover:bg-gray-50 dark:hover:bg-gray-800" : ""}`,
|
|
461
|
+
style: item.backgroundColor ? { backgroundColor: item.backgroundColor } : void 0,
|
|
227
462
|
children: [
|
|
228
463
|
item.image && /* @__PURE__ */ jsx2("img", { src: item.image, alt: item.title, className: "w-16 h-16 rounded object-cover" }),
|
|
229
464
|
/* @__PURE__ */ jsxs2("div", { className: `flex-1 ${item.image ? "ml-4" : ""}`, children: [
|
|
@@ -329,11 +564,133 @@ function Widgets({
|
|
|
329
564
|
return /* @__PURE__ */ jsx5("div", { className: cn(layoutClasses[layout], spacingClasses[spacing], className), children: widgets.map((widget) => /* @__PURE__ */ jsx5(WidgetRenderer, { widget, onAction }, widget.id)) });
|
|
330
565
|
}
|
|
331
566
|
|
|
332
|
-
// src/components/Chat/
|
|
567
|
+
// src/components/Chat/MarkdownContent.tsx
|
|
333
568
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
569
|
+
function parseInlineMarkdown(text, keyPrefix = "") {
|
|
570
|
+
const result = [];
|
|
571
|
+
const boldRegex = /(\*\*|__)(.+?)\1/g;
|
|
572
|
+
let lastIndex = 0;
|
|
573
|
+
let match;
|
|
574
|
+
let key = 0;
|
|
575
|
+
while ((match = boldRegex.exec(text)) !== null) {
|
|
576
|
+
if (match.index > lastIndex) {
|
|
577
|
+
result.push(text.slice(lastIndex, match.index));
|
|
578
|
+
}
|
|
579
|
+
result.push(/* @__PURE__ */ jsx6("strong", { children: match[2] }, `${keyPrefix}b${key++}`));
|
|
580
|
+
lastIndex = match.index + match[0].length;
|
|
581
|
+
}
|
|
582
|
+
if (lastIndex < text.length) {
|
|
583
|
+
result.push(text.slice(lastIndex));
|
|
584
|
+
}
|
|
585
|
+
return result.length > 0 ? result : [text];
|
|
586
|
+
}
|
|
587
|
+
function parseMarkdown(content) {
|
|
588
|
+
const lines = content.split("\n");
|
|
589
|
+
const result = [];
|
|
590
|
+
let key = 0;
|
|
591
|
+
let i = 0;
|
|
592
|
+
while (i < lines.length) {
|
|
593
|
+
const line = lines[i];
|
|
594
|
+
const ulMatch = line.match(/^(\s*)([-*+])\s+(.*)$/);
|
|
595
|
+
if (ulMatch) {
|
|
596
|
+
const listItems = [];
|
|
597
|
+
const indent = ulMatch[1].length;
|
|
598
|
+
while (i < lines.length) {
|
|
599
|
+
const itemMatch = lines[i].match(/^(\s*)([-*+])\s+(.*)$/);
|
|
600
|
+
if (itemMatch && itemMatch[1].length === indent) {
|
|
601
|
+
listItems.push(
|
|
602
|
+
/* @__PURE__ */ jsx6("li", { children: parseInlineMarkdown(itemMatch[3], `${key}`) }, `li${key++}`)
|
|
603
|
+
);
|
|
604
|
+
i++;
|
|
605
|
+
} else {
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
result.push(
|
|
610
|
+
/* @__PURE__ */ jsx6("ul", { className: "list-disc pl-5 my-1", children: listItems }, `ul${key++}`)
|
|
611
|
+
);
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const olMatch = line.match(/^(\s*)(\d+)\.\s+(.*)$/);
|
|
615
|
+
if (olMatch) {
|
|
616
|
+
const listItems = [];
|
|
617
|
+
const indent = olMatch[1].length;
|
|
618
|
+
while (i < lines.length) {
|
|
619
|
+
const itemMatch = lines[i].match(/^(\s*)(\d+)\.\s+(.*)$/);
|
|
620
|
+
if (itemMatch && itemMatch[1].length === indent) {
|
|
621
|
+
listItems.push(
|
|
622
|
+
/* @__PURE__ */ jsx6("li", { children: parseInlineMarkdown(itemMatch[3], `${key}`) }, `li${key++}`)
|
|
623
|
+
);
|
|
624
|
+
i++;
|
|
625
|
+
} else {
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
result.push(
|
|
630
|
+
/* @__PURE__ */ jsx6("ol", { className: "list-decimal pl-5 my-1", children: listItems }, `ol${key++}`)
|
|
631
|
+
);
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
if (line === "") {
|
|
635
|
+
result.push(/* @__PURE__ */ jsx6("br", {}, `br${key++}`));
|
|
636
|
+
} else {
|
|
637
|
+
result.push(
|
|
638
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
639
|
+
parseInlineMarkdown(line, `${key}`),
|
|
640
|
+
i < lines.length - 1 ? "\n" : ""
|
|
641
|
+
] }, `p${key++}`)
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
i++;
|
|
645
|
+
}
|
|
646
|
+
return result;
|
|
647
|
+
}
|
|
648
|
+
function MarkdownContent({ content, className = "" }) {
|
|
649
|
+
return /* @__PURE__ */ jsx6("div", { className: `markdown-content !text-sm leading-relaxed whitespace-pre-wrap ${className}`, children: parseMarkdown(content) });
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// src/components/Chat/ToolCall.tsx
|
|
653
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
654
|
+
function ToolCall({ name, status }) {
|
|
655
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 py-2 px-3 my-2 rounded-lg bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 text-sm", children: [
|
|
656
|
+
status === "running" && /* @__PURE__ */ jsx7("div", { className: "w-2 h-2 rounded-full bg-blue-500 animate-pulse" }),
|
|
657
|
+
status === "completed" && /* @__PURE__ */ jsx7("div", { className: "w-2 h-2 rounded-full bg-green-500" }),
|
|
658
|
+
status === "error" && /* @__PURE__ */ jsx7("div", { className: "w-2 h-2 rounded-full bg-red-500" }),
|
|
659
|
+
/* @__PURE__ */ jsx7("span", { className: "text-gray-700 dark:text-gray-300 font-mono", children: name }),
|
|
660
|
+
status === "running" && /* @__PURE__ */ jsx7("span", { className: "text-gray-500 dark:text-gray-400 ml-auto", children: "Running..." }),
|
|
661
|
+
status === "completed" && /* @__PURE__ */ jsx7("span", { className: "text-green-600 dark:text-green-400 ml-auto", children: "Completed" }),
|
|
662
|
+
status === "error" && /* @__PURE__ */ jsx7("span", { className: "text-red-600 dark:text-red-400 ml-auto", children: "Error" })
|
|
663
|
+
] });
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// src/components/Chat/Message.tsx
|
|
667
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
334
668
|
function Message({ message, onAction }) {
|
|
335
669
|
const isUser = message.role === "user";
|
|
336
|
-
|
|
670
|
+
const contentSegments = message.metadata?.content_segments;
|
|
671
|
+
const renderContent = () => {
|
|
672
|
+
if (isUser) {
|
|
673
|
+
return /* @__PURE__ */ jsx8("div", { className: "whitespace-pre-wrap !text-sm leading-relaxed", children: message.content });
|
|
674
|
+
}
|
|
675
|
+
if (contentSegments && contentSegments.length > 0) {
|
|
676
|
+
return /* @__PURE__ */ jsx8("div", { children: contentSegments.map((segment, index) => {
|
|
677
|
+
if (segment.type === "text") {
|
|
678
|
+
return segment.content ? /* @__PURE__ */ jsx8(MarkdownContent, { content: segment.content }, `text-${index}`) : null;
|
|
679
|
+
} else if (segment.type === "tool") {
|
|
680
|
+
return /* @__PURE__ */ jsx8("div", { className: "my-2", children: /* @__PURE__ */ jsx8(
|
|
681
|
+
ToolCall,
|
|
682
|
+
{
|
|
683
|
+
name: segment.name,
|
|
684
|
+
status: segment.result !== void 0 ? "completed" : "running"
|
|
685
|
+
}
|
|
686
|
+
) }, segment.id);
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
}) });
|
|
690
|
+
}
|
|
691
|
+
return /* @__PURE__ */ jsx8(MarkdownContent, { content: message.content });
|
|
692
|
+
};
|
|
693
|
+
return /* @__PURE__ */ jsxs6(
|
|
337
694
|
"div",
|
|
338
695
|
{
|
|
339
696
|
className: cn(
|
|
@@ -341,16 +698,16 @@ function Message({ message, onAction }) {
|
|
|
341
698
|
isUser ? "px-4 py-2.5 rounded-xl bg-gray-100 dark:bg-gray-800 !text-gray-900 dark:!text-gray-100 ml-auto" : "!text-gray-900 dark:!text-gray-100"
|
|
342
699
|
),
|
|
343
700
|
children: [
|
|
344
|
-
|
|
345
|
-
message.widgets && message.widgets.length > 0 && /* @__PURE__ */
|
|
346
|
-
/* @__PURE__ */
|
|
701
|
+
renderContent(),
|
|
702
|
+
message.widgets && message.widgets.length > 0 && /* @__PURE__ */ jsx8("div", { className: cn(isUser ? "mt-3" : "mt-2"), children: /* @__PURE__ */ jsx8(Widgets, { widgets: message.widgets, onAction, layout: "stack" }) }),
|
|
703
|
+
/* @__PURE__ */ jsx8("div", { className: cn("!text-xs opacity-70", isUser ? "mt-1.5 !text-gray-500 dark:!text-gray-400" : "mt-1 !text-gray-500 dark:!text-gray-400"), suppressHydrationWarning: true, children: message.timestamp.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) })
|
|
347
704
|
]
|
|
348
705
|
}
|
|
349
706
|
);
|
|
350
707
|
}
|
|
351
708
|
|
|
352
709
|
// src/components/Chat/MessageList.tsx
|
|
353
|
-
import { jsx as
|
|
710
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
354
711
|
function MessageList({ messages, onAction }) {
|
|
355
712
|
const listRef = useRef(null);
|
|
356
713
|
useEffect2(() => {
|
|
@@ -358,15 +715,15 @@ function MessageList({ messages, onAction }) {
|
|
|
358
715
|
listRef.current.scrollTop = listRef.current.scrollHeight;
|
|
359
716
|
}
|
|
360
717
|
}, [messages]);
|
|
361
|
-
return /* @__PURE__ */
|
|
362
|
-
/* @__PURE__ */
|
|
363
|
-
/* @__PURE__ */
|
|
364
|
-
] }) }) : messages.map((message) => /* @__PURE__ */
|
|
718
|
+
return /* @__PURE__ */ jsx9("div", { ref: listRef, className: "flex-1 overflow-y-auto px-4 py-4 space-y-3", children: messages.length === 0 ? /* @__PURE__ */ jsx9("div", { className: "flex items-center justify-center h-full !text-gray-500 dark:!text-gray-400", children: /* @__PURE__ */ jsxs7("div", { className: "text-center space-y-2", children: [
|
|
719
|
+
/* @__PURE__ */ jsx9("div", { className: "text-4xl", children: "\u{1F4AC}" }),
|
|
720
|
+
/* @__PURE__ */ jsx9("p", { children: "No messages yet. Start a conversation!" })
|
|
721
|
+
] }) }) : messages.map((message) => /* @__PURE__ */ jsx9(Message, { message, onAction }, message.id)) });
|
|
365
722
|
}
|
|
366
723
|
|
|
367
724
|
// src/components/Chat/Composer.tsx
|
|
368
725
|
import { useState, useRef as useRef2 } from "react";
|
|
369
|
-
import { Fragment, jsx as
|
|
726
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
370
727
|
function Composer({ onSendMessage, placeholder = "Type a message...", disabled = false, onFileUpload }) {
|
|
371
728
|
const [text, setText] = useState("");
|
|
372
729
|
const [showMenu, setShowMenu] = useState(false);
|
|
@@ -398,32 +755,32 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
398
755
|
setShowMenu(false);
|
|
399
756
|
}
|
|
400
757
|
};
|
|
401
|
-
return /* @__PURE__ */
|
|
402
|
-
showMenu && /* @__PURE__ */
|
|
403
|
-
/* @__PURE__ */
|
|
404
|
-
/* @__PURE__ */
|
|
758
|
+
return /* @__PURE__ */ jsxs8("div", { className: "px-4 py-3 bg-white dark:bg-gray-900 relative", children: [
|
|
759
|
+
showMenu && /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
760
|
+
/* @__PURE__ */ jsx10("div", { className: "fixed inset-0 z-10", onClick: () => setShowMenu(false) }),
|
|
761
|
+
/* @__PURE__ */ jsx10("div", { className: "absolute bottom-full left-4 mb-2 bg-gray-800 dark:bg-gray-700 rounded-xl shadow-lg overflow-hidden z-20 min-w-[240px]", children: /* @__PURE__ */ jsxs8(
|
|
405
762
|
"button",
|
|
406
763
|
{
|
|
407
764
|
onClick: () => fileInputRef.current?.click(),
|
|
408
765
|
className: "w-full flex items-center gap-3 px-4 py-3 hover:bg-gray-700 dark:hover:bg-gray-600 transition-colors !text-white text-left",
|
|
409
766
|
children: [
|
|
410
|
-
/* @__PURE__ */
|
|
411
|
-
/* @__PURE__ */
|
|
767
|
+
/* @__PURE__ */ jsx10("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx10("path", { d: "M10.5 3.5L5.5 8.5C4.67157 9.32843 4.67157 10.6716 5.5 11.5C6.32843 12.3284 7.67157 12.3284 8.5 11.5L14.5 5.5C15.8807 4.11929 15.8807 1.88071 14.5 0.5C13.1193 -0.880711 10.8807 -0.880711 9.5 0.5L3.5 6.5C1.56846 8.43154 1.56846 11.5685 3.5 13.5C5.43154 15.4315 8.56846 15.4315 10.5 13.5L15.5 8.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(2, 3)" }) }),
|
|
768
|
+
/* @__PURE__ */ jsx10("span", { className: "!text-sm font-medium", children: "Add photos & files" })
|
|
412
769
|
]
|
|
413
770
|
}
|
|
414
771
|
) })
|
|
415
772
|
] }),
|
|
416
|
-
/* @__PURE__ */
|
|
417
|
-
/* @__PURE__ */
|
|
773
|
+
/* @__PURE__ */ jsxs8("div", { className: "relative border-2 border-gray-300 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-900 transition-all duration-300 flex items-center px-3 py-2 gap-3", children: [
|
|
774
|
+
/* @__PURE__ */ jsx10(
|
|
418
775
|
"button",
|
|
419
776
|
{
|
|
420
777
|
onClick: () => setShowMenu(!showMenu),
|
|
421
778
|
className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-gray-700 dark:!text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
422
779
|
title: "More options",
|
|
423
|
-
children: /* @__PURE__ */
|
|
780
|
+
children: /* @__PURE__ */ jsx10("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx10("path", { d: "M10 5v10M5 10h10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
424
781
|
}
|
|
425
782
|
),
|
|
426
|
-
/* @__PURE__ */
|
|
783
|
+
/* @__PURE__ */ jsx10(
|
|
427
784
|
"textarea",
|
|
428
785
|
{
|
|
429
786
|
ref: textareaRef,
|
|
@@ -437,18 +794,18 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
437
794
|
style: { maxHeight: "120px" }
|
|
438
795
|
}
|
|
439
796
|
),
|
|
440
|
-
/* @__PURE__ */
|
|
797
|
+
/* @__PURE__ */ jsx10(
|
|
441
798
|
"button",
|
|
442
799
|
{
|
|
443
800
|
onClick: handleSend,
|
|
444
801
|
disabled: !text.trim() || disabled,
|
|
445
802
|
className: "w-8 h-8 rounded-lg flex items-center justify-center font-bold transition-all flex-shrink-0 border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 !text-gray-700 dark:!text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-30 disabled:cursor-not-allowed !text-lg",
|
|
446
803
|
title: "Send message",
|
|
447
|
-
children: /* @__PURE__ */
|
|
804
|
+
children: /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx10("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
448
805
|
}
|
|
449
806
|
)
|
|
450
807
|
] }),
|
|
451
|
-
/* @__PURE__ */
|
|
808
|
+
/* @__PURE__ */ jsx10(
|
|
452
809
|
"input",
|
|
453
810
|
{
|
|
454
811
|
ref: fileInputRef,
|
|
@@ -462,12 +819,178 @@ function Composer({ onSendMessage, placeholder = "Type a message...", disabled =
|
|
|
462
819
|
] });
|
|
463
820
|
}
|
|
464
821
|
|
|
822
|
+
// src/lib/apteva-client.ts
|
|
823
|
+
var DEFAULT_API_URL = "http://localhost:3000/agents";
|
|
824
|
+
var DEFAULT_API_KEY = "agt_894abd5966bc9f1e9f8f17f2a6f6b5e0";
|
|
825
|
+
var AptevaClient = class {
|
|
826
|
+
constructor() {
|
|
827
|
+
__publicField(this, "config");
|
|
828
|
+
this.config = {
|
|
829
|
+
apiUrl: DEFAULT_API_URL,
|
|
830
|
+
apiKey: DEFAULT_API_KEY
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Update client configuration (optional - users can override defaults)
|
|
835
|
+
*/
|
|
836
|
+
configure(config) {
|
|
837
|
+
if (config.apiUrl) this.config.apiUrl = config.apiUrl;
|
|
838
|
+
if (config.apiKey) this.config.apiKey = config.apiKey;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Get current configuration
|
|
842
|
+
*/
|
|
843
|
+
getConfig() {
|
|
844
|
+
return { ...this.config };
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Send a chat message to an agent
|
|
848
|
+
*/
|
|
849
|
+
async chat(request) {
|
|
850
|
+
try {
|
|
851
|
+
console.log("[AptevaClient] Chat request:", {
|
|
852
|
+
agent_id: request.agent_id,
|
|
853
|
+
message: typeof request.message === "string" ? request.message.substring(0, 100) + "..." : "[multi-part message]",
|
|
854
|
+
system: request.system,
|
|
855
|
+
stream: request.stream
|
|
856
|
+
});
|
|
857
|
+
const response = await fetch(`${this.config.apiUrl}/chat`, {
|
|
858
|
+
method: "POST",
|
|
859
|
+
headers: {
|
|
860
|
+
"Content-Type": "application/json",
|
|
861
|
+
"X-API-Key": this.config.apiKey
|
|
862
|
+
},
|
|
863
|
+
body: JSON.stringify(request)
|
|
864
|
+
});
|
|
865
|
+
if (!response.ok) {
|
|
866
|
+
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
867
|
+
throw new Error(error.error || `Request failed with status ${response.status}`);
|
|
868
|
+
}
|
|
869
|
+
const data = await response.json();
|
|
870
|
+
return {
|
|
871
|
+
message: data.response || data.message || "",
|
|
872
|
+
thread_id: data.thread_id,
|
|
873
|
+
widgets: data.widgets
|
|
874
|
+
};
|
|
875
|
+
} catch (error) {
|
|
876
|
+
console.error("Chat API error:", error);
|
|
877
|
+
throw error;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Send a chat message with streaming response
|
|
882
|
+
*/
|
|
883
|
+
async chatStream(request, onChunk, onComplete, onError) {
|
|
884
|
+
try {
|
|
885
|
+
console.log("[AptevaClient] Chat stream request:", {
|
|
886
|
+
agent_id: request.agent_id,
|
|
887
|
+
message: typeof request.message === "string" ? request.message.substring(0, 100) + "..." : "[multi-part message]",
|
|
888
|
+
system: request.system,
|
|
889
|
+
stream: request.stream
|
|
890
|
+
});
|
|
891
|
+
const response = await fetch(`${this.config.apiUrl}/chat`, {
|
|
892
|
+
method: "POST",
|
|
893
|
+
headers: {
|
|
894
|
+
"Content-Type": "application/json",
|
|
895
|
+
"X-API-Key": this.config.apiKey,
|
|
896
|
+
"Accept": "text/event-stream"
|
|
897
|
+
},
|
|
898
|
+
body: JSON.stringify({
|
|
899
|
+
...request,
|
|
900
|
+
stream: true
|
|
901
|
+
})
|
|
902
|
+
});
|
|
903
|
+
if (!response.ok) {
|
|
904
|
+
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
905
|
+
throw new Error(error.error || `Request failed with status ${response.status}`);
|
|
906
|
+
}
|
|
907
|
+
const reader = response.body?.getReader();
|
|
908
|
+
if (!reader) {
|
|
909
|
+
throw new Error("Response body is not readable");
|
|
910
|
+
}
|
|
911
|
+
const decoder = new TextDecoder();
|
|
912
|
+
let buffer = "";
|
|
913
|
+
let threadId = "";
|
|
914
|
+
while (true) {
|
|
915
|
+
const { done, value } = await reader.read();
|
|
916
|
+
if (done) break;
|
|
917
|
+
buffer += decoder.decode(value, { stream: true });
|
|
918
|
+
const lines = buffer.split("\n");
|
|
919
|
+
buffer = lines.pop() || "";
|
|
920
|
+
for (const line of lines) {
|
|
921
|
+
if (!line.trim() || line.startsWith(":")) continue;
|
|
922
|
+
if (line.startsWith("data: ")) {
|
|
923
|
+
const data = line.slice(6);
|
|
924
|
+
if (data === "[DONE]") {
|
|
925
|
+
onComplete?.(threadId);
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
try {
|
|
929
|
+
const chunk = JSON.parse(data);
|
|
930
|
+
if (chunk.thread_id) {
|
|
931
|
+
threadId = chunk.thread_id;
|
|
932
|
+
}
|
|
933
|
+
onChunk(chunk);
|
|
934
|
+
} catch (e) {
|
|
935
|
+
console.warn("[AptevaClient] Failed to parse SSE data:", data);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
onComplete?.(threadId);
|
|
941
|
+
} catch (error) {
|
|
942
|
+
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
943
|
+
onError?.(err);
|
|
944
|
+
throw err;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Create a new thread
|
|
949
|
+
*/
|
|
950
|
+
async createThread(agentId, metadata) {
|
|
951
|
+
const response = await fetch(`${this.config.apiUrl}/agents/${agentId}/threads`, {
|
|
952
|
+
method: "POST",
|
|
953
|
+
headers: {
|
|
954
|
+
"Content-Type": "application/json",
|
|
955
|
+
"X-API-Key": this.config.apiKey
|
|
956
|
+
},
|
|
957
|
+
body: JSON.stringify({ metadata })
|
|
958
|
+
});
|
|
959
|
+
if (!response.ok) {
|
|
960
|
+
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
961
|
+
throw new Error(error.error || `Request failed with status ${response.status}`);
|
|
962
|
+
}
|
|
963
|
+
const data = await response.json();
|
|
964
|
+
return data.thread_id;
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Get thread messages
|
|
968
|
+
*/
|
|
969
|
+
async getThreadMessages(threadId) {
|
|
970
|
+
const response = await fetch(`${this.config.apiUrl}/threads/${threadId}/messages`, {
|
|
971
|
+
method: "GET",
|
|
972
|
+
headers: {
|
|
973
|
+
"X-API-Key": this.config.apiKey
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
if (!response.ok) {
|
|
977
|
+
const error = await response.json().catch(() => ({ error: "Request failed" }));
|
|
978
|
+
throw new Error(error.error || `Request failed with status ${response.status}`);
|
|
979
|
+
}
|
|
980
|
+
const data = await response.json();
|
|
981
|
+
return data.messages;
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
var aptevaClient = new AptevaClient();
|
|
985
|
+
|
|
465
986
|
// src/components/Chat/Chat.tsx
|
|
466
|
-
import { jsx as
|
|
987
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
467
988
|
function Chat({
|
|
468
989
|
agentId,
|
|
469
990
|
threadId,
|
|
470
991
|
initialMessages = [],
|
|
992
|
+
context,
|
|
993
|
+
useMock = false,
|
|
471
994
|
onThreadChange,
|
|
472
995
|
onMessageSent,
|
|
473
996
|
onAction,
|
|
@@ -477,8 +1000,9 @@ function Chat({
|
|
|
477
1000
|
headerTitle = "Chat",
|
|
478
1001
|
className
|
|
479
1002
|
}) {
|
|
480
|
-
const [messages, setMessages] = useState2(initialMessages
|
|
1003
|
+
const [messages, setMessages] = useState2(initialMessages);
|
|
481
1004
|
const [isLoading, setIsLoading] = useState2(false);
|
|
1005
|
+
const [currentThreadId, setCurrentThreadId] = useState2(threadId || null);
|
|
482
1006
|
useEffect3(() => {
|
|
483
1007
|
if (threadId) {
|
|
484
1008
|
console.log("Loading thread:", threadId);
|
|
@@ -496,31 +1020,220 @@ function Chat({
|
|
|
496
1020
|
onMessageSent?.(userMessage);
|
|
497
1021
|
setIsLoading(true);
|
|
498
1022
|
try {
|
|
499
|
-
|
|
500
|
-
|
|
1023
|
+
if (useMock) {
|
|
1024
|
+
const response = await generateMockResponse(1e3);
|
|
1025
|
+
setMessages((prev) => [...prev, response]);
|
|
1026
|
+
} else {
|
|
1027
|
+
let contentSegments = [];
|
|
1028
|
+
let currentTextBuffer = "";
|
|
1029
|
+
let accumulatedWidgets = [];
|
|
1030
|
+
let responseThreadId = currentThreadId;
|
|
1031
|
+
let toolInputBuffer = "";
|
|
1032
|
+
const updateMessage = () => {
|
|
1033
|
+
const segments = [...contentSegments];
|
|
1034
|
+
if (currentTextBuffer) {
|
|
1035
|
+
const lastSegment = segments[segments.length - 1];
|
|
1036
|
+
if (lastSegment && lastSegment.type === "text") {
|
|
1037
|
+
lastSegment.content = currentTextBuffer;
|
|
1038
|
+
} else {
|
|
1039
|
+
segments.push({ type: "text", content: currentTextBuffer });
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
setMessages((prev) => {
|
|
1043
|
+
const lastMessage = prev[prev.length - 1];
|
|
1044
|
+
if (lastMessage && lastMessage.role === "assistant") {
|
|
1045
|
+
return [
|
|
1046
|
+
...prev.slice(0, -1),
|
|
1047
|
+
{
|
|
1048
|
+
...lastMessage,
|
|
1049
|
+
content: currentTextBuffer,
|
|
1050
|
+
widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
|
|
1051
|
+
metadata: {
|
|
1052
|
+
...lastMessage.metadata,
|
|
1053
|
+
content_segments: segments
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
];
|
|
1057
|
+
} else {
|
|
1058
|
+
return [
|
|
1059
|
+
...prev,
|
|
1060
|
+
{
|
|
1061
|
+
id: `msg-${Date.now()}-streaming`,
|
|
1062
|
+
role: "assistant",
|
|
1063
|
+
content: currentTextBuffer,
|
|
1064
|
+
widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
|
|
1065
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1066
|
+
metadata: {
|
|
1067
|
+
content_segments: segments
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
];
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
};
|
|
1074
|
+
await aptevaClient.chatStream(
|
|
1075
|
+
{
|
|
1076
|
+
agent_id: agentId,
|
|
1077
|
+
message: text,
|
|
1078
|
+
stream: true,
|
|
1079
|
+
...currentThreadId && { thread_id: currentThreadId },
|
|
1080
|
+
...context && { system: context }
|
|
1081
|
+
},
|
|
1082
|
+
(chunk) => {
|
|
1083
|
+
console.log("[Chat] Chunk:", chunk);
|
|
1084
|
+
switch (chunk.type) {
|
|
1085
|
+
case "start":
|
|
1086
|
+
break;
|
|
1087
|
+
case "thread_id":
|
|
1088
|
+
if (chunk.thread_id) {
|
|
1089
|
+
responseThreadId = chunk.thread_id;
|
|
1090
|
+
if (!currentThreadId) {
|
|
1091
|
+
setCurrentThreadId(chunk.thread_id);
|
|
1092
|
+
onThreadChange?.(chunk.thread_id);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
break;
|
|
1096
|
+
case "content":
|
|
1097
|
+
case "token":
|
|
1098
|
+
if (chunk.content) {
|
|
1099
|
+
currentTextBuffer += chunk.content;
|
|
1100
|
+
updateMessage();
|
|
1101
|
+
}
|
|
1102
|
+
break;
|
|
1103
|
+
case "tool_call":
|
|
1104
|
+
if (chunk.tool_id && chunk.tool_name) {
|
|
1105
|
+
if (currentTextBuffer) {
|
|
1106
|
+
contentSegments.push({ type: "text", content: currentTextBuffer });
|
|
1107
|
+
currentTextBuffer = "";
|
|
1108
|
+
}
|
|
1109
|
+
contentSegments.push({
|
|
1110
|
+
type: "tool",
|
|
1111
|
+
id: chunk.tool_id,
|
|
1112
|
+
name: chunk.tool_name
|
|
1113
|
+
});
|
|
1114
|
+
toolInputBuffer = "";
|
|
1115
|
+
updateMessage();
|
|
1116
|
+
}
|
|
1117
|
+
break;
|
|
1118
|
+
case "tool_input_delta":
|
|
1119
|
+
if (chunk.tool_id && chunk.content) {
|
|
1120
|
+
toolInputBuffer += chunk.content;
|
|
1121
|
+
}
|
|
1122
|
+
break;
|
|
1123
|
+
case "tool_use":
|
|
1124
|
+
toolInputBuffer = "";
|
|
1125
|
+
break;
|
|
1126
|
+
case "tool_result":
|
|
1127
|
+
if (chunk.tool_id) {
|
|
1128
|
+
const toolSegment = contentSegments.find(
|
|
1129
|
+
(s) => s.type === "tool" && s.id === chunk.tool_id
|
|
1130
|
+
);
|
|
1131
|
+
if (toolSegment) {
|
|
1132
|
+
toolSegment.result = chunk.content;
|
|
1133
|
+
}
|
|
1134
|
+
updateMessage();
|
|
1135
|
+
}
|
|
1136
|
+
break;
|
|
1137
|
+
case "widget":
|
|
1138
|
+
if (chunk.widget) {
|
|
1139
|
+
accumulatedWidgets.push(chunk.widget);
|
|
1140
|
+
updateMessage();
|
|
1141
|
+
}
|
|
1142
|
+
break;
|
|
1143
|
+
case "stop":
|
|
1144
|
+
break;
|
|
1145
|
+
case "complete":
|
|
1146
|
+
break;
|
|
1147
|
+
case "error":
|
|
1148
|
+
throw new Error(chunk.message || "Stream error");
|
|
1149
|
+
default:
|
|
1150
|
+
break;
|
|
1151
|
+
}
|
|
1152
|
+
},
|
|
1153
|
+
(threadId2) => {
|
|
1154
|
+
if (currentTextBuffer) {
|
|
1155
|
+
const lastSegment = contentSegments[contentSegments.length - 1];
|
|
1156
|
+
if (lastSegment && lastSegment.type === "text") {
|
|
1157
|
+
lastSegment.content = currentTextBuffer;
|
|
1158
|
+
} else {
|
|
1159
|
+
contentSegments.push({ type: "text", content: currentTextBuffer });
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
setMessages((prev) => {
|
|
1163
|
+
const lastMessage = prev[prev.length - 1];
|
|
1164
|
+
if (lastMessage && lastMessage.role === "assistant") {
|
|
1165
|
+
return [
|
|
1166
|
+
...prev.slice(0, -1),
|
|
1167
|
+
{
|
|
1168
|
+
...lastMessage,
|
|
1169
|
+
id: `msg-${Date.now()}`,
|
|
1170
|
+
content: currentTextBuffer || "Response received",
|
|
1171
|
+
widgets: accumulatedWidgets.length > 0 ? accumulatedWidgets : void 0,
|
|
1172
|
+
metadata: {
|
|
1173
|
+
thread_id: threadId2,
|
|
1174
|
+
content_segments: contentSegments
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
];
|
|
1178
|
+
}
|
|
1179
|
+
return prev;
|
|
1180
|
+
});
|
|
1181
|
+
if (threadId2 && threadId2 !== currentThreadId) {
|
|
1182
|
+
setCurrentThreadId(threadId2);
|
|
1183
|
+
onThreadChange?.(threadId2);
|
|
1184
|
+
}
|
|
1185
|
+
setIsLoading(false);
|
|
1186
|
+
},
|
|
1187
|
+
(error) => {
|
|
1188
|
+
const errorMessage = {
|
|
1189
|
+
id: `msg-${Date.now()}-error`,
|
|
1190
|
+
role: "assistant",
|
|
1191
|
+
content: `Error: ${error.message}`,
|
|
1192
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1193
|
+
metadata: { error: true }
|
|
1194
|
+
};
|
|
1195
|
+
setMessages((prev) => {
|
|
1196
|
+
const lastMessage = prev[prev.length - 1];
|
|
1197
|
+
if (lastMessage && lastMessage.id.includes("streaming")) {
|
|
1198
|
+
return [...prev.slice(0, -1), errorMessage];
|
|
1199
|
+
}
|
|
1200
|
+
return [...prev, errorMessage];
|
|
1201
|
+
});
|
|
1202
|
+
setIsLoading(false);
|
|
1203
|
+
}
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
501
1206
|
} catch (error) {
|
|
502
|
-
console.error("
|
|
1207
|
+
console.error("Chat error:", error);
|
|
1208
|
+
const errorMessage = {
|
|
1209
|
+
id: `msg-${Date.now()}-error`,
|
|
1210
|
+
role: "assistant",
|
|
1211
|
+
content: error instanceof Error ? `Error: ${error.message}` : "An error occurred",
|
|
1212
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1213
|
+
metadata: { error: true }
|
|
1214
|
+
};
|
|
1215
|
+
setMessages((prev) => [...prev, errorMessage]);
|
|
503
1216
|
} finally {
|
|
504
1217
|
setIsLoading(false);
|
|
505
1218
|
}
|
|
506
1219
|
};
|
|
507
|
-
return /* @__PURE__ */
|
|
508
|
-
showHeader && /* @__PURE__ */
|
|
509
|
-
/* @__PURE__ */
|
|
510
|
-
/* @__PURE__ */
|
|
1220
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn("flex flex-col h-full bg-white dark:bg-gray-900", className), children: [
|
|
1221
|
+
showHeader && /* @__PURE__ */ jsxs9("div", { className: "px-4 py-3 bg-white dark:bg-gray-900", children: [
|
|
1222
|
+
/* @__PURE__ */ jsx11("h2", { className: "!text-lg font-semibold !text-gray-900 dark:!text-white", children: headerTitle }),
|
|
1223
|
+
/* @__PURE__ */ jsxs9("p", { className: "!text-xs !text-gray-500 dark:!text-gray-400", children: [
|
|
511
1224
|
"Agent: ",
|
|
512
1225
|
agentId
|
|
513
1226
|
] })
|
|
514
1227
|
] }),
|
|
515
|
-
/* @__PURE__ */
|
|
516
|
-
isLoading && /* @__PURE__ */
|
|
517
|
-
/* @__PURE__ */
|
|
1228
|
+
/* @__PURE__ */ jsx11(MessageList, { messages, onAction }),
|
|
1229
|
+
isLoading && /* @__PURE__ */ jsx11("div", { className: "px-4 py-2 !text-sm !text-gray-500 dark:!text-gray-400 italic", children: "AI is thinking..." }),
|
|
1230
|
+
/* @__PURE__ */ jsx11(Composer, { onSendMessage: handleSendMessage, placeholder, disabled: isLoading, onFileUpload })
|
|
518
1231
|
] });
|
|
519
1232
|
}
|
|
520
1233
|
|
|
521
1234
|
// src/components/Command/Command.tsx
|
|
522
1235
|
import React, { useState as useState3, useEffect as useEffect4 } from "react";
|
|
523
|
-
import { Fragment as Fragment2, jsx as
|
|
1236
|
+
import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
524
1237
|
function Command({
|
|
525
1238
|
agentId,
|
|
526
1239
|
command: initialCommand,
|
|
@@ -530,12 +1243,17 @@ function Command({
|
|
|
530
1243
|
placeholder = "Enter your command...",
|
|
531
1244
|
submitButtonText = "Execute",
|
|
532
1245
|
variant = "default",
|
|
1246
|
+
useMock = false,
|
|
1247
|
+
planMode = false,
|
|
1248
|
+
onPlanModeChange,
|
|
1249
|
+
enableFileUpload = true,
|
|
533
1250
|
onStart,
|
|
534
1251
|
onProgress,
|
|
535
1252
|
onChunk,
|
|
536
1253
|
onComplete,
|
|
537
1254
|
onError,
|
|
538
1255
|
onFileUpload,
|
|
1256
|
+
onAction,
|
|
539
1257
|
loadingText = "Processing...",
|
|
540
1258
|
showProgress = true,
|
|
541
1259
|
enableStreaming = false,
|
|
@@ -548,82 +1266,345 @@ function Command({
|
|
|
548
1266
|
const [progress, setProgress] = useState3(0);
|
|
549
1267
|
const [command, setCommand] = useState3(initialCommand || "");
|
|
550
1268
|
const [streamedContent, setStreamedContent] = useState3("");
|
|
1269
|
+
const [plan, setPlan] = useState3("");
|
|
1270
|
+
const [pendingCommand, setPendingCommand] = useState3("");
|
|
1271
|
+
const [showPlanDetails, setShowPlanDetails] = useState3(false);
|
|
1272
|
+
const [uploadedFiles, setUploadedFiles] = useState3([]);
|
|
1273
|
+
const [showSettingsMenu, setShowSettingsMenu] = useState3(false);
|
|
1274
|
+
const [internalPlanMode, setInternalPlanMode] = useState3(planMode);
|
|
551
1275
|
const fileInputRef = React.useRef(null);
|
|
552
1276
|
useEffect4(() => {
|
|
553
1277
|
if (autoExecute && state === "idle" && command) {
|
|
554
1278
|
executeCommand();
|
|
555
1279
|
}
|
|
556
1280
|
}, [autoExecute]);
|
|
557
|
-
|
|
558
|
-
|
|
1281
|
+
useEffect4(() => {
|
|
1282
|
+
setInternalPlanMode(planMode);
|
|
1283
|
+
}, [planMode]);
|
|
1284
|
+
useEffect4(() => {
|
|
1285
|
+
const handleClickOutside = (event) => {
|
|
1286
|
+
const target = event.target;
|
|
1287
|
+
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
1288
|
+
setShowSettingsMenu(false);
|
|
1289
|
+
}
|
|
1290
|
+
};
|
|
1291
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1292
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1293
|
+
}, [showSettingsMenu]);
|
|
1294
|
+
const executeCommand = async (commandOverride) => {
|
|
1295
|
+
const currentCommand = commandOverride || command;
|
|
1296
|
+
if (!currentCommand.trim()) {
|
|
559
1297
|
setError(new Error("Please enter a command"));
|
|
560
1298
|
setState("error");
|
|
561
1299
|
return;
|
|
562
1300
|
}
|
|
563
|
-
|
|
1301
|
+
if (internalPlanMode && state !== "plan-pending") {
|
|
1302
|
+
setState("loading");
|
|
1303
|
+
setError(null);
|
|
1304
|
+
setCommand("");
|
|
1305
|
+
if (useMock) {
|
|
1306
|
+
setTimeout(() => {
|
|
1307
|
+
const mockPlan = generateMockPlan(currentCommand);
|
|
1308
|
+
setPlan(mockPlan);
|
|
1309
|
+
setPendingCommand(currentCommand);
|
|
1310
|
+
setState("plan-pending");
|
|
1311
|
+
}, 800);
|
|
1312
|
+
} else {
|
|
1313
|
+
try {
|
|
1314
|
+
let messageContent;
|
|
1315
|
+
if (uploadedFiles.length > 0) {
|
|
1316
|
+
messageContent = [
|
|
1317
|
+
{
|
|
1318
|
+
type: "text",
|
|
1319
|
+
text: currentCommand
|
|
1320
|
+
},
|
|
1321
|
+
...uploadedFiles.map((file) => ({
|
|
1322
|
+
type: file.type,
|
|
1323
|
+
source: {
|
|
1324
|
+
type: "base64",
|
|
1325
|
+
media_type: file.mediaType,
|
|
1326
|
+
data: file.data
|
|
1327
|
+
}
|
|
1328
|
+
}))
|
|
1329
|
+
];
|
|
1330
|
+
} else {
|
|
1331
|
+
messageContent = currentCommand;
|
|
1332
|
+
}
|
|
1333
|
+
let systemMessage = context || "";
|
|
1334
|
+
const planningInstruction = `CRITICAL PLANNING MODE - READ CAREFULLY:
|
|
1335
|
+
|
|
1336
|
+
You are ONLY creating a plan. You are NOT executing anything.
|
|
1337
|
+
|
|
1338
|
+
YOUR TASK: Write a numbered list of steps describing what WOULD be done.
|
|
1339
|
+
DO NOT: Execute any actions, make API calls, access databases, modify data, or perform any operations.
|
|
1340
|
+
DO NOT: Ask questions or clarifications. Make reasonable assumptions.
|
|
1341
|
+
DO: Describe the steps as "Step 1: Would search database...", "Step 2: Would analyze results...", etc.
|
|
1342
|
+
DO: Use default values or best practices if details are missing.
|
|
1343
|
+
|
|
1344
|
+
FORMAT REQUIRED:
|
|
1345
|
+
1. [First action that would be taken]
|
|
1346
|
+
2. [Second action that would be taken]
|
|
1347
|
+
3. [Third action that would be taken]
|
|
1348
|
+
...
|
|
1349
|
+
|
|
1350
|
+
IMPORTANT: This is COMMAND MODE - figure things out yourself. Make intelligent assumptions based on context. ONLY ask questions if something is absolutely impossible to proceed without (e.g., missing required credentials). Otherwise, use sensible defaults and proceed with the plan.
|
|
1351
|
+
|
|
1352
|
+
REMEMBER: This is ONLY a plan. The user will approve it, THEN it will be executed. Right now you are just describing what would happen - NOT doing it.`;
|
|
1353
|
+
systemMessage = systemMessage ? `${systemMessage}
|
|
1354
|
+
|
|
1355
|
+
${planningInstruction}` : planningInstruction;
|
|
1356
|
+
aptevaClient.chat({
|
|
1357
|
+
agent_id: agentId,
|
|
1358
|
+
message: messageContent,
|
|
1359
|
+
stream: false,
|
|
1360
|
+
system: systemMessage
|
|
1361
|
+
}).then((response) => {
|
|
1362
|
+
setPlan(response.message);
|
|
1363
|
+
setPendingCommand(currentCommand);
|
|
1364
|
+
setState("plan-pending");
|
|
1365
|
+
}).catch((err) => {
|
|
1366
|
+
const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
|
|
1367
|
+
setError(error2);
|
|
1368
|
+
setState("error");
|
|
1369
|
+
onError?.(error2);
|
|
1370
|
+
});
|
|
1371
|
+
} catch (err) {
|
|
1372
|
+
const error2 = err instanceof Error ? err : new Error("Failed to generate plan");
|
|
1373
|
+
setError(error2);
|
|
1374
|
+
setState("error");
|
|
1375
|
+
onError?.(error2);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
564
1380
|
setState("loading");
|
|
565
1381
|
setError(null);
|
|
566
1382
|
setProgress(0);
|
|
567
1383
|
setStreamedContent("");
|
|
568
1384
|
setCommand("");
|
|
1385
|
+
setUploadedFiles([]);
|
|
569
1386
|
onStart?.();
|
|
570
1387
|
try {
|
|
571
|
-
if (
|
|
572
|
-
|
|
573
|
-
"
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
1388
|
+
if (useMock) {
|
|
1389
|
+
if (enableStreaming) {
|
|
1390
|
+
let accumulatedContent = "";
|
|
1391
|
+
generateMockCommandStream(
|
|
1392
|
+
currentCommand,
|
|
1393
|
+
(chunk) => {
|
|
1394
|
+
if (chunk.type === "token" && chunk.content) {
|
|
1395
|
+
accumulatedContent += chunk.content;
|
|
1396
|
+
setStreamedContent(accumulatedContent);
|
|
1397
|
+
onChunk?.(chunk.content);
|
|
1398
|
+
const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
|
|
1399
|
+
setProgress(estimatedProgress);
|
|
1400
|
+
onProgress?.(estimatedProgress);
|
|
1401
|
+
} else if (chunk.type === "widget" && chunk.widget) {
|
|
1402
|
+
const widget = chunk.widget;
|
|
1403
|
+
setResult((prev) => ({
|
|
1404
|
+
success: true,
|
|
1405
|
+
data: prev?.data || {},
|
|
1406
|
+
widgets: [...prev?.widgets || [], widget],
|
|
1407
|
+
message: accumulatedContent || "Command executed successfully"
|
|
1408
|
+
}));
|
|
1409
|
+
}
|
|
1410
|
+
},
|
|
1411
|
+
(threadId) => {
|
|
1412
|
+
const result2 = {
|
|
1413
|
+
success: true,
|
|
1414
|
+
data: {
|
|
1415
|
+
summary: accumulatedContent,
|
|
1416
|
+
thread_id: threadId,
|
|
1417
|
+
agentId,
|
|
1418
|
+
context,
|
|
1419
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1420
|
+
},
|
|
1421
|
+
message: accumulatedContent || "Command executed successfully"
|
|
1422
|
+
};
|
|
1423
|
+
setResult(result2);
|
|
1424
|
+
setState("success");
|
|
1425
|
+
setProgress(100);
|
|
1426
|
+
onComplete?.(result2);
|
|
1427
|
+
},
|
|
1428
|
+
(error2) => {
|
|
1429
|
+
setError(error2);
|
|
1430
|
+
setState("error");
|
|
1431
|
+
onError?.(error2);
|
|
1432
|
+
}
|
|
1433
|
+
);
|
|
1434
|
+
} else {
|
|
1435
|
+
const progressInterval = setInterval(() => {
|
|
1436
|
+
setProgress((prev) => {
|
|
1437
|
+
const next = Math.min(prev + 10, 90);
|
|
1438
|
+
onProgress?.(next);
|
|
1439
|
+
return next;
|
|
1440
|
+
});
|
|
1441
|
+
}, 200);
|
|
1442
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
1443
|
+
clearInterval(progressInterval);
|
|
1444
|
+
const mockResponse = generateMockCommandWithWidgets(currentCommand);
|
|
1445
|
+
const result2 = {
|
|
1446
|
+
success: true,
|
|
1447
|
+
data: {
|
|
1448
|
+
summary: mockResponse.message,
|
|
1449
|
+
thread_id: `mock_thread_${Date.now()}`,
|
|
1450
|
+
agentId,
|
|
1451
|
+
context,
|
|
1452
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1453
|
+
action: mockResponse.action
|
|
1454
|
+
// Include agent action intent
|
|
1455
|
+
},
|
|
1456
|
+
widgets: mockResponse.widgets,
|
|
1457
|
+
message: mockResponse.message
|
|
1458
|
+
};
|
|
1459
|
+
setResult(result2);
|
|
1460
|
+
setState("success");
|
|
1461
|
+
setProgress(100);
|
|
1462
|
+
onComplete?.(result2);
|
|
588
1463
|
}
|
|
589
|
-
const mockResult = {
|
|
590
|
-
success: true,
|
|
591
|
-
data: {
|
|
592
|
-
summary: `Successfully processed: "${currentCommand}"`,
|
|
593
|
-
agentId,
|
|
594
|
-
context,
|
|
595
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
596
|
-
},
|
|
597
|
-
message: "Command executed successfully"
|
|
598
|
-
};
|
|
599
|
-
setResult(mockResult);
|
|
600
|
-
setState("success");
|
|
601
|
-
setProgress(100);
|
|
602
|
-
onComplete?.(mockResult);
|
|
603
1464
|
} else {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
1465
|
+
if (enableStreaming) {
|
|
1466
|
+
let accumulatedContent = "";
|
|
1467
|
+
let messageContent;
|
|
1468
|
+
if (uploadedFiles.length > 0) {
|
|
1469
|
+
messageContent = [
|
|
1470
|
+
{
|
|
1471
|
+
type: "text",
|
|
1472
|
+
text: currentCommand
|
|
1473
|
+
},
|
|
1474
|
+
...uploadedFiles.map((file) => ({
|
|
1475
|
+
type: file.type,
|
|
1476
|
+
// 'image' or 'document'
|
|
1477
|
+
source: {
|
|
1478
|
+
type: "base64",
|
|
1479
|
+
media_type: file.mediaType,
|
|
1480
|
+
data: file.data
|
|
1481
|
+
}
|
|
1482
|
+
}))
|
|
1483
|
+
];
|
|
1484
|
+
} else {
|
|
1485
|
+
messageContent = currentCommand;
|
|
1486
|
+
}
|
|
1487
|
+
let systemMessage = context || "";
|
|
1488
|
+
let commandInstruction;
|
|
1489
|
+
if (isCompact) {
|
|
1490
|
+
commandInstruction = 'CRITICAL COMMAND MODE: Maximum 10 words per response. Execute immediately, make intelligent assumptions, use defaults when needed. NO questions unless absolutely critical (missing required credentials). State action or result ONLY. Examples: "Searching database for matching records..." or "Found 3 user records in database" or "Task completed successfully". NO greetings, NO explanations, NO clarification requests. Just execute and report.';
|
|
1491
|
+
} else {
|
|
1492
|
+
commandInstruction = `CRITICAL COMMAND MODE: Maximum 10 words per response. Execute the command immediately. Make reasonable assumptions based on context. Use sensible defaults for missing details. DO NOT ask questions unless something is truly impossible without user input (e.g., missing required password). State what you're doing or the result. Examples: "Analyzing customer data from last quarter..." or "Created 5 new database entries successfully" or "Search complete: found 12 matching results". NO greetings, NO filler words, NO clarification requests. Action/result only.`;
|
|
1493
|
+
}
|
|
1494
|
+
systemMessage = systemMessage ? `${systemMessage}
|
|
1495
|
+
|
|
1496
|
+
${commandInstruction}` : commandInstruction;
|
|
1497
|
+
await aptevaClient.chatStream(
|
|
1498
|
+
{
|
|
1499
|
+
agent_id: agentId,
|
|
1500
|
+
message: messageContent,
|
|
1501
|
+
stream: true,
|
|
1502
|
+
...systemMessage && { system: systemMessage }
|
|
1503
|
+
},
|
|
1504
|
+
(chunk) => {
|
|
1505
|
+
if (chunk.type === "token" && chunk.content) {
|
|
1506
|
+
accumulatedContent += chunk.content;
|
|
1507
|
+
setStreamedContent(accumulatedContent);
|
|
1508
|
+
onChunk?.(chunk.content);
|
|
1509
|
+
const estimatedProgress = Math.min(Math.round(accumulatedContent.length / 10), 90);
|
|
1510
|
+
setProgress(estimatedProgress);
|
|
1511
|
+
onProgress?.(estimatedProgress);
|
|
1512
|
+
} else if (chunk.type === "widget" && chunk.widget) {
|
|
1513
|
+
const widget = chunk.widget;
|
|
1514
|
+
setResult((prev) => ({
|
|
1515
|
+
success: true,
|
|
1516
|
+
data: prev?.data || {},
|
|
1517
|
+
widgets: [...prev?.widgets || [], widget],
|
|
1518
|
+
message: accumulatedContent || "Command executed successfully"
|
|
1519
|
+
}));
|
|
1520
|
+
}
|
|
1521
|
+
},
|
|
1522
|
+
(threadId) => {
|
|
1523
|
+
const result2 = {
|
|
1524
|
+
success: true,
|
|
1525
|
+
data: {
|
|
1526
|
+
summary: accumulatedContent,
|
|
1527
|
+
thread_id: threadId,
|
|
1528
|
+
agentId,
|
|
1529
|
+
context,
|
|
1530
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1531
|
+
},
|
|
1532
|
+
message: accumulatedContent || "Command executed successfully"
|
|
1533
|
+
};
|
|
1534
|
+
setResult(result2);
|
|
1535
|
+
setState("success");
|
|
1536
|
+
setProgress(100);
|
|
1537
|
+
onComplete?.(result2);
|
|
1538
|
+
},
|
|
1539
|
+
(error2) => {
|
|
1540
|
+
const err = error2 instanceof Error ? error2 : new Error("Unknown error");
|
|
1541
|
+
setError(err);
|
|
1542
|
+
setState("error");
|
|
1543
|
+
onError?.(err);
|
|
1544
|
+
}
|
|
1545
|
+
);
|
|
1546
|
+
} else {
|
|
1547
|
+
const progressInterval = setInterval(() => {
|
|
1548
|
+
setProgress((prev) => {
|
|
1549
|
+
const next = Math.min(prev + 10, 90);
|
|
1550
|
+
onProgress?.(next);
|
|
1551
|
+
return next;
|
|
1552
|
+
});
|
|
1553
|
+
}, 200);
|
|
1554
|
+
let messageContent;
|
|
1555
|
+
if (uploadedFiles.length > 0) {
|
|
1556
|
+
messageContent = [
|
|
1557
|
+
{
|
|
1558
|
+
type: "text",
|
|
1559
|
+
text: currentCommand
|
|
1560
|
+
},
|
|
1561
|
+
...uploadedFiles.map((file) => ({
|
|
1562
|
+
type: file.type,
|
|
1563
|
+
// 'image' or 'document'
|
|
1564
|
+
source: {
|
|
1565
|
+
type: "base64",
|
|
1566
|
+
media_type: file.mediaType,
|
|
1567
|
+
data: file.data
|
|
1568
|
+
}
|
|
1569
|
+
}))
|
|
1570
|
+
];
|
|
1571
|
+
} else {
|
|
1572
|
+
messageContent = currentCommand;
|
|
1573
|
+
}
|
|
1574
|
+
let systemMessage = context || "";
|
|
1575
|
+
let commandInstruction;
|
|
1576
|
+
if (isCompact) {
|
|
1577
|
+
commandInstruction = 'CRITICAL COMMAND MODE: Maximum 10 words per response. Execute immediately, make intelligent assumptions, use defaults when needed. NO questions unless absolutely critical (missing required credentials). State action or result ONLY. Examples: "Searching database for matching records..." or "Found 3 user records in database" or "Task completed successfully". NO greetings, NO explanations, NO clarification requests. Just execute and report.';
|
|
1578
|
+
} else {
|
|
1579
|
+
commandInstruction = `CRITICAL COMMAND MODE: Maximum 10 words per response. Execute the command immediately. Make reasonable assumptions based on context. Use sensible defaults for missing details. DO NOT ask questions unless something is truly impossible without user input (e.g., missing required password). State what you're doing or the result. Examples: "Analyzing customer data from last quarter..." or "Created 5 new database entries successfully" or "Search complete: found 12 matching results". NO greetings, NO filler words, NO clarification requests. Action/result only.`;
|
|
1580
|
+
}
|
|
1581
|
+
systemMessage = systemMessage ? `${systemMessage}
|
|
1582
|
+
|
|
1583
|
+
${commandInstruction}` : commandInstruction;
|
|
1584
|
+
const response = await aptevaClient.chat({
|
|
1585
|
+
agent_id: agentId,
|
|
1586
|
+
message: messageContent,
|
|
1587
|
+
stream: false,
|
|
1588
|
+
...systemMessage && { system: systemMessage }
|
|
609
1589
|
});
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
1590
|
+
clearInterval(progressInterval);
|
|
1591
|
+
const result2 = {
|
|
1592
|
+
success: true,
|
|
1593
|
+
data: {
|
|
1594
|
+
summary: response.message,
|
|
1595
|
+
thread_id: response.thread_id,
|
|
1596
|
+
agentId,
|
|
1597
|
+
context,
|
|
1598
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1599
|
+
},
|
|
1600
|
+
widgets: response.widgets,
|
|
1601
|
+
message: response.message
|
|
1602
|
+
};
|
|
1603
|
+
setResult(result2);
|
|
1604
|
+
setState("success");
|
|
1605
|
+
setProgress(100);
|
|
1606
|
+
onComplete?.(result2);
|
|
1607
|
+
}
|
|
627
1608
|
}
|
|
628
1609
|
} catch (err) {
|
|
629
1610
|
const error2 = err instanceof Error ? err : new Error("Unknown error");
|
|
@@ -638,14 +1619,71 @@ function Command({
|
|
|
638
1619
|
setError(null);
|
|
639
1620
|
setProgress(0);
|
|
640
1621
|
setCommand("");
|
|
1622
|
+
setPlan("");
|
|
1623
|
+
setPendingCommand("");
|
|
1624
|
+
setShowPlanDetails(false);
|
|
1625
|
+
setUploadedFiles([]);
|
|
641
1626
|
};
|
|
642
|
-
const
|
|
1627
|
+
const approvePlan = () => {
|
|
1628
|
+
setShowPlanDetails(false);
|
|
1629
|
+
const planToExecute = plan;
|
|
1630
|
+
setPlan("");
|
|
1631
|
+
setPendingCommand("");
|
|
1632
|
+
const executionMessage = `Execute this plan now:
|
|
1633
|
+
|
|
1634
|
+
${planToExecute}`;
|
|
1635
|
+
executeCommand(executionMessage);
|
|
1636
|
+
};
|
|
1637
|
+
const rejectPlan = () => {
|
|
1638
|
+
setCommand(pendingCommand);
|
|
1639
|
+
setPlan("");
|
|
1640
|
+
setPendingCommand("");
|
|
1641
|
+
setShowPlanDetails(false);
|
|
1642
|
+
setState("idle");
|
|
1643
|
+
};
|
|
1644
|
+
const handleFileSelect = async (e) => {
|
|
643
1645
|
if (e.target.files && e.target.files.length > 0) {
|
|
644
1646
|
onFileUpload?.(e.target.files);
|
|
1647
|
+
const files = [];
|
|
1648
|
+
for (let i = 0; i < e.target.files.length; i++) {
|
|
1649
|
+
const file = e.target.files[i];
|
|
1650
|
+
const reader = new FileReader();
|
|
1651
|
+
await new Promise((resolve) => {
|
|
1652
|
+
reader.onload = (event) => {
|
|
1653
|
+
if (event.target?.result) {
|
|
1654
|
+
const fullDataUrl = event.target.result;
|
|
1655
|
+
const base64Data = fullDataUrl.split(",")[1];
|
|
1656
|
+
if (file.type.startsWith("image/")) {
|
|
1657
|
+
files.push({
|
|
1658
|
+
type: "image",
|
|
1659
|
+
data: base64Data,
|
|
1660
|
+
mediaType: file.type,
|
|
1661
|
+
preview: fullDataUrl,
|
|
1662
|
+
// Keep full data URL for preview
|
|
1663
|
+
name: file.name
|
|
1664
|
+
});
|
|
1665
|
+
} else if (file.type === "application/pdf" || file.type.startsWith("application/")) {
|
|
1666
|
+
files.push({
|
|
1667
|
+
type: "document",
|
|
1668
|
+
data: base64Data,
|
|
1669
|
+
mediaType: file.type,
|
|
1670
|
+
name: file.name
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
resolve();
|
|
1675
|
+
};
|
|
1676
|
+
reader.readAsDataURL(file);
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
setUploadedFiles((prev) => [...prev, ...files]);
|
|
645
1680
|
}
|
|
646
1681
|
};
|
|
1682
|
+
const removeFile = (index) => {
|
|
1683
|
+
setUploadedFiles((prev) => prev.filter((_, i) => i !== index));
|
|
1684
|
+
};
|
|
647
1685
|
const isCompact = variant === "compact";
|
|
648
|
-
return /* @__PURE__ */
|
|
1686
|
+
return /* @__PURE__ */ jsxs10(
|
|
649
1687
|
"div",
|
|
650
1688
|
{
|
|
651
1689
|
className: cn(
|
|
@@ -653,40 +1691,142 @@ function Command({
|
|
|
653
1691
|
state === "loading" && "animate-pulse-border",
|
|
654
1692
|
state === "idle" && "border-gray-300 dark:border-gray-700",
|
|
655
1693
|
state === "loading" && "border-blue-500",
|
|
1694
|
+
state === "plan-pending" && "border-blue-400",
|
|
656
1695
|
state === "success" && "border-green-500",
|
|
657
1696
|
state === "error" && "border-red-500",
|
|
658
1697
|
className
|
|
659
1698
|
),
|
|
660
1699
|
style: { minHeight: isCompact ? "auto" : "180px" },
|
|
661
1700
|
children: [
|
|
662
|
-
/* @__PURE__ */
|
|
663
|
-
state === "idle" && allowInput && !isCompact && /* @__PURE__ */
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
value: command,
|
|
667
|
-
onChange: (e) => setCommand(e.target.value),
|
|
668
|
-
onKeyDown: (e) => {
|
|
669
|
-
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
670
|
-
e.preventDefault();
|
|
671
|
-
executeCommand();
|
|
672
|
-
}
|
|
673
|
-
},
|
|
674
|
-
placeholder,
|
|
675
|
-
className: "flex-1 w-full resize-none bg-transparent border-none focus:outline-none !text-gray-900 dark:!text-gray-100 placeholder-gray-400 dark:placeholder-gray-500",
|
|
676
|
-
rows: 6
|
|
677
|
-
}
|
|
678
|
-
),
|
|
679
|
-
state === "idle" && allowInput && isCompact && /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
680
|
-
/* @__PURE__ */ jsx10(
|
|
681
|
-
"button",
|
|
1701
|
+
/* @__PURE__ */ jsxs10("div", { className: cn("flex-1 flex", isCompact ? "flex-row items-center p-3 gap-3" : "flex-col p-4"), children: [
|
|
1702
|
+
state === "idle" && allowInput && !isCompact && /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
1703
|
+
/* @__PURE__ */ jsx12(
|
|
1704
|
+
"textarea",
|
|
682
1705
|
{
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
1706
|
+
value: command,
|
|
1707
|
+
onChange: (e) => setCommand(e.target.value),
|
|
1708
|
+
onKeyDown: (e) => {
|
|
1709
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
1710
|
+
e.preventDefault();
|
|
1711
|
+
executeCommand();
|
|
1712
|
+
}
|
|
1713
|
+
},
|
|
1714
|
+
placeholder,
|
|
1715
|
+
className: "flex-1 w-full resize-none bg-transparent border-none focus:outline-none !text-gray-900 dark:!text-gray-100 placeholder-gray-400 dark:placeholder-gray-500",
|
|
1716
|
+
rows: 6
|
|
687
1717
|
}
|
|
688
1718
|
),
|
|
689
|
-
/* @__PURE__ */
|
|
1719
|
+
uploadedFiles.length > 0 && /* @__PURE__ */ jsx12("div", { className: "flex flex-wrap gap-2 mt-2", children: uploadedFiles.map((file, index) => /* @__PURE__ */ jsxs10("div", { className: "relative group", children: [
|
|
1720
|
+
file.type === "image" ? /* @__PURE__ */ jsx12(
|
|
1721
|
+
"img",
|
|
1722
|
+
{
|
|
1723
|
+
src: file.preview,
|
|
1724
|
+
alt: file.name,
|
|
1725
|
+
className: "w-20 h-20 object-cover rounded-lg border-2 border-gray-300 dark:border-gray-600"
|
|
1726
|
+
}
|
|
1727
|
+
) : /* @__PURE__ */ jsxs10("div", { className: "w-20 h-20 flex flex-col items-center justify-center rounded-lg border-2 border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800", children: [
|
|
1728
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-8 h-8 text-gray-500 dark:text-gray-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx12("path", { fillRule: "evenodd", d: "M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z", clipRule: "evenodd" }) }),
|
|
1729
|
+
/* @__PURE__ */ jsx12("span", { className: "text-[8px] text-gray-500 dark:text-gray-400 mt-1 px-1 truncate max-w-full", children: file.name.length > 12 ? file.name.slice(0, 12) + "..." : file.name })
|
|
1730
|
+
] }),
|
|
1731
|
+
/* @__PURE__ */ jsx12(
|
|
1732
|
+
"button",
|
|
1733
|
+
{
|
|
1734
|
+
onClick: () => removeFile(index),
|
|
1735
|
+
className: "absolute -top-2 -right-2 w-6 h-6 bg-red-500 hover:bg-red-600 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1736
|
+
title: `Remove ${file.type}`,
|
|
1737
|
+
children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1738
|
+
}
|
|
1739
|
+
)
|
|
1740
|
+
] }, index)) })
|
|
1741
|
+
] }),
|
|
1742
|
+
state === "idle" && allowInput && isCompact && /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
1743
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-0.5 flex-shrink-0", children: [
|
|
1744
|
+
enableFileUpload && /* @__PURE__ */ jsx12(
|
|
1745
|
+
"button",
|
|
1746
|
+
{
|
|
1747
|
+
onClick: () => fileInputRef.current?.click(),
|
|
1748
|
+
className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-gray-500 dark:!text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
1749
|
+
title: "Attach file",
|
|
1750
|
+
children: /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
|
|
1751
|
+
}
|
|
1752
|
+
),
|
|
1753
|
+
planMode && /* @__PURE__ */ jsxs10("div", { className: "relative settings-menu-container", children: [
|
|
1754
|
+
/* @__PURE__ */ jsx12(
|
|
1755
|
+
"button",
|
|
1756
|
+
{
|
|
1757
|
+
onClick: () => setShowSettingsMenu(!showSettingsMenu),
|
|
1758
|
+
className: cn(
|
|
1759
|
+
"w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
1760
|
+
internalPlanMode ? "!text-blue-600 dark:!text-blue-400" : "!text-gray-500 dark:!text-gray-500"
|
|
1761
|
+
),
|
|
1762
|
+
title: "Settings",
|
|
1763
|
+
children: /* @__PURE__ */ jsxs10("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1764
|
+
/* @__PURE__ */ jsx12("line", { x1: "4", y1: "21", x2: "4", y2: "14" }),
|
|
1765
|
+
/* @__PURE__ */ jsx12("line", { x1: "4", y1: "10", x2: "4", y2: "3" }),
|
|
1766
|
+
/* @__PURE__ */ jsx12("line", { x1: "12", y1: "21", x2: "12", y2: "12" }),
|
|
1767
|
+
/* @__PURE__ */ jsx12("line", { x1: "12", y1: "8", x2: "12", y2: "3" }),
|
|
1768
|
+
/* @__PURE__ */ jsx12("line", { x1: "20", y1: "21", x2: "20", y2: "16" }),
|
|
1769
|
+
/* @__PURE__ */ jsx12("line", { x1: "20", y1: "12", x2: "20", y2: "3" }),
|
|
1770
|
+
/* @__PURE__ */ jsx12("line", { x1: "1", y1: "14", x2: "7", y2: "14" }),
|
|
1771
|
+
/* @__PURE__ */ jsx12("line", { x1: "9", y1: "8", x2: "15", y2: "8" }),
|
|
1772
|
+
/* @__PURE__ */ jsx12("line", { x1: "17", y1: "16", x2: "23", y2: "16" })
|
|
1773
|
+
] })
|
|
1774
|
+
}
|
|
1775
|
+
),
|
|
1776
|
+
showSettingsMenu && /* @__PURE__ */ jsx12("div", { className: "absolute top-10 left-0 z-50 w-56 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-2.5 settings-menu-container", children: /* @__PURE__ */ jsxs10("label", { className: "flex items-center justify-between cursor-pointer group", children: [
|
|
1777
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
|
|
1778
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-3.5 h-3.5 text-gray-500 dark:text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
1779
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
1780
|
+
/* @__PURE__ */ jsx12("div", { className: "text-xs font-medium text-gray-700 dark:text-gray-300", children: "Plan Mode" }),
|
|
1781
|
+
/* @__PURE__ */ jsx12("div", { className: "text-[10px] text-gray-500 dark:text-gray-400", children: "Review first" })
|
|
1782
|
+
] })
|
|
1783
|
+
] }),
|
|
1784
|
+
/* @__PURE__ */ jsx12(
|
|
1785
|
+
"button",
|
|
1786
|
+
{
|
|
1787
|
+
onClick: (e) => {
|
|
1788
|
+
e.stopPropagation();
|
|
1789
|
+
setInternalPlanMode(!internalPlanMode);
|
|
1790
|
+
},
|
|
1791
|
+
className: cn(
|
|
1792
|
+
"relative inline-flex h-4 w-8 items-center rounded-full transition-colors",
|
|
1793
|
+
internalPlanMode ? "bg-blue-600" : "bg-gray-300 dark:bg-gray-600"
|
|
1794
|
+
),
|
|
1795
|
+
type: "button",
|
|
1796
|
+
children: /* @__PURE__ */ jsx12(
|
|
1797
|
+
"span",
|
|
1798
|
+
{
|
|
1799
|
+
className: cn(
|
|
1800
|
+
"inline-block h-3 w-3 transform rounded-full bg-white transition-transform",
|
|
1801
|
+
internalPlanMode ? "translate-x-4.5" : "translate-x-0.5"
|
|
1802
|
+
)
|
|
1803
|
+
}
|
|
1804
|
+
)
|
|
1805
|
+
}
|
|
1806
|
+
)
|
|
1807
|
+
] }) })
|
|
1808
|
+
] })
|
|
1809
|
+
] }),
|
|
1810
|
+
uploadedFiles.length > 0 && /* @__PURE__ */ jsx12("div", { className: "flex gap-1 flex-shrink-0", children: uploadedFiles.map((file, index) => /* @__PURE__ */ jsxs10("div", { className: "relative group", children: [
|
|
1811
|
+
file.type === "image" ? /* @__PURE__ */ jsx12(
|
|
1812
|
+
"img",
|
|
1813
|
+
{
|
|
1814
|
+
src: file.preview,
|
|
1815
|
+
alt: file.name,
|
|
1816
|
+
className: "w-8 h-8 object-cover rounded border border-gray-300 dark:border-gray-600"
|
|
1817
|
+
}
|
|
1818
|
+
) : /* @__PURE__ */ jsx12("div", { className: "w-8 h-8 flex items-center justify-center rounded border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800", title: file.name, children: /* @__PURE__ */ jsx12("svg", { className: "w-4 h-4 text-gray-500 dark:text-gray-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx12("path", { fillRule: "evenodd", d: "M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z", clipRule: "evenodd" }) }) }),
|
|
1819
|
+
/* @__PURE__ */ jsx12(
|
|
1820
|
+
"button",
|
|
1821
|
+
{
|
|
1822
|
+
onClick: () => removeFile(index),
|
|
1823
|
+
className: "absolute -top-1 -right-1 w-4 h-4 bg-red-500 hover:bg-red-600 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1824
|
+
title: "Remove",
|
|
1825
|
+
children: /* @__PURE__ */ jsx12("svg", { className: "w-2.5 h-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3, children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
|
|
1826
|
+
}
|
|
1827
|
+
)
|
|
1828
|
+
] }, index)) }),
|
|
1829
|
+
/* @__PURE__ */ jsx12(
|
|
690
1830
|
"input",
|
|
691
1831
|
{
|
|
692
1832
|
type: "text",
|
|
@@ -702,10 +1842,10 @@ function Command({
|
|
|
702
1842
|
className: "flex-1 bg-transparent border-none focus:outline-none !text-gray-900 dark:!text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 py-1"
|
|
703
1843
|
}
|
|
704
1844
|
),
|
|
705
|
-
/* @__PURE__ */
|
|
1845
|
+
/* @__PURE__ */ jsx12(
|
|
706
1846
|
"button",
|
|
707
1847
|
{
|
|
708
|
-
onClick: executeCommand,
|
|
1848
|
+
onClick: () => executeCommand(),
|
|
709
1849
|
disabled: !command.trim(),
|
|
710
1850
|
className: cn(
|
|
711
1851
|
"w-8 h-8 rounded-lg flex items-center justify-center font-bold transition-all flex-shrink-0",
|
|
@@ -718,33 +1858,33 @@ function Command({
|
|
|
718
1858
|
!command.trim() && "border-gray-200 dark:border-gray-700 !text-gray-400 dark:!text-gray-600"
|
|
719
1859
|
),
|
|
720
1860
|
title: "Execute",
|
|
721
|
-
children: /* @__PURE__ */
|
|
1861
|
+
children: /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
722
1862
|
}
|
|
723
1863
|
)
|
|
724
1864
|
] }),
|
|
725
|
-
state === "loading" && !isCompact && /* @__PURE__ */
|
|
726
|
-
/* @__PURE__ */
|
|
727
|
-
/* @__PURE__ */
|
|
728
|
-
showProgress && /* @__PURE__ */
|
|
729
|
-
/* @__PURE__ */
|
|
1865
|
+
state === "loading" && !isCompact && /* @__PURE__ */ jsxs10("div", { className: "flex-1 flex flex-col items-center justify-center space-y-4 py-8", children: [
|
|
1866
|
+
/* @__PURE__ */ jsx12("div", { className: "w-6 h-6 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin" }),
|
|
1867
|
+
/* @__PURE__ */ jsx12("div", { className: "text-gray-600 dark:text-gray-400 text-sm text-center max-w-md", children: enableStreaming && streamedContent ? streamedContent : loadingText }),
|
|
1868
|
+
showProgress && /* @__PURE__ */ jsxs10("div", { className: "w-full max-w-sm", children: [
|
|
1869
|
+
/* @__PURE__ */ jsx12("div", { className: "w-full bg-gray-200 dark:bg-gray-700 rounded-full h-1.5", children: /* @__PURE__ */ jsx12(
|
|
730
1870
|
"div",
|
|
731
1871
|
{
|
|
732
1872
|
className: "bg-blue-500 h-1.5 rounded-full transition-all duration-300",
|
|
733
1873
|
style: { width: `${progress}%` }
|
|
734
1874
|
}
|
|
735
1875
|
) }),
|
|
736
|
-
/* @__PURE__ */
|
|
1876
|
+
/* @__PURE__ */ jsxs10("p", { className: "text-xs text-gray-500 mt-2 text-center", children: [
|
|
737
1877
|
progress,
|
|
738
1878
|
"%"
|
|
739
1879
|
] })
|
|
740
1880
|
] })
|
|
741
1881
|
] }),
|
|
742
|
-
state === "loading" && isCompact && /* @__PURE__ */
|
|
743
|
-
/* @__PURE__ */
|
|
744
|
-
/* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
1882
|
+
state === "loading" && isCompact && /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
1883
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex-1 flex items-center gap-3 py-1", children: [
|
|
1884
|
+
/* @__PURE__ */ jsx12("div", { className: "w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin" }),
|
|
1885
|
+
/* @__PURE__ */ jsx12("div", { className: "text-gray-600 dark:text-gray-400 text-sm truncate", children: enableStreaming && streamedContent ? streamedContent : loadingText })
|
|
746
1886
|
] }),
|
|
747
|
-
/* @__PURE__ */
|
|
1887
|
+
/* @__PURE__ */ jsx12(
|
|
748
1888
|
"button",
|
|
749
1889
|
{
|
|
750
1890
|
disabled: true,
|
|
@@ -756,19 +1896,77 @@ function Command({
|
|
|
756
1896
|
"!text-lg",
|
|
757
1897
|
"opacity-30 cursor-not-allowed"
|
|
758
1898
|
),
|
|
759
|
-
children: /* @__PURE__ */
|
|
1899
|
+
children: /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
760
1900
|
}
|
|
761
1901
|
)
|
|
762
1902
|
] }),
|
|
763
|
-
state === "
|
|
764
|
-
/* @__PURE__ */
|
|
765
|
-
/* @__PURE__ */
|
|
766
|
-
/* @__PURE__ */
|
|
767
|
-
/* @__PURE__ */
|
|
768
|
-
/* @__PURE__ */
|
|
1903
|
+
state === "plan-pending" && !isCompact && /* @__PURE__ */ jsx12("div", { className: "flex-1 flex flex-col", children: /* @__PURE__ */ jsxs10("div", { className: "mb-4 p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg", children: [
|
|
1904
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-2 mb-3", children: [
|
|
1905
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-5 h-5 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
1906
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex-1", children: [
|
|
1907
|
+
/* @__PURE__ */ jsx12("h3", { className: "text-sm font-semibold text-blue-800 dark:text-blue-300 mb-1", children: "Proposed Plan" }),
|
|
1908
|
+
/* @__PURE__ */ jsx12("div", { className: "text-blue-700 dark:text-blue-300 text-sm whitespace-pre-line leading-relaxed", children: plan })
|
|
1909
|
+
] })
|
|
1910
|
+
] }),
|
|
1911
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex gap-2 mt-4", children: [
|
|
1912
|
+
/* @__PURE__ */ jsx12(
|
|
1913
|
+
"button",
|
|
1914
|
+
{
|
|
1915
|
+
onClick: approvePlan,
|
|
1916
|
+
className: "flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium",
|
|
1917
|
+
children: "Approve & Execute"
|
|
1918
|
+
}
|
|
1919
|
+
),
|
|
1920
|
+
/* @__PURE__ */ jsx12(
|
|
1921
|
+
"button",
|
|
1922
|
+
{
|
|
1923
|
+
onClick: rejectPlan,
|
|
1924
|
+
className: "flex-1 px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors text-sm font-medium",
|
|
1925
|
+
children: "Modify"
|
|
1926
|
+
}
|
|
1927
|
+
)
|
|
1928
|
+
] })
|
|
1929
|
+
] }) }),
|
|
1930
|
+
state === "plan-pending" && isCompact && /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
1931
|
+
/* @__PURE__ */ jsxs10(
|
|
1932
|
+
"button",
|
|
1933
|
+
{
|
|
1934
|
+
onClick: () => setShowPlanDetails(true),
|
|
1935
|
+
className: "flex-1 flex items-center gap-2 px-3 py-2 bg-blue-50 dark:bg-blue-900/30 hover:bg-blue-100 dark:hover:bg-blue-900/40 border border-blue-200 dark:border-blue-800 rounded-lg transition-colors",
|
|
1936
|
+
children: [
|
|
1937
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-4 h-4 text-blue-600 dark:text-blue-400 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
1938
|
+
/* @__PURE__ */ jsx12("span", { className: "text-sm font-medium text-blue-700 dark:text-blue-300 truncate flex-1", children: "View Execution Plan" })
|
|
1939
|
+
]
|
|
1940
|
+
}
|
|
1941
|
+
),
|
|
1942
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex gap-2 flex-shrink-0", children: [
|
|
1943
|
+
/* @__PURE__ */ jsx12(
|
|
1944
|
+
"button",
|
|
1945
|
+
{
|
|
1946
|
+
onClick: approvePlan,
|
|
1947
|
+
className: "px-3 py-1.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-xs font-medium",
|
|
1948
|
+
children: "Approve"
|
|
1949
|
+
}
|
|
1950
|
+
),
|
|
1951
|
+
/* @__PURE__ */ jsx12(
|
|
1952
|
+
"button",
|
|
1953
|
+
{
|
|
1954
|
+
onClick: rejectPlan,
|
|
1955
|
+
className: "px-3 py-1.5 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors text-xs font-medium",
|
|
1956
|
+
children: "Modify"
|
|
1957
|
+
}
|
|
1958
|
+
)
|
|
1959
|
+
] })
|
|
1960
|
+
] }),
|
|
1961
|
+
state === "error" && /* @__PURE__ */ jsxs10("div", { className: "flex-1 flex flex-col", children: [
|
|
1962
|
+
/* @__PURE__ */ jsx12("div", { className: "mb-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-2", children: [
|
|
1963
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-5 h-5 text-red-600 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1964
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
1965
|
+
/* @__PURE__ */ jsx12("h3", { className: "text-sm font-semibold text-red-800 dark:text-red-400", children: "Error" }),
|
|
1966
|
+
/* @__PURE__ */ jsx12("p", { className: "text-red-700 dark:text-red-300 text-sm mt-1", children: error?.message })
|
|
769
1967
|
] })
|
|
770
1968
|
] }) }),
|
|
771
|
-
allowInput && /* @__PURE__ */
|
|
1969
|
+
allowInput && /* @__PURE__ */ jsx12(
|
|
772
1970
|
"textarea",
|
|
773
1971
|
{
|
|
774
1972
|
value: command,
|
|
@@ -785,32 +1983,40 @@ function Command({
|
|
|
785
1983
|
}
|
|
786
1984
|
)
|
|
787
1985
|
] }),
|
|
788
|
-
state === "success" && result && !isCompact && /* @__PURE__ */
|
|
789
|
-
/* @__PURE__ */
|
|
790
|
-
/* @__PURE__ */
|
|
791
|
-
/* @__PURE__ */
|
|
792
|
-
/* @__PURE__ */
|
|
793
|
-
/* @__PURE__ */
|
|
1986
|
+
state === "success" && result && !isCompact && /* @__PURE__ */ jsx12("div", { className: "flex-1 overflow-auto", children: resultRenderer ? resultRenderer(result.data) : /* @__PURE__ */ jsxs10("div", { className: "space-y-4", children: [
|
|
1987
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-3 p-3 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg", children: [
|
|
1988
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-5 h-5 text-green-600 mt-0.5 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1989
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex-1", children: [
|
|
1990
|
+
/* @__PURE__ */ jsx12("h3", { className: "text-sm font-semibold text-green-800 dark:text-green-400 mb-1", children: "Success" }),
|
|
1991
|
+
/* @__PURE__ */ jsx12("p", { className: "text-green-700 dark:text-green-300 text-sm", children: "Command executed successfully" })
|
|
794
1992
|
] })
|
|
795
1993
|
] }),
|
|
796
|
-
result.data?.summary && /* @__PURE__ */
|
|
1994
|
+
result.data?.summary && /* @__PURE__ */ jsx12("div", { className: "text-gray-700 dark:text-gray-300 text-sm leading-relaxed whitespace-pre-line", children: result.data.summary }),
|
|
1995
|
+
result.widgets && result.widgets.length > 0 && /* @__PURE__ */ jsx12("div", { className: "space-y-3", children: result.widgets.map((widget) => /* @__PURE__ */ jsx12(
|
|
1996
|
+
WidgetRenderer,
|
|
1997
|
+
{
|
|
1998
|
+
widget,
|
|
1999
|
+
onAction
|
|
2000
|
+
},
|
|
2001
|
+
widget.id
|
|
2002
|
+
)) })
|
|
797
2003
|
] }) }),
|
|
798
|
-
state === "success" && result && isCompact && /* @__PURE__ */
|
|
799
|
-
/* @__PURE__ */
|
|
2004
|
+
state === "success" && result && isCompact && /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
2005
|
+
/* @__PURE__ */ jsxs10(
|
|
800
2006
|
"div",
|
|
801
2007
|
{
|
|
802
|
-
className: "flex-1 flex items-center gap-2 py-1 cursor-text",
|
|
2008
|
+
className: "flex-1 flex items-center gap-2 py-1 cursor-text min-w-0",
|
|
803
2009
|
onClick: () => {
|
|
804
2010
|
setState("idle");
|
|
805
2011
|
setResult(null);
|
|
806
2012
|
},
|
|
807
2013
|
children: [
|
|
808
|
-
/* @__PURE__ */
|
|
809
|
-
/* @__PURE__ */
|
|
2014
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-4 h-4 text-green-600 flex-shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
2015
|
+
/* @__PURE__ */ jsx12("div", { className: "text-green-700 dark:text-green-300 text-sm truncate flex-1 min-w-0", children: resultRenderer ? resultRenderer(result.data) : result.message || "Command executed successfully" })
|
|
810
2016
|
]
|
|
811
2017
|
}
|
|
812
2018
|
),
|
|
813
|
-
/* @__PURE__ */
|
|
2019
|
+
/* @__PURE__ */ jsx12(
|
|
814
2020
|
"button",
|
|
815
2021
|
{
|
|
816
2022
|
onClick: () => {
|
|
@@ -826,24 +2032,82 @@ function Command({
|
|
|
826
2032
|
"!text-lg"
|
|
827
2033
|
),
|
|
828
2034
|
title: "New command",
|
|
829
|
-
children: /* @__PURE__ */
|
|
2035
|
+
children: /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
830
2036
|
}
|
|
831
2037
|
)
|
|
832
2038
|
] })
|
|
833
2039
|
] }),
|
|
834
|
-
!isCompact && /* @__PURE__ */
|
|
835
|
-
state === "idle" && allowInput && /* @__PURE__ */
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
2040
|
+
!isCompact && /* @__PURE__ */ jsxs10("div", { className: "p-3 flex items-center justify-between gap-2", children: [
|
|
2041
|
+
/* @__PURE__ */ jsx12("div", { className: "flex items-center gap-1", children: state === "idle" && allowInput && /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
2042
|
+
enableFileUpload && /* @__PURE__ */ jsx12(
|
|
2043
|
+
"button",
|
|
2044
|
+
{
|
|
2045
|
+
onClick: () => fileInputRef.current?.click(),
|
|
2046
|
+
className: "w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 !text-gray-500 dark:!text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
2047
|
+
title: "Attach file",
|
|
2048
|
+
children: /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M8.4 2.8L4.4 6.8C3.736 7.464 3.736 8.536 4.4 9.2C5.064 9.864 6.136 9.864 6.8 9.2L11.6 4.4C12.704 3.296 12.704 1.504 11.6 0.4C10.496 -0.704 8.704 -0.704 7.6 0.4L2.8 5.2C1.256 6.744 1.256 9.256 2.8 10.8C4.344 12.344 6.856 12.344 8.4 10.8L12.4 6.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", transform: "translate(1.6, 2.4)" }) })
|
|
2049
|
+
}
|
|
2050
|
+
),
|
|
2051
|
+
planMode && /* @__PURE__ */ jsxs10("div", { className: "relative settings-menu-container", children: [
|
|
2052
|
+
/* @__PURE__ */ jsx12(
|
|
2053
|
+
"button",
|
|
2054
|
+
{
|
|
2055
|
+
onClick: () => setShowSettingsMenu(!showSettingsMenu),
|
|
2056
|
+
className: cn(
|
|
2057
|
+
"w-8 h-8 rounded-lg flex items-center justify-center transition-all flex-shrink-0 hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
2058
|
+
internalPlanMode ? "!text-blue-600 dark:!text-blue-400" : "!text-gray-500 dark:!text-gray-500"
|
|
2059
|
+
),
|
|
2060
|
+
title: "Settings",
|
|
2061
|
+
children: /* @__PURE__ */ jsxs10("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2062
|
+
/* @__PURE__ */ jsx12("line", { x1: "4", y1: "21", x2: "4", y2: "14" }),
|
|
2063
|
+
/* @__PURE__ */ jsx12("line", { x1: "4", y1: "10", x2: "4", y2: "3" }),
|
|
2064
|
+
/* @__PURE__ */ jsx12("line", { x1: "12", y1: "21", x2: "12", y2: "12" }),
|
|
2065
|
+
/* @__PURE__ */ jsx12("line", { x1: "12", y1: "8", x2: "12", y2: "3" }),
|
|
2066
|
+
/* @__PURE__ */ jsx12("line", { x1: "20", y1: "21", x2: "20", y2: "16" }),
|
|
2067
|
+
/* @__PURE__ */ jsx12("line", { x1: "20", y1: "12", x2: "20", y2: "3" }),
|
|
2068
|
+
/* @__PURE__ */ jsx12("line", { x1: "1", y1: "14", x2: "7", y2: "14" }),
|
|
2069
|
+
/* @__PURE__ */ jsx12("line", { x1: "9", y1: "8", x2: "15", y2: "8" }),
|
|
2070
|
+
/* @__PURE__ */ jsx12("line", { x1: "17", y1: "16", x2: "23", y2: "16" })
|
|
2071
|
+
] })
|
|
2072
|
+
}
|
|
2073
|
+
),
|
|
2074
|
+
showSettingsMenu && /* @__PURE__ */ jsx12("div", { className: "absolute top-10 left-0 z-50 w-64 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-3 settings-menu-container", children: /* @__PURE__ */ jsxs10("label", { className: "flex items-center justify-between cursor-pointer group", children: [
|
|
2075
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
|
|
2076
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-4 h-4 text-gray-500 dark:text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
2077
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
2078
|
+
/* @__PURE__ */ jsx12("div", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "Plan Mode" }),
|
|
2079
|
+
/* @__PURE__ */ jsx12("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Review before executing" })
|
|
2080
|
+
] })
|
|
2081
|
+
] }),
|
|
2082
|
+
/* @__PURE__ */ jsx12(
|
|
2083
|
+
"button",
|
|
2084
|
+
{
|
|
2085
|
+
onClick: (e) => {
|
|
2086
|
+
e.stopPropagation();
|
|
2087
|
+
setInternalPlanMode(!internalPlanMode);
|
|
2088
|
+
},
|
|
2089
|
+
className: cn(
|
|
2090
|
+
"relative inline-flex h-5 w-9 items-center rounded-full transition-colors",
|
|
2091
|
+
internalPlanMode ? "bg-blue-600" : "bg-gray-300 dark:bg-gray-600"
|
|
2092
|
+
),
|
|
2093
|
+
type: "button",
|
|
2094
|
+
children: /* @__PURE__ */ jsx12(
|
|
2095
|
+
"span",
|
|
2096
|
+
{
|
|
2097
|
+
className: cn(
|
|
2098
|
+
"inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform",
|
|
2099
|
+
internalPlanMode ? "translate-x-5" : "translate-x-0.5"
|
|
2100
|
+
)
|
|
2101
|
+
}
|
|
2102
|
+
)
|
|
2103
|
+
}
|
|
2104
|
+
)
|
|
2105
|
+
] }) })
|
|
2106
|
+
] })
|
|
2107
|
+
] }) }),
|
|
2108
|
+
!(state === "idle" && allowInput) && /* @__PURE__ */ jsx12("div", {}),
|
|
2109
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
|
|
2110
|
+
(state === "success" || state === "error") && allowInput && /* @__PURE__ */ jsx12(
|
|
847
2111
|
"button",
|
|
848
2112
|
{
|
|
849
2113
|
onClick: resetCommand,
|
|
@@ -851,10 +2115,10 @@ function Command({
|
|
|
851
2115
|
children: "Reset"
|
|
852
2116
|
}
|
|
853
2117
|
),
|
|
854
|
-
(state === "idle" || state === "error") && /* @__PURE__ */
|
|
2118
|
+
(state === "idle" || state === "error") && /* @__PURE__ */ jsx12(
|
|
855
2119
|
"button",
|
|
856
2120
|
{
|
|
857
|
-
onClick: executeCommand,
|
|
2121
|
+
onClick: () => executeCommand(),
|
|
858
2122
|
disabled: !command.trim(),
|
|
859
2123
|
className: cn(
|
|
860
2124
|
"w-8 h-8 rounded-lg flex items-center justify-center font-bold transition-all",
|
|
@@ -867,12 +2131,47 @@ function Command({
|
|
|
867
2131
|
!command.trim() && "border-gray-200 dark:border-gray-700 !text-gray-400 dark:!text-gray-600"
|
|
868
2132
|
),
|
|
869
2133
|
title: state === "error" ? "Retry" : "Execute",
|
|
870
|
-
children: state === "error" ? /* @__PURE__ */
|
|
2134
|
+
children: state === "error" ? /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M13 8C13 10.7614 10.7614 13 8 13C5.23858 13 3 10.7614 3 8C3 5.23858 5.23858 3 8 3C9.65685 3 11.1257 3.82818 12 5.09091M12 3V5.09091M12 5.09091H9.81818", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) : /* @__PURE__ */ jsx12("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx12("path", { d: "M8 3L8 13M8 3L4 7M8 3L12 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
871
2135
|
}
|
|
872
2136
|
)
|
|
873
2137
|
] })
|
|
874
2138
|
] }),
|
|
875
|
-
/* @__PURE__ */
|
|
2139
|
+
showPlanDetails && isCompact && state === "plan-pending" && /* @__PURE__ */ jsx12("div", { className: "fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4", onClick: () => setShowPlanDetails(false), children: /* @__PURE__ */ jsxs10("div", { className: "bg-white dark:bg-gray-900 rounded-2xl shadow-2xl max-w-2xl w-full max-h-[80vh] overflow-hidden", onClick: (e) => e.stopPropagation(), children: [
|
|
2140
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700", children: [
|
|
2141
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-3", children: [
|
|
2142
|
+
/* @__PURE__ */ jsx12("svg", { className: "w-6 h-6 text-blue-600 dark:text-blue-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" }) }),
|
|
2143
|
+
/* @__PURE__ */ jsx12("h2", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: "Proposed Execution Plan" })
|
|
2144
|
+
] }),
|
|
2145
|
+
/* @__PURE__ */ jsx12(
|
|
2146
|
+
"button",
|
|
2147
|
+
{
|
|
2148
|
+
onClick: () => setShowPlanDetails(false),
|
|
2149
|
+
className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors",
|
|
2150
|
+
children: /* @__PURE__ */ jsx12("svg", { className: "w-6 h-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx12("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
2151
|
+
}
|
|
2152
|
+
)
|
|
2153
|
+
] }),
|
|
2154
|
+
/* @__PURE__ */ jsx12("div", { className: "p-6 overflow-y-auto max-h-[calc(80vh-180px)]", children: /* @__PURE__ */ jsx12("div", { className: "prose prose-sm dark:prose-invert max-w-none", children: /* @__PURE__ */ jsx12("div", { className: "text-gray-700 dark:text-gray-300 whitespace-pre-line leading-relaxed", children: plan }) }) }),
|
|
2155
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-end gap-3 p-6 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50", children: [
|
|
2156
|
+
/* @__PURE__ */ jsx12(
|
|
2157
|
+
"button",
|
|
2158
|
+
{
|
|
2159
|
+
onClick: rejectPlan,
|
|
2160
|
+
className: "px-6 py-2.5 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors font-medium",
|
|
2161
|
+
children: "Modify Command"
|
|
2162
|
+
}
|
|
2163
|
+
),
|
|
2164
|
+
/* @__PURE__ */ jsx12(
|
|
2165
|
+
"button",
|
|
2166
|
+
{
|
|
2167
|
+
onClick: approvePlan,
|
|
2168
|
+
className: "px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium",
|
|
2169
|
+
children: "Approve & Execute"
|
|
2170
|
+
}
|
|
2171
|
+
)
|
|
2172
|
+
] })
|
|
2173
|
+
] }) }),
|
|
2174
|
+
/* @__PURE__ */ jsx12(
|
|
876
2175
|
"input",
|
|
877
2176
|
{
|
|
878
2177
|
ref: fileInputRef,
|
|
@@ -883,7 +2182,7 @@ function Command({
|
|
|
883
2182
|
accept: "image/*,application/pdf,.doc,.docx,.txt"
|
|
884
2183
|
}
|
|
885
2184
|
),
|
|
886
|
-
/* @__PURE__ */
|
|
2185
|
+
/* @__PURE__ */ jsx12("style", { dangerouslySetInnerHTML: {
|
|
887
2186
|
__html: `
|
|
888
2187
|
@keyframes pulse-border {
|
|
889
2188
|
0%, 100% {
|
|
@@ -905,11 +2204,12 @@ function Command({
|
|
|
905
2204
|
|
|
906
2205
|
// src/components/Prompt/Prompt.tsx
|
|
907
2206
|
import { useState as useState4 } from "react";
|
|
908
|
-
import { jsx as
|
|
2207
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
909
2208
|
function Prompt({
|
|
910
2209
|
agentId,
|
|
911
2210
|
placeholder = "Enter your prompt...",
|
|
912
2211
|
initialValue = "",
|
|
2212
|
+
useMock = true,
|
|
913
2213
|
submitOn = "button",
|
|
914
2214
|
debounceMs = 0,
|
|
915
2215
|
minLength = 0,
|
|
@@ -936,10 +2236,19 @@ function Prompt({
|
|
|
936
2236
|
onSubmit?.(value);
|
|
937
2237
|
setIsLoading(true);
|
|
938
2238
|
try {
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
2239
|
+
if (useMock) {
|
|
2240
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
2241
|
+
const mockResult = `Enhanced version: ${value} [AI-generated content]`;
|
|
2242
|
+
onResult?.(mockResult);
|
|
2243
|
+
setValue("");
|
|
2244
|
+
} else {
|
|
2245
|
+
const response = await aptevaClient.chat({
|
|
2246
|
+
agent_id: agentId,
|
|
2247
|
+
message: value
|
|
2248
|
+
});
|
|
2249
|
+
onResult?.(response.message);
|
|
2250
|
+
setValue("");
|
|
2251
|
+
}
|
|
943
2252
|
} catch (error) {
|
|
944
2253
|
console.error("Error processing prompt:", error);
|
|
945
2254
|
} finally {
|
|
@@ -957,9 +2266,9 @@ function Prompt({
|
|
|
957
2266
|
handleSubmit();
|
|
958
2267
|
}
|
|
959
2268
|
};
|
|
960
|
-
return /* @__PURE__ */
|
|
961
|
-
/* @__PURE__ */
|
|
962
|
-
/* @__PURE__ */
|
|
2269
|
+
return /* @__PURE__ */ jsxs11("div", { className: cn("space-y-2", className), children: [
|
|
2270
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
|
|
2271
|
+
/* @__PURE__ */ jsx13(
|
|
963
2272
|
"input",
|
|
964
2273
|
{
|
|
965
2274
|
type: "text",
|
|
@@ -972,7 +2281,7 @@ function Prompt({
|
|
|
972
2281
|
className: "flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-apteva-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white"
|
|
973
2282
|
}
|
|
974
2283
|
),
|
|
975
|
-
submitOn === "button" && /* @__PURE__ */
|
|
2284
|
+
submitOn === "button" && /* @__PURE__ */ jsx13(
|
|
976
2285
|
"button",
|
|
977
2286
|
{
|
|
978
2287
|
onClick: handleSubmit,
|
|
@@ -982,13 +2291,13 @@ function Prompt({
|
|
|
982
2291
|
}
|
|
983
2292
|
)
|
|
984
2293
|
] }),
|
|
985
|
-
maxLength && /* @__PURE__ */
|
|
2294
|
+
maxLength && /* @__PURE__ */ jsxs11("p", { className: "text-xs text-gray-500", children: [
|
|
986
2295
|
value.length,
|
|
987
2296
|
" / ",
|
|
988
2297
|
maxLength,
|
|
989
2298
|
" characters"
|
|
990
2299
|
] }),
|
|
991
|
-
showSuggestions && !value && /* @__PURE__ */
|
|
2300
|
+
showSuggestions && !value && /* @__PURE__ */ jsx13("div", { className: "flex flex-wrap gap-2", children: suggestions.map((suggestion, idx) => /* @__PURE__ */ jsx13(
|
|
992
2301
|
"button",
|
|
993
2302
|
{
|
|
994
2303
|
onClick: () => setValue(suggestion),
|
|
@@ -997,21 +2306,22 @@ function Prompt({
|
|
|
997
2306
|
},
|
|
998
2307
|
idx
|
|
999
2308
|
)) }),
|
|
1000
|
-
isLoading && /* @__PURE__ */
|
|
1001
|
-
/* @__PURE__ */
|
|
1002
|
-
/* @__PURE__ */
|
|
2309
|
+
isLoading && /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [
|
|
2310
|
+
/* @__PURE__ */ jsx13("div", { className: "w-4 h-4 border-2 border-apteva-500 border-t-transparent rounded-full animate-spin" }),
|
|
2311
|
+
/* @__PURE__ */ jsx13("span", { children: "AI is processing your request..." })
|
|
1003
2312
|
] })
|
|
1004
2313
|
] });
|
|
1005
2314
|
}
|
|
1006
2315
|
|
|
1007
2316
|
// src/components/Stream/Stream.tsx
|
|
1008
2317
|
import { useState as useState5, useEffect as useEffect5 } from "react";
|
|
1009
|
-
import { jsx as
|
|
2318
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1010
2319
|
function Stream({
|
|
1011
2320
|
agentId,
|
|
1012
2321
|
prompt,
|
|
1013
2322
|
context,
|
|
1014
2323
|
autoStart = false,
|
|
2324
|
+
useMock = true,
|
|
1015
2325
|
onStart,
|
|
1016
2326
|
onChunk,
|
|
1017
2327
|
onComplete,
|
|
@@ -1032,19 +2342,47 @@ function Stream({
|
|
|
1032
2342
|
const startStreaming = async () => {
|
|
1033
2343
|
setIsStreaming(true);
|
|
1034
2344
|
onStart?.();
|
|
1035
|
-
const mockText = "This is a simulated streaming response from the AI agent. In a real implementation, this would stream data from your backend API. The text appears word by word to simulate the streaming effect. You can customize the typing speed and styling based on your needs.";
|
|
1036
2345
|
try {
|
|
1037
|
-
|
|
1038
|
-
mockText,
|
|
1039
|
-
(
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
2346
|
+
if (useMock) {
|
|
2347
|
+
const mockText = "This is a simulated streaming response from the AI agent. In a real implementation, this would stream data from your backend API. The text appears word by word to simulate the streaming effect. You can customize the typing speed and styling based on your needs.";
|
|
2348
|
+
await generateMockStreamingResponse(
|
|
2349
|
+
mockText,
|
|
2350
|
+
(chunk) => {
|
|
2351
|
+
setText((prev) => prev + chunk);
|
|
2352
|
+
onChunk?.(chunk);
|
|
2353
|
+
},
|
|
2354
|
+
typingSpeed
|
|
2355
|
+
);
|
|
2356
|
+
setIsComplete(true);
|
|
2357
|
+
setIsStreaming(false);
|
|
2358
|
+
onComplete?.(text + mockText);
|
|
2359
|
+
} else {
|
|
2360
|
+
let accumulatedText = "";
|
|
2361
|
+
await aptevaClient.chatStream(
|
|
2362
|
+
{
|
|
2363
|
+
agent_id: agentId,
|
|
2364
|
+
message: prompt,
|
|
2365
|
+
stream: true
|
|
2366
|
+
},
|
|
2367
|
+
(chunk) => {
|
|
2368
|
+
if (chunk.type === "token" && chunk.content) {
|
|
2369
|
+
accumulatedText += chunk.content;
|
|
2370
|
+
setText(accumulatedText);
|
|
2371
|
+
onChunk?.(chunk.content);
|
|
2372
|
+
}
|
|
2373
|
+
},
|
|
2374
|
+
() => {
|
|
2375
|
+
setIsComplete(true);
|
|
2376
|
+
setIsStreaming(false);
|
|
2377
|
+
onComplete?.(accumulatedText);
|
|
2378
|
+
},
|
|
2379
|
+
(error) => {
|
|
2380
|
+
const err = error instanceof Error ? error : new Error("Streaming error");
|
|
2381
|
+
onError?.(err);
|
|
2382
|
+
setIsStreaming(false);
|
|
2383
|
+
}
|
|
2384
|
+
);
|
|
2385
|
+
}
|
|
1048
2386
|
} catch (error) {
|
|
1049
2387
|
const err = error instanceof Error ? error : new Error("Streaming error");
|
|
1050
2388
|
onError?.(err);
|
|
@@ -1057,7 +2395,7 @@ function Stream({
|
|
|
1057
2395
|
plain: "text-gray-900 dark:text-gray-100"
|
|
1058
2396
|
};
|
|
1059
2397
|
if (!isStreaming && !isComplete) {
|
|
1060
|
-
return /* @__PURE__ */
|
|
2398
|
+
return /* @__PURE__ */ jsx14("div", { className: cn("p-4", className), children: /* @__PURE__ */ jsx14(
|
|
1061
2399
|
"button",
|
|
1062
2400
|
{
|
|
1063
2401
|
onClick: startStreaming,
|
|
@@ -1066,9 +2404,9 @@ function Stream({
|
|
|
1066
2404
|
}
|
|
1067
2405
|
) });
|
|
1068
2406
|
}
|
|
1069
|
-
return /* @__PURE__ */
|
|
2407
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn(variantClasses[variant], className), children: [
|
|
1070
2408
|
text,
|
|
1071
|
-
isStreaming && showCursor && /* @__PURE__ */
|
|
2409
|
+
isStreaming && showCursor && /* @__PURE__ */ jsx14("span", { className: "apteva-stream-cursor" })
|
|
1072
2410
|
] });
|
|
1073
2411
|
}
|
|
1074
2412
|
|
|
@@ -1076,9 +2414,9 @@ function Stream({
|
|
|
1076
2414
|
import { useState as useState6 } from "react";
|
|
1077
2415
|
|
|
1078
2416
|
// src/components/Threads/ThreadItem.tsx
|
|
1079
|
-
import { jsx as
|
|
2417
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1080
2418
|
function ThreadItem({ thread, isActive = false, onSelect, onDelete }) {
|
|
1081
|
-
return /* @__PURE__ */
|
|
2419
|
+
return /* @__PURE__ */ jsxs13(
|
|
1082
2420
|
"div",
|
|
1083
2421
|
{
|
|
1084
2422
|
className: cn("apteva-thread-item", {
|
|
@@ -1086,19 +2424,19 @@ function ThreadItem({ thread, isActive = false, onSelect, onDelete }) {
|
|
|
1086
2424
|
}),
|
|
1087
2425
|
onClick: onSelect,
|
|
1088
2426
|
children: [
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1091
|
-
thread.preview && /* @__PURE__ */
|
|
1092
|
-
/* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
2427
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex-1 min-w-0", children: [
|
|
2428
|
+
/* @__PURE__ */ jsx15("h4", { className: "font-semibold text-gray-900 dark:text-white truncate", children: thread.title }),
|
|
2429
|
+
thread.preview && /* @__PURE__ */ jsx15("p", { className: "text-sm text-gray-600 dark:text-gray-400 truncate", children: thread.preview }),
|
|
2430
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 mt-1 text-xs text-gray-500", children: [
|
|
2431
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
1094
2432
|
thread.messageCount,
|
|
1095
2433
|
" messages"
|
|
1096
2434
|
] }),
|
|
1097
|
-
/* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
2435
|
+
/* @__PURE__ */ jsx15("span", { children: "\u2022" }),
|
|
2436
|
+
/* @__PURE__ */ jsx15("span", { children: formatRelativeTime(thread.updatedAt) })
|
|
1099
2437
|
] })
|
|
1100
2438
|
] }),
|
|
1101
|
-
onDelete && /* @__PURE__ */
|
|
2439
|
+
onDelete && /* @__PURE__ */ jsx15(
|
|
1102
2440
|
"button",
|
|
1103
2441
|
{
|
|
1104
2442
|
onClick: (e) => {
|
|
@@ -1128,7 +2466,7 @@ function formatRelativeTime(date) {
|
|
|
1128
2466
|
}
|
|
1129
2467
|
|
|
1130
2468
|
// src/components/Threads/ThreadList.tsx
|
|
1131
|
-
import { jsx as
|
|
2469
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1132
2470
|
function ThreadList({
|
|
1133
2471
|
threads,
|
|
1134
2472
|
currentThreadId,
|
|
@@ -1142,8 +2480,8 @@ function ThreadList({
|
|
|
1142
2480
|
(thread) => thread.title.toLowerCase().includes(searchQuery.toLowerCase()) || thread.preview?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
1143
2481
|
);
|
|
1144
2482
|
const groupedThreads = groupBy === "date" ? groupThreadsByDate(filteredThreads) : { All: filteredThreads };
|
|
1145
|
-
return /* @__PURE__ */
|
|
1146
|
-
showSearch && /* @__PURE__ */
|
|
2483
|
+
return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col h-full", children: [
|
|
2484
|
+
showSearch && /* @__PURE__ */ jsx16("div", { className: "p-3 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx16(
|
|
1147
2485
|
"input",
|
|
1148
2486
|
{
|
|
1149
2487
|
type: "text",
|
|
@@ -1153,10 +2491,10 @@ function ThreadList({
|
|
|
1153
2491
|
className: "w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-apteva-500 dark:bg-gray-800 dark:border-gray-600 dark:text-white"
|
|
1154
2492
|
}
|
|
1155
2493
|
) }),
|
|
1156
|
-
/* @__PURE__ */
|
|
1157
|
-
Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */
|
|
1158
|
-
groupBy !== "none" && /* @__PURE__ */
|
|
1159
|
-
groupThreads.map((thread) => /* @__PURE__ */
|
|
2494
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex-1 overflow-y-auto", children: [
|
|
2495
|
+
Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ jsxs14("div", { children: [
|
|
2496
|
+
groupBy !== "none" && /* @__PURE__ */ jsx16("div", { className: "px-3 py-2 text-xs font-semibold text-gray-500 uppercase", children: group }),
|
|
2497
|
+
groupThreads.map((thread) => /* @__PURE__ */ jsx16(
|
|
1160
2498
|
ThreadItem,
|
|
1161
2499
|
{
|
|
1162
2500
|
thread,
|
|
@@ -1167,9 +2505,9 @@ function ThreadList({
|
|
|
1167
2505
|
thread.id
|
|
1168
2506
|
))
|
|
1169
2507
|
] }, group)),
|
|
1170
|
-
filteredThreads.length === 0 && /* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1172
|
-
/* @__PURE__ */
|
|
2508
|
+
filteredThreads.length === 0 && /* @__PURE__ */ jsxs14("div", { className: "p-8 text-center text-gray-500", children: [
|
|
2509
|
+
/* @__PURE__ */ jsx16("div", { className: "text-4xl mb-2", children: "\u{1F4AC}" }),
|
|
2510
|
+
/* @__PURE__ */ jsx16("p", { children: "No conversations found" })
|
|
1173
2511
|
] })
|
|
1174
2512
|
] })
|
|
1175
2513
|
] });
|
|
@@ -1201,7 +2539,7 @@ function groupThreadsByDate(threads) {
|
|
|
1201
2539
|
}
|
|
1202
2540
|
|
|
1203
2541
|
// src/components/Threads/Threads.tsx
|
|
1204
|
-
import { jsx as
|
|
2542
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1205
2543
|
function Threads({
|
|
1206
2544
|
threads,
|
|
1207
2545
|
currentThreadId,
|
|
@@ -1220,8 +2558,8 @@ function Threads({
|
|
|
1220
2558
|
tabs: "flex gap-2 border-b border-gray-200 dark:border-gray-700 overflow-x-auto"
|
|
1221
2559
|
};
|
|
1222
2560
|
if (variant === "tabs") {
|
|
1223
|
-
return /* @__PURE__ */
|
|
1224
|
-
threads.slice(0, 5).map((thread) => /* @__PURE__ */
|
|
2561
|
+
return /* @__PURE__ */ jsxs15("div", { className: cn(variantClasses[variant], className), children: [
|
|
2562
|
+
threads.slice(0, 5).map((thread) => /* @__PURE__ */ jsx17(
|
|
1225
2563
|
"button",
|
|
1226
2564
|
{
|
|
1227
2565
|
onClick: () => onThreadSelect?.(thread.id),
|
|
@@ -1233,7 +2571,7 @@ function Threads({
|
|
|
1233
2571
|
},
|
|
1234
2572
|
thread.id
|
|
1235
2573
|
)),
|
|
1236
|
-
showNewButton && onNewThread && /* @__PURE__ */
|
|
2574
|
+
showNewButton && onNewThread && /* @__PURE__ */ jsx17(
|
|
1237
2575
|
"button",
|
|
1238
2576
|
{
|
|
1239
2577
|
onClick: onNewThread,
|
|
@@ -1243,8 +2581,8 @@ function Threads({
|
|
|
1243
2581
|
)
|
|
1244
2582
|
] });
|
|
1245
2583
|
}
|
|
1246
|
-
return /* @__PURE__ */
|
|
1247
|
-
showNewButton && onNewThread && /* @__PURE__ */
|
|
2584
|
+
return /* @__PURE__ */ jsxs15("div", { className: cn(variantClasses[variant], "flex flex-col", className), children: [
|
|
2585
|
+
showNewButton && onNewThread && /* @__PURE__ */ jsx17("div", { className: "p-3 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx17(
|
|
1248
2586
|
"button",
|
|
1249
2587
|
{
|
|
1250
2588
|
onClick: onNewThread,
|
|
@@ -1252,7 +2590,7 @@ function Threads({
|
|
|
1252
2590
|
children: "+ New Conversation"
|
|
1253
2591
|
}
|
|
1254
2592
|
) }),
|
|
1255
|
-
/* @__PURE__ */
|
|
2593
|
+
/* @__PURE__ */ jsx17(
|
|
1256
2594
|
ThreadList,
|
|
1257
2595
|
{
|
|
1258
2596
|
threads,
|
|
@@ -1290,6 +2628,7 @@ function getThemeScript() {
|
|
|
1290
2628
|
return themeScript;
|
|
1291
2629
|
}
|
|
1292
2630
|
export {
|
|
2631
|
+
AptevaClient,
|
|
1293
2632
|
Button,
|
|
1294
2633
|
Card,
|
|
1295
2634
|
Chat,
|
|
@@ -1299,6 +2638,7 @@ export {
|
|
|
1299
2638
|
Stream,
|
|
1300
2639
|
Threads,
|
|
1301
2640
|
Widgets,
|
|
2641
|
+
aptevaClient,
|
|
1302
2642
|
cn,
|
|
1303
2643
|
getThemeScript,
|
|
1304
2644
|
mockMessages,
|