@contractspec/example.agent-console 1.46.1 → 1.47.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 +37 -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.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,257 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CreateAgentModal - Form for creating a new AI agent
|
|
5
|
+
*
|
|
6
|
+
* Wires to CreateAgentCommand via useAgentMutations hook.
|
|
7
|
+
*/
|
|
8
|
+
import { useState } from 'react';
|
|
9
|
+
import { Button, Input } from '@contractspec/lib.design-system';
|
|
10
|
+
|
|
11
|
+
// Local type definition for modal props
|
|
12
|
+
export interface CreateAgentInput {
|
|
13
|
+
name: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
modelProvider: string;
|
|
16
|
+
modelName: string;
|
|
17
|
+
systemPrompt?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface CreateAgentModalProps {
|
|
21
|
+
isOpen: boolean;
|
|
22
|
+
onClose: () => void;
|
|
23
|
+
onSubmit: (input: CreateAgentInput) => Promise<void>;
|
|
24
|
+
isLoading?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const MODEL_PROVIDERS = [
|
|
28
|
+
{
|
|
29
|
+
value: 'openai',
|
|
30
|
+
label: 'OpenAI',
|
|
31
|
+
models: ['gpt-4o', 'gpt-4-turbo', 'gpt-3.5-turbo'],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: 'anthropic',
|
|
35
|
+
label: 'Anthropic',
|
|
36
|
+
models: ['claude-3-opus', 'claude-3-sonnet', 'claude-3-haiku'],
|
|
37
|
+
},
|
|
38
|
+
{ value: 'google', label: 'Google', models: ['gemini-pro', 'gemini-ultra'] },
|
|
39
|
+
{
|
|
40
|
+
value: 'mistral',
|
|
41
|
+
label: 'Mistral',
|
|
42
|
+
models: ['mistral-large', 'mistral-medium', 'mistral-small'],
|
|
43
|
+
},
|
|
44
|
+
] as const;
|
|
45
|
+
|
|
46
|
+
type ModelProvider = (typeof MODEL_PROVIDERS)[number]['value'];
|
|
47
|
+
|
|
48
|
+
export function CreateAgentModal({
|
|
49
|
+
isOpen,
|
|
50
|
+
onClose,
|
|
51
|
+
onSubmit,
|
|
52
|
+
isLoading = false,
|
|
53
|
+
}: CreateAgentModalProps) {
|
|
54
|
+
const [name, setName] = useState('');
|
|
55
|
+
const [description, setDescription] = useState('');
|
|
56
|
+
const [modelProvider, setModelProvider] = useState<ModelProvider>('openai');
|
|
57
|
+
const [modelName, setModelName] = useState('gpt-4o');
|
|
58
|
+
const [systemPrompt, setSystemPrompt] = useState('');
|
|
59
|
+
const [error, setError] = useState<string | null>(null);
|
|
60
|
+
|
|
61
|
+
const selectedProvider = MODEL_PROVIDERS.find(
|
|
62
|
+
(p) => p.value === modelProvider
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
setError(null);
|
|
68
|
+
|
|
69
|
+
// Validation
|
|
70
|
+
if (!name.trim()) {
|
|
71
|
+
setError('Agent name is required');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await onSubmit({
|
|
77
|
+
name: name.trim(),
|
|
78
|
+
description: description.trim() || undefined,
|
|
79
|
+
modelProvider,
|
|
80
|
+
modelName,
|
|
81
|
+
systemPrompt: systemPrompt.trim() || undefined,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Reset form
|
|
85
|
+
setName('');
|
|
86
|
+
setDescription('');
|
|
87
|
+
setModelProvider('openai');
|
|
88
|
+
setModelName('gpt-4o');
|
|
89
|
+
setSystemPrompt('');
|
|
90
|
+
onClose();
|
|
91
|
+
} catch (err) {
|
|
92
|
+
setError(err instanceof Error ? err.message : 'Failed to create agent');
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Update model when provider changes
|
|
97
|
+
const handleProviderChange = (provider: ModelProvider) => {
|
|
98
|
+
setModelProvider(provider);
|
|
99
|
+
const providerConfig = MODEL_PROVIDERS.find((p) => p.value === provider);
|
|
100
|
+
if (providerConfig) {
|
|
101
|
+
setModelName(providerConfig.models[0]);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
if (!isOpen) return null;
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
|
109
|
+
{/* Backdrop */}
|
|
110
|
+
<div
|
|
111
|
+
className="bg-background/80 absolute inset-0 backdrop-blur-sm"
|
|
112
|
+
onClick={onClose}
|
|
113
|
+
role="button"
|
|
114
|
+
tabIndex={0}
|
|
115
|
+
onKeyDown={(e) => {
|
|
116
|
+
if (e.key === 'Enter' || e.key === ' ') onClose();
|
|
117
|
+
}}
|
|
118
|
+
aria-label="Close modal"
|
|
119
|
+
/>
|
|
120
|
+
|
|
121
|
+
{/* Modal */}
|
|
122
|
+
<div 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">
|
|
123
|
+
<h2 className="mb-4 text-xl font-semibold">Create New Agent</h2>
|
|
124
|
+
|
|
125
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
126
|
+
{/* Agent Name */}
|
|
127
|
+
<div>
|
|
128
|
+
<label
|
|
129
|
+
htmlFor="agent-name"
|
|
130
|
+
className="text-muted-foreground mb-1 block text-sm font-medium"
|
|
131
|
+
>
|
|
132
|
+
Agent Name *
|
|
133
|
+
</label>
|
|
134
|
+
<Input
|
|
135
|
+
id="agent-name"
|
|
136
|
+
value={name}
|
|
137
|
+
onChange={(e) => setName(e.target.value)}
|
|
138
|
+
placeholder="e.g., Customer Support Bot"
|
|
139
|
+
disabled={isLoading}
|
|
140
|
+
/>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
{/* Description */}
|
|
144
|
+
<div>
|
|
145
|
+
<label
|
|
146
|
+
htmlFor="agent-description"
|
|
147
|
+
className="text-muted-foreground mb-1 block text-sm font-medium"
|
|
148
|
+
>
|
|
149
|
+
Description
|
|
150
|
+
</label>
|
|
151
|
+
<textarea
|
|
152
|
+
id="agent-description"
|
|
153
|
+
value={description}
|
|
154
|
+
onChange={(e) => setDescription(e.target.value)}
|
|
155
|
+
placeholder="Describe what this agent does..."
|
|
156
|
+
rows={2}
|
|
157
|
+
disabled={isLoading}
|
|
158
|
+
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"
|
|
159
|
+
/>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
{/* Model Provider & Model */}
|
|
163
|
+
<div className="flex gap-3">
|
|
164
|
+
<div className="flex-1">
|
|
165
|
+
<label
|
|
166
|
+
htmlFor="model-provider"
|
|
167
|
+
className="text-muted-foreground mb-1 block text-sm font-medium"
|
|
168
|
+
>
|
|
169
|
+
Provider *
|
|
170
|
+
</label>
|
|
171
|
+
<select
|
|
172
|
+
id="model-provider"
|
|
173
|
+
value={modelProvider}
|
|
174
|
+
onChange={(e) =>
|
|
175
|
+
handleProviderChange(e.target.value as ModelProvider)
|
|
176
|
+
}
|
|
177
|
+
disabled={isLoading}
|
|
178
|
+
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"
|
|
179
|
+
>
|
|
180
|
+
{MODEL_PROVIDERS.map((p) => (
|
|
181
|
+
<option key={p.value} value={p.value}>
|
|
182
|
+
{p.label}
|
|
183
|
+
</option>
|
|
184
|
+
))}
|
|
185
|
+
</select>
|
|
186
|
+
</div>
|
|
187
|
+
<div className="flex-1">
|
|
188
|
+
<label
|
|
189
|
+
htmlFor="model-name"
|
|
190
|
+
className="text-muted-foreground mb-1 block text-sm font-medium"
|
|
191
|
+
>
|
|
192
|
+
Model *
|
|
193
|
+
</label>
|
|
194
|
+
<select
|
|
195
|
+
id="model-name"
|
|
196
|
+
value={modelName}
|
|
197
|
+
onChange={(e) => setModelName(e.target.value)}
|
|
198
|
+
disabled={isLoading}
|
|
199
|
+
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"
|
|
200
|
+
>
|
|
201
|
+
{selectedProvider?.models.map((m) => (
|
|
202
|
+
<option key={m} value={m}>
|
|
203
|
+
{m}
|
|
204
|
+
</option>
|
|
205
|
+
))}
|
|
206
|
+
</select>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
{/* System Prompt */}
|
|
211
|
+
<div>
|
|
212
|
+
<label
|
|
213
|
+
htmlFor="system-prompt"
|
|
214
|
+
className="text-muted-foreground mb-1 block text-sm font-medium"
|
|
215
|
+
>
|
|
216
|
+
System Prompt
|
|
217
|
+
</label>
|
|
218
|
+
<textarea
|
|
219
|
+
id="system-prompt"
|
|
220
|
+
value={systemPrompt}
|
|
221
|
+
onChange={(e) => setSystemPrompt(e.target.value)}
|
|
222
|
+
placeholder="You are a helpful assistant that..."
|
|
223
|
+
rows={4}
|
|
224
|
+
disabled={isLoading}
|
|
225
|
+
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"
|
|
226
|
+
/>
|
|
227
|
+
<p className="text-muted-foreground mt-1 text-xs">
|
|
228
|
+
Instructions that define the agent's behavior
|
|
229
|
+
</p>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
{/* Error Message */}
|
|
233
|
+
{error && (
|
|
234
|
+
<div className="bg-destructive/10 text-destructive rounded-md p-3 text-sm">
|
|
235
|
+
{error}
|
|
236
|
+
</div>
|
|
237
|
+
)}
|
|
238
|
+
|
|
239
|
+
{/* Actions */}
|
|
240
|
+
<div className="flex justify-end gap-3 pt-2">
|
|
241
|
+
<Button
|
|
242
|
+
type="button"
|
|
243
|
+
variant="ghost"
|
|
244
|
+
onPress={onClose}
|
|
245
|
+
disabled={isLoading}
|
|
246
|
+
>
|
|
247
|
+
Cancel
|
|
248
|
+
</Button>
|
|
249
|
+
<Button type="submit" disabled={isLoading}>
|
|
250
|
+
{isLoading ? 'Creating...' : 'Create Agent'}
|
|
251
|
+
</Button>
|
|
252
|
+
</div>
|
|
253
|
+
</form>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo Overlay Definitions for Agent Console
|
|
3
|
+
*
|
|
4
|
+
* These overlays customize the presentation for different contexts
|
|
5
|
+
* (e.g., demo users, different roles).
|
|
6
|
+
*/
|
|
7
|
+
import type { OverlayDefinition } from '../../shared/overlay-types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Demo user overlay - hides advanced configuration options
|
|
11
|
+
*/
|
|
12
|
+
export const agentConsoleDemoOverlay: OverlayDefinition = {
|
|
13
|
+
overlayId: 'agent-console.demo-user',
|
|
14
|
+
version: '1.0.0',
|
|
15
|
+
description: 'Simplifies agent console for demo users',
|
|
16
|
+
appliesTo: {
|
|
17
|
+
feature: 'agent-console',
|
|
18
|
+
role: 'demo',
|
|
19
|
+
},
|
|
20
|
+
modifications: [
|
|
21
|
+
{
|
|
22
|
+
type: 'hideField',
|
|
23
|
+
field: 'modelConfig',
|
|
24
|
+
reason: 'Advanced config not relevant for demo',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: 'hideField',
|
|
28
|
+
field: 'webhookConfig',
|
|
29
|
+
reason: 'Integration not available in demo',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: 'renameLabel',
|
|
33
|
+
field: 'systemPrompt',
|
|
34
|
+
newLabel: 'Agent Instructions',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'addBadge',
|
|
38
|
+
position: 'header',
|
|
39
|
+
label: 'Demo Mode',
|
|
40
|
+
variant: 'warning',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Read-only overlay - for viewing without edit permissions
|
|
47
|
+
*/
|
|
48
|
+
export const agentConsoleReadOnlyOverlay: OverlayDefinition = {
|
|
49
|
+
overlayId: 'agent-console.read-only',
|
|
50
|
+
version: '1.0.0',
|
|
51
|
+
description: 'Read-only view for non-admin users',
|
|
52
|
+
appliesTo: {
|
|
53
|
+
feature: 'agent-console',
|
|
54
|
+
role: 'viewer',
|
|
55
|
+
},
|
|
56
|
+
modifications: [
|
|
57
|
+
{
|
|
58
|
+
type: 'hideField',
|
|
59
|
+
field: 'deleteButton',
|
|
60
|
+
reason: 'No delete permission',
|
|
61
|
+
},
|
|
62
|
+
{ type: 'hideField', field: 'editButton', reason: 'No edit permission' },
|
|
63
|
+
{
|
|
64
|
+
type: 'hideField',
|
|
65
|
+
field: 'createButton',
|
|
66
|
+
reason: 'No create permission',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* All overlays for agent-console
|
|
73
|
+
*/
|
|
74
|
+
export const agentConsoleOverlays: OverlayDefinition[] = [
|
|
75
|
+
agentConsoleDemoOverlay,
|
|
76
|
+
agentConsoleReadOnlyOverlay,
|
|
77
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './demo-overlays';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown Renderer for Agent List Presentation
|
|
3
|
+
*
|
|
4
|
+
* Uses handlers from the agent-console example package.
|
|
5
|
+
*/
|
|
6
|
+
import type {
|
|
7
|
+
PresentationRenderer,
|
|
8
|
+
PresentationSpec,
|
|
9
|
+
} from '@contractspec/lib.contracts';
|
|
10
|
+
import {
|
|
11
|
+
type AgentSummary,
|
|
12
|
+
mockListAgentsHandler,
|
|
13
|
+
} from '@contractspec/example.agent-console/handlers';
|
|
14
|
+
|
|
15
|
+
type Agent = AgentSummary;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Markdown renderer for agent-console.agent.list presentation
|
|
19
|
+
* Only handles AgentListView component
|
|
20
|
+
*/
|
|
21
|
+
export const agentListMarkdownRenderer: PresentationRenderer<{
|
|
22
|
+
mimeType: string;
|
|
23
|
+
body: string;
|
|
24
|
+
}> = {
|
|
25
|
+
target: 'markdown',
|
|
26
|
+
render: async (desc: PresentationSpec) => {
|
|
27
|
+
// Only handle AgentListView
|
|
28
|
+
if (
|
|
29
|
+
desc.source.type !== 'component' ||
|
|
30
|
+
desc.source.componentKey !== 'AgentListView'
|
|
31
|
+
) {
|
|
32
|
+
throw new Error('agentListMarkdownRenderer: not AgentListView');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Fetch data using mock handler
|
|
36
|
+
const data = await mockListAgentsHandler({
|
|
37
|
+
organizationId: 'demo-org',
|
|
38
|
+
limit: 50,
|
|
39
|
+
offset: 0,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Generate markdown
|
|
43
|
+
const lines: string[] = [
|
|
44
|
+
`# ${desc.meta.description ?? 'Agent List'}`,
|
|
45
|
+
'',
|
|
46
|
+
`> ${desc.meta.key} v${desc.meta.version}`,
|
|
47
|
+
'',
|
|
48
|
+
`**Total Agents:** ${data.total}`,
|
|
49
|
+
'',
|
|
50
|
+
'## Agents',
|
|
51
|
+
'',
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
// Group by status
|
|
55
|
+
const byStatus: Record<string, Agent[]> = {};
|
|
56
|
+
for (const agent of data.items) {
|
|
57
|
+
const status = agent.status;
|
|
58
|
+
if (byStatus[status]) {
|
|
59
|
+
byStatus[status].push(agent);
|
|
60
|
+
} else {
|
|
61
|
+
byStatus[status] = [agent];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const [status, agents] of Object.entries(byStatus)) {
|
|
66
|
+
lines.push(`### ${status} (${agents.length})`);
|
|
67
|
+
lines.push('');
|
|
68
|
+
for (const agent of agents) {
|
|
69
|
+
lines.push(
|
|
70
|
+
`- **${agent.name}** (${agent.modelProvider}/${agent.modelName})`
|
|
71
|
+
);
|
|
72
|
+
if (agent.description) {
|
|
73
|
+
lines.push(` > ${agent.description}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
lines.push('');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
mimeType: 'text/markdown',
|
|
81
|
+
body: lines.join('\n'),
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Renderer for Agent List Presentation
|
|
3
|
+
*/
|
|
4
|
+
import type {
|
|
5
|
+
PresentationRenderer,
|
|
6
|
+
PresentationSpec,
|
|
7
|
+
} from '@contractspec/lib.contracts';
|
|
8
|
+
import { AgentListView } from '../views/AgentListView';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* React renderer for agent-console.agent.list presentation
|
|
12
|
+
*/
|
|
13
|
+
export const agentListReactRenderer: PresentationRenderer<React.ReactElement> =
|
|
14
|
+
{
|
|
15
|
+
target: 'react',
|
|
16
|
+
render: async (desc: PresentationSpec) => {
|
|
17
|
+
if (desc.source.type !== 'component') {
|
|
18
|
+
throw new Error('AgentListRenderer: expected component source');
|
|
19
|
+
}
|
|
20
|
+
if (desc.source.componentKey !== 'AgentListView') {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`AgentListRenderer: unknown component ${desc.source.componentKey}`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return <AgentListView />;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown Renderer for Agent Console Dashboard
|
|
3
|
+
*
|
|
4
|
+
* Provides a comprehensive overview of agents, runs, and tools.
|
|
5
|
+
*/
|
|
6
|
+
import type {
|
|
7
|
+
PresentationSpec,
|
|
8
|
+
PresentationRenderer,
|
|
9
|
+
} from '@contractspec/lib.contracts';
|
|
10
|
+
import {
|
|
11
|
+
mockListAgentsHandler,
|
|
12
|
+
mockListRunsHandler,
|
|
13
|
+
mockListToolsHandler,
|
|
14
|
+
} from '@contractspec/example.agent-console/handlers';
|
|
15
|
+
|
|
16
|
+
function formatDuration(ms: number): string {
|
|
17
|
+
if (ms < 1000) return `${ms}ms`;
|
|
18
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
|
|
19
|
+
return `${(ms / 60000).toFixed(1)}m`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Markdown renderer for agent-console.dashboard presentation
|
|
24
|
+
* Only handles AgentConsoleDashboard component
|
|
25
|
+
*/
|
|
26
|
+
export const agentDashboardMarkdownRenderer: PresentationRenderer<{
|
|
27
|
+
mimeType: string;
|
|
28
|
+
body: string;
|
|
29
|
+
}> = {
|
|
30
|
+
target: 'markdown',
|
|
31
|
+
render: async (desc: PresentationSpec) => {
|
|
32
|
+
// Only handle AgentConsoleDashboard
|
|
33
|
+
if (
|
|
34
|
+
desc.source.type !== 'component' ||
|
|
35
|
+
desc.source.componentKey !== 'AgentConsoleDashboard'
|
|
36
|
+
) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
'agentDashboardMarkdownRenderer: not AgentConsoleDashboard'
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Fetch all data in parallel
|
|
43
|
+
const [agentsData, runsData, toolsData] = await Promise.all([
|
|
44
|
+
mockListAgentsHandler({
|
|
45
|
+
organizationId: 'demo-org',
|
|
46
|
+
limit: 100,
|
|
47
|
+
}),
|
|
48
|
+
mockListRunsHandler({
|
|
49
|
+
limit: 100,
|
|
50
|
+
}),
|
|
51
|
+
mockListToolsHandler({
|
|
52
|
+
organizationId: 'demo-org',
|
|
53
|
+
limit: 100,
|
|
54
|
+
}),
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
// Calculate stats
|
|
58
|
+
const activeAgents = agentsData.items.filter(
|
|
59
|
+
(a) => a.status === 'ACTIVE'
|
|
60
|
+
).length;
|
|
61
|
+
const completedRuns = runsData.items.filter(
|
|
62
|
+
(r) => r.status === 'COMPLETED'
|
|
63
|
+
).length;
|
|
64
|
+
const failedRuns = runsData.items.filter(
|
|
65
|
+
(r) => r.status === 'FAILED'
|
|
66
|
+
).length;
|
|
67
|
+
const totalTokens = runsData.items.reduce(
|
|
68
|
+
(sum, r) => sum + (r.totalTokens ?? 0),
|
|
69
|
+
0
|
|
70
|
+
);
|
|
71
|
+
const totalCost = runsData.items.reduce(
|
|
72
|
+
(sum, r) => sum + (r.estimatedCostUsd ?? 0),
|
|
73
|
+
0
|
|
74
|
+
);
|
|
75
|
+
const activeTools = toolsData.items.filter(
|
|
76
|
+
(t) => t.status === 'ACTIVE'
|
|
77
|
+
).length;
|
|
78
|
+
|
|
79
|
+
// Build dashboard markdown
|
|
80
|
+
const lines: string[] = [
|
|
81
|
+
'# Agent Console Dashboard',
|
|
82
|
+
'',
|
|
83
|
+
'> AI agent operations overview',
|
|
84
|
+
'',
|
|
85
|
+
'## Summary',
|
|
86
|
+
'',
|
|
87
|
+
'| Metric | Value |',
|
|
88
|
+
'|--------|-------|',
|
|
89
|
+
`| Total Agents | ${agentsData.total} |`,
|
|
90
|
+
`| Active Agents | ${activeAgents} |`,
|
|
91
|
+
`| Total Runs | ${runsData.total} |`,
|
|
92
|
+
`| Completed Runs | ${completedRuns} |`,
|
|
93
|
+
`| Failed Runs | ${failedRuns} |`,
|
|
94
|
+
`| Total Tokens | ${totalTokens.toLocaleString()} |`,
|
|
95
|
+
`| Total Cost | $${totalCost.toFixed(4)} |`,
|
|
96
|
+
`| Total Tools | ${toolsData.total} |`,
|
|
97
|
+
`| Active Tools | ${activeTools} |`,
|
|
98
|
+
'',
|
|
99
|
+
'## Agents',
|
|
100
|
+
'',
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
// Agent list
|
|
104
|
+
if (agentsData.items.length === 0) {
|
|
105
|
+
lines.push('_No agents configured._');
|
|
106
|
+
} else {
|
|
107
|
+
lines.push('| Agent | Model | Status | Description |');
|
|
108
|
+
lines.push('|-------|-------|--------|-------------|');
|
|
109
|
+
for (const agent of agentsData.items.slice(0, 5)) {
|
|
110
|
+
lines.push(
|
|
111
|
+
`| ${agent.name} | ${agent.modelProvider}/${agent.modelName} | ${agent.status} | ${agent.description ?? '-'} |`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
if (agentsData.items.length > 5) {
|
|
115
|
+
lines.push(`| ... | ... | ... | _${agentsData.total - 5} more_ |`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
lines.push('');
|
|
120
|
+
lines.push('## Recent Runs');
|
|
121
|
+
lines.push('');
|
|
122
|
+
|
|
123
|
+
// Recent runs
|
|
124
|
+
if (runsData.items.length === 0) {
|
|
125
|
+
lines.push('_No runs yet._');
|
|
126
|
+
} else {
|
|
127
|
+
lines.push('| Run ID | Agent | Status | Duration | Tokens | Cost |');
|
|
128
|
+
lines.push('|--------|-------|--------|----------|--------|------|');
|
|
129
|
+
for (const run of runsData.items.slice(0, 5)) {
|
|
130
|
+
lines.push(
|
|
131
|
+
`| ${run.id.slice(-8)} | ${run.agentName} | ${run.status} | ${run.durationMs ? formatDuration(run.durationMs) : '-'} | ${run.totalTokens ?? 0} | $${(run.estimatedCostUsd ?? 0).toFixed(4)} |`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (runsData.items.length > 5) {
|
|
135
|
+
lines.push(
|
|
136
|
+
`| ... | ... | ... | ... | ... | _${runsData.total - 5} more_ |`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
lines.push('');
|
|
142
|
+
lines.push('## Tools');
|
|
143
|
+
lines.push('');
|
|
144
|
+
|
|
145
|
+
// Tool categories
|
|
146
|
+
const toolsByCategory: Record<string, typeof toolsData.items> = {};
|
|
147
|
+
for (const tool of toolsData.items) {
|
|
148
|
+
const cat = tool.category;
|
|
149
|
+
if (!toolsByCategory[cat]) toolsByCategory[cat] = [];
|
|
150
|
+
toolsByCategory[cat].push(tool);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (Object.keys(toolsByCategory).length === 0) {
|
|
154
|
+
lines.push('_No tools registered._');
|
|
155
|
+
} else {
|
|
156
|
+
lines.push('| Category | Tools | Active |');
|
|
157
|
+
lines.push('|----------|-------|--------|');
|
|
158
|
+
for (const [category, tools] of Object.entries(toolsByCategory).sort()) {
|
|
159
|
+
const active = tools.filter((t) => t.status === 'ACTIVE').length;
|
|
160
|
+
lines.push(`| ${category} | ${tools.length} | ${active} |`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
mimeType: 'text/markdown',
|
|
166
|
+
body: lines.join('\n'),
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renderers for agent-console presentations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// React renderers
|
|
6
|
+
export { agentListReactRenderer } from './agent-list.renderer';
|
|
7
|
+
|
|
8
|
+
// Markdown renderers
|
|
9
|
+
export { agentListMarkdownRenderer } from './agent-list.markdown';
|
|
10
|
+
export { runListMarkdownRenderer } from './run-list.markdown';
|
|
11
|
+
export { toolRegistryMarkdownRenderer } from './tool-registry.markdown';
|
|
12
|
+
export { agentDashboardMarkdownRenderer } from './dashboard.markdown';
|