@synergenius/flow-weaver-pack-weaver 0.9.80 → 0.9.82
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/ai-chat-provider.d.ts.map +1 -1
- package/dist/ai-chat-provider.js +40 -1
- package/dist/ai-chat-provider.js.map +1 -1
- package/dist/cli-bridge.d.ts.map +1 -1
- package/dist/cli-bridge.js +5 -3
- package/dist/cli-bridge.js.map +1 -1
- package/dist/cli-handlers.d.ts +16 -7
- package/dist/cli-handlers.d.ts.map +1 -1
- package/dist/cli-handlers.js +293 -416
- package/dist/cli-handlers.js.map +1 -1
- package/dist/ui/swarm-dashboard.js +906 -323
- package/dist/ui/task-detail-view.js +27 -16
- package/dist/ui/task-editor.js +613 -0
- package/flowweaver.manifest.json +16 -5
- package/package.json +1 -1
- package/src/ai-chat-provider.ts +39 -1
- package/src/cli-bridge.ts +6 -3
- package/src/cli-handlers.ts +280 -433
- package/src/ui/swarm-dashboard.tsx +41 -12
- package/src/ui/task-detail-view.tsx +23 -15
- package/src/ui/task-editor.tsx +591 -0
- package/src/ui/task-create-form.tsx +0 -87
|
@@ -530,75 +530,11 @@ function TaskPoolList({ tasks, onTaskClick }) {
|
|
|
530
530
|
var task_pool_list_default = TaskPoolList;
|
|
531
531
|
module.exports = TaskPoolList;
|
|
532
532
|
|
|
533
|
-
// src/ui/task-create-form.tsx
|
|
534
|
-
var import_react2 = __toESM(require("react"), 1);
|
|
535
|
-
var import_plugin_ui_kit2 = require("@fw/plugin-ui-kit");
|
|
536
|
-
var { useState: useState3, useCallback: useCallback2 } = import_react2.default;
|
|
537
|
-
function parseToolResult(raw) {
|
|
538
|
-
if (typeof raw === "string") {
|
|
539
|
-
try {
|
|
540
|
-
return JSON.parse(raw);
|
|
541
|
-
} catch {
|
|
542
|
-
return raw;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
return raw;
|
|
546
|
-
}
|
|
547
|
-
function TaskCreateForm({ onTaskCreated }) {
|
|
548
|
-
const ctx = (0, import_plugin_ui_kit2.usePackWorkspace)();
|
|
549
|
-
const { callTool } = ctx;
|
|
550
|
-
const [title, setTitle] = useState3("");
|
|
551
|
-
const [creating, setCreating] = useState3(false);
|
|
552
|
-
const handleCreate = useCallback2(async () => {
|
|
553
|
-
const trimmed = title.trim();
|
|
554
|
-
if (!trimmed) return;
|
|
555
|
-
setCreating(true);
|
|
556
|
-
try {
|
|
557
|
-
const raw = await callTool("fw_weaver_task_create", { title: trimmed });
|
|
558
|
-
const result = parseToolResult(raw);
|
|
559
|
-
(0, import_plugin_ui_kit2.toast)(`Task created: ${result?.task?.title ?? trimmed}`, { type: "success" });
|
|
560
|
-
setTitle("");
|
|
561
|
-
onTaskCreated?.();
|
|
562
|
-
} catch (err) {
|
|
563
|
-
(0, import_plugin_ui_kit2.toast)(err instanceof Error ? err.message : "Failed to create task", { type: "error" });
|
|
564
|
-
} finally {
|
|
565
|
-
setCreating(false);
|
|
566
|
-
}
|
|
567
|
-
}, [title, callTool, onTaskCreated]);
|
|
568
|
-
return import_react2.default.createElement(
|
|
569
|
-
import_plugin_ui_kit2.Flex,
|
|
570
|
-
{
|
|
571
|
-
variant: "row-center-start-nowrap-6"
|
|
572
|
-
},
|
|
573
|
-
import_react2.default.createElement(import_plugin_ui_kit2.Input, {
|
|
574
|
-
type: "text",
|
|
575
|
-
size: "small",
|
|
576
|
-
placeholder: "What needs to be done?",
|
|
577
|
-
value: title,
|
|
578
|
-
onChange: (v) => setTitle(v),
|
|
579
|
-
onEnter: handleCreate,
|
|
580
|
-
disabled: creating,
|
|
581
|
-
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
582
|
-
inputBoxStyle: { maxWidth: "none" }
|
|
583
|
-
}),
|
|
584
|
-
import_react2.default.createElement(import_plugin_ui_kit2.IconButton, {
|
|
585
|
-
icon: "add",
|
|
586
|
-
size: "sm",
|
|
587
|
-
variant: "fill",
|
|
588
|
-
color: "primary",
|
|
589
|
-
onClick: handleCreate,
|
|
590
|
-
disabled: creating || !title.trim(),
|
|
591
|
-
loading: creating
|
|
592
|
-
})
|
|
593
|
-
);
|
|
594
|
-
}
|
|
595
|
-
var task_create_form_default = TaskCreateForm;
|
|
596
|
-
|
|
597
533
|
// src/ui/use-stream-timeline.ts
|
|
598
|
-
var
|
|
599
|
-
var { useMemo, useState:
|
|
534
|
+
var React5 = require("react");
|
|
535
|
+
var { useMemo, useState: useState3, useEffect, useRef } = React5;
|
|
600
536
|
function useStreamTimeline(events, isDone) {
|
|
601
|
-
const [elapsed, setElapsed] =
|
|
537
|
+
const [elapsed, setElapsed] = useState3(0);
|
|
602
538
|
const startTimeRef = useRef(null);
|
|
603
539
|
useEffect(() => {
|
|
604
540
|
if (events.length === 0) {
|
|
@@ -855,17 +791,17 @@ function traceToTimeline(run) {
|
|
|
855
791
|
}
|
|
856
792
|
|
|
857
793
|
// src/ui/task-detail-view.tsx
|
|
858
|
-
var
|
|
859
|
-
var { useState:
|
|
794
|
+
var React6 = require("react");
|
|
795
|
+
var { useState: useState4, useEffect: useEffect2, useCallback: useCallback2, useRef: useRef2, useMemo: useMemo2 } = React6;
|
|
860
796
|
var {
|
|
861
|
-
Flex:
|
|
797
|
+
Flex: Flex5,
|
|
862
798
|
Typography: Typography5,
|
|
863
799
|
ScrollArea: ScrollArea2,
|
|
864
800
|
StatusIcon: StatusIcon3,
|
|
865
801
|
Tag: Tag2,
|
|
866
802
|
Badge: Badge2,
|
|
867
803
|
Icon: Icon3,
|
|
868
|
-
IconButton:
|
|
804
|
+
IconButton: IconButton3,
|
|
869
805
|
TaskBlock,
|
|
870
806
|
Button: Button2,
|
|
871
807
|
Card,
|
|
@@ -874,8 +810,8 @@ var {
|
|
|
874
810
|
Table,
|
|
875
811
|
Tabs,
|
|
876
812
|
EmptyState: EmptyState2,
|
|
877
|
-
toast:
|
|
878
|
-
usePackWorkspace:
|
|
813
|
+
toast: toast2,
|
|
814
|
+
usePackWorkspace: usePackWorkspace2,
|
|
879
815
|
useEventStream
|
|
880
816
|
} = require("@fw/plugin-ui-kit");
|
|
881
817
|
var statusToIcon2 = {
|
|
@@ -920,9 +856,9 @@ var subtaskRowHoverStyle = {
|
|
|
920
856
|
backgroundColor: "var(--color-surface-elevated)"
|
|
921
857
|
};
|
|
922
858
|
function SubtaskRowItem({ sub, onBack }) {
|
|
923
|
-
const [hovered, setHovered] =
|
|
924
|
-
return
|
|
925
|
-
|
|
859
|
+
const [hovered, setHovered] = useState4(false);
|
|
860
|
+
return React6.createElement(
|
|
861
|
+
Flex5,
|
|
926
862
|
{
|
|
927
863
|
variant: "row-center-start-nowrap-8",
|
|
928
864
|
style: hovered ? subtaskRowHoverStyle : subtaskRowStyle,
|
|
@@ -930,37 +866,37 @@ function SubtaskRowItem({ sub, onBack }) {
|
|
|
930
866
|
onMouseEnter: () => setHovered(true),
|
|
931
867
|
onMouseLeave: () => setHovered(false)
|
|
932
868
|
},
|
|
933
|
-
|
|
869
|
+
React6.createElement(StatusIcon3, {
|
|
934
870
|
status: statusToIcon2[sub.status] || "pending",
|
|
935
871
|
size: "sm"
|
|
936
872
|
}),
|
|
937
|
-
|
|
938
|
-
|
|
873
|
+
React6.createElement(
|
|
874
|
+
Flex5,
|
|
939
875
|
{
|
|
940
876
|
variant: "row-center-start-nowrap-0",
|
|
941
877
|
style: { flex: 1, minWidth: 0 }
|
|
942
878
|
},
|
|
943
|
-
|
|
879
|
+
React6.createElement(Typography5, { variant: "caption-regular", truncate: true }, sub.title)
|
|
944
880
|
),
|
|
945
|
-
sub.assignedProfile &&
|
|
881
|
+
sub.assignedProfile && React6.createElement(Tag2, {
|
|
946
882
|
size: "small",
|
|
947
883
|
color: "info"
|
|
948
884
|
}, sub.assignedProfile),
|
|
949
|
-
|
|
885
|
+
React6.createElement(Typography5, {
|
|
950
886
|
variant: "caption-regular",
|
|
951
887
|
color: "color-text-subtle"
|
|
952
888
|
}, `#${sub.attempt}`)
|
|
953
889
|
);
|
|
954
890
|
}
|
|
955
|
-
function TaskDetailView({ taskId, onBack }) {
|
|
956
|
-
const ctx =
|
|
891
|
+
function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
892
|
+
const ctx = usePackWorkspace2();
|
|
957
893
|
const { callTool } = ctx;
|
|
958
894
|
const packId = ctx.packId;
|
|
959
|
-
const [task, setTask] =
|
|
960
|
-
const [subtasks, setSubtasks] =
|
|
961
|
-
const [history, setHistory] =
|
|
962
|
-
const [loading, setLoading] =
|
|
963
|
-
const fetchTask =
|
|
895
|
+
const [task, setTask] = useState4(null);
|
|
896
|
+
const [subtasks, setSubtasks] = useState4([]);
|
|
897
|
+
const [history, setHistory] = useState4([]);
|
|
898
|
+
const [loading, setLoading] = useState4(true);
|
|
899
|
+
const fetchTask = useCallback2(async () => {
|
|
964
900
|
try {
|
|
965
901
|
const raw = await callTool("fw_weaver_task_get", { id: taskId });
|
|
966
902
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
@@ -979,7 +915,7 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
979
915
|
} catch (err) {
|
|
980
916
|
}
|
|
981
917
|
}, [callTool, taskId]);
|
|
982
|
-
const fetchHistory =
|
|
918
|
+
const fetchHistory = useCallback2(async () => {
|
|
983
919
|
try {
|
|
984
920
|
const raw = await callTool("fw_weaver_history", { taskId });
|
|
985
921
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
@@ -1023,9 +959,9 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1023
959
|
stream.start(packId, "fw_weaver_events", currentRunId);
|
|
1024
960
|
return () => stream.stop();
|
|
1025
961
|
}, [isLive, currentRunId, packId]);
|
|
1026
|
-
const [detailTab, setDetailTab] =
|
|
1027
|
-
const [actionLoading, setActionLoading] =
|
|
1028
|
-
const [availableProfiles, setAvailableProfiles] =
|
|
962
|
+
const [detailTab, setDetailTab] = useState4("runs");
|
|
963
|
+
const [actionLoading, setActionLoading] = useState4(null);
|
|
964
|
+
const [availableProfiles, setAvailableProfiles] = useState4([]);
|
|
1029
965
|
useEffect2(() => {
|
|
1030
966
|
callTool("fw_weaver_profile_list", {}).then((raw) => {
|
|
1031
967
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
@@ -1033,18 +969,18 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1033
969
|
}).catch(() => {
|
|
1034
970
|
});
|
|
1035
971
|
}, [callTool]);
|
|
1036
|
-
const handleRetry =
|
|
972
|
+
const handleRetry = useCallback2(async () => {
|
|
1037
973
|
setActionLoading("retry");
|
|
1038
974
|
try {
|
|
1039
975
|
await callTool("fw_weaver_task_retry", { id: taskId });
|
|
1040
|
-
|
|
976
|
+
toast2("Task retried, back in pool", { type: "success" });
|
|
1041
977
|
fetchTask();
|
|
1042
978
|
} catch (err) {
|
|
1043
|
-
|
|
979
|
+
toast2(err instanceof Error ? err.message : "Failed to retry", { type: "error" });
|
|
1044
980
|
}
|
|
1045
981
|
setActionLoading(null);
|
|
1046
982
|
}, [callTool, taskId, fetchTask]);
|
|
1047
|
-
const handleCancel =
|
|
983
|
+
const handleCancel = useCallback2(async () => {
|
|
1048
984
|
const ok = await ctx.confirm("Cancel this task? It cannot be undone.", {
|
|
1049
985
|
title: "Cancel Task",
|
|
1050
986
|
confirmLabel: "Cancel Task",
|
|
@@ -1054,26 +990,26 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1054
990
|
setActionLoading("cancel");
|
|
1055
991
|
try {
|
|
1056
992
|
await callTool("fw_weaver_task_cancel", { id: taskId });
|
|
1057
|
-
|
|
993
|
+
toast2("Task cancelled", { type: "info" });
|
|
1058
994
|
fetchTask();
|
|
1059
995
|
} catch (err) {
|
|
1060
|
-
|
|
996
|
+
toast2(err instanceof Error ? err.message : "Failed to cancel", { type: "error" });
|
|
1061
997
|
}
|
|
1062
998
|
setActionLoading(null);
|
|
1063
999
|
}, [callTool, taskId, fetchTask, ctx]);
|
|
1064
|
-
const handleAssignProfile =
|
|
1000
|
+
const handleAssignProfile = useCallback2(async (profileId) => {
|
|
1065
1001
|
setActionLoading("assign-profile");
|
|
1066
1002
|
try {
|
|
1067
1003
|
const newProfile = task?.assignedProfile === profileId ? void 0 : profileId;
|
|
1068
1004
|
await callTool("fw_weaver_task_update", { id: taskId, assignedProfile: newProfile ?? null });
|
|
1069
|
-
|
|
1005
|
+
toast2(newProfile ? `Assigned profile ${profileId}` : `Unassigned profile`, { type: "success" });
|
|
1070
1006
|
fetchTask();
|
|
1071
1007
|
} catch (err) {
|
|
1072
|
-
|
|
1008
|
+
toast2(err instanceof Error ? err.message : "Failed to assign profile", { type: "error" });
|
|
1073
1009
|
}
|
|
1074
1010
|
setActionLoading(null);
|
|
1075
1011
|
}, [callTool, taskId, task, fetchTask]);
|
|
1076
|
-
const handlePriorityChange =
|
|
1012
|
+
const handlePriorityChange = useCallback2(async (delta) => {
|
|
1077
1013
|
const newPriority = Math.max(0, (task?.priority ?? 0) + delta);
|
|
1078
1014
|
try {
|
|
1079
1015
|
await callTool("fw_weaver_task_update", { id: taskId, priority: newPriority });
|
|
@@ -1081,9 +1017,9 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1081
1017
|
} catch {
|
|
1082
1018
|
}
|
|
1083
1019
|
}, [callTool, taskId, task, fetchTask]);
|
|
1084
|
-
const [expandedRunId, setExpandedRunId] =
|
|
1085
|
-
const [liveExpanded, setLiveExpanded] =
|
|
1086
|
-
const toggleExpand =
|
|
1020
|
+
const [expandedRunId, setExpandedRunId] = useState4(null);
|
|
1021
|
+
const [liveExpanded, setLiveExpanded] = useState4(true);
|
|
1022
|
+
const toggleExpand = useCallback2((id) => {
|
|
1087
1023
|
setExpandedRunId((prev) => prev === id ? null : id);
|
|
1088
1024
|
}, []);
|
|
1089
1025
|
const scrollRef = useRef2(null);
|
|
@@ -1091,33 +1027,33 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1091
1027
|
const el = scrollRef.current;
|
|
1092
1028
|
if (el) el.scrollTop = el.scrollHeight;
|
|
1093
1029
|
}, [liveTimeline.length, stream.events.length]);
|
|
1094
|
-
const [approvalStatus, setApprovalStatus] =
|
|
1095
|
-
const [approvalLoading, setApprovalLoading] =
|
|
1030
|
+
const [approvalStatus, setApprovalStatus] = useState4(null);
|
|
1031
|
+
const [approvalLoading, setApprovalLoading] = useState4(false);
|
|
1096
1032
|
useEffect2(() => {
|
|
1097
1033
|
if (awaitingApproval) setApprovalStatus("pending");
|
|
1098
1034
|
}, [awaitingApproval]);
|
|
1099
1035
|
useEffect2(() => {
|
|
1100
1036
|
if (stream.events.length === 0) setApprovalStatus(null);
|
|
1101
1037
|
}, [stream.events.length]);
|
|
1102
|
-
const handleApprove =
|
|
1038
|
+
const handleApprove = useCallback2(async () => {
|
|
1103
1039
|
setApprovalLoading(true);
|
|
1104
1040
|
try {
|
|
1105
1041
|
await callTool("fw_weaver_approve", { approved: true });
|
|
1106
1042
|
setApprovalStatus("approved");
|
|
1107
|
-
|
|
1043
|
+
toast2("Plan approved", { type: "success" });
|
|
1108
1044
|
} catch (err) {
|
|
1109
|
-
|
|
1045
|
+
toast2(err instanceof Error ? err.message : "Failed to approve", { type: "error" });
|
|
1110
1046
|
}
|
|
1111
1047
|
setApprovalLoading(false);
|
|
1112
1048
|
}, [callTool]);
|
|
1113
|
-
const handleReject =
|
|
1049
|
+
const handleReject = useCallback2(async () => {
|
|
1114
1050
|
setApprovalLoading(true);
|
|
1115
1051
|
try {
|
|
1116
1052
|
await callTool("fw_weaver_approve", { approved: false });
|
|
1117
1053
|
setApprovalStatus("rejected");
|
|
1118
|
-
|
|
1054
|
+
toast2("Plan rejected", { type: "info" });
|
|
1119
1055
|
} catch (err) {
|
|
1120
|
-
|
|
1056
|
+
toast2(err instanceof Error ? err.message : "Failed to reject", { type: "error" });
|
|
1121
1057
|
}
|
|
1122
1058
|
setApprovalLoading(false);
|
|
1123
1059
|
}, [callTool]);
|
|
@@ -1146,32 +1082,32 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1146
1082
|
return "Bot run";
|
|
1147
1083
|
}
|
|
1148
1084
|
if (loading && !task) {
|
|
1149
|
-
return
|
|
1150
|
-
|
|
1085
|
+
return React6.createElement(
|
|
1086
|
+
Flex5,
|
|
1151
1087
|
{
|
|
1152
1088
|
variant: "column-stretch-start-nowrap-0",
|
|
1153
1089
|
style: { width: "100%", height: "100%", overflow: "hidden" }
|
|
1154
1090
|
},
|
|
1155
|
-
|
|
1156
|
-
|
|
1091
|
+
React6.createElement(
|
|
1092
|
+
Flex5,
|
|
1157
1093
|
{
|
|
1158
1094
|
variant: "column-stretch-start-nowrap-8",
|
|
1159
1095
|
style: headerStyle
|
|
1160
1096
|
},
|
|
1161
|
-
|
|
1097
|
+
React6.createElement(
|
|
1162
1098
|
Button2,
|
|
1163
1099
|
{ variant: "ghost", size: "sm", onClick: onBack },
|
|
1164
|
-
|
|
1100
|
+
React6.createElement(Icon3, { name: "arrowBack", size: 16 }),
|
|
1165
1101
|
" Back"
|
|
1166
1102
|
)
|
|
1167
1103
|
),
|
|
1168
|
-
|
|
1169
|
-
|
|
1104
|
+
React6.createElement(
|
|
1105
|
+
Flex5,
|
|
1170
1106
|
{
|
|
1171
1107
|
variant: "column-center-center-nowrap-0",
|
|
1172
1108
|
style: { flex: 1 }
|
|
1173
1109
|
},
|
|
1174
|
-
|
|
1110
|
+
React6.createElement(
|
|
1175
1111
|
Typography5,
|
|
1176
1112
|
{ variant: "caption-regular", color: "color-text-subtle" },
|
|
1177
1113
|
"Loading task..."
|
|
@@ -1180,32 +1116,32 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1180
1116
|
);
|
|
1181
1117
|
}
|
|
1182
1118
|
if (!task) {
|
|
1183
|
-
return
|
|
1184
|
-
|
|
1119
|
+
return React6.createElement(
|
|
1120
|
+
Flex5,
|
|
1185
1121
|
{
|
|
1186
1122
|
variant: "column-stretch-start-nowrap-0",
|
|
1187
1123
|
style: { width: "100%", height: "100%", overflow: "hidden" }
|
|
1188
1124
|
},
|
|
1189
|
-
|
|
1190
|
-
|
|
1125
|
+
React6.createElement(
|
|
1126
|
+
Flex5,
|
|
1191
1127
|
{
|
|
1192
1128
|
variant: "column-stretch-start-nowrap-8",
|
|
1193
1129
|
style: headerStyle
|
|
1194
1130
|
},
|
|
1195
|
-
|
|
1131
|
+
React6.createElement(
|
|
1196
1132
|
Button2,
|
|
1197
1133
|
{ variant: "ghost", size: "sm", onClick: onBack },
|
|
1198
|
-
|
|
1134
|
+
React6.createElement(Icon3, { name: "arrowBack", size: 16 }),
|
|
1199
1135
|
" Back"
|
|
1200
1136
|
)
|
|
1201
1137
|
),
|
|
1202
|
-
|
|
1203
|
-
|
|
1138
|
+
React6.createElement(
|
|
1139
|
+
Flex5,
|
|
1204
1140
|
{
|
|
1205
1141
|
variant: "column-center-center-nowrap-0",
|
|
1206
1142
|
style: { flex: 1 }
|
|
1207
1143
|
},
|
|
1208
|
-
|
|
1144
|
+
React6.createElement(
|
|
1209
1145
|
Typography5,
|
|
1210
1146
|
{ variant: "caption-regular", color: "color-text-subtle" },
|
|
1211
1147
|
"Task not found."
|
|
@@ -1216,71 +1152,82 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1216
1152
|
const hasContext = task.context?.files?.length > 0 || task.context?.notes;
|
|
1217
1153
|
const hasSubtasks = task.isParent && subtasks.length > 0;
|
|
1218
1154
|
const hasRuns = runItems.length > 0 || isLive;
|
|
1219
|
-
return
|
|
1220
|
-
|
|
1155
|
+
return React6.createElement(
|
|
1156
|
+
Flex5,
|
|
1221
1157
|
{
|
|
1222
1158
|
variant: "column-stretch-start-nowrap-0",
|
|
1223
1159
|
style: { width: "100%", height: "100%", overflow: "hidden" }
|
|
1224
1160
|
},
|
|
1225
1161
|
// ── Header ──
|
|
1226
|
-
|
|
1227
|
-
|
|
1162
|
+
React6.createElement(
|
|
1163
|
+
Flex5,
|
|
1228
1164
|
{
|
|
1229
1165
|
variant: "column-stretch-start-nowrap-6",
|
|
1230
1166
|
style: { ...headerStyle, padding: "12px 16px", borderBottom: "1px solid var(--color-border-default)" }
|
|
1231
1167
|
},
|
|
1232
|
-
// Top row: back + title + status
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
{ variant: "row-center-
|
|
1236
|
-
|
|
1237
|
-
|
|
1168
|
+
// Top row: back + title + status + edit
|
|
1169
|
+
React6.createElement(
|
|
1170
|
+
Flex5,
|
|
1171
|
+
{ variant: "row-center-space-between-nowrap-8" },
|
|
1172
|
+
React6.createElement(
|
|
1173
|
+
Flex5,
|
|
1174
|
+
{ variant: "row-center-start-nowrap-8", style: { flex: 1, minWidth: 0 } },
|
|
1175
|
+
React6.createElement(IconButton3, {
|
|
1176
|
+
icon: "back",
|
|
1177
|
+
size: "xs",
|
|
1178
|
+
variant: "clear",
|
|
1179
|
+
onClick: onBack
|
|
1180
|
+
}),
|
|
1181
|
+
React6.createElement(StatusIcon3, {
|
|
1182
|
+
status: statusToIcon2[task.status] || "pending",
|
|
1183
|
+
size: "sm"
|
|
1184
|
+
}),
|
|
1185
|
+
React6.createElement(Typography5, {
|
|
1186
|
+
variant: "caption-thick",
|
|
1187
|
+
color: "color-text-high",
|
|
1188
|
+
style: { flex: 1, minWidth: 0, wordBreak: "break-word" }
|
|
1189
|
+
}, task.title || "Untitled Task")
|
|
1190
|
+
),
|
|
1191
|
+
onEdit && React6.createElement(IconButton3, {
|
|
1192
|
+
icon: "edit",
|
|
1238
1193
|
size: "xs",
|
|
1239
1194
|
variant: "clear",
|
|
1240
|
-
onClick:
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
status: statusToIcon2[task.status] || "pending",
|
|
1244
|
-
size: "sm"
|
|
1245
|
-
}),
|
|
1246
|
-
React7.createElement(Typography5, {
|
|
1247
|
-
variant: "caption-thick",
|
|
1248
|
-
color: "color-text-high",
|
|
1249
|
-
style: { flex: 1, minWidth: 0, wordBreak: "break-word" }
|
|
1250
|
-
}, task.title || "Untitled Task")
|
|
1195
|
+
onClick: () => onEdit(taskId),
|
|
1196
|
+
title: "Edit task"
|
|
1197
|
+
})
|
|
1251
1198
|
),
|
|
1252
1199
|
// Meta row: status tag, assigned profile, priority, attempts
|
|
1253
|
-
|
|
1254
|
-
|
|
1200
|
+
React6.createElement(
|
|
1201
|
+
Flex5,
|
|
1255
1202
|
{ variant: "row-center-start-wrap-6" },
|
|
1256
|
-
|
|
1203
|
+
React6.createElement(Tag2, {
|
|
1257
1204
|
size: "small",
|
|
1258
1205
|
color: task.status === "done" ? "positive" : task.status === "failed" ? "negative" : task.status === "in-progress" ? "info" : task.status === "blocked" ? "caution" : "secondary"
|
|
1259
1206
|
}, statusToLabel2[task.status] || task.status || "pending"),
|
|
1260
|
-
task.assignedProfile &&
|
|
1261
|
-
task.priority > 0 &&
|
|
1207
|
+
task.assignedProfile && React6.createElement(Tag2, { key: `profile-${task.assignedProfile}`, size: "small", color: "info" }, task.assignedProfile),
|
|
1208
|
+
task.priority > 0 && React6.createElement(Tag2, {
|
|
1262
1209
|
size: "small",
|
|
1263
1210
|
color: task.priority >= 3 ? "caution" : "info"
|
|
1264
1211
|
}, `P${task.priority}`),
|
|
1265
|
-
task.attempt != null && task.maxAttempts != null &&
|
|
1212
|
+
task.attempt != null && task.maxAttempts != null && React6.createElement(Typography5, {
|
|
1266
1213
|
variant: "smallCaption-regular",
|
|
1267
1214
|
color: "color-text-subtle"
|
|
1268
1215
|
}, `Attempt ${task.attempt}/${task.maxAttempts}`)
|
|
1269
1216
|
),
|
|
1270
1217
|
// Description
|
|
1271
|
-
task.description &&
|
|
1218
|
+
task.description && React6.createElement(Typography5, {
|
|
1272
1219
|
variant: "smallCaption-regular",
|
|
1273
1220
|
color: "color-text-medium"
|
|
1274
1221
|
}, task.description),
|
|
1275
1222
|
// Profile routing info
|
|
1276
|
-
task.assignedProfile &&
|
|
1277
|
-
|
|
1223
|
+
task.assignedProfile && React6.createElement(
|
|
1224
|
+
Flex5,
|
|
1278
1225
|
{ variant: "column-stretch-start-nowrap-2" },
|
|
1279
|
-
|
|
1226
|
+
React6.createElement(Typography5, {
|
|
1280
1227
|
variant: "smallCaption-regular",
|
|
1281
1228
|
color: "color-text-medium"
|
|
1282
1229
|
}, `Profile: ${task.assignedProfile}`),
|
|
1283
|
-
task.routingReason &&
|
|
1230
|
+
task.routingReason && React6.createElement(Typography5, {
|
|
1284
1231
|
variant: "smallCaption-regular",
|
|
1285
1232
|
color: "color-text-subtle"
|
|
1286
1233
|
}, task.routingReason)
|
|
@@ -1288,7 +1235,7 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1288
1235
|
// (Actions moved to tab)
|
|
1289
1236
|
),
|
|
1290
1237
|
// ── Tabs ──
|
|
1291
|
-
|
|
1238
|
+
React6.createElement(Tabs, {
|
|
1292
1239
|
tabs: [
|
|
1293
1240
|
{ id: "runs", title: `Runs (${runItems.length}${isLive ? "+1" : ""})` },
|
|
1294
1241
|
...hasSubtasks ? [{ id: "subtasks", title: `Subtasks (${subtasks.filter((s) => s.status === "done").length}/${subtasks.length})` }] : [],
|
|
@@ -1300,21 +1247,21 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1300
1247
|
size: "sm"
|
|
1301
1248
|
}),
|
|
1302
1249
|
// ── Tab content ──
|
|
1303
|
-
|
|
1250
|
+
React6.createElement(
|
|
1304
1251
|
ScrollArea2,
|
|
1305
1252
|
{ ref: scrollRef, style: { flex: 1 } },
|
|
1306
|
-
|
|
1307
|
-
|
|
1253
|
+
React6.createElement(
|
|
1254
|
+
Flex5,
|
|
1308
1255
|
{ variant: "column-stretch-start-nowrap-8", style: { padding: "12px 16px" } },
|
|
1309
1256
|
// ── Runs tab ──
|
|
1310
|
-
detailTab === "runs" && (hasRuns || (task.runs?.length ?? 0) > 0) ?
|
|
1311
|
-
|
|
1257
|
+
detailTab === "runs" && (hasRuns || (task.runs?.length ?? 0) > 0) ? React6.createElement(
|
|
1258
|
+
Flex5,
|
|
1312
1259
|
{ variant: "column-stretch-start-nowrap-8" },
|
|
1313
1260
|
...runItems.map(({ run, runTimeline }) => {
|
|
1314
1261
|
const runId = run.id;
|
|
1315
1262
|
const isExpanded = expandedRunId === runId;
|
|
1316
1263
|
const isSuccess = run.outcome === "completed" || run.success === true;
|
|
1317
|
-
return
|
|
1264
|
+
return React6.createElement(TaskBlock, {
|
|
1318
1265
|
key: `run-${runId}`,
|
|
1319
1266
|
state: isSuccess ? "completed" : "failed",
|
|
1320
1267
|
instruction: extractInstruction(run),
|
|
@@ -1328,7 +1275,7 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1328
1275
|
});
|
|
1329
1276
|
}),
|
|
1330
1277
|
// Live run
|
|
1331
|
-
isLive &&
|
|
1278
|
+
isLive && React6.createElement(TaskBlock, {
|
|
1332
1279
|
key: "live-run",
|
|
1333
1280
|
state: "running",
|
|
1334
1281
|
instruction: liveInstruction ?? task.title,
|
|
@@ -1345,19 +1292,19 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1345
1292
|
expanded: liveExpanded,
|
|
1346
1293
|
onToggleExpand: () => setLiveExpanded((v) => !v)
|
|
1347
1294
|
})
|
|
1348
|
-
) : detailTab === "runs" &&
|
|
1295
|
+
) : detailTab === "runs" && React6.createElement(EmptyState2, {
|
|
1349
1296
|
icon: "smartToy",
|
|
1350
1297
|
message: "No runs yet",
|
|
1351
1298
|
description: "This task has not been executed yet."
|
|
1352
1299
|
}),
|
|
1353
1300
|
// ── Subtasks tab ──
|
|
1354
|
-
detailTab === "subtasks" && hasSubtasks &&
|
|
1355
|
-
|
|
1301
|
+
detailTab === "subtasks" && hasSubtasks && React6.createElement(
|
|
1302
|
+
Flex5,
|
|
1356
1303
|
{
|
|
1357
1304
|
variant: "column-stretch-start-nowrap-0"
|
|
1358
1305
|
},
|
|
1359
1306
|
...(subtasks ?? []).map(
|
|
1360
|
-
(sub) =>
|
|
1307
|
+
(sub) => React6.createElement(SubtaskRowItem, {
|
|
1361
1308
|
key: sub.id,
|
|
1362
1309
|
sub,
|
|
1363
1310
|
onBack
|
|
@@ -1365,20 +1312,20 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1365
1312
|
)
|
|
1366
1313
|
),
|
|
1367
1314
|
// ── Actions tab ──
|
|
1368
|
-
detailTab === "actions" &&
|
|
1369
|
-
|
|
1315
|
+
detailTab === "actions" && React6.createElement(
|
|
1316
|
+
Flex5,
|
|
1370
1317
|
{
|
|
1371
1318
|
variant: "column-stretch-start-nowrap-16"
|
|
1372
1319
|
},
|
|
1373
1320
|
// Status actions
|
|
1374
|
-
|
|
1375
|
-
|
|
1321
|
+
React6.createElement(
|
|
1322
|
+
Flex5,
|
|
1376
1323
|
{ variant: "column-stretch-start-nowrap-8" },
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1324
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Status"),
|
|
1325
|
+
React6.createElement(
|
|
1326
|
+
Flex5,
|
|
1380
1327
|
{ variant: "row-center-start-nowrap-6" },
|
|
1381
|
-
task.status === "failed" &&
|
|
1328
|
+
task.status === "failed" && React6.createElement(Button2, {
|
|
1382
1329
|
size: "xs",
|
|
1383
1330
|
variant: "fill",
|
|
1384
1331
|
color: "primary",
|
|
@@ -1386,7 +1333,7 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1386
1333
|
loading: actionLoading === "retry",
|
|
1387
1334
|
disabled: !!actionLoading
|
|
1388
1335
|
}, "Retry Task"),
|
|
1389
|
-
(task.status === "pending" || task.status === "in-progress" || task.status === "blocked") &&
|
|
1336
|
+
(task.status === "pending" || task.status === "in-progress" || task.status === "blocked") && React6.createElement(Button2, {
|
|
1390
1337
|
size: "xs",
|
|
1391
1338
|
variant: "outlined",
|
|
1392
1339
|
color: "danger",
|
|
@@ -1397,26 +1344,26 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1397
1344
|
)
|
|
1398
1345
|
),
|
|
1399
1346
|
// Priority
|
|
1400
|
-
|
|
1401
|
-
|
|
1347
|
+
React6.createElement(
|
|
1348
|
+
Flex5,
|
|
1402
1349
|
{ variant: "column-stretch-start-nowrap-8" },
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1350
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Priority"),
|
|
1351
|
+
React6.createElement(
|
|
1352
|
+
Flex5,
|
|
1406
1353
|
{ variant: "row-center-start-nowrap-8" },
|
|
1407
|
-
|
|
1354
|
+
React6.createElement(IconButton3, {
|
|
1408
1355
|
icon: "expandLess",
|
|
1409
1356
|
size: "xs",
|
|
1410
1357
|
variant: "outlined",
|
|
1411
1358
|
onClick: () => handlePriorityChange(1),
|
|
1412
1359
|
title: "Increase priority"
|
|
1413
1360
|
}),
|
|
1414
|
-
|
|
1361
|
+
React6.createElement(
|
|
1415
1362
|
Typography5,
|
|
1416
1363
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
1417
1364
|
`P${task.priority ?? 0}`
|
|
1418
1365
|
),
|
|
1419
|
-
|
|
1366
|
+
React6.createElement(IconButton3, {
|
|
1420
1367
|
icon: "expandMore",
|
|
1421
1368
|
size: "xs",
|
|
1422
1369
|
variant: "outlined",
|
|
@@ -1426,11 +1373,11 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1426
1373
|
)
|
|
1427
1374
|
),
|
|
1428
1375
|
// Assign Profile
|
|
1429
|
-
availableProfiles.length > 0 &&
|
|
1430
|
-
|
|
1376
|
+
availableProfiles.length > 0 && React6.createElement(
|
|
1377
|
+
Flex5,
|
|
1431
1378
|
{ variant: "column-stretch-start-nowrap-8" },
|
|
1432
|
-
|
|
1433
|
-
|
|
1379
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Assign Profile"),
|
|
1380
|
+
React6.createElement(Table, {
|
|
1434
1381
|
size: "compact",
|
|
1435
1382
|
getRowKey: (row) => row.id,
|
|
1436
1383
|
columns: [
|
|
@@ -1438,7 +1385,7 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1438
1385
|
key: "icon",
|
|
1439
1386
|
header: "",
|
|
1440
1387
|
width: "30px",
|
|
1441
|
-
render: (_, row) =>
|
|
1388
|
+
render: (_, row) => React6.createElement(Icon3, {
|
|
1442
1389
|
name: row.icon || "smartToy",
|
|
1443
1390
|
size: 14,
|
|
1444
1391
|
color: row.color || "color-text-medium"
|
|
@@ -1454,17 +1401,17 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1454
1401
|
render: (_, row) => {
|
|
1455
1402
|
const caps = row.capabilities || [];
|
|
1456
1403
|
if (caps.length === 0) return null;
|
|
1457
|
-
return
|
|
1458
|
-
|
|
1404
|
+
return React6.createElement(
|
|
1405
|
+
Flex5,
|
|
1459
1406
|
{ variant: "row-center-start-wrap-4" },
|
|
1460
1407
|
...caps.slice(0, 4).map(
|
|
1461
|
-
(cap) =>
|
|
1408
|
+
(cap) => React6.createElement(
|
|
1462
1409
|
"span",
|
|
1463
1410
|
{ key: cap.name, title: cap.description },
|
|
1464
|
-
|
|
1411
|
+
React6.createElement(Chip, { label: cap.name, size: "small", color: "color-brand-main" })
|
|
1465
1412
|
)
|
|
1466
1413
|
),
|
|
1467
|
-
caps.length > 4 &&
|
|
1414
|
+
caps.length > 4 && React6.createElement(Typography5, {
|
|
1468
1415
|
variant: "smallCaption-regular",
|
|
1469
1416
|
color: "color-text-subtle"
|
|
1470
1417
|
}, `+${caps.length - 4}`)
|
|
@@ -1478,7 +1425,7 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1478
1425
|
align: "right",
|
|
1479
1426
|
render: (_, row) => {
|
|
1480
1427
|
const isAssigned = task.assignedProfile === row.id;
|
|
1481
|
-
return
|
|
1428
|
+
return React6.createElement(Checkbox, {
|
|
1482
1429
|
checked: isAssigned,
|
|
1483
1430
|
onChange: () => handleAssignProfile(row.id),
|
|
1484
1431
|
size: "sm"
|
|
@@ -1491,20 +1438,20 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1491
1438
|
)
|
|
1492
1439
|
),
|
|
1493
1440
|
// ── Context tab ──
|
|
1494
|
-
detailTab === "context" && hasContext &&
|
|
1495
|
-
|
|
1441
|
+
detailTab === "context" && hasContext && React6.createElement(
|
|
1442
|
+
Flex5,
|
|
1496
1443
|
{
|
|
1497
1444
|
variant: "column-stretch-start-nowrap-12"
|
|
1498
1445
|
},
|
|
1499
1446
|
// Files
|
|
1500
|
-
(task.context?.files?.length ?? 0) > 0 &&
|
|
1501
|
-
|
|
1447
|
+
(task.context?.files?.length ?? 0) > 0 && React6.createElement(
|
|
1448
|
+
Flex5,
|
|
1502
1449
|
{
|
|
1503
1450
|
variant: "column-stretch-start-nowrap-4"
|
|
1504
1451
|
},
|
|
1505
|
-
|
|
1452
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Files"),
|
|
1506
1453
|
...(task.context?.files ?? []).map(
|
|
1507
|
-
(file) =>
|
|
1454
|
+
(file) => React6.createElement(Typography5, {
|
|
1508
1455
|
key: file,
|
|
1509
1456
|
variant: "smallCaption-regular",
|
|
1510
1457
|
color: "color-text-high",
|
|
@@ -1513,40 +1460,40 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1513
1460
|
)
|
|
1514
1461
|
),
|
|
1515
1462
|
// Notes
|
|
1516
|
-
task.context?.notes &&
|
|
1517
|
-
|
|
1463
|
+
task.context?.notes && React6.createElement(
|
|
1464
|
+
Flex5,
|
|
1518
1465
|
{
|
|
1519
1466
|
variant: "column-stretch-start-nowrap-4"
|
|
1520
1467
|
},
|
|
1521
|
-
|
|
1522
|
-
|
|
1468
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Notes"),
|
|
1469
|
+
React6.createElement(Typography5, {
|
|
1523
1470
|
variant: "smallCaption-regular",
|
|
1524
1471
|
color: "color-text-high",
|
|
1525
1472
|
style: { whiteSpace: "pre-wrap" }
|
|
1526
1473
|
}, task.context.notes)
|
|
1527
1474
|
),
|
|
1528
1475
|
// Last error
|
|
1529
|
-
task.context?.lastError &&
|
|
1530
|
-
|
|
1476
|
+
task.context?.lastError && React6.createElement(
|
|
1477
|
+
Flex5,
|
|
1531
1478
|
{
|
|
1532
1479
|
variant: "column-stretch-start-nowrap-4"
|
|
1533
1480
|
},
|
|
1534
|
-
|
|
1535
|
-
|
|
1481
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-status-negative" }, "Last Error"),
|
|
1482
|
+
React6.createElement(Typography5, {
|
|
1536
1483
|
variant: "smallCaption-regular",
|
|
1537
1484
|
color: "color-text-high",
|
|
1538
1485
|
style: { fontFamily: "var(--font-mono, monospace)", whiteSpace: "pre-wrap" }
|
|
1539
1486
|
}, task.context.lastError)
|
|
1540
1487
|
),
|
|
1541
1488
|
// Run summaries (accumulated context)
|
|
1542
|
-
(task.context?.runSummaries?.length ?? 0) > 0 &&
|
|
1543
|
-
|
|
1489
|
+
(task.context?.runSummaries?.length ?? 0) > 0 && React6.createElement(
|
|
1490
|
+
Flex5,
|
|
1544
1491
|
{
|
|
1545
1492
|
variant: "column-stretch-start-nowrap-6"
|
|
1546
1493
|
},
|
|
1547
|
-
|
|
1494
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Run Summaries"),
|
|
1548
1495
|
...(task.context?.runSummaries ?? []).map(
|
|
1549
|
-
(rs, i) =>
|
|
1496
|
+
(rs, i) => React6.createElement(
|
|
1550
1497
|
Card,
|
|
1551
1498
|
{
|
|
1552
1499
|
key: `rs-${i}`,
|
|
@@ -1554,28 +1501,28 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1554
1501
|
padding: "compact",
|
|
1555
1502
|
style: { gap: "4px" }
|
|
1556
1503
|
},
|
|
1557
|
-
|
|
1558
|
-
|
|
1504
|
+
React6.createElement(
|
|
1505
|
+
Flex5,
|
|
1559
1506
|
{ variant: "row-center-space-between-nowrap-8" },
|
|
1560
|
-
|
|
1507
|
+
React6.createElement(Typography5, {
|
|
1561
1508
|
variant: "smallCaption-thick",
|
|
1562
1509
|
color: rs.outcome === "success" ? "color-status-positive" : "color-status-negative"
|
|
1563
1510
|
}, `${rs.outcome === "success" ? "Success" : "Failed"} (${rs.botId ?? "unknown bot"})`),
|
|
1564
|
-
|
|
1511
|
+
React6.createElement(Typography5, {
|
|
1565
1512
|
variant: "smallCaption-regular",
|
|
1566
1513
|
color: "color-text-subtle"
|
|
1567
1514
|
}, `${Math.round((rs.durationMs ?? 0) / 1e3)}s \xB7 ${rs.tokensUsed ?? 0} tok \xB7 $${(rs.cost ?? 0).toFixed(3)}`)
|
|
1568
1515
|
),
|
|
1569
|
-
|
|
1516
|
+
React6.createElement(Typography5, {
|
|
1570
1517
|
variant: "smallCaption-regular",
|
|
1571
1518
|
color: "color-text-medium"
|
|
1572
1519
|
}, rs.summary ?? ""),
|
|
1573
|
-
(rs.filesModified ?? []).length > 0 &&
|
|
1520
|
+
(rs.filesModified ?? []).length > 0 && React6.createElement(Typography5, {
|
|
1574
1521
|
variant: "smallCaption-regular",
|
|
1575
1522
|
color: "color-text-subtle",
|
|
1576
1523
|
style: { fontFamily: "var(--font-mono, monospace)" }
|
|
1577
1524
|
}, `Files: ${rs.filesModified.join(", ")}`),
|
|
1578
|
-
rs.error &&
|
|
1525
|
+
rs.error && React6.createElement(Typography5, {
|
|
1579
1526
|
variant: "smallCaption-regular",
|
|
1580
1527
|
color: "color-status-negative"
|
|
1581
1528
|
}, `Error: ${rs.error}`)
|
|
@@ -1583,21 +1530,21 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1583
1530
|
)
|
|
1584
1531
|
),
|
|
1585
1532
|
// Budget
|
|
1586
|
-
(task.tokensUsed > 0 || task.costUsed > 0) &&
|
|
1587
|
-
|
|
1533
|
+
(task.tokensUsed > 0 || task.costUsed > 0) && React6.createElement(
|
|
1534
|
+
Flex5,
|
|
1588
1535
|
{
|
|
1589
1536
|
variant: "column-stretch-start-nowrap-4"
|
|
1590
1537
|
},
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1538
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Budget"),
|
|
1539
|
+
React6.createElement(
|
|
1540
|
+
Flex5,
|
|
1594
1541
|
{ variant: "row-center-start-nowrap-16" },
|
|
1595
|
-
|
|
1542
|
+
React6.createElement(
|
|
1596
1543
|
Typography5,
|
|
1597
1544
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
1598
1545
|
`Tokens: ${task.tokensUsed?.toLocaleString() ?? 0}${task.budgetTokens ? ` / ${task.budgetTokens.toLocaleString()}` : ""}`
|
|
1599
1546
|
),
|
|
1600
|
-
|
|
1547
|
+
React6.createElement(
|
|
1601
1548
|
Typography5,
|
|
1602
1549
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
1603
1550
|
`Cost: $${(task.costUsed ?? 0).toFixed(3)}${task.budgetCost ? ` / $${task.budgetCost.toFixed(2)}` : ""}`
|
|
@@ -1612,15 +1559,604 @@ function TaskDetailView({ taskId, onBack }) {
|
|
|
1612
1559
|
var task_detail_view_default = TaskDetailView;
|
|
1613
1560
|
module.exports = TaskDetailView;
|
|
1614
1561
|
|
|
1562
|
+
// src/ui/task-editor.tsx
|
|
1563
|
+
var React7 = require("react");
|
|
1564
|
+
var { useState: useState5, useEffect: useEffect3, useCallback: useCallback3 } = React7;
|
|
1565
|
+
var {
|
|
1566
|
+
Flex: Flex6,
|
|
1567
|
+
Typography: Typography6,
|
|
1568
|
+
Input,
|
|
1569
|
+
Button: Button3,
|
|
1570
|
+
IconButton: IconButton4,
|
|
1571
|
+
Tag: Tag3,
|
|
1572
|
+
Field,
|
|
1573
|
+
toast: toast3,
|
|
1574
|
+
usePackWorkspace: usePackWorkspace3
|
|
1575
|
+
} = require("@fw/plugin-ui-kit");
|
|
1576
|
+
var PRIORITY_OPTIONS = [
|
|
1577
|
+
{ id: "0", label: "0 \u2014 None" },
|
|
1578
|
+
{ id: "1", label: "1 \u2014 Low" },
|
|
1579
|
+
{ id: "2", label: "2 \u2014 Medium" },
|
|
1580
|
+
{ id: "3", label: "3 \u2014 High" },
|
|
1581
|
+
{ id: "4", label: "4 \u2014 Critical" }
|
|
1582
|
+
];
|
|
1583
|
+
var COMPLEXITY_OPTIONS = [
|
|
1584
|
+
{ id: "", label: "Not set" },
|
|
1585
|
+
{ id: "trivial", label: "Trivial" },
|
|
1586
|
+
{ id: "simple", label: "Simple" },
|
|
1587
|
+
{ id: "moderate", label: "Moderate" },
|
|
1588
|
+
{ id: "complex", label: "Complex" }
|
|
1589
|
+
];
|
|
1590
|
+
var STATUS_COLOR = {
|
|
1591
|
+
"pending": "secondary",
|
|
1592
|
+
"in-progress": "info",
|
|
1593
|
+
"blocked": "caution",
|
|
1594
|
+
"done": "positive",
|
|
1595
|
+
"failed": "negative",
|
|
1596
|
+
"cancelled": "negative"
|
|
1597
|
+
};
|
|
1598
|
+
function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
1599
|
+
const ctx = usePackWorkspace3();
|
|
1600
|
+
const { callTool } = ctx;
|
|
1601
|
+
const [title, setTitle] = useState5("");
|
|
1602
|
+
const [description, setDescription] = useState5("");
|
|
1603
|
+
const [priority, setPriority] = useState5("0");
|
|
1604
|
+
const [complexity, setComplexity] = useState5("");
|
|
1605
|
+
const [assignedProfile, setAssignedProfile] = useState5("");
|
|
1606
|
+
const [maxAttempts, setMaxAttempts] = useState5("3");
|
|
1607
|
+
const [budgetTokens, setBudgetTokens] = useState5("");
|
|
1608
|
+
const [budgetCost, setBudgetCost] = useState5("");
|
|
1609
|
+
const [notes, setNotes] = useState5("");
|
|
1610
|
+
const [files, setFiles] = useState5([]);
|
|
1611
|
+
const [newFile, setNewFile] = useState5("");
|
|
1612
|
+
const [dependsOn, setDependsOn] = useState5([]);
|
|
1613
|
+
const [newDep, setNewDep] = useState5("");
|
|
1614
|
+
const [taskData, setTaskData] = useState5(null);
|
|
1615
|
+
const [profiles, setProfiles] = useState5([]);
|
|
1616
|
+
const [loading, setLoading] = useState5(mode === "edit");
|
|
1617
|
+
useEffect3(() => {
|
|
1618
|
+
(async () => {
|
|
1619
|
+
try {
|
|
1620
|
+
const raw = await callTool("fw_weaver_profile_list", {});
|
|
1621
|
+
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1622
|
+
if (Array.isArray(data)) {
|
|
1623
|
+
setProfiles(data.map((p) => ({
|
|
1624
|
+
id: p.id,
|
|
1625
|
+
name: p.name || p.id
|
|
1626
|
+
})));
|
|
1627
|
+
}
|
|
1628
|
+
} catch {
|
|
1629
|
+
}
|
|
1630
|
+
})();
|
|
1631
|
+
}, [callTool]);
|
|
1632
|
+
useEffect3(() => {
|
|
1633
|
+
if (mode !== "edit" || !taskId) return;
|
|
1634
|
+
let cancelled = false;
|
|
1635
|
+
(async () => {
|
|
1636
|
+
try {
|
|
1637
|
+
const raw = await callTool("fw_weaver_task_get", { id: taskId });
|
|
1638
|
+
if (cancelled) return;
|
|
1639
|
+
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1640
|
+
const t = data?.task ?? data;
|
|
1641
|
+
if (!t || !t.id) {
|
|
1642
|
+
toast3("Task not found", { type: "error" });
|
|
1643
|
+
onCancel();
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
setTaskData(t);
|
|
1647
|
+
setTitle(t.title || "");
|
|
1648
|
+
setDescription(t.description || "");
|
|
1649
|
+
setPriority(String(t.priority ?? 0));
|
|
1650
|
+
setComplexity(t.complexity || "");
|
|
1651
|
+
setAssignedProfile(t.assignedProfile || "");
|
|
1652
|
+
setMaxAttempts(String(t.maxAttempts ?? 3));
|
|
1653
|
+
setBudgetTokens(t.budgetTokens != null ? String(t.budgetTokens) : "");
|
|
1654
|
+
setBudgetCost(t.budgetCost != null ? String(t.budgetCost) : "");
|
|
1655
|
+
setNotes(t.context?.notes || "");
|
|
1656
|
+
setFiles(t.context?.files || []);
|
|
1657
|
+
setDependsOn(t.dependsOn || []);
|
|
1658
|
+
} catch {
|
|
1659
|
+
toast3("Failed to load task", { type: "error" });
|
|
1660
|
+
onCancel();
|
|
1661
|
+
} finally {
|
|
1662
|
+
if (!cancelled) setLoading(false);
|
|
1663
|
+
}
|
|
1664
|
+
})();
|
|
1665
|
+
return () => {
|
|
1666
|
+
cancelled = true;
|
|
1667
|
+
};
|
|
1668
|
+
}, [mode, taskId, callTool, onCancel]);
|
|
1669
|
+
const handleAddFile = useCallback3(() => {
|
|
1670
|
+
const trimmed = newFile.trim();
|
|
1671
|
+
if (!trimmed) return;
|
|
1672
|
+
setFiles((prev) => [...prev, trimmed]);
|
|
1673
|
+
setNewFile("");
|
|
1674
|
+
}, [newFile]);
|
|
1675
|
+
const handleRemoveFile = useCallback3((index) => {
|
|
1676
|
+
setFiles((prev) => prev.filter((_, i) => i !== index));
|
|
1677
|
+
}, []);
|
|
1678
|
+
const handleAddDep = useCallback3(() => {
|
|
1679
|
+
const trimmed = newDep.trim();
|
|
1680
|
+
if (!trimmed) return;
|
|
1681
|
+
setDependsOn((prev) => [...prev, trimmed]);
|
|
1682
|
+
setNewDep("");
|
|
1683
|
+
}, [newDep]);
|
|
1684
|
+
const handleRemoveDep = useCallback3((index) => {
|
|
1685
|
+
setDependsOn((prev) => prev.filter((_, i) => i !== index));
|
|
1686
|
+
}, []);
|
|
1687
|
+
const handleSave = useCallback3(async () => {
|
|
1688
|
+
if (!title.trim()) {
|
|
1689
|
+
toast3("Title is required", { type: "error" });
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
try {
|
|
1693
|
+
if (mode === "create") {
|
|
1694
|
+
const args = {
|
|
1695
|
+
title: title.trim(),
|
|
1696
|
+
description: description.trim(),
|
|
1697
|
+
priority: parseInt(priority, 10) || 0,
|
|
1698
|
+
maxAttempts: parseInt(maxAttempts, 10) || 3
|
|
1699
|
+
};
|
|
1700
|
+
if (complexity) args.complexity = complexity;
|
|
1701
|
+
if (assignedProfile) args.assignedProfile = assignedProfile;
|
|
1702
|
+
if (budgetTokens) args.budgetTokens = parseInt(budgetTokens, 10);
|
|
1703
|
+
if (budgetCost) args.budgetCost = parseFloat(budgetCost);
|
|
1704
|
+
if (dependsOn.length > 0) args.dependsOn = dependsOn;
|
|
1705
|
+
await callTool("fw_weaver_task_create", args);
|
|
1706
|
+
toast3("Task created", { type: "success" });
|
|
1707
|
+
if (notes.trim() || files.length > 0) {
|
|
1708
|
+
try {
|
|
1709
|
+
} catch {
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
} else {
|
|
1713
|
+
const patch = {
|
|
1714
|
+
id: taskId,
|
|
1715
|
+
title: title.trim(),
|
|
1716
|
+
description: description.trim(),
|
|
1717
|
+
priority: parseInt(priority, 10) || 0,
|
|
1718
|
+
maxAttempts: parseInt(maxAttempts, 10) || 3,
|
|
1719
|
+
complexity: complexity || void 0,
|
|
1720
|
+
assignedProfile: assignedProfile || null
|
|
1721
|
+
};
|
|
1722
|
+
if (budgetTokens) {
|
|
1723
|
+
patch.budgetTokens = parseInt(budgetTokens, 10);
|
|
1724
|
+
} else {
|
|
1725
|
+
patch.budgetTokens = void 0;
|
|
1726
|
+
}
|
|
1727
|
+
if (budgetCost) {
|
|
1728
|
+
patch.budgetCost = parseFloat(budgetCost);
|
|
1729
|
+
} else {
|
|
1730
|
+
patch.budgetCost = void 0;
|
|
1731
|
+
}
|
|
1732
|
+
patch.context = {
|
|
1733
|
+
files,
|
|
1734
|
+
notes: notes.trim(),
|
|
1735
|
+
runSummaries: taskData?.context?.runSummaries || [],
|
|
1736
|
+
lastError: taskData?.context?.lastError
|
|
1737
|
+
};
|
|
1738
|
+
await callTool("fw_weaver_task_update", patch);
|
|
1739
|
+
toast3("Task updated", { type: "success" });
|
|
1740
|
+
}
|
|
1741
|
+
onSave();
|
|
1742
|
+
} catch (err) {
|
|
1743
|
+
toast3(err instanceof Error ? err.message : `Failed to ${mode} task`, { type: "error" });
|
|
1744
|
+
}
|
|
1745
|
+
}, [mode, taskId, title, description, priority, complexity, assignedProfile, maxAttempts, budgetTokens, budgetCost, notes, files, dependsOn, taskData, callTool, onSave]);
|
|
1746
|
+
const handleDelete = useCallback3(async () => {
|
|
1747
|
+
if (!taskId) return;
|
|
1748
|
+
const ok = await ctx.confirm("Are you sure you want to cancel this task?", {
|
|
1749
|
+
title: "Cancel Task",
|
|
1750
|
+
confirmLabel: "Cancel Task",
|
|
1751
|
+
state: "danger"
|
|
1752
|
+
});
|
|
1753
|
+
if (!ok) return;
|
|
1754
|
+
try {
|
|
1755
|
+
await callTool("fw_weaver_task_cancel", { id: taskId });
|
|
1756
|
+
toast3("Task cancelled", { type: "success" });
|
|
1757
|
+
if (onDelete) onDelete();
|
|
1758
|
+
} catch (err) {
|
|
1759
|
+
toast3(err instanceof Error ? err.message : "Failed to cancel task", { type: "error" });
|
|
1760
|
+
}
|
|
1761
|
+
}, [taskId, callTool, onDelete, ctx]);
|
|
1762
|
+
if (loading) {
|
|
1763
|
+
return React7.createElement(
|
|
1764
|
+
Flex6,
|
|
1765
|
+
{
|
|
1766
|
+
variant: "column-center-center-nowrap-12",
|
|
1767
|
+
style: { padding: "24px 16px" }
|
|
1768
|
+
},
|
|
1769
|
+
React7.createElement(Typography6, { variant: "caption-regular", color: "color-text-subtle" }, "Loading task...")
|
|
1770
|
+
);
|
|
1771
|
+
}
|
|
1772
|
+
const profileOptions = [
|
|
1773
|
+
{ id: "", label: "Not assigned" },
|
|
1774
|
+
...profiles.map((p) => ({ id: p.id, label: p.name }))
|
|
1775
|
+
];
|
|
1776
|
+
return React7.createElement(
|
|
1777
|
+
Flex6,
|
|
1778
|
+
{
|
|
1779
|
+
variant: "column-stretch-start-nowrap-0",
|
|
1780
|
+
style: { width: "100%", height: "100%", overflow: "hidden" }
|
|
1781
|
+
},
|
|
1782
|
+
// -- Header bar --
|
|
1783
|
+
React7.createElement(
|
|
1784
|
+
Flex6,
|
|
1785
|
+
{
|
|
1786
|
+
variant: "row-center-space-between-nowrap-8",
|
|
1787
|
+
style: { padding: "8px 16px", flexShrink: 0, borderBottom: "1px solid var(--color-border-default)" }
|
|
1788
|
+
},
|
|
1789
|
+
React7.createElement(
|
|
1790
|
+
Flex6,
|
|
1791
|
+
{ variant: "row-center-start-nowrap-8" },
|
|
1792
|
+
React7.createElement(IconButton4, {
|
|
1793
|
+
icon: "back",
|
|
1794
|
+
size: "xs",
|
|
1795
|
+
variant: "clear",
|
|
1796
|
+
onClick: onCancel,
|
|
1797
|
+
title: "Back"
|
|
1798
|
+
}),
|
|
1799
|
+
React7.createElement(
|
|
1800
|
+
Typography6,
|
|
1801
|
+
{ variant: "caption-thick", color: "color-text-high" },
|
|
1802
|
+
mode === "create" ? "Create Task" : "Edit Task"
|
|
1803
|
+
)
|
|
1804
|
+
),
|
|
1805
|
+
mode === "edit" && onDelete && React7.createElement(IconButton4, {
|
|
1806
|
+
icon: "outlinedDelete",
|
|
1807
|
+
size: "sm",
|
|
1808
|
+
variant: "clear",
|
|
1809
|
+
color: "danger",
|
|
1810
|
+
onClick: handleDelete,
|
|
1811
|
+
title: "Cancel task"
|
|
1812
|
+
})
|
|
1813
|
+
),
|
|
1814
|
+
// -- Scrollable form body --
|
|
1815
|
+
React7.createElement(
|
|
1816
|
+
Flex6,
|
|
1817
|
+
{
|
|
1818
|
+
variant: "column-stretch-start-nowrap-10",
|
|
1819
|
+
style: { flex: 1, minHeight: 0, overflow: "auto", padding: "12px 16px" }
|
|
1820
|
+
},
|
|
1821
|
+
// -- Edit-only: Status tag --
|
|
1822
|
+
mode === "edit" && taskData && React7.createElement(
|
|
1823
|
+
Field,
|
|
1824
|
+
{ label: "Status" },
|
|
1825
|
+
React7.createElement(Tag3, {
|
|
1826
|
+
size: "small",
|
|
1827
|
+
color: STATUS_COLOR[taskData.status] || "secondary"
|
|
1828
|
+
}, taskData.status)
|
|
1829
|
+
),
|
|
1830
|
+
// -- Title --
|
|
1831
|
+
React7.createElement(
|
|
1832
|
+
Field,
|
|
1833
|
+
{ label: "Title" },
|
|
1834
|
+
React7.createElement(Input, {
|
|
1835
|
+
type: "text",
|
|
1836
|
+
size: "small",
|
|
1837
|
+
placeholder: "Task title (required)",
|
|
1838
|
+
value: title,
|
|
1839
|
+
onChange: (v) => setTitle(v),
|
|
1840
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
1841
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
1842
|
+
})
|
|
1843
|
+
),
|
|
1844
|
+
// -- Description --
|
|
1845
|
+
React7.createElement(
|
|
1846
|
+
Field,
|
|
1847
|
+
{ label: "Description" },
|
|
1848
|
+
React7.createElement(Input, {
|
|
1849
|
+
type: "text",
|
|
1850
|
+
size: "small",
|
|
1851
|
+
placeholder: "Detailed task description",
|
|
1852
|
+
value: description,
|
|
1853
|
+
onChange: (v) => setDescription(v),
|
|
1854
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
1855
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
1856
|
+
})
|
|
1857
|
+
),
|
|
1858
|
+
// -- Priority --
|
|
1859
|
+
React7.createElement(
|
|
1860
|
+
Field,
|
|
1861
|
+
{ label: "Priority" },
|
|
1862
|
+
React7.createElement(Input, {
|
|
1863
|
+
type: "select",
|
|
1864
|
+
size: "small",
|
|
1865
|
+
options: PRIORITY_OPTIONS,
|
|
1866
|
+
optionId: priority,
|
|
1867
|
+
onChange: (id) => setPriority(id),
|
|
1868
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 }
|
|
1869
|
+
})
|
|
1870
|
+
),
|
|
1871
|
+
// -- Complexity --
|
|
1872
|
+
React7.createElement(
|
|
1873
|
+
Field,
|
|
1874
|
+
{ label: "Complexity" },
|
|
1875
|
+
React7.createElement(Input, {
|
|
1876
|
+
type: "select",
|
|
1877
|
+
size: "small",
|
|
1878
|
+
options: COMPLEXITY_OPTIONS,
|
|
1879
|
+
optionId: complexity,
|
|
1880
|
+
onChange: (id) => setComplexity(id),
|
|
1881
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 }
|
|
1882
|
+
})
|
|
1883
|
+
),
|
|
1884
|
+
// -- Assigned Profile --
|
|
1885
|
+
React7.createElement(
|
|
1886
|
+
Field,
|
|
1887
|
+
{ label: "Profile" },
|
|
1888
|
+
React7.createElement(Input, {
|
|
1889
|
+
type: "select",
|
|
1890
|
+
size: "small",
|
|
1891
|
+
options: profileOptions,
|
|
1892
|
+
optionId: assignedProfile,
|
|
1893
|
+
onChange: (id) => setAssignedProfile(id),
|
|
1894
|
+
placeholder: "Select profile",
|
|
1895
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 }
|
|
1896
|
+
})
|
|
1897
|
+
),
|
|
1898
|
+
// -- Max Attempts --
|
|
1899
|
+
React7.createElement(
|
|
1900
|
+
Field,
|
|
1901
|
+
{ label: "Max Attempts" },
|
|
1902
|
+
React7.createElement(Input, {
|
|
1903
|
+
type: "number",
|
|
1904
|
+
size: "small",
|
|
1905
|
+
placeholder: "3",
|
|
1906
|
+
value: maxAttempts,
|
|
1907
|
+
onChange: (v) => setMaxAttempts(v),
|
|
1908
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
1909
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
1910
|
+
})
|
|
1911
|
+
),
|
|
1912
|
+
// -- Budget Tokens --
|
|
1913
|
+
React7.createElement(
|
|
1914
|
+
Field,
|
|
1915
|
+
{ label: "Budget Tokens" },
|
|
1916
|
+
React7.createElement(Input, {
|
|
1917
|
+
type: "number",
|
|
1918
|
+
size: "small",
|
|
1919
|
+
placeholder: "Optional token limit",
|
|
1920
|
+
value: budgetTokens,
|
|
1921
|
+
onChange: (v) => setBudgetTokens(v),
|
|
1922
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
1923
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
1924
|
+
})
|
|
1925
|
+
),
|
|
1926
|
+
// -- Budget Cost --
|
|
1927
|
+
React7.createElement(
|
|
1928
|
+
Field,
|
|
1929
|
+
{ label: "Budget Cost" },
|
|
1930
|
+
React7.createElement(Input, {
|
|
1931
|
+
type: "number",
|
|
1932
|
+
size: "small",
|
|
1933
|
+
placeholder: "Optional cost limit (USD)",
|
|
1934
|
+
value: budgetCost,
|
|
1935
|
+
onChange: (v) => setBudgetCost(v),
|
|
1936
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
1937
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
1938
|
+
})
|
|
1939
|
+
),
|
|
1940
|
+
// -- Notes --
|
|
1941
|
+
React7.createElement(
|
|
1942
|
+
Field,
|
|
1943
|
+
{ label: "Notes" },
|
|
1944
|
+
React7.createElement(Input, {
|
|
1945
|
+
type: "text",
|
|
1946
|
+
size: "small",
|
|
1947
|
+
placeholder: "Optional notes for context",
|
|
1948
|
+
value: notes,
|
|
1949
|
+
onChange: (v) => setNotes(v),
|
|
1950
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
1951
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
1952
|
+
})
|
|
1953
|
+
),
|
|
1954
|
+
// -- Files --
|
|
1955
|
+
React7.createElement(
|
|
1956
|
+
Field,
|
|
1957
|
+
{ label: "Files", align: "start" },
|
|
1958
|
+
React7.createElement(
|
|
1959
|
+
Flex6,
|
|
1960
|
+
{ variant: "column-stretch-start-nowrap-6" },
|
|
1961
|
+
// Add file row
|
|
1962
|
+
React7.createElement(
|
|
1963
|
+
Flex6,
|
|
1964
|
+
{ variant: "row-center-start-nowrap-4", style: { overflow: "hidden" } },
|
|
1965
|
+
React7.createElement(Input, {
|
|
1966
|
+
type: "text",
|
|
1967
|
+
size: "small",
|
|
1968
|
+
placeholder: "File path",
|
|
1969
|
+
value: newFile,
|
|
1970
|
+
onChange: (v) => setNewFile(v),
|
|
1971
|
+
onEnter: handleAddFile,
|
|
1972
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
1973
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
1974
|
+
}),
|
|
1975
|
+
React7.createElement(IconButton4, {
|
|
1976
|
+
icon: "add",
|
|
1977
|
+
size: "sm",
|
|
1978
|
+
variant: "outlined",
|
|
1979
|
+
color: "primary",
|
|
1980
|
+
onClick: handleAddFile,
|
|
1981
|
+
disabled: !newFile.trim()
|
|
1982
|
+
})
|
|
1983
|
+
),
|
|
1984
|
+
...files.map(
|
|
1985
|
+
(file, idx) => React7.createElement(
|
|
1986
|
+
Flex6,
|
|
1987
|
+
{
|
|
1988
|
+
key: `file-${idx}`,
|
|
1989
|
+
variant: "row-center-start-nowrap-6",
|
|
1990
|
+
style: { paddingLeft: "4px" }
|
|
1991
|
+
},
|
|
1992
|
+
React7.createElement(Typography6, {
|
|
1993
|
+
variant: "smallCaption-regular",
|
|
1994
|
+
color: "color-text-high",
|
|
1995
|
+
style: { flex: 1, minWidth: 0, fontFamily: "var(--font-mono, monospace)" }
|
|
1996
|
+
}, file),
|
|
1997
|
+
React7.createElement(IconButton4, {
|
|
1998
|
+
icon: "close",
|
|
1999
|
+
size: "xs",
|
|
2000
|
+
variant: "clear",
|
|
2001
|
+
color: "danger",
|
|
2002
|
+
onClick: () => handleRemoveFile(idx)
|
|
2003
|
+
})
|
|
2004
|
+
)
|
|
2005
|
+
)
|
|
2006
|
+
)
|
|
2007
|
+
),
|
|
2008
|
+
// -- Dependencies --
|
|
2009
|
+
React7.createElement(
|
|
2010
|
+
Field,
|
|
2011
|
+
{ label: "Dependencies", align: "start" },
|
|
2012
|
+
React7.createElement(
|
|
2013
|
+
Flex6,
|
|
2014
|
+
{ variant: "column-stretch-start-nowrap-6" },
|
|
2015
|
+
// Add dependency row (create mode only)
|
|
2016
|
+
mode === "create" && React7.createElement(
|
|
2017
|
+
Flex6,
|
|
2018
|
+
{ variant: "row-center-start-nowrap-4", style: { overflow: "hidden" } },
|
|
2019
|
+
React7.createElement(Input, {
|
|
2020
|
+
type: "text",
|
|
2021
|
+
size: "small",
|
|
2022
|
+
placeholder: "Task ID",
|
|
2023
|
+
value: newDep,
|
|
2024
|
+
onChange: (v) => setNewDep(v),
|
|
2025
|
+
onEnter: handleAddDep,
|
|
2026
|
+
defaultBoxStyle: { flex: 1, minWidth: 0 },
|
|
2027
|
+
inputBoxStyle: { maxWidth: "none" }
|
|
2028
|
+
}),
|
|
2029
|
+
React7.createElement(IconButton4, {
|
|
2030
|
+
icon: "add",
|
|
2031
|
+
size: "sm",
|
|
2032
|
+
variant: "outlined",
|
|
2033
|
+
color: "primary",
|
|
2034
|
+
onClick: handleAddDep,
|
|
2035
|
+
disabled: !newDep.trim()
|
|
2036
|
+
})
|
|
2037
|
+
),
|
|
2038
|
+
// Dependency list
|
|
2039
|
+
dependsOn.length > 0 ? React7.createElement(
|
|
2040
|
+
Flex6,
|
|
2041
|
+
{ variant: "column-stretch-start-nowrap-4" },
|
|
2042
|
+
...dependsOn.map(
|
|
2043
|
+
(dep, idx) => React7.createElement(
|
|
2044
|
+
Flex6,
|
|
2045
|
+
{
|
|
2046
|
+
key: `dep-${idx}`,
|
|
2047
|
+
variant: "row-center-start-nowrap-6",
|
|
2048
|
+
style: { paddingLeft: "4px" }
|
|
2049
|
+
},
|
|
2050
|
+
React7.createElement(Typography6, {
|
|
2051
|
+
variant: "smallCaption-regular",
|
|
2052
|
+
color: "color-text-high",
|
|
2053
|
+
style: { flex: 1, minWidth: 0, fontFamily: "var(--font-mono, monospace)" }
|
|
2054
|
+
}, dep),
|
|
2055
|
+
mode === "create" && React7.createElement(IconButton4, {
|
|
2056
|
+
icon: "close",
|
|
2057
|
+
size: "xs",
|
|
2058
|
+
variant: "clear",
|
|
2059
|
+
color: "danger",
|
|
2060
|
+
onClick: () => handleRemoveDep(idx)
|
|
2061
|
+
})
|
|
2062
|
+
)
|
|
2063
|
+
)
|
|
2064
|
+
) : React7.createElement(Typography6, {
|
|
2065
|
+
variant: "smallCaption-regular",
|
|
2066
|
+
color: "color-text-subtle",
|
|
2067
|
+
style: { paddingLeft: "4px" }
|
|
2068
|
+
}, "None")
|
|
2069
|
+
)
|
|
2070
|
+
),
|
|
2071
|
+
// -- Edit-only: read-only metadata --
|
|
2072
|
+
mode === "edit" && taskData && React7.createElement(
|
|
2073
|
+
Flex6,
|
|
2074
|
+
{
|
|
2075
|
+
variant: "column-stretch-start-nowrap-10",
|
|
2076
|
+
style: { marginTop: 8, paddingTop: 12, borderTop: "1px solid var(--color-border-default)" }
|
|
2077
|
+
},
|
|
2078
|
+
React7.createElement(
|
|
2079
|
+
Field,
|
|
2080
|
+
{ label: "Created by" },
|
|
2081
|
+
React7.createElement(
|
|
2082
|
+
Typography6,
|
|
2083
|
+
{ variant: "smallCaption-regular", color: "color-text-medium" },
|
|
2084
|
+
taskData.createdBy || "unknown"
|
|
2085
|
+
)
|
|
2086
|
+
),
|
|
2087
|
+
React7.createElement(
|
|
2088
|
+
Field,
|
|
2089
|
+
{ label: "Created at" },
|
|
2090
|
+
React7.createElement(
|
|
2091
|
+
Typography6,
|
|
2092
|
+
{ variant: "smallCaption-regular", color: "color-text-medium" },
|
|
2093
|
+
taskData.createdAt ? new Date(taskData.createdAt).toLocaleString() : "-"
|
|
2094
|
+
)
|
|
2095
|
+
),
|
|
2096
|
+
React7.createElement(
|
|
2097
|
+
Field,
|
|
2098
|
+
{ label: "Updated at" },
|
|
2099
|
+
React7.createElement(
|
|
2100
|
+
Typography6,
|
|
2101
|
+
{ variant: "smallCaption-regular", color: "color-text-medium" },
|
|
2102
|
+
taskData.updatedAt ? new Date(taskData.updatedAt).toLocaleString() : "-"
|
|
2103
|
+
)
|
|
2104
|
+
),
|
|
2105
|
+
React7.createElement(
|
|
2106
|
+
Field,
|
|
2107
|
+
{ label: "Tokens used" },
|
|
2108
|
+
React7.createElement(
|
|
2109
|
+
Typography6,
|
|
2110
|
+
{ variant: "smallCaption-regular", color: "color-text-medium" },
|
|
2111
|
+
(taskData.tokensUsed ?? 0).toLocaleString()
|
|
2112
|
+
)
|
|
2113
|
+
),
|
|
2114
|
+
React7.createElement(
|
|
2115
|
+
Field,
|
|
2116
|
+
{ label: "Cost used" },
|
|
2117
|
+
React7.createElement(
|
|
2118
|
+
Typography6,
|
|
2119
|
+
{ variant: "smallCaption-regular", color: "color-text-medium" },
|
|
2120
|
+
`$${(taskData.costUsed ?? 0).toFixed(3)}`
|
|
2121
|
+
)
|
|
2122
|
+
),
|
|
2123
|
+
taskData.context?.lastError && React7.createElement(
|
|
2124
|
+
Field,
|
|
2125
|
+
{ label: "Last error", align: "start" },
|
|
2126
|
+
React7.createElement(Typography6, {
|
|
2127
|
+
variant: "smallCaption-regular",
|
|
2128
|
+
color: "color-status-negative",
|
|
2129
|
+
style: { fontFamily: "var(--font-mono, monospace)", whiteSpace: "pre-wrap" }
|
|
2130
|
+
}, taskData.context.lastError)
|
|
2131
|
+
)
|
|
2132
|
+
),
|
|
2133
|
+
// -- Save button --
|
|
2134
|
+
React7.createElement(
|
|
2135
|
+
Flex6,
|
|
2136
|
+
{ variant: "row-center-end-nowrap-8", style: { paddingTop: 8 } },
|
|
2137
|
+
React7.createElement(Button3, {
|
|
2138
|
+
size: "xs",
|
|
2139
|
+
variant: "fill",
|
|
2140
|
+
color: "primary",
|
|
2141
|
+
onClick: handleSave,
|
|
2142
|
+
disabled: !title.trim()
|
|
2143
|
+
}, mode === "create" ? "Create" : "Save")
|
|
2144
|
+
)
|
|
2145
|
+
)
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
var task_editor_default = TaskEditor;
|
|
2149
|
+
module.exports = TaskEditor;
|
|
2150
|
+
|
|
1615
2151
|
// src/ui/profile-card.tsx
|
|
1616
2152
|
var React8 = require("react");
|
|
1617
2153
|
var {
|
|
1618
2154
|
Flex: Flex7,
|
|
1619
|
-
Typography:
|
|
2155
|
+
Typography: Typography7,
|
|
1620
2156
|
Icon: Icon4,
|
|
1621
2157
|
Chip: Chip2,
|
|
1622
2158
|
IconButton: IconButton5,
|
|
1623
|
-
Tag:
|
|
2159
|
+
Tag: Tag4
|
|
1624
2160
|
} = require("@fw/plugin-ui-kit");
|
|
1625
2161
|
function ProfileCard({ profile, activeInstances, onEdit, onDelete }) {
|
|
1626
2162
|
const {
|
|
@@ -1660,7 +2196,7 @@ function ProfileCard({ profile, activeInstances, onEdit, onDelete }) {
|
|
|
1660
2196
|
},
|
|
1661
2197
|
React8.createElement(Icon4, { name: icon || "smartToy", size: 18 })
|
|
1662
2198
|
),
|
|
1663
|
-
React8.createElement(
|
|
2199
|
+
React8.createElement(Typography7, {
|
|
1664
2200
|
variant: "caption-thick",
|
|
1665
2201
|
color: "color-text-high",
|
|
1666
2202
|
style: { flex: 1, minWidth: 0 }
|
|
@@ -1682,7 +2218,7 @@ function ProfileCard({ profile, activeInstances, onEdit, onDelete }) {
|
|
|
1682
2218
|
})
|
|
1683
2219
|
),
|
|
1684
2220
|
// Description
|
|
1685
|
-
description && React8.createElement(
|
|
2221
|
+
description && React8.createElement(Typography7, {
|
|
1686
2222
|
variant: "smallCaption-regular",
|
|
1687
2223
|
color: "color-text-medium"
|
|
1688
2224
|
}, description),
|
|
@@ -1695,7 +2231,7 @@ function ProfileCard({ profile, activeInstances, onEdit, onDelete }) {
|
|
|
1695
2231
|
capabilities.length > 0 && React8.createElement(
|
|
1696
2232
|
Flex7,
|
|
1697
2233
|
{ variant: "row-center-start-wrap-4" },
|
|
1698
|
-
React8.createElement(
|
|
2234
|
+
React8.createElement(Typography7, {
|
|
1699
2235
|
variant: "smallCaption-regular",
|
|
1700
2236
|
color: "color-text-subtle",
|
|
1701
2237
|
style: { flexShrink: 0 }
|
|
@@ -1712,7 +2248,7 @@ function ProfileCard({ profile, activeInstances, onEdit, onDelete }) {
|
|
|
1712
2248
|
React8.createElement(
|
|
1713
2249
|
Flex7,
|
|
1714
2250
|
{ variant: "row-center-start-wrap-12" },
|
|
1715
|
-
React8.createElement(
|
|
2251
|
+
React8.createElement(Typography7, {
|
|
1716
2252
|
variant: "smallCaption-regular",
|
|
1717
2253
|
color: "color-text-subtle"
|
|
1718
2254
|
}, `Cost strategy: ${preferences.costStrategy}`)
|
|
@@ -1721,22 +2257,22 @@ function ProfileCard({ profile, activeInstances, onEdit, onDelete }) {
|
|
|
1721
2257
|
React8.createElement(
|
|
1722
2258
|
Flex7,
|
|
1723
2259
|
{ variant: "row-center-start-wrap-12" },
|
|
1724
|
-
React8.createElement(
|
|
2260
|
+
React8.createElement(Typography7, {
|
|
1725
2261
|
variant: "smallCaption-regular",
|
|
1726
2262
|
color: "color-text-subtle"
|
|
1727
2263
|
}, `Instances: ${activeInstances}/${maxInstances} active`),
|
|
1728
|
-
React8.createElement(
|
|
2264
|
+
React8.createElement(Tag4, {
|
|
1729
2265
|
size: "small",
|
|
1730
2266
|
color: preferences.requireApproval ? "caution" : "positive"
|
|
1731
2267
|
}, preferences.requireApproval ? "Approval required" : "Auto-approve")
|
|
1732
2268
|
),
|
|
1733
2269
|
// Budget line
|
|
1734
|
-
budgetText && React8.createElement(
|
|
2270
|
+
budgetText && React8.createElement(Typography7, {
|
|
1735
2271
|
variant: "smallCaption-regular",
|
|
1736
2272
|
color: "color-text-subtle"
|
|
1737
2273
|
}, `Budget: ${budgetText}`),
|
|
1738
2274
|
// Instructions
|
|
1739
|
-
preferences.instructions && React8.createElement(
|
|
2275
|
+
preferences.instructions && React8.createElement(Typography7, {
|
|
1740
2276
|
variant: "smallCaption-regular",
|
|
1741
2277
|
color: "color-text-subtle",
|
|
1742
2278
|
style: { fontStyle: "italic" }
|
|
@@ -1930,17 +2466,17 @@ var BOT_COLORS = [
|
|
|
1930
2466
|
|
|
1931
2467
|
// src/ui/profile-editor.tsx
|
|
1932
2468
|
var React9 = require("react");
|
|
1933
|
-
var { useState: useState6, useEffect:
|
|
2469
|
+
var { useState: useState6, useEffect: useEffect4, useCallback: useCallback4 } = React9;
|
|
1934
2470
|
var {
|
|
1935
2471
|
Flex: Flex8,
|
|
1936
|
-
Typography:
|
|
2472
|
+
Typography: Typography8,
|
|
1937
2473
|
Input: Input2,
|
|
1938
|
-
Button:
|
|
2474
|
+
Button: Button4,
|
|
1939
2475
|
IconButton: IconButton6,
|
|
1940
2476
|
Icon: Icon5,
|
|
1941
2477
|
SectionTitle,
|
|
1942
2478
|
Checkbox: Checkbox2,
|
|
1943
|
-
Field,
|
|
2479
|
+
Field: Field2,
|
|
1944
2480
|
IconPicker,
|
|
1945
2481
|
ColorPicker,
|
|
1946
2482
|
toast: toast4,
|
|
@@ -1961,7 +2497,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
1961
2497
|
const [instructions, setInstructions] = useState6("");
|
|
1962
2498
|
const [requireApproval, setRequireApproval] = useState6(false);
|
|
1963
2499
|
const [loading, setLoading] = useState6(mode === "edit");
|
|
1964
|
-
|
|
2500
|
+
useEffect4(() => {
|
|
1965
2501
|
if (mode !== "edit" || !profileId) return;
|
|
1966
2502
|
let cancelled = false;
|
|
1967
2503
|
(async () => {
|
|
@@ -2079,7 +2615,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2079
2615
|
variant: "column-center-center-nowrap-12",
|
|
2080
2616
|
style: { padding: "24px 16px" }
|
|
2081
2617
|
},
|
|
2082
|
-
React9.createElement(
|
|
2618
|
+
React9.createElement(Typography8, { variant: "caption-regular", color: "color-text-subtle" }, "Loading profile...")
|
|
2083
2619
|
);
|
|
2084
2620
|
}
|
|
2085
2621
|
return React9.createElement(
|
|
@@ -2105,7 +2641,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2105
2641
|
onClick: onCancel,
|
|
2106
2642
|
title: "Back"
|
|
2107
2643
|
}),
|
|
2108
|
-
React9.createElement(
|
|
2644
|
+
React9.createElement(Typography8, { variant: "caption-thick", color: "color-text-high" }, mode === "create" ? "Create Profile" : "Edit Profile")
|
|
2109
2645
|
),
|
|
2110
2646
|
mode === "edit" && onDelete && React9.createElement(IconButton6, {
|
|
2111
2647
|
icon: "outlinedDelete",
|
|
@@ -2125,7 +2661,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2125
2661
|
},
|
|
2126
2662
|
// ── Name ──
|
|
2127
2663
|
React9.createElement(
|
|
2128
|
-
|
|
2664
|
+
Field2,
|
|
2129
2665
|
{ label: "Name" },
|
|
2130
2666
|
React9.createElement(Input2, {
|
|
2131
2667
|
type: "text",
|
|
@@ -2139,7 +2675,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2139
2675
|
),
|
|
2140
2676
|
// ── Description ──
|
|
2141
2677
|
React9.createElement(
|
|
2142
|
-
|
|
2678
|
+
Field2,
|
|
2143
2679
|
{ label: "Description" },
|
|
2144
2680
|
React9.createElement(Input2, {
|
|
2145
2681
|
type: "text",
|
|
@@ -2153,7 +2689,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2153
2689
|
),
|
|
2154
2690
|
// ── Bot ──
|
|
2155
2691
|
React9.createElement(
|
|
2156
|
-
|
|
2692
|
+
Field2,
|
|
2157
2693
|
{ label: "Bot" },
|
|
2158
2694
|
React9.createElement(Input2, {
|
|
2159
2695
|
type: "select",
|
|
@@ -2168,7 +2704,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2168
2704
|
),
|
|
2169
2705
|
// ── Icon ──
|
|
2170
2706
|
React9.createElement(
|
|
2171
|
-
|
|
2707
|
+
Field2,
|
|
2172
2708
|
{ label: "Icon", align: "start" },
|
|
2173
2709
|
React9.createElement(IconPicker, {
|
|
2174
2710
|
catalog: ICON_CATALOG,
|
|
@@ -2180,7 +2716,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2180
2716
|
),
|
|
2181
2717
|
// ── Color ──
|
|
2182
2718
|
React9.createElement(
|
|
2183
|
-
|
|
2719
|
+
Field2,
|
|
2184
2720
|
{ label: "Color", align: "start" },
|
|
2185
2721
|
React9.createElement(ColorPicker, {
|
|
2186
2722
|
colors: BOT_COLORS,
|
|
@@ -2191,7 +2727,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2191
2727
|
),
|
|
2192
2728
|
// ── Cost Strategy ──
|
|
2193
2729
|
React9.createElement(
|
|
2194
|
-
|
|
2730
|
+
Field2,
|
|
2195
2731
|
{ label: "Cost Strategy" },
|
|
2196
2732
|
React9.createElement(Input2, {
|
|
2197
2733
|
type: "select",
|
|
@@ -2208,7 +2744,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2208
2744
|
),
|
|
2209
2745
|
// ── Capabilities ──
|
|
2210
2746
|
React9.createElement(
|
|
2211
|
-
|
|
2747
|
+
Field2,
|
|
2212
2748
|
{ label: "Capabilities", align: "start" },
|
|
2213
2749
|
React9.createElement(
|
|
2214
2750
|
Flex8,
|
|
@@ -2253,12 +2789,12 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2253
2789
|
variant: "row-center-start-nowrap-6",
|
|
2254
2790
|
style: { paddingLeft: "4px" }
|
|
2255
2791
|
},
|
|
2256
|
-
React9.createElement(
|
|
2792
|
+
React9.createElement(Typography8, {
|
|
2257
2793
|
variant: "smallCaption-regular",
|
|
2258
2794
|
color: "color-text-high",
|
|
2259
2795
|
style: { flexShrink: 0 }
|
|
2260
2796
|
}, `\u2022 ${cap.name}:`),
|
|
2261
|
-
React9.createElement(
|
|
2797
|
+
React9.createElement(Typography8, {
|
|
2262
2798
|
variant: "smallCaption-regular",
|
|
2263
2799
|
color: "color-text-medium",
|
|
2264
2800
|
style: { flex: 1, minWidth: 0 }
|
|
@@ -2276,7 +2812,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2276
2812
|
),
|
|
2277
2813
|
// ── Instructions ──
|
|
2278
2814
|
React9.createElement(
|
|
2279
|
-
|
|
2815
|
+
Field2,
|
|
2280
2816
|
{ label: "Instructions" },
|
|
2281
2817
|
React9.createElement(Input2, {
|
|
2282
2818
|
type: "text",
|
|
@@ -2290,7 +2826,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2290
2826
|
),
|
|
2291
2827
|
// ── Require Approval ──
|
|
2292
2828
|
React9.createElement(
|
|
2293
|
-
|
|
2829
|
+
Field2,
|
|
2294
2830
|
{ label: "" },
|
|
2295
2831
|
React9.createElement(Checkbox2, {
|
|
2296
2832
|
checked: requireApproval,
|
|
@@ -2303,7 +2839,7 @@ function ProfileEditor({ mode, profileId, bots, onSave, onCancel, onDelete }) {
|
|
|
2303
2839
|
React9.createElement(
|
|
2304
2840
|
Flex8,
|
|
2305
2841
|
{ variant: "row-center-end-nowrap-8" },
|
|
2306
|
-
React9.createElement(
|
|
2842
|
+
React9.createElement(Button4, {
|
|
2307
2843
|
size: "xs",
|
|
2308
2844
|
variant: "fill",
|
|
2309
2845
|
color: "primary",
|
|
@@ -2321,9 +2857,9 @@ module.exports = ProfileEditor;
|
|
|
2321
2857
|
var React10 = require("react");
|
|
2322
2858
|
var {
|
|
2323
2859
|
Flex: Flex9,
|
|
2324
|
-
Typography:
|
|
2860
|
+
Typography: Typography9,
|
|
2325
2861
|
ScrollArea: ScrollArea3,
|
|
2326
|
-
Tag:
|
|
2862
|
+
Tag: Tag5,
|
|
2327
2863
|
SectionTitle: SectionTitle2
|
|
2328
2864
|
} = require("@fw/plugin-ui-kit");
|
|
2329
2865
|
var methodColors = {
|
|
@@ -2355,7 +2891,7 @@ function DecisionLog({ decisions }) {
|
|
|
2355
2891
|
variant: "column-stretch-start-nowrap-4"
|
|
2356
2892
|
},
|
|
2357
2893
|
React10.createElement(SectionTitle2, null, "Decision Log"),
|
|
2358
|
-
React10.createElement(
|
|
2894
|
+
React10.createElement(Typography9, {
|
|
2359
2895
|
variant: "smallCaption-regular",
|
|
2360
2896
|
color: "color-text-subtle"
|
|
2361
2897
|
}, "No routing decisions yet.")
|
|
@@ -2394,28 +2930,28 @@ function DecisionLog({ decisions }) {
|
|
|
2394
2930
|
React10.createElement(
|
|
2395
2931
|
Flex9,
|
|
2396
2932
|
{ variant: "row-center-start-nowrap-8" },
|
|
2397
|
-
React10.createElement(
|
|
2933
|
+
React10.createElement(Typography9, {
|
|
2398
2934
|
variant: "smallCaption-regular",
|
|
2399
2935
|
color: "color-text-subtle",
|
|
2400
2936
|
style: { flexShrink: 0, fontFamily: "var(--font-mono, monospace)", fontSize: "11px" }
|
|
2401
2937
|
}, formatTime(d.timestamp)),
|
|
2402
|
-
React10.createElement(
|
|
2938
|
+
React10.createElement(Typography9, {
|
|
2403
2939
|
variant: "smallCaption-regular",
|
|
2404
2940
|
color: "color-text-high",
|
|
2405
2941
|
style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }
|
|
2406
2942
|
}, `"${truncate(d.taskTitle, 40)}"`),
|
|
2407
|
-
React10.createElement(
|
|
2943
|
+
React10.createElement(Typography9, {
|
|
2408
2944
|
variant: "smallCaption-regular",
|
|
2409
2945
|
color: "color-text-medium",
|
|
2410
2946
|
style: { flexShrink: 0 }
|
|
2411
2947
|
}, `\u2192 ${d.assignedInstanceId}`),
|
|
2412
|
-
React10.createElement(
|
|
2948
|
+
React10.createElement(Tag5, {
|
|
2413
2949
|
size: "small",
|
|
2414
2950
|
color: methodColors[d.method] || "secondary"
|
|
2415
2951
|
}, methodLabel)
|
|
2416
2952
|
),
|
|
2417
2953
|
// Reason line
|
|
2418
|
-
React10.createElement(
|
|
2954
|
+
React10.createElement(Typography9, {
|
|
2419
2955
|
variant: "smallCaption-regular",
|
|
2420
2956
|
color: "color-text-subtle",
|
|
2421
2957
|
style: { paddingLeft: "70px" }
|
|
@@ -2431,19 +2967,19 @@ module.exports = DecisionLog;
|
|
|
2431
2967
|
|
|
2432
2968
|
// src/ui/swarm-dashboard.tsx
|
|
2433
2969
|
var React11 = require("react");
|
|
2434
|
-
var { useState: useState7, useEffect:
|
|
2970
|
+
var { useState: useState7, useEffect: useEffect5, useCallback: useCallback5, useRef: useRef3 } = React11;
|
|
2435
2971
|
var {
|
|
2436
2972
|
Flex: Flex10,
|
|
2437
2973
|
ScrollArea: ScrollArea4,
|
|
2438
2974
|
EmptyState: EmptyState3,
|
|
2439
|
-
Typography:
|
|
2975
|
+
Typography: Typography10,
|
|
2440
2976
|
StatusIcon: StatusIcon4,
|
|
2441
2977
|
Icon: Icon6,
|
|
2442
|
-
Tag:
|
|
2978
|
+
Tag: Tag6,
|
|
2443
2979
|
Card: Card2,
|
|
2444
2980
|
Tabs: Tabs2,
|
|
2445
2981
|
SectionTitle: SectionTitle3,
|
|
2446
|
-
Button:
|
|
2982
|
+
Button: Button5,
|
|
2447
2983
|
Input: Input3,
|
|
2448
2984
|
IconButton: IconButton7,
|
|
2449
2985
|
IconPicker: IconPicker2,
|
|
@@ -2451,7 +2987,7 @@ var {
|
|
|
2451
2987
|
toast: toast5,
|
|
2452
2988
|
usePackWorkspace: usePackWorkspace5
|
|
2453
2989
|
} = require("@fw/plugin-ui-kit");
|
|
2454
|
-
function
|
|
2990
|
+
function parseToolResult(raw) {
|
|
2455
2991
|
if (typeof raw === "string") {
|
|
2456
2992
|
try {
|
|
2457
2993
|
return JSON.parse(raw);
|
|
@@ -2474,6 +3010,8 @@ function SwarmDashboard() {
|
|
|
2474
3010
|
const [editingBotId, setEditingBotId] = useState7(null);
|
|
2475
3011
|
const [profileEditorMode, setProfileEditorMode] = useState7(null);
|
|
2476
3012
|
const [editingProfileId, setEditingProfileId] = useState7(null);
|
|
3013
|
+
const [taskEditorMode, setTaskEditorMode] = useState7(null);
|
|
3014
|
+
const [editingTaskId, setEditingTaskId] = useState7(null);
|
|
2477
3015
|
const [swarmStatus, setSwarmStatus] = useState7(null);
|
|
2478
3016
|
const [tasks, setTasks] = useState7([]);
|
|
2479
3017
|
const [registeredBots, setRegisteredBots] = useState7([]);
|
|
@@ -2483,7 +3021,7 @@ function SwarmDashboard() {
|
|
|
2483
3021
|
const [orchestratorDecisions, setOrchestratorDecisions] = useState7([]);
|
|
2484
3022
|
const [loading, setLoading] = useState7(true);
|
|
2485
3023
|
const mountedRef = useRef3(true);
|
|
2486
|
-
|
|
3024
|
+
useEffect5(() => {
|
|
2487
3025
|
mountedRef.current = true;
|
|
2488
3026
|
return () => {
|
|
2489
3027
|
mountedRef.current = false;
|
|
@@ -2493,7 +3031,7 @@ function SwarmDashboard() {
|
|
|
2493
3031
|
try {
|
|
2494
3032
|
const raw = await callTool("fw_weaver_swarm_status", {});
|
|
2495
3033
|
if (!mountedRef.current) return;
|
|
2496
|
-
const data =
|
|
3034
|
+
const data = parseToolResult(raw);
|
|
2497
3035
|
if (data) setSwarmStatus(data);
|
|
2498
3036
|
} catch {
|
|
2499
3037
|
}
|
|
@@ -2502,7 +3040,7 @@ function SwarmDashboard() {
|
|
|
2502
3040
|
try {
|
|
2503
3041
|
const raw = await callTool("fw_weaver_task_list", {});
|
|
2504
3042
|
if (!mountedRef.current) return;
|
|
2505
|
-
const data =
|
|
3043
|
+
const data = parseToolResult(raw);
|
|
2506
3044
|
if (Array.isArray(data)) {
|
|
2507
3045
|
setTasks(data);
|
|
2508
3046
|
} else if (data && typeof data === "object" && Array.isArray(data.tasks)) {
|
|
@@ -2559,25 +3097,25 @@ function SwarmDashboard() {
|
|
|
2559
3097
|
await Promise.all([fetchSwarmStatus(), fetchTaskList(), fetchBots(), fetchConfig(), fetchProfiles(), fetchOrchestratorStatus()]);
|
|
2560
3098
|
if (mountedRef.current) setLoading(false);
|
|
2561
3099
|
}, [fetchSwarmStatus, fetchTaskList, fetchBots, fetchConfig, fetchProfiles, fetchOrchestratorStatus]);
|
|
2562
|
-
|
|
3100
|
+
useEffect5(() => {
|
|
2563
3101
|
refreshAll();
|
|
2564
3102
|
}, [refreshAll]);
|
|
2565
|
-
|
|
3103
|
+
useEffect5(() => {
|
|
2566
3104
|
const interval = setInterval(fetchSwarmStatus, 3e3);
|
|
2567
3105
|
return () => clearInterval(interval);
|
|
2568
3106
|
}, [fetchSwarmStatus]);
|
|
2569
|
-
|
|
3107
|
+
useEffect5(() => {
|
|
2570
3108
|
const interval = setInterval(fetchTaskList, 5e3);
|
|
2571
3109
|
return () => clearInterval(interval);
|
|
2572
3110
|
}, [fetchTaskList]);
|
|
2573
|
-
|
|
3111
|
+
useEffect5(() => {
|
|
2574
3112
|
const interval = setInterval(() => {
|
|
2575
3113
|
fetchProfiles();
|
|
2576
3114
|
fetchOrchestratorStatus();
|
|
2577
3115
|
}, 1e4);
|
|
2578
3116
|
return () => clearInterval(interval);
|
|
2579
3117
|
}, [fetchProfiles, fetchOrchestratorStatus]);
|
|
2580
|
-
|
|
3118
|
+
useEffect5(() => {
|
|
2581
3119
|
return onRefresh(() => refreshAll());
|
|
2582
3120
|
}, [refreshAll, onRefresh]);
|
|
2583
3121
|
const handleUpdateBot = useCallback5(async (botId, patch) => {
|
|
@@ -2605,13 +3143,35 @@ function SwarmDashboard() {
|
|
|
2605
3143
|
setSelectedTaskId(null);
|
|
2606
3144
|
refreshAll();
|
|
2607
3145
|
}, [refreshAll]);
|
|
2608
|
-
const
|
|
2609
|
-
|
|
2610
|
-
|
|
3146
|
+
const handleEditFromDetail = useCallback5((tid) => {
|
|
3147
|
+
setEditingTaskId(tid);
|
|
3148
|
+
setTaskEditorMode("edit");
|
|
3149
|
+
}, []);
|
|
3150
|
+
if (selectedTaskId && taskEditorMode === "edit" && editingTaskId) {
|
|
3151
|
+
return React11.createElement(task_editor_default, {
|
|
3152
|
+
mode: "edit",
|
|
3153
|
+
taskId: editingTaskId,
|
|
3154
|
+
onSave: () => {
|
|
3155
|
+
setTaskEditorMode(null);
|
|
3156
|
+
setEditingTaskId(null);
|
|
3157
|
+
},
|
|
3158
|
+
onCancel: () => {
|
|
3159
|
+
setTaskEditorMode(null);
|
|
3160
|
+
setEditingTaskId(null);
|
|
3161
|
+
},
|
|
3162
|
+
onDelete: () => {
|
|
3163
|
+
setTaskEditorMode(null);
|
|
3164
|
+
setEditingTaskId(null);
|
|
3165
|
+
setSelectedTaskId(null);
|
|
3166
|
+
fetchTaskList();
|
|
3167
|
+
}
|
|
3168
|
+
});
|
|
3169
|
+
}
|
|
2611
3170
|
if (selectedTaskId) {
|
|
2612
3171
|
return React11.createElement(task_detail_view_default, {
|
|
2613
3172
|
taskId: selectedTaskId,
|
|
2614
|
-
onBack: handleBack
|
|
3173
|
+
onBack: handleBack,
|
|
3174
|
+
onEdit: handleEditFromDetail
|
|
2615
3175
|
});
|
|
2616
3176
|
}
|
|
2617
3177
|
const swarmInstances = swarmStatus?.instances ?? {};
|
|
@@ -2672,8 +3232,27 @@ function SwarmDashboard() {
|
|
|
2672
3232
|
variant: "column-stretch-start-nowrap-0",
|
|
2673
3233
|
style: { flex: 1, minHeight: 0, overflow: "auto" }
|
|
2674
3234
|
},
|
|
2675
|
-
// Tasks tab
|
|
2676
|
-
activeTab === "tasks" && React11.createElement(
|
|
3235
|
+
// Tasks tab — when TaskEditor is open, render it INSTEAD of the list
|
|
3236
|
+
activeTab === "tasks" && taskEditorMode != null && React11.createElement(task_editor_default, {
|
|
3237
|
+
mode: taskEditorMode,
|
|
3238
|
+
taskId: editingTaskId ?? void 0,
|
|
3239
|
+
onSave: () => {
|
|
3240
|
+
setTaskEditorMode(null);
|
|
3241
|
+
setEditingTaskId(null);
|
|
3242
|
+
fetchTaskList();
|
|
3243
|
+
},
|
|
3244
|
+
onCancel: () => {
|
|
3245
|
+
setTaskEditorMode(null);
|
|
3246
|
+
setEditingTaskId(null);
|
|
3247
|
+
},
|
|
3248
|
+
onDelete: taskEditorMode === "edit" ? () => {
|
|
3249
|
+
setTaskEditorMode(null);
|
|
3250
|
+
setEditingTaskId(null);
|
|
3251
|
+
fetchTaskList();
|
|
3252
|
+
} : void 0
|
|
3253
|
+
}),
|
|
3254
|
+
// Tasks tab — default list view
|
|
3255
|
+
activeTab === "tasks" && taskEditorMode == null && React11.createElement(
|
|
2677
3256
|
Flex10,
|
|
2678
3257
|
{
|
|
2679
3258
|
variant: "column-stretch-start-nowrap-0",
|
|
@@ -2695,7 +3274,7 @@ function SwarmDashboard() {
|
|
|
2695
3274
|
variant: "row-center-start-nowrap-8",
|
|
2696
3275
|
style: { padding: "4px 16px", flexShrink: 0 }
|
|
2697
3276
|
},
|
|
2698
|
-
React11.createElement(
|
|
3277
|
+
React11.createElement(Button5, {
|
|
2699
3278
|
size: "xs",
|
|
2700
3279
|
variant: "outlined",
|
|
2701
3280
|
color: "secondary",
|
|
@@ -2709,7 +3288,7 @@ function SwarmDashboard() {
|
|
|
2709
3288
|
if (!ok) return;
|
|
2710
3289
|
try {
|
|
2711
3290
|
const raw = await callTool("fw_weaver_tasks_clear", { filter: "completed" });
|
|
2712
|
-
const data =
|
|
3291
|
+
const data = parseToolResult(raw);
|
|
2713
3292
|
toast5(`Cleared ${data?.cleared ?? 0} tasks`, { type: "success" });
|
|
2714
3293
|
fetchTaskList();
|
|
2715
3294
|
} catch (err) {
|
|
@@ -2717,7 +3296,7 @@ function SwarmDashboard() {
|
|
|
2717
3296
|
}
|
|
2718
3297
|
}
|
|
2719
3298
|
}, "Clear Completed"),
|
|
2720
|
-
React11.createElement(
|
|
3299
|
+
React11.createElement(Button5, {
|
|
2721
3300
|
size: "xs",
|
|
2722
3301
|
variant: "outlined",
|
|
2723
3302
|
color: "danger",
|
|
@@ -2731,7 +3310,7 @@ function SwarmDashboard() {
|
|
|
2731
3310
|
if (!ok) return;
|
|
2732
3311
|
try {
|
|
2733
3312
|
const raw = await callTool("fw_weaver_tasks_clear", { filter: "all" });
|
|
2734
|
-
const data =
|
|
3313
|
+
const data = parseToolResult(raw);
|
|
2735
3314
|
toast5(`Cleared ${data?.cleared ?? 0} tasks`, { type: "success" });
|
|
2736
3315
|
refreshAll();
|
|
2737
3316
|
} catch (err) {
|
|
@@ -2740,16 +3319,20 @@ function SwarmDashboard() {
|
|
|
2740
3319
|
}
|
|
2741
3320
|
}, "Clear All")
|
|
2742
3321
|
),
|
|
2743
|
-
// Task
|
|
3322
|
+
// New Task button (bottom bar)
|
|
2744
3323
|
React11.createElement(
|
|
2745
3324
|
Flex10,
|
|
2746
3325
|
{
|
|
2747
3326
|
variant: "column-stretch-start-nowrap-0",
|
|
2748
|
-
style: {
|
|
3327
|
+
style: { flexShrink: 0, borderTop: "1px solid var(--color-border-default)", padding: "8px 16px" }
|
|
2749
3328
|
},
|
|
2750
|
-
React11.createElement(
|
|
2751
|
-
|
|
2752
|
-
|
|
3329
|
+
React11.createElement(Button5, {
|
|
3330
|
+
size: "xs",
|
|
3331
|
+
variant: "clear",
|
|
3332
|
+
color: "primary",
|
|
3333
|
+
leftIcon: "add",
|
|
3334
|
+
onClick: () => setTaskEditorMode("create")
|
|
3335
|
+
}, "New Task")
|
|
2753
3336
|
)
|
|
2754
3337
|
),
|
|
2755
3338
|
// Bots tab
|
|
@@ -2771,37 +3354,37 @@ function SwarmDashboard() {
|
|
|
2771
3354
|
variant: "row-center-start-nowrap-8",
|
|
2772
3355
|
style: { padding: "8px 16px", borderBottom: "1px solid var(--color-border-default)" }
|
|
2773
3356
|
},
|
|
2774
|
-
React11.createElement(
|
|
3357
|
+
React11.createElement(Typography10, {
|
|
2775
3358
|
variant: "smallCaption-regular",
|
|
2776
3359
|
color: "color-text-subtle",
|
|
2777
3360
|
style: { width: "120px", flexShrink: 0 }
|
|
2778
3361
|
}, "Instance"),
|
|
2779
|
-
React11.createElement(
|
|
3362
|
+
React11.createElement(Typography10, {
|
|
2780
3363
|
variant: "smallCaption-regular",
|
|
2781
3364
|
color: "color-text-subtle",
|
|
2782
3365
|
style: { width: "110px", flexShrink: 0 }
|
|
2783
3366
|
}, "Bot"),
|
|
2784
|
-
React11.createElement(
|
|
3367
|
+
React11.createElement(Typography10, {
|
|
2785
3368
|
variant: "smallCaption-regular",
|
|
2786
3369
|
color: "color-text-subtle",
|
|
2787
3370
|
style: { width: "70px", flexShrink: 0 }
|
|
2788
3371
|
}, "Status"),
|
|
2789
|
-
React11.createElement(
|
|
3372
|
+
React11.createElement(Typography10, {
|
|
2790
3373
|
variant: "smallCaption-regular",
|
|
2791
3374
|
color: "color-text-subtle",
|
|
2792
3375
|
style: { flex: 1, minWidth: 0 }
|
|
2793
3376
|
}, "Task"),
|
|
2794
|
-
React11.createElement(
|
|
3377
|
+
React11.createElement(Typography10, {
|
|
2795
3378
|
variant: "smallCaption-regular",
|
|
2796
3379
|
color: "color-text-subtle",
|
|
2797
3380
|
style: { width: "50px", flexShrink: 0, textAlign: "right" }
|
|
2798
3381
|
}, "Tokens"),
|
|
2799
|
-
React11.createElement(
|
|
3382
|
+
React11.createElement(Typography10, {
|
|
2800
3383
|
variant: "smallCaption-regular",
|
|
2801
3384
|
color: "color-text-subtle",
|
|
2802
3385
|
style: { width: "50px", flexShrink: 0, textAlign: "right" }
|
|
2803
3386
|
}, "Cost"),
|
|
2804
|
-
React11.createElement(
|
|
3387
|
+
React11.createElement(Typography10, {
|
|
2805
3388
|
variant: "smallCaption-regular",
|
|
2806
3389
|
color: "color-text-subtle",
|
|
2807
3390
|
style: { width: "50px", flexShrink: 0 }
|
|
@@ -2866,8 +3449,8 @@ function SwarmDashboard() {
|
|
|
2866
3449
|
React11.createElement(
|
|
2867
3450
|
Flex10,
|
|
2868
3451
|
{ variant: "column-start-start-nowrap-1", style: { flex: 1, minWidth: 0 } },
|
|
2869
|
-
React11.createElement(
|
|
2870
|
-
bot.description && React11.createElement(
|
|
3452
|
+
React11.createElement(Typography10, { variant: "smallCaption-regular", color: "color-text-high" }, bot.name),
|
|
3453
|
+
bot.description && React11.createElement(Typography10, { variant: "smallCaption-regular", color: "color-text-subtle" }, bot.description)
|
|
2871
3454
|
),
|
|
2872
3455
|
React11.createElement(Icon6, { name: isEditing ? "expandLess" : "expandMore", size: 14, color: "color-text-subtle" })
|
|
2873
3456
|
),
|
|
@@ -2985,7 +3568,7 @@ function SwarmDashboard() {
|
|
|
2985
3568
|
variant: "column-stretch-start-nowrap-0",
|
|
2986
3569
|
style: { flexShrink: 0, borderTop: "1px solid var(--color-border-default)", padding: "8px 16px" }
|
|
2987
3570
|
},
|
|
2988
|
-
React11.createElement(
|
|
3571
|
+
React11.createElement(Button5, {
|
|
2989
3572
|
size: "xs",
|
|
2990
3573
|
variant: "clear",
|
|
2991
3574
|
color: "primary",
|
|
@@ -3005,25 +3588,25 @@ function SwarmDashboard() {
|
|
|
3005
3588
|
React11.createElement(
|
|
3006
3589
|
Flex10,
|
|
3007
3590
|
{ variant: "row-center-space-between-nowrap-8" },
|
|
3008
|
-
React11.createElement(
|
|
3591
|
+
React11.createElement(Typography10, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Provider"),
|
|
3009
3592
|
React11.createElement(
|
|
3010
3593
|
Flex10,
|
|
3011
3594
|
{ variant: "row-center-start-nowrap-4" },
|
|
3012
3595
|
React11.createElement(
|
|
3013
|
-
|
|
3596
|
+
Typography10,
|
|
3014
3597
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
3015
3598
|
providers.find((p) => p.envVarsSet)?.name ?? "None detected"
|
|
3016
3599
|
),
|
|
3017
|
-
providers.find((p) => p.envVarsSet) && React11.createElement(
|
|
3600
|
+
providers.find((p) => p.envVarsSet) && React11.createElement(Tag6, { size: "small", color: "info" }, "active")
|
|
3018
3601
|
)
|
|
3019
3602
|
),
|
|
3020
3603
|
// Trust
|
|
3021
3604
|
insights?.trust && React11.createElement(
|
|
3022
3605
|
Flex10,
|
|
3023
3606
|
{ variant: "row-center-space-between-nowrap-8" },
|
|
3024
|
-
React11.createElement(
|
|
3607
|
+
React11.createElement(Typography10, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Trust"),
|
|
3025
3608
|
React11.createElement(
|
|
3026
|
-
|
|
3609
|
+
Typography10,
|
|
3027
3610
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
3028
3611
|
`Phase ${insights.trust.phase} \xB7 ${insights.trust.score}/100`
|
|
3029
3612
|
)
|
|
@@ -3032,9 +3615,9 @@ function SwarmDashboard() {
|
|
|
3032
3615
|
insights?.health && React11.createElement(
|
|
3033
3616
|
Flex10,
|
|
3034
3617
|
{ variant: "row-center-space-between-nowrap-8" },
|
|
3035
|
-
React11.createElement(
|
|
3618
|
+
React11.createElement(Typography10, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Health"),
|
|
3036
3619
|
React11.createElement(
|
|
3037
|
-
|
|
3620
|
+
Typography10,
|
|
3038
3621
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
3039
3622
|
`${insights.health.overall}/100`
|
|
3040
3623
|
)
|
|
@@ -3043,12 +3626,12 @@ function SwarmDashboard() {
|
|
|
3043
3626
|
providers.length > 0 && React11.createElement(
|
|
3044
3627
|
Flex10,
|
|
3045
3628
|
{ variant: "column-stretch-start-nowrap-4" },
|
|
3046
|
-
React11.createElement(
|
|
3629
|
+
React11.createElement(Typography10, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Available Providers"),
|
|
3047
3630
|
React11.createElement(
|
|
3048
3631
|
Flex10,
|
|
3049
3632
|
{ variant: "row-center-start-wrap-4" },
|
|
3050
3633
|
...providers.map(
|
|
3051
|
-
(p) => React11.createElement(
|
|
3634
|
+
(p) => React11.createElement(Tag6, {
|
|
3052
3635
|
key: p.name,
|
|
3053
3636
|
size: "small",
|
|
3054
3637
|
color: p.envVarsSet ? "positive" : "secondary"
|
|
@@ -3064,7 +3647,7 @@ function SwarmDashboard() {
|
|
|
3064
3647
|
React11.createElement(
|
|
3065
3648
|
Flex10,
|
|
3066
3649
|
{ variant: "row-center-start-nowrap-8" },
|
|
3067
|
-
React11.createElement(
|
|
3650
|
+
React11.createElement(Button5, {
|
|
3068
3651
|
size: "xs",
|
|
3069
3652
|
variant: "outlined",
|
|
3070
3653
|
color: "secondary",
|
|
@@ -3085,7 +3668,7 @@ function SwarmDashboard() {
|
|
|
3085
3668
|
}
|
|
3086
3669
|
}
|
|
3087
3670
|
}, "Reset Config"),
|
|
3088
|
-
React11.createElement(
|
|
3671
|
+
React11.createElement(Button5, {
|
|
3089
3672
|
size: "xs",
|
|
3090
3673
|
variant: "outlined",
|
|
3091
3674
|
color: "danger",
|
|
@@ -3102,7 +3685,7 @@ function SwarmDashboard() {
|
|
|
3102
3685
|
if (!ok) return;
|
|
3103
3686
|
try {
|
|
3104
3687
|
const raw = await callTool("fw_weaver_reset_all", {});
|
|
3105
|
-
const data =
|
|
3688
|
+
const data = parseToolResult(raw);
|
|
3106
3689
|
toast5(`Full reset complete \u2014 ${data?.tasksCleared ?? 0} tasks, ${data?.profilesCleared ?? 0} profiles cleared`, { type: "success" });
|
|
3107
3690
|
refreshAll();
|
|
3108
3691
|
} catch (err) {
|