@contractspec/example.agent-console 3.7.6 → 3.7.7

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 (175) hide show
  1. package/.turbo/turbo-build.log +18 -18
  2. package/AGENTS.md +50 -31
  3. package/README.md +69 -77
  4. package/dist/agent/agent.event.js +1 -1
  5. package/dist/agent/agent.operation.js +1 -1
  6. package/dist/agent/index.d.ts +5 -5
  7. package/dist/agent/index.js +1 -1
  8. package/dist/browser/agent/agent.event.js +1 -1
  9. package/dist/browser/agent/agent.operation.js +1 -1
  10. package/dist/browser/agent/index.js +1 -1
  11. package/dist/browser/index.js +2145 -2145
  12. package/dist/browser/presentations/index.js +4 -4
  13. package/dist/browser/run/index.js +536 -536
  14. package/dist/browser/run/run.event.js +2 -2
  15. package/dist/browser/run/run.presentation.js +2 -2
  16. package/dist/browser/tool/index.js +260 -260
  17. package/dist/browser/tool/tool.event.js +1 -1
  18. package/dist/browser/tool/tool.presentation.js +2 -2
  19. package/dist/browser/ui/AgentDashboard.js +956 -956
  20. package/dist/browser/ui/AgentRunList.js +16 -16
  21. package/dist/browser/ui/AgentToolRegistry.js +9 -9
  22. package/dist/browser/ui/hooks/index.js +153 -153
  23. package/dist/browser/ui/hooks/useAgentList.js +1 -1
  24. package/dist/browser/ui/hooks/useAgentMutations.js +1 -1
  25. package/dist/browser/ui/hooks/useRunList.js +1 -1
  26. package/dist/browser/ui/hooks/useToolList.js +1 -1
  27. package/dist/browser/ui/index.js +1222 -1222
  28. package/dist/browser/ui/modals/AgentActionsModal.js +13 -13
  29. package/dist/browser/ui/modals/CreateAgentModal.js +15 -15
  30. package/dist/browser/ui/modals/index.js +297 -297
  31. package/dist/browser/ui/renderers/agent-list.renderer.js +7 -7
  32. package/dist/browser/ui/renderers/index.js +157 -157
  33. package/dist/browser/ui/views/AgentListView.js +7 -7
  34. package/dist/browser/ui/views/RunListView.js +16 -16
  35. package/dist/browser/ui/views/ToolRegistryView.js +9 -9
  36. package/dist/browser/ui/views/index.js +97 -97
  37. package/dist/handlers/index.d.ts +1 -1
  38. package/dist/index.d.ts +4 -4
  39. package/dist/index.js +2145 -2145
  40. package/dist/node/agent/agent.event.js +1 -1
  41. package/dist/node/agent/agent.operation.js +1 -1
  42. package/dist/node/agent/index.js +1 -1
  43. package/dist/node/index.js +2145 -2145
  44. package/dist/node/presentations/index.js +4 -4
  45. package/dist/node/run/index.js +536 -536
  46. package/dist/node/run/run.event.js +2 -2
  47. package/dist/node/run/run.presentation.js +2 -2
  48. package/dist/node/tool/index.js +260 -260
  49. package/dist/node/tool/tool.event.js +1 -1
  50. package/dist/node/tool/tool.presentation.js +2 -2
  51. package/dist/node/ui/AgentDashboard.js +956 -956
  52. package/dist/node/ui/AgentRunList.js +16 -16
  53. package/dist/node/ui/AgentToolRegistry.js +9 -9
  54. package/dist/node/ui/hooks/index.js +153 -153
  55. package/dist/node/ui/hooks/useAgentList.js +1 -1
  56. package/dist/node/ui/hooks/useAgentMutations.js +1 -1
  57. package/dist/node/ui/hooks/useRunList.js +1 -1
  58. package/dist/node/ui/hooks/useToolList.js +1 -1
  59. package/dist/node/ui/index.js +1222 -1222
  60. package/dist/node/ui/modals/AgentActionsModal.js +13 -13
  61. package/dist/node/ui/modals/CreateAgentModal.js +15 -15
  62. package/dist/node/ui/modals/index.js +297 -297
  63. package/dist/node/ui/renderers/agent-list.renderer.js +7 -7
  64. package/dist/node/ui/renderers/index.js +157 -157
  65. package/dist/node/ui/views/AgentListView.js +7 -7
  66. package/dist/node/ui/views/RunListView.js +16 -16
  67. package/dist/node/ui/views/ToolRegistryView.js +9 -9
  68. package/dist/node/ui/views/index.js +97 -97
  69. package/dist/presentations/index.d.ts +3 -5
  70. package/dist/presentations/index.js +4 -4
  71. package/dist/run/index.d.ts +7 -7
  72. package/dist/run/index.js +536 -536
  73. package/dist/run/run.event.js +2 -2
  74. package/dist/run/run.handler.d.ts +3 -0
  75. package/dist/run/run.presentation.js +2 -2
  76. package/dist/shared/index.d.ts +1 -1
  77. package/dist/tool/index.d.ts +7 -7
  78. package/dist/tool/index.js +260 -260
  79. package/dist/tool/tool.event.js +1 -1
  80. package/dist/tool/tool.handler.d.ts +1 -1
  81. package/dist/tool/tool.presentation.js +2 -2
  82. package/dist/ui/AgentDashboard.js +956 -956
  83. package/dist/ui/AgentRunList.js +16 -16
  84. package/dist/ui/AgentToolRegistry.js +9 -9
  85. package/dist/ui/hooks/index.d.ts +4 -4
  86. package/dist/ui/hooks/index.js +153 -153
  87. package/dist/ui/hooks/useAgentList.d.ts +5 -0
  88. package/dist/ui/hooks/useAgentList.js +1 -1
  89. package/dist/ui/hooks/useAgentMutations.d.ts +9 -2
  90. package/dist/ui/hooks/useAgentMutations.js +1 -1
  91. package/dist/ui/hooks/useRunList.d.ts +5 -0
  92. package/dist/ui/hooks/useRunList.js +1 -1
  93. package/dist/ui/hooks/useToolList.d.ts +5 -0
  94. package/dist/ui/hooks/useToolList.js +1 -1
  95. package/dist/ui/index.d.ts +3 -3
  96. package/dist/ui/index.js +1222 -1222
  97. package/dist/ui/modals/AgentActionsModal.js +13 -13
  98. package/dist/ui/modals/CreateAgentModal.js +15 -15
  99. package/dist/ui/modals/index.d.ts +1 -1
  100. package/dist/ui/modals/index.js +297 -297
  101. package/dist/ui/renderers/agent-list.markdown.d.ts +5 -0
  102. package/dist/ui/renderers/agent-list.renderer.js +7 -7
  103. package/dist/ui/renderers/dashboard.markdown.d.ts +5 -0
  104. package/dist/ui/renderers/index.d.ts +2 -2
  105. package/dist/ui/renderers/index.js +157 -157
  106. package/dist/ui/renderers/run-list.markdown.d.ts +5 -0
  107. package/dist/ui/renderers/tool-registry.markdown.d.ts +5 -0
  108. package/dist/ui/views/AgentListView.js +7 -7
  109. package/dist/ui/views/RunListView.js +16 -16
  110. package/dist/ui/views/ToolRegistryView.js +9 -9
  111. package/dist/ui/views/index.js +97 -97
  112. package/package.json +6 -6
  113. package/src/agent/agent.entity.ts +111 -111
  114. package/src/agent/agent.enum.ts +12 -12
  115. package/src/agent/agent.event.ts +91 -91
  116. package/src/agent/agent.handler.ts +123 -123
  117. package/src/agent/agent.operation.ts +400 -400
  118. package/src/agent/agent.presentation.ts +62 -62
  119. package/src/agent/agent.schema.ts +175 -175
  120. package/src/agent/agent.test-spec.ts +48 -48
  121. package/src/agent/index.ts +46 -51
  122. package/src/agent.capability.ts +11 -11
  123. package/src/agent.feature.ts +131 -131
  124. package/src/docs/agent-console.docblock.ts +42 -42
  125. package/src/example.ts +35 -35
  126. package/src/handlers/agent.handlers.ts +522 -521
  127. package/src/handlers/index.ts +12 -12
  128. package/src/index.ts +8 -9
  129. package/src/presentations/index.ts +11 -13
  130. package/src/run/index.ts +49 -54
  131. package/src/run/run.entity.ts +137 -137
  132. package/src/run/run.enum.ts +18 -18
  133. package/src/run/run.event.ts +174 -174
  134. package/src/run/run.handler.ts +92 -91
  135. package/src/run/run.operation.ts +474 -474
  136. package/src/run/run.presentation.ts +42 -42
  137. package/src/run/run.schema.ts +126 -126
  138. package/src/run/run.test-spec.ts +48 -48
  139. package/src/seeders/index.ts +21 -21
  140. package/src/shared/index.ts +1 -1
  141. package/src/shared/mock-agents.ts +76 -76
  142. package/src/shared/mock-runs.ts +102 -102
  143. package/src/shared/mock-tools.ts +140 -140
  144. package/src/shared/overlay-types.ts +23 -23
  145. package/src/tool/index.ts +39 -44
  146. package/src/tool/tool.entity.ts +73 -73
  147. package/src/tool/tool.enum.ts +13 -13
  148. package/src/tool/tool.event.ts +80 -80
  149. package/src/tool/tool.handler.ts +102 -102
  150. package/src/tool/tool.operation.ts +328 -328
  151. package/src/tool/tool.presentation.ts +43 -43
  152. package/src/tool/tool.schema.ts +106 -106
  153. package/src/tool/tool.test-spec.ts +48 -48
  154. package/src/ui/AgentDashboard.tsx +348 -348
  155. package/src/ui/hooks/index.ts +7 -7
  156. package/src/ui/hooks/useAgentList.ts +57 -56
  157. package/src/ui/hooks/useAgentMutations.ts +160 -159
  158. package/src/ui/hooks/useRunList.ts +58 -57
  159. package/src/ui/hooks/useToolList.ts +102 -101
  160. package/src/ui/index.ts +6 -9
  161. package/src/ui/modals/AgentActionsModal.tsx +262 -262
  162. package/src/ui/modals/CreateAgentModal.tsx +232 -232
  163. package/src/ui/modals/index.ts +1 -1
  164. package/src/ui/overlays/demo-overlays.ts +52 -52
  165. package/src/ui/renderers/agent-list.markdown.ts +61 -60
  166. package/src/ui/renderers/agent-list.renderer.tsx +14 -14
  167. package/src/ui/renderers/dashboard.markdown.ts +140 -139
  168. package/src/ui/renderers/index.ts +3 -4
  169. package/src/ui/renderers/run-list.markdown.ts +48 -47
  170. package/src/ui/renderers/tool-registry.markdown.ts +66 -65
  171. package/src/ui/views/AgentListView.tsx +90 -90
  172. package/src/ui/views/RunListView.tsx +141 -141
  173. package/src/ui/views/ToolRegistryView.tsx +113 -113
  174. package/tsconfig.json +7 -8
  175. package/tsdown.config.js +7 -3
