@synergenius/flow-weaver-pack-weaver 0.9.62 → 0.9.78

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 (162) hide show
  1. package/dist/ai-chat-provider.d.ts +12 -0
  2. package/dist/ai-chat-provider.d.ts.map +1 -1
  3. package/dist/ai-chat-provider.js +173 -19
  4. package/dist/ai-chat-provider.js.map +1 -1
  5. package/dist/bot/agent-loop.d.ts +20 -0
  6. package/dist/bot/agent-loop.d.ts.map +1 -0
  7. package/dist/bot/agent-loop.js +331 -0
  8. package/dist/bot/agent-loop.js.map +1 -0
  9. package/dist/bot/ai-router.d.ts +19 -0
  10. package/dist/bot/ai-router.d.ts.map +1 -0
  11. package/dist/bot/ai-router.js +104 -0
  12. package/dist/bot/ai-router.js.map +1 -0
  13. package/dist/bot/bot-registry.js +2 -2
  14. package/dist/bot/bot-registry.js.map +1 -1
  15. package/dist/bot/conversation-store.d.ts +1 -0
  16. package/dist/bot/conversation-store.d.ts.map +1 -1
  17. package/dist/bot/conversation-store.js.map +1 -1
  18. package/dist/bot/improve-loop.js.map +1 -1
  19. package/dist/bot/instance-manager.d.ts +31 -0
  20. package/dist/bot/instance-manager.d.ts.map +1 -0
  21. package/dist/bot/instance-manager.js +115 -0
  22. package/dist/bot/instance-manager.js.map +1 -0
  23. package/dist/bot/orchestrator.d.ts +36 -0
  24. package/dist/bot/orchestrator.d.ts.map +1 -0
  25. package/dist/bot/orchestrator.js +176 -0
  26. package/dist/bot/orchestrator.js.map +1 -0
  27. package/dist/bot/profile-store.d.ts +36 -0
  28. package/dist/bot/profile-store.d.ts.map +1 -0
  29. package/dist/bot/profile-store.js +208 -0
  30. package/dist/bot/profile-store.js.map +1 -0
  31. package/dist/bot/profile-types.d.ts +126 -0
  32. package/dist/bot/profile-types.d.ts.map +1 -0
  33. package/dist/bot/profile-types.js +7 -0
  34. package/dist/bot/profile-types.js.map +1 -0
  35. package/dist/bot/session-state.d.ts +25 -0
  36. package/dist/bot/session-state.d.ts.map +1 -0
  37. package/dist/bot/session-state.js +110 -0
  38. package/dist/bot/session-state.js.map +1 -0
  39. package/dist/bot/swarm-controller.d.ts +37 -21
  40. package/dist/bot/swarm-controller.d.ts.map +1 -1
  41. package/dist/bot/swarm-controller.js +344 -163
  42. package/dist/bot/swarm-controller.js.map +1 -1
  43. package/dist/bot/task-prompt-builder.d.ts +2 -1
  44. package/dist/bot/task-prompt-builder.d.ts.map +1 -1
  45. package/dist/bot/task-prompt-builder.js +33 -10
  46. package/dist/bot/task-prompt-builder.js.map +1 -1
  47. package/dist/bot/task-queue.d.ts +46 -0
  48. package/dist/bot/task-queue.d.ts.map +1 -0
  49. package/dist/bot/task-queue.js +237 -0
  50. package/dist/bot/task-queue.js.map +1 -0
  51. package/dist/bot/task-store.d.ts +1 -6
  52. package/dist/bot/task-store.d.ts.map +1 -1
  53. package/dist/bot/task-store.js +27 -78
  54. package/dist/bot/task-store.js.map +1 -1
  55. package/dist/bot/task-types.d.ts +8 -4
  56. package/dist/bot/task-types.d.ts.map +1 -1
  57. package/dist/cli-handlers.d.ts.map +1 -1
  58. package/dist/cli-handlers.js +2 -3
  59. package/dist/cli-handlers.js.map +1 -1
  60. package/dist/cli.d.ts +3 -0
  61. package/dist/cli.d.ts.map +1 -0
  62. package/dist/cli.js +749 -0
  63. package/dist/cli.js.map +1 -0
  64. package/dist/docs/docs/weaver-bot-usage.md +35 -18
  65. package/dist/docs/docs/weaver-config.md +20 -0
  66. package/dist/docs/docs/weaver-task-queue.md +31 -19
  67. package/dist/docs/weaver-config.md +15 -9
  68. package/dist/mcp-tools.d.ts +17 -0
  69. package/dist/mcp-tools.d.ts.map +1 -1
  70. package/dist/mcp-tools.js +98 -232
  71. package/dist/mcp-tools.js.map +1 -1
  72. package/dist/node-types/orchestrator-dispatch.d.ts +17 -0
  73. package/dist/node-types/orchestrator-dispatch.d.ts.map +1 -0
  74. package/dist/node-types/orchestrator-dispatch.js +63 -0
  75. package/dist/node-types/orchestrator-dispatch.js.map +1 -0
  76. package/dist/node-types/orchestrator-load-state.d.ts +16 -0
  77. package/dist/node-types/orchestrator-load-state.d.ts.map +1 -0
  78. package/dist/node-types/orchestrator-load-state.js +60 -0
  79. package/dist/node-types/orchestrator-load-state.js.map +1 -0
  80. package/dist/node-types/orchestrator-route.d.ts +16 -0
  81. package/dist/node-types/orchestrator-route.d.ts.map +1 -0
  82. package/dist/node-types/orchestrator-route.js +28 -0
  83. package/dist/node-types/orchestrator-route.js.map +1 -0
  84. package/dist/node-types/receive-task.d.ts +2 -3
  85. package/dist/node-types/receive-task.d.ts.map +1 -1
  86. package/dist/node-types/receive-task.js +3 -28
  87. package/dist/node-types/receive-task.js.map +1 -1
  88. package/dist/templates/weaver-template.d.ts +11 -0
  89. package/dist/templates/weaver-template.d.ts.map +1 -0
  90. package/dist/templates/weaver-template.js +53 -0
  91. package/dist/templates/weaver-template.js.map +1 -0
  92. package/dist/ui/bot-constants.d.ts +14 -0
  93. package/dist/ui/bot-constants.d.ts.map +1 -0
  94. package/dist/ui/bot-constants.js +189 -0
  95. package/dist/ui/bot-constants.js.map +1 -0
  96. package/dist/ui/bot-panel.js +51 -90
  97. package/dist/ui/bot-slot-card.js +87 -122
  98. package/dist/ui/budget-bar.js +5 -3
  99. package/dist/ui/chat-task-result.js +4 -7
  100. package/dist/ui/decision-log.js +136 -0
  101. package/dist/ui/profile-card.js +158 -0
  102. package/dist/ui/profile-editor.js +597 -0
  103. package/dist/ui/swarm-controls.js +36 -27
  104. package/dist/ui/swarm-dashboard.js +2034 -736
  105. package/dist/ui/task-create-form.js +39 -116
  106. package/dist/ui/task-detail-view.js +490 -239
  107. package/dist/ui/task-pool-list.js +69 -94
  108. package/dist/workflows/orchestrator.d.ts +21 -0
  109. package/dist/workflows/orchestrator.d.ts.map +1 -0
  110. package/dist/workflows/orchestrator.js +281 -0
  111. package/dist/workflows/orchestrator.js.map +1 -0
  112. package/dist/workflows/weaver-bot-session.d.ts +65 -0
  113. package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
  114. package/dist/workflows/weaver-bot-session.js +68 -0
  115. package/dist/workflows/weaver-bot-session.js.map +1 -0
  116. package/dist/workflows/weaver.d.ts +24 -0
  117. package/dist/workflows/weaver.d.ts.map +1 -0
  118. package/dist/workflows/weaver.js +28 -0
  119. package/dist/workflows/weaver.js.map +1 -0
  120. package/flowweaver.manifest.json +253 -66
  121. package/package.json +1 -1
  122. package/src/ai-chat-provider.ts +184 -18
  123. package/src/bot/ai-router.ts +132 -0
  124. package/src/bot/bot-registry.ts +2 -2
  125. package/src/bot/conversation-store.ts +2 -1
  126. package/src/bot/improve-loop.ts +6 -6
  127. package/src/bot/instance-manager.ts +128 -0
  128. package/src/bot/orchestrator.ts +244 -0
  129. package/src/bot/profile-store.ts +225 -0
  130. package/src/bot/profile-types.ts +141 -0
  131. package/src/bot/swarm-controller.ts +385 -186
  132. package/src/bot/task-prompt-builder.ts +37 -6
  133. package/src/bot/task-store.ts +28 -89
  134. package/src/bot/task-types.ts +10 -4
  135. package/src/cli-handlers.ts +2 -3
  136. package/src/docs/weaver-bot-usage.md +35 -18
  137. package/src/docs/weaver-config.md +20 -0
  138. package/src/docs/weaver-task-queue.md +31 -19
  139. package/src/mcp-tools.ts +129 -320
  140. package/src/node-types/orchestrator-dispatch.ts +71 -0
  141. package/src/node-types/orchestrator-load-state.ts +66 -0
  142. package/src/node-types/orchestrator-route.ts +33 -0
  143. package/src/node-types/receive-task.ts +3 -26
  144. package/src/ui/bot-constants.ts +192 -0
  145. package/src/ui/bot-panel.tsx +55 -79
  146. package/src/ui/bot-slot-card.tsx +69 -117
  147. package/src/ui/budget-bar.tsx +5 -3
  148. package/src/ui/chat-task-result.tsx +6 -9
  149. package/src/ui/decision-log.tsx +148 -0
  150. package/src/ui/profile-card.tsx +157 -0
  151. package/src/ui/profile-editor.tsx +384 -0
  152. package/src/ui/swarm-controls.tsx +35 -31
  153. package/src/ui/swarm-dashboard.tsx +409 -80
  154. package/src/ui/task-create-form.tsx +29 -119
  155. package/src/ui/task-detail-view.tsx +461 -215
  156. package/src/ui/task-pool-list.tsx +74 -95
  157. package/src/workflows/orchestrator.ts +302 -0
  158. package/dist/docs/weaver-bot-usage.md +0 -34
  159. package/dist/docs/weaver-genesis.md +0 -32
  160. package/dist/docs/weaver-task-queue.md +0 -34
  161. package/src/bot/error-guide.ts +0 -4
  162. package/src/bot/retry-utils.ts +0 -4
