@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
|
@@ -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>(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { JSONSchema7 } from 'ai';
|
|
2
|
-
import {
|
|
1
|
+
import type { JSONSchema7 } from 'ai';
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { useLogger } from './useLogger';
|
|
3
4
|
|
|
4
5
|
export interface AgentSchema {
|
|
5
6
|
input?: {
|
|
@@ -13,18 +14,18 @@ export interface AgentSchema {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export interface AgentMetadata {
|
|
16
|
-
|
|
17
|
-
name: string;
|
|
17
|
+
agentId: string;
|
|
18
18
|
description?: string;
|
|
19
|
-
version?: string;
|
|
20
19
|
filename?: string;
|
|
20
|
+
id: string;
|
|
21
21
|
identifier?: string;
|
|
22
|
-
|
|
22
|
+
name: string;
|
|
23
|
+
version?: string;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export interface AgentSchemaData {
|
|
26
|
-
schema: AgentSchema;
|
|
27
27
|
metadata: AgentMetadata;
|
|
28
|
+
schema: AgentSchema;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export interface AgentSchemasResponse {
|
|
@@ -32,15 +33,15 @@ export interface AgentSchemasResponse {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export interface UseAgentSchemasOptions {
|
|
35
|
-
baseUrl?: string;
|
|
36
36
|
apiKey?: string;
|
|
37
|
+
baseUrl?: string;
|
|
37
38
|
enabled?: boolean;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export interface UseAgentSchemasResult {
|
|
41
42
|
data: AgentSchemasResponse | null;
|
|
42
|
-
isLoading: boolean;
|
|
43
43
|
error: Error | null;
|
|
44
|
+
isLoading: boolean;
|
|
44
45
|
refetch: () => void;
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -67,6 +68,7 @@ export interface UseAgentSchemasResult {
|
|
|
67
68
|
export function useAgentSchemas(options: UseAgentSchemasOptions = {}): UseAgentSchemasResult {
|
|
68
69
|
const { baseUrl = '', apiKey, enabled = true } = options;
|
|
69
70
|
|
|
71
|
+
const logger = useLogger('useAgentSchemas');
|
|
70
72
|
const [data, setData] = useState<AgentSchemasResponse | null>(null);
|
|
71
73
|
const [isLoading, setIsLoading] = useState(false);
|
|
72
74
|
const [error, setError] = useState<Error | null>(null);
|
|
@@ -84,7 +86,7 @@ export function useAgentSchemas(options: UseAgentSchemasOptions = {}): UseAgentS
|
|
|
84
86
|
};
|
|
85
87
|
|
|
86
88
|
if (apiKey) {
|
|
87
|
-
headers
|
|
89
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
const response = await fetch(url, {
|
|
@@ -96,27 +98,36 @@ export function useAgentSchemas(options: UseAgentSchemasOptions = {}): UseAgentS
|
|
|
96
98
|
// Handle 404/500 gracefully without throwing
|
|
97
99
|
if (response.status === 401) {
|
|
98
100
|
setError(new Error('Unauthorized: Invalid or missing API key'));
|
|
101
|
+
|
|
99
102
|
return;
|
|
100
103
|
}
|
|
104
|
+
|
|
101
105
|
if (response.status === 404 || response.status >= 500) {
|
|
102
106
|
setError(new Error(`Server error: ${response.status} ${response.statusText}`));
|
|
107
|
+
|
|
103
108
|
return;
|
|
104
109
|
}
|
|
110
|
+
|
|
105
111
|
setError(new Error(`HTTP ${response.status}: ${response.statusText}`));
|
|
112
|
+
|
|
106
113
|
return;
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
try {
|
|
110
117
|
const result = (await response.json()) as AgentSchemasResponse;
|
|
118
|
+
|
|
111
119
|
setData(result);
|
|
112
120
|
} catch (jsonError) {
|
|
113
121
|
setError(new Error('Invalid JSON response from server'));
|
|
114
|
-
|
|
122
|
+
|
|
123
|
+
logger.error('Failed to parse JSON response:', jsonError);
|
|
115
124
|
}
|
|
116
125
|
} catch (err) {
|
|
117
126
|
const error = err instanceof Error ? err : new Error('Unknown error occurred');
|
|
127
|
+
|
|
118
128
|
setError(error);
|
|
119
|
-
|
|
129
|
+
|
|
130
|
+
logger.error('Failed to fetch agent schemas:', error);
|
|
120
131
|
} finally {
|
|
121
132
|
setIsLoading(false);
|
|
122
133
|
}
|
|
@@ -132,8 +143,8 @@ export function useAgentSchemas(options: UseAgentSchemasOptions = {}): UseAgentS
|
|
|
132
143
|
|
|
133
144
|
return {
|
|
134
145
|
data,
|
|
135
|
-
isLoading,
|
|
136
146
|
error,
|
|
147
|
+
isLoading,
|
|
137
148
|
refetch,
|
|
138
149
|
};
|
|
139
150
|
}
|
|
@@ -148,10 +159,10 @@ export function useAgentSchema(agentName: string, options: UseAgentSchemasOption
|
|
|
148
159
|
|
|
149
160
|
return {
|
|
150
161
|
data: agentData,
|
|
151
|
-
isLoading,
|
|
152
162
|
error,
|
|
163
|
+
isLoading,
|
|
164
|
+
metadata: agentData?.metadata || null,
|
|
153
165
|
refetch,
|
|
154
166
|
schema: agentData?.schema || null,
|
|
155
|
-
metadata: agentData?.metadata || null,
|
|
156
167
|
};
|
|
157
168
|
}
|
package/src/hooks/useLogger.ts
CHANGED
|
@@ -12,9 +12,11 @@ interface Logger {
|
|
|
12
12
|
const getLogLevel = (): LogLevel | null => {
|
|
13
13
|
try {
|
|
14
14
|
const level = localStorage.getItem('AGENTUITY_LOG_LEVEL');
|
|
15
|
+
|
|
15
16
|
if (level && ['debug', 'info', 'warn', 'error'].includes(level)) {
|
|
16
17
|
return level as LogLevel;
|
|
17
18
|
}
|
|
19
|
+
|
|
18
20
|
return null;
|
|
19
21
|
} catch {
|
|
20
22
|
return null;
|
|
@@ -23,6 +25,7 @@ const getLogLevel = (): LogLevel | null => {
|
|
|
23
25
|
|
|
24
26
|
const shouldLog = (messageLevel: LogLevel): boolean => {
|
|
25
27
|
const currentLevel = getLogLevel();
|
|
28
|
+
|
|
26
29
|
if (!currentLevel) return false;
|
|
27
30
|
|
|
28
31
|
const levels: Record<LogLevel, number> = {
|
|
@@ -39,10 +42,13 @@ export function useLogger(component?: string): Logger {
|
|
|
39
42
|
const createLogFunction = useCallback(
|
|
40
43
|
(level: LogLevel) =>
|
|
41
44
|
(...args: unknown[]) => {
|
|
42
|
-
if (!shouldLog(level))
|
|
45
|
+
if (!shouldLog(level)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
43
48
|
|
|
44
49
|
const prefix = component ? `[${component}]` : '[Workbench]';
|
|
45
50
|
const consoleFn = console[level] || console.log;
|
|
51
|
+
|
|
46
52
|
consoleFn(prefix, ...args);
|
|
47
53
|
},
|
|
48
54
|
[component]
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
interface ReconnectOptions {
|
|
4
|
-
onReconnect: () => void;
|
|
5
|
-
threshold?: number;
|
|
6
4
|
baseDelay?: number;
|
|
5
|
+
enabled?: () => boolean;
|
|
7
6
|
factor?: number;
|
|
8
|
-
maxDelay?: number;
|
|
9
7
|
jitter?: number;
|
|
10
|
-
|
|
8
|
+
maxDelay?: number;
|
|
9
|
+
onReconnect: () => void;
|
|
10
|
+
threshold?: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
interface ReconnectManager {
|
|
14
|
-
recordFailure: () => { scheduled: boolean; delay: number | null };
|
|
15
|
-
recordSuccess: () => void;
|
|
16
14
|
cancel: () => void;
|
|
17
|
-
reset: () => void;
|
|
18
15
|
dispose: () => void;
|
|
19
16
|
getAttempts: () => number;
|
|
17
|
+
recordFailure: () => { scheduled: boolean; delay: number | null };
|
|
18
|
+
recordSuccess: () => void;
|
|
19
|
+
reset: () => void;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function createReconnectManager(opts: ReconnectOptions): ReconnectManager {
|
|
@@ -26,12 +26,14 @@ function createReconnectManager(opts: ReconnectOptions): ReconnectManager {
|
|
|
26
26
|
const cancel = () => {
|
|
27
27
|
if (timer) {
|
|
28
28
|
clearTimeout(timer);
|
|
29
|
+
|
|
29
30
|
timer = null;
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
const reset = () => {
|
|
34
35
|
attempts = 0;
|
|
36
|
+
|
|
35
37
|
cancel();
|
|
36
38
|
};
|
|
37
39
|
|
|
@@ -42,14 +44,17 @@ function createReconnectManager(opts: ReconnectOptions): ReconnectManager {
|
|
|
42
44
|
const factor = opts.factor ?? 2;
|
|
43
45
|
const max = opts.maxDelay ?? 30000;
|
|
44
46
|
const jitterMax = opts.jitter ?? 250;
|
|
45
|
-
const backoff = Math.min(base *
|
|
47
|
+
const backoff = Math.min(base * factor ** attemptAfterThreshold, max);
|
|
46
48
|
const jitter = jitterMax > 0 ? Math.random() * jitterMax : 0;
|
|
49
|
+
|
|
47
50
|
return backoff + jitter;
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
const recordFailure = () => {
|
|
51
54
|
attempts += 1;
|
|
55
|
+
|
|
52
56
|
const threshold = opts.threshold ?? 0;
|
|
57
|
+
|
|
53
58
|
if (opts.enabled && !opts.enabled()) {
|
|
54
59
|
return { scheduled: false, delay: null };
|
|
55
60
|
}
|
|
@@ -57,13 +62,18 @@ function createReconnectManager(opts: ReconnectOptions): ReconnectManager {
|
|
|
57
62
|
if (attempts - threshold >= 0) {
|
|
58
63
|
const after = Math.max(0, attempts - threshold);
|
|
59
64
|
const delay = computeDelay(after);
|
|
65
|
+
|
|
60
66
|
cancel();
|
|
67
|
+
|
|
61
68
|
timer = setTimeout(() => {
|
|
62
69
|
if (opts.enabled && !opts.enabled()) return;
|
|
70
|
+
|
|
63
71
|
opts.onReconnect();
|
|
64
72
|
}, delay);
|
|
73
|
+
|
|
65
74
|
return { scheduled: true, delay };
|
|
66
75
|
}
|
|
76
|
+
|
|
67
77
|
return { scheduled: false, delay: null };
|
|
68
78
|
};
|
|
69
79
|
|
|
@@ -75,12 +85,12 @@ function createReconnectManager(opts: ReconnectOptions): ReconnectManager {
|
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
export interface UseWorkbenchWebsocketOptions {
|
|
78
|
-
baseUrl?: string;
|
|
79
88
|
apiKey?: string;
|
|
89
|
+
baseUrl?: string;
|
|
80
90
|
enabled?: boolean;
|
|
91
|
+
onAlive?: () => void;
|
|
81
92
|
onConnect?: () => void;
|
|
82
93
|
onReconnect?: () => void;
|
|
83
|
-
onAlive?: () => void;
|
|
84
94
|
onRestarting?: () => void;
|
|
85
95
|
}
|
|
86
96
|
|
|
@@ -94,47 +104,59 @@ export function useWorkbenchWebsocket(
|
|
|
94
104
|
): UseWorkbenchWebsocketResult {
|
|
95
105
|
const { baseUrl, apiKey, onConnect, onReconnect, onAlive, onRestarting } = options;
|
|
96
106
|
|
|
107
|
+
const [connected, setConnected] = useState(false);
|
|
108
|
+
const [error, setError] = useState<Error | null>(null);
|
|
109
|
+
|
|
110
|
+
const hasConnectedOnce = useRef(false);
|
|
97
111
|
const manualClose = useRef(false);
|
|
98
|
-
const
|
|
99
|
-
const reconnectManagerRef = useRef<ReturnType<typeof createReconnectManager> | undefined>(
|
|
100
|
-
undefined
|
|
101
|
-
);
|
|
112
|
+
const onAliveRef = useRef(onAlive);
|
|
102
113
|
const onConnectRef = useRef(onConnect);
|
|
103
114
|
const onReconnectRef = useRef(onReconnect);
|
|
104
|
-
const onAliveRef = useRef(onAlive);
|
|
105
115
|
const onRestartingRef = useRef(onRestarting);
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
116
|
+
const reconnectManagerRef = useRef<ReturnType<typeof createReconnectManager> | undefined>(
|
|
117
|
+
undefined
|
|
118
|
+
);
|
|
119
|
+
const wsRef = useRef<WebSocket | undefined>(undefined);
|
|
110
120
|
|
|
111
121
|
// Update refs when callbacks change
|
|
112
122
|
useEffect(() => {
|
|
123
|
+
onAliveRef.current = onAlive;
|
|
113
124
|
onConnectRef.current = onConnect;
|
|
114
125
|
onReconnectRef.current = onReconnect;
|
|
115
|
-
onAliveRef.current = onAlive;
|
|
116
126
|
onRestartingRef.current = onRestarting;
|
|
117
127
|
}, [onConnect, onReconnect, onAlive, onRestarting]);
|
|
118
128
|
|
|
119
129
|
const wsUrl = useCallback(() => {
|
|
120
|
-
if (!baseUrl)
|
|
130
|
+
if (!baseUrl) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
121
134
|
const wsBase = baseUrl.replace(/^http(s?):/, 'ws$1:');
|
|
122
135
|
const url = new URL(`${wsBase}/_agentuity/workbench/ws`);
|
|
136
|
+
|
|
123
137
|
if (apiKey) {
|
|
124
138
|
url.searchParams.set('apiKey', apiKey);
|
|
125
139
|
}
|
|
140
|
+
|
|
126
141
|
return url.toString();
|
|
127
142
|
}, [baseUrl, apiKey]);
|
|
128
143
|
|
|
129
144
|
const connect = useCallback(() => {
|
|
130
|
-
if (manualClose.current || !options.enabled)
|
|
145
|
+
if (manualClose.current || !options.enabled) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
131
149
|
const url = wsUrl();
|
|
132
|
-
|
|
150
|
+
|
|
151
|
+
if (!url) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
133
154
|
|
|
134
155
|
wsRef.current = new WebSocket(url);
|
|
135
156
|
|
|
136
157
|
wsRef.current.onopen = () => {
|
|
137
158
|
reconnectManagerRef.current?.recordSuccess();
|
|
159
|
+
|
|
138
160
|
setConnected(true);
|
|
139
161
|
setError(null);
|
|
140
162
|
|
|
@@ -153,13 +175,17 @@ export function useWorkbenchWebsocket(
|
|
|
153
175
|
|
|
154
176
|
wsRef.current.onclose = (evt) => {
|
|
155
177
|
wsRef.current = undefined;
|
|
178
|
+
|
|
156
179
|
setConnected(false);
|
|
180
|
+
|
|
157
181
|
if (manualClose.current) {
|
|
158
182
|
return;
|
|
159
183
|
}
|
|
184
|
+
|
|
160
185
|
if (evt.code !== 1000) {
|
|
161
186
|
setError(new Error(`WebSocket closed: ${evt.code} ${evt.reason || ''}`));
|
|
162
187
|
}
|
|
188
|
+
|
|
163
189
|
reconnectManagerRef.current?.recordFailure();
|
|
164
190
|
};
|
|
165
191
|
|
|
@@ -172,41 +198,50 @@ export function useWorkbenchWebsocket(
|
|
|
172
198
|
onRestartingRef.current?.();
|
|
173
199
|
}
|
|
174
200
|
};
|
|
175
|
-
}, [wsUrl]);
|
|
201
|
+
}, [wsUrl, options.enabled]);
|
|
176
202
|
|
|
177
203
|
useEffect(() => {
|
|
178
204
|
reconnectManagerRef.current = createReconnectManager({
|
|
179
|
-
onReconnect: connect,
|
|
180
|
-
threshold: 0,
|
|
181
205
|
baseDelay: 500,
|
|
206
|
+
enabled: () => !manualClose.current && !!baseUrl,
|
|
182
207
|
factor: 2,
|
|
183
|
-
maxDelay: 30000,
|
|
184
208
|
jitter: 500,
|
|
185
|
-
|
|
209
|
+
maxDelay: 30000,
|
|
210
|
+
onReconnect: connect,
|
|
211
|
+
threshold: 0,
|
|
186
212
|
});
|
|
213
|
+
|
|
187
214
|
return () => reconnectManagerRef.current?.dispose();
|
|
188
215
|
}, [connect, baseUrl]);
|
|
189
216
|
|
|
190
217
|
const cleanup = useCallback(() => {
|
|
191
218
|
manualClose.current = true;
|
|
219
|
+
|
|
192
220
|
reconnectManagerRef.current?.dispose();
|
|
221
|
+
|
|
193
222
|
const ws = wsRef.current;
|
|
223
|
+
|
|
194
224
|
if (ws) {
|
|
195
|
-
ws.
|
|
196
|
-
ws.onerror = null;
|
|
225
|
+
ws.close();
|
|
197
226
|
ws.onclose = null;
|
|
227
|
+
ws.onerror = null;
|
|
198
228
|
ws.onmessage = null;
|
|
199
|
-
ws.
|
|
229
|
+
ws.onopen = null;
|
|
200
230
|
}
|
|
231
|
+
|
|
201
232
|
wsRef.current = undefined;
|
|
233
|
+
|
|
202
234
|
setConnected(false);
|
|
203
235
|
// Don't reset hasConnectedOnce here - we want to track if we've ever connected
|
|
204
236
|
}, []);
|
|
205
237
|
|
|
206
238
|
useEffect(() => {
|
|
207
|
-
if (!baseUrl)
|
|
239
|
+
if (!baseUrl) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
208
242
|
|
|
209
243
|
manualClose.current = false;
|
|
244
|
+
|
|
210
245
|
connect();
|
|
211
246
|
|
|
212
247
|
return () => {
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
export { default as App } from './components/App';
|
|
2
|
+
export { Chat } from './components/internal/chat';
|
|
3
|
+
export { StatusIndicator } from './components/internal/header';
|
|
4
|
+
export { Schema } from './components/internal/schema';
|
|
5
|
+
export { useWorkbench, WorkbenchProvider } from './components/internal/workbench-provider';
|
|
2
6
|
export type { WorkbenchInstance } from './types';
|
|
3
7
|
export type { ConnectionStatus } from './types/config';
|
|
4
|
-
|
|
5
|
-
// Export components
|
|
6
|
-
export { default as App } from './components/App';
|
|
7
|
-
export { Chat } from './components/internal/Chat';
|
|
8
|
-
export { Schema } from './components/internal/Schema';
|
|
9
|
-
export { StatusIndicator } from './components/internal/Header';
|
|
10
|
-
export { WorkbenchProvider, useWorkbench } from './components/internal/WorkbenchProvider';
|
|
11
|
-
// Export workbench functions
|
|
12
8
|
export { createWorkbench } from './workbench';
|
package/src/lib/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ClassValue, clsx } from 'clsx';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import type { ErrorInfo } from '@/types/config';
|
|
3
4
|
|
|
4
5
|
export function cn(...inputs: ClassValue[]) {
|
|
5
6
|
return twMerge(clsx(inputs));
|
|
@@ -19,8 +20,10 @@ export function parseTokensHeader(header: string): Record<string, number> {
|
|
|
19
20
|
|
|
20
21
|
for (const entry of entries) {
|
|
21
22
|
const [model, countStr] = entry.split(':').map((s) => s.trim());
|
|
23
|
+
|
|
22
24
|
if (model && countStr) {
|
|
23
25
|
const count = Number.parseInt(countStr, 10);
|
|
26
|
+
|
|
24
27
|
if (!Number.isNaN(count)) {
|
|
25
28
|
result[model] = count;
|
|
26
29
|
}
|
|
@@ -44,9 +47,11 @@ export const getProcessEnv = (key: string): string | undefined => {
|
|
|
44
47
|
if (typeof import.meta.env !== 'undefined') {
|
|
45
48
|
return import.meta.env[key];
|
|
46
49
|
}
|
|
50
|
+
|
|
47
51
|
if (typeof process !== 'undefined' && process.env) {
|
|
48
52
|
return process.env[key];
|
|
49
53
|
}
|
|
54
|
+
|
|
50
55
|
return undefined;
|
|
51
56
|
};
|
|
52
57
|
|
|
@@ -57,14 +62,19 @@ export const buildUrl = (
|
|
|
57
62
|
query?: URLSearchParams
|
|
58
63
|
): string => {
|
|
59
64
|
path = path.startsWith('/') ? path : `/${path}`;
|
|
65
|
+
|
|
60
66
|
let url = base.replace(/\/$/, '') + path;
|
|
67
|
+
|
|
61
68
|
if (subpath) {
|
|
62
69
|
subpath = subpath.startsWith('/') ? subpath : `/${subpath}`;
|
|
70
|
+
|
|
63
71
|
url += subpath;
|
|
64
72
|
}
|
|
73
|
+
|
|
65
74
|
if (query) {
|
|
66
75
|
url += `?${query.toString()}`;
|
|
67
76
|
}
|
|
77
|
+
|
|
68
78
|
return url;
|
|
69
79
|
};
|
|
70
80
|
|
|
@@ -80,3 +90,81 @@ export const defaultBaseUrl: string =
|
|
|
80
90
|
getProcessEnv('AGENTUITY_URL') ||
|
|
81
91
|
tryOrigin() ||
|
|
82
92
|
'http://localhost:3500';
|
|
93
|
+
|
|
94
|
+
type SchemaLike = {
|
|
95
|
+
type?: string | string[];
|
|
96
|
+
properties?: Record<string, unknown>;
|
|
97
|
+
[key: string]: unknown;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
function generateEmptyValueForSchema(schema: unknown): unknown {
|
|
101
|
+
if (typeof schema === 'boolean') {
|
|
102
|
+
return schema ? {} : undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (typeof schema !== 'object' || schema === null) {
|
|
106
|
+
return '';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const s = schema as SchemaLike;
|
|
110
|
+
const type = s.type;
|
|
111
|
+
|
|
112
|
+
if (Array.isArray(type)) {
|
|
113
|
+
return generateEmptyValueForSchema({ ...s, type: type[0] });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
switch (type) {
|
|
117
|
+
case 'string':
|
|
118
|
+
return '';
|
|
119
|
+
case 'number':
|
|
120
|
+
case 'integer':
|
|
121
|
+
return 0;
|
|
122
|
+
case 'boolean':
|
|
123
|
+
return false;
|
|
124
|
+
case 'null':
|
|
125
|
+
return null;
|
|
126
|
+
case 'array':
|
|
127
|
+
return [];
|
|
128
|
+
case 'object': {
|
|
129
|
+
const result: Record<string, unknown> = {};
|
|
130
|
+
|
|
131
|
+
if (s.properties) {
|
|
132
|
+
for (const [key, propSchema] of Object.entries(s.properties)) {
|
|
133
|
+
result[key] = generateEmptyValueForSchema(propSchema);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
default:
|
|
140
|
+
if (s.properties) {
|
|
141
|
+
const result: Record<string, unknown> = {};
|
|
142
|
+
|
|
143
|
+
for (const [key, propSchema] of Object.entries(s.properties)) {
|
|
144
|
+
result[key] = generateEmptyValueForSchema(propSchema);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return '';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function generateTemplateFromSchema(schema?: unknown): string {
|
|
155
|
+
if (!schema) return '{}';
|
|
156
|
+
|
|
157
|
+
const template = generateEmptyValueForSchema(schema);
|
|
158
|
+
|
|
159
|
+
return JSON.stringify(template, null, 2);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function formatErrorForCopy(error: ErrorInfo): string {
|
|
163
|
+
return [
|
|
164
|
+
error.code ? `[${error.code}] ${error.message}` : error.message,
|
|
165
|
+
error.stack,
|
|
166
|
+
error.cause ? `Cause: ${JSON.stringify(error.cause, null, 2)}` : null,
|
|
167
|
+
]
|
|
168
|
+
.filter(Boolean)
|
|
169
|
+
.join('\n\n');
|
|
170
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
// This file exports only the server-side createWorkbench function
|
|
3
3
|
// without pulling in browser-side React components
|
|
4
4
|
|
|
5
|
-
export { createWorkbench } from './workbench';
|
|
6
5
|
export type { WorkbenchInstance } from './types';
|
|
6
|
+
export { createWorkbench } from './workbench';
|
package/src/types/config.ts
CHANGED
|
@@ -1,39 +1,46 @@
|
|
|
1
|
-
import type { UIMessage } from 'ai';
|
|
2
1
|
import type { WorkbenchConfig } from '@agentuity/core/workbench';
|
|
2
|
+
import type { UIMessage } from 'ai';
|
|
3
3
|
import type { AgentSchemaData, AgentSchemasResponse } from '../hooks/useAgentSchemas';
|
|
4
4
|
|
|
5
5
|
export interface Agent {
|
|
6
|
+
avatar?: string;
|
|
7
|
+
description?: string;
|
|
6
8
|
id: string;
|
|
7
9
|
name: string;
|
|
8
|
-
description?: string;
|
|
9
|
-
avatar?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export type ConnectionStatus = 'connected' | 'restarting' | 'disconnected';
|
|
13
13
|
|
|
14
14
|
// Context type for the provider
|
|
15
15
|
export interface WorkbenchContextType {
|
|
16
|
-
config: WorkbenchConfig;
|
|
17
16
|
agents: Record<string, AgentSchemaData>;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
submitMessage: (value: string, mode?: 'text' | 'form') => Promise<void>;
|
|
17
|
+
clearAgentState: (agentId: string) => Promise<void>;
|
|
18
|
+
config: WorkbenchConfig;
|
|
19
|
+
connectionStatus: ConnectionStatus;
|
|
20
|
+
env: {
|
|
21
|
+
agentuity: boolean;
|
|
22
|
+
authenticated: boolean;
|
|
23
|
+
cloud: boolean;
|
|
24
|
+
};
|
|
27
25
|
generateSample: (agentId: string) => Promise<string>;
|
|
26
|
+
inputMode: 'text' | 'form';
|
|
28
27
|
isGeneratingSample: boolean;
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
isLoading: boolean;
|
|
29
|
+
messages: UIMessage[];
|
|
30
|
+
refetchSchemas: () => void;
|
|
31
31
|
schemas: AgentSchemasResponse | null;
|
|
32
|
-
schemasLoading: boolean;
|
|
33
32
|
schemasError: Error | null;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
schemasLoading: boolean;
|
|
34
|
+
selectedAgent: string;
|
|
35
|
+
setInputMode: (mode: 'text' | 'form') => void;
|
|
36
|
+
setMessages: (messages: UIMessage[] | ((prev: UIMessage[]) => UIMessage[])) => void;
|
|
37
|
+
setSelectedAgent: (agentId: string) => void;
|
|
38
|
+
submitMessage: (value: string, mode?: 'text' | 'form') => Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ErrorInfo {
|
|
42
|
+
message: string;
|
|
43
|
+
stack?: string;
|
|
44
|
+
code?: string;
|
|
45
|
+
cause?: unknown;
|
|
39
46
|
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export interface ChatProps {
|
|
3
|
-
className?: string;
|
|
4
|
-
schemaOpen: boolean;
|
|
5
|
-
onSchemaToggle: () => void;
|
|
6
|
-
emptyState?: React.ReactNode;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Chat component - conversation and input area (everything except header)
|
|
10
|
-
* Must be used within WorkbenchProvider
|
|
11
|
-
*/
|
|
12
|
-
export declare function Chat({ className: _className, schemaOpen, onSchemaToggle, emptyState }: ChatProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
-
export default Chat;
|
|
14
|
-
//# sourceMappingURL=Chat.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/components/internal/Chat.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAexC,MAAM,WAAW,SAAS;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,SAAS,2CA0KhG;AAED,eAAe,IAAI,CAAC"}
|