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.
Files changed (83) hide show
  1. package/dist/{ActivityPage.c48n83h2.js → ActivityPage.sw9p594m.js} +1 -1
  2. package/dist/{ApiDocsPage.yzcxx5ax.js → ApiDocsPage.90e03bz7.js} +1 -1
  3. package/dist/App.0ws87fpx.js +53 -0
  4. package/dist/App.3vnrera5.js +4 -0
  5. package/dist/App.94x6mh7f.js +20 -0
  6. package/dist/{App.qzbx5wtj.js → App.9sryp183.js} +1 -1
  7. package/dist/App.d9tny4t0.js +221 -0
  8. package/dist/{App.r5serxkt.js → App.jhb45d7r.js} +1 -1
  9. package/dist/App.p7jjw1zf.js +4 -0
  10. package/dist/App.pfbdzrhh.js +4 -0
  11. package/dist/App.stgng5bx.js +13 -0
  12. package/dist/{App.152mbs1r.js → App.tm3k7h4b.js} +1 -1
  13. package/dist/App.vkg121c6.js +4 -0
  14. package/dist/App.wghtdzsk.js +1 -0
  15. package/dist/App.xf7wsckg.js +4 -0
  16. package/dist/App.xva0tfzh.js +4 -0
  17. package/dist/App.ysxy7akk.js +61 -0
  18. package/dist/App.yzkh4gq2.js +4 -0
  19. package/dist/ConnectionsPage.q5f9fd37.js +3 -0
  20. package/dist/McpPage.f3ccrezb.js +3 -0
  21. package/dist/SettingsPage.3sqx6wm4.js +3 -0
  22. package/dist/SkillsPage.whxnez67.js +3 -0
  23. package/dist/TasksPage.zp4jfevw.js +3 -0
  24. package/dist/TelemetryPage.a9fmxq87.js +3 -0
  25. package/dist/TestsPage.18krj0d1.js +3 -0
  26. package/dist/ThreadsPage.nnphgy98.js +3 -0
  27. package/dist/apteva-kit.css +1 -1
  28. package/dist/index.html +1 -1
  29. package/dist/styles.css +1 -1
  30. package/package.json +5 -4
  31. package/src/db.ts +42 -4
  32. package/src/providers.ts +14 -9
  33. package/src/routes/api/agent-utils.ts +25 -3
  34. package/src/routes/api/telemetry.ts +20 -2
  35. package/src/server.ts +52 -1
  36. package/src/web/App.tsx +1 -1
  37. package/src/web/components/agents/AgentCard.tsx +9 -7
  38. package/src/web/components/agents/AgentPanel.tsx +205 -44
  39. package/src/web/components/agents/CreateAgentModal.tsx +5 -5
  40. package/src/web/components/auth/LoginPage.tsx +2 -2
  41. package/src/web/components/common/LoadingSpinner.tsx +1 -1
  42. package/src/web/components/common/Modal.tsx +6 -6
  43. package/src/web/components/common/Select.tsx +2 -2
  44. package/src/web/components/connections/ConnectionsPage.tsx +1 -1
  45. package/src/web/components/connections/IntegrationsTab.tsx +3 -3
  46. package/src/web/components/connections/OverviewTab.tsx +3 -3
  47. package/src/web/components/connections/TriggersTab.tsx +8 -8
  48. package/src/web/components/dashboard/Dashboard.tsx +2 -2
  49. package/src/web/components/layout/Header.tsx +3 -3
  50. package/src/web/components/layout/Sidebar.tsx +3 -2
  51. package/src/web/components/mcp/McpPage.tsx +13 -13
  52. package/src/web/components/onboarding/OnboardingWizard.tsx +2 -2
  53. package/src/web/components/settings/SettingsPage.tsx +55 -22
  54. package/src/web/components/skills/SkillsPage.tsx +7 -7
  55. package/src/web/components/tasks/TasksPage.tsx +212 -36
  56. package/src/web/components/telemetry/TelemetryPage.tsx +278 -9
  57. package/src/web/components/tests/TestsPage.tsx +2 -2
  58. package/src/web/components/threads/ThreadsPage.tsx +2 -2
  59. package/src/web/context/ThemeContext.tsx +31 -10
  60. package/src/web/index.html +1 -6
  61. package/src/web/styles.css +47 -0
  62. package/src/web/themes.ts +68 -5
  63. package/dist/App.09yb8t0b.js +0 -1
  64. package/dist/App.3a67nx9w.js +0 -4
  65. package/dist/App.9epx6785.js +0 -4
  66. package/dist/App.d8955awp.js +0 -4
  67. package/dist/App.drwb57jq.js +0 -4
  68. package/dist/App.gssbmajb.js +0 -4
  69. package/dist/App.qw70pc29.js +0 -53
  70. package/dist/App.tpmp9020.js +0 -20
  71. package/dist/App.v2wb4d7d.js +0 -61
  72. package/dist/App.vxmaaj0m.js +0 -13
  73. package/dist/App.w4p2tda9.js +0 -4
  74. package/dist/App.wv2ng55q.js +0 -221
  75. package/dist/App.yncnrn0f.js +0 -4
  76. package/dist/ConnectionsPage.k6cspyqq.js +0 -3
  77. package/dist/McpPage.cdxm48xj.js +0 -3
  78. package/dist/SettingsPage.evpv7c2y.js +0 -3
  79. package/dist/SkillsPage.pvzp6c1a.js +0 -3
  80. package/dist/TasksPage.6jnvbpsy.js +0 -3
  81. package/dist/TelemetryPage.t7vk24zc.js +0 -3
  82. package/dist/TestsPage.5x6658aa.js +0 -3
  83. 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
- <button onClick={onClose} className="text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition">
369
- <CloseIcon />
370
- </button>
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
- <h3 className="text-lg font-medium">{task.title}</h3>
380
- <span className={`px-2 py-1 rounded text-xs font-medium flex-shrink-0 ${statusColors[task.status]}`}>
381
- {task.status}
382
- </span>
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
- <button
385
- onClick={() => onSelectAgent?.(task.agentId)}
386
- className="text-sm text-[var(--color-accent)] hover:underline"
387
- >
388
- {task.agentName}
389
- </button>
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
- {task.description && (
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
- <div className="grid grid-cols-2 gap-3 text-sm">
402
- <div>
403
- <span className="text-[var(--color-text-muted)]">Type</span>
404
- <p className="capitalize">{task.type}</p>
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
- <span className="text-[var(--color-text-muted)]">Priority</span>
408
- <p>{task.priority}</p>
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
- <span className="text-[var(--color-text-muted)]">Source</span>
412
- <p className="capitalize">{task.source}</p>
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
- {task.recurrence && (
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)] border border-[var(--color-border)] rounded-lg w-full max-w-md" onClick={e => e.stopPropagation()}>
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">