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