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