@synergenius/flow-weaver-pack-weaver 0.9.199 → 0.9.201

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 (181) hide show
  1. package/dist/ai-chat-provider.js +5 -5
  2. package/dist/ai-chat-provider.js.map +1 -1
  3. package/dist/bot/acceptance-merge.d.ts +21 -0
  4. package/dist/bot/acceptance-merge.d.ts.map +1 -0
  5. package/dist/bot/acceptance-merge.js +46 -0
  6. package/dist/bot/acceptance-merge.js.map +1 -0
  7. package/dist/bot/ai-client.d.ts +14 -2
  8. package/dist/bot/ai-client.d.ts.map +1 -1
  9. package/dist/bot/ai-client.js +71 -24
  10. package/dist/bot/ai-client.js.map +1 -1
  11. package/dist/bot/assistant-tools.js +3 -3
  12. package/dist/bot/assistant-tools.js.map +1 -1
  13. package/dist/bot/audit-logger.d.ts.map +1 -1
  14. package/dist/bot/audit-logger.js +34 -14
  15. package/dist/bot/audit-logger.js.map +1 -1
  16. package/dist/bot/audit-trail.d.ts +67 -0
  17. package/dist/bot/audit-trail.d.ts.map +1 -0
  18. package/dist/bot/audit-trail.js +153 -0
  19. package/dist/bot/audit-trail.js.map +1 -0
  20. package/dist/bot/behavior-defaults.d.ts +1 -1
  21. package/dist/bot/behavior-defaults.d.ts.map +1 -1
  22. package/dist/bot/behavior-defaults.js +7 -3
  23. package/dist/bot/behavior-defaults.js.map +1 -1
  24. package/dist/bot/capability-registry.d.ts +9 -0
  25. package/dist/bot/capability-registry.d.ts.map +1 -1
  26. package/dist/bot/capability-registry.js +81 -27
  27. package/dist/bot/capability-registry.js.map +1 -1
  28. package/dist/bot/capability-types.d.ts +10 -0
  29. package/dist/bot/capability-types.d.ts.map +1 -1
  30. package/dist/bot/cli-provider.d.ts.map +1 -1
  31. package/dist/bot/cli-provider.js +8 -7
  32. package/dist/bot/cli-provider.js.map +1 -1
  33. package/dist/bot/preflight.d.ts +48 -0
  34. package/dist/bot/preflight.d.ts.map +1 -0
  35. package/dist/bot/preflight.js +247 -0
  36. package/dist/bot/preflight.js.map +1 -0
  37. package/dist/bot/provider-shim.d.ts +74 -0
  38. package/dist/bot/provider-shim.d.ts.map +1 -0
  39. package/dist/bot/provider-shim.js +176 -0
  40. package/dist/bot/provider-shim.js.map +1 -0
  41. package/dist/bot/runner.d.ts +2 -0
  42. package/dist/bot/runner.d.ts.map +1 -1
  43. package/dist/bot/runner.js +60 -17
  44. package/dist/bot/runner.js.map +1 -1
  45. package/dist/bot/step-executor.d.ts.map +1 -1
  46. package/dist/bot/step-executor.js +72 -115
  47. package/dist/bot/step-executor.js.map +1 -1
  48. package/dist/bot/swarm-controller.d.ts +2 -0
  49. package/dist/bot/swarm-controller.d.ts.map +1 -1
  50. package/dist/bot/swarm-controller.js +92 -20
  51. package/dist/bot/swarm-controller.js.map +1 -1
  52. package/dist/bot/task-create-handler.d.ts +37 -0
  53. package/dist/bot/task-create-handler.d.ts.map +1 -0
  54. package/dist/bot/task-create-handler.js +124 -0
  55. package/dist/bot/task-create-handler.js.map +1 -0
  56. package/dist/bot/task-store.d.ts +1 -0
  57. package/dist/bot/task-store.d.ts.map +1 -1
  58. package/dist/bot/task-store.js +67 -0
  59. package/dist/bot/task-store.js.map +1 -1
  60. package/dist/bot/types.d.ts +1 -1
  61. package/dist/bot/types.d.ts.map +1 -1
  62. package/dist/bot/weaver-tools.d.ts.map +1 -1
  63. package/dist/bot/weaver-tools.js +7 -39
  64. package/dist/bot/weaver-tools.js.map +1 -1
  65. package/dist/node-types/agent-execute.d.ts +25 -8
  66. package/dist/node-types/agent-execute.d.ts.map +1 -1
  67. package/dist/node-types/agent-execute.js +89 -23
  68. package/dist/node-types/agent-execute.js.map +1 -1
  69. package/dist/node-types/bot-report.d.ts.map +1 -1
  70. package/dist/node-types/bot-report.js +24 -3
  71. package/dist/node-types/bot-report.js.map +1 -1
  72. package/dist/node-types/plan-task.d.ts +8 -17
  73. package/dist/node-types/plan-task.d.ts.map +1 -1
  74. package/dist/node-types/plan-task.js +217 -256
  75. package/dist/node-types/plan-task.js.map +1 -1
  76. package/dist/node-types/review-result.js +8 -6
  77. package/dist/node-types/review-result.js.map +1 -1
  78. package/dist/palindrome.d.ts +9 -0
  79. package/dist/palindrome.d.ts.map +1 -0
  80. package/dist/palindrome.js +14 -0
  81. package/dist/palindrome.js.map +1 -0
  82. package/dist/ui/approval-card.js +91 -82
  83. package/dist/ui/bot-activity.js +73 -56
  84. package/dist/ui/bot-config.js +48 -31
  85. package/dist/ui/bot-dashboard.js +52 -36
  86. package/dist/ui/bot-panel.js +230 -228
  87. package/dist/ui/bot-slot-card.js +100 -90
  88. package/dist/ui/bot-status.js +37 -15
  89. package/dist/ui/budget-bar.js +57 -31
  90. package/dist/ui/capability-editor.js +447 -378
  91. package/dist/ui/chat-task-result.js +78 -71
  92. package/dist/ui/decision-log.js +68 -81
  93. package/dist/ui/genesis-block.js +86 -95
  94. package/dist/ui/instance-stream-view.js +722 -0
  95. package/dist/ui/profile-card.js +96 -221
  96. package/dist/ui/profile-editor.js +532 -575
  97. package/dist/ui/settings-section.js +41 -45
  98. package/dist/ui/swarm-controls.js +212 -135
  99. package/dist/ui/swarm-dashboard.js +3992 -2715
  100. package/dist/ui/task-detail-view.js +415 -521
  101. package/dist/ui/task-editor.js +339 -390
  102. package/dist/ui/task-pool-list.js +60 -55
  103. package/dist/workflows/src/palindrome.d.ts +11 -0
  104. package/dist/workflows/src/palindrome.d.ts.map +1 -0
  105. package/dist/workflows/src/palindrome.js +16 -0
  106. package/dist/workflows/src/palindrome.js.map +1 -0
  107. package/dist/workflows/tests/palindrome.test.d.ts +2 -0
  108. package/dist/workflows/tests/palindrome.test.d.ts.map +1 -0
  109. package/dist/workflows/tests/palindrome.test.js +41 -0
  110. package/dist/workflows/tests/palindrome.test.js.map +1 -0
  111. package/dist/workflows/weaver-bot-batch.js +1 -1
  112. package/dist/workflows/weaver-bot-batch.js.map +1 -1
  113. package/dist/workflows/weaver-bot.js +1 -1
  114. package/dist/workflows/weaver-bot.js.map +1 -1
  115. package/flowweaver.manifest.json +1 -1
  116. package/package.json +8 -2
  117. package/src/ai-chat-provider.ts +5 -5
  118. package/src/bot/acceptance-merge.ts +62 -0
  119. package/src/bot/ai-client.ts +77 -21
  120. package/src/bot/assistant-tools.ts +3 -3
  121. package/src/bot/audit-logger.ts +42 -14
  122. package/src/bot/audit-trail.ts +211 -0
  123. package/src/bot/behavior-defaults.ts +7 -2
  124. package/src/bot/capability-registry.ts +84 -28
  125. package/src/bot/capability-types.ts +11 -0
  126. package/src/bot/cli-provider.ts +8 -7
  127. package/src/bot/preflight.ts +285 -0
  128. package/src/bot/provider-shim.ts +218 -0
  129. package/src/bot/runner.ts +68 -20
  130. package/src/bot/step-executor.ts +69 -127
  131. package/src/bot/swarm-controller.ts +94 -20
  132. package/src/bot/task-create-handler.ts +164 -0
  133. package/src/bot/task-store.ts +83 -0
  134. package/src/bot/types.ts +4 -1
  135. package/src/bot/weaver-tools.ts +7 -45
  136. package/src/node-types/agent-execute.ts +102 -16
  137. package/src/node-types/bot-report.ts +24 -3
  138. package/src/node-types/plan-task.ts +238 -280
  139. package/src/node-types/review-result.ts +8 -6
  140. package/src/palindrome.ts +14 -0
  141. package/src/ui/approval-card.tsx +78 -62
  142. package/src/ui/bot-activity.tsx +12 -10
  143. package/src/ui/bot-config.tsx +12 -10
  144. package/src/ui/bot-dashboard.tsx +13 -11
  145. package/src/ui/bot-panel.tsx +189 -171
  146. package/src/ui/bot-slot-card.tsx +125 -70
  147. package/src/ui/bot-status.tsx +4 -4
  148. package/src/ui/budget-bar.tsx +86 -25
  149. package/src/ui/capability-editor.tsx +392 -257
  150. package/src/ui/chat-task-result.tsx +81 -78
  151. package/src/ui/decision-log.tsx +76 -73
  152. package/src/ui/genesis-block.tsx +91 -61
  153. package/src/ui/instance-stream-view.tsx +861 -0
  154. package/src/ui/profile-card.tsx +195 -168
  155. package/src/ui/profile-editor.tsx +453 -370
  156. package/src/ui/settings-section.tsx +46 -39
  157. package/src/ui/swarm-controls.tsx +252 -123
  158. package/src/ui/swarm-dashboard.tsx +999 -466
  159. package/src/ui/task-detail-view.tsx +485 -428
  160. package/src/ui/task-editor.tsx +329 -271
  161. package/src/ui/task-pool-list.tsx +68 -62
  162. package/src/workflows/src/palindrome.ts +16 -0
  163. package/src/workflows/tests/palindrome.test.ts +49 -0
  164. package/src/workflows/weaver-bot-batch.ts +1 -1
  165. package/src/workflows/weaver-bot.ts +1 -1
  166. package/dist/ui/bot-constants.d.ts +0 -14
  167. package/dist/ui/bot-constants.d.ts.map +0 -1
  168. package/dist/ui/bot-constants.js +0 -189
  169. package/dist/ui/bot-constants.js.map +0 -1
  170. package/dist/ui/steer-api.d.ts +0 -7
  171. package/dist/ui/steer-api.d.ts.map +0 -1
  172. package/dist/ui/steer-api.js +0 -11
  173. package/dist/ui/steer-api.js.map +0 -1
  174. package/dist/ui/trace-to-timeline.d.ts +0 -91
  175. package/dist/ui/trace-to-timeline.d.ts.map +0 -1
  176. package/dist/ui/trace-to-timeline.js +0 -116
  177. package/dist/ui/trace-to-timeline.js.map +0 -1
  178. package/dist/ui/use-stream-timeline.d.ts +0 -50
  179. package/dist/ui/use-stream-timeline.d.ts.map +0 -1
  180. package/dist/ui/use-stream-timeline.js +0 -245
  181. package/dist/ui/use-stream-timeline.js.map +0 -1
