apteva 0.4.44 → 0.4.48
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/{ActivityPage.c48n83h2.js → ActivityPage.sw9p594m.js} +1 -1
- package/dist/{ApiDocsPage.yzcxx5ax.js → ApiDocsPage.90e03bz7.js} +1 -1
- package/dist/App.0ws87fpx.js +53 -0
- package/dist/App.3vnrera5.js +4 -0
- package/dist/App.94x6mh7f.js +20 -0
- package/dist/{App.qzbx5wtj.js → App.9sryp183.js} +1 -1
- package/dist/App.d9tny4t0.js +221 -0
- package/dist/{App.r5serxkt.js → App.jhb45d7r.js} +1 -1
- package/dist/App.p7jjw1zf.js +4 -0
- package/dist/App.pfbdzrhh.js +4 -0
- package/dist/App.stgng5bx.js +13 -0
- package/dist/{App.152mbs1r.js → App.tm3k7h4b.js} +1 -1
- package/dist/App.vkg121c6.js +4 -0
- package/dist/App.wghtdzsk.js +1 -0
- package/dist/App.xf7wsckg.js +4 -0
- package/dist/App.xva0tfzh.js +4 -0
- package/dist/App.ysxy7akk.js +61 -0
- package/dist/App.yzkh4gq2.js +4 -0
- package/dist/ConnectionsPage.q5f9fd37.js +3 -0
- package/dist/McpPage.f3ccrezb.js +3 -0
- package/dist/SettingsPage.3sqx6wm4.js +3 -0
- package/dist/SkillsPage.whxnez67.js +3 -0
- package/dist/TasksPage.zp4jfevw.js +3 -0
- package/dist/TelemetryPage.a9fmxq87.js +3 -0
- package/dist/TestsPage.18krj0d1.js +3 -0
- package/dist/ThreadsPage.nnphgy98.js +3 -0
- package/dist/apteva-kit.css +1 -1
- package/dist/index.html +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -4
- package/src/db.ts +42 -4
- package/src/providers.ts +14 -9
- package/src/routes/api/agent-utils.ts +25 -3
- package/src/routes/api/telemetry.ts +20 -2
- package/src/server.ts +52 -1
- package/src/web/App.tsx +1 -1
- package/src/web/components/agents/AgentCard.tsx +9 -7
- package/src/web/components/agents/AgentPanel.tsx +205 -44
- package/src/web/components/agents/CreateAgentModal.tsx +5 -5
- package/src/web/components/auth/LoginPage.tsx +2 -2
- package/src/web/components/common/LoadingSpinner.tsx +1 -1
- package/src/web/components/common/Modal.tsx +6 -6
- package/src/web/components/common/Select.tsx +2 -2
- package/src/web/components/connections/ConnectionsPage.tsx +1 -1
- package/src/web/components/connections/IntegrationsTab.tsx +3 -3
- package/src/web/components/connections/OverviewTab.tsx +3 -3
- package/src/web/components/connections/TriggersTab.tsx +8 -8
- package/src/web/components/dashboard/Dashboard.tsx +2 -2
- package/src/web/components/layout/Header.tsx +3 -3
- package/src/web/components/layout/Sidebar.tsx +3 -2
- package/src/web/components/mcp/McpPage.tsx +13 -13
- package/src/web/components/onboarding/OnboardingWizard.tsx +2 -2
- package/src/web/components/settings/SettingsPage.tsx +55 -22
- package/src/web/components/skills/SkillsPage.tsx +7 -7
- package/src/web/components/tasks/TasksPage.tsx +212 -36
- package/src/web/components/telemetry/TelemetryPage.tsx +278 -9
- package/src/web/components/tests/TestsPage.tsx +2 -2
- package/src/web/components/threads/ThreadsPage.tsx +2 -2
- package/src/web/context/ThemeContext.tsx +31 -10
- package/src/web/index.html +1 -6
- package/src/web/styles.css +47 -0
- package/src/web/themes.ts +68 -5
- package/dist/App.09yb8t0b.js +0 -1
- package/dist/App.3a67nx9w.js +0 -4
- package/dist/App.9epx6785.js +0 -4
- package/dist/App.d8955awp.js +0 -4
- package/dist/App.drwb57jq.js +0 -4
- package/dist/App.gssbmajb.js +0 -4
- package/dist/App.qw70pc29.js +0 -53
- package/dist/App.tpmp9020.js +0 -20
- package/dist/App.v2wb4d7d.js +0 -61
- package/dist/App.vxmaaj0m.js +0 -13
- package/dist/App.w4p2tda9.js +0 -4
- package/dist/App.wv2ng55q.js +0 -221
- package/dist/App.yncnrn0f.js +0 -4
- package/dist/ConnectionsPage.k6cspyqq.js +0 -3
- package/dist/McpPage.cdxm48xj.js +0 -3
- package/dist/SettingsPage.evpv7c2y.js +0 -3
- package/dist/SkillsPage.pvzp6c1a.js +0 -3
- package/dist/TasksPage.6jnvbpsy.js +0 -3
- package/dist/TelemetryPage.t7vk24zc.js +0 -3
- package/dist/TestsPage.5x6658aa.js +0 -3
- package/dist/ThreadsPage.3fvhtevh.js +0 -3
|
@@ -304,8 +304,63 @@ export interface TaskDetailPanelProps {
|
|
|
304
304
|
export function TaskDetailPanel({ task, statusColors, onClose, onSelectAgent, loading, authFetch, onRefresh }: TaskDetailPanelProps) {
|
|
305
305
|
const [executing, setExecuting] = useState(false);
|
|
306
306
|
const [deleting, setDeleting] = useState(false);
|
|
307
|
+
const [editing, setEditing] = useState(false);
|
|
308
|
+
const [saving, setSaving] = useState(false);
|
|
309
|
+
const [editForm, setEditForm] = useState({
|
|
310
|
+
title: task.title,
|
|
311
|
+
description: task.description || "",
|
|
312
|
+
type: task.type as "once" | "recurring",
|
|
313
|
+
priority: task.priority,
|
|
314
|
+
execute_at: task.execute_at ? new Date(task.execute_at).toISOString().slice(0, 16) : "",
|
|
315
|
+
recurrence: task.recurrence || "",
|
|
316
|
+
});
|
|
307
317
|
const { confirm, ConfirmDialog } = useConfirm();
|
|
308
318
|
|
|
319
|
+
// Reset edit form when task changes
|
|
320
|
+
useEffect(() => {
|
|
321
|
+
setEditForm({
|
|
322
|
+
title: task.title,
|
|
323
|
+
description: task.description || "",
|
|
324
|
+
type: task.type as "once" | "recurring",
|
|
325
|
+
priority: task.priority,
|
|
326
|
+
execute_at: task.execute_at ? new Date(task.execute_at).toISOString().slice(0, 16) : "",
|
|
327
|
+
recurrence: task.recurrence || "",
|
|
328
|
+
});
|
|
329
|
+
setEditing(false);
|
|
330
|
+
}, [task.id, task.agentId]);
|
|
331
|
+
|
|
332
|
+
const handleSave = async () => {
|
|
333
|
+
if (!authFetch || saving) return;
|
|
334
|
+
setSaving(true);
|
|
335
|
+
try {
|
|
336
|
+
const body: Record<string, unknown> = {
|
|
337
|
+
title: editForm.title.trim(),
|
|
338
|
+
description: editForm.description.trim() || undefined,
|
|
339
|
+
type: editForm.type,
|
|
340
|
+
priority: editForm.priority,
|
|
341
|
+
};
|
|
342
|
+
if (editForm.type === "once" && editForm.execute_at) {
|
|
343
|
+
body.execute_at = new Date(editForm.execute_at).toISOString();
|
|
344
|
+
}
|
|
345
|
+
if (editForm.type === "recurring" && editForm.recurrence.trim()) {
|
|
346
|
+
body.recurrence = editForm.recurrence.trim();
|
|
347
|
+
}
|
|
348
|
+
const res = await authFetch(`/api/tasks/${task.agentId}/${task.id}`, {
|
|
349
|
+
method: "PUT",
|
|
350
|
+
headers: { "Content-Type": "application/json" },
|
|
351
|
+
body: JSON.stringify(body),
|
|
352
|
+
});
|
|
353
|
+
if (res.ok) {
|
|
354
|
+
setEditing(false);
|
|
355
|
+
onRefresh?.();
|
|
356
|
+
}
|
|
357
|
+
} catch (e) {
|
|
358
|
+
console.error("Failed to update task:", e);
|
|
359
|
+
} finally {
|
|
360
|
+
setSaving(false);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
309
364
|
const handleExecute = async () => {
|
|
310
365
|
if (!authFetch || executing) return;
|
|
311
366
|
setExecuting(true);
|
|
@@ -338,14 +393,25 @@ export function TaskDetailPanel({ task, statusColors, onClose, onSelectAgent, lo
|
|
|
338
393
|
}
|
|
339
394
|
};
|
|
340
395
|
|
|
396
|
+
const inputClass = "w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded px-2 py-1.5 text-sm focus:outline-none focus:border-[var(--color-accent)] text-[var(--color-text)]";
|
|
397
|
+
|
|
341
398
|
return (
|
|
342
399
|
<div className="w-full md:w-1/2 lg:w-1/3 border-l border-[var(--color-border)] bg-[var(--color-bg)] flex flex-col overflow-hidden">
|
|
343
400
|
{ConfirmDialog}
|
|
344
401
|
{/* Header */}
|
|
345
402
|
<div className="flex items-center justify-between p-4 border-b border-[var(--color-border)]">
|
|
346
|
-
<h2 className="font-medium truncate pr-2">Task Details</h2>
|
|
403
|
+
<h2 className="font-medium truncate pr-2">{editing ? "Edit Task" : "Task Details"}</h2>
|
|
347
404
|
<div className="flex items-center gap-2">
|
|
348
|
-
{authFetch && (task.status === "pending" || task.status === "completed") && (
|
|
405
|
+
{authFetch && !editing && (task.status === "pending" || task.status === "completed" || task.status === "failed") && (
|
|
406
|
+
<button
|
|
407
|
+
onClick={() => setEditing(true)}
|
|
408
|
+
title="Edit task"
|
|
409
|
+
className="text-[var(--color-text-muted)] hover:text-[var(--color-accent)] transition"
|
|
410
|
+
>
|
|
411
|
+
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" /></svg>
|
|
412
|
+
</button>
|
|
413
|
+
)}
|
|
414
|
+
{authFetch && !editing && (task.status === "pending" || task.status === "completed") && (
|
|
349
415
|
<button
|
|
350
416
|
onClick={handleExecute}
|
|
351
417
|
disabled={executing}
|
|
@@ -355,7 +421,7 @@ export function TaskDetailPanel({ task, statusColors, onClose, onSelectAgent, lo
|
|
|
355
421
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" /><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
|
356
422
|
</button>
|
|
357
423
|
)}
|
|
358
|
-
{authFetch && (
|
|
424
|
+
{authFetch && !editing && (
|
|
359
425
|
<button
|
|
360
426
|
onClick={handleDelete}
|
|
361
427
|
disabled={deleting}
|
|
@@ -365,9 +431,38 @@ export function TaskDetailPanel({ task, statusColors, onClose, onSelectAgent, lo
|
|
|
365
431
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /></svg>
|
|
366
432
|
</button>
|
|
367
433
|
)}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
434
|
+
{editing && (
|
|
435
|
+
<>
|
|
436
|
+
<button
|
|
437
|
+
onClick={() => {
|
|
438
|
+
setEditing(false);
|
|
439
|
+
setEditForm({
|
|
440
|
+
title: task.title,
|
|
441
|
+
description: task.description || "",
|
|
442
|
+
type: task.type as "once" | "recurring",
|
|
443
|
+
priority: task.priority,
|
|
444
|
+
execute_at: task.execute_at ? new Date(task.execute_at).toISOString().slice(0, 16) : "",
|
|
445
|
+
recurrence: task.recurrence || "",
|
|
446
|
+
});
|
|
447
|
+
}}
|
|
448
|
+
className="text-[var(--color-text-muted)] hover:text-[var(--color-text)] text-sm transition"
|
|
449
|
+
>
|
|
450
|
+
Cancel
|
|
451
|
+
</button>
|
|
452
|
+
<button
|
|
453
|
+
onClick={handleSave}
|
|
454
|
+
disabled={saving || !editForm.title.trim()}
|
|
455
|
+
className="px-3 py-1 rounded text-sm bg-[var(--color-accent)] text-black hover:opacity-90 transition disabled:opacity-50"
|
|
456
|
+
>
|
|
457
|
+
{saving ? "Saving..." : "Save"}
|
|
458
|
+
</button>
|
|
459
|
+
</>
|
|
460
|
+
)}
|
|
461
|
+
{!editing && (
|
|
462
|
+
<button onClick={onClose} className="text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition">
|
|
463
|
+
<CloseIcon />
|
|
464
|
+
</button>
|
|
465
|
+
)}
|
|
371
466
|
</div>
|
|
372
467
|
</div>
|
|
373
468
|
|
|
@@ -376,51 +471,131 @@ export function TaskDetailPanel({ task, statusColors, onClose, onSelectAgent, lo
|
|
|
376
471
|
{/* Title & Status */}
|
|
377
472
|
<div>
|
|
378
473
|
<div className="flex items-start justify-between gap-2 mb-2">
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
474
|
+
{editing ? (
|
|
475
|
+
<input
|
|
476
|
+
type="text"
|
|
477
|
+
value={editForm.title}
|
|
478
|
+
onChange={e => setEditForm({ ...editForm, title: e.target.value })}
|
|
479
|
+
className={`${inputClass} text-lg font-medium`}
|
|
480
|
+
placeholder="Task title"
|
|
481
|
+
/>
|
|
482
|
+
) : (
|
|
483
|
+
<h3 className="text-lg font-medium">{task.title}</h3>
|
|
484
|
+
)}
|
|
485
|
+
{!editing && (
|
|
486
|
+
<span className={`px-2 py-1 rounded text-xs font-medium flex-shrink-0 ${statusColors[task.status]}`}>
|
|
487
|
+
{task.status}
|
|
488
|
+
</span>
|
|
489
|
+
)}
|
|
383
490
|
</div>
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
491
|
+
{!editing && (
|
|
492
|
+
<button
|
|
493
|
+
onClick={() => onSelectAgent?.(task.agentId)}
|
|
494
|
+
className="text-sm text-[var(--color-accent)] hover:underline"
|
|
495
|
+
>
|
|
496
|
+
{task.agentName}
|
|
497
|
+
</button>
|
|
498
|
+
)}
|
|
390
499
|
</div>
|
|
391
500
|
|
|
392
501
|
{/* Description */}
|
|
393
|
-
{
|
|
502
|
+
{editing ? (
|
|
503
|
+
<div>
|
|
504
|
+
<h4 className="text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1">Description</h4>
|
|
505
|
+
<textarea
|
|
506
|
+
value={editForm.description}
|
|
507
|
+
onChange={e => setEditForm({ ...editForm, description: e.target.value })}
|
|
508
|
+
className={`${inputClass} resize-none`}
|
|
509
|
+
rows={3}
|
|
510
|
+
placeholder="Task description..."
|
|
511
|
+
/>
|
|
512
|
+
</div>
|
|
513
|
+
) : task.description ? (
|
|
394
514
|
<div>
|
|
395
515
|
<h4 className="text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1">Description</h4>
|
|
396
516
|
<p className="text-sm text-[var(--color-text-secondary)] whitespace-pre-wrap">{task.description}</p>
|
|
397
517
|
</div>
|
|
398
|
-
)}
|
|
518
|
+
) : null}
|
|
399
519
|
|
|
400
520
|
{/* Metadata */}
|
|
401
|
-
|
|
402
|
-
<div>
|
|
403
|
-
<
|
|
404
|
-
|
|
521
|
+
{editing ? (
|
|
522
|
+
<div className="grid grid-cols-2 gap-3">
|
|
523
|
+
<div>
|
|
524
|
+
<label className="text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block">Type</label>
|
|
525
|
+
<select
|
|
526
|
+
value={editForm.type}
|
|
527
|
+
onChange={e => setEditForm({ ...editForm, type: e.target.value as "once" | "recurring" })}
|
|
528
|
+
className={inputClass}
|
|
529
|
+
>
|
|
530
|
+
<option value="once">One-time</option>
|
|
531
|
+
<option value="recurring">Recurring</option>
|
|
532
|
+
</select>
|
|
533
|
+
</div>
|
|
534
|
+
<div>
|
|
535
|
+
<label className="text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block">Priority</label>
|
|
536
|
+
<input
|
|
537
|
+
type="number"
|
|
538
|
+
min={1}
|
|
539
|
+
max={10}
|
|
540
|
+
value={editForm.priority}
|
|
541
|
+
onChange={e => setEditForm({ ...editForm, priority: Number(e.target.value) })}
|
|
542
|
+
className={inputClass}
|
|
543
|
+
/>
|
|
544
|
+
</div>
|
|
545
|
+
</div>
|
|
546
|
+
) : (
|
|
547
|
+
<div className="grid grid-cols-2 gap-3 text-sm">
|
|
548
|
+
<div>
|
|
549
|
+
<span className="text-[var(--color-text-muted)]">Type</span>
|
|
550
|
+
<p className="capitalize">{task.type}</p>
|
|
551
|
+
</div>
|
|
552
|
+
<div>
|
|
553
|
+
<span className="text-[var(--color-text-muted)]">Priority</span>
|
|
554
|
+
<p>{task.priority}</p>
|
|
555
|
+
</div>
|
|
556
|
+
<div>
|
|
557
|
+
<span className="text-[var(--color-text-muted)]">Source</span>
|
|
558
|
+
<p className="capitalize">{task.source}</p>
|
|
559
|
+
</div>
|
|
560
|
+
{task.recurrence && (
|
|
561
|
+
<div>
|
|
562
|
+
<span className="text-[var(--color-text-muted)]">Recurrence</span>
|
|
563
|
+
<p>{formatCron(task.recurrence)}</p>
|
|
564
|
+
<p className="text-xs text-[var(--color-text-faint)] mt-0.5 font-mono">{task.recurrence}</p>
|
|
565
|
+
</div>
|
|
566
|
+
)}
|
|
405
567
|
</div>
|
|
568
|
+
)}
|
|
569
|
+
|
|
570
|
+
{/* Schedule (edit mode) */}
|
|
571
|
+
{editing && editForm.type === "once" && (
|
|
406
572
|
<div>
|
|
407
|
-
<
|
|
408
|
-
<
|
|
573
|
+
<label className="text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block">Schedule</label>
|
|
574
|
+
<input
|
|
575
|
+
type="datetime-local"
|
|
576
|
+
value={editForm.execute_at}
|
|
577
|
+
onChange={e => setEditForm({ ...editForm, execute_at: e.target.value })}
|
|
578
|
+
className={inputClass}
|
|
579
|
+
/>
|
|
580
|
+
<p className="text-xs text-[var(--color-text-faint)] mt-1">Leave empty for manual execution</p>
|
|
409
581
|
</div>
|
|
582
|
+
)}
|
|
583
|
+
{editing && editForm.type === "recurring" && (
|
|
410
584
|
<div>
|
|
411
|
-
<
|
|
412
|
-
<
|
|
585
|
+
<label className="text-xs text-[var(--color-text-muted)] uppercase tracking-wider mb-1 block">Cron Schedule</label>
|
|
586
|
+
<input
|
|
587
|
+
type="text"
|
|
588
|
+
value={editForm.recurrence}
|
|
589
|
+
onChange={e => setEditForm({ ...editForm, recurrence: e.target.value })}
|
|
590
|
+
className={`${inputClass} font-mono`}
|
|
591
|
+
placeholder="*/30 * * * *"
|
|
592
|
+
/>
|
|
593
|
+
<p className="text-xs text-[var(--color-text-faint)] mt-1">e.g. */30 * * * * = every 30 min</p>
|
|
413
594
|
</div>
|
|
414
|
-
|
|
415
|
-
<div>
|
|
416
|
-
<span className="text-[var(--color-text-muted)]">Recurrence</span>
|
|
417
|
-
<p>{formatCron(task.recurrence)}</p>
|
|
418
|
-
<p className="text-xs text-[var(--color-text-faint)] mt-0.5 font-mono">{task.recurrence}</p>
|
|
419
|
-
</div>
|
|
420
|
-
)}
|
|
421
|
-
</div>
|
|
595
|
+
)}
|
|
422
596
|
|
|
423
|
-
{/* Timestamps */}
|
|
597
|
+
{/* Timestamps (view mode only) */}
|
|
598
|
+
{!editing && (
|
|
424
599
|
<div className="space-y-2 text-sm">
|
|
425
600
|
<div className="flex justify-between">
|
|
426
601
|
<span className="text-[var(--color-text-muted)]">Created</span>
|
|
@@ -451,6 +626,7 @@ export function TaskDetailPanel({ task, statusColors, onClose, onSelectAgent, lo
|
|
|
451
626
|
</div>
|
|
452
627
|
)}
|
|
453
628
|
</div>
|
|
629
|
+
)}
|
|
454
630
|
|
|
455
631
|
{/* Error */}
|
|
456
632
|
{task.status === "failed" && task.error && (
|
|
@@ -707,7 +883,7 @@ function CreateTaskModal({ authFetch, currentProjectId, onClose, onCreated }: Cr
|
|
|
707
883
|
|
|
708
884
|
return (
|
|
709
885
|
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4" onClick={onClose}>
|
|
710
|
-
<div className="bg-[var(--color-surface)]
|
|
886
|
+
<div className="bg-[var(--color-surface)] card w-full max-w-md" onClick={e => e.stopPropagation()}>
|
|
711
887
|
<div className="flex items-center justify-between p-4 border-b border-[var(--color-border)]">
|
|
712
888
|
<h2 className="font-medium">Create Task</h2>
|
|
713
889
|
<button onClick={onClose} className="text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition">
|