@agentuity/workbench 0.0.80 → 0.0.85
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/internal/Chat.d.ts.map +1 -1
- package/dist/components/internal/Chat.js +1 -1
- package/dist/components/internal/Chat.js.map +1 -1
- package/dist/components/internal/InputSection.d.ts.map +1 -1
- package/dist/components/internal/InputSection.js +8 -152
- package/dist/components/internal/InputSection.js.map +1 -1
- package/dist/components/internal/MonacoJsonEditor.d.ts +11 -0
- package/dist/components/internal/MonacoJsonEditor.d.ts.map +1 -0
- package/dist/components/internal/MonacoJsonEditor.js +270 -0
- package/dist/components/internal/MonacoJsonEditor.js.map +1 -0
- package/dist/components/internal/Schema.d.ts.map +1 -1
- package/dist/components/internal/Schema.js +1 -1
- package/dist/components/internal/Schema.js.map +1 -1
- package/dist/components/internal/WorkbenchProvider.d.ts.map +1 -1
- package/dist/components/internal/WorkbenchProvider.js +6 -3
- package/dist/components/internal/WorkbenchProvider.js.map +1 -1
- package/dist/components/ui/field.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +60 -0
- package/package.json +4 -4
- package/src/components/internal/Chat.tsx +3 -1
- package/src/components/internal/InputSection.tsx +65 -209
- package/src/components/internal/MonacoJsonEditor.tsx +359 -0
- package/src/components/internal/Schema.tsx +2 -1
- package/src/components/internal/WorkbenchProvider.tsx +8 -3
- package/src/index.ts +1 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import Editor, { type Monaco, type OnMount } from '@monaco-editor/react';
|
|
3
|
+
import { useTheme } from '../ui/theme-provider';
|
|
4
|
+
import { bundledThemes } from 'shiki';
|
|
5
|
+
import type { JSONSchema7 } from 'ai';
|
|
6
|
+
|
|
7
|
+
interface MonacoJsonEditorProps {
|
|
8
|
+
value: string;
|
|
9
|
+
onChange: (value: string) => void;
|
|
10
|
+
schema?: JSONSchema7;
|
|
11
|
+
schemaUri?: string;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Convert color value to valid hex for Monaco
|
|
16
|
+
function normalizeColorForMonaco(color: string | undefined, isDark: boolean): string {
|
|
17
|
+
if (!color) return isDark ? 'abb2bf' : '383a42'; // Default foreground colors
|
|
18
|
+
|
|
19
|
+
// Remove # prefix if present
|
|
20
|
+
let normalized = color.replace('#', '');
|
|
21
|
+
|
|
22
|
+
// Handle common color names that might appear in themes
|
|
23
|
+
const colorMap: Record<string, string> = {
|
|
24
|
+
white: isDark ? 'ffffff' : '383a42',
|
|
25
|
+
black: isDark ? '000000' : 'abb2bf',
|
|
26
|
+
red: 'e45649',
|
|
27
|
+
green: '50a14f',
|
|
28
|
+
blue: '4078f2',
|
|
29
|
+
yellow: '986801',
|
|
30
|
+
cyan: '0184bc',
|
|
31
|
+
magenta: 'a626a4',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (colorMap[normalized.toLowerCase()]) {
|
|
35
|
+
normalized = colorMap[normalized.toLowerCase()];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Validate it's a proper hex color (3 or 6 characters)
|
|
39
|
+
if (!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$/.test(normalized)) {
|
|
40
|
+
return isDark ? 'abb2bf' : '383a42'; // Fallback to default
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return normalized;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Convert Shiki theme to Monaco theme
|
|
47
|
+
function convertShikiToMonaco(
|
|
48
|
+
shikiTheme: {
|
|
49
|
+
colors?: Record<string, string>;
|
|
50
|
+
tokenColors?: Array<{
|
|
51
|
+
scope?: string | string[];
|
|
52
|
+
settings?: { foreground?: string; fontStyle?: string };
|
|
53
|
+
}>;
|
|
54
|
+
},
|
|
55
|
+
themeName: string
|
|
56
|
+
) {
|
|
57
|
+
const colors = shikiTheme.colors || {};
|
|
58
|
+
const tokenColors = shikiTheme.tokenColors || [];
|
|
59
|
+
const isDark = themeName.includes('dark');
|
|
60
|
+
|
|
61
|
+
// Convert token colors to Monaco rules
|
|
62
|
+
const rules: Array<{ token: string; foreground: string; fontStyle?: string }> = [];
|
|
63
|
+
tokenColors.forEach((tokenColor) => {
|
|
64
|
+
if (tokenColor.scope && tokenColor.settings?.foreground) {
|
|
65
|
+
const scopes = Array.isArray(tokenColor.scope) ? tokenColor.scope : [tokenColor.scope];
|
|
66
|
+
scopes.forEach((scope: string) => {
|
|
67
|
+
// Map common scopes to Monaco tokens
|
|
68
|
+
let token = scope;
|
|
69
|
+
if (scope.includes('string.quoted.double.json')) token = 'string.value.json';
|
|
70
|
+
if (scope.includes('support.type.property-name.json')) token = 'string.key.json';
|
|
71
|
+
if (scope.includes('constant.numeric.json')) token = 'number.json';
|
|
72
|
+
if (scope.includes('constant.language.json')) token = 'keyword.json';
|
|
73
|
+
if (scope.includes('punctuation.definition.string.json'))
|
|
74
|
+
token = 'delimiter.bracket.json';
|
|
75
|
+
|
|
76
|
+
const normalizedColor = normalizeColorForMonaco(
|
|
77
|
+
tokenColor.settings?.foreground,
|
|
78
|
+
isDark
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
rules.push({
|
|
82
|
+
token,
|
|
83
|
+
foreground: normalizedColor,
|
|
84
|
+
fontStyle: tokenColor.settings?.fontStyle || undefined,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
base: isDark ? 'vs-dark' : 'vs',
|
|
92
|
+
inherit: true,
|
|
93
|
+
rules,
|
|
94
|
+
colors: {
|
|
95
|
+
'editor.background': '#00000000', // Always transparent
|
|
96
|
+
'editor.foreground': normalizeColorForMonaco(colors['editor.foreground'], isDark),
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function MonacoJsonEditor({
|
|
102
|
+
value,
|
|
103
|
+
onChange,
|
|
104
|
+
schema,
|
|
105
|
+
schemaUri = 'agentuity://schema/default',
|
|
106
|
+
className = '',
|
|
107
|
+
}: MonacoJsonEditorProps) {
|
|
108
|
+
const { theme } = useTheme();
|
|
109
|
+
const [editorInstance, setEditorInstance] = useState<Parameters<OnMount>[0] | null>(null);
|
|
110
|
+
const [monacoInstance, setMonacoInstance] = useState<Monaco | null>(null);
|
|
111
|
+
const [editorHeight, setEditorHeight] = useState(120);
|
|
112
|
+
|
|
113
|
+
// Get resolved theme (similar to useTheme's resolvedTheme from next-themes)
|
|
114
|
+
const resolvedTheme = React.useMemo(() => {
|
|
115
|
+
if (theme === 'system') {
|
|
116
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
117
|
+
}
|
|
118
|
+
return theme;
|
|
119
|
+
}, [theme]);
|
|
120
|
+
|
|
121
|
+
// Configure JSON schema when schema or monacoInstance changes
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (!monacoInstance || !schema) return;
|
|
124
|
+
|
|
125
|
+
const schemaObject = typeof schema === 'string' ? JSON.parse(schema) : schema;
|
|
126
|
+
|
|
127
|
+
// Configure Monaco JSON language support for schema validation
|
|
128
|
+
monacoInstance.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
129
|
+
validate: true,
|
|
130
|
+
schemas: [
|
|
131
|
+
{
|
|
132
|
+
uri: schemaUri,
|
|
133
|
+
fileMatch: ['*'],
|
|
134
|
+
schema: schemaObject,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
});
|
|
138
|
+
}, [monacoInstance, schema, schemaUri]);
|
|
139
|
+
|
|
140
|
+
// Handle theme changes for existing editor instance
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (editorInstance && monacoInstance) {
|
|
143
|
+
editorInstance.updateOptions({
|
|
144
|
+
theme: resolvedTheme === 'light' ? 'custom-light' : 'custom-dark',
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}, [resolvedTheme, editorInstance, monacoInstance]);
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<div
|
|
151
|
+
className={`w-full pl-3 pb-3 [&_.monaco-editor]:!bg-transparent [&_.monaco-editor-background]:!bg-transparent [&_.view-lines]:!bg-transparent [&_.monaco-editor]:!shadow-none [&_.monaco-scrollable-element]:!shadow-none [&_.overflow-guard]:!shadow-none [&_.monaco-scrollable-element>.shadow.top]:!hidden [&_.monaco-editor_.scroll-decoration]:!hidden [&_.shadow.top]:!hidden [&_.scroll-decoration]:!hidden ${className}`}
|
|
152
|
+
style={{ minHeight: '64px', maxHeight: '192px', height: `${editorHeight}px` }}
|
|
153
|
+
>
|
|
154
|
+
<Editor
|
|
155
|
+
value={value || '{}'}
|
|
156
|
+
onChange={(newValue) => onChange(newValue || '')}
|
|
157
|
+
language="json"
|
|
158
|
+
theme={resolvedTheme === 'light' ? 'custom-light' : 'custom-dark'}
|
|
159
|
+
height="100%"
|
|
160
|
+
options={{
|
|
161
|
+
minimap: { enabled: false },
|
|
162
|
+
lineNumbers: 'off',
|
|
163
|
+
folding: false,
|
|
164
|
+
scrollBeyondLastLine: false,
|
|
165
|
+
wordWrap: 'on',
|
|
166
|
+
renderLineHighlight: 'none',
|
|
167
|
+
overviewRulerBorder: false,
|
|
168
|
+
overviewRulerLanes: 0,
|
|
169
|
+
hideCursorInOverviewRuler: true,
|
|
170
|
+
fixedOverflowWidgets: true,
|
|
171
|
+
roundedSelection: false,
|
|
172
|
+
occurrencesHighlight: 'off',
|
|
173
|
+
selectionHighlight: false,
|
|
174
|
+
renderWhitespace: 'none',
|
|
175
|
+
fontSize: 14,
|
|
176
|
+
fontWeight: '400',
|
|
177
|
+
formatOnPaste: true,
|
|
178
|
+
formatOnType: true,
|
|
179
|
+
autoIndent: 'full',
|
|
180
|
+
glyphMargin: false,
|
|
181
|
+
lineDecorationsWidth: 0,
|
|
182
|
+
lineNumbersMinChars: 0,
|
|
183
|
+
automaticLayout: true,
|
|
184
|
+
scrollbar: {
|
|
185
|
+
vertical: 'auto',
|
|
186
|
+
horizontal: 'auto',
|
|
187
|
+
verticalScrollbarSize: 10,
|
|
188
|
+
horizontalScrollbarSize: 10,
|
|
189
|
+
// Disable scroll shadows
|
|
190
|
+
verticalHasArrows: false,
|
|
191
|
+
horizontalHasArrows: false,
|
|
192
|
+
},
|
|
193
|
+
padding: { top: 12, bottom: 12 },
|
|
194
|
+
// Additional background transparency options
|
|
195
|
+
renderValidationDecorations: 'off',
|
|
196
|
+
guides: {
|
|
197
|
+
indentation: false,
|
|
198
|
+
highlightActiveIndentation: false,
|
|
199
|
+
},
|
|
200
|
+
// Disable sticky scroll feature
|
|
201
|
+
stickyScroll: { enabled: false },
|
|
202
|
+
// Disable scroll decorations/shadows
|
|
203
|
+
scrollBeyondLastColumn: 0,
|
|
204
|
+
renderLineHighlightOnlyWhenFocus: true,
|
|
205
|
+
}}
|
|
206
|
+
onMount={(editor, monaco) => {
|
|
207
|
+
setEditorInstance(editor);
|
|
208
|
+
setMonacoInstance(monaco);
|
|
209
|
+
editor.focus();
|
|
210
|
+
|
|
211
|
+
// Auto-resize based on content
|
|
212
|
+
const updateHeight = () => {
|
|
213
|
+
const contentHeight = editor.getContentHeight();
|
|
214
|
+
const maxHeight = 192; // max-h-48 = 12rem = 192px
|
|
215
|
+
const minHeight = 64; // min-h-16 = 4rem = 64px
|
|
216
|
+
const newHeight = Math.min(Math.max(contentHeight + 24, minHeight), maxHeight);
|
|
217
|
+
setEditorHeight(newHeight);
|
|
218
|
+
|
|
219
|
+
// Layout after height change
|
|
220
|
+
setTimeout(() => editor.layout(), 0);
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// Update height on content changes
|
|
224
|
+
editor.onDidChangeModelContent(updateHeight);
|
|
225
|
+
|
|
226
|
+
// Initial height update
|
|
227
|
+
setTimeout(updateHeight, 0);
|
|
228
|
+
|
|
229
|
+
// Ensure background transparency and remove shadows
|
|
230
|
+
setTimeout(() => {
|
|
231
|
+
const editorElement = editor.getDomNode();
|
|
232
|
+
if (editorElement) {
|
|
233
|
+
// Set transparent backgrounds on all relevant elements
|
|
234
|
+
const elementsToMakeTransparent = [
|
|
235
|
+
'.monaco-editor',
|
|
236
|
+
'.monaco-editor .monaco-editor-background',
|
|
237
|
+
'.monaco-editor .view-lines',
|
|
238
|
+
'.monaco-editor .margin',
|
|
239
|
+
'.monaco-editor .monaco-scrollable-element',
|
|
240
|
+
'.monaco-editor .overflow-guard',
|
|
241
|
+
'.view-overlays',
|
|
242
|
+
'.decorationsOverviewRuler',
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
elementsToMakeTransparent.forEach((selector) => {
|
|
246
|
+
const element = editorElement.querySelector(selector);
|
|
247
|
+
if (element) {
|
|
248
|
+
(element as HTMLElement).style.backgroundColor = 'transparent';
|
|
249
|
+
(element as HTMLElement).style.boxShadow = 'none';
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Remove scroll shadows specifically - target the exact classes
|
|
254
|
+
const shadowTop = editorElement.querySelector(
|
|
255
|
+
'.monaco-scrollable-element > .shadow.top'
|
|
256
|
+
);
|
|
257
|
+
if (shadowTop) {
|
|
258
|
+
(shadowTop as HTMLElement).style.display = 'none';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const scrollDecorations = editorElement.querySelectorAll(
|
|
262
|
+
'.monaco-editor .scroll-decoration, .scroll-decoration'
|
|
263
|
+
);
|
|
264
|
+
scrollDecorations.forEach((decoration) => {
|
|
265
|
+
(decoration as HTMLElement).style.display = 'none';
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const scrollableElement = editorElement.querySelector(
|
|
269
|
+
'.monaco-scrollable-element'
|
|
270
|
+
);
|
|
271
|
+
if (scrollableElement) {
|
|
272
|
+
(scrollableElement as HTMLElement).style.setProperty(
|
|
273
|
+
'--scroll-shadow',
|
|
274
|
+
'none'
|
|
275
|
+
);
|
|
276
|
+
(scrollableElement as HTMLElement).style.setProperty(
|
|
277
|
+
'box-shadow',
|
|
278
|
+
'none',
|
|
279
|
+
'important'
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Also set transparent and remove shadow on the editor element itself
|
|
284
|
+
(editorElement as HTMLElement).style.backgroundColor = 'transparent';
|
|
285
|
+
(editorElement as HTMLElement).style.boxShadow = 'none';
|
|
286
|
+
}
|
|
287
|
+
}, 0);
|
|
288
|
+
}}
|
|
289
|
+
beforeMount={async (monaco) => {
|
|
290
|
+
setMonacoInstance(monaco);
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
// Try to use actual Shiki themes
|
|
294
|
+
const oneLightThemeModule = await bundledThemes['one-light']();
|
|
295
|
+
const oneDarkProThemeModule = await bundledThemes['one-dark-pro']();
|
|
296
|
+
|
|
297
|
+
if (oneLightThemeModule?.default) {
|
|
298
|
+
const lightMonacoTheme = convertShikiToMonaco(
|
|
299
|
+
oneLightThemeModule.default,
|
|
300
|
+
'one-light'
|
|
301
|
+
);
|
|
302
|
+
monaco.editor.defineTheme('custom-light', lightMonacoTheme);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (oneDarkProThemeModule?.default) {
|
|
306
|
+
const darkMonacoTheme = convertShikiToMonaco(
|
|
307
|
+
oneDarkProThemeModule.default,
|
|
308
|
+
'one-dark-pro'
|
|
309
|
+
);
|
|
310
|
+
monaco.editor.defineTheme('custom-dark', darkMonacoTheme);
|
|
311
|
+
}
|
|
312
|
+
} catch (error) {
|
|
313
|
+
console.warn(
|
|
314
|
+
'Failed to load Shiki themes, falling back to manual themes:',
|
|
315
|
+
error
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// Fallback to manual theme definitions
|
|
319
|
+
monaco.editor.defineTheme('custom-light', {
|
|
320
|
+
base: 'vs',
|
|
321
|
+
inherit: true,
|
|
322
|
+
rules: [
|
|
323
|
+
{ token: 'string.key.json', foreground: 'e45649' },
|
|
324
|
+
{ token: 'string.value.json', foreground: '50a14f' },
|
|
325
|
+
{ token: 'number.json', foreground: '986801' },
|
|
326
|
+
{ token: 'keyword.json', foreground: '986801' },
|
|
327
|
+
{ token: 'string', foreground: '50a14f' },
|
|
328
|
+
{ token: 'number', foreground: '986801' },
|
|
329
|
+
{ token: 'keyword', foreground: '986801' },
|
|
330
|
+
],
|
|
331
|
+
colors: {
|
|
332
|
+
'editor.background': '#00000000',
|
|
333
|
+
'editor.foreground': '#383a42',
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
monaco.editor.defineTheme('custom-dark', {
|
|
338
|
+
base: 'vs-dark',
|
|
339
|
+
inherit: true,
|
|
340
|
+
rules: [
|
|
341
|
+
{ token: 'string.key.json', foreground: 'e06c75' },
|
|
342
|
+
{ token: 'string.value.json', foreground: '98c379' },
|
|
343
|
+
{ token: 'number.json', foreground: 'd19a66' },
|
|
344
|
+
{ token: 'keyword.json', foreground: 'c678dd' },
|
|
345
|
+
{ token: 'string', foreground: '98c379' },
|
|
346
|
+
{ token: 'number', foreground: 'd19a66' },
|
|
347
|
+
{ token: 'keyword', foreground: 'c678dd' },
|
|
348
|
+
],
|
|
349
|
+
colors: {
|
|
350
|
+
'editor.background': '#00000000',
|
|
351
|
+
'editor.foreground': '#abb2bf',
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}}
|
|
356
|
+
/>
|
|
357
|
+
</div>
|
|
358
|
+
);
|
|
359
|
+
}
|
|
@@ -14,7 +14,8 @@ export interface SchemaProps {
|
|
|
14
14
|
export function Schema({ open, onOpenChange }: SchemaProps) {
|
|
15
15
|
const { agents, selectedAgent, schemasLoading, schemasError } = useWorkbench();
|
|
16
16
|
|
|
17
|
-
const selectedAgentData =
|
|
17
|
+
const selectedAgentData =
|
|
18
|
+
Object.values(agents).find((agent) => agent.metadata.agentId === selectedAgent) || null;
|
|
18
19
|
|
|
19
20
|
return (
|
|
20
21
|
<>
|
|
@@ -103,8 +103,11 @@ export function WorkbenchProvider({ config, children }: WorkbenchProviderProps)
|
|
|
103
103
|
useEffect(() => {
|
|
104
104
|
if (agents && Object.keys(agents).length > 0 && !selectedAgent) {
|
|
105
105
|
logger.debug('🔍 Available agents:', agents);
|
|
106
|
-
const
|
|
107
|
-
|
|
106
|
+
const sortedAgents = Object.values(agents).sort((a, b) =>
|
|
107
|
+
a.metadata.name.localeCompare(b.metadata.name)
|
|
108
|
+
);
|
|
109
|
+
const firstAgent = sortedAgents[0];
|
|
110
|
+
logger.debug('🎯 First agent (alphabetically):', firstAgent);
|
|
108
111
|
logger.debug('🆔 Setting selectedAgent to:', firstAgent.metadata.agentId);
|
|
109
112
|
setSelectedAgent(firstAgent.metadata.agentId);
|
|
110
113
|
}
|
|
@@ -123,7 +126,9 @@ export function WorkbenchProvider({ config, children }: WorkbenchProviderProps)
|
|
|
123
126
|
if (!selectedAgent) return;
|
|
124
127
|
|
|
125
128
|
logger.debug('🚀 Submitting message with selectedAgent:', selectedAgent);
|
|
126
|
-
const selectedAgentData = agents
|
|
129
|
+
const selectedAgentData = agents
|
|
130
|
+
? Object.values(agents).find((agent) => agent.metadata.agentId === selectedAgent)
|
|
131
|
+
: undefined;
|
|
127
132
|
logger.debug('📊 Found selectedAgentData:', selectedAgentData);
|
|
128
133
|
const hasInputSchema = selectedAgentData?.schema?.input?.json;
|
|
129
134
|
logger.debug('📝 hasInputSchema:', hasInputSchema, 'value:', value);
|
package/src/index.ts
CHANGED
|
@@ -16,4 +16,5 @@ export { Input } from './components/ui/input';
|
|
|
16
16
|
// Export components
|
|
17
17
|
export { default as App } from './components/App';
|
|
18
18
|
export { default as Inline } from './components/Inline';
|
|
19
|
+
export { MonacoJsonEditor } from './components/internal/MonacoJsonEditor';
|
|
19
20
|
export { createWorkbench } from './workbench';
|