@contractspec/example.agent-console 3.7.6 → 3.8.2

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 (288) hide show
  1. package/.turbo/turbo-build.log +126 -105
  2. package/AGENTS.md +52 -31
  3. package/CHANGELOG.md +29 -0
  4. package/README.md +112 -83
  5. package/dist/agent/agent.event.js +1 -1
  6. package/dist/agent/agent.handler.d.ts +3 -0
  7. package/dist/agent/agent.handler.js +730 -1
  8. package/dist/agent/agent.operation.js +1 -1
  9. package/dist/agent/index.d.ts +5 -5
  10. package/dist/agent/index.js +74 -73
  11. package/dist/agent.feature.js +179 -0
  12. package/dist/browser/agent/agent.event.js +1 -1
  13. package/dist/browser/agent/agent.handler.js +730 -1
  14. package/dist/browser/agent/agent.operation.js +1 -1
  15. package/dist/browser/agent/index.js +74 -73
  16. package/dist/browser/agent.feature.js +179 -0
  17. package/dist/browser/docs/agent-console.docblock.js +11 -8
  18. package/dist/browser/docs/index.js +11 -8
  19. package/dist/browser/example.js +2 -3
  20. package/dist/browser/handlers/agent.handlers.js +1883 -2
  21. package/dist/browser/handlers/index.js +2142 -8
  22. package/dist/browser/index.js +4075 -3161
  23. package/dist/browser/presentations/index.js +51 -51
  24. package/dist/browser/run/index.js +380 -374
  25. package/dist/browser/run/run.event.js +2 -2
  26. package/dist/browser/run/run.handler.js +666 -1
  27. package/dist/browser/run/run.presentation.js +2 -2
  28. package/dist/browser/shared/index.js +293 -1
  29. package/dist/browser/shared/mock-runs.js +5 -0
  30. package/dist/browser/tool/index.js +161 -161
  31. package/dist/browser/tool/tool.event.js +1 -1
  32. package/dist/browser/tool/tool.handler.js +479 -3
  33. package/dist/browser/tool/tool.presentation.js +2 -2
  34. package/dist/browser/ui/AgentDashboard.js +1816 -931
  35. package/dist/browser/ui/AgentDashboard.visualizations.js +217 -0
  36. package/dist/browser/ui/AgentRunList.js +360 -128
  37. package/dist/browser/ui/AgentToolRegistry.js +9 -9
  38. package/dist/browser/ui/hooks/index.js +611 -161
  39. package/dist/browser/ui/hooks/useAgentList.js +1 -1
  40. package/dist/browser/ui/hooks/useAgentMutations.js +444 -9
  41. package/dist/browser/ui/hooks/useRunList.js +26 -11
  42. package/dist/browser/ui/hooks/useToolList.js +1 -1
  43. package/dist/browser/ui/index.js +2161 -1258
  44. package/dist/browser/ui/modals/AgentActionsModal.js +13 -13
  45. package/dist/browser/ui/modals/CreateAgentModal.js +15 -15
  46. package/dist/browser/ui/modals/index.js +297 -297
  47. package/dist/browser/ui/renderers/agent-list.markdown.js +14 -5
  48. package/dist/browser/ui/renderers/agent-list.renderer.js +7 -7
  49. package/dist/browser/ui/renderers/dashboard.markdown.js +207 -36
  50. package/dist/browser/ui/renderers/index.js +359 -163
  51. package/dist/browser/ui/renderers/run-list.markdown.js +9 -4
  52. package/dist/browser/ui/renderers/tool-registry.markdown.js +15 -4
  53. package/dist/browser/ui/views/AgentListView.js +7 -7
  54. package/dist/browser/ui/views/RunDataTable.js +326 -0
  55. package/dist/browser/ui/views/RunListView.js +360 -128
  56. package/dist/browser/ui/views/ToolRegistryView.js +9 -9
  57. package/dist/browser/ui/views/index.js +478 -246
  58. package/dist/browser/ui/views/run-data-table.columns.js +271 -0
  59. package/dist/browser/ui/views/run-list.shared.js +177 -0
  60. package/dist/browser/visualizations/catalog.js +134 -0
  61. package/dist/browser/visualizations/index.js +187 -0
  62. package/dist/browser/visualizations/selectors.js +181 -0
  63. package/dist/docs/agent-console.docblock.js +11 -8
  64. package/dist/docs/index.js +11 -8
  65. package/dist/example.js +2 -3
  66. package/dist/example.test.d.ts +1 -0
  67. package/dist/handlers/agent.handlers.d.ts +2 -0
  68. package/dist/handlers/agent.handlers.js +1883 -2
  69. package/dist/handlers/index.d.ts +2 -4
  70. package/dist/handlers/index.js +2142 -8
  71. package/dist/handlers/mock-handlers.test.d.ts +1 -0
  72. package/dist/index.d.ts +6 -4
  73. package/dist/index.js +4075 -3161
  74. package/dist/node/agent/agent.event.js +1 -1
  75. package/dist/node/agent/agent.handler.js +730 -1
  76. package/dist/node/agent/agent.operation.js +1 -1
  77. package/dist/node/agent/index.js +74 -73
  78. package/dist/node/agent.feature.js +179 -0
  79. package/dist/node/docs/agent-console.docblock.js +11 -8
  80. package/dist/node/docs/index.js +11 -8
  81. package/dist/node/example.js +2 -3
  82. package/dist/node/handlers/agent.handlers.js +1883 -2
  83. package/dist/node/handlers/index.js +2142 -8
  84. package/dist/node/index.js +4075 -3161
  85. package/dist/node/presentations/index.js +51 -51
  86. package/dist/node/run/index.js +380 -374
  87. package/dist/node/run/run.event.js +2 -2
  88. package/dist/node/run/run.handler.js +666 -1
  89. package/dist/node/run/run.presentation.js +2 -2
  90. package/dist/node/shared/index.js +293 -1
  91. package/dist/node/shared/mock-runs.js +5 -0
  92. package/dist/node/tool/index.js +161 -161
  93. package/dist/node/tool/tool.event.js +1 -1
  94. package/dist/node/tool/tool.handler.js +479 -3
  95. package/dist/node/tool/tool.presentation.js +2 -2
  96. package/dist/node/ui/AgentDashboard.js +1816 -931
  97. package/dist/node/ui/AgentDashboard.visualizations.js +217 -0
  98. package/dist/node/ui/AgentRunList.js +360 -128
  99. package/dist/node/ui/AgentToolRegistry.js +9 -9
  100. package/dist/node/ui/hooks/index.js +611 -161
  101. package/dist/node/ui/hooks/useAgentList.js +1 -1
  102. package/dist/node/ui/hooks/useAgentMutations.js +444 -9
  103. package/dist/node/ui/hooks/useRunList.js +26 -11
  104. package/dist/node/ui/hooks/useToolList.js +1 -1
  105. package/dist/node/ui/index.js +2161 -1258
  106. package/dist/node/ui/modals/AgentActionsModal.js +13 -13
  107. package/dist/node/ui/modals/CreateAgentModal.js +15 -15
  108. package/dist/node/ui/modals/index.js +297 -297
  109. package/dist/node/ui/renderers/agent-list.markdown.js +14 -5
  110. package/dist/node/ui/renderers/agent-list.renderer.js +7 -7
  111. package/dist/node/ui/renderers/dashboard.markdown.js +207 -36
  112. package/dist/node/ui/renderers/index.js +359 -163
  113. package/dist/node/ui/renderers/run-list.markdown.js +9 -4
  114. package/dist/node/ui/renderers/tool-registry.markdown.js +15 -4
  115. package/dist/node/ui/views/AgentListView.js +7 -7
  116. package/dist/node/ui/views/RunDataTable.js +326 -0
  117. package/dist/node/ui/views/RunListView.js +360 -128
  118. package/dist/node/ui/views/ToolRegistryView.js +9 -9
  119. package/dist/node/ui/views/index.js +478 -246
  120. package/dist/node/ui/views/run-data-table.columns.js +271 -0
  121. package/dist/node/ui/views/run-list.shared.js +177 -0
  122. package/dist/node/visualizations/catalog.js +134 -0
  123. package/dist/node/visualizations/index.js +187 -0
  124. package/dist/node/visualizations/selectors.js +181 -0
  125. package/dist/presentations/index.d.ts +3 -5
  126. package/dist/presentations/index.js +51 -51
  127. package/dist/proof/index.d.ts +2 -0
  128. package/dist/proof/meetup-proof.d.ts +10 -0
  129. package/dist/proof/meetup-proof.runtime.d.ts +22 -0
  130. package/dist/proof/meetup-proof.scenario.d.ts +2 -0
  131. package/dist/proof/meetup-proof.suite.d.ts +1 -0
  132. package/dist/proof/meetup-proof.test.d.ts +1 -0
  133. package/dist/run/index.d.ts +7 -7
  134. package/dist/run/index.js +380 -374
  135. package/dist/run/run.event.js +2 -2
  136. package/dist/run/run.handler.d.ts +7 -0
  137. package/dist/run/run.handler.js +666 -1
  138. package/dist/run/run.presentation.js +2 -2
  139. package/dist/shared/demo-dashboard-data.d.ts +16 -0
  140. package/dist/shared/demo-runtime-seed.d.ts +17 -0
  141. package/dist/shared/demo-runtime.d.ts +8 -0
  142. package/dist/shared/demo-runtime.test.d.ts +1 -0
  143. package/dist/shared/index.d.ts +4 -1
  144. package/dist/shared/index.js +293 -1
  145. package/dist/shared/mock-runs.d.ts +4 -0
  146. package/dist/shared/mock-runs.js +5 -0
  147. package/dist/tool/index.d.ts +7 -7
  148. package/dist/tool/index.js +161 -161
  149. package/dist/tool/tool.event.js +1 -1
  150. package/dist/tool/tool.handler.d.ts +3 -0
  151. package/dist/tool/tool.handler.js +479 -3
  152. package/dist/tool/tool.presentation.js +2 -2
  153. package/dist/ui/AgentDashboard.js +1816 -931
  154. package/dist/ui/AgentDashboard.sandbox.test.d.ts +1 -0
  155. package/dist/ui/AgentDashboard.visualizations.d.ts +4 -0
  156. package/dist/ui/AgentDashboard.visualizations.js +218 -0
  157. package/dist/ui/AgentRunList.js +360 -128
  158. package/dist/ui/AgentToolRegistry.js +9 -9
  159. package/dist/ui/hooks/index.d.ts +4 -4
  160. package/dist/ui/hooks/index.js +611 -161
  161. package/dist/ui/hooks/useAgentList.d.ts +5 -0
  162. package/dist/ui/hooks/useAgentList.js +1 -1
  163. package/dist/ui/hooks/useAgentMutations.d.ts +9 -2
  164. package/dist/ui/hooks/useAgentMutations.js +444 -9
  165. package/dist/ui/hooks/useRunList.d.ts +13 -2
  166. package/dist/ui/hooks/useRunList.js +26 -11
  167. package/dist/ui/hooks/useToolList.d.ts +5 -0
  168. package/dist/ui/hooks/useToolList.js +1 -1
  169. package/dist/ui/index.d.ts +3 -3
  170. package/dist/ui/index.js +2161 -1258
  171. package/dist/ui/modals/AgentActionsModal.js +13 -13
  172. package/dist/ui/modals/CreateAgentModal.js +15 -15
  173. package/dist/ui/modals/index.d.ts +1 -1
  174. package/dist/ui/modals/index.js +297 -297
  175. package/dist/ui/renderers/agent-list.markdown.d.ts +5 -0
  176. package/dist/ui/renderers/agent-list.markdown.js +14 -5
  177. package/dist/ui/renderers/agent-list.renderer.js +7 -7
  178. package/dist/ui/renderers/dashboard.markdown.d.ts +5 -0
  179. package/dist/ui/renderers/dashboard.markdown.js +207 -36
  180. package/dist/ui/renderers/index.d.ts +2 -2
  181. package/dist/ui/renderers/index.js +359 -163
  182. package/dist/ui/renderers/run-list.markdown.d.ts +5 -0
  183. package/dist/ui/renderers/run-list.markdown.js +9 -4
  184. package/dist/ui/renderers/tool-registry.markdown.d.ts +6 -1
  185. package/dist/ui/renderers/tool-registry.markdown.js +15 -4
  186. package/dist/ui/views/AgentListView.js +7 -7
  187. package/dist/ui/views/RunDataTable.d.ts +18 -0
  188. package/dist/ui/views/RunDataTable.js +327 -0
  189. package/dist/ui/views/RunListView.js +360 -128
  190. package/dist/ui/views/ToolRegistryView.js +9 -9
  191. package/dist/ui/views/index.js +478 -246
  192. package/dist/ui/views/run-data-table.columns.d.ts +3 -0
  193. package/dist/ui/views/run-data-table.columns.js +272 -0
  194. package/dist/ui/views/run-list.shared.d.ts +14 -0
  195. package/dist/ui/views/run-list.shared.js +178 -0
  196. package/dist/visualizations/catalog.d.ts +10 -0
  197. package/dist/visualizations/catalog.js +135 -0
  198. package/dist/visualizations/index.d.ts +2 -0
  199. package/dist/visualizations/index.js +188 -0
  200. package/dist/visualizations/selectors.d.ts +3 -0
  201. package/dist/visualizations/selectors.js +182 -0
  202. package/dist/visualizations/selectors.test.d.ts +1 -0
  203. package/package.json +114 -12
  204. package/proofs/agent-console-meetup.replay.json +220 -0
  205. package/src/agent/agent.entity.ts +111 -111
  206. package/src/agent/agent.enum.ts +12 -12
  207. package/src/agent/agent.event.ts +91 -91
  208. package/src/agent/agent.handler.ts +144 -127
  209. package/src/agent/agent.operation.ts +400 -400
  210. package/src/agent/agent.presentation.ts +62 -62
  211. package/src/agent/agent.schema.ts +175 -175
  212. package/src/agent/agent.test-spec.ts +48 -48
  213. package/src/agent/index.ts +46 -51
  214. package/src/agent.capability.ts +11 -11
  215. package/src/agent.feature.ts +134 -131
  216. package/src/docs/agent-console.docblock.ts +52 -49
  217. package/src/example.test.ts +75 -0
  218. package/src/example.ts +34 -35
  219. package/src/handlers/agent.handlers.ts +576 -522
  220. package/src/handlers/index.ts +30 -14
  221. package/src/handlers/mock-handlers.test.ts +77 -0
  222. package/src/index.ts +10 -9
  223. package/src/presentations/index.ts +11 -13
  224. package/src/proof/index.ts +2 -0
  225. package/src/proof/meetup-proof.runtime.ts +196 -0
  226. package/src/proof/meetup-proof.scenario.ts +99 -0
  227. package/src/proof/meetup-proof.suite.ts +29 -0
  228. package/src/proof/meetup-proof.test.ts +28 -0
  229. package/src/proof/meetup-proof.ts +130 -0
  230. package/src/run/index.ts +49 -54
  231. package/src/run/run.entity.ts +137 -137
  232. package/src/run/run.enum.ts +18 -18
  233. package/src/run/run.event.ts +174 -174
  234. package/src/run/run.handler.ts +113 -96
  235. package/src/run/run.operation.ts +474 -474
  236. package/src/run/run.presentation.ts +42 -42
  237. package/src/run/run.schema.ts +126 -126
  238. package/src/run/run.test-spec.ts +48 -48
  239. package/src/seeders/index.ts +21 -21
  240. package/src/shared/demo-dashboard-data.ts +58 -0
  241. package/src/shared/demo-runtime-seed.ts +139 -0
  242. package/src/shared/demo-runtime.test.ts +169 -0
  243. package/src/shared/demo-runtime.ts +260 -0
  244. package/src/shared/index.ts +12 -1
  245. package/src/shared/mock-agents.ts +76 -76
  246. package/src/shared/mock-runs.ts +107 -102
  247. package/src/shared/mock-tools.ts +140 -140
  248. package/src/shared/overlay-types.ts +23 -23
  249. package/src/tool/index.ts +39 -44
  250. package/src/tool/tool.entity.ts +73 -73
  251. package/src/tool/tool.enum.ts +13 -13
  252. package/src/tool/tool.event.ts +80 -80
  253. package/src/tool/tool.handler.ts +124 -107
  254. package/src/tool/tool.operation.ts +328 -328
  255. package/src/tool/tool.presentation.ts +43 -43
  256. package/src/tool/tool.schema.ts +106 -106
  257. package/src/tool/tool.test-spec.ts +48 -48
  258. package/src/ui/AgentDashboard.sandbox.test.tsx +312 -0
  259. package/src/ui/AgentDashboard.tsx +351 -348
  260. package/src/ui/AgentDashboard.visualizations.tsx +35 -0
  261. package/src/ui/hooks/index.ts +7 -7
  262. package/src/ui/hooks/useAgentList.ts +57 -56
  263. package/src/ui/hooks/useAgentMutations.ts +168 -159
  264. package/src/ui/hooks/useRunList.ts +90 -57
  265. package/src/ui/hooks/useToolList.ts +102 -101
  266. package/src/ui/index.ts +6 -9
  267. package/src/ui/modals/AgentActionsModal.tsx +262 -262
  268. package/src/ui/modals/CreateAgentModal.tsx +232 -232
  269. package/src/ui/modals/index.ts +1 -1
  270. package/src/ui/overlays/demo-overlays.ts +52 -52
  271. package/src/ui/renderers/agent-list.markdown.ts +81 -61
  272. package/src/ui/renderers/agent-list.renderer.tsx +14 -14
  273. package/src/ui/renderers/dashboard.markdown.ts +135 -139
  274. package/src/ui/renderers/index.ts +3 -4
  275. package/src/ui/renderers/run-list.markdown.ts +56 -47
  276. package/src/ui/renderers/tool-registry.markdown.ts +79 -66
  277. package/src/ui/views/AgentListView.tsx +90 -90
  278. package/src/ui/views/RunDataTable.tsx +74 -0
  279. package/src/ui/views/RunListView.tsx +84 -158
  280. package/src/ui/views/ToolRegistryView.tsx +113 -113
  281. package/src/ui/views/run-data-table.columns.tsx +102 -0
  282. package/src/ui/views/run-list.shared.tsx +139 -0
  283. package/src/visualizations/catalog.ts +132 -0
  284. package/src/visualizations/index.ts +2 -0
  285. package/src/visualizations/selectors.test.ts +12 -0
  286. package/src/visualizations/selectors.ts +70 -0
  287. package/tsconfig.json +7 -8
  288. package/tsdown.config.js +24 -3