@@ -7,15 +7,12 @@
7
7
  * - "Open Dashboard" button to launch the swarm-dashboard workspace
8
8
  *
9
9
  * Polls fw_weaver_swarm_status every 5s for live updates.
10
- *
11
- * Pattern: CommonJS require, React.createElement, module.exports, usePackWorkspace.
12
10
  */
13
- const React = require('react');
14
- const { useState, useEffect, useCallback, useRef } = React;
15
- const {
11
+ import React, { useState, useEffect, useCallback, useRef } from 'react';
12
+ import {
16
13
  Flex, Typography, Button, IconButton, Icon, EmptyState,
17
14
  ScrollArea, StatusIcon, usePackWorkspace,
18
- } = require('@fw/plugin-ui-kit');
15
+ } from '@fw/plugin-ui-kit';
19
16
 
20
17
  // ---------------------------------------------------------------------------
21
18
  // Types
@@ -112,7 +109,7 @@ function BotPanel() {
112
109
  return () => { mountedRef.current = false; };
113
110
  }, []);
114
111
 
115
- // ── Fetch swarm status ──────────────────────────────────────────
112
+ // -- Fetch swarm status --
116
113
  const fetchStatus = useCallback(async () => {
117
114
  try {
118
115
  setError(null);
@@ -136,7 +133,7 @@ function BotPanel() {
136
133
  return () => clearInterval(timer);
137
134
  }, [fetchStatus]);
138
135
 
139
- // ── Open dashboard ──────────────────────────────────────────────
136
+ // -- Open dashboard --
140
137
  const handleOpenDashboard = useCallback(() => {
141
138
  ctx.openWindow({
142
139
  type: 'custom',
@@ -152,197 +149,218 @@ function BotPanel() {
152
149
  } as Record<string, unknown>);
153
150
  }, [ctx, packId]);
154
151
 
155
- // ── Render ──────────────────────────────────────────────────────
152
+ // -- Render --
156
153
 
157
154
  // Header
158
- const header = React.createElement(Flex, {
159
- variant: 'row-center-space-between-nowrap-8',
160
- style: { padding: '8px 12px', borderBottom: '1px solid var(--color-border-default)', flexShrink: 0 },
161
- },
162
- React.createElement(Flex, { variant: 'row-center-start-nowrap-6' },
163
- React.createElement(Icon, { name: 'smartToy', size: 16, color: 'color-text-medium' }),
164
- React.createElement(Typography, { variant: 'caption-thick', color: 'color-text-high' }, 'Weaver'),
165
- ),
166
- React.createElement(IconButton, {
167
- icon: 'reset', size: 'xs', variant: 'clear',
168
- onClick: fetchStatus, title: 'Refresh',
169
- }),
155
+ const header = (
156
+ <Flex
157
+ variant="row-center-space-between-nowrap-8"
158
+ style={{ padding: '8px 12px', borderBottom: '1px solid var(--color-border-default)', flexShrink: 0 }}
159
+ >
160
+ <Flex variant="row-center-start-nowrap-6">
161
+ <Icon name="smartToy" size={16} color="color-text-medium" />
162
+ <Typography variant="caption-thick" color="color-text-high">Weaver</Typography>
163
+ </Flex>
164
+ <IconButton
165
+ icon="reset" size="xs" variant="clear"
166
+ onClick={fetchStatus} title="Refresh"
167
+ />
168
+ </Flex>
170
169
  );
171
170
 
172
171
  // Loading state
173
172
  if (loading) {
174
- return React.createElement(Flex, {
175
- variant: 'column-stretch-start-nowrap-0',
176
- style: { width: '100%', height: '100%' },
177
- },
178
- header,
179
- React.createElement(Flex, {
180
- variant: 'column-center-center-nowrap-8',
181
- style: { flex: 1 },
182
- },
183
- React.createElement(Typography, { variant: 'caption-regular', color: 'color-text-subtle' }, 'Loading swarm status...'),
184
- ),
173
+ return (
174
+ <Flex
175
+ variant="column-stretch-start-nowrap-0"
176
+ style={{ width: '100%', height: '100%' }}
177
+ >
178
+ {header}
179
+ <Flex
180
+ variant="column-center-center-nowrap-8"
181
+ style={{ flex: 1 }}
182
+ >
183
+ <Typography variant="caption-regular" color="color-text-subtle">Loading swarm status...</Typography>
184
+ </Flex>
185
+ </Flex>
185
186
  );
186
187
  }
187
188
 
188
189
  // Error state
189
190
  if (error) {
190
- return React.createElement(Flex, {
191
- variant: 'column-stretch-start-nowrap-0',
192
- style: { width: '100%', height: '100%' },
193
- },
194
- header,
195
- React.createElement(Flex, {
196
- variant: 'column-center-center-nowrap-8',
197
- style: { flex: 1 },
198
- },
199
- React.createElement(Typography, { variant: 'caption-regular', color: 'color-status-negative' }, error),
200
- React.createElement(Button, { size: 'xs', variant: 'outlined', onClick: fetchStatus }, 'Retry'),
201
- ),
191
+ return (
192
+ <Flex
193
+ variant="column-stretch-start-nowrap-0"
194
+ style={{ width: '100%', height: '100%' }}
195
+ >
196
+ {header}
197
+ <Flex
198
+ variant="column-center-center-nowrap-8"
199
+ style={{ flex: 1 }}
200
+ >
201
+ <Typography variant="caption-regular" color="color-status-negative">{error}</Typography>
202
+ <Button size="xs" variant="outlined" onClick={fetchStatus}>Retry</Button>
203
+ </Flex>
204
+ </Flex>
202
205
  );
203
206
  }
204
207
 
205
208
  // Swarm status indicator
206
209
  const swarmStatus = swarm?.status ?? 'idle';
207
210
 
208
- const statusRow = React.createElement(Flex, {
209
- variant: 'row-center-space-between-nowrap-8',
210
- style: { padding: '8px 12px', borderBottom: '1px solid var(--color-border-default)' },
211
- },
212
- React.createElement(Flex, { variant: 'row-center-start-nowrap-6' },
213
- React.createElement(StatusIcon, {
214
- status: statusToIconStatus(swarmStatus),
215
- size: 'sm',
216
- }),
217
- React.createElement(Typography, { variant: 'caption-thick', color: 'color-text-high' },
218
- statusLabel(swarmStatus),
219
- ),
220
- ),
221
- React.createElement(Button, {
222
- size: 'xs', variant: 'outlined', color: 'primary',
223
- onClick: handleOpenDashboard,
224
- }, 'Open Dashboard'),
211
+ const statusRow = (
212
+ <Flex
213
+ variant="row-center-space-between-nowrap-8"
214
+ style={{ padding: '8px 12px', borderBottom: '1px solid var(--color-border-default)' }}
215
+ >
216
+ <Flex variant="row-center-start-nowrap-6">
217
+ <StatusIcon
218
+ status={statusToIconStatus(swarmStatus)}
219
+ size="sm"
220
+ />
221
+ <Typography variant="caption-thick" color="color-text-high">
222
+ {statusLabel(swarmStatus)}
223
+ </Typography>
224
+ </Flex>
225
+ <Button
226
+ size="xs" variant="outlined" color="primary"
227
+ onClick={handleOpenDashboard}
228
+ >
229
+ Open Dashboard
230
+ </Button>
231
+ </Flex>
225
232
  );
226
233
 
227
234
  // Quick stats
228
- const statsRow = React.createElement(Flex, {
229
- variant: 'row-center-space-between-nowrap-8',
230
- style: { padding: '8px 12px', borderBottom: '1px solid var(--color-border-default)', backgroundColor: 'var(--color-surface-low)' },
231
- },
232
- React.createElement(Flex, { variant: 'column-center-center-nowrap-1' },
233
- React.createElement(Typography, { variant: 'smallCaption-thick', color: 'color-text-high' },
234
- String(swarm?.tasksCompleted ?? 0),
235
- ),
236
- React.createElement(Typography, { variant: 'smallCaption-regular', color: 'color-text-subtle' }, 'Done'),
237
- ),
238
- React.createElement(Flex, { variant: 'column-center-center-nowrap-1' },
239
- React.createElement(Typography, { variant: 'smallCaption-thick', color: 'color-text-high' },
240
- String(swarm?.runsIncomplete ?? 0),
241
- ),
242
- React.createElement(Typography, { variant: 'smallCaption-regular', color: 'color-text-subtle' }, 'Failed'),
243
- ),
244
- React.createElement(Flex, { variant: 'column-center-center-nowrap-1' },
245
- React.createElement(Typography, { variant: 'smallCaption-thick', color: 'color-text-high' },
246
- formatTokens(swarm?.totalTokensUsed ?? 0),
247
- ),
248
- React.createElement(Typography, { variant: 'smallCaption-regular', color: 'color-text-subtle' }, 'Tokens'),
249
- ),
250
- React.createElement(Flex, { variant: 'column-center-center-nowrap-1' },
251
- React.createElement(Typography, { variant: 'smallCaption-thick', color: 'color-text-high' },
252
- formatCost(swarm?.totalCost ?? 0),
253
- ),
254
- React.createElement(Typography, { variant: 'smallCaption-regular', color: 'color-text-subtle' }, 'Cost'),
255
- ),
235
+ const statsRow = (
236
+ <Flex
237
+ variant="row-center-space-between-nowrap-8"
238
+ style={{ padding: '8px 12px', borderBottom: '1px solid var(--color-border-default)', backgroundColor: 'var(--color-surface-low)' }}
239
+ >
240
+ <Flex variant="column-center-center-nowrap-1">
241
+ <Typography variant="smallCaption-thick" color="color-text-high">
242
+ {String(swarm?.tasksCompleted ?? 0)}
243
+ </Typography>
244
+ <Typography variant="smallCaption-regular" color="color-text-subtle">Done</Typography>
245
+ </Flex>
246
+ <Flex variant="column-center-center-nowrap-1">
247
+ <Typography variant="smallCaption-thick" color="color-text-high">
248
+ {String(swarm?.runsIncomplete ?? 0)}
249
+ </Typography>
250
+ <Typography variant="smallCaption-regular" color="color-text-subtle">Failed</Typography>
251
+ </Flex>
252
+ <Flex variant="column-center-center-nowrap-1">
253
+ <Typography variant="smallCaption-thick" color="color-text-high">
254
+ {formatTokens(swarm?.totalTokensUsed ?? 0)}
255
+ </Typography>
256
+ <Typography variant="smallCaption-regular" color="color-text-subtle">Tokens</Typography>
257
+ </Flex>
258
+ <Flex variant="column-center-center-nowrap-1">
259
+ <Typography variant="smallCaption-thick" color="color-text-high">
260
+ {formatCost(swarm?.totalCost ?? 0)}
261
+ </Typography>
262
+ <Typography variant="smallCaption-regular" color="color-text-subtle">Cost</Typography>
263
+ </Flex>
264
+ </Flex>
256
265
  );
257
266
 
258
267
  // Bot list
259
268
  const instanceEntries = Object.values(swarm?.instances ?? {}) as InstanceInfo[];
260
269
  const hasBots = instanceEntries.length > 0;
261
270
 
262
- const botCards = instanceEntries.map((inst: InstanceInfo) =>
263
- React.createElement(Flex, {
264
- key: inst.instanceId,
265
- variant: 'row-center-start-nowrap-8',
266
- style: { padding: '8px', borderRadius: 'var(--border-radius-regular)', border: '1px solid var(--color-border-default)' },
267
- },
268
- // Bot icon
269
- React.createElement(Flex, {
270
- variant: 'row-center-center-nowrap-0',
271
- style: {
272
- width: 26, height: 26,
273
- borderRadius: 'var(--border-radius-compact)',
274
- flexShrink: 0,
275
- background: 'var(--color-surface-low)',
276
- },
277
- },
278
- React.createElement(Icon, { name: 'smartToy', size: 14, color: 'color-text-medium' }),
279
- ),
280
-
281
- // Name + status + task
282
- React.createElement(Flex, {
283
- variant: 'column-start-start-nowrap-1',
284
- style: { flex: 1, minWidth: 0 },
285
- },
286
- React.createElement(Flex, { variant: 'row-center-start-nowrap-4' },
287
- React.createElement(Typography, {
288
- variant: 'caption-thick', color: 'color-text-high',
289
- }, inst.profileId ? `${inst.instanceId} (${inst.profileId})` : inst.instanceId),
290
- React.createElement(StatusIcon, {
291
- status: statusToIconStatus(inst.status),
292
- size: 'sm',
293
- }),
294
- React.createElement(Typography, {
295
- variant: 'smallCaption-regular', color: 'color-text-subtle',
296
- }, statusLabel(inst.status)),
297
- ),
298
- inst.currentTaskId ? React.createElement(Typography, {
299
- variant: 'smallCaption-regular', color: 'color-text-medium',
300
- truncate: true,
301
- }, `Task: ${inst.currentTaskId}`) : null,
302
- ),
303
-
304
- // Per-instance stats
305
- React.createElement(Flex, {
306
- variant: 'column-end-end-nowrap-1',
307
- style: { flexShrink: 0 },
308
- },
309
- React.createElement(Typography, { variant: 'smallCaption-regular', color: 'color-text-subtle' },
310
- formatTokens(inst.tokensUsed),
311
- ),
312
- React.createElement(Typography, { variant: 'smallCaption-regular', color: 'color-text-subtle' },
313
- formatCost(inst.cost),
314
- ),
315
- ),
316
- ),
271
+ const content = hasBots ? (
272
+ <ScrollArea style={{ flex: 1 }}>
273
+ <Flex
274
+ variant="column-stretch-start-nowrap-6"
275
+ style={{ padding: '8px 12px' }}
276
+ >
277
+ {instanceEntries.map((inst: InstanceInfo) => (
278
+ <Flex
279
+ key={inst.instanceId}
280
+ variant="row-center-start-nowrap-8"
281
+ style={{ padding: '8px', borderRadius: 'var(--border-radius-regular)', border: '1px solid var(--color-border-default)' }}
282
+ >
283
+ {/* Bot icon */}
284
+ <Flex
285
+ variant="row-center-center-nowrap-0"
286
+ style={{
287
+ width: 26, height: 26,
288
+ borderRadius: 'var(--border-radius-compact)',
289
+ flexShrink: 0,
290
+ background: 'var(--color-surface-low)',
291
+ }}
292
+ >
293
+ <Icon name="smartToy" size={14} color="color-text-medium" />
294
+ </Flex>
295
+
296
+ {/* Name + status + task */}
297
+ <Flex
298
+ variant="column-start-start-nowrap-1"
299
+ style={{ flex: 1, minWidth: 0 }}
300
+ >
301
+ <Flex variant="row-center-start-nowrap-4">
302
+ <Typography variant="caption-thick" color="color-text-high">
303
+ {inst.profileId ? `${inst.instanceId} (${inst.profileId})` : inst.instanceId}
304
+ </Typography>
305
+ <StatusIcon
306
+ status={statusToIconStatus(inst.status)}
307
+ size="sm"
308
+ />
309
+ <Typography variant="smallCaption-regular" color="color-text-subtle">
310
+ {statusLabel(inst.status)}
311
+ </Typography>
312
+ </Flex>
313
+ {inst.currentTaskId && (
314
+ <Typography
315
+ variant="smallCaption-regular" color="color-text-medium"
316
+ truncate={true}
317
+ >
318
+ Task: {inst.currentTaskId}
319
+ </Typography>
320
+ )}
321
+ </Flex>
322
+
323
+ {/* Per-instance stats */}
324
+ <Flex
325
+ variant="column-end-end-nowrap-1"
326
+ style={{ flexShrink: 0 }}
327
+ >
328
+ <Typography variant="smallCaption-regular" color="color-text-subtle">
329
+ {formatTokens(inst.tokensUsed)}
330
+ </Typography>
331
+ <Typography variant="smallCaption-regular" color="color-text-subtle">
332
+ {formatCost(inst.cost)}
333
+ </Typography>
334
+ </Flex>
335
+ </Flex>
336
+ ))}
337
+ </Flex>
338
+ </ScrollArea>
339
+ ) : (
340
+ <Flex
341
+ variant="column-center-center-nowrap-0"
342
+ style={{ flex: 1 }}
343
+ >
344
+ <EmptyState
345
+ icon="smartToy"
346
+ message={swarmStatus === 'idle' ? 'Idle' : 'No instances active'}
347
+ description="Open the dashboard to configure and start the swarm."
348
+ />
349
+ </Flex>
317
350
  );
318
351
 
319
- const content = hasBots
320
- ? React.createElement(ScrollArea, { style: { flex: 1 } },
321
- React.createElement(Flex, {
322
- variant: 'column-stretch-start-nowrap-6',
323
- style: { padding: '8px 12px' },
324
- }, ...botCards),
325
- )
326
- : React.createElement(Flex, {
327
- variant: 'column-center-center-nowrap-0',
328
- style: { flex: 1 },
329
- },
330
- React.createElement(EmptyState, {
331
- icon: 'smartToy',
332
- message: swarmStatus === 'idle' ? 'Idle' : 'No instances active',
333
- description: 'Open the dashboard to configure and start the swarm.',
334
- }),
335
- );
336
-
337
- return React.createElement(Flex, {
338
- variant: 'column-stretch-start-nowrap-0',
339
- style: { width: '100%', height: '100%', overflow: 'hidden' },
340
- },
341
- header,
342
- statusRow,
343
- statsRow,
344
- content,
352
+ return (
353
+ <Flex
354
+ variant="column-stretch-start-nowrap-0"
355
+ style={{ width: '100%', height: '100%', overflow: 'hidden' }}
356
+ >
357
+ {header}
358
+ {statusRow}
359
+ {statsRow}
360
+ {content}
361
+ </Flex>
345
362
  );
346
363
  }
347
364
 
348
- module.exports = BotPanel;
365
+ export { BotPanel };
366
+ export default BotPanel;
@@ -1,9 +1,13 @@
1
1
  /**
2
2
  * BotSlotCard — single row in the bot table for the swarm dashboard.
3
- * Displays bot name, status, current task, tokens, and cost in a table row layout.
3
+ * Displays bot name, status, current task, tokens, and cost in fixed-width columns.
4
+ *
5
+ * Uses styled components from @fw/plugin-theme for hover — zero inline styles.
6
+ * The swarm dashboard renders a column header row + BotSlotCard per instance.
4
7
  */
5
8
  import React from 'react';
6
9
  import { Flex, Typography, Icon, IconButton } from '@fw/plugin-ui-kit';
10
+ import { styled } from '@fw/plugin-theme';
7
11
 
8
12
  // ---------------------------------------------------------------------------
9
13
  // Types
@@ -27,11 +31,43 @@ interface BotSlotCardProps {
27
31
  botDisplayName?: string;
28
32
  botIcon?: string;
29
33
  botColor?: string;
34
+ onView?: (botId: string) => void;
30
35
  onPause?: (botId: string) => void;
31
36
  onResume?: (botId: string) => void;
32
37
  onStop?: (botId: string) => void;
33
38
  }
34
39
 
40
+ // ---------------------------------------------------------------------------
41
+ // Styled — row with CSS :hover, columns with fixed widths
42
+ // ---------------------------------------------------------------------------
43
+
44
+ const Row = styled.div({
45
+ display: 'flex',
46
+ alignItems: 'center',
47
+ gap: '$gap-tight',
48
+ padding: '6px 16px',
49
+ minHeight: '38px',
50
+ borderBottom: '1px solid $color-border-default',
51
+ transition: 'background-color 0.15s ease',
52
+ variants: {
53
+ clickable: {
54
+ true: {
55
+ cursor: 'pointer',
56
+ '&:hover': { backgroundColor: '$color-surface-hover' },
57
+ '&:active': { backgroundColor: '$color-surface-active' },
58
+ },
59
+ false: {},
60
+ },
61
+ },
62
+ });
63
+
64
+ const WorkerCol = styled.div({ width: '120px', flexShrink: 0 });
65
+ const BotCol = styled.div({ width: '110px', flexShrink: 0, display: 'flex', alignItems: 'center', gap: '4px' });
66
+ const StatusCol = styled.div({ width: '70px', flexShrink: 0 });
67
+ const TaskCol = styled.div({ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' });
68
+ const StatCol = styled.div({ width: '50px', flexShrink: 0, textAlign: 'right' });
69
+ const ActionsCol = styled.div({ width: '50px', flexShrink: 0 });
70
+
35
71
  // ---------------------------------------------------------------------------
36
72
  // Helpers
37
73
  // ---------------------------------------------------------------------------
@@ -58,80 +94,99 @@ function formatCost(n: number): string {
58
94
  // Component
59
95
  // ---------------------------------------------------------------------------
60
96
 
61
- function BotSlotCard({ bot, currentTaskTitle, profileName, botDisplayName, botIcon, botColor, onPause, onResume, onStop }: BotSlotCardProps) {
97
+ function BotSlotCard({ bot, currentTaskTitle, profileName, botDisplayName, botIcon, botColor, onView, onPause, onResume, onStop }: BotSlotCardProps) {
62
98
  const { botId, botName, status, currentTaskId, tokensUsed, cost } = bot;
63
99
  const isExecuting = status === 'executing';
64
100
  const isPaused = status === 'paused';
65
101
  const label = statusToLabel[status] ?? status;
66
102
  const taskText = isExecuting ? (currentTaskTitle || currentTaskId || '-') : '-';
67
-
68
- return React.createElement(Flex, {
69
- variant: 'row-center-start-nowrap-8',
70
- style: { padding: '6px 16px', minHeight: '38px', borderBottom: '1px solid var(--color-border-default)' },
71
- },
72
- // Instance name
73
- React.createElement(Typography, {
74
- variant: 'smallCaption-regular', color: 'color-text-high',
75
- style: { width: '120px', flexShrink: 0 },
76
- }, profileName ? `${profileName} #${botId.split('-').pop() ?? '0'}` : botName),
77
-
78
- // Bot (icon + name)
79
- React.createElement(Flex, {
80
- variant: 'row-center-start-nowrap-4',
81
- style: { width: '110px', flexShrink: 0, color: botColor ? `var(--${botColor})` : undefined },
82
- },
83
- React.createElement(Icon, { name: botIcon || 'smartToy', size: 12 }),
84
- React.createElement(Typography, {
85
- variant: 'smallCaption-regular', color: 'color-text-subtle',
86
- }, botDisplayName || '-'),
87
- ),
88
-
89
- // Status
90
- React.createElement(Typography, {
91
- variant: 'smallCaption-regular',
92
- color: isExecuting ? 'color-brand-main' : 'color-text-subtle',
93
- style: { width: '70px', flexShrink: 0 },
94
- }, label),
95
-
96
- // Current task
97
- React.createElement(Typography, {
98
- variant: 'smallCaption-regular',
99
- color: isExecuting ? 'color-text-medium' : 'color-text-subtle',
100
- style: { flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },
101
- }, taskText),
102
-
103
- // Tokens
104
- React.createElement(Typography, {
105
- variant: 'smallCaption-regular',
106
- color: 'color-text-subtle',
107
- style: { width: '50px', flexShrink: 0, textAlign: 'right' },
108
- }, formatTokens(tokensUsed)),
109
-
110
- // Cost
111
- React.createElement(Typography, {
112
- variant: 'smallCaption-regular',
113
- color: 'color-text-subtle',
114
- style: { width: '50px', flexShrink: 0, textAlign: 'right' },
115
- }, formatCost(cost)),
116
-
117
- // Actions
118
- React.createElement(Flex, {
119
- variant: 'row-center-end-nowrap-1',
120
- style: { width: '50px', flexShrink: 0 },
121
- },
122
- isExecuting && onPause && React.createElement(IconButton, {
123
- icon: 'pause', size: 'xs', variant: 'clear',
124
- onClick: () => onPause(botId), title: 'Pause',
125
- }),
126
- isPaused && onResume && React.createElement(IconButton, {
127
- icon: 'playArrow', size: 'xs', variant: 'clear',
128
- onClick: () => onResume(botId), title: 'Resume',
129
- }),
130
- (isExecuting || isPaused) && onStop && React.createElement(IconButton, {
131
- icon: 'stop', size: 'xs', variant: 'clear', color: 'danger',
132
- onClick: () => onStop(botId), title: 'Stop',
133
- }),
134
- ),
103
+ const clickable = isExecuting && onView;
104
+
105
+ return (
106
+ <Row
107
+ clickable={!!clickable}
108
+ onClick={clickable ? () => onView!(botId) : undefined}
109
+ >
110
+ <WorkerCol>
111
+ <Typography variant="smallCaption-regular" color="color-text-high">
112
+ {profileName ? `${profileName} #${botId.split('-').pop() ?? '0'}` : botName}
113
+ </Typography>
114
+ </WorkerCol>
115
+
116
+ <BotCol>
117
+ <Icon name={botIcon || 'smartToy'} size={12} color={botColor || 'color-text-subtle'} />
118
+ <Typography variant="smallCaption-regular" color="color-text-subtle">
119
+ {botDisplayName || '-'}
120
+ </Typography>
121
+ </BotCol>
122
+
123
+ <StatusCol>
124
+ <Typography
125
+ variant="smallCaption-regular"
126
+ color={isExecuting ? 'color-brand-main' : 'color-text-subtle'}
127
+ >
128
+ {label}
129
+ </Typography>
130
+ </StatusCol>
131
+
132
+ <TaskCol>
133
+ <Typography
134
+ variant="smallCaption-regular"
135
+ color={isExecuting ? 'color-text-medium' : 'color-text-subtle'}
136
+ truncate={true}
137
+ >
138
+ {taskText}
139
+ </Typography>
140
+ </TaskCol>
141
+
142
+ <StatCol>
143
+ <Typography variant="smallCaption-regular" color="color-text-subtle">
144
+ {formatTokens(tokensUsed)}
145
+ </Typography>
146
+ </StatCol>
147
+
148
+ <StatCol>
149
+ <Typography variant="smallCaption-regular" color="color-text-subtle">
150
+ {formatCost(cost)}
151
+ </Typography>
152
+ </StatCol>
153
+
154
+ <ActionsCol>
155
+ <Flex
156
+ variant="row-center-end-nowrap-1"
157
+ onClick={(e: { stopPropagation: () => void }) => e.stopPropagation()}
158
+ >
159
+ {isExecuting && onPause && (
160
+ <IconButton
161
+ icon="pause"
162
+ size="xs"
163
+ variant="clear"
164
+ onClick={() => onPause(botId)}
165
+ title="Pause"
166
+ />
167
+ )}
168
+ {isPaused && onResume && (
169
+ <IconButton
170
+ icon="playArrow"
171
+ size="xs"
172
+ variant="clear"
173
+ onClick={() => onResume(botId)}
174
+ title="Resume"
175
+ />
176
+ )}
177
+ {(isExecuting || isPaused) && onStop && (
178
+ <IconButton
179
+ icon="stop"
180
+ size="xs"
181
+ variant="clear"
182
+ color="danger"
183
+ onClick={() => onStop(botId)}
184
+ title="Stop"
185
+ />
186
+ )}
187
+ </Flex>
188
+ </ActionsCol>
189
+ </Row>
135
190
  );
136
191
  }
137
192