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