@synergenius/flow-weaver-pack-weaver 0.9.59 → 0.9.77

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 (217) 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 +351 -335
  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/assistant-tools.d.ts.map +1 -1
  14. package/dist/bot/assistant-tools.js +49 -33
  15. package/dist/bot/assistant-tools.js.map +1 -1
  16. package/dist/bot/async-mutex.d.ts +13 -0
  17. package/dist/bot/async-mutex.d.ts.map +1 -0
  18. package/dist/bot/async-mutex.js +37 -0
  19. package/dist/bot/async-mutex.js.map +1 -0
  20. package/dist/bot/bot-manager.d.ts +2 -2
  21. package/dist/bot/bot-manager.d.ts.map +1 -1
  22. package/dist/bot/bot-manager.js +3 -3
  23. package/dist/bot/bot-manager.js.map +1 -1
  24. package/dist/bot/bot-registry.js +2 -2
  25. package/dist/bot/bot-registry.js.map +1 -1
  26. package/dist/bot/conversation-store.d.ts +1 -0
  27. package/dist/bot/conversation-store.d.ts.map +1 -1
  28. package/dist/bot/conversation-store.js.map +1 -1
  29. package/dist/bot/dashboard.d.ts.map +1 -1
  30. package/dist/bot/dashboard.js +17 -8
  31. package/dist/bot/dashboard.js.map +1 -1
  32. package/dist/bot/improve-loop.js.map +1 -1
  33. package/dist/bot/index.d.ts +2 -4
  34. package/dist/bot/index.d.ts.map +1 -1
  35. package/dist/bot/index.js +1 -2
  36. package/dist/bot/index.js.map +1 -1
  37. package/dist/bot/instance-manager.d.ts +31 -0
  38. package/dist/bot/instance-manager.d.ts.map +1 -0
  39. package/dist/bot/instance-manager.js +115 -0
  40. package/dist/bot/instance-manager.js.map +1 -0
  41. package/dist/bot/orchestrator.d.ts +36 -0
  42. package/dist/bot/orchestrator.d.ts.map +1 -0
  43. package/dist/bot/orchestrator.js +176 -0
  44. package/dist/bot/orchestrator.js.map +1 -0
  45. package/dist/bot/profile-store.d.ts +36 -0
  46. package/dist/bot/profile-store.d.ts.map +1 -0
  47. package/dist/bot/profile-store.js +208 -0
  48. package/dist/bot/profile-store.js.map +1 -0
  49. package/dist/bot/profile-types.d.ts +126 -0
  50. package/dist/bot/profile-types.d.ts.map +1 -0
  51. package/dist/bot/profile-types.js +7 -0
  52. package/dist/bot/profile-types.js.map +1 -0
  53. package/dist/bot/run-store.d.ts.map +1 -1
  54. package/dist/bot/run-store.js +8 -0
  55. package/dist/bot/run-store.js.map +1 -1
  56. package/dist/bot/runner.d.ts +4 -0
  57. package/dist/bot/runner.d.ts.map +1 -1
  58. package/dist/bot/runner.js +5 -1
  59. package/dist/bot/runner.js.map +1 -1
  60. package/dist/bot/swarm-controller.d.ts +109 -0
  61. package/dist/bot/swarm-controller.d.ts.map +1 -0
  62. package/dist/bot/swarm-controller.js +640 -0
  63. package/dist/bot/swarm-controller.js.map +1 -0
  64. package/dist/bot/swarm-event-log.d.ts +28 -0
  65. package/dist/bot/swarm-event-log.d.ts.map +1 -0
  66. package/dist/bot/swarm-event-log.js +54 -0
  67. package/dist/bot/swarm-event-log.js.map +1 -0
  68. package/dist/bot/task-prompt-builder.d.ts +22 -0
  69. package/dist/bot/task-prompt-builder.d.ts.map +1 -0
  70. package/dist/bot/task-prompt-builder.js +240 -0
  71. package/dist/bot/task-prompt-builder.js.map +1 -0
  72. package/dist/bot/task-store.d.ts +21 -0
  73. package/dist/bot/task-store.d.ts.map +1 -0
  74. package/dist/bot/task-store.js +364 -0
  75. package/dist/bot/task-store.js.map +1 -0
  76. package/dist/bot/task-types.d.ts +79 -0
  77. package/dist/bot/task-types.d.ts.map +1 -0
  78. package/dist/bot/task-types.js +6 -0
  79. package/dist/bot/task-types.js.map +1 -0
  80. package/dist/bot/types.d.ts +8 -0
  81. package/dist/bot/types.d.ts.map +1 -1
  82. package/dist/cli-handlers.d.ts.map +1 -1
  83. package/dist/cli-handlers.js +79 -54
  84. package/dist/cli-handlers.js.map +1 -1
  85. package/dist/cli.d.ts +3 -0
  86. package/dist/cli.d.ts.map +1 -0
  87. package/dist/cli.js +749 -0
  88. package/dist/cli.js.map +1 -0
  89. package/dist/docs/docs/weaver-bot-usage.md +35 -18
  90. package/dist/docs/docs/weaver-config.md +20 -0
  91. package/dist/docs/docs/weaver-task-queue.md +31 -19
  92. package/dist/docs/weaver-config.md +15 -9
  93. package/dist/index.d.ts +2 -2
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +1 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/mcp-tools.d.ts +17 -0
  98. package/dist/mcp-tools.d.ts.map +1 -1
  99. package/dist/mcp-tools.js +98 -279
  100. package/dist/mcp-tools.js.map +1 -1
  101. package/dist/node-types/bot-report.d.ts.map +1 -1
  102. package/dist/node-types/bot-report.js +6 -24
  103. package/dist/node-types/bot-report.js.map +1 -1
  104. package/dist/node-types/orchestrator-dispatch.d.ts +17 -0
  105. package/dist/node-types/orchestrator-dispatch.d.ts.map +1 -0
  106. package/dist/node-types/orchestrator-dispatch.js +63 -0
  107. package/dist/node-types/orchestrator-dispatch.js.map +1 -0
  108. package/dist/node-types/orchestrator-load-state.d.ts +16 -0
  109. package/dist/node-types/orchestrator-load-state.d.ts.map +1 -0
  110. package/dist/node-types/orchestrator-load-state.js +60 -0
  111. package/dist/node-types/orchestrator-load-state.js.map +1 -0
  112. package/dist/node-types/orchestrator-route.d.ts +16 -0
  113. package/dist/node-types/orchestrator-route.d.ts.map +1 -0
  114. package/dist/node-types/orchestrator-route.js +28 -0
  115. package/dist/node-types/orchestrator-route.js.map +1 -0
  116. package/dist/node-types/receive-task.d.ts +2 -3
  117. package/dist/node-types/receive-task.d.ts.map +1 -1
  118. package/dist/node-types/receive-task.js +3 -48
  119. package/dist/node-types/receive-task.js.map +1 -1
  120. package/dist/templates/weaver-template.d.ts +11 -0
  121. package/dist/templates/weaver-template.d.ts.map +1 -0
  122. package/dist/templates/weaver-template.js +53 -0
  123. package/dist/templates/weaver-template.js.map +1 -0
  124. package/dist/ui/bot-activity.js +2 -2
  125. package/dist/ui/bot-constants.d.ts +14 -0
  126. package/dist/ui/bot-constants.d.ts.map +1 -0
  127. package/dist/ui/bot-constants.js +189 -0
  128. package/dist/ui/bot-constants.js.map +1 -0
  129. package/dist/ui/bot-panel.js +207 -245
  130. package/dist/ui/bot-slot-card.js +141 -0
  131. package/dist/ui/budget-bar.js +59 -0
  132. package/dist/ui/chat-task-result.js +178 -0
  133. package/dist/ui/decision-log.js +136 -0
  134. package/dist/ui/profile-card.js +158 -0
  135. package/dist/ui/profile-editor.js +597 -0
  136. package/dist/ui/swarm-controls.js +245 -0
  137. package/dist/ui/swarm-dashboard.js +3012 -0
  138. package/dist/ui/task-create-form.js +98 -0
  139. package/dist/ui/task-detail-view.js +1044 -0
  140. package/dist/ui/task-pool-list.js +156 -0
  141. package/dist/workflows/orchestrator.d.ts +21 -0
  142. package/dist/workflows/orchestrator.d.ts.map +1 -0
  143. package/dist/workflows/orchestrator.js +281 -0
  144. package/dist/workflows/orchestrator.js.map +1 -0
  145. package/dist/workflows/weaver-bot-session.d.ts +65 -0
  146. package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
  147. package/dist/workflows/weaver-bot-session.js +68 -0
  148. package/dist/workflows/weaver-bot-session.js.map +1 -0
  149. package/dist/workflows/weaver.d.ts +24 -0
  150. package/dist/workflows/weaver.d.ts.map +1 -0
  151. package/dist/workflows/weaver.js +28 -0
  152. package/dist/workflows/weaver.js.map +1 -0
  153. package/flowweaver.manifest.json +547 -133
  154. package/package.json +1 -1
  155. package/src/ai-chat-provider.ts +378 -371
  156. package/src/bot/ai-router.ts +132 -0
  157. package/src/bot/assistant-tools.ts +47 -29
  158. package/src/bot/async-mutex.ts +37 -0
  159. package/src/bot/bot-manager.ts +3 -3
  160. package/src/bot/bot-registry.ts +2 -2
  161. package/src/bot/conversation-store.ts +2 -1
  162. package/src/bot/dashboard.ts +17 -8
  163. package/src/bot/improve-loop.ts +6 -6
  164. package/src/bot/index.ts +2 -4
  165. package/src/bot/instance-manager.ts +128 -0
  166. package/src/bot/orchestrator.ts +244 -0
  167. package/src/bot/profile-store.ts +225 -0
  168. package/src/bot/profile-types.ts +141 -0
  169. package/src/bot/run-store.ts +8 -0
  170. package/src/bot/runner.ts +9 -1
  171. package/src/bot/swarm-controller.ts +780 -0
  172. package/src/bot/swarm-event-log.ts +57 -0
  173. package/src/bot/task-prompt-builder.ts +309 -0
  174. package/src/bot/task-store.ts +407 -0
  175. package/src/bot/task-types.ts +100 -0
  176. package/src/bot/types.ts +8 -0
  177. package/src/cli-handlers.ts +78 -53
  178. package/src/docs/weaver-bot-usage.md +35 -18
  179. package/src/docs/weaver-config.md +20 -0
  180. package/src/docs/weaver-task-queue.md +31 -19
  181. package/src/index.ts +5 -4
  182. package/src/mcp-tools.ts +129 -372
  183. package/src/node-types/bot-report.ts +6 -24
  184. package/src/node-types/orchestrator-dispatch.ts +71 -0
  185. package/src/node-types/orchestrator-load-state.ts +66 -0
  186. package/src/node-types/orchestrator-route.ts +33 -0
  187. package/src/node-types/receive-task.ts +3 -57
  188. package/src/ui/bot-activity.tsx +2 -2
  189. package/src/ui/bot-constants.ts +192 -0
  190. package/src/ui/bot-panel.tsx +213 -247
  191. package/src/ui/bot-slot-card.tsx +139 -0
  192. package/src/ui/budget-bar.tsx +30 -0
  193. package/src/ui/chat-task-result.tsx +236 -0
  194. package/src/ui/decision-log.tsx +148 -0
  195. package/src/ui/profile-card.tsx +157 -0
  196. package/src/ui/profile-editor.tsx +384 -0
  197. package/src/ui/swarm-controls.tsx +260 -0
  198. package/src/ui/swarm-dashboard.tsx +647 -0
  199. package/src/ui/task-create-form.tsx +87 -0
  200. package/src/ui/task-detail-view.tsx +841 -0
  201. package/src/ui/task-pool-list.tsx +187 -0
  202. package/src/workflows/orchestrator.ts +302 -0
  203. package/dist/docs/weaver-bot-usage.md +0 -34
  204. package/dist/docs/weaver-genesis.md +0 -32
  205. package/dist/docs/weaver-task-queue.md +0 -34
  206. package/dist/ui/bot-workspace.js +0 -1015
  207. package/dist/ui/chat-bot-result.js +0 -71
  208. package/dist/ui/queue-input.js +0 -82
  209. package/dist/ui/session-bar.js +0 -174
  210. package/src/bot/error-guide.ts +0 -4
  211. package/src/bot/retry-utils.ts +0 -4
  212. package/src/bot/session-state.ts +0 -116
  213. package/src/bot/task-queue.ts +0 -262
  214. package/src/ui/bot-workspace.tsx +0 -442
  215. package/src/ui/chat-bot-result.tsx +0 -81
  216. package/src/ui/queue-input.tsx +0 -56
  217. package/src/ui/session-bar.tsx +0 -157