@@ -3,17 +3,18 @@
3
3
  *
4
4
  * Uses dynamic import for handlers to ensure correct build order.
5
5
  */
6
+
7
+ import { mockListToolsHandler } from '@contractspec/example.agent-console/handlers';
6
8
  import type { PresentationSpec } from '@contractspec/lib.contracts-spec/presentations';
7
9
  import type { PresentationRenderer } from '@contractspec/lib.contracts-spec/presentations/transform-engine';
8
- import { mockListToolsHandler } from '@contractspec/example.agent-console/handlers';
9
10
 
10
11
  interface ToolItem {
11
- id: string;
12
- name: string;
13
- description?: string;
14
- version: string;
15
- category: string;
16
- status: string;
12
+ id: string;
13
+ name: string;
14
+ description?: string;
15
+ version: string;
16
+ category: string;
17
+ status: string;
17
18
  }
18
19
 
19
20
  /**
@@ -21,69 +22,69 @@ interface ToolItem {
21
22
  * Only handles ToolRegistryView component
22
23
  */
23
24
  export const toolRegistryMarkdownRenderer: PresentationRenderer<{
24
- mimeType: string;
25
- body: string;
25
+ mimeType: string;
26
+ body: string;
26
27
  }> = {
27
- target: 'markdown',
28
- render: async (desc: PresentationSpec) => {
29
- // Only handle ToolRegistryView
30
- if (
31
- desc.source.type !== 'component' ||
32
- desc.source.componentKey !== 'ToolRegistryView'
33
- ) {
34
- throw new Error('toolRegistryMarkdownRenderer: not ToolRegistryView');
35
- }
28
+ target: 'markdown',
29
+ render: async (desc: PresentationSpec) => {
30
+ // Only handle ToolRegistryView
31
+ if (
32
+ desc.source.type !== 'component' ||
33
+ desc.source.componentKey !== 'ToolRegistryView'
34
+ ) {
35
+ throw new Error('toolRegistryMarkdownRenderer: not ToolRegistryView');
36
+ }
36
37
 
37
- // Fetch data using mock handler
38
- const data = await mockListToolsHandler({
39
- organizationId: 'demo-org',
40
- limit: 50,
41
- offset: 0,
42
- });
38
+ // Fetch data using mock handler
39
+ const data = await mockListToolsHandler({
40
+ organizationId: 'demo-org',
41
+ limit: 50,
42
+ offset: 0,
43
+ });
43
44
 
44
- // Generate markdown
45
- const lines: string[] = [
46
- `# ${desc.meta.description ?? 'Tool Registry'}`,
47
- '',
48
- `> ${desc.meta.key} v${desc.meta.version}`,
49
- '',
50
- `**Total Tools:** ${data.total}`,
51
- '',
52
- ];
45
+ // Generate markdown
46
+ const lines: string[] = [
47
+ `# ${desc.meta.description ?? 'Tool Registry'}`,
48
+ '',
49
+ `> ${desc.meta.key} v${desc.meta.version}`,
50
+ '',
51
+ `**Total Tools:** ${data.total}`,
52
+ '',
53
+ ];
53
54
 
54
- // Group by category
55
- const byCategory: Record<string, ToolItem[]> = {};
56
- for (const tool of data.items as ToolItem[]) {
57
- const cat = tool.category;
58
- if (!byCategory[cat]) byCategory[cat] = [];
59
- byCategory[cat].push(tool);
60
- }
55
+ // Group by category
56
+ const byCategory: Record<string, ToolItem[]> = {};
57
+ for (const tool of data.items as ToolItem[]) {
58
+ const cat = tool.category;
59
+ if (!byCategory[cat]) byCategory[cat] = [];
60
+ byCategory[cat].push(tool);
61
+ }
61
62
 
62
- for (const [category, tools] of Object.entries(byCategory).sort()) {
63
- lines.push(`## ${category} (${tools.length})`);
64
- lines.push('');
63
+ for (const [category, tools] of Object.entries(byCategory).sort()) {
64
+ lines.push(`## ${category} (${tools.length})`);
65
+ lines.push('');
65
66
 
66
- for (const tool of tools) {
67
- const statusIcon =
68
- tool.status === 'ACTIVE'
69
- ? '✅'
70
- : tool.status === 'DEPRECATED'
71
- ? '⚠️'
72
- : '❌';
73
- lines.push(`### ${statusIcon} ${tool.name} v${tool.version}`);
74
- lines.push('');
75
- lines.push(`> \`${tool.id}\``);
76
- lines.push('');
77
- if (tool.description) {
78
- lines.push(tool.description);
79
- lines.push('');
80
- }
81
- }
82
- }
67
+ for (const tool of tools) {
68
+ const statusIcon =
69
+ tool.status === 'ACTIVE'
70
+ ? '✅'
71
+ : tool.status === 'DEPRECATED'
72
+ ? '⚠️'
73
+ : '❌';
74
+ lines.push(`### ${statusIcon} ${tool.name} v${tool.version}`);
75
+ lines.push('');
76
+ lines.push(`> \`${tool.id}\``);
77
+ lines.push('');
78
+ if (tool.description) {
79
+ lines.push(tool.description);
80
+ lines.push('');
81
+ }
82
+ }
83
+ }
83
84
 
84
- return {
85
- mimeType: 'text/markdown',
86
- body: lines.join('\n'),
87
- };
88
- },
85
+ return {
86
+ mimeType: 'text/markdown',
87
+ body: lines.join('\n'),
88
+ };
89
+ },
89
90
  };