@@ -1,15 +1,814 @@
1
- // src/ui/hooks/useRunList.ts
2
- import { useCallback, useEffect, useState } from "react";
1
+ // src/visualizations/catalog.ts
2
+ import {
3
+ defineVisualization,
4
+ VisualizationRegistry
5
+ } from "@contractspec/lib.contracts-spec/visualizations";
6
+ var RUN_LIST_REF = { key: "agent.run.list", version: "1.0.0" };
7
+ var META = {
8
+ version: "1.0.0",
9
+ domain: "ai-ops",
10
+ stability: "experimental",
11
+ owners: ["@example.agent-console"],
12
+ tags: ["agent-console", "visualization", "operations"]
13
+ };
14
+ var AgentRunStatusVisualization = defineVisualization({
15
+ meta: {
16
+ ...META,
17
+ key: "agent-console.visualization.run-status",
18
+ title: "Run Status Breakdown",
19
+ description: "Distribution of run outcomes across the current sample.",
20
+ goal: "Make operational success and failure mix visible at a glance.",
21
+ context: "Agent operations overview."
22
+ },
23
+ source: { primary: RUN_LIST_REF, resultPath: "data" },
24
+ visualization: {
25
+ kind: "pie",
26
+ nameDimension: "status",
27
+ valueMeasure: "runs",
28
+ dimensions: [
29
+ { key: "status", label: "Status", dataPath: "status", type: "category" }
30
+ ],
31
+ measures: [
32
+ { key: "runs", label: "Runs", dataPath: "runs", format: "number" }
33
+ ],
34
+ table: { caption: "Run counts by status." }
35
+ }
36
+ });
37
+ var AgentRunActivityVisualization = defineVisualization({
38
+ meta: {
39
+ ...META,
40
+ key: "agent-console.visualization.run-activity",
41
+ title: "Recent Run Activity",
42
+ description: "Daily run volume across the current sample.",
43
+ goal: "Show whether agent activity is rising or slowing down.",
44
+ context: "Operations trend monitoring."
45
+ },
46
+ source: { primary: RUN_LIST_REF, resultPath: "data" },
47
+ visualization: {
48
+ kind: "cartesian",
49
+ variant: "line",
50
+ xDimension: "day",
51
+ yMeasures: ["runs"],
52
+ dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
53
+ measures: [
54
+ {
55
+ key: "runs",
56
+ label: "Runs",
57
+ dataPath: "runs",
58
+ format: "number",
59
+ color: "#0f766e"
60
+ }
61
+ ],
62
+ table: { caption: "Daily run counts." }
63
+ }
64
+ });
65
+ var AgentRunEfficiencyVisualization = defineVisualization({
66
+ meta: {
67
+ ...META,
68
+ key: "agent-console.visualization.run-efficiency",
69
+ title: "Duration vs Tokens",
70
+ description: "Scatter chart comparing token consumption and runtime.",
71
+ goal: "Reveal outlier runs that are slow relative to their token usage.",
72
+ context: "Operational performance diagnostics."
73
+ },
74
+ source: { primary: RUN_LIST_REF, resultPath: "data" },
75
+ visualization: {
76
+ kind: "cartesian",
77
+ variant: "scatter",
78
+ xDimension: "totalTokens",
79
+ yMeasures: ["durationMs"],
80
+ dimensions: [
81
+ {
82
+ key: "totalTokens",
83
+ label: "Total Tokens",
84
+ dataPath: "totalTokens",
85
+ type: "number"
86
+ }
87
+ ],
88
+ measures: [
89
+ {
90
+ key: "durationMs",
91
+ label: "Duration",
92
+ dataPath: "durationMs",
93
+ format: "duration",
94
+ color: "#7c3aed"
95
+ },
96
+ {
97
+ key: "estimatedCostUsd",
98
+ label: "Cost",
99
+ dataPath: "estimatedCostUsd",
100
+ format: "currency"
101
+ }
102
+ ],
103
+ series: [
104
+ {
105
+ key: "runs",
106
+ label: "Runs",
107
+ measure: "durationMs",
108
+ type: "scatter",
109
+ color: "#7c3aed"
110
+ }
111
+ ],
112
+ table: { caption: "Run duration versus token usage." }
113
+ }
114
+ });
115
+ var AgentVisualizationSpecs = [
116
+ AgentRunStatusVisualization,
117
+ AgentRunActivityVisualization,
118
+ AgentRunEfficiencyVisualization
119
+ ];
120
+ var AgentVisualizationRegistry = new VisualizationRegistry([
121
+ ...AgentVisualizationSpecs
122
+ ]);
123
+ var AgentVisualizationRefs = AgentVisualizationSpecs.map((spec) => ({
124
+ key: spec.meta.key,
125
+ version: spec.meta.version
126
+ }));
127
+
128
+ // src/visualizations/selectors.ts
129
+ function dayKey(value) {
130
+ if (!value)
131
+ return "unknown";
132
+ return value.toISOString().slice(0, 10);
133
+ }
134
+ function createAgentVisualizationItems(runs) {
135
+ const statusCounts = new Map;
136
+ const activityCounts = new Map;
137
+ for (const run of runs) {
138
+ statusCounts.set(run.status, (statusCounts.get(run.status) ?? 0) + 1);
139
+ activityCounts.set(dayKey(run.startedAt ?? run.queuedAt), (activityCounts.get(dayKey(run.startedAt ?? run.queuedAt)) ?? 0) + 1);
140
+ }
141
+ return [
142
+ {
143
+ key: "run-status",
144
+ spec: AgentRunStatusVisualization,
145
+ data: {
146
+ data: Array.from(statusCounts.entries()).map(([status, count]) => ({
147
+ status,
148
+ runs: count
149
+ }))
150
+ },
151
+ title: "Run Status Breakdown",
152
+ description: "Completed, failed, running, and cancelled runs in the sample.",
153
+ height: 260
154
+ },
155
+ {
156
+ key: "run-activity",
157
+ spec: AgentRunActivityVisualization,
158
+ data: {
159
+ data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, runs: count }))
160
+ },
161
+ title: "Recent Run Activity",
162
+ description: "Daily run volume derived from run start times."
163
+ },
164
+ {
165
+ key: "run-efficiency",
166
+ spec: AgentRunEfficiencyVisualization,
167
+ data: {
168
+ data: runs.filter((run) => typeof run.durationMs === "number").map((run) => ({
169
+ totalTokens: run.totalTokens,
170
+ durationMs: run.durationMs ?? 0,
171
+ estimatedCostUsd: run.estimatedCostUsd
172
+ }))
173
+ },
174
+ title: "Duration vs Tokens",
175
+ description: "Operational scatter plot for spotting inefficient runs."
176
+ }
177
+ ];
178
+ }
179
+ // src/shared/mock-agents.ts
180
+ var MOCK_AGENTS = [
181
+ {
182
+ id: "agent-1",
183
+ organizationId: "demo-org",
184
+ name: "Customer Support Bot",
185
+ slug: "customer-support-bot",
186
+ description: "Handles tier-1 customer inquiries and routes complex issues.",
187
+ status: "ACTIVE",
188
+ modelProvider: "OPENAI",
189
+ modelName: "gpt-4o-mini",
190
+ modelConfig: { temperature: 0.7 },
191
+ systemPrompt: "You are a helpful customer support assistant.",
192
+ toolChoice: "auto",
193
+ maxIterations: 10,
194
+ timeoutMs: 120000,
195
+ version: "1.0.0",
196
+ tags: ["support", "tier-1"],
197
+ createdAt: new Date("2024-01-15T10:00:00Z"),
198
+ updatedAt: new Date("2024-03-20T14:30:00Z")
199
+ },
200
+ {
201
+ id: "agent-2",
202
+ organizationId: "demo-org",
203
+ name: "Code Review Assistant",
204
+ slug: "code-review-assistant",
205
+ description: "Reviews pull requests and provides actionable feedback.",
206
+ status: "ACTIVE",
207
+ modelProvider: "ANTHROPIC",
208
+ modelName: "claude-sonnet-4-20250514",
209
+ modelConfig: { temperature: 0.3 },
210
+ systemPrompt: "You are a code review expert.",
211
+ toolChoice: "auto",
212
+ maxIterations: 15,
213
+ timeoutMs: 180000,
214
+ version: "2.1.0",
215
+ tags: ["code", "review", "dev"],
216
+ createdAt: new Date("2024-02-10T09:00:00Z"),
217
+ updatedAt: new Date("2024-04-05T11:15:00Z")
218
+ },
219
+ {
220
+ id: "agent-3",
221
+ organizationId: "demo-org",
222
+ name: "Data Analyst",
223
+ slug: "data-analyst",
224
+ description: "Queries databases and generates insights from data.",
225
+ status: "PAUSED",
226
+ modelProvider: "OPENAI",
227
+ modelName: "gpt-4o",
228
+ modelConfig: { temperature: 0.5 },
229
+ systemPrompt: "You are a data analyst expert in SQL and analytics.",
230
+ toolChoice: "required",
231
+ maxIterations: 20,
232
+ timeoutMs: 300000,
233
+ version: "1.2.0",
234
+ tags: ["data", "analytics", "sql"],
235
+ createdAt: new Date("2024-03-01T08:00:00Z"),
236
+ updatedAt: new Date("2024-04-10T16:45:00Z")
237
+ },
238
+ {
239
+ id: "agent-4",
240
+ organizationId: "demo-org",
241
+ name: "Meeting Scheduler",
242
+ slug: "meeting-scheduler",
243
+ description: "Schedules meetings and manages calendar conflicts.",
244
+ status: "DRAFT",
245
+ modelProvider: "GOOGLE",
246
+ modelName: "gemini-2.0-flash",
247
+ modelConfig: { temperature: 0.2 },
248
+ systemPrompt: "You help schedule and organize meetings efficiently.",
249
+ toolChoice: "auto",
250
+ maxIterations: 5,
251
+ timeoutMs: 60000,
252
+ version: "0.1.0",
253
+ tags: ["calendar", "scheduling"],
254
+ createdAt: new Date("2024-04-01T12:00:00Z"),
255
+ updatedAt: new Date("2024-04-01T12:00:00Z")
256
+ }
257
+ ];
258
+
259
+ // src/shared/mock-tools.ts
260
+ var MOCK_TOOLS = [
261
+ {
262
+ id: "tool-1",
263
+ organizationId: "demo-org",
264
+ name: "Web Search",
265
+ slug: "web-search",
266
+ description: "Search the web for real-time information using Brave API.",
267
+ category: "RETRIEVAL",
268
+ status: "ACTIVE",
269
+ parametersSchema: {
270
+ type: "object",
271
+ properties: {
272
+ query: { type: "string", description: "Search query" },
273
+ numResults: { type: "number", default: 10 }
274
+ },
275
+ required: ["query"]
276
+ },
277
+ outputSchema: { type: "array", items: { type: "object" } },
278
+ implementationType: "http",
279
+ implementationConfig: {
280
+ url: "https://api.brave.com/search",
281
+ method: "GET"
282
+ },
283
+ maxInvocationsPerMinute: 60,
284
+ timeoutMs: 30000,
285
+ version: "1.0.0",
286
+ tags: ["search", "web"],
287
+ createdAt: new Date("2024-01-01T00:00:00Z"),
288
+ updatedAt: new Date("2024-02-15T10:00:00Z")
289
+ },
290
+ {
291
+ id: "tool-2",
292
+ organizationId: "demo-org",
293
+ name: "SQL Query",
294
+ slug: "sql-query",
295
+ description: "Execute read-only SQL queries against the data warehouse.",
296
+ category: "RETRIEVAL",
297
+ status: "ACTIVE",
298
+ parametersSchema: {
299
+ type: "object",
300
+ properties: {
301
+ query: { type: "string", description: "SQL query" },
302
+ maxRows: { type: "number", default: 100 }
303
+ },
304
+ required: ["query"]
305
+ },
306
+ outputSchema: { type: "object" },
307
+ implementationType: "function",
308
+ implementationConfig: { handler: "executeSqlQuery" },
309
+ maxInvocationsPerMinute: 30,
310
+ timeoutMs: 60000,
311
+ version: "1.1.0",
312
+ tags: ["sql", "database"],
313
+ createdAt: new Date("2024-01-05T00:00:00Z"),
314
+ updatedAt: new Date("2024-03-10T14:00:00Z")
315
+ },
316
+ {
317
+ id: "tool-3",
318
+ organizationId: "demo-org",
319
+ name: "Email Sender",
320
+ slug: "email-sender",
321
+ description: "Send emails via SMTP or API.",
322
+ category: "COMMUNICATION",
323
+ status: "ACTIVE",
324
+ parametersSchema: {
325
+ type: "object",
326
+ properties: {
327
+ to: { type: "string" },
328
+ subject: { type: "string" },
329
+ body: { type: "string" }
330
+ },
331
+ required: ["to", "subject", "body"]
332
+ },
333
+ implementationType: "http",
334
+ implementationConfig: { url: "/api/send-email", method: "POST" },
335
+ maxInvocationsPerMinute: 10,
336
+ timeoutMs: 30000,
337
+ version: "1.0.0",
338
+ tags: ["email", "communication"],
339
+ createdAt: new Date("2024-02-01T00:00:00Z"),
340
+ updatedAt: new Date("2024-02-01T00:00:00Z")
341
+ },
342
+ {
343
+ id: "tool-4",
344
+ organizationId: "demo-org",
345
+ name: "GitHub Integration",
346
+ slug: "github-integration",
347
+ description: "Interact with GitHub repositories, PRs, and issues.",
348
+ category: "INTEGRATION",
349
+ status: "ACTIVE",
350
+ parametersSchema: {
351
+ type: "object",
352
+ properties: {
353
+ action: {
354
+ type: "string",
355
+ enum: ["list_prs", "get_pr", "create_comment"]
356
+ },
357
+ repo: { type: "string" },
358
+ params: { type: "object" }
359
+ },
360
+ required: ["action", "repo"]
361
+ },
362
+ implementationType: "http",
363
+ implementationConfig: { url: "https://api.github.com", auth: "token" },
364
+ maxInvocationsPerMinute: 100,
365
+ timeoutMs: 15000,
366
+ version: "2.0.0",
367
+ tags: ["github", "integration", "code"],
368
+ createdAt: new Date("2024-02-20T00:00:00Z"),
369
+ updatedAt: new Date("2024-04-01T09:00:00Z")
370
+ },
371
+ {
372
+ id: "tool-5",
373
+ organizationId: "demo-org",
374
+ name: "Calculator",
375
+ slug: "calculator",
376
+ description: "Perform mathematical calculations.",
377
+ category: "COMPUTATION",
378
+ status: "ACTIVE",
379
+ parametersSchema: {
380
+ type: "object",
381
+ properties: {
382
+ expression: {
383
+ type: "string",
384
+ description: "Math expression to evaluate"
385
+ }
386
+ },
387
+ required: ["expression"]
388
+ },
389
+ outputSchema: {
390
+ type: "object",
391
+ properties: { result: { type: "number" } }
392
+ },
393
+ implementationType: "function",
394
+ implementationConfig: { handler: "evaluateMath" },
395
+ timeoutMs: 5000,
396
+ version: "1.0.0",
397
+ tags: ["math", "utility"],
398
+ createdAt: new Date("2024-01-10T00:00:00Z"),
399
+ updatedAt: new Date("2024-01-10T00:00:00Z")
400
+ }
401
+ ];
402
+
403
+ // src/shared/mock-runs.ts
404
+ var MOCK_RUNS = [
405
+ {
406
+ id: "run-1",
407
+ organizationId: "demo-org",
408
+ projectId: "demo-project",
409
+ agentId: "agent-1",
410
+ agentName: "Customer Support Bot",
411
+ userId: "user-1",
412
+ sessionId: "session-1",
413
+ input: { message: "How do I reset my password?", context: {} },
414
+ output: { response: "You can reset your password by clicking..." },
415
+ status: "COMPLETED",
416
+ totalTokens: 1250,
417
+ promptTokens: 800,
418
+ completionTokens: 450,
419
+ totalIterations: 3,
420
+ durationMs: 4500,
421
+ estimatedCostUsd: 0.0025,
422
+ queuedAt: new Date("2024-04-15T10:00:00Z"),
423
+ startedAt: new Date("2024-04-15T10:00:01Z"),
424
+ completedAt: new Date("2024-04-15T10:00:05Z"),
425
+ steps: [],
426
+ logs: []
427
+ },
428
+ {
429
+ id: "run-2",
430
+ organizationId: "demo-org",
431
+ projectId: "demo-project",
432
+ agentId: "agent-2",
433
+ agentName: "Code Review Assistant",
434
+ userId: "user-2",
435
+ input: { message: "Review PR #123", context: { prNumber: 123 } },
436
+ status: "IN_PROGRESS",
437
+ totalTokens: 3500,
438
+ promptTokens: 3000,
439
+ completionTokens: 500,
440
+ totalIterations: 5,
441
+ queuedAt: new Date("2024-04-15T10:30:00Z"),
442
+ startedAt: new Date("2024-04-15T10:30:02Z"),
443
+ steps: [],
444
+ logs: []
445
+ },
446
+ {
447
+ id: "run-3",
448
+ organizationId: "demo-org",
449
+ projectId: "demo-project",
450
+ agentId: "agent-1",
451
+ agentName: "Customer Support Bot",
452
+ userId: "user-1",
453
+ input: { message: "What are your business hours?" },
454
+ output: { response: "Our business hours are 9 AM to 5 PM EST..." },
455
+ status: "COMPLETED",
456
+ totalTokens: 800,
457
+ promptTokens: 500,
458
+ completionTokens: 300,
459
+ totalIterations: 2,
460
+ durationMs: 2100,
461
+ estimatedCostUsd: 0.0012,
462
+ queuedAt: new Date("2024-04-15T09:00:00Z"),
463
+ startedAt: new Date("2024-04-15T09:00:01Z"),
464
+ completedAt: new Date("2024-04-15T09:00:03Z"),
465
+ steps: [],
466
+ logs: []
467
+ },
468
+ {
469
+ id: "run-4",
470
+ organizationId: "demo-org",
471
+ projectId: "demo-project",
472
+ agentId: "agent-3",
473
+ agentName: "Data Analyst",
474
+ userId: "user-3",
475
+ input: { message: "Generate sales report for Q1" },
476
+ status: "FAILED",
477
+ errorMessage: "Database connection timeout",
478
+ errorCode: "DB_TIMEOUT",
479
+ totalTokens: 2000,
480
+ promptTokens: 1500,
481
+ completionTokens: 500,
482
+ totalIterations: 8,
483
+ durationMs: 45000,
484
+ queuedAt: new Date("2024-04-14T15:00:00Z"),
485
+ startedAt: new Date("2024-04-14T15:00:05Z"),
486
+ completedAt: new Date("2024-04-14T15:00:50Z"),
487
+ steps: [],
488
+ logs: []
489
+ },
490
+ {
491
+ id: "run-5",
492
+ organizationId: "demo-org",
493
+ projectId: "demo-project",
494
+ agentId: "agent-2",
495
+ agentName: "Code Review Assistant",
496
+ userId: "user-2",
497
+ input: { message: "Review PR #120" },
498
+ output: { response: "Code review complete. 3 suggestions..." },
499
+ status: "COMPLETED",
500
+ totalTokens: 5200,
501
+ promptTokens: 4000,
502
+ completionTokens: 1200,
503
+ totalIterations: 7,
504
+ durationMs: 15000,
505
+ estimatedCostUsd: 0.0156,
506
+ queuedAt: new Date("2024-04-14T11:00:00Z"),
507
+ startedAt: new Date("2024-04-14T11:00:03Z"),
508
+ completedAt: new Date("2024-04-14T11:00:18Z"),
509
+ steps: [],
510
+ logs: []
511
+ }
512
+ ];
513
+
514
+ // src/ui/AgentDashboard.visualizations.tsx
515
+ import {
516
+ VisualizationCard,
517
+ VisualizationGrid
518
+ } from "@contractspec/lib.design-system";
519
+ import { jsxDEV } from "react/jsx-dev-runtime";
520
+ "use client";
521
+ function AgentVisualizationOverview({ runs }) {
522
+ const items = createAgentVisualizationItems(runs);
523
+ return /* @__PURE__ */ jsxDEV("section", {
524
+ className: "space-y-3",
525
+ children: [
526
+ /* @__PURE__ */ jsxDEV("div", {
527
+ children: [
528
+ /* @__PURE__ */ jsxDEV("h3", {
529
+ className: "font-semibold text-lg",
530
+ children: "Operational Visualizations"
531
+ }, undefined, false, undefined, this),
532
+ /* @__PURE__ */ jsxDEV("p", {
533
+ className: "text-muted-foreground text-sm",
534
+ children: "Contract-backed charts derived from recent run activity."
535
+ }, undefined, false, undefined, this)
536
+ ]
537
+ }, undefined, true, undefined, this),
538
+ /* @__PURE__ */ jsxDEV(VisualizationGrid, {
539
+ children: items.map((item) => /* @__PURE__ */ jsxDEV(VisualizationCard, {
540
+ data: item.data,
541
+ description: item.description,
542
+ height: item.height,
543
+ spec: item.spec,
544
+ title: item.title
545
+ }, item.key, false, undefined, this))
546
+ }, undefined, false, undefined, this)
547
+ ]
548
+ }, undefined, true, undefined, this);
549
+ }
550
+
551
+ // src/ui/hooks/useAgentList.ts
3
552
  import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
