@agentuity/workbench 0.0.105 → 0.0.107
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/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +15 -13
- package/dist/components/App.js.map +1 -1
- package/dist/components/ai-elements/actions.d.ts +1 -1
- package/dist/components/ai-elements/actions.d.ts.map +1 -1
- package/dist/components/ai-elements/actions.js +1 -1
- package/dist/components/ai-elements/actions.js.map +1 -1
- package/dist/components/ai-elements/code-block.d.ts +1 -1
- package/dist/components/ai-elements/code-block.d.ts.map +1 -1
- package/dist/components/ai-elements/code-block.js +22 -20
- package/dist/components/ai-elements/code-block.js.map +1 -1
- package/dist/components/ai-elements/conversation.d.ts +2 -2
- package/dist/components/ai-elements/conversation.d.ts.map +1 -1
- package/dist/components/ai-elements/conversation.js +5 -3
- package/dist/components/ai-elements/conversation.js.map +1 -1
- package/dist/components/ai-elements/message.d.ts +1 -1
- package/dist/components/ai-elements/message.d.ts.map +1 -1
- package/dist/components/ai-elements/message.js +4 -9
- package/dist/components/ai-elements/message.js.map +1 -1
- package/dist/components/ai-elements/prompt-input.d.ts.map +1 -1
- package/dist/components/ai-elements/prompt-input.js +1 -1
- package/dist/components/ai-elements/prompt-input.js.map +1 -1
- package/dist/components/ai-elements/shimmer.d.ts.map +1 -1
- package/dist/components/ai-elements/shimmer.js +1 -1
- package/dist/components/ai-elements/shimmer.js.map +1 -1
- package/dist/components/internal/chat.d.ts +10 -0
- package/dist/components/internal/chat.d.ts.map +1 -0
- package/dist/components/internal/chat.js +104 -0
- package/dist/components/internal/chat.js.map +1 -0
- package/dist/components/internal/{Header.d.ts → header.d.ts} +4 -6
- package/dist/components/internal/header.d.ts.map +1 -0
- package/dist/components/internal/header.js +25 -0
- package/dist/components/internal/header.js.map +1 -0
- package/dist/components/internal/{InputSection.d.ts → input-section.d.ts} +9 -9
- package/dist/components/internal/input-section.d.ts.map +1 -0
- package/dist/components/internal/input-section.js +162 -0
- package/dist/components/internal/input-section.js.map +1 -0
- package/dist/components/internal/json-editor.d.ts +14 -0
- package/dist/components/internal/json-editor.d.ts.map +1 -0
- package/dist/components/internal/{MonacoJsonEditor.js → json-editor.js} +40 -37
- package/dist/components/internal/json-editor.js.map +1 -0
- package/dist/components/internal/logo.d.ts +2 -3
- package/dist/components/internal/logo.d.ts.map +1 -1
- package/dist/components/internal/logo.js +2 -2
- package/dist/components/internal/logo.js.map +1 -1
- package/dist/components/internal/resizable-provider.d.ts.map +1 -0
- package/dist/components/internal/resizable-provider.js.map +1 -0
- package/dist/components/internal/{Schema.d.ts → schema.d.ts} +2 -2
- package/dist/components/internal/schema.d.ts.map +1 -0
- package/dist/components/internal/schema.js +13 -0
- package/dist/components/internal/schema.js.map +1 -0
- package/dist/components/internal/{WorkbenchProvider.d.ts → workbench-provider.d.ts} +8 -4
- package/dist/components/internal/workbench-provider.d.ts.map +1 -0
- package/dist/components/internal/{WorkbenchProvider.js → workbench-provider.js} +87 -60
- package/dist/components/internal/workbench-provider.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.d.ts.map +1 -1
- package/dist/components/ui/avatar.js.map +1 -1
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/command.d.ts +1 -1
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/command.js.map +1 -1
- package/dist/components/ui/dialog.d.ts +1 -1
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/dropdown-menu.d.ts +1 -1
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.js.map +1 -1
- package/dist/components/ui/hover-card.d.ts +1 -1
- package/dist/components/ui/hover-card.d.ts.map +1 -1
- package/dist/components/ui/hover-card.js.map +1 -1
- package/dist/components/ui/input-group.d.ts +2 -2
- package/dist/components/ui/input-group.d.ts.map +1 -1
- package/dist/components/ui/input-group.js.map +1 -1
- package/dist/components/ui/input.d.ts +1 -1
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.d.ts +1 -1
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.js.map +1 -1
- package/dist/components/ui/textarea.d.ts +1 -1
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/theme-provider.d.ts.map +1 -1
- package/dist/components/ui/theme-provider.js +1 -1
- package/dist/components/ui/theme-provider.js.map +1 -1
- package/dist/components/ui/tooltip.d.ts +1 -1
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/tooltip.js.map +1 -1
- package/dist/hooks/useAgentSchemas.d.ts +10 -10
- package/dist/hooks/useAgentSchemas.d.ts.map +1 -1
- package/dist/hooks/useAgentSchemas.js +9 -7
- package/dist/hooks/useAgentSchemas.js.map +1 -1
- package/dist/hooks/useLogger.d.ts.map +1 -1
- package/dist/hooks/useLogger.js +2 -1
- package/dist/hooks/useLogger.js.map +1 -1
- package/dist/hooks/useWorkbenchWebsocket.d.ts +2 -2
- package/dist/hooks/useWorkbenchWebsocket.d.ts.map +1 -1
- package/dist/hooks/useWorkbenchWebsocket.js +24 -20
- package/dist/hooks/useWorkbenchWebsocket.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -6
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +59 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js.map +1 -1
- package/dist/standalone.css +360 -295
- package/dist/types/config.d.ts +27 -18
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/base.css +186 -158
- package/src/components/App.tsx +31 -16
- package/src/components/ai-elements/actions.tsx +2 -2
- package/src/components/ai-elements/code-block.tsx +46 -32
- package/src/components/ai-elements/conversation.tsx +18 -17
- package/src/components/ai-elements/message.tsx +4 -9
- package/src/components/ai-elements/prompt-input.tsx +1 -1
- package/src/components/ai-elements/shimmer.tsx +1 -1
- package/src/components/internal/chat.tsx +326 -0
- package/src/components/internal/{Header.tsx → header.tsx} +37 -40
- package/src/components/internal/{InputSection.tsx → input-section.tsx} +173 -119
- package/src/components/internal/{MonacoJsonEditor.tsx → json-editor.tsx} +77 -49
- package/src/components/internal/logo.tsx +3 -5
- package/src/components/internal/schema.tsx +96 -0
- package/src/components/internal/{WorkbenchProvider.tsx → workbench-provider.tsx} +194 -68
- package/src/components/ui/avatar.tsx +1 -1
- package/src/components/ui/command.tsx +1 -1
- package/src/components/ui/dialog.tsx +1 -1
- package/src/components/ui/dropdown-menu.tsx +1 -1
- package/src/components/ui/hover-card.tsx +1 -1
- package/src/components/ui/input-group.tsx +1 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/scroll-area.tsx +1 -1
- package/src/components/ui/textarea.tsx +1 -1
- package/src/components/ui/theme-provider.tsx +1 -1
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/hooks/useAgentSchemas.ts +26 -15
- package/src/hooks/useLogger.ts +7 -1
- package/src/hooks/useWorkbenchWebsocket.ts +67 -32
- package/src/index.ts +5 -9
- package/src/lib/utils.ts +88 -0
- package/src/server.ts +1 -1
- package/src/types/config.ts +28 -21
- package/dist/components/internal/Chat.d.ts +0 -14
- package/dist/components/internal/Chat.d.ts.map +0 -1
- package/dist/components/internal/Chat.js +0 -61
- package/dist/components/internal/Chat.js.map +0 -1
- package/dist/components/internal/Header.d.ts.map +0 -1
- package/dist/components/internal/Header.js +0 -31
- package/dist/components/internal/Header.js.map +0 -1
- package/dist/components/internal/InputSection.d.ts.map +0 -1
- package/dist/components/internal/InputSection.js +0 -152
- package/dist/components/internal/InputSection.js.map +0 -1
- package/dist/components/internal/MonacoJsonEditor.d.ts +0 -13
- package/dist/components/internal/MonacoJsonEditor.d.ts.map +0 -1
- package/dist/components/internal/MonacoJsonEditor.js.map +0 -1
- package/dist/components/internal/Schema.d.ts.map +0 -1
- package/dist/components/internal/Schema.js +0 -13
- package/dist/components/internal/Schema.js.map +0 -1
- package/dist/components/internal/WorkbenchProvider.d.ts.map +0 -1
- package/dist/components/internal/WorkbenchProvider.js.map +0 -1
- package/dist/components/ui/resizable-provider.d.ts.map +0 -1
- package/dist/components/ui/resizable-provider.js.map +0 -1
- package/src/components/internal/Chat.tsx +0 -201
- package/src/components/internal/Schema.tsx +0 -100
- /package/dist/components/{ui → internal}/resizable-provider.d.ts +0 -0
- /package/dist/components/{ui → internal}/resizable-provider.js +0 -0
- /package/src/components/{ui → internal}/resizable-provider.tsx +0 -0
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import React, { createContext, useContext, useEffect, useState, useCallback } from 'react';
|
|
2
|
-
import type { UIMessage } from 'ai';
|
|
3
1
|
import type { WorkbenchConfig } from '@agentuity/core/workbench';
|
|
4
|
-
import type {
|
|
2
|
+
import type { UIMessage } from 'ai';
|
|
3
|
+
import type React from 'react';
|
|
4
|
+
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
5
5
|
import { useAgentSchemas } from '../../hooks/useAgentSchemas';
|
|
6
|
-
import { useWorkbenchWebsocket } from '../../hooks/useWorkbenchWebsocket';
|
|
7
6
|
import { useLogger } from '../../hooks/useLogger';
|
|
8
|
-
import {
|
|
7
|
+
import { useWorkbenchWebsocket } from '../../hooks/useWorkbenchWebsocket';
|
|
8
|
+
import { defaultBaseUrl, getTotalTokens, parseTokensHeader } from '../../lib/utils';
|
|
9
|
+
import type { ConnectionStatus, WorkbenchContextType } from '../../types/config';
|
|
9
10
|
|
|
10
11
|
const WorkbenchContext = createContext<WorkbenchContextType | null>(null);
|
|
11
12
|
|
|
12
13
|
export function useWorkbench() {
|
|
13
14
|
const context = useContext(WorkbenchContext);
|
|
15
|
+
|
|
14
16
|
if (!context) {
|
|
15
17
|
throw new Error('useWorkbench must be used within a WorkbenchProvider');
|
|
16
18
|
}
|
|
19
|
+
|
|
17
20
|
return context;
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -22,25 +25,38 @@ interface WorkbenchProviderProps {
|
|
|
22
25
|
baseUrl?: string | null;
|
|
23
26
|
projectId?: string;
|
|
24
27
|
};
|
|
25
|
-
|
|
28
|
+
env: {
|
|
29
|
+
agentuity: boolean;
|
|
30
|
+
authenticated: boolean;
|
|
31
|
+
cloud: boolean;
|
|
32
|
+
};
|
|
26
33
|
children: React.ReactNode;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
|
-
export function WorkbenchProvider({
|
|
36
|
+
export function WorkbenchProvider({
|
|
37
|
+
config,
|
|
38
|
+
env = {
|
|
39
|
+
agentuity: false,
|
|
40
|
+
authenticated: false,
|
|
41
|
+
cloud: false,
|
|
42
|
+
},
|
|
43
|
+
children,
|
|
44
|
+
}: WorkbenchProviderProps) {
|
|
30
45
|
const logger = useLogger('WorkbenchProvider');
|
|
31
46
|
|
|
32
47
|
// localStorage utilities scoped by project
|
|
33
48
|
const getStorageKey = useCallback(
|
|
34
|
-
(key: string) =>
|
|
49
|
+
(key: string) =>
|
|
50
|
+
`agentuity-workbench-${config.projectId ? `${config.projectId}-` : ''}${key}`,
|
|
35
51
|
[config.projectId]
|
|
36
52
|
);
|
|
37
53
|
|
|
38
54
|
const saveSelectedAgent = useCallback(
|
|
39
55
|
(agentId: string) => {
|
|
40
56
|
try {
|
|
41
|
-
localStorage.setItem(getStorageKey('
|
|
57
|
+
localStorage.setItem(getStorageKey('selected-agent'), agentId);
|
|
42
58
|
} catch (error) {
|
|
43
|
-
|
|
59
|
+
logger.warn('Failed to save selected agent to localStorage:', error);
|
|
44
60
|
}
|
|
45
61
|
},
|
|
46
62
|
[getStorageKey]
|
|
@@ -48,9 +64,9 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
48
64
|
|
|
49
65
|
const loadSelectedAgent = useCallback((): string | null => {
|
|
50
66
|
try {
|
|
51
|
-
return localStorage.getItem(getStorageKey('
|
|
67
|
+
return localStorage.getItem(getStorageKey('selected-agent'));
|
|
52
68
|
} catch (error) {
|
|
53
|
-
|
|
69
|
+
logger.warn('Failed to load selected agent from localStorage:', error);
|
|
54
70
|
return null;
|
|
55
71
|
}
|
|
56
72
|
}, [getStorageKey]);
|
|
@@ -58,9 +74,9 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
58
74
|
const saveThreadId = useCallback(
|
|
59
75
|
(threadId: string) => {
|
|
60
76
|
try {
|
|
61
|
-
localStorage.setItem(getStorageKey('
|
|
77
|
+
localStorage.setItem(getStorageKey('thread-id'), threadId);
|
|
62
78
|
} catch (error) {
|
|
63
|
-
|
|
79
|
+
logger.warn('Failed to save thread id to localStorage:', error);
|
|
64
80
|
}
|
|
65
81
|
},
|
|
66
82
|
[getStorageKey]
|
|
@@ -68,9 +84,10 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
68
84
|
|
|
69
85
|
const loadThreadId = useCallback((): string | null => {
|
|
70
86
|
try {
|
|
71
|
-
return localStorage.getItem(getStorageKey('
|
|
87
|
+
return localStorage.getItem(getStorageKey('thread-id'));
|
|
72
88
|
} catch (error) {
|
|
73
|
-
|
|
89
|
+
logger.warn('Failed to load thread id from localStorage:', error);
|
|
90
|
+
|
|
74
91
|
return null;
|
|
75
92
|
}
|
|
76
93
|
}, [getStorageKey]);
|
|
@@ -120,6 +137,7 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
120
137
|
useEffect(() => {
|
|
121
138
|
if (isBaseUrlNull) {
|
|
122
139
|
logger.debug('🔌 Setting connection status to disconnected (baseUrl is null)');
|
|
140
|
+
|
|
123
141
|
setConnectionStatus('disconnected');
|
|
124
142
|
}
|
|
125
143
|
}, [isBaseUrlNull, logger]);
|
|
@@ -143,6 +161,7 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
143
161
|
|
|
144
162
|
// WebSocket connection for dev server restart detection
|
|
145
163
|
const wsBaseUrl = isBaseUrlNull ? undefined : baseUrl;
|
|
164
|
+
|
|
146
165
|
useEffect(() => {
|
|
147
166
|
if (isBaseUrlNull) {
|
|
148
167
|
logger.debug('🔌 WebSocket connection disabled (baseUrl is null)');
|
|
@@ -178,18 +197,17 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
178
197
|
|
|
179
198
|
// Convert schema data to Agent format, no fallback
|
|
180
199
|
const agents = schemaData?.agents;
|
|
200
|
+
|
|
181
201
|
// Log schema fetch errors for debugging
|
|
182
202
|
useEffect(() => {
|
|
183
203
|
if (schemasError) {
|
|
184
|
-
|
|
204
|
+
logger.warn(
|
|
185
205
|
'Failed to fetch agent schemas from API, using static configuration:',
|
|
186
206
|
schemasError.message
|
|
187
207
|
);
|
|
188
208
|
}
|
|
189
209
|
}, [schemasError]);
|
|
190
210
|
|
|
191
|
-
const [suggestions, _setSuggestions] = useState<string[]>([]);
|
|
192
|
-
|
|
193
211
|
// Fetch state for an agent
|
|
194
212
|
const fetchAgentState = useCallback(
|
|
195
213
|
async (agentId: string) => {
|
|
@@ -205,18 +223,23 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
205
223
|
|
|
206
224
|
try {
|
|
207
225
|
const headers: Record<string, string> = {};
|
|
226
|
+
|
|
208
227
|
if (apiKey) {
|
|
209
228
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
210
229
|
}
|
|
230
|
+
|
|
211
231
|
applyThreadIdHeader(headers);
|
|
212
232
|
|
|
213
233
|
const url = `${baseUrl}/_agentuity/workbench/state?agentId=${encodeURIComponent(agentId)}`;
|
|
234
|
+
|
|
214
235
|
logger.debug('📡 Fetching state for agent:', agentId);
|
|
236
|
+
|
|
215
237
|
const response = await fetch(url, {
|
|
216
238
|
method: 'GET',
|
|
217
239
|
headers,
|
|
218
240
|
credentials: 'include',
|
|
219
241
|
});
|
|
242
|
+
|
|
220
243
|
persistThreadIdFromResponse(response);
|
|
221
244
|
|
|
222
245
|
if (response.ok) {
|
|
@@ -233,8 +256,10 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
233
256
|
typeof msg.data === 'object'
|
|
234
257
|
? JSON.stringify(msg.data, null, 2)
|
|
235
258
|
: String(msg.data);
|
|
259
|
+
|
|
236
260
|
// Use stable ID based on index and a hash of content to maintain identity
|
|
237
261
|
const contentHash = text.substring(0, 20).replace(/[^a-zA-Z0-9]/g, '');
|
|
262
|
+
|
|
238
263
|
return {
|
|
239
264
|
id: `state_${agentId}_${index}_${contentHash}`,
|
|
240
265
|
role: msg.type === 'input' ? 'user' : 'assistant',
|
|
@@ -243,13 +268,16 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
243
268
|
});
|
|
244
269
|
|
|
245
270
|
setMessages(uiMessages);
|
|
271
|
+
|
|
246
272
|
logger.debug('✅ Loaded state messages:', uiMessages.length);
|
|
247
273
|
} else {
|
|
248
274
|
logger.debug('⚠️ Failed to fetch state, starting with empty messages');
|
|
275
|
+
|
|
249
276
|
setMessages([]);
|
|
250
277
|
}
|
|
251
278
|
} catch (error) {
|
|
252
279
|
logger.debug('⚠️ Error fetching state:', error);
|
|
280
|
+
|
|
253
281
|
setMessages([]);
|
|
254
282
|
}
|
|
255
283
|
},
|
|
@@ -264,16 +292,20 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
264
292
|
// First, check for agent query parameter in URL
|
|
265
293
|
const urlParams = new URLSearchParams(window.location.search);
|
|
266
294
|
const agentFromUrl = urlParams.get('agent');
|
|
295
|
+
|
|
267
296
|
logger.debug('🔗 Agent from URL query param:', agentFromUrl);
|
|
268
297
|
|
|
269
298
|
// Try to find agent by URL param (matches agentId only)
|
|
270
299
|
let agentToSelect: string | null = null;
|
|
300
|
+
|
|
271
301
|
if (agentFromUrl) {
|
|
272
302
|
const matchedAgent = Object.values(agents).find(
|
|
273
303
|
(agent) => agent.metadata.agentId === agentFromUrl
|
|
274
304
|
);
|
|
305
|
+
|
|
275
306
|
if (matchedAgent) {
|
|
276
307
|
logger.debug('✅ Found agent from URL param:', matchedAgent.metadata.name);
|
|
308
|
+
|
|
277
309
|
agentToSelect = matchedAgent.metadata.agentId;
|
|
278
310
|
}
|
|
279
311
|
}
|
|
@@ -281,6 +313,7 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
281
313
|
// If no URL param match, try localStorage
|
|
282
314
|
if (!agentToSelect) {
|
|
283
315
|
const savedAgentId = loadSelectedAgent();
|
|
316
|
+
|
|
284
317
|
logger.debug('💾 Saved agent from localStorage:', savedAgentId);
|
|
285
318
|
|
|
286
319
|
const savedAgent = savedAgentId
|
|
@@ -289,6 +322,7 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
289
322
|
|
|
290
323
|
if (savedAgent && savedAgentId) {
|
|
291
324
|
logger.debug('✅ Restoring saved agent:', savedAgent.metadata.name);
|
|
325
|
+
|
|
292
326
|
agentToSelect = savedAgentId;
|
|
293
327
|
}
|
|
294
328
|
}
|
|
@@ -298,44 +332,44 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
298
332
|
const sortedAgents = Object.values(agents).sort((a, b) =>
|
|
299
333
|
a.metadata.name.localeCompare(b.metadata.name)
|
|
300
334
|
);
|
|
335
|
+
|
|
301
336
|
const firstAgent = sortedAgents[0];
|
|
337
|
+
|
|
302
338
|
logger.debug(
|
|
303
339
|
'🎯 No saved agent found, using first agent (alphabetically):',
|
|
304
340
|
firstAgent
|
|
305
341
|
);
|
|
342
|
+
|
|
306
343
|
agentToSelect = firstAgent.metadata.agentId;
|
|
307
344
|
}
|
|
308
345
|
|
|
309
346
|
logger.debug('🆔 Setting selectedAgent to:', agentToSelect);
|
|
347
|
+
|
|
310
348
|
setSelectedAgent(agentToSelect);
|
|
311
349
|
saveSelectedAgent(agentToSelect);
|
|
312
350
|
fetchAgentState(agentToSelect);
|
|
313
351
|
}
|
|
314
352
|
}, [agents, selectedAgent, loadSelectedAgent, saveSelectedAgent, logger, fetchAgentState]);
|
|
315
353
|
|
|
316
|
-
// Fetch suggestions from API if endpoint is provided
|
|
317
|
-
useEffect(() => {
|
|
318
|
-
// No API endpoints hardcoded for now
|
|
319
|
-
}, []);
|
|
320
|
-
|
|
321
|
-
const _fetchSuggestions = async () => {
|
|
322
|
-
// No API endpoints for now
|
|
323
|
-
};
|
|
324
|
-
|
|
325
354
|
const submitMessage = async (value: string, _mode: 'text' | 'form' = 'text') => {
|
|
326
355
|
if (!selectedAgent) return;
|
|
327
356
|
|
|
328
357
|
logger.debug('🚀 Submitting message with selectedAgent:', selectedAgent);
|
|
358
|
+
|
|
329
359
|
const selectedAgentData = agents
|
|
330
360
|
? Object.values(agents).find((agent) => agent.metadata.agentId === selectedAgent)
|
|
331
361
|
: undefined;
|
|
362
|
+
|
|
332
363
|
logger.debug('📊 Found selectedAgentData:', selectedAgentData);
|
|
364
|
+
|
|
333
365
|
const hasInputSchema = selectedAgentData?.schema?.input?.json;
|
|
366
|
+
|
|
334
367
|
logger.debug('📝 hasInputSchema:', hasInputSchema, 'value:', value);
|
|
335
368
|
|
|
336
369
|
// Only require value for agents with input schemas
|
|
337
370
|
if (hasInputSchema && !value.trim()) {
|
|
338
371
|
logger.debug('❌ Returning early - hasInputSchema but no value');
|
|
372
|
+
|
|
339
373
|
return;
|
|
340
374
|
}
|
|
341
375
|
|
|
@@ -353,7 +387,6 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
353
387
|
role: 'user',
|
|
354
388
|
parts: [{ type: 'text', text: displayText }],
|
|
355
389
|
};
|
|
356
|
-
|
|
357
390
|
const assistantMessageId = (now + 1).toString();
|
|
358
391
|
const placeholderAssistantMessage: UIMessage = {
|
|
359
392
|
id: assistantMessageId,
|
|
@@ -365,8 +398,10 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
365
398
|
setIsLoading(true);
|
|
366
399
|
|
|
367
400
|
logger.debug('🔗 baseUrl:', baseUrl, 'isBaseUrlNull:', isBaseUrlNull);
|
|
401
|
+
|
|
368
402
|
if (!baseUrl || isBaseUrlNull) {
|
|
369
403
|
logger.debug('❌ Message submission blocked - baseUrl is null or missing');
|
|
404
|
+
|
|
370
405
|
const errorMessage: UIMessage = {
|
|
371
406
|
id: assistantMessageId,
|
|
372
407
|
role: 'assistant',
|
|
@@ -377,8 +412,11 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
377
412
|
},
|
|
378
413
|
],
|
|
379
414
|
};
|
|
415
|
+
|
|
380
416
|
setMessages((prev) => prev.map((m) => (m.id === assistantMessageId ? errorMessage : m)));
|
|
417
|
+
|
|
381
418
|
setIsLoading(false);
|
|
419
|
+
|
|
382
420
|
return;
|
|
383
421
|
}
|
|
384
422
|
|
|
@@ -386,6 +424,7 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
386
424
|
// Parse input - if it's JSON, parse it, otherwise use as string
|
|
387
425
|
// For agents without input schema, send undefined
|
|
388
426
|
let parsedInput: unknown;
|
|
427
|
+
|
|
389
428
|
if (!hasInputSchema) {
|
|
390
429
|
parsedInput = undefined;
|
|
391
430
|
} else {
|
|
@@ -397,17 +436,17 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
397
436
|
}
|
|
398
437
|
|
|
399
438
|
logger.debug('🌐 About to make API call...');
|
|
439
|
+
|
|
400
440
|
// Call execution endpoint with timeout
|
|
401
441
|
const headers: Record<string, string> = {
|
|
402
442
|
'Content-Type': 'application/json',
|
|
403
443
|
};
|
|
444
|
+
|
|
404
445
|
if (apiKey) {
|
|
405
446
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
406
447
|
}
|
|
407
|
-
applyThreadIdHeader(headers);
|
|
408
448
|
|
|
409
|
-
|
|
410
|
-
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30s timeout
|
|
449
|
+
applyThreadIdHeader(headers);
|
|
411
450
|
|
|
412
451
|
const startTime = performance.now();
|
|
413
452
|
|
|
@@ -416,32 +455,55 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
416
455
|
agentId: selectedAgent,
|
|
417
456
|
input: parsedInput,
|
|
418
457
|
};
|
|
458
|
+
|
|
419
459
|
logger.debug('📤 API Request payload:', requestPayload);
|
|
460
|
+
|
|
420
461
|
const response = await fetch(`${baseUrl}/_agentuity/workbench/execute`, {
|
|
421
462
|
method: 'POST',
|
|
422
463
|
headers,
|
|
423
464
|
body: JSON.stringify(requestPayload),
|
|
424
|
-
signal: controller.signal,
|
|
425
465
|
credentials: 'include',
|
|
426
466
|
});
|
|
467
|
+
|
|
427
468
|
persistThreadIdFromResponse(response);
|
|
428
|
-
clearTimeout(timeoutId);
|
|
429
469
|
|
|
430
470
|
if (!response.ok) {
|
|
431
|
-
let
|
|
471
|
+
let errorText = `Request failed with status ${response.status}`;
|
|
472
|
+
|
|
432
473
|
try {
|
|
433
474
|
const errorData = await response.json();
|
|
434
|
-
|
|
475
|
+
|
|
476
|
+
errorText = errorData.error || errorData.message || errorText;
|
|
435
477
|
} catch {
|
|
436
478
|
// If JSON parsing fails, use status text
|
|
437
|
-
|
|
479
|
+
errorText = response.statusText || errorText;
|
|
438
480
|
}
|
|
439
|
-
|
|
481
|
+
|
|
482
|
+
const errorPayload = JSON.stringify({
|
|
483
|
+
__agentError: true,
|
|
484
|
+
message: errorText,
|
|
485
|
+
code: `HTTP_${response.status}`,
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
const errorMessage: UIMessage = {
|
|
489
|
+
id: assistantMessageId,
|
|
490
|
+
role: 'assistant',
|
|
491
|
+
parts: [{ type: 'text', text: errorPayload }],
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
setMessages((prev) =>
|
|
495
|
+
prev.map((m) => (m.id === assistantMessageId ? errorMessage : m))
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
setIsLoading(false);
|
|
499
|
+
|
|
500
|
+
return;
|
|
440
501
|
}
|
|
441
502
|
|
|
442
|
-
let
|
|
503
|
+
let responseBody: unknown;
|
|
504
|
+
|
|
443
505
|
try {
|
|
444
|
-
|
|
506
|
+
responseBody = await response.json();
|
|
445
507
|
} catch (jsonError) {
|
|
446
508
|
throw new Error(`Invalid JSON response from server: ${jsonError}`);
|
|
447
509
|
}
|
|
@@ -458,27 +520,79 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
458
520
|
const tokensRecord = tokensHeader ? parseTokensHeader(tokensHeader) : undefined;
|
|
459
521
|
const totalTokens = tokensRecord ? getTotalTokens(tokensRecord) : undefined;
|
|
460
522
|
|
|
523
|
+
// Handle wrapped response shape: { success, data?, error? }
|
|
524
|
+
const envelope =
|
|
525
|
+
typeof responseBody === 'object' && responseBody !== null
|
|
526
|
+
? (responseBody as {
|
|
527
|
+
success?: boolean;
|
|
528
|
+
data?: unknown;
|
|
529
|
+
error?: {
|
|
530
|
+
message?: string;
|
|
531
|
+
stack?: string;
|
|
532
|
+
code?: string;
|
|
533
|
+
cause?: unknown;
|
|
534
|
+
};
|
|
535
|
+
})
|
|
536
|
+
: null;
|
|
537
|
+
|
|
538
|
+
if (envelope && 'success' in envelope && envelope.success === false && envelope.error) {
|
|
539
|
+
// Agent execution error - encode as special JSON format for ErrorBubble
|
|
540
|
+
const errorPayload = JSON.stringify({
|
|
541
|
+
__agentError: true,
|
|
542
|
+
message: envelope.error.message || 'Unknown error',
|
|
543
|
+
stack: envelope.error.stack,
|
|
544
|
+
code: envelope.error.code,
|
|
545
|
+
cause: envelope.error.cause,
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
const errorMessage: UIMessage = {
|
|
549
|
+
id: assistantMessageId,
|
|
550
|
+
role: 'assistant',
|
|
551
|
+
parts: [{ type: 'text', text: errorPayload }],
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
setMessages((prev) =>
|
|
555
|
+
prev.map((m) => (m.id === assistantMessageId ? errorMessage : m))
|
|
556
|
+
);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Success - extract data from envelope (or use raw response if not wrapped)
|
|
561
|
+
const result =
|
|
562
|
+
envelope && 'success' in envelope && envelope.success === true
|
|
563
|
+
? envelope.data
|
|
564
|
+
: responseBody;
|
|
565
|
+
|
|
461
566
|
// Format result as JSON string for display
|
|
462
567
|
const resultText =
|
|
463
568
|
typeof result === 'object' ? JSON.stringify(result, null, 2) : String(result);
|
|
464
569
|
|
|
465
|
-
const
|
|
570
|
+
const sessionId = response.headers.get('x-session-id') || undefined;
|
|
571
|
+
|
|
572
|
+
const assistantMessage: UIMessage & {
|
|
573
|
+
tokens?: string;
|
|
574
|
+
duration?: string;
|
|
575
|
+
sessionId?: string;
|
|
576
|
+
} = {
|
|
466
577
|
id: assistantMessageId,
|
|
467
578
|
role: 'assistant',
|
|
468
579
|
parts: [{ type: 'text', text: resultText }],
|
|
469
580
|
tokens: totalTokens?.toString(),
|
|
470
581
|
duration,
|
|
582
|
+
sessionId,
|
|
471
583
|
};
|
|
472
584
|
|
|
473
585
|
setMessages((prev) =>
|
|
474
586
|
prev.map((m) => (m.id === assistantMessageId ? assistantMessage : m))
|
|
475
587
|
);
|
|
476
588
|
} catch (fetchError) {
|
|
477
|
-
|
|
589
|
+
logger.error('❌ Failed to submit message:', fetchError);
|
|
590
|
+
|
|
478
591
|
throw fetchError;
|
|
479
592
|
}
|
|
480
593
|
} catch (error) {
|
|
481
|
-
|
|
594
|
+
logger.error('❌ Failed to submit message:', error);
|
|
595
|
+
|
|
482
596
|
const errorText =
|
|
483
597
|
error instanceof Error
|
|
484
598
|
? error.name === 'AbortError'
|
|
@@ -486,16 +600,19 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
486
600
|
: error.message
|
|
487
601
|
: 'Sorry, I encountered an error processing your message.';
|
|
488
602
|
|
|
603
|
+
const errorPayload = JSON.stringify({
|
|
604
|
+
__agentError: true,
|
|
605
|
+
message: errorText,
|
|
606
|
+
code:
|
|
607
|
+
error instanceof Error && error.name === 'AbortError' ? 'TIMEOUT' : 'REQUEST_ERROR',
|
|
608
|
+
});
|
|
609
|
+
|
|
489
610
|
const errorMessage: UIMessage = {
|
|
490
611
|
id: assistantMessageId,
|
|
491
612
|
role: 'assistant',
|
|
492
|
-
parts: [
|
|
493
|
-
{
|
|
494
|
-
type: 'text',
|
|
495
|
-
text: errorText,
|
|
496
|
-
},
|
|
497
|
-
],
|
|
613
|
+
parts: [{ type: 'text', text: errorPayload }],
|
|
498
614
|
};
|
|
615
|
+
|
|
499
616
|
setMessages((prev) => prev.map((m) => (m.id === assistantMessageId ? errorMessage : m)));
|
|
500
617
|
} finally {
|
|
501
618
|
setIsLoading(false);
|
|
@@ -508,6 +625,7 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
508
625
|
}
|
|
509
626
|
|
|
510
627
|
setIsGeneratingSample(true);
|
|
628
|
+
|
|
511
629
|
try {
|
|
512
630
|
const url = `${baseUrl}/_agentuity/workbench/sample?agentId=${encodeURIComponent(agentId)}`;
|
|
513
631
|
const headers: HeadersInit = {
|
|
@@ -515,8 +633,9 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
515
633
|
};
|
|
516
634
|
|
|
517
635
|
if (apiKey) {
|
|
518
|
-
headers
|
|
636
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
519
637
|
}
|
|
638
|
+
|
|
520
639
|
// Keep thread id stable across workbench endpoints.
|
|
521
640
|
if (typeof headers === 'object' && headers && !Array.isArray(headers)) {
|
|
522
641
|
applyThreadIdHeader(headers as Record<string, string>);
|
|
@@ -527,23 +646,29 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
527
646
|
headers,
|
|
528
647
|
credentials: 'include',
|
|
529
648
|
});
|
|
649
|
+
|
|
530
650
|
persistThreadIdFromResponse(response);
|
|
531
651
|
|
|
532
652
|
if (!response.ok) {
|
|
533
653
|
let errorMessage = `Request failed with status ${response.status}`;
|
|
654
|
+
|
|
534
655
|
try {
|
|
535
656
|
const errorData = await response.json();
|
|
657
|
+
|
|
536
658
|
errorMessage = errorData.error || errorData.message || errorMessage;
|
|
537
659
|
} catch {
|
|
538
660
|
errorMessage = response.statusText || errorMessage;
|
|
539
661
|
}
|
|
662
|
+
|
|
540
663
|
throw new Error(errorMessage);
|
|
541
664
|
}
|
|
542
665
|
|
|
543
666
|
const sample = await response.json();
|
|
667
|
+
|
|
544
668
|
return JSON.stringify(sample, null, 2);
|
|
545
669
|
} catch (error) {
|
|
546
670
|
logger.error('Failed to generate sample JSON:', error);
|
|
671
|
+
|
|
547
672
|
throw error;
|
|
548
673
|
} finally {
|
|
549
674
|
setIsGeneratingSample(false);
|
|
@@ -552,6 +677,7 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
552
677
|
|
|
553
678
|
const handleAgentSelect = async (agentId: string) => {
|
|
554
679
|
logger.debug('🔄 handleAgentSelect called with:', agentId);
|
|
680
|
+
|
|
555
681
|
setSelectedAgent(agentId);
|
|
556
682
|
// Save selection to localStorage for persistence across sessions
|
|
557
683
|
saveSelectedAgent(agentId);
|
|
@@ -567,9 +693,11 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
567
693
|
|
|
568
694
|
try {
|
|
569
695
|
const headers: Record<string, string> = {};
|
|
696
|
+
|
|
570
697
|
if (apiKey) {
|
|
571
698
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
572
699
|
}
|
|
700
|
+
|
|
573
701
|
applyThreadIdHeader(headers);
|
|
574
702
|
|
|
575
703
|
const url = `${baseUrl}/_agentuity/workbench/state?agentId=${encodeURIComponent(agentId)}`;
|
|
@@ -578,10 +706,12 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
578
706
|
headers,
|
|
579
707
|
credentials: 'include',
|
|
580
708
|
});
|
|
709
|
+
|
|
581
710
|
persistThreadIdFromResponse(response);
|
|
582
711
|
|
|
583
712
|
if (response.ok) {
|
|
584
713
|
setMessages([]);
|
|
714
|
+
|
|
585
715
|
logger.debug('✅ Cleared state for agent:', agentId);
|
|
586
716
|
} else {
|
|
587
717
|
logger.debug('⚠️ Failed to clear state');
|
|
@@ -594,29 +724,25 @@ export function WorkbenchProvider({ config, isAuthenticated, children }: Workben
|
|
|
594
724
|
);
|
|
595
725
|
|
|
596
726
|
const contextValue: WorkbenchContextType = {
|
|
597
|
-
config,
|
|
598
727
|
agents: agents || {},
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
setSelectedAgent: handleAgentSelect,
|
|
604
|
-
inputMode,
|
|
605
|
-
setInputMode,
|
|
606
|
-
isLoading: isLoading || !!schemasLoading,
|
|
607
|
-
submitMessage,
|
|
728
|
+
clearAgentState,
|
|
729
|
+
config,
|
|
730
|
+
connectionStatus,
|
|
731
|
+
env,
|
|
608
732
|
generateSample,
|
|
733
|
+
inputMode,
|
|
609
734
|
isGeneratingSample,
|
|
610
|
-
|
|
611
|
-
|
|
735
|
+
isLoading: isLoading || !!schemasLoading,
|
|
736
|
+
messages,
|
|
737
|
+
refetchSchemas,
|
|
612
738
|
schemas: schemaData,
|
|
613
|
-
schemasLoading: !!schemasLoading,
|
|
614
739
|
schemasError,
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
740
|
+
schemasLoading: !!schemasLoading,
|
|
741
|
+
selectedAgent,
|
|
742
|
+
setInputMode,
|
|
743
|
+
setMessages,
|
|
744
|
+
setSelectedAgent: handleAgentSelect,
|
|
745
|
+
submitMessage,
|
|
620
746
|
};
|
|
621
747
|
|
|
622
748
|
return <WorkbenchContext.Provider value={contextValue}>{children}</WorkbenchContext.Provider>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import { Command as CommandPrimitive } from 'cmdk';
|
|
3
2
|
import { SearchIcon } from 'lucide-react';
|
|
3
|
+
import type * as React from 'react';
|
|
4
4
|
|
|
5
5
|
import { cn } from '../../lib/utils';
|
|
6
6
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './dialog';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import * as React from 'react';
|
|
4
3
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
5
4
|
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
|
|
5
|
+
import type * as React from 'react';
|
|
6
6
|
|
|
7
7
|
import { cn } from '../../lib/utils';
|
|
8
8
|
|