@contractspec/example.agent-console 1.46.1 → 1.48.0
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$colon$bundle.log +275 -128
- package/.turbo/turbo-build.log +274 -127
- package/CHANGELOG.md +52 -0
- package/dist/agent/agent.entity.d.ts +36 -36
- package/dist/agent/agent.entity.d.ts.map +1 -1
- package/dist/agent/agent.enum.d.ts +4 -4
- package/dist/agent/agent.enum.d.ts.map +1 -1
- package/dist/agent/agent.event.d.ts +31 -31
- package/dist/agent/agent.event.d.ts.map +1 -1
- package/dist/agent/agent.event.js +5 -5
- package/dist/agent/agent.event.js.map +1 -1
- package/dist/agent/agent.handler.js.map +1 -1
- package/dist/agent/agent.operation.d.ts +117 -117
- package/dist/agent/agent.operation.d.ts.map +1 -1
- package/dist/agent/agent.presentation.d.ts +4 -5
- package/dist/agent/agent.presentation.d.ts.map +1 -1
- package/dist/agent/agent.presentation.js +7 -7
- package/dist/agent/agent.presentation.js.map +1 -1
- package/dist/agent/agent.schema.d.ts +95 -95
- package/dist/agent/agent.schema.d.ts.map +1 -1
- package/dist/agent/agent.test-spec.d.ts +8 -0
- package/dist/agent/agent.test-spec.d.ts.map +1 -0
- package/dist/agent/agent.test-spec.js +65 -0
- package/dist/agent/agent.test-spec.js.map +1 -0
- package/dist/agent.capability.d.ts +7 -0
- package/dist/agent.capability.d.ts.map +1 -0
- package/dist/agent.capability.js +20 -0
- package/dist/agent.capability.js.map +1 -0
- package/dist/agent.feature.d.ts.map +1 -1
- package/dist/agent.feature.js +4 -2
- package/dist/agent.feature.js.map +1 -1
- package/dist/example.d.ts +2 -2
- package/dist/example.d.ts.map +1 -1
- package/dist/example.js +4 -2
- package/dist/example.js.map +1 -1
- package/dist/handlers/agent.handlers.d.ts +135 -0
- package/dist/handlers/agent.handlers.d.ts.map +1 -0
- package/dist/handlers/agent.handlers.js +263 -0
- package/dist/handlers/agent.handlers.js.map +1 -0
- package/dist/handlers/index.d.ts +2 -1
- package/dist/handlers/index.js +2 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +19 -1
- package/dist/run/run.entity.d.ts +56 -56
- package/dist/run/run.enum.d.ts +5 -5
- package/dist/run/run.event.d.ts +71 -71
- package/dist/run/run.event.js +8 -8
- package/dist/run/run.event.js.map +1 -1
- package/dist/run/run.operation.d.ts +175 -175
- package/dist/run/run.presentation.d.ts +3 -4
- package/dist/run/run.presentation.d.ts.map +1 -1
- package/dist/run/run.presentation.js +5 -5
- package/dist/run/run.presentation.js.map +1 -1
- package/dist/run/run.schema.d.ts +99 -99
- package/dist/run/run.test-spec.d.ts +8 -0
- package/dist/run/run.test-spec.d.ts.map +1 -0
- package/dist/run/run.test-spec.js +65 -0
- package/dist/run/run.test-spec.js.map +1 -0
- package/dist/seeders/index.d.ts +10 -0
- package/dist/seeders/index.d.ts.map +1 -0
- package/dist/seeders/index.js +20 -0
- package/dist/seeders/index.js.map +1 -0
- package/dist/shared/overlay-types.d.ts +34 -0
- package/dist/shared/overlay-types.d.ts.map +1 -0
- package/dist/shared/overlay-types.js +0 -0
- package/dist/tool/tool.entity.d.ts +24 -24
- package/dist/tool/tool.enum.d.ts +4 -4
- package/dist/tool/tool.event.d.ts +25 -25
- package/dist/tool/tool.event.js +4 -4
- package/dist/tool/tool.event.js.map +1 -1
- package/dist/tool/tool.handler.d.ts.map +1 -1
- package/dist/tool/tool.operation.d.ts +101 -101
- package/dist/tool/tool.presentation.d.ts +3 -4
- package/dist/tool/tool.presentation.d.ts.map +1 -1
- package/dist/tool/tool.presentation.js +5 -5
- package/dist/tool/tool.presentation.js.map +1 -1
- package/dist/tool/tool.schema.d.ts +52 -52
- package/dist/tool/tool.schema.d.ts.map +1 -1
- package/dist/tool/tool.test-spec.d.ts +8 -0
- package/dist/tool/tool.test-spec.d.ts.map +1 -0
- package/dist/tool/tool.test-spec.js +65 -0
- package/dist/tool/tool.test-spec.js.map +1 -0
- package/dist/ui/AgentDashboard.d.ts +7 -0
- package/dist/ui/AgentDashboard.d.ts.map +1 -0
- package/dist/ui/AgentDashboard.js +420 -0
- package/dist/ui/AgentDashboard.js.map +1 -0
- package/dist/ui/AgentRunList.d.ts +2 -0
- package/dist/ui/AgentRunList.js +5 -0
- package/dist/ui/AgentToolRegistry.d.ts +2 -0
- package/dist/ui/AgentToolRegistry.js +5 -0
- package/dist/ui/hooks/index.d.ts +6 -0
- package/dist/ui/hooks/index.js +8 -0
- package/dist/ui/hooks/useAgentList.d.ts +28 -0
- package/dist/ui/hooks/useAgentList.d.ts.map +1 -0
- package/dist/ui/hooks/useAgentList.js +66 -0
- package/dist/ui/hooks/useAgentList.js.map +1 -0
- package/dist/ui/hooks/useAgentMutations.d.ts +29 -0
- package/dist/ui/hooks/useAgentMutations.d.ts.map +1 -0
- package/dist/ui/hooks/useAgentMutations.js +124 -0
- package/dist/ui/hooks/useAgentMutations.js.map +1 -0
- package/dist/ui/hooks/useRunList.d.ts +24 -0
- package/dist/ui/hooks/useRunList.d.ts.map +1 -0
- package/dist/ui/hooks/useRunList.js +66 -0
- package/dist/ui/hooks/useRunList.js.map +1 -0
- package/dist/ui/hooks/useToolList.d.ts +40 -0
- package/dist/ui/hooks/useToolList.d.ts.map +1 -0
- package/dist/ui/hooks/useToolList.js +96 -0
- package/dist/ui/hooks/useToolList.js.map +1 -0
- package/dist/ui/index.d.ts +24 -0
- package/dist/ui/index.js +24 -0
- package/dist/ui/modals/AgentActionsModal.d.ts +27 -0
- package/dist/ui/modals/AgentActionsModal.d.ts.map +1 -0
- package/dist/ui/modals/AgentActionsModal.js +262 -0
- package/dist/ui/modals/AgentActionsModal.js.map +1 -0
- package/dist/ui/modals/CreateAgentModal.d.ts +25 -0
- package/dist/ui/modals/CreateAgentModal.d.ts.map +1 -0
- package/dist/ui/modals/CreateAgentModal.js +214 -0
- package/dist/ui/modals/CreateAgentModal.js.map +1 -0
- package/dist/ui/modals/index.d.ts +3 -0
- package/dist/ui/modals/index.js +4 -0
- package/dist/ui/overlays/demo-overlays.d.ts +19 -0
- package/dist/ui/overlays/demo-overlays.d.ts.map +1 -0
- package/dist/ui/overlays/demo-overlays.js +73 -0
- package/dist/ui/overlays/demo-overlays.js.map +1 -0
- package/dist/ui/overlays/index.d.ts +2 -0
- package/dist/ui/overlays/index.js +3 -0
- package/dist/ui/renderers/agent-list.markdown.d.ts +15 -0
- package/dist/ui/renderers/agent-list.markdown.d.ts.map +1 -0
- package/dist/ui/renderers/agent-list.markdown.js +51 -0
- package/dist/ui/renderers/agent-list.markdown.js.map +1 -0
- package/dist/ui/renderers/agent-list.renderer.d.ts +11 -0
- package/dist/ui/renderers/agent-list.renderer.d.ts.map +1 -0
- package/dist/ui/renderers/agent-list.renderer.js +19 -0
- package/dist/ui/renderers/agent-list.renderer.js.map +1 -0
- package/dist/ui/renderers/dashboard.markdown.d.ts +15 -0
- package/dist/ui/renderers/dashboard.markdown.d.ts.map +1 -0
- package/dist/ui/renderers/dashboard.markdown.js +100 -0
- package/dist/ui/renderers/dashboard.markdown.js.map +1 -0
- package/dist/ui/renderers/index.d.ts +6 -0
- package/dist/ui/renderers/index.js +7 -0
- package/dist/ui/renderers/run-list.markdown.d.ts +15 -0
- package/dist/ui/renderers/run-list.markdown.d.ts.map +1 -0
- package/dist/ui/renderers/run-list.markdown.js +44 -0
- package/dist/ui/renderers/run-list.markdown.js.map +1 -0
- package/dist/ui/renderers/tool-registry.markdown.d.ts +15 -0
- package/dist/ui/renderers/tool-registry.markdown.d.ts.map +1 -0
- package/dist/ui/renderers/tool-registry.markdown.js +55 -0
- package/dist/ui/renderers/tool-registry.markdown.js.map +1 -0
- package/dist/ui/views/AgentListView.d.ts +7 -0
- package/dist/ui/views/AgentListView.d.ts.map +1 -0
- package/dist/ui/views/AgentListView.js +93 -0
- package/dist/ui/views/AgentListView.js.map +1 -0
- package/dist/ui/views/RunListView.d.ts +14 -0
- package/dist/ui/views/RunListView.d.ts.map +1 -0
- package/dist/ui/views/RunListView.js +165 -0
- package/dist/ui/views/RunListView.js.map +1 -0
- package/dist/ui/views/ToolRegistryView.d.ts +14 -0
- package/dist/ui/views/ToolRegistryView.d.ts.map +1 -0
- package/dist/ui/views/ToolRegistryView.js +97 -0
- package/dist/ui/views/ToolRegistryView.js.map +1 -0
- package/dist/ui/views/index.d.ts +4 -0
- package/dist/ui/views/index.js +5 -0
- package/package.json +46 -10
- package/src/agent/agent.presentation.ts +7 -8
- package/src/agent/agent.test-spec.ts +55 -0
- package/src/agent.capability.ts +13 -0
- package/src/agent.feature.ts +3 -2
- package/src/example.ts +3 -3
- package/src/handlers/agent.handlers.ts +572 -0
- package/src/handlers/index.ts +3 -0
- package/src/index.ts +5 -0
- package/src/run/run.presentation.ts +5 -6
- package/src/run/run.test-spec.ts +55 -0
- package/src/seeders/index.ts +29 -0
- package/src/shared/overlay-types.ts +39 -0
- package/src/tool/tool.presentation.ts +5 -6
- package/src/tool/tool.test-spec.ts +55 -0
- package/src/ui/AgentDashboard.tsx +416 -0
- package/src/ui/AgentRunList.tsx +8 -0
- package/src/ui/AgentToolRegistry.tsx +8 -0
- package/src/ui/hooks/index.ts +14 -0
- package/src/ui/hooks/useAgentList.ts +80 -0
- package/src/ui/hooks/useAgentMutations.ts +156 -0
- package/src/ui/hooks/useRunList.ts +81 -0
- package/src/ui/hooks/useToolList.ts +122 -0
- package/src/ui/index.ts +21 -0
- package/src/ui/modals/AgentActionsModal.tsx +306 -0
- package/src/ui/modals/CreateAgentModal.tsx +257 -0
- package/src/ui/modals/index.ts +2 -0
- package/src/ui/overlays/demo-overlays.ts +77 -0
- package/src/ui/overlays/index.ts +1 -0
- package/src/ui/renderers/agent-list.markdown.ts +84 -0
- package/src/ui/renderers/agent-list.renderer.tsx +27 -0
- package/src/ui/renderers/dashboard.markdown.ts +169 -0
- package/src/ui/renderers/index.ts +12 -0
- package/src/ui/renderers/run-list.markdown.ts +75 -0
- package/src/ui/renderers/tool-registry.markdown.ts +91 -0
- package/src/ui/views/AgentListView.tsx +113 -0
- package/src/ui/views/RunListView.tsx +173 -0
- package/src/ui/views/ToolRegistryView.tsx +140 -0
- package/src/ui/views/index.ts +6 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-local Agent Console handlers
|
|
3
|
+
*
|
|
4
|
+
* Database-backed handlers for agent management and runs.
|
|
5
|
+
*/
|
|
6
|
+
import type { DatabasePort } from '@contractspec/lib.runtime-sandbox';
|
|
7
|
+
import { web } from '@contractspec/lib.runtime-sandbox';
|
|
8
|
+
const { generateId } = web;
|
|
9
|
+
|
|
10
|
+
// ============ Types ============
|
|
11
|
+
|
|
12
|
+
export interface Agent {
|
|
13
|
+
id: string;
|
|
14
|
+
projectId: string;
|
|
15
|
+
organizationId: string;
|
|
16
|
+
name: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
modelProvider: string;
|
|
19
|
+
modelName: string;
|
|
20
|
+
systemPrompt?: string;
|
|
21
|
+
temperature: number;
|
|
22
|
+
maxTokens: number;
|
|
23
|
+
status: 'DRAFT' | 'ACTIVE' | 'PAUSED' | 'ARCHIVED';
|
|
24
|
+
createdAt: Date;
|
|
25
|
+
updatedAt: Date;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface Tool {
|
|
29
|
+
id: string;
|
|
30
|
+
projectId: string;
|
|
31
|
+
organizationId: string;
|
|
32
|
+
name: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
version: string;
|
|
35
|
+
category:
|
|
36
|
+
| 'RETRIEVAL'
|
|
37
|
+
| 'COMPUTATION'
|
|
38
|
+
| 'COMMUNICATION'
|
|
39
|
+
| 'INTEGRATION'
|
|
40
|
+
| 'UTILITY'
|
|
41
|
+
| 'CUSTOM';
|
|
42
|
+
status: 'ACTIVE' | 'DISABLED' | 'DEPRECATED' | 'DRAFT';
|
|
43
|
+
inputSchema?: string;
|
|
44
|
+
outputSchema?: string;
|
|
45
|
+
endpoint?: string;
|
|
46
|
+
createdAt: Date;
|
|
47
|
+
updatedAt: Date;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Run {
|
|
51
|
+
id: string;
|
|
52
|
+
projectId: string;
|
|
53
|
+
agentId: string;
|
|
54
|
+
agentName?: string;
|
|
55
|
+
status: 'QUEUED' | 'RUNNING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
|
|
56
|
+
input?: string;
|
|
57
|
+
output?: string;
|
|
58
|
+
totalTokens: number;
|
|
59
|
+
promptTokens: number;
|
|
60
|
+
completionTokens: number;
|
|
61
|
+
estimatedCostUsd: number;
|
|
62
|
+
durationMs?: number;
|
|
63
|
+
errorMessage?: string;
|
|
64
|
+
queuedAt: Date;
|
|
65
|
+
startedAt?: Date;
|
|
66
|
+
completedAt?: Date;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface RunMetrics {
|
|
70
|
+
totalRuns: number;
|
|
71
|
+
successRate: number;
|
|
72
|
+
averageDurationMs: number;
|
|
73
|
+
totalTokens: number;
|
|
74
|
+
totalCostUsd: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface ListAgentsInput {
|
|
78
|
+
projectId: string;
|
|
79
|
+
organizationId?: string;
|
|
80
|
+
status?: Agent['status'] | 'all';
|
|
81
|
+
search?: string;
|
|
82
|
+
limit?: number;
|
|
83
|
+
offset?: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface ListAgentsOutput {
|
|
87
|
+
items: Agent[];
|
|
88
|
+
total: number;
|
|
89
|
+
hasMore: boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface ListToolsInput {
|
|
93
|
+
projectId: string;
|
|
94
|
+
organizationId?: string;
|
|
95
|
+
category?: Tool['category'] | 'all';
|
|
96
|
+
status?: Tool['status'] | 'all';
|
|
97
|
+
search?: string;
|
|
98
|
+
limit?: number;
|
|
99
|
+
offset?: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface ListToolsOutput {
|
|
103
|
+
items: Tool[];
|
|
104
|
+
total: number;
|
|
105
|
+
hasMore: boolean;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface ListRunsInput {
|
|
109
|
+
projectId: string;
|
|
110
|
+
organizationId?: string;
|
|
111
|
+
agentId?: string;
|
|
112
|
+
status?: Run['status'] | 'all';
|
|
113
|
+
limit?: number;
|
|
114
|
+
offset?: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface ListRunsOutput {
|
|
118
|
+
items: Run[];
|
|
119
|
+
total: number;
|
|
120
|
+
hasMore: boolean;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface CreateAgentInput {
|
|
124
|
+
name: string;
|
|
125
|
+
description?: string;
|
|
126
|
+
modelProvider?: string;
|
|
127
|
+
modelName?: string;
|
|
128
|
+
systemPrompt?: string;
|
|
129
|
+
temperature?: number;
|
|
130
|
+
maxTokens?: number;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface UpdateAgentInput {
|
|
134
|
+
id: string;
|
|
135
|
+
name?: string;
|
|
136
|
+
description?: string;
|
|
137
|
+
status?: Agent['status'];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ============ Row Types ============
|
|
141
|
+
|
|
142
|
+
interface AgentRow extends Record<string, unknown> {
|
|
143
|
+
id: string;
|
|
144
|
+
projectId: string;
|
|
145
|
+
organizationId: string;
|
|
146
|
+
name: string;
|
|
147
|
+
description: string | null;
|
|
148
|
+
modelProvider: string;
|
|
149
|
+
modelName: string;
|
|
150
|
+
systemPrompt: string | null;
|
|
151
|
+
temperature: number;
|
|
152
|
+
maxTokens: number;
|
|
153
|
+
status: string;
|
|
154
|
+
createdAt: string;
|
|
155
|
+
updatedAt: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
interface ToolRow extends Record<string, unknown> {
|
|
159
|
+
id: string;
|
|
160
|
+
projectId: string;
|
|
161
|
+
organizationId: string;
|
|
162
|
+
name: string;
|
|
163
|
+
description: string | null;
|
|
164
|
+
version: string;
|
|
165
|
+
category: string;
|
|
166
|
+
status: string;
|
|
167
|
+
inputSchema: string | null;
|
|
168
|
+
outputSchema: string | null;
|
|
169
|
+
endpoint: string | null;
|
|
170
|
+
createdAt: string;
|
|
171
|
+
updatedAt: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
interface RunRow extends Record<string, unknown> {
|
|
175
|
+
id: string;
|
|
176
|
+
projectId: string;
|
|
177
|
+
agentId: string;
|
|
178
|
+
status: string;
|
|
179
|
+
input: string | null;
|
|
180
|
+
output: string | null;
|
|
181
|
+
totalTokens: number;
|
|
182
|
+
promptTokens: number;
|
|
183
|
+
completionTokens: number;
|
|
184
|
+
estimatedCostUsd: number;
|
|
185
|
+
durationMs: number | null;
|
|
186
|
+
errorMessage: string | null;
|
|
187
|
+
queuedAt: string;
|
|
188
|
+
startedAt: string | null;
|
|
189
|
+
completedAt: string | null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function rowToAgent(row: AgentRow): Agent {
|
|
193
|
+
return {
|
|
194
|
+
id: row.id,
|
|
195
|
+
projectId: row.projectId,
|
|
196
|
+
organizationId: row.organizationId,
|
|
197
|
+
name: row.name,
|
|
198
|
+
description: row.description ?? undefined,
|
|
199
|
+
modelProvider: row.modelProvider,
|
|
200
|
+
modelName: row.modelName,
|
|
201
|
+
systemPrompt: row.systemPrompt ?? undefined,
|
|
202
|
+
temperature: row.temperature,
|
|
203
|
+
maxTokens: row.maxTokens,
|
|
204
|
+
status: row.status as Agent['status'],
|
|
205
|
+
createdAt: new Date(row.createdAt),
|
|
206
|
+
updatedAt: new Date(row.updatedAt),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function rowToTool(row: ToolRow): Tool {
|
|
211
|
+
return {
|
|
212
|
+
id: row.id,
|
|
213
|
+
projectId: row.projectId,
|
|
214
|
+
organizationId: row.organizationId,
|
|
215
|
+
name: row.name,
|
|
216
|
+
description: row.description ?? undefined,
|
|
217
|
+
version: row.version,
|
|
218
|
+
category: row.category as Tool['category'],
|
|
219
|
+
status: row.status as Tool['status'],
|
|
220
|
+
inputSchema: row.inputSchema ?? undefined,
|
|
221
|
+
outputSchema: row.outputSchema ?? undefined,
|
|
222
|
+
endpoint: row.endpoint ?? undefined,
|
|
223
|
+
createdAt: new Date(row.createdAt),
|
|
224
|
+
updatedAt: new Date(row.updatedAt),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function rowToRun(row: RunRow, agentName?: string): Run {
|
|
229
|
+
return {
|
|
230
|
+
id: row.id,
|
|
231
|
+
projectId: row.projectId,
|
|
232
|
+
agentId: row.agentId,
|
|
233
|
+
agentName,
|
|
234
|
+
status: row.status as Run['status'],
|
|
235
|
+
input: row.input ?? undefined,
|
|
236
|
+
output: row.output ?? undefined,
|
|
237
|
+
totalTokens: row.totalTokens,
|
|
238
|
+
promptTokens: row.promptTokens,
|
|
239
|
+
completionTokens: row.completionTokens,
|
|
240
|
+
estimatedCostUsd: row.estimatedCostUsd,
|
|
241
|
+
durationMs: row.durationMs ?? undefined,
|
|
242
|
+
errorMessage: row.errorMessage ?? undefined,
|
|
243
|
+
queuedAt: new Date(row.queuedAt),
|
|
244
|
+
startedAt: row.startedAt ? new Date(row.startedAt) : undefined,
|
|
245
|
+
completedAt: row.completedAt ? new Date(row.completedAt) : undefined,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ============ Handler Factory ============
|
|
250
|
+
|
|
251
|
+
export function createAgentHandlers(db: DatabasePort) {
|
|
252
|
+
/**
|
|
253
|
+
* List agents
|
|
254
|
+
*/
|
|
255
|
+
async function listAgents(input: ListAgentsInput): Promise<ListAgentsOutput> {
|
|
256
|
+
const {
|
|
257
|
+
projectId,
|
|
258
|
+
organizationId,
|
|
259
|
+
status,
|
|
260
|
+
search,
|
|
261
|
+
limit = 20,
|
|
262
|
+
offset = 0,
|
|
263
|
+
} = input;
|
|
264
|
+
|
|
265
|
+
let whereClause = 'WHERE projectId = ?';
|
|
266
|
+
const params: (string | number)[] = [projectId];
|
|
267
|
+
|
|
268
|
+
if (organizationId) {
|
|
269
|
+
whereClause += ' AND organizationId = ?';
|
|
270
|
+
params.push(organizationId);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (status && status !== 'all') {
|
|
274
|
+
whereClause += ' AND status = ?';
|
|
275
|
+
params.push(status);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (search) {
|
|
279
|
+
whereClause += ' AND (name LIKE ? OR description LIKE ?)';
|
|
280
|
+
params.push(`%${search}%`, `%${search}%`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const countResult = (
|
|
284
|
+
await db.query(
|
|
285
|
+
`SELECT COUNT(*) as count FROM agent_definition ${whereClause}`,
|
|
286
|
+
params
|
|
287
|
+
)
|
|
288
|
+
).rows as unknown as { count: number }[];
|
|
289
|
+
const total = countResult[0]?.count ?? 0;
|
|
290
|
+
|
|
291
|
+
const rows = (
|
|
292
|
+
await db.query(
|
|
293
|
+
`SELECT * FROM agent_definition ${whereClause} ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
294
|
+
[...params, limit, offset]
|
|
295
|
+
)
|
|
296
|
+
).rows as unknown as AgentRow[];
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
items: rows.map(rowToAgent),
|
|
300
|
+
total,
|
|
301
|
+
hasMore: offset + rows.length < total,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get a single agent
|
|
307
|
+
*/
|
|
308
|
+
async function getAgent(id: string): Promise<Agent | null> {
|
|
309
|
+
const rows = (
|
|
310
|
+
await db.query(`SELECT * FROM agent_definition WHERE id = ?`, [id])
|
|
311
|
+
).rows as unknown as AgentRow[];
|
|
312
|
+
return rows[0] ? rowToAgent(rows[0]) : null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Create an agent
|
|
317
|
+
*/
|
|
318
|
+
async function createAgent(
|
|
319
|
+
input: CreateAgentInput,
|
|
320
|
+
context: { projectId: string; organizationId: string }
|
|
321
|
+
): Promise<Agent> {
|
|
322
|
+
const id = generateId('agent');
|
|
323
|
+
const now = new Date().toISOString();
|
|
324
|
+
|
|
325
|
+
await db.execute(
|
|
326
|
+
`INSERT INTO agent_definition (id, projectId, organizationId, name, description, modelProvider, modelName, systemPrompt, temperature, maxTokens, status, createdAt, updatedAt)
|
|
327
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
328
|
+
[
|
|
329
|
+
id,
|
|
330
|
+
context.projectId,
|
|
331
|
+
context.organizationId,
|
|
332
|
+
input.name,
|
|
333
|
+
input.description ?? null,
|
|
334
|
+
input.modelProvider ?? 'openai',
|
|
335
|
+
input.modelName ?? 'gpt-4',
|
|
336
|
+
input.systemPrompt ?? null,
|
|
337
|
+
input.temperature ?? 0.7,
|
|
338
|
+
input.maxTokens ?? 4096,
|
|
339
|
+
'DRAFT',
|
|
340
|
+
now,
|
|
341
|
+
now,
|
|
342
|
+
]
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
const rows = (
|
|
346
|
+
await db.query(`SELECT * FROM agent_definition WHERE id = ?`, [id])
|
|
347
|
+
).rows as unknown as AgentRow[];
|
|
348
|
+
|
|
349
|
+
const row = rows[0];
|
|
350
|
+
if (!row) {
|
|
351
|
+
throw new Error('Failed to retrieve created agent');
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return rowToAgent(row);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Update an agent
|
|
359
|
+
*/
|
|
360
|
+
async function updateAgent(input: UpdateAgentInput): Promise<Agent> {
|
|
361
|
+
const now = new Date().toISOString();
|
|
362
|
+
const updates: string[] = ['updatedAt = ?'];
|
|
363
|
+
const params: (string | null)[] = [now];
|
|
364
|
+
|
|
365
|
+
if (input.name !== undefined) {
|
|
366
|
+
updates.push('name = ?');
|
|
367
|
+
params.push(input.name);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (input.description !== undefined) {
|
|
371
|
+
updates.push('description = ?');
|
|
372
|
+
params.push(input.description);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (input.status !== undefined) {
|
|
376
|
+
updates.push('status = ?');
|
|
377
|
+
params.push(input.status);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
params.push(input.id);
|
|
381
|
+
|
|
382
|
+
await db.execute(
|
|
383
|
+
`UPDATE agent_definition SET ${updates.join(', ')} WHERE id = ?`,
|
|
384
|
+
params
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
const rows = (
|
|
388
|
+
await db.query(`SELECT * FROM agent_definition WHERE id = ?`, [input.id])
|
|
389
|
+
).rows as unknown as AgentRow[];
|
|
390
|
+
|
|
391
|
+
if (!rows[0]) {
|
|
392
|
+
throw new Error('NOT_FOUND');
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return rowToAgent(rows[0]);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* List tools
|
|
400
|
+
*/
|
|
401
|
+
async function listTools(input: ListToolsInput): Promise<ListToolsOutput> {
|
|
402
|
+
const {
|
|
403
|
+
projectId,
|
|
404
|
+
organizationId,
|
|
405
|
+
category,
|
|
406
|
+
status,
|
|
407
|
+
search,
|
|
408
|
+
limit = 50,
|
|
409
|
+
offset = 0,
|
|
410
|
+
} = input;
|
|
411
|
+
|
|
412
|
+
let whereClause = 'WHERE projectId = ?';
|
|
413
|
+
const params: (string | number)[] = [projectId];
|
|
414
|
+
|
|
415
|
+
if (organizationId) {
|
|
416
|
+
whereClause += ' AND organizationId = ?';
|
|
417
|
+
params.push(organizationId);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (category && category !== 'all') {
|
|
421
|
+
whereClause += ' AND category = ?';
|
|
422
|
+
params.push(category);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (status && status !== 'all') {
|
|
426
|
+
whereClause += ' AND status = ?';
|
|
427
|
+
params.push(status);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (search) {
|
|
431
|
+
whereClause += ' AND (name LIKE ? OR description LIKE ?)';
|
|
432
|
+
params.push(`%${search}%`, `%${search}%`);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const countResult = (
|
|
436
|
+
await db.query(
|
|
437
|
+
`SELECT COUNT(*) as count FROM agent_tool ${whereClause}`,
|
|
438
|
+
params
|
|
439
|
+
)
|
|
440
|
+
).rows as unknown as { count: number }[];
|
|
441
|
+
const total = countResult[0]?.count ?? 0;
|
|
442
|
+
|
|
443
|
+
const rows = (
|
|
444
|
+
await db.query(
|
|
445
|
+
`SELECT * FROM agent_tool ${whereClause} ORDER BY name ASC LIMIT ? OFFSET ?`,
|
|
446
|
+
[...params, limit, offset]
|
|
447
|
+
)
|
|
448
|
+
).rows as unknown as ToolRow[];
|
|
449
|
+
|
|
450
|
+
return {
|
|
451
|
+
items: rows.map(rowToTool),
|
|
452
|
+
total,
|
|
453
|
+
hasMore: offset + rows.length < total,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* List runs
|
|
459
|
+
*/
|
|
460
|
+
async function listRuns(input: ListRunsInput): Promise<ListRunsOutput> {
|
|
461
|
+
const { projectId, agentId, status, limit = 20, offset = 0 } = input;
|
|
462
|
+
|
|
463
|
+
let whereClause = 'WHERE r.projectId = ?';
|
|
464
|
+
const params: (string | number)[] = [projectId];
|
|
465
|
+
|
|
466
|
+
if (agentId) {
|
|
467
|
+
whereClause += ' AND r.agentId = ?';
|
|
468
|
+
params.push(agentId);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (status && status !== 'all') {
|
|
472
|
+
whereClause += ' AND r.status = ?';
|
|
473
|
+
params.push(status);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const countResult = (
|
|
477
|
+
await db.query(
|
|
478
|
+
`SELECT COUNT(*) as count FROM agent_run r ${whereClause}`,
|
|
479
|
+
params
|
|
480
|
+
)
|
|
481
|
+
).rows as unknown as { count: number }[];
|
|
482
|
+
const total = countResult[0]?.count ?? 0;
|
|
483
|
+
|
|
484
|
+
const rows = (
|
|
485
|
+
await db.query(
|
|
486
|
+
`SELECT r.*, a.name as agentName
|
|
487
|
+
FROM agent_run r
|
|
488
|
+
LEFT JOIN agent_definition a ON r.agentId = a.id
|
|
489
|
+
${whereClause}
|
|
490
|
+
ORDER BY r.queuedAt DESC LIMIT ? OFFSET ?`,
|
|
491
|
+
[...params, limit, offset]
|
|
492
|
+
)
|
|
493
|
+
).rows as unknown as (RunRow & { agentName: string })[];
|
|
494
|
+
|
|
495
|
+
return {
|
|
496
|
+
items: rows.map((r) => rowToRun(r, r.agentName)),
|
|
497
|
+
total,
|
|
498
|
+
hasMore: offset + rows.length < total,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Get run metrics
|
|
504
|
+
*/
|
|
505
|
+
async function getRunMetrics(input: {
|
|
506
|
+
projectId: string;
|
|
507
|
+
agentId?: string;
|
|
508
|
+
startDate?: Date;
|
|
509
|
+
endDate?: Date;
|
|
510
|
+
}): Promise<RunMetrics> {
|
|
511
|
+
let whereClause = 'WHERE projectId = ?';
|
|
512
|
+
const params: (string | number)[] = [input.projectId];
|
|
513
|
+
|
|
514
|
+
if (input.agentId) {
|
|
515
|
+
whereClause += ' AND agentId = ?';
|
|
516
|
+
params.push(input.agentId);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (input.startDate) {
|
|
520
|
+
whereClause += ' AND queuedAt >= ?';
|
|
521
|
+
params.push(input.startDate.toISOString());
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (input.endDate) {
|
|
525
|
+
whereClause += ' AND queuedAt <= ?';
|
|
526
|
+
params.push(input.endDate.toISOString());
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const result = (
|
|
530
|
+
await db.query(
|
|
531
|
+
`SELECT
|
|
532
|
+
COUNT(*) as totalRuns,
|
|
533
|
+
SUM(CASE WHEN status = 'COMPLETED' THEN 1 ELSE 0 END) as completedRuns,
|
|
534
|
+
AVG(CASE WHEN status = 'COMPLETED' THEN durationMs ELSE NULL END) as avgDuration,
|
|
535
|
+
COALESCE(SUM(totalTokens), 0) as totalTokens,
|
|
536
|
+
COALESCE(SUM(estimatedCostUsd), 0) as totalCost
|
|
537
|
+
FROM agent_run ${whereClause}`,
|
|
538
|
+
params
|
|
539
|
+
)
|
|
540
|
+
).rows as unknown as {
|
|
541
|
+
totalRuns: number;
|
|
542
|
+
completedRuns: number;
|
|
543
|
+
avgDuration: number | null;
|
|
544
|
+
totalTokens: number;
|
|
545
|
+
totalCost: number;
|
|
546
|
+
}[];
|
|
547
|
+
|
|
548
|
+
const data = result[0];
|
|
549
|
+
const totalRuns = data?.totalRuns ?? 0;
|
|
550
|
+
const completedRuns = data?.completedRuns ?? 0;
|
|
551
|
+
|
|
552
|
+
return {
|
|
553
|
+
totalRuns,
|
|
554
|
+
successRate: totalRuns > 0 ? completedRuns / totalRuns : 0,
|
|
555
|
+
averageDurationMs: data?.avgDuration ?? 0,
|
|
556
|
+
totalTokens: data?.totalTokens ?? 0,
|
|
557
|
+
totalCostUsd: data?.totalCost ?? 0,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return {
|
|
562
|
+
listAgents,
|
|
563
|
+
getAgent,
|
|
564
|
+
createAgent,
|
|
565
|
+
updateAgent,
|
|
566
|
+
listTools,
|
|
567
|
+
listRuns,
|
|
568
|
+
getRunMetrics,
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export type AgentHandlers = ReturnType<typeof createAgentHandlers>;
|
package/src/handlers/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -20,6 +20,11 @@ export * from './agent';
|
|
|
20
20
|
export * from './run';
|
|
21
21
|
export * from './tool';
|
|
22
22
|
export * from './shared';
|
|
23
|
+
export * from './ui';
|
|
24
|
+
export {
|
|
25
|
+
createAgentHandlers,
|
|
26
|
+
type AgentHandlers,
|
|
27
|
+
} from './handlers/agent.handlers';
|
|
23
28
|
|
|
24
29
|
// Feature spec export
|
|
25
30
|
export * from './agent.feature';
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { StabilityEnum } from '@contractspec/lib.contracts';
|
|
1
|
+
import { StabilityEnum, definePresentation } from '@contractspec/lib.contracts';
|
|
3
2
|
import { RunSummaryModel } from './run.schema';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Presentation for displaying a list of agent runs.
|
|
7
6
|
*/
|
|
8
|
-
export const RunListPresentation
|
|
7
|
+
export const RunListPresentation = definePresentation({
|
|
9
8
|
meta: {
|
|
10
9
|
key: 'agent-console.run.list',
|
|
11
10
|
version: '1.0.0',
|
|
@@ -27,12 +26,12 @@ export const RunListPresentation: PresentationSpec = {
|
|
|
27
26
|
},
|
|
28
27
|
targets: ['react', 'markdown', 'application/json'],
|
|
29
28
|
policy: { flags: ['agent-console.enabled'] },
|
|
30
|
-
};
|
|
29
|
+
});
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
32
|
* Presentation for run detail view.
|
|
34
33
|
*/
|
|
35
|
-
export const RunDetailPresentation
|
|
34
|
+
export const RunDetailPresentation = definePresentation({
|
|
36
35
|
meta: {
|
|
37
36
|
key: 'agent-console.run.detail',
|
|
38
37
|
version: '1.0.0',
|
|
@@ -52,4 +51,4 @@ export const RunDetailPresentation: PresentationSpec = {
|
|
|
52
51
|
},
|
|
53
52
|
targets: ['react', 'markdown'],
|
|
54
53
|
policy: { flags: ['agent-console.enabled'] },
|
|
55
|
-
};
|
|
54
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { defineTestSpec } from '@contractspec/lib.contracts';
|
|
2
|
+
|
|
3
|
+
export const runListTest = defineTestSpec({
|
|
4
|
+
meta: {
|
|
5
|
+
key: 'test.agent.run.list',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
owners: ['@agent-console-team'],
|
|
8
|
+
description: 'Test for listing runs',
|
|
9
|
+
stability: 'stable',
|
|
10
|
+
tags: ['test'],
|
|
11
|
+
},
|
|
12
|
+
target: {
|
|
13
|
+
type: 'operation',
|
|
14
|
+
operation: { key: 'agent.run.list', version: '1.0.0' },
|
|
15
|
+
},
|
|
16
|
+
scenarios: [
|
|
17
|
+
{
|
|
18
|
+
key: 'success',
|
|
19
|
+
when: { operation: { key: 'agent.run.list' } },
|
|
20
|
+
then: [{ type: 'expectOutput', match: {} }],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'error',
|
|
24
|
+
when: { operation: { key: 'agent.run.list' } },
|
|
25
|
+
then: [{ type: 'expectError' }],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export const runGetTest = defineTestSpec({
|
|
31
|
+
meta: {
|
|
32
|
+
key: 'test.agent.run.get',
|
|
33
|
+
version: '1.0.0',
|
|
34
|
+
owners: ['@agent-console-team'],
|
|
35
|
+
description: 'Test for getting run',
|
|
36
|
+
stability: 'stable',
|
|
37
|
+
tags: ['test'],
|
|
38
|
+
},
|
|
39
|
+
target: {
|
|
40
|
+
type: 'operation',
|
|
41
|
+
operation: { key: 'agent.run.get', version: '1.0.0' },
|
|
42
|
+
},
|
|
43
|
+
scenarios: [
|
|
44
|
+
{
|
|
45
|
+
key: 'success',
|
|
46
|
+
when: { operation: { key: 'agent.run.get' } },
|
|
47
|
+
then: [{ type: 'expectOutput', match: {} }],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
key: 'error',
|
|
51
|
+
when: { operation: { key: 'agent.run.get' } },
|
|
52
|
+
then: [{ type: 'expectError' }],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { DatabasePort } from '@contractspec/lib.runtime-sandbox';
|
|
2
|
+
|
|
3
|
+
export async function seedAgentConsole(params: {
|
|
4
|
+
projectId: string;
|
|
5
|
+
db: DatabasePort;
|
|
6
|
+
}) {
|
|
7
|
+
const { projectId, db } = params;
|
|
8
|
+
|
|
9
|
+
const existing = await db.query(
|
|
10
|
+
`SELECT COUNT(*) as count FROM agent_definition WHERE "projectId" = $1`,
|
|
11
|
+
[projectId]
|
|
12
|
+
);
|
|
13
|
+
if ((existing.rows[0]?.count as number) > 0) return;
|
|
14
|
+
|
|
15
|
+
await db.execute(
|
|
16
|
+
`INSERT INTO agent_definition (id, "projectId", "organizationId", name, description, "modelProvider", "modelName", status)
|
|
17
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
|
|
18
|
+
[
|
|
19
|
+
'agent_1',
|
|
20
|
+
projectId,
|
|
21
|
+
'org_demo',
|
|
22
|
+
'Demo Agent',
|
|
23
|
+
'A demo AI agent',
|
|
24
|
+
'openai',
|
|
25
|
+
'gpt-4',
|
|
26
|
+
'ACTIVE',
|
|
27
|
+
]
|
|
28
|
+
);
|
|
29
|
+
}
|