@@ -7,107 +7,107 @@
7
7
  * Uses design-system components with correct props.
8
8
  */
9
9
  import {
10
- Button,
11
- StatCard,
12
- StatCardGroup,
13
- EntityCard,
14
- StatusChip,
15
- LoaderBlock,
16
- ErrorState,
17
- EmptyState,
10
+ Button,
11
+ EmptyState,
12
+ EntityCard,
13
+ ErrorState,
14
+ LoaderBlock,
15
+ StatCard,
16
+ StatCardGroup,
17
+ StatusChip,
18
18
  } from '@contractspec/lib.design-system';
19
- import { useAgentList, type Agent } from '../hooks/useAgentList';
19
+ import { type Agent, useAgentList } from '../hooks/useAgentList';
20
20
 
21
21
  function getStatusTone(
22
- status: Agent['status']
22
+ status: Agent['status']
23
23
  ): 'success' | 'warning' | 'neutral' {
24
- switch (status) {
25
- case 'ACTIVE':
26
- return 'success';
27
- case 'PAUSED':
28
- case 'DRAFT':
29
- return 'warning';
30
- case 'ARCHIVED':
31
- return 'neutral';
32
- default:
33
- return 'neutral';
34
- }
24
+ switch (status) {
25
+ case 'ACTIVE':
26
+ return 'success';
27
+ case 'PAUSED':
28
+ case 'DRAFT':
29
+ return 'warning';
30
+ case 'ARCHIVED':
31
+ return 'neutral';
32
+ default:
33
+ return 'neutral';
34
+ }
35
35
  }
