@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.
- package/.turbo/turbo-build.log +126 -105
- package/AGENTS.md +52 -31
- package/CHANGELOG.md +29 -0
- package/README.md +112 -83
- package/dist/agent/agent.event.js +1 -1
- package/dist/agent/agent.handler.d.ts +3 -0
- package/dist/agent/agent.handler.js +730 -1
- package/dist/agent/agent.operation.js +1 -1
- package/dist/agent/index.d.ts +5 -5
- package/dist/agent/index.js +74 -73
- package/dist/agent.feature.js +179 -0
- package/dist/browser/agent/agent.event.js +1 -1
- package/dist/browser/agent/agent.handler.js +730 -1
- package/dist/browser/agent/agent.operation.js +1 -1
- package/dist/browser/agent/index.js +74 -73
- package/dist/browser/agent.feature.js +179 -0
- package/dist/browser/docs/agent-console.docblock.js +11 -8
- package/dist/browser/docs/index.js +11 -8
- package/dist/browser/example.js +2 -3
- package/dist/browser/handlers/agent.handlers.js +1883 -2
- package/dist/browser/handlers/index.js +2142 -8
- package/dist/browser/index.js +4075 -3161
- package/dist/browser/presentations/index.js +51 -51
- package/dist/browser/run/index.js +380 -374
- package/dist/browser/run/run.event.js +2 -2
- package/dist/browser/run/run.handler.js +666 -1
- package/dist/browser/run/run.presentation.js +2 -2
- package/dist/browser/shared/index.js +293 -1
- package/dist/browser/shared/mock-runs.js +5 -0
- package/dist/browser/tool/index.js +161 -161
- package/dist/browser/tool/tool.event.js +1 -1
- package/dist/browser/tool/tool.handler.js +479 -3
- package/dist/browser/tool/tool.presentation.js +2 -2
- package/dist/browser/ui/AgentDashboard.js +1816 -931
- package/dist/browser/ui/AgentDashboard.visualizations.js +217 -0
- package/dist/browser/ui/AgentRunList.js +360 -128
- package/dist/browser/ui/AgentToolRegistry.js +9 -9
- package/dist/browser/ui/hooks/index.js +611 -161
- package/dist/browser/ui/hooks/useAgentList.js +1 -1
- package/dist/browser/ui/hooks/useAgentMutations.js +444 -9
- package/dist/browser/ui/hooks/useRunList.js +26 -11
- package/dist/browser/ui/hooks/useToolList.js +1 -1
- package/dist/browser/ui/index.js +2161 -1258
- package/dist/browser/ui/modals/AgentActionsModal.js +13 -13
- package/dist/browser/ui/modals/CreateAgentModal.js +15 -15
- package/dist/browser/ui/modals/index.js +297 -297
- package/dist/browser/ui/renderers/agent-list.markdown.js +14 -5
- package/dist/browser/ui/renderers/agent-list.renderer.js +7 -7
- package/dist/browser/ui/renderers/dashboard.markdown.js +207 -36
- package/dist/browser/ui/renderers/index.js +359 -163
- package/dist/browser/ui/renderers/run-list.markdown.js +9 -4
- package/dist/browser/ui/renderers/tool-registry.markdown.js +15 -4
- package/dist/browser/ui/views/AgentListView.js +7 -7
- package/dist/browser/ui/views/RunDataTable.js +326 -0
- package/dist/browser/ui/views/RunListView.js +360 -128
- package/dist/browser/ui/views/ToolRegistryView.js +9 -9
- package/dist/browser/ui/views/index.js +478 -246
- package/dist/browser/ui/views/run-data-table.columns.js +271 -0
- package/dist/browser/ui/views/run-list.shared.js +177 -0
- package/dist/browser/visualizations/catalog.js +134 -0
- package/dist/browser/visualizations/index.js +187 -0
- package/dist/browser/visualizations/selectors.js +181 -0
- package/dist/docs/agent-console.docblock.js +11 -8
- package/dist/docs/index.js +11 -8
- package/dist/example.js +2 -3
- package/dist/example.test.d.ts +1 -0
- package/dist/handlers/agent.handlers.d.ts +2 -0
- package/dist/handlers/agent.handlers.js +1883 -2
- package/dist/handlers/index.d.ts +2 -4
- package/dist/handlers/index.js +2142 -8
- package/dist/handlers/mock-handlers.test.d.ts +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4075 -3161
- package/dist/node/agent/agent.event.js +1 -1
- package/dist/node/agent/agent.handler.js +730 -1
- package/dist/node/agent/agent.operation.js +1 -1
- package/dist/node/agent/index.js +74 -73
- package/dist/node/agent.feature.js +179 -0
- package/dist/node/docs/agent-console.docblock.js +11 -8
- package/dist/node/docs/index.js +11 -8
- package/dist/node/example.js +2 -3
- package/dist/node/handlers/agent.handlers.js +1883 -2
- package/dist/node/handlers/index.js +2142 -8
- package/dist/node/index.js +4075 -3161
- package/dist/node/presentations/index.js +51 -51
- package/dist/node/run/index.js +380 -374
- package/dist/node/run/run.event.js +2 -2
- package/dist/node/run/run.handler.js +666 -1
- package/dist/node/run/run.presentation.js +2 -2
- package/dist/node/shared/index.js +293 -1
- package/dist/node/shared/mock-runs.js +5 -0
- package/dist/node/tool/index.js +161 -161
- package/dist/node/tool/tool.event.js +1 -1
- package/dist/node/tool/tool.handler.js +479 -3
- package/dist/node/tool/tool.presentation.js +2 -2
- package/dist/node/ui/AgentDashboard.js +1816 -931
- package/dist/node/ui/AgentDashboard.visualizations.js +217 -0
- package/dist/node/ui/AgentRunList.js +360 -128
- package/dist/node/ui/AgentToolRegistry.js +9 -9
- package/dist/node/ui/hooks/index.js +611 -161
- package/dist/node/ui/hooks/useAgentList.js +1 -1
- package/dist/node/ui/hooks/useAgentMutations.js +444 -9
- package/dist/node/ui/hooks/useRunList.js +26 -11
- package/dist/node/ui/hooks/useToolList.js +1 -1
- package/dist/node/ui/index.js +2161 -1258
- package/dist/node/ui/modals/AgentActionsModal.js +13 -13
- package/dist/node/ui/modals/CreateAgentModal.js +15 -15
- package/dist/node/ui/modals/index.js +297 -297
- package/dist/node/ui/renderers/agent-list.markdown.js +14 -5
- package/dist/node/ui/renderers/agent-list.renderer.js +7 -7
- package/dist/node/ui/renderers/dashboard.markdown.js +207 -36
- package/dist/node/ui/renderers/index.js +359 -163
- package/dist/node/ui/renderers/run-list.markdown.js +9 -4
- package/dist/node/ui/renderers/tool-registry.markdown.js +15 -4
- package/dist/node/ui/views/AgentListView.js +7 -7
- package/dist/node/ui/views/RunDataTable.js +326 -0
- package/dist/node/ui/views/RunListView.js +360 -128
- package/dist/node/ui/views/ToolRegistryView.js +9 -9
- package/dist/node/ui/views/index.js +478 -246
- package/dist/node/ui/views/run-data-table.columns.js +271 -0
- package/dist/node/ui/views/run-list.shared.js +177 -0
- package/dist/node/visualizations/catalog.js +134 -0
- package/dist/node/visualizations/index.js +187 -0
- package/dist/node/visualizations/selectors.js +181 -0
- package/dist/presentations/index.d.ts +3 -5
- package/dist/presentations/index.js +51 -51
- package/dist/proof/index.d.ts +2 -0
- package/dist/proof/meetup-proof.d.ts +10 -0
- package/dist/proof/meetup-proof.runtime.d.ts +22 -0
- package/dist/proof/meetup-proof.scenario.d.ts +2 -0
- package/dist/proof/meetup-proof.suite.d.ts +1 -0
- package/dist/proof/meetup-proof.test.d.ts +1 -0
- package/dist/run/index.d.ts +7 -7
- package/dist/run/index.js +380 -374
- package/dist/run/run.event.js +2 -2
- package/dist/run/run.handler.d.ts +7 -0
- package/dist/run/run.handler.js +666 -1
- package/dist/run/run.presentation.js +2 -2
- package/dist/shared/demo-dashboard-data.d.ts +16 -0
- package/dist/shared/demo-runtime-seed.d.ts +17 -0
- package/dist/shared/demo-runtime.d.ts +8 -0
- package/dist/shared/demo-runtime.test.d.ts +1 -0
- package/dist/shared/index.d.ts +4 -1
- package/dist/shared/index.js +293 -1
- package/dist/shared/mock-runs.d.ts +4 -0
- package/dist/shared/mock-runs.js +5 -0
- package/dist/tool/index.d.ts +7 -7
- package/dist/tool/index.js +161 -161
- package/dist/tool/tool.event.js +1 -1
- package/dist/tool/tool.handler.d.ts +3 -0
- package/dist/tool/tool.handler.js +479 -3
- package/dist/tool/tool.presentation.js +2 -2
- package/dist/ui/AgentDashboard.js +1816 -931
- package/dist/ui/AgentDashboard.sandbox.test.d.ts +1 -0
- package/dist/ui/AgentDashboard.visualizations.d.ts +4 -0
- package/dist/ui/AgentDashboard.visualizations.js +218 -0
- package/dist/ui/AgentRunList.js +360 -128
- package/dist/ui/AgentToolRegistry.js +9 -9
- package/dist/ui/hooks/index.d.ts +4 -4
- package/dist/ui/hooks/index.js +611 -161
- package/dist/ui/hooks/useAgentList.d.ts +5 -0
- package/dist/ui/hooks/useAgentList.js +1 -1
- package/dist/ui/hooks/useAgentMutations.d.ts +9 -2
- package/dist/ui/hooks/useAgentMutations.js +444 -9
- package/dist/ui/hooks/useRunList.d.ts +13 -2
- package/dist/ui/hooks/useRunList.js +26 -11
- package/dist/ui/hooks/useToolList.d.ts +5 -0
- package/dist/ui/hooks/useToolList.js +1 -1
- package/dist/ui/index.d.ts +3 -3
- package/dist/ui/index.js +2161 -1258
- package/dist/ui/modals/AgentActionsModal.js +13 -13
- package/dist/ui/modals/CreateAgentModal.js +15 -15
- package/dist/ui/modals/index.d.ts +1 -1
- package/dist/ui/modals/index.js +297 -297
- package/dist/ui/renderers/agent-list.markdown.d.ts +5 -0
- package/dist/ui/renderers/agent-list.markdown.js +14 -5
- package/dist/ui/renderers/agent-list.renderer.js +7 -7
- package/dist/ui/renderers/dashboard.markdown.d.ts +5 -0
- package/dist/ui/renderers/dashboard.markdown.js +207 -36
- package/dist/ui/renderers/index.d.ts +2 -2
- package/dist/ui/renderers/index.js +359 -163
- package/dist/ui/renderers/run-list.markdown.d.ts +5 -0
- package/dist/ui/renderers/run-list.markdown.js +9 -4
- package/dist/ui/renderers/tool-registry.markdown.d.ts +6 -1
- package/dist/ui/renderers/tool-registry.markdown.js +15 -4
- package/dist/ui/views/AgentListView.js +7 -7
- package/dist/ui/views/RunDataTable.d.ts +18 -0
- package/dist/ui/views/RunDataTable.js +327 -0
- package/dist/ui/views/RunListView.js +360 -128
- package/dist/ui/views/ToolRegistryView.js +9 -9
- package/dist/ui/views/index.js +478 -246
- package/dist/ui/views/run-data-table.columns.d.ts +3 -0
- package/dist/ui/views/run-data-table.columns.js +272 -0
- package/dist/ui/views/run-list.shared.d.ts +14 -0
- package/dist/ui/views/run-list.shared.js +178 -0
- package/dist/visualizations/catalog.d.ts +10 -0
- package/dist/visualizations/catalog.js +135 -0
- package/dist/visualizations/index.d.ts +2 -0
- package/dist/visualizations/index.js +188 -0
- package/dist/visualizations/selectors.d.ts +3 -0
- package/dist/visualizations/selectors.js +182 -0
- package/dist/visualizations/selectors.test.d.ts +1 -0
- package/package.json +114 -12
- package/proofs/agent-console-meetup.replay.json +220 -0
- package/src/agent/agent.entity.ts +111 -111
- package/src/agent/agent.enum.ts +12 -12
- package/src/agent/agent.event.ts +91 -91
- package/src/agent/agent.handler.ts +144 -127
- package/src/agent/agent.operation.ts +400 -400
- package/src/agent/agent.presentation.ts +62 -62
- package/src/agent/agent.schema.ts +175 -175
- package/src/agent/agent.test-spec.ts +48 -48
- package/src/agent/index.ts +46 -51
- package/src/agent.capability.ts +11 -11
- package/src/agent.feature.ts +134 -131
- package/src/docs/agent-console.docblock.ts +52 -49
- package/src/example.test.ts +75 -0
- package/src/example.ts +34 -35
- package/src/handlers/agent.handlers.ts +576 -522
- package/src/handlers/index.ts +30 -14
- package/src/handlers/mock-handlers.test.ts +77 -0
- package/src/index.ts +10 -9
- package/src/presentations/index.ts +11 -13
- package/src/proof/index.ts +2 -0
- package/src/proof/meetup-proof.runtime.ts +196 -0
- package/src/proof/meetup-proof.scenario.ts +99 -0
- package/src/proof/meetup-proof.suite.ts +29 -0
- package/src/proof/meetup-proof.test.ts +28 -0
- package/src/proof/meetup-proof.ts +130 -0
- package/src/run/index.ts +49 -54
- package/src/run/run.entity.ts +137 -137
- package/src/run/run.enum.ts +18 -18
- package/src/run/run.event.ts +174 -174
- package/src/run/run.handler.ts +113 -96
- package/src/run/run.operation.ts +474 -474
- package/src/run/run.presentation.ts +42 -42
- package/src/run/run.schema.ts +126 -126
- package/src/run/run.test-spec.ts +48 -48
- package/src/seeders/index.ts +21 -21
- package/src/shared/demo-dashboard-data.ts +58 -0
- package/src/shared/demo-runtime-seed.ts +139 -0
- package/src/shared/demo-runtime.test.ts +169 -0
- package/src/shared/demo-runtime.ts +260 -0
- package/src/shared/index.ts +12 -1
- package/src/shared/mock-agents.ts +76 -76
- package/src/shared/mock-runs.ts +107 -102
- package/src/shared/mock-tools.ts +140 -140
- package/src/shared/overlay-types.ts +23 -23
- package/src/tool/index.ts +39 -44
- package/src/tool/tool.entity.ts +73 -73
- package/src/tool/tool.enum.ts +13 -13
- package/src/tool/tool.event.ts +80 -80
- package/src/tool/tool.handler.ts +124 -107
- package/src/tool/tool.operation.ts +328 -328
- package/src/tool/tool.presentation.ts +43 -43
- package/src/tool/tool.schema.ts +106 -106
- package/src/tool/tool.test-spec.ts +48 -48
- package/src/ui/AgentDashboard.sandbox.test.tsx +312 -0
- package/src/ui/AgentDashboard.tsx +351 -348
- package/src/ui/AgentDashboard.visualizations.tsx +35 -0
- package/src/ui/hooks/index.ts +7 -7
- package/src/ui/hooks/useAgentList.ts +57 -56
- package/src/ui/hooks/useAgentMutations.ts +168 -159
- package/src/ui/hooks/useRunList.ts +90 -57
- package/src/ui/hooks/useToolList.ts +102 -101
- package/src/ui/index.ts +6 -9
- package/src/ui/modals/AgentActionsModal.tsx +262 -262
- package/src/ui/modals/CreateAgentModal.tsx +232 -232
- package/src/ui/modals/index.ts +1 -1
- package/src/ui/overlays/demo-overlays.ts +52 -52
- package/src/ui/renderers/agent-list.markdown.ts +81 -61
- package/src/ui/renderers/agent-list.renderer.tsx +14 -14
- package/src/ui/renderers/dashboard.markdown.ts +135 -139
- package/src/ui/renderers/index.ts +3 -4
- package/src/ui/renderers/run-list.markdown.ts +56 -47
- package/src/ui/renderers/tool-registry.markdown.ts +79 -66
- package/src/ui/views/AgentListView.tsx +90 -90
- package/src/ui/views/RunDataTable.tsx +74 -0
- package/src/ui/views/RunListView.tsx +84 -158
- package/src/ui/views/ToolRegistryView.tsx +113 -113
- package/src/ui/views/run-data-table.columns.tsx +102 -0
- package/src/ui/views/run-list.shared.tsx +139 -0
- package/src/visualizations/catalog.ts +132 -0
- package/src/visualizations/index.ts +2 -0
- package/src/visualizations/selectors.test.ts +12 -0
- package/src/visualizations/selectors.ts +70 -0
- package/tsconfig.json +7 -8
- package/tsdown.config.js +24 -3
|
@@ -1,16 +1,815 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// src/
|
|
3
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
23
|
-
|
|
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
|
-
}, [
|
|
40
|
-
|
|
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: () =>
|
|
51
|
-
prevPage:
|
|
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/
|
|
56
|
-
import {
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
871
|
+
function getStatusColor(status) {
|
|
67
872
|
switch (status) {
|
|
68
|
-
case "
|
|
69
|
-
return "
|
|
70
|
-
case "
|
|
71
|
-
return "
|
|
72
|
-
case "
|
|
73
|
-
return "
|
|
74
|
-
case "
|
|
75
|
-
|
|
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 "
|
|
882
|
+
return "text-gray-600 bg-gray-100";
|
|
79
883
|
}
|
|
80
884
|
}
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
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__ */
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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__ */
|
|
156
|
-
className: "text-muted-foreground
|
|
157
|
-
children:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}, undefined,
|
|
163
|
-
/* @__PURE__ */
|
|
164
|
-
className:
|
|
165
|
-
children:
|
|
166
|
-
}, undefined, false, undefined, this)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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__ */
|
|
189
|
-
className: "
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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__ */
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
},
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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("
|
|
423
|
-
className: "
|
|
424
|
-
children:
|
|
425
|
-
|
|
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: "
|
|
430
|
-
children:
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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:
|
|
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
|
-
|
|
442
|
-
className: "
|
|
443
|
-
children:
|
|
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
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
},
|
|
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
|
|
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: "
|
|
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
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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
|
|
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
|
|
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/
|
|
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 {
|
|
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
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
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
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
const [
|
|
871
|
-
const
|
|
872
|
-
|
|
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
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
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
|
|
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
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
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__ */
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
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__ */
|
|
940
|
-
className: "
|
|
1982
|
+
/* @__PURE__ */ jsxDEV8("div", {
|
|
1983
|
+
className: "flex items-center gap-2",
|
|
941
1984
|
children: [
|
|
942
|
-
/* @__PURE__ */
|
|
943
|
-
className: "text-
|
|
944
|
-
children:
|
|
1985
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
1986
|
+
className: "text-2xl",
|
|
1987
|
+
children: categoryIcons[category]
|
|
945
1988
|
}, undefined, false, undefined, this),
|
|
946
|
-
/* @__PURE__ */
|
|
947
|
-
className: "
|
|
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__ */
|
|
1043
|
-
className: "
|
|
1044
|
-
children:
|
|
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
|
-
|
|
1054
|
-
className: "
|
|
1055
|
-
children:
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
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:
|
|
2006
|
+
children: tool.description
|
|
1114
2007
|
}, undefined, false, undefined, this),
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
2008
|
+
chips: /* @__PURE__ */ jsxDEV8(StatusChip3, {
|
|
2009
|
+
tone: getStatusTone2(tool.status),
|
|
2010
|
+
label: tool.status
|
|
1118
2011
|
}, undefined, false, undefined, this),
|
|
1119
|
-
/* @__PURE__ */
|
|
1120
|
-
className: "
|
|
1121
|
-
children:
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
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
|
-
},
|
|
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 {
|
|
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] =
|
|
1154
|
-
const [isCreateModalOpen, setIsCreateModalOpen] =
|
|
1155
|
-
const [selectedAgent, setSelectedAgent] =
|
|
1156
|
-
const [isAgentActionsOpen, setIsAgentActionsOpen] =
|
|
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 =
|
|
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__ */
|
|
2089
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
1208
2090
|
className: "space-y-6",
|
|
1209
2091
|
children: [
|
|
1210
|
-
/* @__PURE__ */
|
|
2092
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1211
2093
|
className: "flex items-center justify-between",
|
|
1212
2094
|
children: [
|
|
1213
|
-
/* @__PURE__ */
|
|
1214
|
-
className: "text-2xl
|
|
2095
|
+
/* @__PURE__ */ jsxDEV9("h2", {
|
|
2096
|
+
className: "font-bold text-2xl",
|
|
1215
2097
|
children: "AI Agent Console"
|
|
1216
2098
|
}, undefined, false, undefined, this),
|
|
1217
|
-
/* @__PURE__ */
|
|
2099
|
+
/* @__PURE__ */ jsxDEV9(Button5, {
|
|
1218
2100
|
onPress: () => setIsCreateModalOpen(true),
|
|
1219
2101
|
children: [
|
|
1220
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1230
|
-
children: summaryStats.map((stat, i) => /* @__PURE__ */
|
|
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__ */
|
|
1237
|
-
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2138
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1254
2139
|
className: "min-h-[400px]",
|
|
1255
2140
|
role: "tabpanel",
|
|
1256
2141
|
children: [
|
|
1257
|
-
activeTab === "runs" && /* @__PURE__ */
|
|
1258
|
-
activeTab === "agents" && /* @__PURE__ */
|
|
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__ */
|
|
1262
|
-
activeTab === "metrics" && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1305
|
-
className: "
|
|
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__ */
|
|
1311
|
-
className: "
|
|
2195
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
2196
|
+
className: "flex h-64 flex-col items-center justify-center text-destructive",
|
|
1312
2197
|
children: [
|
|
1313
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1330
|
-
className: "
|
|
2214
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
2215
|
+
className: "flex h-64 flex-col items-center justify-center text-muted-foreground",
|
|
1331
2216
|
children: [
|
|
1332
|
-
/* @__PURE__ */
|
|
1333
|
-
className: "text-lg
|
|
2217
|
+
/* @__PURE__ */ jsxDEV9("p", {
|
|
2218
|
+
className: "font-medium text-lg",
|
|
1334
2219
|
children: "No agents yet"
|
|
1335
2220
|
}, undefined, false, undefined, this),
|
|
1336
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2228
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
1344
2229
|
className: "space-y-4",
|
|
1345
2230
|
children: [
|
|
1346
|
-
stats && /* @__PURE__ */
|
|
2231
|
+
stats && /* @__PURE__ */ jsxDEV9("div", {
|
|
1347
2232
|
className: "flex gap-4 text-sm",
|
|
1348
2233
|
children: [
|
|
1349
|
-
/* @__PURE__ */
|
|
2234
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
1350
2235
|
children: [
|
|
1351
2236
|
"Total: ",
|
|
1352
2237
|
stats.total
|
|
1353
2238
|
]
|
|
1354
2239
|
}, undefined, true, undefined, this),
|
|
1355
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2280
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
1396
2281
|
onClick,
|
|
1397
|
-
className: "
|
|
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__ */
|
|
2290
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1406
2291
|
className: "flex items-start justify-between",
|
|
1407
2292
|
children: [
|
|
1408
|
-
/* @__PURE__ */
|
|
2293
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1409
2294
|
className: "min-w-0 flex-1",
|
|
1410
2295
|
children: [
|
|
1411
|
-
/* @__PURE__ */
|
|
2296
|
+
/* @__PURE__ */ jsxDEV9("h3", {
|
|
1412
2297
|
className: "truncate font-semibold",
|
|
1413
2298
|
children: agent.name
|
|
1414
2299
|
}, undefined, false, undefined, this),
|
|
1415
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1426
|
-
className: `rounded-full px-2 py-0.5 text-xs
|
|
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__ */
|
|
1432
|
-
className: "
|
|
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__ */
|
|
2320
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1436
2321
|
className: "mt-3 flex items-center justify-between",
|
|
1437
2322
|
children: [
|
|
1438
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1456
|
-
className: "
|
|
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__ */
|
|
2347
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
1463
2348
|
className: "space-y-6",
|
|
1464
2349
|
children: [
|
|
1465
|
-
/* @__PURE__ */
|
|
1466
|
-
className: "text-lg
|
|
2350
|
+
/* @__PURE__ */ jsxDEV9("h3", {
|
|
2351
|
+
className: "font-semibold text-lg",
|
|
1467
2352
|
children: "Usage Analytics"
|
|
1468
2353
|
}, undefined, false, undefined, this),
|
|
1469
|
-
/* @__PURE__ */
|
|
2354
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1470
2355
|
className: "grid gap-6 md:grid-cols-2",
|
|
1471
2356
|
children: [
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
className: "border-border bg-card
|
|
2357
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
2358
|
+
className: "rounded-xl border border-border bg-card p-4",
|
|
1474
2359
|
children: [
|
|
1475
|
-
/* @__PURE__ */
|
|
2360
|
+
/* @__PURE__ */ jsxDEV9("h4", {
|
|
1476
2361
|
className: "font-medium",
|
|
1477
2362
|
children: "Run Outcomes"
|
|
1478
2363
|
}, undefined, false, undefined, this),
|
|
1479
|
-
/* @__PURE__ */
|
|
2364
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1480
2365
|
className: "mt-4 space-y-3",
|
|
1481
2366
|
children: [
|
|
1482
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1499
|
-
className: "border-border bg-card
|
|
2383
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
2384
|
+
className: "rounded-xl border border-border bg-card p-4",
|
|
1500
2385
|
children: [
|
|
1501
|
-
/* @__PURE__ */
|
|
2386
|
+
/* @__PURE__ */ jsxDEV9("h4", {
|
|
1502
2387
|
className: "font-medium",
|
|
1503
2388
|
children: "Performance"
|
|
1504
2389
|
}, undefined, false, undefined, this),
|
|
1505
|
-
/* @__PURE__ */
|
|
2390
|
+
/* @__PURE__ */ jsxDEV9("dl", {
|
|
1506
2391
|
className: "mt-4 grid grid-cols-2 gap-4",
|
|
1507
2392
|
children: [
|
|
1508
|
-
/* @__PURE__ */
|
|
2393
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1509
2394
|
children: [
|
|
1510
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1515
|
-
className: "text-xl
|
|
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__ */
|
|
2408
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1524
2409
|
children: [
|
|
1525
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1530
|
-
className: "text-xl
|
|
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__ */
|
|
1545
|
-
className: "border-border bg-card
|
|
2429
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
2430
|
+
className: "rounded-xl border border-border bg-card p-4",
|
|
1546
2431
|
children: [
|
|
1547
|
-
/* @__PURE__ */
|
|
2432
|
+
/* @__PURE__ */ jsxDEV9("h4", {
|
|
1548
2433
|
className: "font-medium",
|
|
1549
2434
|
children: "Key Metrics"
|
|
1550
2435
|
}, undefined, false, undefined, this),
|
|
1551
|
-
/* @__PURE__ */
|
|
2436
|
+
/* @__PURE__ */ jsxDEV9("dl", {
|
|
1552
2437
|
className: "mt-4 grid gap-4 sm:grid-cols-3",
|
|
1553
2438
|
children: [
|
|
1554
|
-
/* @__PURE__ */
|
|
2439
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1555
2440
|
children: [
|
|
1556
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1561
|
-
className: "text-2xl
|
|
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__ */
|
|
2451
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1567
2452
|
children: [
|
|
1568
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1573
|
-
className: "text-2xl
|
|
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__ */
|
|
2466
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1582
2467
|
children: [
|
|
1583
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1588
|
-
className: "text-2xl
|
|
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__ */
|
|
2495
|
+
return /* @__PURE__ */ jsxDEV9("div", {
|
|
1611
2496
|
children: [
|
|
1612
|
-
/* @__PURE__ */
|
|
2497
|
+
/* @__PURE__ */ jsxDEV9("div", {
|
|
1613
2498
|
className: "flex justify-between text-sm",
|
|
1614
2499
|
children: [
|
|
1615
|
-
/* @__PURE__ */
|
|
2500
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
1616
2501
|
children: label
|
|
1617
2502
|
}, undefined, false, undefined, this),
|
|
1618
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1630
|
-
className: "
|
|
1631
|
-
children: /* @__PURE__ */
|
|
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)
|