@@ -9,11 +9,9 @@ var {
9
9
  Button,
10
10
  IconButton,
11
11
  Icon,
12
- Input,
13
12
  EmptyState,
14
13
  ScrollArea,
15
14
  StatusIcon,
16
- toast,
17
15
  usePackWorkspace
18
16
  } = require("@fw/plugin-ui-kit");
19
17
  function parseToolResult(raw) {
@@ -26,181 +24,113 @@ function parseToolResult(raw) {
26
24
  }
27
25
  return raw;
28
26
  }
29
- function validationIcon(state) {
30
- switch (state) {
31
- case "valid":
32
- return { icon: "checkCircle", color: "var(--color-success)" };
33
- case "invalid":
34
- return { icon: "error", color: "var(--color-danger)" };
35
- case "checking":
36
- return { icon: "sync", color: "var(--color-warning)" };
27
+ function statusToIconStatus(status) {
28
+ switch (status) {
29
+ case "executing":
30
+ case "running":
31
+ return "running";
32
+ case "paused":
33
+ return "pending";
34
+ case "stopped":
35
+ case "stopping":
36
+ return "failed";
37
37
  default:
38
- return { icon: "helpOutline", color: "var(--color-text-subtle)" };
38
+ return "completed";
39
39
  }
40
40
  }
41
+ function statusLabel(status) {
42
+ switch (status) {
43
+ case "executing":
44
+ return "Executing";
45
+ case "running":
46
+ return "Running";
47
+ case "paused":
48
+ return "Paused";
49
+ case "stopped":
50
+ return "Stopped";
51
+ case "stopping":
52
+ return "Stopping";
53
+ default:
54
+ return "Idle";
55
+ }
56
+ }
57
+ function formatTokens(n) {
58
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
59
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
60
+ return String(n);
61
+ }
62
+ function formatCost(n) {
63
+ return `$${n.toFixed(2)}`;
64
+ }
65
+ var POLL_INTERVAL_MS = 5e3;
41
66
  function BotPanel() {
42
67
  const ctx = usePackWorkspace();
43
- const { callTool, dispatchEvent } = ctx;
68
+ const { callTool } = ctx;
44
69
  const packId = ctx.packId;
45
- const [bots, setBots] = useState([]);
70
+ const [swarm, setSwarm] = useState(null);
46
71
  const [loading, setLoading] = useState(true);
47
72
  const [error, setError] = useState(null);
48
- const [showRegForm, setShowRegForm] = useState(false);
49
- const [regName, setRegName] = useState("");
50
- const [regFilePath, setRegFilePath] = useState("");
51
- const [regExport, setRegExport] = useState("");
52
- const [registering, setRegistering] = useState(false);
53
- const [confirmUnregId, setConfirmUnregId] = useState(null);
54
- const [unregistering, setUnregistering] = useState(false);
55
- const loadBots = useCallback(async () => {
73
+ const mountedRef = useRef(true);
74
+ useEffect(() => {
75
+ mountedRef.current = true;
76
+ return () => {
77
+ mountedRef.current = false;
78
+ };
79
+ }, []);
80
+ const fetchStatus = useCallback(async () => {
56
81
  try {
57
82
  setError(null);
58
- const raw = await callTool("fw_weaver_list_bots");
83
+ const raw = await callTool("fw_weaver_swarm_status", {});
84
+ if (!mountedRef.current) return;
59
85
  const parsed = parseToolResult(raw);
60
- if (Array.isArray(parsed)) {
61
- setBots(parsed);
62
- } else {
63
- setBots([]);
64
- }
86
+ if (parsed) setSwarm(parsed);
65
87
  } catch (err) {
66
- const msg = err instanceof Error ? err.message : "Failed to load bots";
88
+ if (!mountedRef.current) return;
89
+ const msg = err instanceof Error ? err.message : "Failed to load swarm status";
67
90
  setError(msg);
68
91
  } finally {
69
- setLoading(false);
92
+ if (mountedRef.current) setLoading(false);
70
93
  }
71
94
  }, [callTool]);
72
- const mountedRef = useRef(false);
73
95
  useEffect(() => {
74
- if (!mountedRef.current) {
75
- mountedRef.current = true;
76
- loadBots();
77
- }
78
- }, [loadBots]);
79
- const handleRegister = useCallback(async () => {
80
- if (!regName.trim() || !regFilePath.trim() || !regExport.trim()) return;
81
- setRegistering(true);
82
- try {
83
- await callTool("fw_weaver_register_bot", {
84
- name: regName.trim(),
85
- filePath: regFilePath.trim(),
86
- workflowExport: regExport.trim(),
87
- paramName: "taskJson"
88
- });
89
- toast("Bot registered", { type: "success" });
90
- setRegName("");
91
- setRegFilePath("");
92
- setRegExport("");
93
- setShowRegForm(false);
94
- await loadBots();
95
- } catch (err) {
96
- toast(err instanceof Error ? err.message : "Registration failed", { type: "error" });
97
- } finally {
98
- setRegistering(false);
99
- }
100
- }, [regName, regFilePath, regExport, callTool, loadBots]);
101
- const handleUnregister = useCallback(async (id) => {
102
- setUnregistering(true);
103
- try {
104
- await callTool("fw_weaver_unregister_bot", { id });
105
- toast("Bot unregistered", { type: "warning" });
106
- setConfirmUnregId(null);
107
- await loadBots();
108
- } catch (err) {
109
- toast(err instanceof Error ? err.message : "Unregister failed", { type: "error" });
110
- } finally {
111
- setUnregistering(false);
112
- }
113
- }, [callTool, loadBots]);
114
- const handleOpenWorkspace = useCallback((botId) => {
115
- dispatchEvent("fw:open-bot-workspace", { botId, packId, live: false });
116
- }, [dispatchEvent, packId]);
117
- const hasBots = bots.length > 0;
96
+ fetchStatus();
97
+ const timer = setInterval(fetchStatus, POLL_INTERVAL_MS);
98
+ return () => clearInterval(timer);
99
+ }, [fetchStatus]);
100
+ const handleOpenDashboard = useCallback(() => {
101
+ ctx.openWindow({
102
+ type: "custom",
103
+ title: "Swarm Dashboard",
104
+ icon: "dashboard",
105
+ contentType: "bot-workspace",
106
+ displayState: "docked",
107
+ dockZone: "center",
108
+ definitionId: "bot-workspace",
109
+ size: { width: 1e3, height: 700 },
110
+ singleton: true,
111
+ data: { packId }
112
+ });
113
+ }, [ctx, packId]);
118
114
  const header = React.createElement(
119
115
  Flex,
120
116
  {
121
- variant: "row-center-between-nowrap-8",
117
+ variant: "row-center-space-between-nowrap-8",
122
118
  style: { padding: "8px 12px", borderBottom: "1px solid var(--color-border-default)", flexShrink: 0 }
123
119
  },
124
120
  React.createElement(
125
121
  Flex,
126
122
  { variant: "row-center-start-nowrap-6" },
127
123
  React.createElement(Icon, { name: "smartToy", size: 16, color: "color-text-medium" }),
128
- React.createElement(Typography, { variant: "caption-thick", color: "color-text-high" }, "Bots")
124
+ React.createElement(Typography, { variant: "caption-thick", color: "color-text-high" }, "Swarm")
129
125
  ),
130
- React.createElement(
131
- Flex,
132
- { variant: "row-center-start-nowrap-4" },
133
- React.createElement(IconButton, {
134
- icon: "refresh",
135
- size: "xs",
136
- variant: "clear",
137
- onClick: loadBots,
138
- title: "Refresh"
139
- }),
140
- React.createElement(IconButton, {
141
- icon: "add",
142
- size: "xs",
143
- variant: "clear",
144
- onClick: () => setShowRegForm((v) => !v),
145
- title: "Register bot"
146
- })
147
- )
126
+ React.createElement(IconButton, {
127
+ icon: "reset",
128
+ size: "xs",
129
+ variant: "clear",
130
+ onClick: fetchStatus,
131
+ title: "Refresh"
132
+ })
148
133
  );
149
- const regForm = showRegForm ? React.createElement(
150
- Flex,
151
- {
152
- variant: "column-start-start-nowrap-8",
153
- style: {
154
- padding: "10px 12px",
155
- borderBottom: "1px solid var(--color-border-default)",
156
- backgroundColor: "var(--color-surface-low)"
157
- }
158
- },
159
- React.createElement(Typography, { variant: "smallCaption-thick", color: "color-text-medium" }, "Register Existing Workflow"),
160
- React.createElement(Input, {
161
- type: "text",
162
- size: "small",
163
- placeholder: "Bot name",
164
- value: regName,
165
- onChange: setRegName
166
- }),
167
- React.createElement(Input, {
168
- type: "text",
169
- size: "small",
170
- placeholder: "File path (e.g. my-bot.ts)",
171
- value: regFilePath,
172
- onChange: setRegFilePath
173
- }),
174
- React.createElement(Input, {
175
- type: "text",
176
- size: "small",
177
- placeholder: "Export name (e.g. myBot)",
178
- value: regExport,
179
- onChange: setRegExport
180
- }),
181
- React.createElement(
182
- Flex,
183
- { variant: "row-center-start-nowrap-6" },
184
- React.createElement(Button, {
185
- size: "xs",
186
- variant: "fill",
187
- color: "primary",
188
- onClick: handleRegister,
189
- disabled: registering || !regName.trim() || !regFilePath.trim() || !regExport.trim()
190
- }, registering ? "Registering..." : "Register"),
191
- React.createElement(Button, {
192
- size: "xs",
193
- variant: "clear",
194
- color: "secondary",
195
- onClick: () => {
196
- setShowRegForm(false);
197
- setRegName("");
198
- setRegFilePath("");
199
- setRegExport("");
200
- }
201
- }, "Cancel")
202
- )
203
- ) : null;
204
134
  if (loading) {
205
135
  return React.createElement(
206
136
  Flex,
@@ -213,9 +143,9 @@ function BotPanel() {
213
143
  Flex,
214
144
  {
215
145
  variant: "column-center-center-nowrap-8",
216
- style: { flex: 1, padding: "24px" }
146
+ style: { flex: 1 }
217
147
  },
218
- React.createElement(Typography, { variant: "caption-regular", color: "color-text-subtle" }, "Loading bots...")
148
+ React.createElement(Typography, { variant: "caption-regular", color: "color-text-subtle" }, "Loading swarm status...")
219
149
  )
220
150
  );
221
151
  }
@@ -231,60 +161,113 @@ function BotPanel() {
231
161
  Flex,
232
162
  {
233
163
  variant: "column-center-center-nowrap-8",
234
- style: { flex: 1, padding: "24px" }
164
+ style: { flex: 1 }
235
165
  },
236
- React.createElement(Typography, { variant: "caption-regular", color: "color-danger" }, error),
237
- React.createElement(Button, { size: "xs", variant: "outlined", onClick: loadBots }, "Retry")
166
+ React.createElement(Typography, { variant: "caption-regular", color: "color-status-negative" }, error),
167
+ React.createElement(Button, { size: "xs", variant: "outlined", onClick: fetchStatus }, "Retry")
238
168
  )
239
169
  );
240
170
  }
241
- const botCards = bots.map((bot) => {
242
- const vState = bot.validation?.state;
243
- const vInfo = validationIcon(vState);
244
- const isConfirming = confirmUnregId === bot.id;
245
- return React.createElement(
171
+ const swarmStatus = swarm?.status ?? "idle";
172
+ const statusRow = React.createElement(
173
+ Flex,
174
+ {
175
+ variant: "row-center-space-between-nowrap-8",
176
+ style: { padding: "8px 12px", borderBottom: "1px solid var(--color-border-default)" }
177
+ },
178
+ React.createElement(
179
+ Flex,
180
+ { variant: "row-center-start-nowrap-6" },
181
+ React.createElement(StatusIcon, {
182
+ status: statusToIconStatus(swarmStatus),
183
+ size: "sm"
184
+ }),
185
+ React.createElement(
186
+ Typography,
187
+ { variant: "caption-thick", color: "color-text-high" },
188
+ statusLabel(swarmStatus)
189
+ )
190
+ ),
191
+ React.createElement(Button, {
192
+ size: "xs",
193
+ variant: "outlined",
194
+ color: "primary",
195
+ onClick: handleOpenDashboard
196
+ }, "Open Dashboard")
197
+ );
198
+ const statsRow = React.createElement(
199
+ Flex,
200
+ {
201
+ variant: "row-center-space-between-nowrap-8",
202
+ style: { padding: "8px 12px", borderBottom: "1px solid var(--color-border-default)", backgroundColor: "var(--color-surface-low)" }
203
+ },
204
+ React.createElement(
205
+ Flex,
206
+ { variant: "column-center-center-nowrap-1" },
207
+ React.createElement(
208
+ Typography,
209
+ { variant: "smallCaption-thick", color: "color-text-high" },
210
+ String(swarm?.tasksCompleted ?? 0)
211
+ ),
212
+ React.createElement(Typography, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Done")
213
+ ),
214
+ React.createElement(
215
+ Flex,
216
+ { variant: "column-center-center-nowrap-1" },
217
+ React.createElement(
218
+ Typography,
219
+ { variant: "smallCaption-thick", color: "color-text-high" },
220
+ String(swarm?.tasksFailed ?? 0)
221
+ ),
222
+ React.createElement(Typography, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Failed")
223
+ ),
224
+ React.createElement(
225
+ Flex,
226
+ { variant: "column-center-center-nowrap-1" },
227
+ React.createElement(
228
+ Typography,
229
+ { variant: "smallCaption-thick", color: "color-text-high" },
230
+ formatTokens(swarm?.totalTokensUsed ?? 0)
231
+ ),
232
+ React.createElement(Typography, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Tokens")
233
+ ),
234
+ React.createElement(
235
+ Flex,
236
+ { variant: "column-center-center-nowrap-1" },
237
+ React.createElement(
238
+ Typography,
239
+ { variant: "smallCaption-thick", color: "color-text-high" },
240
+ formatCost(swarm?.totalCost ?? 0)
241
+ ),
242
+ React.createElement(Typography, { variant: "smallCaption-regular", color: "color-text-subtle" }, "Cost")
243
+ )
244
+ );
245
+ const instanceEntries = Object.values(swarm?.instances ?? {});
246
+ const hasBots = instanceEntries.length > 0;
247
+ const botCards = instanceEntries.map(
248
+ (inst) => React.createElement(
246
249
  Flex,
247
250
  {
248
- key: bot.id,
251
+ key: inst.instanceId,
249
252
  variant: "row-center-start-nowrap-8",
250
- style: {
251
- padding: "7px 8px",
252
- borderRadius: "var(--border-radius-secondary)",
253
- border: "1px solid var(--color-border-default)",
254
- cursor: "pointer",
255
- transition: "background-color 0.12s"
256
- },
257
- onClick: () => handleOpenWorkspace(bot.id),
258
- onMouseEnter: (e) => {
259
- e.currentTarget.style.backgroundColor = "var(--color-surface-raised)";
260
- },
261
- onMouseLeave: (e) => {
262
- e.currentTarget.style.backgroundColor = "";
263
- }
253
+ style: { padding: "8px", borderRadius: "var(--border-radius-regular)", border: "1px solid var(--color-border-default)" }
264
254
  },
265
- // Icon
255
+ // Bot icon
266
256
  React.createElement(
267
- "div",
257
+ Flex,
268
258
  {
259
+ variant: "row-center-center-nowrap-0",
269
260
  style: {
270
- width: "26px",
271
- height: "26px",
261
+ width: 26,
262
+ height: 26,
272
263
  borderRadius: "var(--border-radius-compact)",
273
- display: "flex",
274
- alignItems: "center",
275
- justifyContent: "center",
276
264
  flexShrink: 0,
277
- background: bot.color ? `color-mix(in srgb, ${bot.color} 14%, transparent)` : "var(--color-surface-low)"
265
+ background: "var(--color-surface-low)"
278
266
  }
279
267
  },
280
- React.createElement(Icon, {
281
- name: bot.icon || "smartToy",
282
- size: 14,
283
- color: bot.color ? void 0 : "color-text-medium",
284
- style: bot.color ? { color: bot.color } : void 0
285
- })
268
+ React.createElement(Icon, { name: "smartToy", size: 14, color: "color-text-medium" })
286
269
  ),
287
- // Name + description
270
+ // Name + status + task
288
271
  React.createElement(
289
272
  Flex,
290
273
  {
@@ -296,82 +279,60 @@ function BotPanel() {
296
279
  { variant: "row-center-start-nowrap-4" },
297
280
  React.createElement(Typography, {
298
281
  variant: "caption-thick",
299
- color: "color-text-high",
300
- style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }
301
- }, bot.name),
302
- // Validation badge
303
- React.createElement(Icon, {
304
- name: vInfo.icon,
305
- size: 12,
306
- style: { color: vInfo.color, flexShrink: 0 }
307
- })
282
+ color: "color-text-high"
283
+ }, `${inst.profileId} #${inst.index}`),
284
+ React.createElement(StatusIcon, {
285
+ status: statusToIconStatus(inst.status),
286
+ size: "sm"
287
+ }),
288
+ React.createElement(Typography, {
289
+ variant: "smallCaption-regular",
290
+ color: "color-text-subtle"
291
+ }, statusLabel(inst.status))
308
292
  ),
309
- bot.description ? React.createElement(Typography, {
293
+ inst.currentTaskId ? React.createElement(Typography, {
310
294
  variant: "smallCaption-regular",
311
295
  color: "color-text-medium",
312
- style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }
313
- }, bot.description) : null
296
+ truncate: true
297
+ }, `Task: ${inst.currentTaskId}`) : null
314
298
  ),
315
- // Actions
316
- isConfirming ? React.createElement(
317
- Flex,
318
- {
319
- variant: "row-center-start-nowrap-4",
320
- onClick: (e) => e.stopPropagation()
321
- },
322
- React.createElement(Button, {
323
- size: "xs",
324
- variant: "fill",
325
- color: "danger",
326
- onClick: () => handleUnregister(bot.id),
327
- disabled: unregistering
328
- }, unregistering ? "..." : "Yes"),
329
- React.createElement(Button, {
330
- size: "xs",
331
- variant: "clear",
332
- color: "secondary",
333
- onClick: () => setConfirmUnregId(null)
334
- }, "No")
335
- ) : React.createElement(
299
+ // Per-instance stats
300
+ React.createElement(
336
301
  Flex,
337
302
  {
338
- variant: "row-center-start-nowrap-2",
339
- onClick: (e) => e.stopPropagation()
303
+ variant: "column-end-end-nowrap-1",
304
+ style: { flexShrink: 0 }
340
305
  },
341
- React.createElement(IconButton, {
342
- icon: "openInNew",
343
- size: "xs",
344
- variant: "clear",
345
- onClick: () => handleOpenWorkspace(bot.id),
346
- title: "Open workspace"
347
- }),
348
- React.createElement(IconButton, {
349
- icon: "close",
350
- size: "xs",
351
- variant: "clear",
352
- onClick: () => setConfirmUnregId(bot.id),
353
- title: "Unregister"
354
- })
306
+ React.createElement(
307
+ Typography,
308
+ { variant: "smallCaption-regular", color: "color-text-subtle" },
309
+ formatTokens(inst.tokensUsed)
310
+ ),
311
+ React.createElement(
312
+ Typography,
313
+ { variant: "smallCaption-regular", color: "color-text-subtle" },
314
+ formatCost(inst.cost)
315
+ )
355
316
  )
356
- );
357
- });
317
+ )
318
+ );
358
319
  const content = hasBots ? React.createElement(
359
320
  ScrollArea,
360
321
  { style: { flex: 1 } },
361
322
  React.createElement(Flex, {
362
- variant: "column-start-start-nowrap-4",
323
+ variant: "column-stretch-start-nowrap-6",
363
324
  style: { padding: "8px 12px" }
364
325
  }, ...botCards)
365
326
  ) : React.createElement(
366
327
  Flex,
367
328
  {
368
329
  variant: "column-center-center-nowrap-0",
369
- style: { flex: 1, padding: "24px" }
330
+ style: { flex: 1 }
370
331
  },
371
332
  React.createElement(EmptyState, {
372
333
  icon: "smartToy",
373
- message: "No bots registered",
374
- description: "Register an existing workflow or ask the AI assistant to create one."
334
+ message: swarmStatus === "idle" ? "Swarm idle" : "No bots active",
335
+ description: "Open the dashboard to configure and start the swarm."
375
336
  })
376
337
  );
377
338
  return React.createElement(
@@ -381,7 +342,8 @@ function BotPanel() {
381
342
  style: { width: "100%", height: "100%", overflow: "hidden" }
382
343
  },
383
344
  header,
384
- regForm,
345
+ statusRow,
346
+ statsRow,
385
347
  content
386
348
  );
387
349
  }