36
36
 
37
37
  export function AgentListView() {
38
- const { data, loading, error, stats, refetch } = useAgentList();
38
+ const { data, loading, error, stats, refetch } = useAgentList();
39
39
 
40
- if (loading && !data) {
41
- return <LoaderBlock label="Loading agents..." />;
42
- }
40
+ if (loading && !data) {
41
+ return <LoaderBlock label="Loading agents..." />;
42
+ }
43
43
 
44
- if (error) {
45
- return (
46
- <ErrorState
47
- title="Failed to load agents"
48
- description={error.message}
49
- onRetry={refetch}
50
- retryLabel="Retry"
51
- />
52
- );
53
- }
44
+ if (error) {
45
+ return (
46
+ <ErrorState
47
+ title="Failed to load agents"
48
+ description={error.message}
49
+ onRetry={refetch}
50
+ retryLabel="Retry"
51
+ />
52
+ );
53
+ }
54
54
 
55
- if (!data?.items.length) {
56
- return (
57
- <EmptyState
58
- title="No agents yet"
59
- description="Create your first AI agent to get started."
60
- />
61
- );
62
- }
55
+ if (!data?.items.length) {
56
+ return (
57
+ <EmptyState
58
+ title="No agents yet"
59
+ description="Create your first AI agent to get started."
60
+ />
61
+ );
62
+ }
63
63
 
64
- return (
65
- <div className="space-y-6">
66
- {/* Stats */}
67
- {stats && (
68
- <StatCardGroup>
69
- <StatCard label="Total Agents" value={stats.total} />
70
- <StatCard label="Active" value={stats.active} />
71
- <StatCard label="Paused" value={stats.paused} />
72
- <StatCard label="Draft" value={stats.draft} />
73
- </StatCardGroup>
74
- )}
64
+ return (
65
+ <div className="space-y-6">
66
+ {/* Stats */}
67
+ {stats && (
68
+ <StatCardGroup>
69
+ <StatCard label="Total Agents" value={stats.total} />
70
+ <StatCard label="Active" value={stats.active} />
71
+ <StatCard label="Paused" value={stats.paused} />
72
+ <StatCard label="Draft" value={stats.draft} />
73
+ </StatCardGroup>
74
+ )}
75
75
 
76
- {/* Actions */}
77
- <div className="flex items-center justify-between">
78
- <h3 className="text-lg font-semibold">Agents</h3>
79
- <Button onPress={() => alert('Create Agent clicked!')}>
80
- Create Agent
81
- </Button>
82
- </div>
76
+ {/* Actions */}
77
+ <div className="flex items-center justify-between">
78
+ <h3 className="font-semibold text-lg">Agents</h3>
79
+ <Button onPress={() => alert('Create Agent clicked!')}>
80
+ Create Agent
81
+ </Button>
82
+ </div>
83
83
 
84
- {/* Agent List */}
85
- <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
86
- {data.items.map((agent) => (
87
- <EntityCard
88
- key={agent.id}
89
- cardTitle={agent.name}
90
- cardSubtitle={agent.modelName}
91
- meta={
92
- <p className="text-muted-foreground text-sm">
93
- {agent.description}
94
- </p>
95
- }
96
- chips={
97
- <StatusChip
98
- tone={getStatusTone(agent.status)}
99
- label={agent.status}
100
- />
101
- }
102
- footer={
103
- <span className="text-muted-foreground text-xs">
104
- Created {agent.createdAt.toLocaleDateString()}
105
- </span>
106
- }
107
- onClick={() => alert(`View agent: ${agent.name}`)}
108
- />
109
- ))}
110
- </div>
111
- </div>
112
- );
84
+ {/* Agent List */}
85
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
86
+ {data.items.map((agent) => (
87
+ <EntityCard
88
+ key={agent.id}
89
+ cardTitle={agent.name}
90
+ cardSubtitle={agent.modelName}
91
+ meta={
92
+ <p className="text-muted-foreground text-sm">
93
+ {agent.description}
94
+ </p>
95
+ }
96
+ chips={
97
+ <StatusChip
98
+ tone={getStatusTone(agent.status)}
99
+ label={agent.status}
100
+ />
101
+ }
102
+ footer={
103
+ <span className="text-muted-foreground text-xs">
104
+ Created {agent.createdAt.toLocaleDateString()}
105
+ </span>
106
+ }
107
+ onClick={() => alert(`View agent: ${agent.name}`)}
108
+ />
109
+ ))}
110
+ </div>
111
+ </div>
112
+ );
113
113
  }