@@ -296,13 +296,19 @@ var {
296
296
  Tag,
297
297
  Badge,
298
298
  Icon,
299
+ IconButton,
299
300
  TaskBlock,
300
301
  Button,
302
+ Card,
303
+ Chip,
304
+ Checkbox,
305
+ Table,
306
+ Tabs,
307
+ EmptyState,
301
308
  toast,
302
309
  usePackWorkspace,
303
310
  useEventStream
304
311
  } = require("@fw/plugin-ui-kit");
305
- var { styled } = require("@fw/plugin-theme");
306
312
  var statusToIcon = {
307
313
  "pending": "pending",
308
314
  "in-progress": "running",
@@ -319,76 +325,64 @@ var statusToLabel = {
319
325
  "blocked": "Blocked",
320
326
  "cancelled": "Cancelled"
321
327
  };
322
- var priorityLabel = (p) => p >= 3 ? "High" : p === 2 ? "Medium" : p === 1 ? "Low" : "None";
323
- var Container = styled.div({
324
- display: "flex",
325
- flexDirection: "column",
326
- width: "100%",
327
- height: "100%",
328
- overflow: "hidden"
329
- });
330
- var Header = styled.div({
328
+ var headerStyle = {
331
329
  padding: "12px 16px",
332
- borderBottom: "1px solid $color-border-default",
333
- display: "flex",
334
- flexDirection: "column",
335
- gap: "8px",
330
+ borderBottom: "1px solid var(--color-border-default)",
336
331
  flexShrink: 0
337
- });
338
- var HeaderTopRow = styled.div({
339
- display: "flex",
340
- alignItems: "center",
341
- gap: "8px"
342
- });
343
- var HeaderMeta = styled.div({
344
- display: "flex",
345
- alignItems: "center",
346
- gap: "8px",
347
- flexWrap: "wrap"
348
- });
349
- var Section = styled.div({
350
- padding: "12px 16px",
351
- borderBottom: "1px solid $color-border-default"
352
- });
353
- var SectionTitle = styled.div({
354
- marginBottom: "8px"
355
- });
356
- var FileList = styled.div({
357
- display: "flex",
358
- flexDirection: "column",
359
- gap: "2px"
360
- });
361
- var FileItem = styled.div({
332
+ };
333
+ var fileItemStyle = {
362
334
  fontFamily: "monospace",
363
335
  fontSize: "12px",
364
- color: "$color-text-mid",
336
+ color: "var(--color-text-mid)",
365
337
  padding: "2px 4px",
366
- borderRadius: "4px",
367
- "&:hover": { backgroundColor: "$color-surface-elevated" }
368
- });
369
- var NotesBlock = styled.div({
370
- whiteSpace: "pre-wrap",
371
- fontSize: "13px",
372
- color: "$color-text-mid",
373
- lineHeight: 1.5,
374
- padding: "4px 0"
375
- });
376
- var SubtaskRow = styled.div({
377
- display: "flex",
378
- alignItems: "center",
379
- gap: "8px",
338
+ borderRadius: "4px"
339
+ };
340
+ var fileItemHoverStyle = {
341
+ ...fileItemStyle,
342
+ backgroundColor: "var(--color-surface-elevated)"
343
+ };
344
+ var subtaskRowStyle = {
380
345
  padding: "6px 8px",
381
346
  cursor: "pointer",
382
- borderRadius: "6px",
383
- "&:hover": { backgroundColor: "$color-surface-elevated" }
384
- });
385
- var SubtaskTitle = styled.div({
386
- flex: 1,
387
- overflow: "hidden",
388
- textOverflow: "ellipsis",
389
- whiteSpace: "nowrap",
390
- minWidth: 0
391
- });
347
+ borderRadius: "6px"
348
+ };
349
+ var subtaskRowHoverStyle = {
350
+ ...subtaskRowStyle,
351
+ backgroundColor: "var(--color-surface-elevated)"
352
+ };
353
+ function SubtaskRowItem({ sub, onBack }) {
354
+ const [hovered, setHovered] = useState2(false);
355
+ return React2.createElement(
356
+ Flex,
357
+ {
358
+ variant: "row-center-start-nowrap-8",
359
+ style: hovered ? subtaskRowHoverStyle : subtaskRowStyle,
360
+ onClick: () => onBack(),
361
+ onMouseEnter: () => setHovered(true),
362
+ onMouseLeave: () => setHovered(false)
363
+ },
364
+ React2.createElement(StatusIcon, {
365
+ status: statusToIcon[sub.status] || "pending",
366
+ size: "sm"
367
+ }),
368
+ React2.createElement(
369
+ Flex,
370
+ {
371
+ variant: "row-center-start-nowrap-0",
372
+ style: { flex: 1, minWidth: 0 }
373
+ },
374
+ React2.createElement(Typography, { variant: "caption-regular", truncate: true }, sub.title)
375
+ ),
376
+ sub.assignedProfile && React2.createElement(Tag, {
377
+ size: "small",
378
+ color: "info"
379
+ }, sub.assignedProfile),
380
+ React2.createElement(Typography, {
381
+ variant: "caption-regular",
382
+ color: "color-text-subtle"
383
+ }, `#${sub.attempt}`)
384
+ );
385
+ }
392
386
  function TaskDetailView({ taskId, onBack }) {
393
387
  const ctx = usePackWorkspace();
394
388
  const { callTool } = ctx;
@@ -399,12 +393,16 @@ function TaskDetailView({ taskId, onBack }) {
399
393
  const [loading, setLoading] = useState2(true);
400
394
  const fetchTask = useCallback(async () => {
401
395
  try {
402
- const data = await callTool("fw_weaver_task_get", { id: taskId });
396
+ const raw = await callTool("fw_weaver_task_get", { id: taskId });
397
+ const data = typeof raw === "string" ? JSON.parse(raw) : raw;
403
398
  if (!data) return;
404
- const t = data;
399
+ const t = data.task ?? data;
405
400
  setTask(t);
406
- if (t.isParent) {
407
- const listData = await callTool("fw_weaver_task_list", { parentId: taskId });
401
+ if (data.subtasks && Array.isArray(data.subtasks)) {
402
+ setSubtasks(data.subtasks);
403
+ } else if (t.isParent) {
404
+ const listRaw = await callTool("fw_weaver_task_list", { parentId: taskId });
405
+ const listData = typeof listRaw === "string" ? JSON.parse(listRaw) : listRaw;
408
406
  if (Array.isArray(listData)) {
409
407
  setSubtasks(listData);
410
408
  }
@@ -414,7 +412,8 @@ function TaskDetailView({ taskId, onBack }) {
414
412
  }, [callTool, taskId]);
415
413
  const fetchHistory = useCallback(async () => {
416
414
  try {
417
- const data = await callTool("fw_weaver_history", { taskId });
415
+ const raw = await callTool("fw_weaver_history", { taskId });
416
+ const data = typeof raw === "string" ? JSON.parse(raw) : raw;
418
417
  if (Array.isArray(data)) {
419
418
  setHistory(
420
419
  data.map((r) => {
@@ -455,6 +454,64 @@ function TaskDetailView({ taskId, onBack }) {
455
454
  stream.start(packId, "fw_weaver_events", currentRunId);
456
455
  return () => stream.stop();
457
456
  }, [isLive, currentRunId, packId]);
457
+ const [detailTab, setDetailTab] = useState2("runs");
458
+ const [actionLoading, setActionLoading] = useState2(null);
459
+ const [availableProfiles, setAvailableProfiles] = useState2([]);
460
+ useEffect2(() => {
461
+ callTool("fw_weaver_profile_list", {}).then((raw) => {
462
+ const data = typeof raw === "string" ? JSON.parse(raw) : raw;
463
+ if (Array.isArray(data)) setAvailableProfiles(data);
464
+ }).catch(() => {
465
+ });
466
+ }, [callTool]);
467
+ const handleRetry = useCallback(async () => {
468
+ setActionLoading("retry");
469
+ try {
470
+ await callTool("fw_weaver_task_retry", { id: taskId });
471
+ toast("Task retried, back in pool", { type: "success" });
472
+ fetchTask();
473
+ } catch (err) {
474
+ toast(err instanceof Error ? err.message : "Failed to retry", { type: "error" });
475
+ }
476
+ setActionLoading(null);
477
+ }, [callTool, taskId, fetchTask]);
478
+ const handleCancel = useCallback(async () => {
479
+ const ok = await ctx.confirm("Cancel this task? It cannot be undone.", {
480
+ title: "Cancel Task",
481
+ confirmLabel: "Cancel Task",
482
+ state: "warning"
483
+ });
484
+ if (!ok) return;
485
+ setActionLoading("cancel");
486
+ try {
487
+ await callTool("fw_weaver_task_cancel", { id: taskId });
488
+ toast("Task cancelled", { type: "info" });
489
+ fetchTask();
490
+ } catch (err) {
491
+ toast(err instanceof Error ? err.message : "Failed to cancel", { type: "error" });
492
+ }
493
+ setActionLoading(null);
494
+ }, [callTool, taskId, fetchTask, ctx]);
495
+ const handleAssignProfile = useCallback(async (profileId) => {
496
+ setActionLoading("assign-profile");
497
+ try {
498
+ const newProfile = task?.assignedProfile === profileId ? void 0 : profileId;
499
+ await callTool("fw_weaver_task_update", { id: taskId, assignedProfile: newProfile ?? null });
500
+ toast(newProfile ? `Assigned profile ${profileId}` : `Unassigned profile`, { type: "success" });
501
+ fetchTask();
502
+ } catch (err) {
503
+ toast(err instanceof Error ? err.message : "Failed to assign profile", { type: "error" });
504
+ }
505
+ setActionLoading(null);
506
+ }, [callTool, taskId, task, fetchTask]);
507
+ const handlePriorityChange = useCallback(async (delta) => {
508
+ const newPriority = Math.max(0, (task?.priority ?? 0) + delta);
509
+ try {
510
+ await callTool("fw_weaver_task_update", { id: taskId, priority: newPriority });
511
+ fetchTask();
512
+ } catch {
513
+ }
514
+ }, [callTool, taskId, task, fetchTask]);
458
515
  const [expandedRunId, setExpandedRunId] = useState2(null);
459
516
  const [liveExpanded, setLiveExpanded] = useState2(true);
460
517
  const toggleExpand = useCallback((id) => {
@@ -521,11 +578,17 @@ function TaskDetailView({ taskId, onBack }) {
521
578
  }
522
579
  if (loading && !task) {
523
580
  return React2.createElement(
524
- Container,
525
- null,
581
+ Flex,
582
+ {
583
+ variant: "column-stretch-start-nowrap-0",
584
+ style: { width: "100%", height: "100%", overflow: "hidden" }
585
+ },
526
586
  React2.createElement(
527
- Header,
528
- null,
587
+ Flex,
588
+ {
589
+ variant: "column-stretch-start-nowrap-8",
590
+ style: headerStyle
591
+ },
529
592
  React2.createElement(
530
593
  Button,
531
594
  { variant: "ghost", size: "sm", onClick: onBack },
@@ -537,7 +600,7 @@ function TaskDetailView({ taskId, onBack }) {
537
600
  Flex,
538
601
  {
539
602
  variant: "column-center-center-nowrap-0",
540
- style: { flex: 1, padding: "24px" }
603
+ style: { flex: 1 }
541
604
  },
542
605
  React2.createElement(
543
606
  Typography,
@@ -549,11 +612,17 @@ function TaskDetailView({ taskId, onBack }) {
549
612
  }
550
613
  if (!task) {
551
614
  return React2.createElement(
552
- Container,
553
- null,
615
+ Flex,
616
+ {
617
+ variant: "column-stretch-start-nowrap-0",
618
+ style: { width: "100%", height: "100%", overflow: "hidden" }
619
+ },
554
620
  React2.createElement(
555
- Header,
556
- null,
621
+ Flex,
622
+ {
623
+ variant: "column-stretch-start-nowrap-8",
624
+ style: headerStyle
625
+ },
557
626
  React2.createElement(
558
627
  Button,
559
628
  { variant: "ghost", size: "sm", onClick: onBack },
@@ -565,7 +634,7 @@ function TaskDetailView({ taskId, onBack }) {
565
634
  Flex,
566
635
  {
567
636
  variant: "column-center-center-nowrap-0",
568
- style: { flex: 1, padding: "24px" }
637
+ style: { flex: 1 }
569
638
  },
570
639
  React2.createElement(
571
640
  Typography,
@@ -579,210 +648,392 @@ function TaskDetailView({ taskId, onBack }) {
579
648
  const hasSubtasks = task.isParent && subtasks.length > 0;
580
649
  const hasRuns = runItems.length > 0 || isLive;
581
650
  return React2.createElement(
582
- Container,
583
- null,
651
+ Flex,
652
+ {
653
+ variant: "column-stretch-start-nowrap-0",
654
+ style: { width: "100%", height: "100%", overflow: "hidden" }
655
+ },
584
656
  // ── Header ──
585
657
  React2.createElement(
586
- Header,
587
- null,
588
- // Back button
658
+ Flex,
659
+ {
660
+ variant: "column-stretch-start-nowrap-6",
661
+ style: { ...headerStyle, padding: "12px 16px", borderBottom: "1px solid var(--color-border-default)" }
662
+ },
663
+ // Top row: back + title + status
589
664
  React2.createElement(
590
- Button,
591
- { variant: "ghost", size: "sm", onClick: onBack },
592
- React2.createElement(Icon, { name: "arrowBack", size: 16 }),
593
- " Back"
594
- ),
595
- // Title row
596
- React2.createElement(
597
- HeaderTopRow,
598
- null,
665
+ Flex,
666
+ { variant: "row-center-start-nowrap-8" },
667
+ React2.createElement(IconButton, {
668
+ icon: "back",
669
+ size: "xs",
670
+ variant: "clear",
671
+ onClick: onBack
672
+ }),
599
673
  React2.createElement(StatusIcon, {
600
674
  status: statusToIcon[task.status] || "pending",
601
- size: "md"
675
+ size: "sm"
602
676
  }),
603
- React2.createElement(Typography, { variant: "body-semibold" }, task.title)
677
+ React2.createElement(Typography, {
678
+ variant: "caption-thick",
679
+ color: "color-text-high",
680
+ style: { flex: 1, minWidth: 0, wordBreak: "break-word" }
681
+ }, task.title || "Untitled Task")
604
682
  ),
605
- // Meta row: status label, assigned bots, priority, attempts
683
+ // Meta row: status tag, assigned profile, priority, attempts
606
684
  React2.createElement(
607
- HeaderMeta,
608
- null,
685
+ Flex,
686
+ { variant: "row-center-start-wrap-6" },
609
687
  React2.createElement(Tag, {
610
688
  size: "small",
611
- color: task.status === "done" ? "positive" : task.status === "failed" ? "negative" : task.status === "in-progress" ? "info" : task.status === "blocked" ? "caution" : "default"
612
- }, statusToLabel[task.status]),
613
- ...task.assignedBots.map(
614
- (botId) => React2.createElement(Tag, { key: `bot-${botId}`, size: "small", color: "info" }, botId)
615
- ),
616
- // Priority
617
- task.priority > 0 && React2.createElement(Badge, {
618
- variant: task.priority >= 3 ? "warning" : "info"
619
- }, `P${task.priority} ${priorityLabel(task.priority)}`),
620
- // Attempt count
621
- React2.createElement(Typography, {
622
- variant: "caption-regular",
689
+ color: task.status === "done" ? "positive" : task.status === "failed" ? "negative" : task.status === "in-progress" ? "info" : task.status === "blocked" ? "caution" : "secondary"
690
+ }, statusToLabel[task.status] || task.status || "pending"),
691
+ task.assignedProfile && React2.createElement(Tag, { key: `profile-${task.assignedProfile}`, size: "small", color: "info" }, task.assignedProfile),
692
+ task.priority > 0 && React2.createElement(Tag, {
693
+ size: "small",
694
+ color: task.priority >= 3 ? "caution" : "info"
695
+ }, `P${task.priority}`),
696
+ task.attempt != null && task.maxAttempts != null && React2.createElement(Typography, {
697
+ variant: "smallCaption-regular",
623
698
  color: "color-text-subtle"
624
699
  }, `Attempt ${task.attempt}/${task.maxAttempts}`)
625
700
  ),
626
701
  // Description
627
702
  task.description && React2.createElement(Typography, {
628
- variant: "caption-regular",
629
- color: "color-text-mid",
630
- style: { marginTop: "4px" }
631
- }, task.description)
703
+ variant: "smallCaption-regular",
704
+ color: "color-text-medium"
705
+ }, task.description),
706
+ // Profile routing info
707
+ task.assignedProfile && React2.createElement(
708
+ Flex,
709
+ { variant: "column-stretch-start-nowrap-2" },
710
+ React2.createElement(Typography, {
711
+ variant: "smallCaption-regular",
712
+ color: "color-text-medium"
713
+ }, `Profile: ${task.assignedProfile}`),
714
+ task.routingReason && React2.createElement(Typography, {
715
+ variant: "smallCaption-regular",
716
+ color: "color-text-subtle"
717
+ }, task.routingReason)
718
+ )
719
+ // (Actions moved to tab)
632
720
  ),
633
- // ── Scrollable content ──
721
+ // ── Tabs ──
722
+ React2.createElement(Tabs, {
723
+ tabs: [
724
+ { id: "runs", title: `Runs (${runItems.length}${isLive ? "+1" : ""})` },
725
+ ...hasSubtasks ? [{ id: "subtasks", title: `Subtasks (${subtasks.filter((s) => s.status === "done").length}/${subtasks.length})` }] : [],
726
+ ...task.status !== "done" && task.status !== "cancelled" ? [{ id: "actions", title: "Actions" }] : [],
727
+ ...hasContext ? [{ id: "context", title: "Context" }] : []
728
+ ],
729
+ activeTabId: detailTab,
730
+ onSelectTab: (id) => setDetailTab(id),
731
+ size: "sm"
732
+ }),
733
+ // ── Tab content ──
634
734
  React2.createElement(
635
735
  ScrollArea,
636
736
  { ref: scrollRef, style: { flex: 1 } },
637
737
  React2.createElement(
638
738
  Flex,
639
- { variant: "column-stretch-start-nowrap-0" },
640
- // ── Context section ──
641
- hasContext && React2.createElement(
642
- Section,
643
- null,
739
+ { variant: "column-stretch-start-nowrap-8", style: { padding: "12px 16px" } },
740
+ // ── Runs tab ──
741
+ detailTab === "runs" && (hasRuns || (task.runs?.length ?? 0) > 0) ? React2.createElement(
742
+ Flex,
743
+ { variant: "column-stretch-start-nowrap-8" },
744
+ ...runItems.map(({ run, runTimeline }) => {
745
+ const runId = run.id;
746
+ const isExpanded = expandedRunId === runId;
747
+ const isSuccess = run.outcome === "completed" || run.success === true;
748
+ return React2.createElement(TaskBlock, {
749
+ key: `run-${runId}`,
750
+ state: isSuccess ? "completed" : "failed",
751
+ instruction: extractInstruction(run),
752
+ timeline: runTimeline,
753
+ cost: typeof run.cost === "number" ? run.cost : run.costDetail?.totalCost ?? null,
754
+ plan: run.plan,
755
+ startedAt: run.startedAt,
756
+ durationMs: run.durationMs ?? run.duration,
757
+ expanded: isExpanded,
758
+ onToggleExpand: () => toggleExpand(runId)
759
+ });
760
+ }),
761
+ // Live run
762
+ isLive && React2.createElement(TaskBlock, {
763
+ key: "live-run",
764
+ state: "running",
765
+ instruction: liveInstruction ?? task.title,
766
+ timeline: liveTimeline,
767
+ phase: livePhase,
768
+ elapsed,
769
+ cost: liveCost,
770
+ plan,
771
+ error: stream.error,
772
+ approval: approvalStatus ?? void 0,
773
+ approvalLoading,
774
+ onApprove: handleApprove,
775
+ onReject: handleReject,
776
+ expanded: liveExpanded,
777
+ onToggleExpand: () => setLiveExpanded((v) => !v)
778
+ })
779
+ ) : detailTab === "runs" && React2.createElement(EmptyState, {
780
+ icon: "smartToy",
781
+ message: "No runs yet",
782
+ description: "This task has not been executed yet."
783
+ }),
784
+ // ── Subtasks tab ──
785
+ detailTab === "subtasks" && hasSubtasks && React2.createElement(
786
+ Flex,
787
+ {
788
+ variant: "column-stretch-start-nowrap-0"
789
+ },
790
+ ...(subtasks ?? []).map(
791
+ (sub) => React2.createElement(SubtaskRowItem, {
792
+ key: sub.id,
793
+ sub,
794
+ onBack
795
+ })
796
+ )
797
+ ),
798
+ // ── Actions tab ──
799
+ detailTab === "actions" && React2.createElement(
800
+ Flex,
801
+ {
802
+ variant: "column-stretch-start-nowrap-16"
803
+ },
804
+ // Status actions
644
805
  React2.createElement(
645
- SectionTitle,
646
- null,
647
- React2.createElement(Typography, { variant: "caption-semibold", color: "color-text-high" }, "Context")
806
+ Flex,
807
+ { variant: "column-stretch-start-nowrap-8" },
808
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Status"),
809
+ React2.createElement(
810
+ Flex,
811
+ { variant: "row-center-start-nowrap-6" },
812
+ task.status === "failed" && React2.createElement(Button, {
813
+ size: "xs",
814
+ variant: "fill",
815
+ color: "primary",
816
+ onClick: handleRetry,
817
+ loading: actionLoading === "retry",
818
+ disabled: !!actionLoading
819
+ }, "Retry Task"),
820
+ (task.status === "pending" || task.status === "in-progress" || task.status === "blocked") && React2.createElement(Button, {
821
+ size: "xs",
822
+ variant: "outlined",
823
+ color: "danger",
824
+ onClick: handleCancel,
825
+ loading: actionLoading === "cancel",
826
+ disabled: !!actionLoading
827
+ }, "Cancel Task")
828
+ )
648
829
  ),
649
- // Files
650
- task.context.files.length > 0 && React2.createElement(
830
+ // Priority
831
+ React2.createElement(
651
832
  Flex,
652
- {
653
- variant: "column-stretch-start-nowrap-4",
654
- style: { marginBottom: "8px" }
655
- },
656
- React2.createElement(Typography, { variant: "caption-regular", color: "color-text-subtle" }, "Files:"),
833
+ { variant: "column-stretch-start-nowrap-8" },
834
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Priority"),
657
835
  React2.createElement(
658
- FileList,
659
- null,
660
- ...task.context.files.map(
661
- (file) => React2.createElement(FileItem, { key: file }, file)
662
- )
836
+ Flex,
837
+ { variant: "row-center-start-nowrap-8" },
838
+ React2.createElement(IconButton, {
839
+ icon: "expandLess",
840
+ size: "xs",
841
+ variant: "outlined",
842
+ onClick: () => handlePriorityChange(1),
843
+ title: "Increase priority"
844
+ }),
845
+ React2.createElement(
846
+ Typography,
847
+ { variant: "smallCaption-regular", color: "color-text-high" },
848
+ `P${task.priority ?? 0}`
849
+ ),
850
+ React2.createElement(IconButton, {
851
+ icon: "expandMore",
852
+ size: "xs",
853
+ variant: "outlined",
854
+ onClick: () => handlePriorityChange(-1),
855
+ title: "Decrease priority"
856
+ })
663
857
  )
664
858
  ),
665
- // Notes
666
- task.context.notes && React2.createElement(
859
+ // Assign Profile
860
+ availableProfiles.length > 0 && React2.createElement(
667
861
  Flex,
668
- { variant: "column-stretch-start-nowrap-4" },
669
- React2.createElement(Typography, { variant: "caption-regular", color: "color-text-subtle" }, "Notes:"),
670
- React2.createElement(NotesBlock, null, task.context.notes)
862
+ { variant: "column-stretch-start-nowrap-8" },
863
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Assign Profile"),
864
+ React2.createElement(Table, {
865
+ size: "compact",
866
+ getRowKey: (row) => row.id,
867
+ columns: [
868
+ {
869
+ key: "icon",
870
+ header: "",
871
+ width: "30px",
872
+ render: (_, row) => React2.createElement(Icon, {
873
+ name: row.icon || "smartToy",
874
+ size: 14,
875
+ color: row.color || "color-text-medium"
876
+ })
877
+ },
878
+ {
879
+ key: "name",
880
+ header: "Profile"
881
+ },
882
+ {
883
+ key: "capabilities",
884
+ header: "Capabilities",
885
+ render: (_, row) => {
886
+ const caps = row.capabilities || [];
887
+ if (caps.length === 0) return null;
888
+ return React2.createElement(
889
+ Flex,
890
+ { variant: "row-center-start-wrap-4" },
891
+ ...caps.slice(0, 4).map(
892
+ (cap) => React2.createElement(
893
+ "span",
894
+ { key: cap.name, title: cap.description },
895
+ React2.createElement(Chip, { label: cap.name, size: "small", color: "color-brand-main" })
896
+ )
897
+ ),
898
+ caps.length > 4 && React2.createElement(Typography, {
899
+ variant: "smallCaption-regular",
900
+ color: "color-text-subtle"
901
+ }, `+${caps.length - 4}`)
902
+ );
903
+ }
904
+ },
905
+ {
906
+ key: "assigned",
907
+ header: "Assign",
908
+ width: "50px",
909
+ align: "right",
910
+ render: (_, row) => {
911
+ const isAssigned = task.assignedProfile === row.id;
912
+ return React2.createElement(Checkbox, {
913
+ checked: isAssigned,
914
+ onChange: () => handleAssignProfile(row.id),
915
+ size: "sm"
916
+ });
917
+ }
918
+ }
919
+ ],
920
+ data: availableProfiles
921
+ })
671
922
  )
672
923
  ),
673
- // ── Subtasks section ──
674
- hasSubtasks && React2.createElement(
675
- Section,
676
- null,
677
- React2.createElement(
678
- SectionTitle,
679
- null,
680
- React2.createElement(
681
- Typography,
682
- { variant: "caption-semibold", color: "color-text-high" },
683
- `Subtasks (${subtasks.filter((s) => s.status === "done").length}/${subtasks.length} done)`
924
+ // ── Context tab ──
925
+ detailTab === "context" && hasContext && React2.createElement(
926
+ Flex,
927
+ {
928
+ variant: "column-stretch-start-nowrap-12"
929
+ },
930
+ // Files
931
+ (task.context?.files?.length ?? 0) > 0 && React2.createElement(
932
+ Flex,
933
+ {
934
+ variant: "column-stretch-start-nowrap-4"
935
+ },
936
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Files"),
937
+ ...(task.context?.files ?? []).map(
938
+ (file) => React2.createElement(Typography, {
939
+ key: file,
940
+ variant: "smallCaption-regular",
941
+ color: "color-text-high",
942
+ style: { fontFamily: "var(--font-mono, monospace)" }
943
+ }, file)
684
944
  )
685
945
  ),
686
- React2.createElement(
946
+ // Notes
947
+ task.context?.notes && React2.createElement(
948
+ Flex,
949
+ {
950
+ variant: "column-stretch-start-nowrap-4"
951
+ },
952
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Notes"),
953
+ React2.createElement(Typography, {
954
+ variant: "smallCaption-regular",
955
+ color: "color-text-high",
956
+ style: { whiteSpace: "pre-wrap" }
957
+ }, task.context.notes)
958
+ ),
959
+ // Last error
960
+ task.context?.lastError && React2.createElement(
961
+ Flex,
962
+ {
963
+ variant: "column-stretch-start-nowrap-4"
964
+ },
965
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-status-negative" }, "Last Error"),
966
+ React2.createElement(Typography, {
967
+ variant: "smallCaption-regular",
968
+ color: "color-text-high",
969
+ style: { fontFamily: "var(--font-mono, monospace)", whiteSpace: "pre-wrap" }
970
+ }, task.context.lastError)
971
+ ),
972
+ // Run summaries (accumulated context)
973
+ (task.context?.runSummaries?.length ?? 0) > 0 && React2.createElement(
687
974
  Flex,
688
- { variant: "column-stretch-start-nowrap-0" },
689
- ...subtasks.map(
690
- (sub) => React2.createElement(
691
- SubtaskRow,
975
+ {
976
+ variant: "column-stretch-start-nowrap-6"
977
+ },
978
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Run Summaries"),
979
+ ...(task.context?.runSummaries ?? []).map(
980
+ (rs, i) => React2.createElement(
981
+ Card,
692
982
  {
693
- key: sub.id,
694
- onClick: () => {
695
- onBack();
696
- }
983
+ key: `rs-${i}`,
984
+ variant: "bordered",
985
+ padding: "compact",
986
+ style: { gap: "4px" }
697
987
  },
698
- React2.createElement(StatusIcon, {
699
- status: statusToIcon[sub.status] || "pending",
700
- size: "sm"
701
- }),
702
988
  React2.createElement(
703
- SubtaskTitle,
704
- null,
705
- React2.createElement(Typography, { variant: "caption-regular" }, sub.title)
989
+ Flex,
990
+ { variant: "row-center-space-between-nowrap-8" },
991
+ React2.createElement(Typography, {
992
+ variant: "smallCaption-thick",
993
+ color: rs.outcome === "success" ? "color-status-positive" : "color-status-negative"
994
+ }, `${rs.outcome === "success" ? "Success" : "Failed"} (${rs.botId ?? "unknown bot"})`),
995
+ React2.createElement(Typography, {
996
+ variant: "smallCaption-regular",
997
+ color: "color-text-subtle"
998
+ }, `${Math.round((rs.durationMs ?? 0) / 1e3)}s \xB7 ${rs.tokensUsed ?? 0} tok \xB7 $${(rs.cost ?? 0).toFixed(3)}`)
706
999
  ),
707
- sub.assignedBots.length > 0 && React2.createElement(Tag, {
708
- size: "small",
709
- color: "info"
710
- }, sub.assignedBots[0]),
711
1000
  React2.createElement(Typography, {
712
- variant: "caption-regular",
713
- color: "color-text-subtle"
714
- }, `#${sub.attempt}`)
1001
+ variant: "smallCaption-regular",
1002
+ color: "color-text-medium"
1003
+ }, rs.summary ?? ""),
1004
+ (rs.filesModified ?? []).length > 0 && React2.createElement(Typography, {
1005
+ variant: "smallCaption-regular",
1006
+ color: "color-text-subtle",
1007
+ style: { fontFamily: "var(--font-mono, monospace)" }
1008
+ }, `Files: ${rs.filesModified.join(", ")}`),
1009
+ rs.error && React2.createElement(Typography, {
1010
+ variant: "smallCaption-regular",
1011
+ color: "color-status-negative"
1012
+ }, `Error: ${rs.error}`)
715
1013
  )
716
1014
  )
717
- )
718
- ),
719
- // ── Run history section ──
720
- (hasRuns || task.runs.length > 0) && React2.createElement(
721
- Section,
722
- { style: { borderBottom: "none" } },
723
- React2.createElement(
724
- SectionTitle,
725
- null,
726
- React2.createElement(
727
- Typography,
728
- { variant: "caption-semibold", color: "color-text-high" },
729
- `Run History (${runItems.length}${isLive ? " + 1 live" : ""})`
730
- )
731
1015
  ),
732
- React2.createElement(
733
- Flex,
734
- { variant: "column-stretch-start-nowrap-8" },
735
- ...runItems.map(({ run, runTimeline }) => {
736
- const runId = run.id;
737
- const isExpanded = expandedRunId === runId;
738
- const isSuccess = run.outcome === "completed" || run.success === true;
739
- return React2.createElement(TaskBlock, {
740
- key: `run-${runId}`,
741
- state: isSuccess ? "completed" : "failed",
742
- instruction: extractInstruction(run),
743
- timeline: runTimeline,
744
- cost: typeof run.cost === "number" ? run.cost : run.costDetail?.totalCost ?? null,
745
- plan: run.plan,
746
- startedAt: run.startedAt,
747
- durationMs: run.durationMs ?? run.duration,
748
- expanded: isExpanded,
749
- onToggleExpand: () => toggleExpand(runId)
750
- });
751
- }),
752
- // Live run
753
- isLive && React2.createElement(TaskBlock, {
754
- key: "live-run",
755
- state: "running",
756
- instruction: liveInstruction ?? task.title,
757
- timeline: liveTimeline,
758
- phase: livePhase,
759
- elapsed,
760
- cost: liveCost,
761
- plan,
762
- error: stream.error,
763
- approval: approvalStatus ?? void 0,
764
- approvalLoading,
765
- onApprove: handleApprove,
766
- onReject: handleReject,
767
- expanded: liveExpanded,
768
- onToggleExpand: () => setLiveExpanded((v) => !v)
769
- })
770
- )
771
- ),
772
- // Empty state when no runs and no live
773
- !hasRuns && task.runs.length === 0 && React2.createElement(
774
- Section,
775
- { style: { borderBottom: "none" } },
776
- React2.createElement(
1016
+ // Budget
1017
+ (task.tokensUsed > 0 || task.costUsed > 0) && React2.createElement(
777
1018
  Flex,
778
1019
  {
779
- variant: "column-center-center-nowrap-0",
780
- style: { padding: "16px" }
1020
+ variant: "column-stretch-start-nowrap-4"
781
1021
  },
782
- React2.createElement(Typography, {
783
- variant: "caption-regular",
784
- color: "color-text-subtle"
785
- }, "No runs yet for this task.")
1022
+ React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Budget"),
1023
+ React2.createElement(
1024
+ Flex,
1025
+ { variant: "row-center-start-nowrap-16" },
1026
+ React2.createElement(
1027
+ Typography,
1028
+ { variant: "smallCaption-regular", color: "color-text-high" },
1029
+ `Tokens: ${task.tokensUsed?.toLocaleString() ?? 0}${task.budgetTokens ? ` / ${task.budgetTokens.toLocaleString()}` : ""}`
1030
+ ),
1031
+ React2.createElement(
1032
+ Typography,
1033
+ { variant: "smallCaption-regular", color: "color-text-high" },
1034
+ `Cost: $${(task.costUsed ?? 0).toFixed(3)}${task.budgetCost ? ` / $${task.budgetCost.toFixed(2)}` : ""}`
1035
+ )
1036
+ )
786
1037
  )
787
1038
  )
788
1039
  )