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