@@ -4,170 +4,170 @@
4
4
  * Run List View - Shows agent execution runs with stats
5
5
  */
6
6
  import {
7
- StatCard,
8
- StatCardGroup,
9
- StatusChip,
10
- EmptyState,
11
- LoaderBlock,
12
- ErrorState,
7
+ EmptyState,
8
+ ErrorState,
9
+ LoaderBlock,
10
+ StatCard,
11
+ StatCardGroup,
12
+ StatusChip,
13
13
  } from '@contractspec/lib.design-system';
14
- import { useRunList, type Run } from '../hooks/useRunList';
14
+ import { type Run, useRunList } from '../hooks/useRunList';
15
15
 
16
16
  interface RunListViewProps {
17
- agentId?: string;
18
- onRunClick?: (runId: string) => void;
17
+ agentId?: string;
18
+ onRunClick?: (runId: string) => void;
19
19
  }
20
20
 
21
21
  function getStatusTone(
22
- status: Run['status']
22
+ status: Run['status']
23
23
  ): 'success' | 'warning' | 'neutral' | 'danger' {
24
- switch (status) {
25
- case 'COMPLETED':
26
- return 'success';
27
- case 'RUNNING':
28
- return 'warning';
29
- case 'QUEUED':
30
- return 'neutral';
31
- case 'FAILED':
32
- case 'CANCELLED':
33
- return 'danger';
34
- default:
35
- return 'neutral';
36
- }
24
+ switch (status) {
25
+ case 'COMPLETED':
26
+ return 'success';
27
+ case 'RUNNING':
28
+ return 'warning';
29
+ case 'QUEUED':
30
+ return 'neutral';
31
+ case 'FAILED':
32
+ case 'CANCELLED':
33
+ return 'danger';
34
+ default:
35
+ return 'neutral';
36
+ }
37
37
  }