4
- function useRunList(options = {}) {
553
+ import { useCallback, useEffect, useMemo, useState } from "react";
554
+ function useAgentList(options = {}) {
5
555
  const { handlers, projectId } = useTemplateRuntime();
6
556
  const { agent } = handlers;
7
557
  const [data, setData] = useState(null);
8
- const [metrics, setMetrics] = useState(null);
9
558
  const [loading, setLoading] = useState(true);
10
559
  const [error, setError] = useState(null);
11
560
  const [page, setPage] = useState(1);
12
561
  const fetchData = useCallback(async () => {
562
+ setLoading(true);
563
+ setError(null);
564
+ try {
565
+ const result = await agent.listAgents({
566
+ projectId,
567
+ search: options.search,
568
+ status: options.status === "all" ? undefined : options.status,
569
+ limit: options.limit ?? 20,
570
+ offset: (page - 1) * (options.limit ?? 20)
571
+ });
572
+ setData(result);
573
+ } catch (err) {
574
+ setError(err instanceof Error ? err : new Error("Unknown error"));
575
+ } finally {
576
+ setLoading(false);
577
+ }
578
+ }, [agent, projectId, options.search, options.status, options.limit, page]);
579
+ useEffect(() => {
580
+ fetchData();
581
+ }, [fetchData]);
582
+ const stats = useMemo(() => {
583
+ if (!data)
584
+ return null;
585
+ return {
586
+ total: data.total,
587
+ active: data.items.filter((a) => a.status === "ACTIVE").length,
588
+ paused: data.items.filter((a) => a.status === "PAUSED").length,
589
+ draft: data.items.filter((a) => a.status === "DRAFT").length
590
+ };
591
+ }, [data]);
592
+ return {
593
+ data,
594
+ loading,
595
+ error,
596
+ stats,
597
+ page,
598
+ refetch: fetchData,
599
+ nextPage: () => setPage((p) => p + 1),
600
+ prevPage: () => page > 1 && setPage((p) => p - 1)
601
+ };
602
+ }
603
+
604
+ // src/ui/hooks/useAgentMutations.ts
605
+ import { useTemplateRuntime as useTemplateRuntime2 } from "@contractspec/lib.example-shared-ui";
606
+ import { useCallback as useCallback2, useState as useState2 } from "react";
607
+
608
+ // src/shared/demo-runtime-seed.ts
609
+ var AGENT_CONSOLE_DEMO_ORGANIZATION_ID = "demo-org";
610
+ var AGENT_CONSOLE_DEMO_PROJECT_ID = "agent-console-demo";
611
+ function slugify(name) {
612
+ return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
613
+ }
614
+ function cloneAgent(agent) {
615
+ return { ...agent };
616
+ }
617
+ function cloneTool(tool) {
618
+ return { ...tool };
619
+ }
620
+ function cloneRun(run) {
621
+ return { ...run };
622
+ }
623
+ function createDefaultNow() {
624
+ let tick = 0;
625
+ const base = Date.parse("2026-03-20T09:00:00.000Z");
626
+ return () => new Date(base + tick++ * 60000);
627
+ }
628
+ function normalizeProvider(provider) {
629
+ return provider.toLowerCase();
630
+ }
631
+ function normalizeRunStatus(status) {
632
+ return status === "IN_PROGRESS" ? "RUNNING" : status;
633
+ }
634
+ function createSeedState(projectId, organizationId) {
635
+ const agents = MOCK_AGENTS.map((agent) => ({
636
+ id: agent.id,
637
+ projectId,
638
+ organizationId,
639
+ name: agent.name,
640
+ slug: agent.slug,
641
+ description: agent.description,
642
+ modelProvider: normalizeProvider(agent.modelProvider),
643
+ modelName: agent.modelName,
644
+ systemPrompt: agent.systemPrompt,
645
+ temperature: typeof agent.modelConfig?.temperature === "number" ? agent.modelConfig.temperature : 0.4,
646
+ maxTokens: 8192,
647
+ status: agent.status,
648
+ createdAt: agent.createdAt,
649
+ updatedAt: agent.updatedAt
650
+ }));
651
+ const tools = MOCK_TOOLS.map((tool) => ({
652
+ id: tool.id,
653
+ projectId,
654
+ organizationId,
655
+ name: tool.name,
656
+ description: tool.description,
657
+ version: tool.version,
658
+ category: tool.category,
659
+ status: tool.status,
660
+ inputSchema: JSON.stringify(tool.parametersSchema),
661
+ outputSchema: tool.outputSchema ? JSON.stringify(tool.outputSchema) : undefined,
662
+ endpoint: typeof tool.implementationConfig?.url === "string" ? tool.implementationConfig.url : undefined,
663
+ createdAt: tool.createdAt,
664
+ updatedAt: tool.updatedAt
665
+ }));
666
+ const agentNames = new Map(agents.map((agent) => [agent.id, agent.name]));
667
+ const runs = MOCK_RUNS.map((run) => ({
668
+ id: run.id,
669
+ projectId,
670
+ agentId: run.agentId,
671
+ agentName: agentNames.get(run.agentId) ?? run.agentName ?? "Unknown agent",
672
+ status: normalizeRunStatus(run.status),
673
+ input: JSON.stringify(run.input),
674
+ output: run.output ? JSON.stringify(run.output) : undefined,
675
+ totalTokens: run.totalTokens,
676
+ promptTokens: run.promptTokens,
677
+ completionTokens: run.completionTokens,
678
+ estimatedCostUsd: run.estimatedCostUsd ?? 0,
679
+ durationMs: run.durationMs,
680
+ errorMessage: run.errorMessage,
681
+ queuedAt: run.queuedAt,
682
+ startedAt: run.startedAt,
683
+ completedAt: run.completedAt
684
+ }));
685
+ return { agents, tools, runs };
686
+ }
687
+ function summarizeRunMetrics(runs) {
688
+ const totalRuns = runs.length;
689
+ const completedRuns = runs.filter((run) => run.status === "COMPLETED").length;
690
+ const completedDurations = runs.map((run) => run.durationMs).filter((duration) => typeof duration === "number");
691
+ return {
692
+ totalRuns,
693
+ successRate: totalRuns === 0 ? 0 : completedRuns / totalRuns,
694
+ averageDurationMs: completedDurations.length === 0 ? 0 : Math.round(completedDurations.reduce((sum, duration) => sum + duration, 0) / completedDurations.length),
695
+ totalTokens: runs.reduce((sum, run) => sum + run.totalTokens, 0),
696
+ totalCostUsd: runs.reduce((sum, run) => sum + run.estimatedCostUsd, 0)
697
+ };
698
+ }
699
+
700
+ // src/ui/hooks/useAgentMutations.ts
701
+ function normalizeMutationError(error, fallbackMessage) {
702
+ return error instanceof Error ? error : new Error(fallbackMessage);
703
+ }
704
+ function useAgentMutations(options = {}) {
705
+ const { handlers, projectId } = useTemplateRuntime2();
706
+ const { agent } = handlers;
707
+ const [createState, setCreateState] = useState2({
708
+ loading: false,
709
+ error: null,
710
+ data: null
711
+ });
712
+ const [updateState, setUpdateState] = useState2({
713
+ loading: false,
714
+ error: null,
715
+ data: null
716
+ });
717
+ const [executeState, setExecuteState] = useState2({
718
+ loading: false,
719
+ error: null,
720
+ data: null
721
+ });
722
+ const createAgent = useCallback2(async (input) => {
723
+ setCreateState({ loading: true, error: null, data: null });
724
+ try {
725
+ const result = await agent.createAgent(input, {
726
+ projectId,
727
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID
728
+ });
729
+ setCreateState({ loading: false, error: null, data: result });
730
+ options.onSuccess?.();
731
+ return result;
732
+ } catch (err) {
733
+ const error = normalizeMutationError(err, "Failed to create agent");
734
+ setCreateState({ loading: false, error, data: null });
735
+ options.onError?.(error);
736
+ throw error;
737
+ }
738
+ }, [agent, projectId, options]);
739
+ const updateAgent = useCallback2(async (input) => {
740
+ setUpdateState({ loading: true, error: null, data: null });
741
+ try {
742
+ const result = await agent.updateAgent(input);
743
+ setUpdateState({ loading: false, error: null, data: result });
744
+ options.onSuccess?.();
745
+ return result;
746
+ } catch (err) {
747
+ const error = normalizeMutationError(err, "Failed to update agent");
748
+ setUpdateState({ loading: false, error, data: null });
749
+ options.onError?.(error);
750
+ throw error;
751
+ }
752
+ }, [agent, options]);
753
+ const activateAgent = useCallback2(async (agentId) => {
754
+ return updateAgent({ id: agentId, status: "ACTIVE" });
755
+ }, [updateAgent]);
756
+ const pauseAgent = useCallback2(async (agentId) => {
757
+ return updateAgent({ id: agentId, status: "PAUSED" });
758
+ }, [updateAgent]);
759
+ const archiveAgent = useCallback2(async (agentId) => {
760
+ return updateAgent({ id: agentId, status: "ARCHIVED" });
761
+ }, [updateAgent]);
762
+ const executeAgent = useCallback2(async (input) => {
763
+ setExecuteState({ loading: true, error: null, data: null });
764
+ try {
765
+ const result = await agent.executeAgent({
766
+ agentId: input.agentId,
767
+ message: input.message,
768
+ context: {
769
+ projectId,
770
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID
771
+ }
772
+ });
773
+ setExecuteState({ loading: false, error: null, data: result });
774
+ options.onSuccess?.();
775
+ return result;
776
+ } catch (err) {
777
+ const error = normalizeMutationError(err, "Failed to execute agent");
778
+ setExecuteState({ loading: false, error, data: null });
779
+ options.onError?.(error);
780
+ throw error;
781
+ }
782
+ }, [agent, projectId, options]);
783
+ return {
784
+ createAgent,
785
+ updateAgent,
786
+ activateAgent,
787
+ pauseAgent,
788
+ archiveAgent,
789
+ executeAgent,
790
+ createState,
791
+ updateState,
792
+ executeState,
793
+ isLoading: createState.loading || updateState.loading || executeState.loading
794
+ };
795
+ }
796
+
797
+ // src/ui/hooks/useRunList.ts
798
+ import { useTemplateRuntime as useTemplateRuntime3 } from "@contractspec/lib.example-shared-ui";
799
+ import { useCallback as useCallback3, useEffect as useEffect2, useState as useState3 } from "react";
800
+ function useRunList(options = {}) {
801
+ const { handlers, projectId } = useTemplateRuntime3();
802
+ const { agent } = handlers;
803
+ const [data, setData] = useState3(null);
804
+ const [metrics, setMetrics] = useState3(null);
805
+ const [loading, setLoading] = useState3(true);
806
+ const [error, setError] = useState3(null);
807
+ const [internalPageIndex, setInternalPageIndex] = useState3(0);
808
+ const pageSize = options.pageSize ?? options.limit ?? 20;
809
+ const pageIndex = options.pageIndex ?? internalPageIndex;
810
+ const [sort] = options.sorting ?? [];
811
+ const fetchData = useCallback3(async () => {
13
812
  setLoading(true);
14
813
  setError(null);
15
814
  try {
@@ -18,14 +817,14 @@ function useRunList(options = {}) {
18
817
  projectId,
19
818
  agentId: options.agentId,
20
819
  status: options.status === "all" ? undefined : options.status,
21
- limit: options.limit ?? 20,
22
- offset: (page - 1) * (options.limit ?? 20)
820
+ sortBy: sort?.id,
821
+ sortDirection: sort ? sort.desc ? "desc" : "asc" : undefined,
822
+ limit: pageSize,
823
+ offset: pageIndex * pageSize
23
824
  }),
24
825
  agent.getRunMetrics({
25
826
  projectId,
26
- agentId: options.agentId,
27
- startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
28
- endDate: new Date
827
+ agentId: options.agentId
29
828
  })
30
829
  ]);
31
830
  setData(runsResult);
@@ -35,570 +834,339 @@ function useRunList(options = {}) {
35
834
  } finally {
36
835
  setLoading(false);
37
836
  }
38
- }, [agent, projectId, options.agentId, options.status, options.limit, page]);
39
- useEffect(() => {
837
+ }, [
838
+ agent,
839
+ pageIndex,
840
+ pageSize,
841
+ projectId,
842
+ options.agentId,
843
+ options.status,
844
+ sort?.desc,
845
+ sort?.id
846
+ ]);
847
+ useEffect2(() => {
40
848
  fetchData();
41
849
  }, [fetchData]);
850
+ const hasControlledPagination = options.pageIndex !== undefined;
42
851
  return {
43
852
  data,
44
853
  metrics,
45
854
  loading,
46
855
  error,
47
- page,
856
+ page: pageIndex + 1,
857
+ pageIndex,
858
+ pageSize,
48
859
  refetch: fetchData,
49
- nextPage: () => setPage((p) => p + 1),
50
- prevPage: () => page > 1 && setPage((p) => p - 1)
860
+ nextPage: hasControlledPagination ? undefined : () => setInternalPageIndex((current) => current + 1),
861
+ prevPage: hasControlledPagination ? undefined : () => setInternalPageIndex((current) => Math.max(0, current - 1))
51
862
  };
52
863
  }
53
864
 
54
- // src/ui/views/RunListView.tsx
55
- import {
56
- StatCard,
57
- StatCardGroup,
58
- StatusChip,
59
- EmptyState,
60
- LoaderBlock,
61
- ErrorState
62
- } from "@contractspec/lib.design-system";
63
- import { jsxDEV } from "react/jsx-dev-runtime";
865
+ // src/ui/modals/AgentActionsModal.tsx
866
+ import { Button } from "@contractspec/lib.design-system";
867
+ import { useState as useState4 } from "react";
868
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
64
869
  "use client";
