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