38
38
 
39
39
  function formatDuration(ms?: number): string {
40
- if (!ms) return '-';
41
- if (ms < 1000) return `${ms}ms`;
42
- if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
43
- return `${(ms / 60000).toFixed(1)}m`;
40
+ if (!ms) return '-';
41
+ if (ms < 1000) return `${ms}ms`;
42
+ if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
43
+ return `${(ms / 60000).toFixed(1)}m`;
44
44
  }
45
45
 
46
46
  function formatTokens(tokens: number): string {
47
- if (tokens < 1000) return tokens.toString();
48
- if (tokens < 1000000) return `${(tokens / 1000).toFixed(1)}K`;
49
- return `${(tokens / 1000000).toFixed(2)}M`;
47
+ if (tokens < 1000) return tokens.toString();
48
+ if (tokens < 1000000) return `${(tokens / 1000).toFixed(1)}K`;
49
+ return `${(tokens / 1000000).toFixed(2)}M`;
50
50
  }
51
51
 
52
52
  function formatCost(cost?: number): string {
53
- if (!cost) return '-';
54
- return `$${cost.toFixed(4)}`;
53
+ if (!cost) return '-';
54
+ return `$${cost.toFixed(4)}`;
55
55
  }
56
56
 
57
57
  export function RunListView({ agentId, onRunClick }: RunListViewProps) {
58
- const { data, metrics, loading, error, refetch } = useRunList({ agentId });
58
+ const { data, metrics, loading, error, refetch } = useRunList({ agentId });
59
59
 
60
- if (loading && !data) {
61
- return <LoaderBlock label="Loading runs..." />;
62
- }
60
+ if (loading && !data) {
61
+ return <LoaderBlock label="Loading runs..." />;
62
+ }
63
63
 
64
- if (error) {
65
- return (
66
- <ErrorState
67
- title="Failed to load runs"
68
- description={error.message}
69
- onRetry={refetch}
70
- retryLabel="Retry"
71
- />
72
- );
73
- }
64
+ if (error) {
65
+ return (
66
+ <ErrorState
67
+ title="Failed to load runs"
68
+ description={error.message}
69
+ onRetry={refetch}
70
+ retryLabel="Retry"
71
+ />
72
+ );
73
+ }
74
74
 
75
- if (!data?.items.length) {
76
- return (
77
- <EmptyState
78
- title="No runs yet"
79
- description="Execute an agent to see run history here."
80
- />
81
- );
82
- }
75
+ if (!data?.items.length) {
76
+ return (
77
+ <EmptyState
78
+ title="No runs yet"
79
+ description="Execute an agent to see run history here."
80
+ />
81
+ );
82
+ }
83
83
 
84
- return (
85
- <div className="space-y-6">
86
- {/* Metrics Stats */}
87
- {metrics && (
88
- <StatCardGroup>
89
- <StatCard label="Total Runs" value={metrics.totalRuns} />
90
- <StatCard
91
- label="Success Rate"
92
- value={`${(metrics.successRate * 100).toFixed(1)}%`}
93
- />
94
- <StatCard
95
- label="Total Tokens"
96
- value={formatTokens(metrics.totalTokens)}
97
- />
98
- <StatCard
99
- label="Total Cost"
100
- value={`$${metrics.totalCostUsd.toFixed(2)}`}
101
- />
102
- </StatCardGroup>
103
- )}
84
+ return (
85
+ <div className="space-y-6">
86
+ {/* Metrics Stats */}
87
+ {metrics && (
88
+ <StatCardGroup>
89
+ <StatCard label="Total Runs" value={metrics.totalRuns} />
90
+ <StatCard
91
+ label="Success Rate"
92
+ value={`${(metrics.successRate * 100).toFixed(1)}%`}
93
+ />
94
+ <StatCard
95
+ label="Total Tokens"
96
+ value={formatTokens(metrics.totalTokens)}
97
+ />
98
+ <StatCard
99
+ label="Total Cost"
100
+ value={`$${metrics.totalCostUsd.toFixed(2)}`}
101
+ />
102
+ </StatCardGroup>
103
+ )}
104
104
 
105
- {/* Run List */}
106
- <div className="border-border rounded-lg border">
107
- <table className="w-full">
108
- <thead className="border-border bg-muted/30 border-b">
109
- <tr>
110
- <th className="text-muted-foreground px-4 py-3 text-left text-sm font-medium">
111
- Run
112
- </th>
113
- <th className="text-muted-foreground px-4 py-3 text-left text-sm font-medium">
114
- Agent
115
- </th>
116
- <th className="text-muted-foreground px-4 py-3 text-left text-sm font-medium">
117
- Status
118
- </th>
119
- <th className="text-muted-foreground px-4 py-3 text-right text-sm font-medium">
120
- Tokens
121
- </th>
122
- <th className="text-muted-foreground px-4 py-3 text-right text-sm font-medium">
123
- Duration
124
- </th>
125
- <th className="text-muted-foreground px-4 py-3 text-right text-sm font-medium">
126
- Cost
127
- </th>
128
- </tr>
129
- </thead>
130
- <tbody className="divide-border divide-y">
131
- {data.items.map((run: Run) => (
132
- <tr
133
- key={run.id}
134
- className="hover:bg-muted/50 cursor-pointer transition-colors"
135
- onClick={() => onRunClick?.(run.id)}
136
- >
137
- <td className="px-4 py-3">
138
- <div className="font-mono text-sm">{run.id.slice(-8)}</div>
139
- <div className="text-muted-foreground text-xs">
140
- {run.queuedAt.toLocaleString()}
141
- </div>
142
- </td>
143
- <td className="px-4 py-3">
144
- <span className="font-medium">{run.agentName}</span>
145
- </td>
146
- <td className="px-4 py-3">
147
- <StatusChip
148
- tone={getStatusTone(run.status)}
149
- label={run.status}
150
- />
151
- </td>
152
- <td className="px-4 py-3 text-right font-mono text-sm">
153
- {formatTokens(run.totalTokens)}
154
- </td>
155
- <td className="px-4 py-3 text-right font-mono text-sm">
156
- {formatDuration(run.durationMs)}
157
- </td>
158
- <td className="px-4 py-3 text-right font-mono text-sm">
159
- {formatCost(run.estimatedCostUsd)}
160
- </td>
161
- </tr>
162
- ))}
163
- </tbody>
164
- </table>
165
- </div>
105
+ {/* Run List */}
106
+ <div className="rounded-lg border border-border">
107
+ <table className="w-full">
108
+ <thead className="border-border border-b bg-muted/30">
109
+ <tr>
110
+ <th className="px-4 py-3 text-left font-medium text-muted-foreground text-sm">
111
+ Run
112
+ </th>
113
+ <th className="px-4 py-3 text-left font-medium text-muted-foreground text-sm">
114
+ Agent
115
+ </th>
116
+ <th className="px-4 py-3 text-left font-medium text-muted-foreground text-sm">
117
+ Status
118
+ </th>
119
+ <th className="px-4 py-3 text-right font-medium text-muted-foreground text-sm">
120
+ Tokens
121
+ </th>
122
+ <th className="px-4 py-3 text-right font-medium text-muted-foreground text-sm">
123
+ Duration
124
+ </th>
125
+ <th className="px-4 py-3 text-right font-medium text-muted-foreground text-sm">
126
+ Cost
127
+ </th>
128
+ </tr>
129
+ </thead>
130
+ <tbody className="divide-y divide-border">
131
+ {data.items.map((run: Run) => (
132
+ <tr
133
+ key={run.id}
134
+ className="cursor-pointer transition-colors hover:bg-muted/50"
135
+ onClick={() => onRunClick?.(run.id)}
136
+ >
137
+ <td className="px-4 py-3">
138
+ <div className="font-mono text-sm">{run.id.slice(-8)}</div>
139
+ <div className="text-muted-foreground text-xs">
140
+ {run.queuedAt.toLocaleString()}
141
+ </div>
142
+ </td>
143
+ <td className="px-4 py-3">
144
+ <span className="font-medium">{run.agentName}</span>
145
+ </td>
146
+ <td className="px-4 py-3">
147
+ <StatusChip
148
+ tone={getStatusTone(run.status)}
149
+ label={run.status}
150
+ />
151
+ </td>
152
+ <td className="px-4 py-3 text-right font-mono text-sm">
153
+ {formatTokens(run.totalTokens)}
154
+ </td>
155
+ <td className="px-4 py-3 text-right font-mono text-sm">
156
+ {formatDuration(run.durationMs)}
157
+ </td>
158
+ <td className="px-4 py-3 text-right font-mono text-sm">
159
+ {formatCost(run.estimatedCostUsd)}
160
+ </td>
161
+ </tr>
162
+ ))}
163
+ </tbody>
164
+ </table>
165
+ </div>
166
166
 
167
- {/* Pagination */}
168
- <div className="text-muted-foreground text-center text-sm">
169
- Showing {data.items.length} of {data.total} runs
170
- </div>
171
- </div>
172
- );
167
+ {/* Pagination */}
168
+ <div className="text-center text-muted-foreground text-sm">
169
+ Showing {data.items.length} of {data.total} runs
170
+ </div>
171
+ </div>
172
+ );
173
173
  }