65
- function getStatusTone(status) {
870
+ function getStatusColor(status) {
66
871
  switch (status) {
67
- case "COMPLETED":
68
- return "success";
69
- case "RUNNING":
70
- return "warning";
71
- case "QUEUED":
72
- return "neutral";
73
- case "FAILED":
74
- case "CANCELLED":
75
- return "danger";
872
+ case "ACTIVE":
873
+ return "text-green-600 bg-green-100 dark:text-green-400 dark:bg-green-900/30";
874
+ case "DRAFT":
875
+ return "text-blue-600 bg-blue-100 dark:text-blue-400 dark:bg-blue-900/30";
876
+ case "PAUSED":
877
+ return "text-yellow-600 bg-yellow-100 dark:text-yellow-400 dark:bg-yellow-900/30";
878
+ case "ARCHIVED":
879
+ return "text-gray-600 bg-gray-100 dark:text-gray-400 dark:bg-gray-700";
76
880
  default:
77
- return "neutral";
881
+ return "text-gray-600 bg-gray-100";
78
882
  }
79
883
  }
80
- function formatDuration(ms) {
81
- if (!ms)
82
- return "-";
83
- if (ms < 1000)
84
- return `${ms}ms`;
85
- if (ms < 60000)
86
- return `${(ms / 1000).toFixed(1)}s`;
87
- return `${(ms / 60000).toFixed(1)}m`;
88
- }
89
- function formatTokens(tokens) {
90
- if (tokens < 1000)
91
- return tokens.toString();
92
- if (tokens < 1e6)
93
- return `${(tokens / 1000).toFixed(1)}K`;
94
- return `${(tokens / 1e6).toFixed(2)}M`;
95
- }
96
- function formatCost(cost) {
97
- if (!cost)
98
- return "-";
99
- return `$${cost.toFixed(4)}`;
100
- }
101
- function RunListView({ agentId, onRunClick }) {
102
- const { data, metrics, loading, error, refetch } = useRunList({ agentId });
103
- if (loading && !data) {
104
- return /* @__PURE__ */ jsxDEV(LoaderBlock, {
105
- label: "Loading runs..."
106
- }, undefined, false, undefined, this);
107
- }
108
- if (error) {
109
- return /* @__PURE__ */ jsxDEV(ErrorState, {
110
- title: "Failed to load runs",
111
- description: error.message,
112
- onRetry: refetch,
113
- retryLabel: "Retry"
114
- }, undefined, false, undefined, this);
115
- }
116
- if (!data?.items.length) {
117
- return /* @__PURE__ */ jsxDEV(EmptyState, {
118
- title: "No runs yet",
119
- description: "Execute an agent to see run history here."
120
- }, undefined, false, undefined, this);
121
- }
122
- return /* @__PURE__ */ jsxDEV("div", {
123
- className: "space-y-6",
884
+ function AgentActionsModal({
885
+ isOpen,
886
+ agent,
887
+ onClose,
888
+ onActivate,
889
+ onPause,
890
+ onArchive,
891
+ onExecute,
892
+ isLoading = false
893
+ }) {
894
+ const [mode, setMode] = useState4("menu");
895
+ const [message, setMessage] = useState4("");
896
+ const [confirmAction, setConfirmAction] = useState4(null);
897
+ const [error, setError] = useState4(null);
898
+ const resetForm = () => {
899
+ setMode("menu");
900
+ setMessage("");
901
+ setConfirmAction(null);
902
+ setError(null);
903
+ };
904
+ const handleClose = () => {
905
+ resetForm();
906
+ onClose();
907
+ };
908
+ const handleExecute = async () => {
909
+ if (!agent)
910
+ return;
911
+ setError(null);
912
+ if (!message.trim()) {
913
+ setError("Please enter a message");
914
+ return;
915
+ }
916
+ try {
917
+ await onExecute(agent.id, message.trim());
918
+ handleClose();
919
+ } catch (err) {
920
+ setError(err instanceof Error ? err.message : "Failed to execute agent");
921
+ }
922
+ };
923
+ const handleStatusChange = async (action) => {
924
+ if (!agent)
925
+ return;
926
+ setError(null);
927
+ try {
928
+ switch (action) {
929
+ case "activate":
930
+ await onActivate(agent.id);
931
+ break;
932
+ case "pause":
933
+ await onPause(agent.id);
934
+ break;
935
+ case "archive":
936
+ await onArchive(agent.id);
937
+ break;
938
+ }
939
+ handleClose();
940
+ } catch (err) {
941
+ setError(err instanceof Error ? err.message : `Failed to ${action} agent`);
942
+ }
943
+ };
944
+ if (!isOpen || !agent)
945
+ return null;
946
+ return /* @__PURE__ */ jsxDEV2("div", {
947
+ className: "fixed inset-0 z-50 flex items-center justify-center",
124
948
  children: [
125
- metrics && /* @__PURE__ */ jsxDEV(StatCardGroup, {
949
+ /* @__PURE__ */ jsxDEV2("div", {
950
+ className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
951
+ onClick: handleClose,
952
+ role: "button",
953
+ tabIndex: 0,
954
+ onKeyDown: (e) => {
955
+ if (e.key === "Enter" || e.key === " ")
956
+ handleClose();
957
+ },
958
+ "aria-label": "Close modal"
959
+ }, undefined, false, undefined, this),
960
+ /* @__PURE__ */ jsxDEV2("div", {
961
+ className: "relative z-10 w-full max-w-md rounded-xl border border-border bg-card p-6 shadow-xl",
126
962
  children: [
127
- /* @__PURE__ */ jsxDEV(StatCard, {
128
- label: "Total Runs",
129
- value: metrics.totalRuns
130
- }, undefined, false, undefined, this),
131
- /* @__PURE__ */ jsxDEV(StatCard, {
132
- label: "Success Rate",
133
- value: `${(metrics.successRate * 100).toFixed(1)}%`
134
- }, undefined, false, undefined, this),
135
- /* @__PURE__ */ jsxDEV(StatCard, {
136
- label: "Total Tokens",
137
- value: formatTokens(metrics.totalTokens)
138
- }, undefined, false, undefined, this),
139
- /* @__PURE__ */ jsxDEV(StatCard, {
140
- label: "Total Cost",
141
- value: `$${metrics.totalCostUsd.toFixed(2)}`
142
- }, undefined, false, undefined, this)
143
- ]
144
- }, undefined, true, undefined, this),
145
- /* @__PURE__ */ jsxDEV("div", {
146
- className: "border-border rounded-lg border",
147
- children: /* @__PURE__ */ jsxDEV("table", {
148
- className: "w-full",
149
- children: [
150
- /* @__PURE__ */ jsxDEV("thead", {
151
- className: "border-border bg-muted/30 border-b",
152
- children: /* @__PURE__ */ jsxDEV("tr", {
963
+ /* @__PURE__ */ jsxDEV2("div", {
964
+ className: "mb-4 border-border border-b pb-4",
965
+ children: [
966
+ /* @__PURE__ */ jsxDEV2("h2", {
967
+ className: "font-semibold text-xl",
968
+ children: agent.name
969
+ }, undefined, false, undefined, this),
970
+ /* @__PURE__ */ jsxDEV2("div", {
971
+ className: "mt-1 flex items-center gap-2",
153
972
  children: [
154
- /* @__PURE__ */ jsxDEV("th", {
155
- className: "text-muted-foreground px-4 py-3 text-left text-sm font-medium",
156
- children: "Run"
157
- }, undefined, false, undefined, this),
158
- /* @__PURE__ */ jsxDEV("th", {
159
- className: "text-muted-foreground px-4 py-3 text-left text-sm font-medium",
160
- children: "Agent"
161
- }, undefined, false, undefined, this),
162
- /* @__PURE__ */ jsxDEV("th", {
163
- className: "text-muted-foreground px-4 py-3 text-left text-sm font-medium",
164
- children: "Status"
165
- }, undefined, false, undefined, this),
166
- /* @__PURE__ */ jsxDEV("th", {
167
- className: "text-muted-foreground px-4 py-3 text-right text-sm font-medium",
168
- children: "Tokens"
973
+ /* @__PURE__ */ jsxDEV2("span", {
974
+ className: "text-muted-foreground text-sm",
975
+ children: [
976
+ agent.modelProvider,
977
+ " / ",
978
+ agent.modelName
979
+ ]
980
+ }, undefined, true, undefined, this),
981
+ /* @__PURE__ */ jsxDEV2("span", {
982
+ className: `rounded-full px-2 py-0.5 font-medium text-xs ${getStatusColor(agent.status)}`,
983
+ children: agent.status
984
+ }, undefined, false, undefined, this)
985
+ ]
986
+ }, undefined, true, undefined, this),
987
+ agent.description && /* @__PURE__ */ jsxDEV2("p", {
988
+ className: "mt-2 text-muted-foreground text-sm",
989
+ children: agent.description
990
+ }, undefined, false, undefined, this)
991
+ ]
992
+ }, undefined, true, undefined, this),
993
+ mode === "menu" && /* @__PURE__ */ jsxDEV2("div", {
994
+ className: "space-y-3",
995
+ children: [
996
+ agent.status === "ACTIVE" && /* @__PURE__ */ jsxDEV2(Button, {
997
+ className: "w-full justify-start",
998
+ variant: "ghost",
999
+ onPress: () => setMode("execute"),
1000
+ children: [
1001
+ /* @__PURE__ */ jsxDEV2("span", {
1002
+ className: "mr-2",
1003
+ children: "▶️"
169
1004
  }, undefined, false, undefined, this),
170
- /* @__PURE__ */ jsxDEV("th", {
171
- className: "text-muted-foreground px-4 py-3 text-right text-sm font-medium",
172
- children: "Duration"
1005
+ " Execute Agent"
1006
+ ]
1007
+ }, undefined, true, undefined, this),
1008
+ (agent.status === "DRAFT" || agent.status === "PAUSED") && /* @__PURE__ */ jsxDEV2(Button, {
1009
+ className: "w-full justify-start",
1010
+ variant: "ghost",
1011
+ onPress: () => handleStatusChange("activate"),
1012
+ disabled: isLoading,
1013
+ children: [
1014
+ /* @__PURE__ */ jsxDEV2("span", {
1015
+ className: "mr-2",
1016
+ children: "\uD83D\uDFE2"
173
1017
  }, undefined, false, undefined, this),
174
- /* @__PURE__ */ jsxDEV("th", {
175
- className: "text-muted-foreground px-4 py-3 text-right text-sm font-medium",
176
- children: "Cost"
177
- }, undefined, false, undefined, this)
1018
+ " Activate Agent"
178
1019
  ]
179
- }, undefined, true, undefined, this)
180
- }, undefined, false, undefined, this),
181
- /* @__PURE__ */ jsxDEV("tbody", {
182
- className: "divide-border divide-y",
183
- children: data.items.map((run) => /* @__PURE__ */ jsxDEV("tr", {
184
- className: "hover:bg-muted/50 cursor-pointer transition-colors",
185
- onClick: () => onRunClick?.(run.id),
1020
+ }, undefined, true, undefined, this),
1021
+ agent.status === "ACTIVE" && /* @__PURE__ */ jsxDEV2(Button, {
1022
+ className: "w-full justify-start",
1023
+ variant: "ghost",
1024
+ onPress: () => handleStatusChange("pause"),
1025
+ disabled: isLoading,
186
1026
  children: [
187
- /* @__PURE__ */ jsxDEV("td", {
188
- className: "px-4 py-3",
189
- children: [
190
- /* @__PURE__ */ jsxDEV("div", {
191
- className: "font-mono text-sm",
192
- children: run.id.slice(-8)
193
- }, undefined, false, undefined, this),
194
- /* @__PURE__ */ jsxDEV("div", {
195
- className: "text-muted-foreground text-xs",
196
- children: run.queuedAt.toLocaleString()
197
- }, undefined, false, undefined, this)
198
- ]
199
- }, undefined, true, undefined, this),
200
- /* @__PURE__ */ jsxDEV("td", {
201
- className: "px-4 py-3",
202
- children: /* @__PURE__ */ jsxDEV("span", {
203
- className: "font-medium",
204
- children: run.agentName
205
- }, undefined, false, undefined, this)
1027
+ /* @__PURE__ */ jsxDEV2("span", {
1028
+ className: "mr-2",
1029
+ children: "⏸️"
206
1030
  }, undefined, false, undefined, this),
207
- /* @__PURE__ */ jsxDEV("td", {
208
- className: "px-4 py-3",
209
- children: /* @__PURE__ */ jsxDEV(StatusChip, {
210
- tone: getStatusTone(run.status),
211
- label: run.status
212
- }, undefined, false, undefined, this)
1031
+ " Pause Agent"
1032
+ ]
1033
+ }, undefined, true, undefined, this),
1034
+ agent.status !== "ARCHIVED" && /* @__PURE__ */ jsxDEV2(Button, {
1035
+ className: "w-full justify-start text-yellow-600 hover:text-yellow-700",
1036
+ variant: "ghost",
1037
+ onPress: () => {
1038
+ setConfirmAction("archive");
1039
+ setMode("confirm");
1040
+ },
1041
+ children: [
1042
+ /* @__PURE__ */ jsxDEV2("span", {
1043
+ className: "mr-2",
1044
+ children: "\uD83D\uDCE6"
213
1045
  }, undefined, false, undefined, this),
214
- /* @__PURE__ */ jsxDEV("td", {
215
- className: "px-4 py-3 text-right font-mono text-sm",
216
- children: formatTokens(run.totalTokens)
1046
+ " Archive Agent"
1047
+ ]
1048
+ }, undefined, true, undefined, this),
1049
+ agent.status === "ARCHIVED" && /* @__PURE__ */ jsxDEV2(Button, {
1050
+ className: "w-full justify-start",
1051
+ variant: "ghost",
1052
+ onPress: () => handleStatusChange("activate"),
1053
+ disabled: isLoading,
1054
+ children: [
1055
+ /* @__PURE__ */ jsxDEV2("span", {
1056
+ className: "mr-2",
1057
+ children: "\uD83D\uDD04"
217
1058
  }, undefined, false, undefined, this),
218
- /* @__PURE__ */ jsxDEV("td", {
219
- className: "px-4 py-3 text-right font-mono text-sm",
220
- children: formatDuration(run.durationMs)
1059
+ " Restore Agent"
1060
+ ]
1061
+ }, undefined, true, undefined, this),
1062
+ error && /* @__PURE__ */ jsxDEV2("div", {
1063
+ className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
1064
+ children: error
1065
+ }, undefined, false, undefined, this),
1066
+ /* @__PURE__ */ jsxDEV2("div", {
1067
+ className: "border-border border-t pt-3",
1068
+ children: /* @__PURE__ */ jsxDEV2(Button, {
1069
+ className: "w-full",
1070
+ variant: "outline",
1071
+ onPress: handleClose,
1072
+ children: "Close"
1073
+ }, undefined, false, undefined, this)
1074
+ }, undefined, false, undefined, this)
1075
+ ]
1076
+ }, undefined, true, undefined, this),
1077
+ mode === "execute" && /* @__PURE__ */ jsxDEV2("div", {
1078
+ className: "space-y-4",
1079
+ children: [
1080
+ /* @__PURE__ */ jsxDEV2("div", {
1081
+ children: [
1082
+ /* @__PURE__ */ jsxDEV2("label", {
1083
+ htmlFor: "execute-message",
1084
+ className: "mb-1 block font-medium text-muted-foreground text-sm",
1085
+ children: "Message *"
221
1086
  }, undefined, false, undefined, this),
222
- /* @__PURE__ */ jsxDEV("td", {
223
- className: "px-4 py-3 text-right font-mono text-sm",
224
- children: formatCost(run.estimatedCostUsd)
1087
+ /* @__PURE__ */ jsxDEV2("textarea", {
1088
+ id: "execute-message",
1089
+ value: message,
1090
+ onChange: (e) => setMessage(e.target.value),
1091
+ placeholder: "Enter your message to the agent...",
1092
+ rows: 4,
1093
+ disabled: isLoading,
1094
+ className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
225
1095
  }, undefined, false, undefined, this)
226
1096
  ]
227
- }, run.id, true, undefined, this))
228
- }, undefined, false, undefined, this)
229
- ]
230
- }, undefined, true, undefined, this)
231
- }, undefined, false, undefined, this),
232
- /* @__PURE__ */ jsxDEV("div", {
233
- className: "text-muted-foreground text-center text-sm",
234
- children: [
235
- "Showing ",
236
- data.items.length,
237
- " of ",
238
- data.total,
239
- " runs"
240
- ]
241
- }, undefined, true, undefined, this)
242
- ]
243
- }, undefined, true, undefined, this);
244
- }
245
-
246
- // src/ui/hooks/useToolList.ts
247
- import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
248
- import { useTemplateRuntime as useTemplateRuntime2 } from "@contractspec/lib.example-shared-ui";
249
- function useToolList(options = {}) {
250
- const { handlers, projectId } = useTemplateRuntime2();
251
- const { agent } = handlers;
252
- const [data, setData] = useState2(null);
253
- const [loading, setLoading] = useState2(true);
254
- const [error, setError] = useState2(null);
255
- const [page, setPage] = useState2(1);
256
- const fetchData = useCallback2(async () => {
257
- setLoading(true);
258
- setError(null);
259
- try {
260
- const result = await agent.listTools({
261
- projectId,
262
- search: options.search,
263
- category: options.category,
264
- status: options.status === "all" ? undefined : options.status,
265
- limit: options.limit ?? 50,
266
- offset: (page - 1) * (options.limit ?? 50)
267
- });
268
- setData(result);
269
- } catch (err) {
270
- setError(err instanceof Error ? err : new Error("Unknown error"));
271
- } finally {
272
- setLoading(false);
273
- }
274
- }, [
275
- agent,
276
- projectId,
277
- options.search,
278
- options.category,
279
- options.status,
280
- options.limit,
281
- page
282
- ]);
283
- useEffect2(() => {
284
- fetchData();
285
- }, [fetchData]);
286
- const { stats, groupedByCategory, categoryStats } = useMemo(() => {
287
- if (!data)
288
- return { stats: null, groupedByCategory: {}, categoryStats: [] };
289
- const items = data.items;
290
- const active = items.filter((t) => t.status === "ACTIVE").length;
291
- const deprecated = items.filter((t) => t.status === "DEPRECATED").length;
292
- const disabled = items.filter((t) => t.status === "DISABLED").length;
293
- const grouped = {};
294
- const byCategory = {};
295
- items.forEach((t) => {
296
- const cat = t.category;
297
- if (!grouped[cat])
298
- grouped[cat] = [];
299
- grouped[cat].push(t);
300
- byCategory[cat] = (byCategory[cat] || 0) + 1;
301
- });
302
- const catStats = Object.entries(byCategory).map(([category, count]) => ({ category, count })).sort((a, b) => b.count - a.count);
303
- return {
304
- stats: {
305
- total: data.total,
306
- active,
307
- deprecated,
308
- disabled,
309
- topCategories: catStats.slice(0, 5)
310
- },
311
- groupedByCategory: grouped,
312
- categoryStats: catStats
313
- };
314
- }, [data]);
315
- return {
316
- data,
317
- loading,
318
- error,
319
- stats,
320
- groupedByCategory,
321
- categoryStats,
322
- page,
323
- refetch: fetchData,
324
- nextPage: () => setPage((p) => p + 1),
325
- prevPage: () => page > 1 && setPage((p) => p - 1)
326
- };
327
- }
328
-
329
- // src/ui/views/ToolRegistryView.tsx
330
- import {
331
- StatCard as StatCard2,
332
- StatCardGroup as StatCardGroup2,
333
- StatusChip as StatusChip2,
334
- EntityCard,
335
- EmptyState as EmptyState2,
336
- LoaderBlock as LoaderBlock2,
337
- ErrorState as ErrorState2,
338
- Button
339
- } from "@contractspec/lib.design-system";
340
- import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
341
- "use client";
342
- var categoryIcons = {
343
- RETRIEVAL: "\uD83D\uDD0D",
344
- COMPUTATION: "\uD83E\uDDEE",
345
- COMMUNICATION: "\uD83D\uDCE7",
346
- INTEGRATION: "\uD83D\uDD17",
347
- UTILITY: "\uD83D\uDEE0️",
348
- CUSTOM: "⚙️"
349
- };
350
- function getStatusTone2(status) {
351
- switch (status) {
352
- case "ACTIVE":
353
- return "success";
354
- case "DRAFT":
355
- return "neutral";
356
- case "DEPRECATED":
357
- return "warning";
358
- case "DISABLED":
359
- return "danger";
360
- default:
361
- return "neutral";
362
- }
363
- }
364
- function ToolRegistryView({
365
- onToolClick,
366
- onCreateTool
367
- }) {
368
- const { data, loading, error, groupedByCategory, categoryStats, refetch } = useToolList();
369
- if (loading && !data) {
370
- return /* @__PURE__ */ jsxDEV2(LoaderBlock2, {
371
- label: "Loading tools..."
372
- }, undefined, false, undefined, this);
373
- }
374
- if (error) {
375
- return /* @__PURE__ */ jsxDEV2(ErrorState2, {
376
- title: "Failed to load tools",
377
- description: error.message,
378
- onRetry: refetch,
379
- retryLabel: "Retry"
380
- }, undefined, false, undefined, this);
381
- }
382
- if (!data?.items.length) {
383
- return /* @__PURE__ */ jsxDEV2(EmptyState2, {
384
- title: "No tools registered",
385
- description: "Create your first tool to extend agent capabilities.",
386
- primaryAction: onCreateTool ? /* @__PURE__ */ jsxDEV2(Button, {
387
- onPress: onCreateTool,
388
- children: "Create Tool"
389
- }, undefined, false, undefined, this) : undefined
390
- }, undefined, false, undefined, this);
391
- }
392
- return /* @__PURE__ */ jsxDEV2("div", {
393
- className: "space-y-8",
394
- children: [
395
- /* @__PURE__ */ jsxDEV2(StatCardGroup2, {
396
- children: [
397
- /* @__PURE__ */ jsxDEV2(StatCard2, {
398
- label: "Total Tools",
399
- value: data.total
400
- }, undefined, false, undefined, this),
401
- categoryStats.slice(0, 3).map(({ category, count }) => /* @__PURE__ */ jsxDEV2(StatCard2, {
402
- label: `${categoryIcons[category] ?? ""} ${category}`,
403
- value: count
404
- }, category, false, undefined, this))
405
- ]
406
- }, undefined, true, undefined, this),
407
- Object.entries(groupedByCategory).map(([category, tools]) => /* @__PURE__ */ jsxDEV2("section", {
408
- className: "space-y-4",
409
- children: [
410
- /* @__PURE__ */ jsxDEV2("div", {
411
- className: "flex items-center gap-2",
412
- children: [
413
- /* @__PURE__ */ jsxDEV2("span", {
414
- className: "text-2xl",
415
- children: categoryIcons[category]
416
- }, undefined, false, undefined, this),
417
- /* @__PURE__ */ jsxDEV2("h3", {
418
- className: "text-lg font-semibold",
419
- children: category
1097
+ }, undefined, true, undefined, this),
1098
+ error && /* @__PURE__ */ jsxDEV2("div", {
1099
+ className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
1100
+ children: error
420
1101
  }, undefined, false, undefined, this),
421
- /* @__PURE__ */ jsxDEV2("span", {
422
- className: "bg-muted text-muted-foreground rounded-full px-2 py-0.5 text-xs",
423
- children: tools.length
424
- }, undefined, false, undefined, this)
1102
+ /* @__PURE__ */ jsxDEV2("div", {
1103
+ className: "flex justify-end gap-3 pt-2",
1104
+ children: [
1105
+ /* @__PURE__ */ jsxDEV2(Button, {
1106
+ variant: "ghost",
1107
+ onPress: () => setMode("menu"),
1108
+ disabled: isLoading,
1109
+ children: "Back"
1110
+ }, undefined, false, undefined, this),
1111
+ /* @__PURE__ */ jsxDEV2(Button, {
1112
+ onPress: handleExecute,
1113
+ disabled: isLoading,
1114
+ children: isLoading ? "Executing..." : "▶️ Execute"
1115
+ }, undefined, false, undefined, this)
1116
+ ]
1117
+ }, undefined, true, undefined, this)
425
1118
  ]
426
1119
  }, undefined, true, undefined, this),
427
- /* @__PURE__ */ jsxDEV2("div", {
428
- className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
429
- children: tools.map((tool) => /* @__PURE__ */ jsxDEV2(EntityCard, {
430
- cardTitle: tool.name,
431
- cardSubtitle: `v${tool.version}`,
432
- meta: /* @__PURE__ */ jsxDEV2("p", {
1120
+ mode === "confirm" && confirmAction === "archive" && /* @__PURE__ */ jsxDEV2("div", {
1121
+ className: "space-y-4",
1122
+ children: [
1123
+ /* @__PURE__ */ jsxDEV2("p", {
1124
+ className: "text-muted-foreground",
1125
+ children: [
1126
+ "Are you sure you want to archive",
1127
+ " ",
1128
+ /* @__PURE__ */ jsxDEV2("span", {
1129
+ className: "font-medium text-foreground",
1130
+ children: agent.name
1131
+ }, undefined, false, undefined, this),
1132
+ "?"
1133
+ ]
1134
+ }, undefined, true, undefined, this),
1135
+ /* @__PURE__ */ jsxDEV2("p", {
433
1136
  className: "text-muted-foreground text-sm",
434
- children: tool.description
435
- }, undefined, false, undefined, this),
436
- chips: /* @__PURE__ */ jsxDEV2(StatusChip2, {
437
- tone: getStatusTone2(tool.status),
438
- label: tool.status
1137
+ children: "Archived agents cannot be executed but can be restored later."
439
1138
  }, undefined, false, undefined, this),
440
- footer: /* @__PURE__ */ jsxDEV2("code", {
441
- className: "text-muted-foreground text-xs",
442
- children: tool.name
1139
+ error && /* @__PURE__ */ jsxDEV2("div", {
1140
+ className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
1141
+ children: error
443
1142
  }, undefined, false, undefined, this),
444
- onClick: onToolClick ? () => onToolClick(tool.id) : undefined
445
- }, tool.id, false, undefined, this))
446
- }, undefined, false, undefined, this)
1143
+ /* @__PURE__ */ jsxDEV2("div", {
1144
+ className: "flex justify-end gap-3 pt-2",
1145
+ children: [
1146
+ /* @__PURE__ */ jsxDEV2(Button, {
1147
+ variant: "ghost",
1148
+ onPress: () => setMode("menu"),
1149
+ disabled: isLoading,
1150
+ children: "Cancel"
1151
+ }, undefined, false, undefined, this),
1152
+ /* @__PURE__ */ jsxDEV2(Button, {
1153
+ onPress: () => handleStatusChange("archive"),
1154
+ disabled: isLoading,
1155
+ children: isLoading ? "Archiving..." : "\uD83D\uDCE6 Archive"
1156
+ }, undefined, false, undefined, this)
1157
+ ]
1158
+ }, undefined, true, undefined, this)
1159
+ ]
1160
+ }, undefined, true, undefined, this)
447
1161
  ]
448
- }, category, true, undefined, this))
1162
+ }, undefined, true, undefined, this)
449
1163
  ]
450
1164
  }, undefined, true, undefined, this);
451
1165
  }
452
1166
 
453
- // src/ui/hooks/useAgentList.ts
454
- import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo2, useState as useState3 } from "react";
455
- import { useTemplateRuntime as useTemplateRuntime3 } from "@contractspec/lib.example-shared-ui";
456
- function useAgentList(options = {}) {
457
- const { handlers, projectId } = useTemplateRuntime3();
458
- const { agent } = handlers;
459
- const [data, setData] = useState3(null);
460
- const [loading, setLoading] = useState3(true);
461
- const [error, setError] = useState3(null);
462
- const [page, setPage] = useState3(1);
463
- const fetchData = useCallback3(async () => {
464
- setLoading(true);
465
- setError(null);
466
- try {
467
- const result = await agent.listAgents({
468
- projectId,
469
- search: options.search,
470
- status: options.status === "all" ? undefined : options.status,
471
- limit: options.limit ?? 20,
472
- offset: (page - 1) * (options.limit ?? 20)
473
- });
474
- setData(result);
475
- } catch (err) {
476
- setError(err instanceof Error ? err : new Error("Unknown error"));
477
- } finally {
478
- setLoading(false);
479
- }
480
- }, [agent, projectId, options.search, options.status, options.limit, page]);
481
- useEffect3(() => {
482
- fetchData();
483
- }, [fetchData]);
484
- const stats = useMemo2(() => {
485
- if (!data)
486
- return null;
487
- return {
488
- total: data.total,
489
- active: data.items.filter((a) => a.status === "ACTIVE").length,
490
- paused: data.items.filter((a) => a.status === "PAUSED").length,
491
- draft: data.items.filter((a) => a.status === "DRAFT").length
492
- };
493
- }, [data]);
494
- return {
495
- data,
496
- loading,
497
- error,
498
- stats,
499
- page,
500
- refetch: fetchData,
501
- nextPage: () => setPage((p) => p + 1),
502
- prevPage: () => page > 1 && setPage((p) => p - 1)
503
- };
504
- }
505
-
506
- // src/ui/hooks/useAgentMutations.ts
507
- import { useCallback as useCallback4, useState as useState4 } from "react";
508
- import { useTemplateRuntime as useTemplateRuntime4 } from "@contractspec/lib.example-shared-ui";
509
- function useAgentMutations(options = {}) {
510
- const { handlers, projectId } = useTemplateRuntime4();
511
- const { agent } = handlers;
512
- const [createState, setCreateState] = useState4({
513
- loading: false,
514
- error: null,
515
- data: null
516
- });
517
- const [updateState, setUpdateState] = useState4({
518
- loading: false,
519
- error: null,
520
- data: null
521
- });
522
- const [executeState, setExecuteState] = useState4({
523
- loading: false,
524
- error: null,
525
- data: null
526
- });
527
- const createAgent = useCallback4(async (input) => {
528
- setCreateState({ loading: true, error: null, data: null });
529
- try {
530
- const result = await agent.createAgent(input, {
531
- projectId,
532
- organizationId: "demo-org"
533
- });
534
- setCreateState({ loading: false, error: null, data: result });
535
- options.onSuccess?.();
536
- return result;
537
- } catch (err) {
538
- const error = err instanceof Error ? err : new Error("Failed to create agent");
539
- setCreateState({ loading: false, error, data: null });
540
- options.onError?.(error);
541
- return null;
542
- }
543
- }, [agent, projectId, options]);
544
- const updateAgent = useCallback4(async (input) => {
545
- setUpdateState({ loading: true, error: null, data: null });
546
- try {
547
- const result = await agent.updateAgent(input);
548
- setUpdateState({ loading: false, error: null, data: result });
549
- options.onSuccess?.();
550
- return result;
551
- } catch (err) {
552
- const error = err instanceof Error ? err : new Error("Failed to update agent");
553
- setUpdateState({ loading: false, error, data: null });
554
- options.onError?.(error);
555
- return null;
556
- }
557
- }, [agent, options]);
558
- const activateAgent = useCallback4(async (agentId) => {
559
- return updateAgent({ id: agentId, status: "ACTIVE" });
560
- }, [updateAgent]);
561
- const pauseAgent = useCallback4(async (agentId) => {
562
- return updateAgent({ id: agentId, status: "PAUSED" });
563
- }, [updateAgent]);
564
- const archiveAgent = useCallback4(async (agentId) => {
565
- return updateAgent({ id: agentId, status: "ARCHIVED" });
566
- }, [updateAgent]);
567
- const executeAgent = useCallback4(async (input) => {
568
- setExecuteState({ loading: true, error: null, data: null });
569
- try {
570
- const result = await agent.executeAgent({
571
- agentId: input.agentId,
572
- message: input.message,
573
- context: { projectId, organizationId: "demo-org" }
574
- });
575
- setExecuteState({ loading: false, error: null, data: result });
576
- options.onSuccess?.();
577
- return result;
578
- } catch (err) {
579
- const error = err instanceof Error ? err : new Error("Failed to execute agent");
580
- setExecuteState({ loading: false, error, data: null });
581
- options.onError?.(error);
582
- return null;
583
- }
584
- }, [agent, projectId, options]);
585
- return {
586
- createAgent,
587
- updateAgent,
588
- activateAgent,
589
- pauseAgent,
590
- archiveAgent,
591
- executeAgent,
592
- createState,
593
- updateState,
594
- executeState,
595
- isLoading: createState.loading || updateState.loading || executeState.loading
596
- };
597
- }
598
-
599
1167
  // src/ui/modals/CreateAgentModal.tsx
600
- import { useState as useState5 } from "react";
601
1168
  import { Button as Button2, Input } from "@contractspec/lib.design-system";
1169
+ import { useState as useState5 } from "react";
602
1170
  import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
603
1171
  "use client";
604
1172
  var MODEL_PROVIDERS = [
@@ -684,7 +1252,7 @@ function CreateAgentModal({
684
1252
  className: "fixed inset-0 z-50 flex items-center justify-center",
685
1253
  children: [
686
1254
  /* @__PURE__ */ jsxDEV3("div", {
687
- className: "bg-background/80 absolute inset-0 backdrop-blur-sm",
1255
+ className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
688
1256
  onClick: onClose,
689
1257
  role: "button",
690
1258
  tabIndex: 0,
@@ -695,10 +1263,10 @@ function CreateAgentModal({
695
1263
  "aria-label": "Close modal"
696
1264
  }, undefined, false, undefined, this),
697
1265
  /* @__PURE__ */ jsxDEV3("div", {
698
- className: "bg-card border-border relative z-10 max-h-[90vh] w-full max-w-lg overflow-y-auto rounded-xl border p-6 shadow-xl",
1266
+ className: "relative z-10 max-h-[90vh] w-full max-w-lg overflow-y-auto rounded-xl border border-border bg-card p-6 shadow-xl",
699
1267
  children: [
700
1268
  /* @__PURE__ */ jsxDEV3("h2", {
701
- className: "mb-4 text-xl font-semibold",
1269
+ className: "mb-4 font-semibold text-xl",
702
1270
  children: "Create New Agent"
703
1271
  }, undefined, false, undefined, this),
704
1272
  /* @__PURE__ */ jsxDEV3("form", {
@@ -709,7 +1277,7 @@ function CreateAgentModal({
709
1277
  children: [
710
1278
  /* @__PURE__ */ jsxDEV3("label", {
711
1279
  htmlFor: "agent-name",
712
- className: "text-muted-foreground mb-1 block text-sm font-medium",
1280
+ className: "mb-1 block font-medium text-muted-foreground text-sm",
713
1281
  children: "Agent Name *"
714
1282
  }, undefined, false, undefined, this),
715
1283
  /* @__PURE__ */ jsxDEV3(Input, {
@@ -725,7 +1293,7 @@ function CreateAgentModal({
725
1293
  children: [
726
1294
  /* @__PURE__ */ jsxDEV3("label", {
727
1295
  htmlFor: "agent-description",
728
- className: "text-muted-foreground mb-1 block text-sm font-medium",
1296
+ className: "mb-1 block font-medium text-muted-foreground text-sm",
729
1297
  children: "Description"
730
1298
  }, undefined, false, undefined, this),
731
1299
  /* @__PURE__ */ jsxDEV3("textarea", {
@@ -735,7 +1303,7 @@ function CreateAgentModal({
735
1303
  placeholder: "Describe what this agent does...",
736
1304
  rows: 2,
737
1305
  disabled: isLoading,
738
- className: "border-input bg-background focus:ring-ring w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none disabled:opacity-50"
1306
+ className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
739
1307
  }, undefined, false, undefined, this)
740
1308
  ]
741
1309
  }, undefined, true, undefined, this),
@@ -747,7 +1315,7 @@ function CreateAgentModal({
747
1315
  children: [
748
1316
  /* @__PURE__ */ jsxDEV3("label", {
749
1317
  htmlFor: "model-provider",
750
- className: "text-muted-foreground mb-1 block text-sm font-medium",
1318
+ className: "mb-1 block font-medium text-muted-foreground text-sm",
751
1319
  children: "Provider *"
752
1320
  }, undefined, false, undefined, this),
753
1321
  /* @__PURE__ */ jsxDEV3("select", {
@@ -755,7 +1323,7 @@ function CreateAgentModal({
755
1323
  value: modelProvider,
756
1324
  onChange: (e) => handleProviderChange(e.target.value),
757
1325
  disabled: isLoading,
758
- className: "border-input bg-background focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none disabled:opacity-50",
1326
+ className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50",
759
1327
  children: MODEL_PROVIDERS.map((p) => /* @__PURE__ */ jsxDEV3("option", {
760
1328
  value: p.value,
761
1329
  children: p.label
@@ -768,7 +1336,7 @@ function CreateAgentModal({
768
1336
  children: [
769
1337
  /* @__PURE__ */ jsxDEV3("label", {
770
1338
  htmlFor: "model-name",
771
- className: "text-muted-foreground mb-1 block text-sm font-medium",
1339
+ className: "mb-1 block font-medium text-muted-foreground text-sm",
772
1340
  children: "Model *"
773
1341
  }, undefined, false, undefined, this),
774
1342
  /* @__PURE__ */ jsxDEV3("select", {
@@ -776,7 +1344,7 @@ function CreateAgentModal({
776
1344
  value: modelName,
777
1345
  onChange: (e) => setModelName(e.target.value),
778
1346
  disabled: isLoading,
779
- className: "border-input bg-background focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none disabled:opacity-50",
1347
+ className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50",
780
1348
  children: selectedProvider?.models.map((m) => /* @__PURE__ */ jsxDEV3("option", {
781
1349
  value: m,
782
1350
  children: m
@@ -790,7 +1358,7 @@ function CreateAgentModal({
790
1358
  children: [
791
1359
  /* @__PURE__ */ jsxDEV3("label", {
792
1360
  htmlFor: "system-prompt",
793
- className: "text-muted-foreground mb-1 block text-sm font-medium",
1361
+ className: "mb-1 block font-medium text-muted-foreground text-sm",
794
1362
  children: "System Prompt"
795
1363
  }, undefined, false, undefined, this),
796
1364
  /* @__PURE__ */ jsxDEV3("textarea", {
@@ -800,16 +1368,16 @@ function CreateAgentModal({
800
1368
  placeholder: "You are a helpful assistant that...",
801
1369
  rows: 4,
802
1370
  disabled: isLoading,
803
- className: "border-input bg-background focus:ring-ring w-full rounded-md border px-3 py-2 font-mono text-sm focus:ring-2 focus:outline-none disabled:opacity-50"
1371
+ className: "w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
804
1372
  }, undefined, false, undefined, this),
805
1373
  /* @__PURE__ */ jsxDEV3("p", {
806
- className: "text-muted-foreground mt-1 text-xs",
1374
+ className: "mt-1 text-muted-foreground text-xs",
807
1375
  children: "Instructions that define the agent's behavior"
808
1376
  }, undefined, false, undefined, this)
809
1377
  ]
810
1378
  }, undefined, true, undefined, this),
811
1379
  error && /* @__PURE__ */ jsxDEV3("div", {
812
- className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
1380
+ className: "rounded-md bg-destructive/10 p-3 text-destructive text-sm",
813
1381
  children: error
814
1382
  }, undefined, false, undefined, this),
815
1383
  /* @__PURE__ */ jsxDEV3("div", {
@@ -837,323 +1405,637 @@ function CreateAgentModal({
837
1405
  }, undefined, true, undefined, this);
838
1406
  }
839
1407
 
840
- // src/ui/modals/AgentActionsModal.tsx
1408
+ // src/ui/views/run-list.shared.tsx
1409
+ import { Button as Button3, StatusChip } from "@contractspec/lib.design-system";
1410
+ import { HStack, VStack } from "@contractspec/lib.ui-kit-web/ui/stack";
1411
+ import { Text } from "@contractspec/lib.ui-kit-web/ui/text";
1412
+ import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
1413
+ "use client";
1414
+ function getStatusTone(status) {
1415
+ switch (status) {
1416
+ case "COMPLETED":
1417
+ return "success";
1418
+ case "RUNNING":
1419
+ return "warning";
1420
+ case "QUEUED":
1421
+ return "neutral";
1422
+ case "FAILED":
1423
+ case "CANCELLED":
1424
+ return "danger";
1425
+ default:
1426
+ return "neutral";
1427
+ }
1428
+ }
1429
+ function formatDuration(ms) {
1430
+ if (!ms)
1431
+ return "-";
1432
+ if (ms < 1000)
1433
+ return `${ms}ms`;
1434
+ if (ms < 60000)
1435
+ return `${(ms / 1000).toFixed(1)}s`;
1436
+ return `${(ms / 60000).toFixed(1)}m`;
1437
+ }
1438
+ function formatTokens(tokens) {
1439
+ if (tokens < 1000)
1440
+ return tokens.toString();
1441
+ if (tokens < 1e6)
1442
+ return `${(tokens / 1000).toFixed(1)}K`;
1443
+ return `${(tokens / 1e6).toFixed(2)}M`;
1444
+ }
1445
+ function formatCost(cost) {
1446
+ if (!cost)
1447
+ return "-";
1448
+ return `$${cost.toFixed(4)}`;
1449
+ }
1450
+ function formatJson(value) {
1451
+ return JSON.stringify(value ?? null, null, 2);
1452
+ }
1453
+ function RunExpandedContent({ run }) {
1454
+ return /* @__PURE__ */ jsxDEV4(VStack, {
1455
+ gap: "sm",
1456
+ className: "py-2",
1457
+ children: [
1458
+ /* @__PURE__ */ jsxDEV4(HStack, {
1459
+ justify: "between",
1460
+ className: "flex-wrap",
1461
+ children: [
1462
+ /* @__PURE__ */ jsxDEV4(StatusChip, {
1463
+ tone: getStatusTone(run.status),
1464
+ label: run.status
1465
+ }, undefined, false, undefined, this),
1466
+ /* @__PURE__ */ jsxDEV4(Text, {
1467
+ className: "text-muted-foreground text-sm",
1468
+ children: [
1469
+ "Queued ",
1470
+ run.queuedAt.toLocaleString()
1471
+ ]
1472
+ }, undefined, true, undefined, this)
1473
+ ]
1474
+ }, undefined, true, undefined, this),
1475
+ /* @__PURE__ */ jsxDEV4(HStack, {
1476
+ gap: "lg",
1477
+ className: "flex-wrap",
1478
+ children: [
1479
+ /* @__PURE__ */ jsxDEV4(Text, {
1480
+ className: "text-muted-foreground text-sm",
1481
+ children: [
1482
+ "Prompt ",
1483
+ formatTokens(run.promptTokens)
1484
+ ]
1485
+ }, undefined, true, undefined, this),
1486
+ /* @__PURE__ */ jsxDEV4(Text, {
1487
+ className: "text-muted-foreground text-sm",
1488
+ children: [
1489
+ "Completion ",
1490
+ formatTokens(run.completionTokens)
1491
+ ]
1492
+ }, undefined, true, undefined, this),
1493
+ /* @__PURE__ */ jsxDEV4(Text, {
1494
+ className: "text-muted-foreground text-sm",
1495
+ children: [
1496
+ "Duration ",
1497
+ formatDuration(run.durationMs)
1498
+ ]
1499
+ }, undefined, true, undefined, this)
1500
+ ]
1501
+ }, undefined, true, undefined, this),
1502
+ /* @__PURE__ */ jsxDEV4(VStack, {
1503
+ gap: "xs",
1504
+ children: [
1505
+ /* @__PURE__ */ jsxDEV4(Text, {
1506
+ className: "font-medium text-sm",
1507
+ children: "Input"
1508
+ }, undefined, false, undefined, this),
1509
+ /* @__PURE__ */ jsxDEV4("pre", {
1510
+ className: "overflow-auto rounded-md bg-muted/40 p-3 text-xs",
1511
+ children: formatJson(run.input)
1512
+ }, undefined, false, undefined, this)
1513
+ ]
1514
+ }, undefined, true, undefined, this),
1515
+ /* @__PURE__ */ jsxDEV4(VStack, {
1516
+ gap: "xs",
1517
+ children: [
1518
+ /* @__PURE__ */ jsxDEV4(Text, {
1519
+ className: "font-medium text-sm",
1520
+ children: "Output"
1521
+ }, undefined, false, undefined, this),
1522
+ /* @__PURE__ */ jsxDEV4("pre", {
1523
+ className: "overflow-auto rounded-md bg-muted/40 p-3 text-xs",
1524
+ children: formatJson(run.output ?? run.errorMessage ?? "Pending")
1525
+ }, undefined, false, undefined, this)
1526
+ ]
1527
+ }, undefined, true, undefined, this)
1528
+ ]
1529
+ }, undefined, true, undefined, this);
1530
+ }
1531
+ function RunTableToolbar({
1532
+ controller,
1533
+ totalRuns
1534
+ }) {
1535
+ const firstRow = controller.rows[0];
1536
+ const queuedColumn = controller.columns.find((column) => column.id === "queuedAt");
1537
+ const durationColumn = controller.columns.find((column) => column.id === "durationMs");
1538
+ const costColumn = controller.columns.find((column) => column.id === "estimatedCostUsd");
1539
+ return /* @__PURE__ */ jsxDEV4(HStack, {
1540
+ gap: "sm",
1541
+ className: "flex-wrap",
1542
+ children: [
1543
+ /* @__PURE__ */ jsxDEV4(Text, {
1544
+ className: "text-muted-foreground text-sm",
1545
+ children: [
1546
+ totalRuns,
1547
+ " runs"
1548
+ ]
1549
+ }, undefined, true, undefined, this),
1550
+ /* @__PURE__ */ jsxDEV4(Button3, {
1551
+ variant: "outline",
1552
+ size: "sm",
1553
+ onPress: () => firstRow?.toggleExpanded?.(!firstRow?.isExpanded),
1554
+ children: "Expand Latest Run"
1555
+ }, undefined, false, undefined, this),
1556
+ /* @__PURE__ */ jsxDEV4(Button3, {
1557
+ variant: "outline",
1558
+ size: "sm",
1559
+ onPress: () => queuedColumn?.toggleVisibility?.(!queuedColumn?.visible),
1560
+ children: queuedColumn?.visible ? "Hide Time" : "Show Time"
1561
+ }, undefined, false, undefined, this),
1562
+ /* @__PURE__ */ jsxDEV4(Button3, {
1563
+ variant: "outline",
1564
+ size: "sm",
1565
+ onPress: () => durationColumn?.toggleVisibility?.(!durationColumn?.visible),
1566
+ children: durationColumn?.visible ? "Hide Duration" : "Show Duration"
1567
+ }, undefined, false, undefined, this),
1568
+ /* @__PURE__ */ jsxDEV4(Button3, {
1569
+ variant: "outline",
1570
+ size: "sm",
1571
+ onPress: () => costColumn?.toggleVisibility?.(!costColumn?.visible),
1572
+ children: costColumn?.visible ? "Hide Cost" : "Show Cost"
1573
+ }, undefined, false, undefined, this)
1574
+ ]
1575
+ }, undefined, true, undefined, this);
1576
+ }
1577
+
1578
+ // src/ui/views/run-data-table.columns.tsx
1579
+ import { StatusChip as StatusChip2 } from "@contractspec/lib.design-system";
1580
+ import { VStack as VStack2 } from "@contractspec/lib.ui-kit-web/ui/stack";
1581
+ import { Text as Text2 } from "@contractspec/lib.ui-kit-web/ui/text";
1582
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
1583
+ "use client";
1584
+ function createRunTableColumns() {
1585
+ return [
1586
+ {
1587
+ id: "queuedAt",
1588
+ header: "Run",
1589
+ label: "Run",
1590
+ accessor: (run) => run.queuedAt.getTime(),
1591
+ cell: ({ item }) => /* @__PURE__ */ jsxDEV5(VStack2, {
1592
+ gap: "xs",
1593
+ children: [
1594
+ /* @__PURE__ */ jsxDEV5(Text2, {
1595
+ className: "font-mono text-sm",
1596
+ children: item.id.slice(-8)
1597
+ }, undefined, false, undefined, this),
1598
+ /* @__PURE__ */ jsxDEV5(Text2, {
1599
+ className: "text-muted-foreground text-xs",
1600
+ children: item.queuedAt.toLocaleString()
1601
+ }, undefined, false, undefined, this)
1602
+ ]
1603
+ }, undefined, true, undefined, this),
1604
+ size: 220,
1605
+ minSize: 180,
1606
+ canSort: true,
1607
+ canHide: true,
1608
+ canResize: true
1609
+ },
1610
+ {
1611
+ id: "agentName",
1612
+ header: "Agent",
1613
+ label: "Agent",
1614
+ accessor: (run) => run.agentName ?? "Unknown Agent",
1615
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV5(Text2, {
1616
+ className: "font-medium",
1617
+ children: typeof value === "string" ? value : "Unknown Agent"
1618
+ }, undefined, false, undefined, this),
1619
+ size: 220,
1620
+ canSort: true,
1621
+ canResize: true
1622
+ },
1623
+ {
1624
+ id: "status",
1625
+ header: "Status",
1626
+ label: "Status",
1627
+ accessorKey: "status",
1628
+ cell: ({ value }) => {
1629
+ const status = typeof value === "string" ? value : "QUEUED";
1630
+ return /* @__PURE__ */ jsxDEV5(StatusChip2, {
1631
+ tone: getStatusTone(status),
1632
+ label: status
1633
+ }, undefined, false, undefined, this);
1634
+ },
1635
+ size: 150,
1636
+ canSort: true,
1637
+ canResize: true
1638
+ },
1639
+ {
1640
+ id: "totalTokens",
1641
+ header: "Tokens",
1642
+ label: "Tokens",
1643
+ accessorKey: "totalTokens",
1644
+ cell: ({ value }) => formatTokens(Number(value ?? 0)),
1645
+ align: "right",
1646
+ size: 140,
1647
+ canSort: true,
1648
+ canResize: true
1649
+ },
1650
+ {
1651
+ id: "durationMs",
1652
+ header: "Duration",
1653
+ label: "Duration",
1654
+ accessorKey: "durationMs",
1655
+ cell: ({ value }) => formatDuration(typeof value === "number" ? value : undefined),
1656
+ align: "right",
1657
+ size: 140,
1658
+ canSort: true,
1659
+ canHide: true,
1660
+ canResize: true
1661
+ },
1662
+ {
1663
+ id: "estimatedCostUsd",
1664
+ header: "Cost",
1665
+ label: "Cost",
1666
+ accessorKey: "estimatedCostUsd",
1667
+ cell: ({ value }) => formatCost(typeof value === "number" ? value : undefined),
1668
+ align: "right",
1669
+ size: 140,
1670
+ canSort: true,
1671
+ canHide: true,
1672
+ canResize: true
1673
+ }
1674
+ ];
1675
+ }
1676
+
1677
+ // src/ui/views/RunDataTable.tsx
1678
+ import { DataTable } from "@contractspec/lib.design-system";
1679
+ import { useContractTable } from "@contractspec/lib.presentation-runtime-react";
1680
+ import * as React from "react";
1681
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
1682
+ "use client";
1683
+ function RunDataTable({
1684
+ runs,
1685
+ totalItems,
1686
+ pageIndex,
1687
+ pageSize,
1688
+ sorting,
1689
+ loading,
1690
+ onSortingChange,
1691
+ onPaginationChange,
1692
+ onRunClick
1693
+ }) {
1694
+ const columns = React.useMemo(() => createRunTableColumns(), []);
1695
+ const controller = useContractTable({
1696
+ data: runs,
1697
+ columns,
1698
+ executionMode: "server",
1699
+ totalItems,
1700
+ state: {
1701
+ sorting,
1702
+ pagination: { pageIndex, pageSize }
1703
+ },
1704
+ onSortingChange,
1705
+ onPaginationChange,
1706
+ initialState: {
1707
+ columnVisibility: { estimatedCostUsd: false }
1708
+ },
1709
+ getRowId: (run) => run.id,
1710
+ renderExpandedContent: (run) => /* @__PURE__ */ jsxDEV6(RunExpandedContent, {
1711
+ run
1712
+ }, undefined, false, undefined, this),
1713
+ getCanExpand: () => true
1714
+ });
1715
+ return /* @__PURE__ */ jsxDEV6(DataTable, {
1716
+ controller,
1717
+ title: "Run History",
1718
+ description: "Server-mode ContractSpec table with shared pagination, sorting, visibility, and expansion.",
1719
+ loading,
1720
+ onRowPress: (row) => onRunClick?.(row.id),
1721
+ toolbar: /* @__PURE__ */ jsxDEV6(RunTableToolbar, {
1722
+ controller,
1723
+ totalRuns: totalItems
1724
+ }, undefined, false, undefined, this),
1725
+ emptyState: /* @__PURE__ */ jsxDEV6("div", {
1726
+ className: "rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",
1727
+ children: "No runs yet"
1728
+ }, undefined, false, undefined, this)
1729
+ }, undefined, false, undefined, this);
1730
+ }
1731
+
1732
+ // src/ui/views/RunListView.tsx
1733
+ import {
1734
+ EmptyState,
1735
+ ErrorState,
1736
+ LoaderBlock,
1737
+ StatCard,
1738
+ StatCardGroup
1739
+ } from "@contractspec/lib.design-system";
841
1740
  import { useState as useState6 } from "react";
842
- import { Button as Button3 } from "@contractspec/lib.design-system";
843
- import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
1741
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
844
1742
  "use client";
845
- function getStatusColor(status) {
846
- switch (status) {
847
- case "ACTIVE":
848
- return "text-green-600 bg-green-100 dark:text-green-400 dark:bg-green-900/30";
849
- case "DRAFT":
850
- return "text-blue-600 bg-blue-100 dark:text-blue-400 dark:bg-blue-900/30";
851
- case "PAUSED":
852
- return "text-yellow-600 bg-yellow-100 dark:text-yellow-400 dark:bg-yellow-900/30";
853
- case "ARCHIVED":
854
- return "text-gray-600 bg-gray-100 dark:text-gray-400 dark:bg-gray-700";
855
- default:
856
- return "text-gray-600 bg-gray-100";
1743
+ function RunListView({ agentId, onRunClick }) {
1744
+ const [sorting, setSorting] = useState6([
1745
+ { id: "queuedAt", desc: true }
1746
+ ]);
1747
+ const [pagination, setPagination] = useState6({
1748
+ pageIndex: 0,
1749
+ pageSize: 3
1750
+ });
1751
+ const { data, metrics, loading, error, refetch } = useRunList({
1752
+ agentId,
1753
+ pageIndex: pagination.pageIndex,
1754
+ pageSize: pagination.pageSize,
1755
+ sorting
1756
+ });
1757
+ if (loading && !data) {
1758
+ return /* @__PURE__ */ jsxDEV7(LoaderBlock, {
1759
+ label: "Loading runs..."
1760
+ }, undefined, false, undefined, this);
1761
+ }
1762
+ if (error) {
1763
+ return /* @__PURE__ */ jsxDEV7(ErrorState, {
1764
+ title: "Failed to load runs",
1765
+ description: error.message,
1766
+ onRetry: refetch,
1767
+ retryLabel: "Retry"
1768
+ }, undefined, false, undefined, this);
1769
+ }
1770
+ if (!data?.items.length) {
1771
+ return /* @__PURE__ */ jsxDEV7(EmptyState, {
1772
+ title: "No runs yet",
1773
+ description: "Execute an agent to see run history here."
1774
+ }, undefined, false, undefined, this);
857
1775
  }
1776
+ return /* @__PURE__ */ jsxDEV7("div", {
1777
+ className: "space-y-6",
1778
+ children: [
1779
+ metrics ? /* @__PURE__ */ jsxDEV7(StatCardGroup, {
1780
+ children: [
1781
+ /* @__PURE__ */ jsxDEV7(StatCard, {
1782
+ label: "Total Runs",
1783
+ value: metrics.totalRuns
1784
+ }, undefined, false, undefined, this),
1785
+ /* @__PURE__ */ jsxDEV7(StatCard, {
1786
+ label: "Success Rate",
1787
+ value: `${(metrics.successRate * 100).toFixed(1)}%`
1788
+ }, undefined, false, undefined, this),
1789
+ /* @__PURE__ */ jsxDEV7(StatCard, {
1790
+ label: "Total Tokens",
1791
+ value: formatTokens(metrics.totalTokens)
1792
+ }, undefined, false, undefined, this),
1793
+ /* @__PURE__ */ jsxDEV7(StatCard, {
1794
+ label: "Total Cost",
1795
+ value: `$${metrics.totalCostUsd.toFixed(2)}`
1796
+ }, undefined, false, undefined, this)
1797
+ ]
1798
+ }, undefined, true, undefined, this) : null,
1799
+ /* @__PURE__ */ jsxDEV7(RunDataTable, {
1800
+ runs: data.items,
1801
+ totalItems: data.total,
1802
+ pageIndex: pagination.pageIndex,
1803
+ pageSize: pagination.pageSize,
1804
+ sorting,
1805
+ loading,
1806
+ onSortingChange: (nextSorting) => {
1807
+ setSorting(nextSorting);
1808
+ setPagination((current) => ({ ...current, pageIndex: 0 }));
1809
+ },
1810
+ onPaginationChange: setPagination,
1811
+ onRunClick
1812
+ }, undefined, false, undefined, this)
1813
+ ]
1814
+ }, undefined, true, undefined, this);
858
1815
  }
859
- function AgentActionsModal({
860
- isOpen,
861
- agent,
862
- onClose,
863
- onActivate,
864
- onPause,
865
- onArchive,
866
- onExecute,
867
- isLoading = false
868
- }) {
869
- const [mode, setMode] = useState6("menu");
870
- const [message, setMessage] = useState6("");
871
- const [confirmAction, setConfirmAction] = useState6(null);
872
- const [error, setError] = useState6(null);
873
- const resetForm = () => {
874
- setMode("menu");
875
- setMessage("");
876
- setConfirmAction(null);
877
- setError(null);
878
- };
879
- const handleClose = () => {
880
- resetForm();
881
- onClose();
882
- };
883
- const handleExecute = async () => {
884
- if (!agent)
885
- return;
886
- setError(null);
887
- if (!message.trim()) {
888
- setError("Please enter a message");
889
- return;
890
- }
891
- try {
892
- await onExecute(agent.id, message.trim());
893
- handleClose();
894
- } catch (err) {
895
- setError(err instanceof Error ? err.message : "Failed to execute agent");
896
- }
897
- };
898
- const handleStatusChange = async (action) => {
899
- if (!agent)
900
- return;
1816
+
1817
+ // src/ui/hooks/useToolList.ts
1818
+ import { useTemplateRuntime as useTemplateRuntime4 } from "@contractspec/lib.example-shared-ui";
1819
+ import { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo3, useState as useState7 } from "react";
1820
+ function useToolList(options = {}) {
1821
+ const { handlers, projectId } = useTemplateRuntime4();
1822
+ const { agent } = handlers;
1823
+ const [data, setData] = useState7(null);
1824
+ const [loading, setLoading] = useState7(true);
1825
+ const [error, setError] = useState7(null);
1826
+ const [page, setPage] = useState7(1);
1827
+ const fetchData = useCallback4(async () => {
1828
+ setLoading(true);
901
1829
  setError(null);
902
1830
  try {
903
- switch (action) {
904
- case "activate":
905
- await onActivate(agent.id);
906
- break;
907
- case "pause":
908
- await onPause(agent.id);
909
- break;
910
- case "archive":
911
- await onArchive(agent.id);
912
- break;
913
- }
914
- handleClose();
1831
+ const result = await agent.listTools({
1832
+ projectId,
1833
+ search: options.search,
1834
+ category: options.category,
1835
+ status: options.status === "all" ? undefined : options.status,
1836
+ limit: options.limit ?? 50,
1837
+ offset: (page - 1) * (options.limit ?? 50)
1838
+ });
1839
+ setData(result);
915
1840
  } catch (err) {
916
- setError(err instanceof Error ? err.message : `Failed to ${action} agent`);
1841
+ setError(err instanceof Error ? err : new Error("Unknown error"));
1842
+ } finally {
1843
+ setLoading(false);
917
1844
  }
1845
+ }, [
1846
+ agent,
1847
+ projectId,
1848
+ options.search,
1849
+ options.category,
1850
+ options.status,
1851
+ options.limit,
1852
+ page
1853
+ ]);
1854
+ useEffect3(() => {
1855
+ fetchData();
1856
+ }, [fetchData]);
1857
+ const { stats, groupedByCategory, categoryStats } = useMemo3(() => {
1858
+ if (!data)
1859
+ return { stats: null, groupedByCategory: {}, categoryStats: [] };
1860
+ const items = data.items;
1861
+ const active = items.filter((t) => t.status === "ACTIVE").length;
1862
+ const deprecated = items.filter((t) => t.status === "DEPRECATED").length;
1863
+ const disabled = items.filter((t) => t.status === "DISABLED").length;
1864
+ const grouped = {};
1865
+ const byCategory = {};
1866
+ items.forEach((t) => {
1867
+ const cat = t.category;
1868
+ if (!grouped[cat])
1869
+ grouped[cat] = [];
1870
+ grouped[cat].push(t);
1871
+ byCategory[cat] = (byCategory[cat] || 0) + 1;
1872
+ });
1873
+ const catStats = Object.entries(byCategory).map(([category, count]) => ({ category, count })).sort((a, b) => b.count - a.count);
1874
+ return {
1875
+ stats: {
1876
+ total: data.total,
1877
+ active,
1878
+ deprecated,
1879
+ disabled,
1880
+ topCategories: catStats.slice(0, 5)
1881
+ },
1882
+ groupedByCategory: grouped,
1883
+ categoryStats: catStats
1884
+ };
1885
+ }, [data]);
1886
+ return {
1887
+ data,
1888
+ loading,
1889
+ error,
1890
+ stats,
1891
+ groupedByCategory,
1892
+ categoryStats,
1893
+ page,
1894
+ refetch: fetchData,
1895
+ nextPage: () => setPage((p) => p + 1),
1896
+ prevPage: () => page > 1 && setPage((p) => p - 1)
918
1897
  };
919
- if (!isOpen || !agent)
920
- return null;
921
- return /* @__PURE__ */ jsxDEV4("div", {
922
- className: "fixed inset-0 z-50 flex items-center justify-center",
1898
+ }
1899
+
1900
+ // src/ui/views/ToolRegistryView.tsx
1901
+ import {
1902
+ Button as Button4,
1903
+ EmptyState as EmptyState2,
1904
+ EntityCard,
1905
+ ErrorState as ErrorState2,
1906
+ LoaderBlock as LoaderBlock2,
1907
+ StatCard as StatCard2,
1908
+ StatCardGroup as StatCardGroup2,
1909
+ StatusChip as StatusChip3
1910
+ } from "@contractspec/lib.design-system";
1911
+ import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
1912
+ "use client";
1913
+ var categoryIcons = {
1914
+ RETRIEVAL: "\uD83D\uDD0D",
1915
+ COMPUTATION: "\uD83E\uDDEE",
1916
+ COMMUNICATION: "\uD83D\uDCE7",
1917
+ INTEGRATION: "\uD83D\uDD17",
1918
+ UTILITY: "\uD83D\uDEE0️",
1919
+ CUSTOM: "⚙️"
1920
+ };
1921
+ function getStatusTone2(status) {
1922
+ switch (status) {
1923
+ case "ACTIVE":
1924
+ return "success";
1925
+ case "DRAFT":
1926
+ return "neutral";
1927
+ case "DEPRECATED":
1928
+ return "warning";
1929
+ case "DISABLED":
1930
+ return "danger";
1931
+ default:
1932
+ return "neutral";
1933
+ }
1934
+ }
1935
+ function ToolRegistryView({
1936
+ onToolClick,
1937
+ onCreateTool
1938
+ }) {
1939
+ const { data, loading, error, groupedByCategory, categoryStats, refetch } = useToolList();
1940
+ if (loading && !data) {
1941
+ return /* @__PURE__ */ jsxDEV8(LoaderBlock2, {
1942
+ label: "Loading tools..."
1943
+ }, undefined, false, undefined, this);
1944
+ }
1945
+ if (error) {
1946
+ return /* @__PURE__ */ jsxDEV8(ErrorState2, {
1947
+ title: "Failed to load tools",
1948
+ description: error.message,
1949
+ onRetry: refetch,
1950
+ retryLabel: "Retry"
1951
+ }, undefined, false, undefined, this);
1952
+ }
1953
+ if (!data?.items.length) {
1954
+ return /* @__PURE__ */ jsxDEV8(EmptyState2, {
1955
+ title: "No tools registered",
1956
+ description: "Create your first tool to extend agent capabilities.",
1957
+ primaryAction: onCreateTool ? /* @__PURE__ */ jsxDEV8(Button4, {
1958
+ onPress: onCreateTool,
1959
+ children: "Create Tool"
1960
+ }, undefined, false, undefined, this) : undefined
1961
+ }, undefined, false, undefined, this);
1962
+ }
1963
+ return /* @__PURE__ */ jsxDEV8("div", {
1964
+ className: "space-y-8",
923
1965
  children: [
924
- /* @__PURE__ */ jsxDEV4("div", {
925
- className: "bg-background/80 absolute inset-0 backdrop-blur-sm",
926
- onClick: handleClose,
927
- role: "button",
928
- tabIndex: 0,
929
- onKeyDown: (e) => {
930
- if (e.key === "Enter" || e.key === " ")
931
- handleClose();
932
- },
933
- "aria-label": "Close modal"
934
- }, undefined, false, undefined, this),
935
- /* @__PURE__ */ jsxDEV4("div", {
936
- className: "bg-card border-border relative z-10 w-full max-w-md rounded-xl border p-6 shadow-xl",
1966
+ /* @__PURE__ */ jsxDEV8(StatCardGroup2, {
1967
+ children: [
1968
+ /* @__PURE__ */ jsxDEV8(StatCard2, {
1969
+ label: "Total Tools",
1970
+ value: data.total
1971
+ }, undefined, false, undefined, this),
1972
+ categoryStats.slice(0, 3).map(({ category, count }) => /* @__PURE__ */ jsxDEV8(StatCard2, {
1973
+ label: `${categoryIcons[category] ?? ""} ${category}`,
1974
+ value: count
1975
+ }, category, false, undefined, this))
1976
+ ]
1977
+ }, undefined, true, undefined, this),
1978
+ Object.entries(groupedByCategory).map(([category, tools]) => /* @__PURE__ */ jsxDEV8("section", {
1979
+ className: "space-y-4",
937
1980
  children: [
938
- /* @__PURE__ */ jsxDEV4("div", {
939
- className: "border-border mb-4 border-b pb-4",
1981
+ /* @__PURE__ */ jsxDEV8("div", {
1982
+ className: "flex items-center gap-2",
940
1983
  children: [
941
- /* @__PURE__ */ jsxDEV4("h2", {
942
- className: "text-xl font-semibold",
943
- children: agent.name
1984
+ /* @__PURE__ */ jsxDEV8("span", {
1985
+ className: "text-2xl",
1986
+ children: categoryIcons[category]
944
1987
  }, undefined, false, undefined, this),
945
- /* @__PURE__ */ jsxDEV4("div", {
946
- className: "mt-1 flex items-center gap-2",
947
- children: [
948
- /* @__PURE__ */ jsxDEV4("span", {
949
- className: "text-muted-foreground text-sm",
950
- children: [
951
- agent.modelProvider,
952
- " / ",
953
- agent.modelName
954
- ]
955
- }, undefined, true, undefined, this),
956
- /* @__PURE__ */ jsxDEV4("span", {
957
- className: `rounded-full px-2 py-0.5 text-xs font-medium ${getStatusColor(agent.status)}`,
958
- children: agent.status
959
- }, undefined, false, undefined, this)
960
- ]
961
- }, undefined, true, undefined, this),
962
- agent.description && /* @__PURE__ */ jsxDEV4("p", {
963
- className: "text-muted-foreground mt-2 text-sm",
964
- children: agent.description
965
- }, undefined, false, undefined, this)
966
- ]
967
- }, undefined, true, undefined, this),
968
- mode === "menu" && /* @__PURE__ */ jsxDEV4("div", {
969
- className: "space-y-3",
970
- children: [
971
- agent.status === "ACTIVE" && /* @__PURE__ */ jsxDEV4(Button3, {
972
- className: "w-full justify-start",
973
- variant: "ghost",
974
- onPress: () => setMode("execute"),
975
- children: [
976
- /* @__PURE__ */ jsxDEV4("span", {
977
- className: "mr-2",
978
- children: "▶️"
979
- }, undefined, false, undefined, this),
980
- " Execute Agent"
981
- ]
982
- }, undefined, true, undefined, this),
983
- (agent.status === "DRAFT" || agent.status === "PAUSED") && /* @__PURE__ */ jsxDEV4(Button3, {
984
- className: "w-full justify-start",
985
- variant: "ghost",
986
- onPress: () => handleStatusChange("activate"),
987
- disabled: isLoading,
988
- children: [
989
- /* @__PURE__ */ jsxDEV4("span", {
990
- className: "mr-2",
991
- children: "\uD83D\uDFE2"
992
- }, undefined, false, undefined, this),
993
- " Activate Agent"
994
- ]
995
- }, undefined, true, undefined, this),
996
- agent.status === "ACTIVE" && /* @__PURE__ */ jsxDEV4(Button3, {
997
- className: "w-full justify-start",
998
- variant: "ghost",
999
- onPress: () => handleStatusChange("pause"),
1000
- disabled: isLoading,
1001
- children: [
1002
- /* @__PURE__ */ jsxDEV4("span", {
1003
- className: "mr-2",
1004
- children: "⏸️"
1005
- }, undefined, false, undefined, this),
1006
- " Pause Agent"
1007
- ]
1008
- }, undefined, true, undefined, this),
1009
- agent.status !== "ARCHIVED" && /* @__PURE__ */ jsxDEV4(Button3, {
1010
- className: "w-full justify-start text-yellow-600 hover:text-yellow-700",
1011
- variant: "ghost",
1012
- onPress: () => {
1013
- setConfirmAction("archive");
1014
- setMode("confirm");
1015
- },
1016
- children: [
1017
- /* @__PURE__ */ jsxDEV4("span", {
1018
- className: "mr-2",
1019
- children: "\uD83D\uDCE6"
1020
- }, undefined, false, undefined, this),
1021
- " Archive Agent"
1022
- ]
1023
- }, undefined, true, undefined, this),
1024
- agent.status === "ARCHIVED" && /* @__PURE__ */ jsxDEV4(Button3, {
1025
- className: "w-full justify-start",
1026
- variant: "ghost",
1027
- onPress: () => handleStatusChange("activate"),
1028
- disabled: isLoading,
1029
- children: [
1030
- /* @__PURE__ */ jsxDEV4("span", {
1031
- className: "mr-2",
1032
- children: "\uD83D\uDD04"
1033
- }, undefined, false, undefined, this),
1034
- " Restore Agent"
1035
- ]
1036
- }, undefined, true, undefined, this),
1037
- error && /* @__PURE__ */ jsxDEV4("div", {
1038
- className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
1039
- children: error
1988
+ /* @__PURE__ */ jsxDEV8("h3", {
1989
+ className: "font-semibold text-lg",
1990
+ children: category
1040
1991
  }, undefined, false, undefined, this),
1041
- /* @__PURE__ */ jsxDEV4("div", {
1042
- className: "border-border border-t pt-3",
1043
- children: /* @__PURE__ */ jsxDEV4(Button3, {
1044
- className: "w-full",
1045
- variant: "outline",
1046
- onPress: handleClose,
1047
- children: "Close"
1048
- }, undefined, false, undefined, this)
1992
+ /* @__PURE__ */ jsxDEV8("span", {
1993
+ className: "rounded-full bg-muted px-2 py-0.5 text-muted-foreground text-xs",
1994
+ children: tools.length
1049
1995
  }, undefined, false, undefined, this)
1050
1996
  ]
1051
1997
  }, undefined, true, undefined, this),
1052
- mode === "execute" && /* @__PURE__ */ jsxDEV4("div", {
1053
- className: "space-y-4",
1054
- children: [
1055
- /* @__PURE__ */ jsxDEV4("div", {
1056
- children: [
1057
- /* @__PURE__ */ jsxDEV4("label", {
1058
- htmlFor: "execute-message",
1059
- className: "text-muted-foreground mb-1 block text-sm font-medium",
1060
- children: "Message *"
1061
- }, undefined, false, undefined, this),
1062
- /* @__PURE__ */ jsxDEV4("textarea", {
1063
- id: "execute-message",
1064
- value: message,
1065
- onChange: (e) => setMessage(e.target.value),
1066
- placeholder: "Enter your message to the agent...",
1067
- rows: 4,
1068
- disabled: isLoading,
1069
- className: "border-input bg-background focus:ring-ring w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none disabled:opacity-50"
1070
- }, undefined, false, undefined, this)
1071
- ]
1072
- }, undefined, true, undefined, this),
1073
- error && /* @__PURE__ */ jsxDEV4("div", {
1074
- className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
1075
- children: error
1076
- }, undefined, false, undefined, this),
1077
- /* @__PURE__ */ jsxDEV4("div", {
1078
- className: "flex justify-end gap-3 pt-2",
1079
- children: [
1080
- /* @__PURE__ */ jsxDEV4(Button3, {
1081
- variant: "ghost",
1082
- onPress: () => setMode("menu"),
1083
- disabled: isLoading,
1084
- children: "Back"
1085
- }, undefined, false, undefined, this),
1086
- /* @__PURE__ */ jsxDEV4(Button3, {
1087
- onPress: handleExecute,
1088
- disabled: isLoading,
1089
- children: isLoading ? "Executing..." : "▶️ Execute"
1090
- }, undefined, false, undefined, this)
1091
- ]
1092
- }, undefined, true, undefined, this)
1093
- ]
1094
- }, undefined, true, undefined, this),
1095
- mode === "confirm" && confirmAction === "archive" && /* @__PURE__ */ jsxDEV4("div", {
1096
- className: "space-y-4",
1097
- children: [
1098
- /* @__PURE__ */ jsxDEV4("p", {
1099
- className: "text-muted-foreground",
1100
- children: [
1101
- "Are you sure you want to archive",
1102
- " ",
1103
- /* @__PURE__ */ jsxDEV4("span", {
1104
- className: "text-foreground font-medium",
1105
- children: agent.name
1106
- }, undefined, false, undefined, this),
1107
- "?"
1108
- ]
1109
- }, undefined, true, undefined, this),
1110
- /* @__PURE__ */ jsxDEV4("p", {
1998
+ /* @__PURE__ */ jsxDEV8("div", {
1999
+ className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
2000
+ children: tools.map((tool) => /* @__PURE__ */ jsxDEV8(EntityCard, {
2001
+ cardTitle: tool.name,
2002
+ cardSubtitle: `v${tool.version}`,
2003
+ meta: /* @__PURE__ */ jsxDEV8("p", {
1111
2004
  className: "text-muted-foreground text-sm",
1112
- children: "Archived agents cannot be executed but can be restored later."
2005
+ children: tool.description
1113
2006
  }, undefined, false, undefined, this),
1114
- error && /* @__PURE__ */ jsxDEV4("div", {
1115
- className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
1116
- children: error
2007
+ chips: /* @__PURE__ */ jsxDEV8(StatusChip3, {
2008
+ tone: getStatusTone2(tool.status),
2009
+ label: tool.status
1117
2010
  }, undefined, false, undefined, this),
1118
- /* @__PURE__ */ jsxDEV4("div", {
1119
- className: "flex justify-end gap-3 pt-2",
1120
- children: [
1121
- /* @__PURE__ */ jsxDEV4(Button3, {
1122
- variant: "ghost",
1123
- onPress: () => setMode("menu"),
1124
- disabled: isLoading,
1125
- children: "Cancel"
1126
- }, undefined, false, undefined, this),
1127
- /* @__PURE__ */ jsxDEV4(Button3, {
1128
- onPress: () => handleStatusChange("archive"),
1129
- disabled: isLoading,
1130
- children: isLoading ? "Archiving..." : "\uD83D\uDCE6 Archive"
1131
- }, undefined, false, undefined, this)
1132
- ]
1133
- }, undefined, true, undefined, this)
1134
- ]
1135
- }, undefined, true, undefined, this)
2011
+ footer: /* @__PURE__ */ jsxDEV8("code", {
2012
+ className: "text-muted-foreground text-xs",
2013
+ children: tool.name
2014
+ }, undefined, false, undefined, this),
2015
+ onClick: onToolClick ? () => onToolClick(tool.id) : undefined
2016
+ }, tool.id, false, undefined, this))
2017
+ }, undefined, false, undefined, this)
1136
2018
  ]
1137
- }, undefined, true, undefined, this)
2019
+ }, category, true, undefined, this))
1138
2020
  ]
1139
2021
  }, undefined, true, undefined, this);
1140
2022
  }
1141
2023
 
1142
2024
  // src/ui/AgentDashboard.tsx
1143
- import { useState as useState7, useMemo as useMemo3, useCallback as useCallback5 } from "react";
1144
2025
  import {
2026
+ Button as Button5,
1145
2027
  StatCard as StatCard3,
1146
- StatCardGroup as StatCardGroup3,
1147
- Button as Button4
2028
+ StatCardGroup as StatCardGroup3
1148
2029
  } from "@contractspec/lib.design-system";
1149
- import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
2030
+ import { useCallback as useCallback5, useMemo as useMemo4, useState as useState8 } from "react";
2031
+ import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
1150
2032
  "use client";
1151
2033
  function AgentDashboard() {
1152
- const [activeTab, setActiveTab] = useState7("runs");
1153
- const [isCreateModalOpen, setIsCreateModalOpen] = useState7(false);
1154
- const [selectedAgent, setSelectedAgent] = useState7(null);
1155
- const [isAgentActionsOpen, setIsAgentActionsOpen] = useState7(false);
1156
- const { metrics, refetch: refetchRuns } = useRunList();
2034
+ const [activeTab, setActiveTab] = useState8("runs");
2035
+ const [isCreateModalOpen, setIsCreateModalOpen] = useState8(false);
2036
+ const [selectedAgent, setSelectedAgent] = useState8(null);
2037
+ const [isAgentActionsOpen, setIsAgentActionsOpen] = useState8(false);
2038
+ const { data: runData, metrics, refetch: refetchRuns } = useRunList();
1157
2039
  const { refetch: refetchAgents } = useAgentList();
1158
2040
  const mutations = useAgentMutations({
1159
2041
  onSuccess: () => {
@@ -1171,7 +2053,7 @@ function AgentDashboard() {
1171
2053
  { id: "tools", label: "Tools", icon: "\uD83D\uDD27" },
1172
2054
  { id: "metrics", label: "Metrics", icon: "\uD83D\uDCCA" }
1173
2055
  ];
1174
- const summaryStats = useMemo3(() => {
2056
+ const summaryStats = useMemo4(() => {
1175
2057
  if (!metrics) {
1176
2058
  return [
1177
2059
  { label: "Total Runs", value: "-", hint: "Loading..." },
@@ -1203,20 +2085,20 @@ function AgentDashboard() {
1203
2085
  }
1204
2086
  ];
1205
2087
  }, [metrics]);
1206
- return /* @__PURE__ */ jsxDEV5("div", {
2088
+ return /* @__PURE__ */ jsxDEV9("div", {
1207
2089
  className: "space-y-6",
1208
2090
  children: [
1209
- /* @__PURE__ */ jsxDEV5("div", {
2091
+ /* @__PURE__ */ jsxDEV9("div", {
1210
2092
  className: "flex items-center justify-between",
1211
2093
  children: [
1212
- /* @__PURE__ */ jsxDEV5("h2", {
1213
- className: "text-2xl font-bold",
2094
+ /* @__PURE__ */ jsxDEV9("h2", {
2095
+ className: "font-bold text-2xl",
1214
2096
  children: "AI Agent Console"
1215
2097
  }, undefined, false, undefined, this),
1216
- /* @__PURE__ */ jsxDEV5(Button4, {
2098
+ /* @__PURE__ */ jsxDEV9(Button5, {
1217
2099
  onPress: () => setIsCreateModalOpen(true),
1218
2100
  children: [
1219
- /* @__PURE__ */ jsxDEV5("span", {
2101
+ /* @__PURE__ */ jsxDEV9("span", {
1220
2102
  className: "mr-2",
1221
2103
  children: "+"
1222
2104
  }, undefined, false, undefined, this),
@@ -1225,45 +2107,48 @@ function AgentDashboard() {
1225
2107
  }, undefined, true, undefined, this)
1226
2108
  ]
1227
2109
  }, undefined, true, undefined, this),
1228
- /* @__PURE__ */ jsxDEV5(StatCardGroup3, {
1229
- children: summaryStats.map((stat, i) => /* @__PURE__ */ jsxDEV5(StatCard3, {
2110
+ /* @__PURE__ */ jsxDEV9(StatCardGroup3, {
2111
+ children: summaryStats.map((stat, i) => /* @__PURE__ */ jsxDEV9(StatCard3, {
1230
2112
  label: stat.label,
1231
2113
  value: stat.value,
1232
2114
  hint: stat.hint
1233
2115
  }, i, false, undefined, this))
1234
2116
  }, undefined, false, undefined, this),
1235
- /* @__PURE__ */ jsxDEV5("nav", {
1236
- className: "bg-muted flex gap-1 rounded-lg p-1",
2117
+ /* @__PURE__ */ jsxDEV9(AgentVisualizationOverview, {
2118
+ runs: runData?.items ?? []
2119
+ }, undefined, false, undefined, this),
2120
+ /* @__PURE__ */ jsxDEV9("nav", {
2121
+ className: "flex gap-1 rounded-lg bg-muted p-1",
1237
2122
  role: "tablist",
1238
- children: tabs.map((tab) => /* @__PURE__ */ jsxDEV5("button", {
2123
+ children: tabs.map((tab) => /* @__PURE__ */ jsxDEV9("button", {
1239
2124
  type: "button",
1240
2125
  role: "tab",
1241
2126
  "aria-selected": activeTab === tab.id,
1242
2127
  onClick: () => setActiveTab(tab.id),
1243
- className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
2128
+ className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 font-medium text-sm transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
1244
2129
  children: [
1245
- /* @__PURE__ */ jsxDEV5("span", {
2130
+ /* @__PURE__ */ jsxDEV9("span", {
1246
2131
  children: tab.icon
1247
2132
  }, undefined, false, undefined, this),
1248
2133
  tab.label
1249
2134
  ]
1250
2135
  }, tab.id, true, undefined, this))
1251
2136
  }, undefined, false, undefined, this),
1252
- /* @__PURE__ */ jsxDEV5("div", {
2137
+ /* @__PURE__ */ jsxDEV9("div", {
1253
2138
  className: "min-h-[400px]",
1254
2139
  role: "tabpanel",
1255
2140
  children: [
1256
- activeTab === "runs" && /* @__PURE__ */ jsxDEV5(RunListView, {}, undefined, false, undefined, this),
1257
- activeTab === "agents" && /* @__PURE__ */ jsxDEV5(AgentListViewWithActions, {
2141
+ activeTab === "runs" && /* @__PURE__ */ jsxDEV9(RunListView, {}, undefined, false, undefined, this),
2142
+ activeTab === "agents" && /* @__PURE__ */ jsxDEV9(AgentListViewWithActions, {
1258
2143
  onAgentClick: handleAgentClick
1259
2144
  }, undefined, false, undefined, this),
1260
- activeTab === "tools" && /* @__PURE__ */ jsxDEV5(ToolRegistryView, {}, undefined, false, undefined, this),
1261
- activeTab === "metrics" && /* @__PURE__ */ jsxDEV5(MetricsView, {
2145
+ activeTab === "tools" && /* @__PURE__ */ jsxDEV9(ToolRegistryView, {}, undefined, false, undefined, this),
2146
+ activeTab === "metrics" && /* @__PURE__ */ jsxDEV9(MetricsView, {
1262
2147
  metrics
1263
2148
  }, undefined, false, undefined, this)
1264
2149
  ]
1265
2150
  }, undefined, true, undefined, this),
1266
- /* @__PURE__ */ jsxDEV5(CreateAgentModal, {
2151
+ /* @__PURE__ */ jsxDEV9(CreateAgentModal, {
1267
2152
  isOpen: isCreateModalOpen,
1268
2153
  onClose: () => setIsCreateModalOpen(false),
1269
2154
  onSubmit: async (input) => {
@@ -1271,7 +2156,7 @@ function AgentDashboard() {
1271
2156
  },
1272
2157
  isLoading: mutations.createState.loading
1273
2158
  }, undefined, false, undefined, this),
1274
- /* @__PURE__ */ jsxDEV5(AgentActionsModal, {
2159
+ /* @__PURE__ */ jsxDEV9(AgentActionsModal, {
1275
2160
  isOpen: isAgentActionsOpen,
1276
2161
  agent: selectedAgent,
1277
2162
  onClose: () => {
@@ -1300,22 +2185,22 @@ function AgentListViewWithActions({
1300
2185
  }) {
1301
2186
  const { data, loading, error, stats, refetch } = useAgentList();
1302
2187
  if (loading && !data) {
1303
- return /* @__PURE__ */ jsxDEV5("div", {
1304
- className: "text-muted-foreground flex h-64 items-center justify-center",
2188
+ return /* @__PURE__ */ jsxDEV9("div", {
2189
+ className: "flex h-64 items-center justify-center text-muted-foreground",
1305
2190
  children: "Loading agents..."
1306
2191
  }, undefined, false, undefined, this);
1307
2192
  }
1308
2193
  if (error) {
1309
- return /* @__PURE__ */ jsxDEV5("div", {
1310
- className: "text-destructive flex h-64 flex-col items-center justify-center",
2194
+ return /* @__PURE__ */ jsxDEV9("div", {
2195
+ className: "flex h-64 flex-col items-center justify-center text-destructive",
1311
2196
  children: [
1312
- /* @__PURE__ */ jsxDEV5("p", {
2197
+ /* @__PURE__ */ jsxDEV9("p", {
1313
2198
  children: [
1314
2199
  "Failed to load agents: ",
1315
2200
  error.message
1316
2201
  ]
1317
2202
  }, undefined, true, undefined, this),
1318
- /* @__PURE__ */ jsxDEV5(Button4, {
2203
+ /* @__PURE__ */ jsxDEV9(Button5, {
1319
2204
  variant: "outline",
1320
2205
  onPress: refetch,
1321
2206
  className: "mt-2",
@@ -1325,47 +2210,47 @@ function AgentListViewWithActions({
1325
2210
  }, undefined, true, undefined, this);
1326
2211
  }
1327
2212
  if (!data?.items.length) {
1328
- return /* @__PURE__ */ jsxDEV5("div", {
1329
- className: "text-muted-foreground flex h-64 flex-col items-center justify-center",
2213
+ return /* @__PURE__ */ jsxDEV9("div", {
2214
+ className: "flex h-64 flex-col items-center justify-center text-muted-foreground",
1330
2215
  children: [
1331
- /* @__PURE__ */ jsxDEV5("p", {
1332
- className: "text-lg font-medium",
2216
+ /* @__PURE__ */ jsxDEV9("p", {
2217
+ className: "font-medium text-lg",
1333
2218
  children: "No agents yet"
1334
2219
  }, undefined, false, undefined, this),
1335
- /* @__PURE__ */ jsxDEV5("p", {
2220
+ /* @__PURE__ */ jsxDEV9("p", {
1336
2221
  className: "text-sm",
1337
2222
  children: "Create your first AI agent to get started."
1338
2223
  }, undefined, false, undefined, this)
1339
2224
  ]
1340
2225
  }, undefined, true, undefined, this);
1341
2226
  }
1342
- return /* @__PURE__ */ jsxDEV5("div", {
2227
+ return /* @__PURE__ */ jsxDEV9("div", {
1343
2228
  className: "space-y-4",
1344
2229
  children: [
1345
- stats && /* @__PURE__ */ jsxDEV5("div", {
2230
+ stats && /* @__PURE__ */ jsxDEV9("div", {
1346
2231
  className: "flex gap-4 text-sm",
1347
2232
  children: [
1348
- /* @__PURE__ */ jsxDEV5("span", {
2233
+ /* @__PURE__ */ jsxDEV9("span", {
1349
2234
  children: [
1350
2235
  "Total: ",
1351
2236
  stats.total
1352
2237
  ]
1353
2238
  }, undefined, true, undefined, this),
1354
- /* @__PURE__ */ jsxDEV5("span", {
2239
+ /* @__PURE__ */ jsxDEV9("span", {
1355
2240
  className: "text-green-600",
1356
2241
  children: [
1357
2242
  "Active: ",
1358
2243
  stats.active
1359
2244
  ]
1360
2245
  }, undefined, true, undefined, this),
1361
- /* @__PURE__ */ jsxDEV5("span", {
2246
+ /* @__PURE__ */ jsxDEV9("span", {
1362
2247
  className: "text-yellow-600",
1363
2248
  children: [
1364
2249
  "Paused: ",
1365
2250
  stats.paused
1366
2251
  ]
1367
2252
  }, undefined, true, undefined, this),
1368
- /* @__PURE__ */ jsxDEV5("span", {
2253
+ /* @__PURE__ */ jsxDEV9("span", {
1369
2254
  className: "text-blue-600",
1370
2255
  children: [
1371
2256
  "Draft: ",
@@ -1374,9 +2259,9 @@ function AgentListViewWithActions({
1374
2259
  }, undefined, true, undefined, this)
1375
2260
  ]
1376
2261
  }, undefined, true, undefined, this),
1377
- /* @__PURE__ */ jsxDEV5("div", {
2262
+ /* @__PURE__ */ jsxDEV9("div", {
1378
2263
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
1379
- children: data.items.map((agent) => /* @__PURE__ */ jsxDEV5(AgentCard, {
2264
+ children: data.items.map((agent) => /* @__PURE__ */ jsxDEV9(AgentCard, {
1380
2265
  agent,
1381
2266
  onClick: () => onAgentClick(agent)
1382
2267
  }, agent.id, false, undefined, this))
@@ -1391,9 +2276,9 @@ function AgentCard({ agent, onClick }) {
1391
2276
  PAUSED: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",
1392
2277
  ARCHIVED: "bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400"
1393
2278
  };
1394
- return /* @__PURE__ */ jsxDEV5("div", {
2279
+ return /* @__PURE__ */ jsxDEV9("div", {
1395
2280
  onClick,
1396
- className: "border-border bg-card cursor-pointer rounded-xl border p-4 transition-all hover:shadow-md",
2281
+ className: "cursor-pointer rounded-xl border border-border bg-card p-4 transition-all hover:shadow-md",
1397
2282
  role: "button",
1398
2283
  tabIndex: 0,
1399
2284
  onKeyDown: (e) => {
@@ -1401,17 +2286,17 @@ function AgentCard({ agent, onClick }) {
1401
2286
  onClick();
1402
2287
  },
1403
2288
  children: [
1404
- /* @__PURE__ */ jsxDEV5("div", {
2289
+ /* @__PURE__ */ jsxDEV9("div", {
1405
2290
  className: "flex items-start justify-between",
1406
2291
  children: [
1407
- /* @__PURE__ */ jsxDEV5("div", {
2292
+ /* @__PURE__ */ jsxDEV9("div", {
1408
2293
  className: "min-w-0 flex-1",
1409
2294
  children: [
1410
- /* @__PURE__ */ jsxDEV5("h3", {
2295
+ /* @__PURE__ */ jsxDEV9("h3", {
1411
2296
  className: "truncate font-semibold",
1412
2297
  children: agent.name
1413
2298
  }, undefined, false, undefined, this),
1414
- /* @__PURE__ */ jsxDEV5("p", {
2299
+ /* @__PURE__ */ jsxDEV9("p", {
1415
2300
  className: "text-muted-foreground text-sm",
1416
2301
  children: [
1417
2302
  agent.modelProvider,
@@ -1421,24 +2306,24 @@ function AgentCard({ agent, onClick }) {
1421
2306
  }, undefined, true, undefined, this)
1422
2307
  ]
1423
2308
  }, undefined, true, undefined, this),
1424
- /* @__PURE__ */ jsxDEV5("span", {
1425
- className: `rounded-full px-2 py-0.5 text-xs font-medium ${statusColors[agent.status]}`,
2309
+ /* @__PURE__ */ jsxDEV9("span", {
2310
+ className: `rounded-full px-2 py-0.5 font-medium text-xs ${statusColors[agent.status]}`,
1426
2311
  children: agent.status
1427
2312
  }, undefined, false, undefined, this)
1428
2313
  ]
1429
2314
  }, undefined, true, undefined, this),
1430
- agent.description && /* @__PURE__ */ jsxDEV5("p", {
1431
- className: "text-muted-foreground mt-2 line-clamp-2 text-sm",
2315
+ agent.description && /* @__PURE__ */ jsxDEV9("p", {
2316
+ className: "mt-2 line-clamp-2 text-muted-foreground text-sm",
1432
2317
  children: agent.description
1433
2318
  }, undefined, false, undefined, this),
1434
- /* @__PURE__ */ jsxDEV5("div", {
2319
+ /* @__PURE__ */ jsxDEV9("div", {
1435
2320
  className: "mt-3 flex items-center justify-between",
1436
2321
  children: [
1437
- /* @__PURE__ */ jsxDEV5("span", {
2322
+ /* @__PURE__ */ jsxDEV9("span", {
1438
2323
  className: "text-muted-foreground text-xs",
1439
2324
  children: agent.modelName
1440
2325
  }, undefined, false, undefined, this),
1441
- /* @__PURE__ */ jsxDEV5(Button4, {
2326
+ /* @__PURE__ */ jsxDEV9(Button5, {
1442
2327
  variant: "ghost",
1443
2328
  size: "sm",
1444
2329
  onPress: onClick,
@@ -1451,40 +2336,40 @@ function AgentCard({ agent, onClick }) {
1451
2336
  }
1452
2337
  function MetricsView({ metrics }) {
1453
2338
  if (!metrics) {
1454
- return /* @__PURE__ */ jsxDEV5("div", {
1455
- className: "text-muted-foreground flex h-64 items-center justify-center",
2339
+ return /* @__PURE__ */ jsxDEV9("div", {
2340
+ className: "flex h-64 items-center justify-center text-muted-foreground",
1456
2341
  children: "Loading metrics..."
1457
2342
  }, undefined, false, undefined, this);
1458
2343
  }
1459
2344
  const completedRuns = Math.round(metrics.totalRuns * metrics.successRate);
1460
2345
  const failedRuns = metrics.totalRuns - completedRuns;
1461
- return /* @__PURE__ */ jsxDEV5("div", {
2346
+ return /* @__PURE__ */ jsxDEV9("div", {
1462
2347
  className: "space-y-6",
1463
2348
  children: [
1464
- /* @__PURE__ */ jsxDEV5("h3", {
1465
- className: "text-lg font-semibold",
2349
+ /* @__PURE__ */ jsxDEV9("h3", {
2350
+ className: "font-semibold text-lg",
1466
2351
  children: "Usage Analytics"
1467
2352
  }, undefined, false, undefined, this),
1468
- /* @__PURE__ */ jsxDEV5("div", {
2353
+ /* @__PURE__ */ jsxDEV9("div", {
1469
2354
  className: "grid gap-6 md:grid-cols-2",
1470
2355
  children: [
1471
- /* @__PURE__ */ jsxDEV5("div", {
1472
- className: "border-border bg-card rounded-xl border p-4",
2356
+ /* @__PURE__ */ jsxDEV9("div", {
2357
+ className: "rounded-xl border border-border bg-card p-4",
1473
2358
  children: [
1474
- /* @__PURE__ */ jsxDEV5("h4", {
2359
+ /* @__PURE__ */ jsxDEV9("h4", {
1475
2360
  className: "font-medium",
1476
2361
  children: "Run Outcomes"
1477
2362
  }, undefined, false, undefined, this),
1478
- /* @__PURE__ */ jsxDEV5("div", {
2363
+ /* @__PURE__ */ jsxDEV9("div", {
1479
2364
  className: "mt-4 space-y-3",
1480
2365
  children: [
1481
- /* @__PURE__ */ jsxDEV5(ProgressBar, {
2366
+ /* @__PURE__ */ jsxDEV9(ProgressBar, {
1482
2367
  label: "Completed",
1483
2368
  value: completedRuns,
1484
2369
  total: metrics.totalRuns,
1485
2370
  color: "bg-green-500"
1486
2371
  }, undefined, false, undefined, this),
1487
- /* @__PURE__ */ jsxDEV5(ProgressBar, {
2372
+ /* @__PURE__ */ jsxDEV9(ProgressBar, {
1488
2373
  label: "Failed",
1489
2374
  value: failedRuns,
1490
2375
  total: metrics.totalRuns,
@@ -1494,24 +2379,24 @@ function MetricsView({ metrics }) {
1494
2379
  }, undefined, true, undefined, this)
1495
2380
  ]
1496
2381
  }, undefined, true, undefined, this),
1497
- /* @__PURE__ */ jsxDEV5("div", {
1498
- className: "border-border bg-card rounded-xl border p-4",
2382
+ /* @__PURE__ */ jsxDEV9("div", {
2383
+ className: "rounded-xl border border-border bg-card p-4",
1499
2384
  children: [
1500
- /* @__PURE__ */ jsxDEV5("h4", {
2385
+ /* @__PURE__ */ jsxDEV9("h4", {
1501
2386
  className: "font-medium",
1502
2387
  children: "Performance"
1503
2388
  }, undefined, false, undefined, this),
1504
- /* @__PURE__ */ jsxDEV5("dl", {
2389
+ /* @__PURE__ */ jsxDEV9("dl", {
1505
2390
  className: "mt-4 grid grid-cols-2 gap-4",
1506
2391
  children: [
1507
- /* @__PURE__ */ jsxDEV5("div", {
2392
+ /* @__PURE__ */ jsxDEV9("div", {
1508
2393
  children: [
1509
- /* @__PURE__ */ jsxDEV5("dt", {
2394
+ /* @__PURE__ */ jsxDEV9("dt", {
1510
2395
  className: "text-muted-foreground text-sm",
1511
2396
  children: "Avg Duration"
1512
2397
  }, undefined, false, undefined, this),
1513
- /* @__PURE__ */ jsxDEV5("dd", {
1514
- className: "text-xl font-semibold",
2398
+ /* @__PURE__ */ jsxDEV9("dd", {
2399
+ className: "font-semibold text-xl",
1515
2400
  children: [
1516
2401
  (metrics.averageDurationMs / 1000).toFixed(1),
1517
2402
  "s"
@@ -1519,14 +2404,14 @@ function MetricsView({ metrics }) {
1519
2404
  }, undefined, true, undefined, this)
1520
2405
  ]
1521
2406
  }, undefined, true, undefined, this),
1522
- /* @__PURE__ */ jsxDEV5("div", {
2407
+ /* @__PURE__ */ jsxDEV9("div", {
1523
2408
  children: [
1524
- /* @__PURE__ */ jsxDEV5("dt", {
2409
+ /* @__PURE__ */ jsxDEV9("dt", {
1525
2410
  className: "text-muted-foreground text-sm",
1526
2411
  children: "Success Rate"
1527
2412
  }, undefined, false, undefined, this),
1528
- /* @__PURE__ */ jsxDEV5("dd", {
1529
- className: "text-xl font-semibold",
2413
+ /* @__PURE__ */ jsxDEV9("dd", {
2414
+ className: "font-semibold text-xl",
1530
2415
  children: [
1531
2416
  (metrics.successRate * 100).toFixed(0),
1532
2417
  "%"
@@ -1540,36 +2425,36 @@ function MetricsView({ metrics }) {
1540
2425
  }, undefined, true, undefined, this)
1541
2426
  ]
1542
2427
  }, undefined, true, undefined, this),
1543
- /* @__PURE__ */ jsxDEV5("div", {
1544
- className: "border-border bg-card rounded-xl border p-4",
2428
+ /* @__PURE__ */ jsxDEV9("div", {
2429
+ className: "rounded-xl border border-border bg-card p-4",
1545
2430
  children: [
1546
- /* @__PURE__ */ jsxDEV5("h4", {
2431
+ /* @__PURE__ */ jsxDEV9("h4", {
1547
2432
  className: "font-medium",
1548
2433
  children: "Key Metrics"
1549
2434
  }, undefined, false, undefined, this),
1550
- /* @__PURE__ */ jsxDEV5("dl", {
2435
+ /* @__PURE__ */ jsxDEV9("dl", {
1551
2436
  className: "mt-4 grid gap-4 sm:grid-cols-3",
1552
2437
  children: [
1553
- /* @__PURE__ */ jsxDEV5("div", {
2438
+ /* @__PURE__ */ jsxDEV9("div", {
1554
2439
  children: [
1555
- /* @__PURE__ */ jsxDEV5("dt", {
2440
+ /* @__PURE__ */ jsxDEV9("dt", {
1556
2441
  className: "text-muted-foreground text-sm",
1557
2442
  children: "Total Runs"
1558
2443
  }, undefined, false, undefined, this),
1559
- /* @__PURE__ */ jsxDEV5("dd", {
1560
- className: "text-2xl font-semibold",
2444
+ /* @__PURE__ */ jsxDEV9("dd", {
2445
+ className: "font-semibold text-2xl",
1561
2446
  children: metrics.totalRuns.toLocaleString()
1562
2447
  }, undefined, false, undefined, this)
1563
2448
  ]
1564
2449
  }, undefined, true, undefined, this),
1565
- /* @__PURE__ */ jsxDEV5("div", {
2450
+ /* @__PURE__ */ jsxDEV9("div", {
1566
2451
  children: [
1567
- /* @__PURE__ */ jsxDEV5("dt", {
2452
+ /* @__PURE__ */ jsxDEV9("dt", {
1568
2453
  className: "text-muted-foreground text-sm",
1569
2454
  children: "Total Tokens"
1570
2455
  }, undefined, false, undefined, this),
1571
- /* @__PURE__ */ jsxDEV5("dd", {
1572
- className: "text-2xl font-semibold",
2456
+ /* @__PURE__ */ jsxDEV9("dd", {
2457
+ className: "font-semibold text-2xl",
1573
2458
  children: [
1574
2459
  (metrics.totalTokens / 1000).toFixed(0),
1575
2460
  "K"
@@ -1577,14 +2462,14 @@ function MetricsView({ metrics }) {
1577
2462
  }, undefined, true, undefined, this)
1578
2463
  ]
1579
2464
  }, undefined, true, undefined, this),
1580
- /* @__PURE__ */ jsxDEV5("div", {
2465
+ /* @__PURE__ */ jsxDEV9("div", {
1581
2466
  children: [
1582
- /* @__PURE__ */ jsxDEV5("dt", {
2467
+ /* @__PURE__ */ jsxDEV9("dt", {
1583
2468
  className: "text-muted-foreground text-sm",
1584
2469
  children: "Cost per Run"
1585
2470
  }, undefined, false, undefined, this),
1586
- /* @__PURE__ */ jsxDEV5("dd", {
1587
- className: "text-2xl font-semibold",
2471
+ /* @__PURE__ */ jsxDEV9("dd", {
2472
+ className: "font-semibold text-2xl",
1588
2473
  children: [
1589
2474
  "$",
1590
2475
  metrics.totalRuns > 0 ? (metrics.totalCostUsd / metrics.totalRuns).toFixed(4) : "0"
@@ -1606,15 +2491,15 @@ function ProgressBar({
1606
2491
  color
1607
2492
  }) {
1608
2493
  const pct = total > 0 ? value / total * 100 : 0;
1609
- return /* @__PURE__ */ jsxDEV5("div", {
2494
+ return /* @__PURE__ */ jsxDEV9("div", {
1610
2495
  children: [
1611
- /* @__PURE__ */ jsxDEV5("div", {
2496
+ /* @__PURE__ */ jsxDEV9("div", {
1612
2497
  className: "flex justify-between text-sm",
1613
2498
  children: [
1614
- /* @__PURE__ */ jsxDEV5("span", {
2499
+ /* @__PURE__ */ jsxDEV9("span", {
1615
2500
  children: label
1616
2501
  }, undefined, false, undefined, this),
1617
- /* @__PURE__ */ jsxDEV5("span", {
2502
+ /* @__PURE__ */ jsxDEV9("span", {
1618
2503
  className: "text-muted-foreground",
1619
2504
  children: [
1620
2505
  value,
@@ -1625,9 +2510,9 @@ function ProgressBar({
1625
2510
  }, undefined, true, undefined, this)
1626
2511
  ]
1627
2512
  }, undefined, true, undefined, this),
1628
- /* @__PURE__ */ jsxDEV5("div", {
1629
- className: "bg-muted mt-1 h-2 overflow-hidden rounded-full",
1630
- children: /* @__PURE__ */ jsxDEV5("div", {
2513
+ /* @__PURE__ */ jsxDEV9("div", {
2514
+ className: "mt-1 h-2 overflow-hidden rounded-full bg-muted",
2515
+ children: /* @__PURE__ */ jsxDEV9("div", {
1631
2516
  className: `h-full ${color}`,
1632
2517
  style: { width: `${pct}%` }
1633
2518
  }, undefined, false, undefined, this)