@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.
Files changed (171) hide show
  1. package/dist/components/App.d.ts.map +1 -1
  2. package/dist/components/App.js +15 -13
  3. package/dist/components/App.js.map +1 -1
  4. package/dist/components/ai-elements/actions.d.ts +1 -1
  5. package/dist/components/ai-elements/actions.d.ts.map +1 -1
  6. package/dist/components/ai-elements/actions.js +1 -1
  7. package/dist/components/ai-elements/actions.js.map +1 -1
  8. package/dist/components/ai-elements/code-block.d.ts +1 -1
  9. package/dist/components/ai-elements/code-block.d.ts.map +1 -1
  10. package/dist/components/ai-elements/code-block.js +22 -20
  11. package/dist/components/ai-elements/code-block.js.map +1 -1
  12. package/dist/components/ai-elements/conversation.d.ts +2 -2
  13. package/dist/components/ai-elements/conversation.d.ts.map +1 -1
  14. package/dist/components/ai-elements/conversation.js +5 -3
  15. package/dist/components/ai-elements/conversation.js.map +1 -1
  16. package/dist/components/ai-elements/message.d.ts +1 -1
  17. package/dist/components/ai-elements/message.d.ts.map +1 -1
  18. package/dist/components/ai-elements/message.js +4 -9
  19. package/dist/components/ai-elements/message.js.map +1 -1
  20. package/dist/components/ai-elements/prompt-input.d.ts.map +1 -1
  21. package/dist/components/ai-elements/prompt-input.js +1 -1
  22. package/dist/components/ai-elements/prompt-input.js.map +1 -1
  23. package/dist/components/ai-elements/shimmer.d.ts.map +1 -1
  24. package/dist/components/ai-elements/shimmer.js +1 -1
  25. package/dist/components/ai-elements/shimmer.js.map +1 -1
  26. package/dist/components/internal/chat.d.ts +10 -0
  27. package/dist/components/internal/chat.d.ts.map +1 -0
  28. package/dist/components/internal/chat.js +104 -0
  29. package/dist/components/internal/chat.js.map +1 -0
  30. package/dist/components/internal/{Header.d.ts → header.d.ts} +4 -6
  31. package/dist/components/internal/header.d.ts.map +1 -0
  32. package/dist/components/internal/header.js +25 -0
  33. package/dist/components/internal/header.js.map +1 -0
  34. package/dist/components/internal/{InputSection.d.ts → input-section.d.ts} +9 -9
  35. package/dist/components/internal/input-section.d.ts.map +1 -0
  36. package/dist/components/internal/input-section.js +162 -0
  37. package/dist/components/internal/input-section.js.map +1 -0
  38. package/dist/components/internal/json-editor.d.ts +14 -0
  39. package/dist/components/internal/json-editor.d.ts.map +1 -0
  40. package/dist/components/internal/{MonacoJsonEditor.js → json-editor.js} +40 -37
  41. package/dist/components/internal/json-editor.js.map +1 -0
  42. package/dist/components/internal/logo.d.ts +2 -3
  43. package/dist/components/internal/logo.d.ts.map +1 -1
  44. package/dist/components/internal/logo.js +2 -2
  45. package/dist/components/internal/logo.js.map +1 -1
  46. package/dist/components/internal/resizable-provider.d.ts.map +1 -0
  47. package/dist/components/internal/resizable-provider.js.map +1 -0
  48. package/dist/components/internal/{Schema.d.ts → schema.d.ts} +2 -2
  49. package/dist/components/internal/schema.d.ts.map +1 -0
  50. package/dist/components/internal/schema.js +13 -0
  51. package/dist/components/internal/schema.js.map +1 -0
  52. package/dist/components/internal/{WorkbenchProvider.d.ts → workbench-provider.d.ts} +8 -4
  53. package/dist/components/internal/workbench-provider.d.ts.map +1 -0
  54. package/dist/components/internal/{WorkbenchProvider.js → workbench-provider.js} +87 -60
  55. package/dist/components/internal/workbench-provider.js.map +1 -0
  56. package/dist/components/ui/avatar.d.ts +1 -1
  57. package/dist/components/ui/avatar.d.ts.map +1 -1
  58. package/dist/components/ui/avatar.js.map +1 -1
  59. package/dist/components/ui/button.d.ts +1 -1
  60. package/dist/components/ui/command.d.ts +1 -1
  61. package/dist/components/ui/command.d.ts.map +1 -1
  62. package/dist/components/ui/command.js.map +1 -1
  63. package/dist/components/ui/dialog.d.ts +1 -1
  64. package/dist/components/ui/dialog.d.ts.map +1 -1
  65. package/dist/components/ui/dialog.js.map +1 -1
  66. package/dist/components/ui/dropdown-menu.d.ts +1 -1
  67. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  68. package/dist/components/ui/dropdown-menu.js.map +1 -1
  69. package/dist/components/ui/hover-card.d.ts +1 -1
  70. package/dist/components/ui/hover-card.d.ts.map +1 -1
  71. package/dist/components/ui/hover-card.js.map +1 -1
  72. package/dist/components/ui/input-group.d.ts +2 -2
  73. package/dist/components/ui/input-group.d.ts.map +1 -1
  74. package/dist/components/ui/input-group.js.map +1 -1
  75. package/dist/components/ui/input.d.ts +1 -1
  76. package/dist/components/ui/input.d.ts.map +1 -1
  77. package/dist/components/ui/scroll-area.d.ts +1 -1
  78. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  79. package/dist/components/ui/scroll-area.js.map +1 -1
  80. package/dist/components/ui/textarea.d.ts +1 -1
  81. package/dist/components/ui/textarea.d.ts.map +1 -1
  82. package/dist/components/ui/theme-provider.d.ts.map +1 -1
  83. package/dist/components/ui/theme-provider.js +1 -1
  84. package/dist/components/ui/theme-provider.js.map +1 -1
  85. package/dist/components/ui/tooltip.d.ts +1 -1
  86. package/dist/components/ui/tooltip.d.ts.map +1 -1
  87. package/dist/components/ui/tooltip.js.map +1 -1
  88. package/dist/hooks/useAgentSchemas.d.ts +10 -10
  89. package/dist/hooks/useAgentSchemas.d.ts.map +1 -1
  90. package/dist/hooks/useAgentSchemas.js +9 -7
  91. package/dist/hooks/useAgentSchemas.js.map +1 -1
  92. package/dist/hooks/useLogger.d.ts.map +1 -1
  93. package/dist/hooks/useLogger.js +2 -1
  94. package/dist/hooks/useLogger.js.map +1 -1
  95. package/dist/hooks/useWorkbenchWebsocket.d.ts +2 -2
  96. package/dist/hooks/useWorkbenchWebsocket.d.ts.map +1 -1
  97. package/dist/hooks/useWorkbenchWebsocket.js +24 -20
  98. package/dist/hooks/useWorkbenchWebsocket.js.map +1 -1
  99. package/dist/index.d.ts +5 -5
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +4 -6
  102. package/dist/index.js.map +1 -1
  103. package/dist/lib/utils.d.ts +3 -0
  104. package/dist/lib/utils.d.ts.map +1 -1
  105. package/dist/lib/utils.js +59 -0
  106. package/dist/lib/utils.js.map +1 -1
  107. package/dist/server.d.ts +1 -1
  108. package/dist/server.d.ts.map +1 -1
  109. package/dist/server.js.map +1 -1
  110. package/dist/standalone.css +360 -295
  111. package/dist/types/config.d.ts +27 -18
  112. package/dist/types/config.d.ts.map +1 -1
  113. package/package.json +5 -5
  114. package/src/base.css +186 -158
  115. package/src/components/App.tsx +31 -16
  116. package/src/components/ai-elements/actions.tsx +2 -2
  117. package/src/components/ai-elements/code-block.tsx +46 -32
  118. package/src/components/ai-elements/conversation.tsx +18 -17
  119. package/src/components/ai-elements/message.tsx +4 -9
  120. package/src/components/ai-elements/prompt-input.tsx +1 -1
  121. package/src/components/ai-elements/shimmer.tsx +1 -1
  122. package/src/components/internal/chat.tsx +326 -0
  123. package/src/components/internal/{Header.tsx → header.tsx} +37 -40
  124. package/src/components/internal/{InputSection.tsx → input-section.tsx} +173 -119
  125. package/src/components/internal/{MonacoJsonEditor.tsx → json-editor.tsx} +77 -49
  126. package/src/components/internal/logo.tsx +3 -5
  127. package/src/components/internal/schema.tsx +96 -0
  128. package/src/components/internal/{WorkbenchProvider.tsx → workbench-provider.tsx} +194 -68
  129. package/src/components/ui/avatar.tsx +1 -1
  130. package/src/components/ui/command.tsx +1 -1
  131. package/src/components/ui/dialog.tsx +1 -1
  132. package/src/components/ui/dropdown-menu.tsx +1 -1
  133. package/src/components/ui/hover-card.tsx +1 -1
  134. package/src/components/ui/input-group.tsx +1 -1
  135. package/src/components/ui/input.tsx +1 -1
  136. package/src/components/ui/scroll-area.tsx +1 -1
  137. package/src/components/ui/textarea.tsx +1 -1
  138. package/src/components/ui/theme-provider.tsx +1 -1
  139. package/src/components/ui/tooltip.tsx +1 -1
  140. package/src/hooks/useAgentSchemas.ts +26 -15
  141. package/src/hooks/useLogger.ts +7 -1
  142. package/src/hooks/useWorkbenchWebsocket.ts +67 -32
  143. package/src/index.ts +5 -9
  144. package/src/lib/utils.ts +88 -0
  145. package/src/server.ts +1 -1
  146. package/src/types/config.ts +28 -21
  147. package/dist/components/internal/Chat.d.ts +0 -14
  148. package/dist/components/internal/Chat.d.ts.map +0 -1
  149. package/dist/components/internal/Chat.js +0 -61
  150. package/dist/components/internal/Chat.js.map +0 -1
  151. package/dist/components/internal/Header.d.ts.map +0 -1
  152. package/dist/components/internal/Header.js +0 -31
  153. package/dist/components/internal/Header.js.map +0 -1
  154. package/dist/components/internal/InputSection.d.ts.map +0 -1
  155. package/dist/components/internal/InputSection.js +0 -152
  156. package/dist/components/internal/InputSection.js.map +0 -1
  157. package/dist/components/internal/MonacoJsonEditor.d.ts +0 -13
  158. package/dist/components/internal/MonacoJsonEditor.d.ts.map +0 -1
  159. package/dist/components/internal/MonacoJsonEditor.js.map +0 -1
  160. package/dist/components/internal/Schema.d.ts.map +0 -1
  161. package/dist/components/internal/Schema.js +0 -13
  162. package/dist/components/internal/Schema.js.map +0 -1
  163. package/dist/components/internal/WorkbenchProvider.d.ts.map +0 -1
  164. package/dist/components/internal/WorkbenchProvider.js.map +0 -1
  165. package/dist/components/ui/resizable-provider.d.ts.map +0 -1
  166. package/dist/components/ui/resizable-provider.js.map +0 -1
  167. package/src/components/internal/Chat.tsx +0 -201
  168. package/src/components/internal/Schema.tsx +0 -100
  169. /package/dist/components/{ui → internal}/resizable-provider.d.ts +0 -0
  170. /package/dist/components/{ui → internal}/resizable-provider.js +0 -0
  171. /package/src/components/{ui → internal}/resizable-provider.tsx +0 -0
@@ -1,20 +1,50 @@
1
- import React from 'react';
2
1
  import { Settings } from 'lucide-react';
3
- import Logo from './logo';
2
+ import { cn } from '../../lib/utils';
3
+ import type { ConnectionStatus } from '../../types/config';
4
4
  import { Button } from '../ui/button';
5
5
  import { ThemeToggle } from '../ui/theme-toggle';
6
- import { useWorkbench } from './WorkbenchProvider';
7
- import type { ConnectionStatus } from '../../types/config';
6
+ import Logo from './logo';
7
+ import { useWorkbench } from './workbench-provider';
8
8
 
9
9
  export interface HeaderProps {
10
10
  className?: string;
11
+ title?: string;
12
+ showSettings?: boolean;
13
+ }
14
+
15
+ export function Header({ className, title = 'Workbench', showSettings = false }: HeaderProps) {
16
+ const { connectionStatus } = useWorkbench();
17
+
18
+ return (
19
+ <nav className={cn('flex items-center justify-between gap-6 py-2 px-4 border-b', className)}>
20
+ <div className="flex items-center gap-2.5">
21
+ <Logo />
22
+
23
+ <h1 className="text-sm">{title}</h1>
24
+ </div>
25
+
26
+ <div className="flex items-center gap-3">
27
+ <StatusIndicator status={connectionStatus} />
28
+
29
+ <div className="flex items-center gap-1">
30
+ <ThemeToggle />
31
+
32
+ {showSettings && (
33
+ <Button size="icon" variant="ghost">
34
+ <Settings />
35
+ </Button>
36
+ )}
37
+ </div>
38
+ </div>
39
+ </nav>
40
+ );
11
41
  }
12
42
 
13
43
  export function StatusIndicator({ status }: { status: ConnectionStatus }) {
14
44
  if (status === 'connected') {
15
45
  return (
16
46
  <div className="flex items-center gap-1.5 text-xs text-green-600 dark:text-green-400">
17
- <div className="w-2 h-2 rounded-full bg-green-500 animate-pulse"></div>
47
+ <div className="size-2 rounded-full bg-green-500 animate-pulse"></div>
18
48
  <span>Connected</span>
19
49
  </div>
20
50
  );
@@ -23,7 +53,7 @@ export function StatusIndicator({ status }: { status: ConnectionStatus }) {
23
53
  if (status === 'restarting') {
24
54
  return (
25
55
  <div className="flex items-center gap-1.5 text-xs text-amber-600 dark:text-amber-400">
26
- <div className="w-2 h-2 rounded-full bg-amber-500 animate-spin"></div>
56
+ <div className="size-2 rounded-full bg-amber-500 animate-pulse"></div>
27
57
  <span>Restarting...</span>
28
58
  </div>
29
59
  );
@@ -32,7 +62,7 @@ export function StatusIndicator({ status }: { status: ConnectionStatus }) {
32
62
  if (status === 'disconnected') {
33
63
  return (
34
64
  <div className="flex items-center gap-1.5 text-xs text-red-600 dark:text-red-400">
35
- <div className="w-2 h-2 rounded-full bg-red-500"></div>
65
+ <div className="size-2 rounded-full bg-red-500"></div>
36
66
  <span>Disconnected</span>
37
67
  </div>
38
68
  );
@@ -41,37 +71,4 @@ export function StatusIndicator({ status }: { status: ConnectionStatus }) {
41
71
  return null;
42
72
  }
43
73
 
44
- /**
45
- * Header component - navigation bar with logo, title, and settings
46
- * Must be used within WorkbenchProvider
47
- */
48
- export function Header({ className }: HeaderProps) {
49
- const { connectionStatus } = useWorkbench();
50
- const LogoComponent = Logo;
51
- const title = 'Workbench';
52
- const showSettings = true;
53
-
54
- return (
55
- <nav
56
- className={`flex items-center justify-between gap-6 py-2 px-4 border-b ${className || ''}`}
57
- >
58
- <div className="flex items-center gap-2.5">
59
- <LogoComponent />
60
- <h1 className="mt-0.5 text-sm">{title}</h1>
61
- </div>
62
- <div className="flex items-center gap-3">
63
- <StatusIndicator status={connectionStatus} />
64
- <div className="flex items-center gap-1">
65
- <ThemeToggle />
66
- {showSettings && (
67
- <Button size="icon" variant="ghost">
68
- <Settings />
69
- </Button>
70
- )}
71
- </div>
72
- </div>
73
- </nav>
74
- );
75
- }
76
-
77
74
  export default Header;
@@ -1,14 +1,22 @@
1
- import React, { useMemo, useState, useCallback, useEffect } from 'react';
1
+ import type { JSONSchema7 } from 'ai';
2
2
  import {
3
+ ArrowUp,
4
+ Braces,
3
5
  CheckIcon,
6
+ ChevronDownIcon,
4
7
  ChevronsUpDownIcon,
5
- FileJson,
6
- SendIcon,
8
+ ListPlus,
7
9
  Loader2Icon,
10
+ SendIcon,
8
11
  Sparkles,
12
+ SquareCode,
9
13
  Trash2,
10
14
  } from 'lucide-react';
11
- import { MonacoJsonEditor } from './MonacoJsonEditor';
15
+ import { useCallback, useEffect, useMemo, useState } from 'react';
16
+ import { convertJsonSchemaToZod } from 'zod-from-json-schema';
17
+ import type { AgentSchemaData } from '../../hooks/useAgentSchemas';
18
+ import { useLogger } from '../../hooks/useLogger';
19
+ import { cn, generateTemplateFromSchema } from '../../lib/utils';
12
20
  import {
13
21
  PromptInput,
14
22
  PromptInputBody,
@@ -25,31 +33,27 @@ import {
25
33
  CommandList,
26
34
  } from '../ui/command';
27
35
  import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
28
- import { Select, SelectContent, SelectItem, SelectTrigger } from '../ui/select';
29
36
  import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
30
- import { cn } from '../../lib/utils';
31
- import type { AgentSchemaData } from '../../hooks/useAgentSchemas';
32
- import { useLogger } from '../../hooks/useLogger';
33
- import type { JSONSchema7 } from 'ai';
34
- import { useWorkbench } from './WorkbenchProvider';
35
- import { convertJsonSchemaToZod } from 'zod-from-json-schema';
37
+ import { JsonEditor } from './json-editor';
38
+ import { useWorkbench } from './workbench-provider';
36
39
 
37
40
  export interface InputSectionProps {
38
- value: string;
41
+ agents: Record<string, AgentSchemaData>;
42
+ className?: string;
43
+ clearAgentState?: (agentId: string) => Promise<void>;
44
+ isLoading: boolean;
45
+ isSchemaOpen?: boolean;
39
46
  onChange: (value: string) => void;
47
+ onSchemaToggle?: () => void;
40
48
  onSubmit: () => void | Promise<void>;
41
- isLoading: boolean;
42
- agents: Record<string, AgentSchemaData>;
43
49
  selectedAgent: string;
44
50
  setSelectedAgent: (agentId: string) => void;
45
- suggestions: string[];
46
- isSchemaOpen: boolean;
47
- onSchemaToggle: () => void;
48
- clearAgentState?: (agentId: string) => Promise<void>;
51
+ value: string;
49
52
  }
50
53
 
51
54
  function isSchemaRootObject(schemaJson?: JSONSchema7): boolean {
52
55
  if (!schemaJson) return false;
56
+
53
57
  try {
54
58
  return (
55
59
  schemaJson.type === 'object' ||
@@ -61,21 +65,23 @@ function isSchemaRootObject(schemaJson?: JSONSchema7): boolean {
61
65
  }
62
66
 
63
67
  export function InputSection({
64
- value,
68
+ agents,
69
+ className,
70
+ clearAgentState,
71
+ isLoading,
72
+ isSchemaOpen,
65
73
  onChange,
74
+ onSchemaToggle,
66
75
  onSubmit,
67
- isLoading,
68
- agents,
69
76
  selectedAgent,
70
77
  setSelectedAgent,
71
- suggestions,
72
- isSchemaOpen,
73
- onSchemaToggle,
74
- clearAgentState,
78
+ value,
75
79
  }: InputSectionProps) {
76
80
  const logger = useLogger('InputSection');
77
- const { generateSample, isGeneratingSample, isAuthenticated } = useWorkbench();
81
+ const { generateSample, isGeneratingSample, env } = useWorkbench();
82
+ const isAuthenticated = env.authenticated;
78
83
  const [agentSelectOpen, setAgentSelectOpen] = useState(false);
84
+ const [prefillOpen, setPrefillOpen] = useState(false);
79
85
  const [isValidInput, setIsValidInput] = useState(true);
80
86
  const [monacoHasErrors, setMonacoHasErrors] = useState<boolean | null>(null);
81
87
 
@@ -86,6 +92,7 @@ export function InputSection({
86
92
  // Determine input type for switch case
87
93
  const inputType = useMemo(() => {
88
94
  const schema = selectedAgentData?.schema?.input?.json;
95
+
89
96
  logger.debug(
90
97
  '🎛️ InputSection - selectedAgent:',
91
98
  selectedAgent,
@@ -94,17 +101,21 @@ export function InputSection({
94
101
  'schema:',
95
102
  schema
96
103
  );
104
+
97
105
  if (!schema) {
98
106
  return 'none'; // Agent has no input schema
99
107
  }
108
+
100
109
  if (isSchemaRootObject(schema)) {
101
110
  return 'object'; // Complex object schema
102
111
  }
112
+
103
113
  if (schema.type === 'string') {
104
114
  return 'string'; // String schema
105
115
  }
116
+
106
117
  return 'none'; // Default to none for other types
107
- }, [selectedAgentData?.schema.input?.json, logger]);
118
+ }, [selectedAgentData, logger, selectedAgent]);
108
119
 
109
120
  const isObjectSchema = inputType === 'object';
110
121
 
@@ -125,6 +136,7 @@ export function InputSection({
125
136
 
126
137
  // Validate with zod
127
138
  const result = zodSchema.safeParse(parsedJson);
139
+
128
140
  return result.success;
129
141
  } catch {
130
142
  // JSON parse error or schema validation error
@@ -135,11 +147,12 @@ export function InputSection({
135
147
  );
136
148
 
137
149
  // Reset Monaco error state when schema changes
150
+ // biome-ignore lint/correctness/useExhaustiveDependencies: Trigger on schema change
138
151
  useEffect(() => {
139
152
  if (isObjectSchema) {
140
153
  setMonacoHasErrors(null);
141
154
  }
142
- }, [selectedAgentData?.schema?.input?.json, isObjectSchema]);
155
+ }, [selectedAgentData, isObjectSchema]);
143
156
 
144
157
  // Update validation state - use Monaco errors if available, otherwise fall back to zod validation
145
158
  useEffect(() => {
@@ -150,6 +163,7 @@ export function InputSection({
150
163
  } else {
151
164
  // Monaco hasn't reported yet, use zod validation as fallback
152
165
  const isValid = validateInput(value, selectedAgentData?.schema?.input?.json);
166
+
153
167
  setIsValidInput(isValid);
154
168
  }
155
169
  } else {
@@ -169,31 +183,40 @@ export function InputSection({
169
183
 
170
184
  try {
171
185
  const sampleJson = await generateSample(selectedAgent);
186
+
172
187
  onChange(sampleJson);
173
188
  } catch (error) {
174
189
  logger.error('Failed to generate sample JSON:', error);
175
- console.error('Failed to generate sample JSON:', error);
176
190
  }
177
191
  };
178
192
 
179
193
  // Memoized submit disabled condition for readability
180
194
  const isSubmitDisabled = useMemo(() => {
181
- if (isLoading) return true;
182
- if (inputType === 'string' && !value.trim()) return true;
183
- if (inputType === 'object' && (!isValidInput || !value.trim())) return true;
195
+ if (isLoading) {
196
+ return true;
197
+ }
198
+
199
+ if (inputType === 'string' && !value.trim()) {
200
+ return true;
201
+ }
202
+
203
+ if (inputType === 'object' && (!isValidInput || !value.trim())) {
204
+ return true;
205
+ }
206
+
184
207
  return false;
185
208
  }, [isLoading, inputType, value, isValidInput]);
186
209
 
187
210
  return (
188
- <>
189
- <div className="flex items-center gap-2 py-2 px-3">
211
+ <div className={cn('flex flex-col gap-4 p-4 z-100', className)}>
212
+ <div className="flex items-center gap-2">
190
213
  <Popover open={agentSelectOpen} onOpenChange={setAgentSelectOpen}>
191
214
  <PopoverTrigger asChild>
192
215
  <Button
193
216
  aria-expanded={agentSelectOpen}
194
- className="font-normal bg-transparent dark:bg-transparent"
195
217
  variant="outline"
196
218
  size="sm"
219
+ className="font-normal bg-background dark:bg-background hover:bg-background dark:hover:bg-background dark:hover:border-border/70"
197
220
  >
198
221
  {Object.values(agents).find(
199
222
  (agent) => agent.metadata.agentId === selectedAgent
@@ -201,7 +224,7 @@ export function InputSection({
201
224
  <ChevronsUpDownIcon className="size-4 shrink-0 opacity-50" />
202
225
  </Button>
203
226
  </PopoverTrigger>
204
- <PopoverContent className="w-fit p-0">
227
+ <PopoverContent side="top" align="start" className="w-fit p-0 z-101">
205
228
  <Command>
206
229
  <CommandInput placeholder="Search agents..." />
207
230
  <CommandList>
@@ -211,8 +234,10 @@ export function InputSection({
211
234
  .sort((a, b) => a.metadata.name.localeCompare(b.metadata.name))
212
235
  .map((agent) => {
213
236
  const isSelected = selectedAgent === agent.metadata.agentId;
237
+
214
238
  // Use name for search but include agentId to ensure uniqueness
215
239
  const searchValue = `${agent.metadata.name}|${agent.metadata.agentId}`;
240
+
216
241
  return (
217
242
  <CommandItem
218
243
  key={agent.metadata.agentId}
@@ -223,6 +248,7 @@ export function InputSection({
223
248
  const selectedAgentData = Object.values(agents).find(
224
249
  (a) => a.metadata.agentId === agentId
225
250
  );
251
+
226
252
  if (selectedAgentData) {
227
253
  logger.debug(
228
254
  '🎯 Agent selected by name:',
@@ -230,8 +256,10 @@ export function InputSection({
230
256
  'agentId:',
231
257
  agentId
232
258
  );
259
+
233
260
  setSelectedAgent(agentId);
234
261
  }
262
+
235
263
  setAgentSelectOpen(false);
236
264
  }}
237
265
  >
@@ -251,96 +279,118 @@ export function InputSection({
251
279
  </PopoverContent>
252
280
  </Popover>
253
281
 
254
- {suggestions.length > 0 && (
255
- <Select onValueChange={(value) => onChange(value)}>
256
- <SelectTrigger
257
- size="sm"
258
- className="ml-auto bg-transparent dark:bg-transparent text-foreground!"
259
- >
260
- Suggestions
261
- </SelectTrigger>
262
- <SelectContent className="text-sm" side="top" align="end">
263
- {suggestions.map((suggestion) => (
264
- <SelectItem key={suggestion} value={suggestion}>
265
- {suggestion}
266
- </SelectItem>
267
- ))}
268
- </SelectContent>
269
- </Select>
282
+ {onSchemaToggle && (
283
+ <Button
284
+ aria-label={isSchemaOpen ? 'Hide Schema' : 'View Schema'}
285
+ size="sm"
286
+ variant="outline"
287
+ className={cn(
288
+ 'font-normal bg-background dark:bg-background hover:bg-background dark:hover:bg-background dark:hover:border-border/50',
289
+ isSchemaOpen && 'bg-secondary!'
290
+ )}
291
+ onClick={onSchemaToggle}
292
+ >
293
+ <Braces className="size-4" />
294
+ Schema
295
+ </Button>
270
296
  )}
271
297
 
272
- {isObjectSchema &&
273
- (isAuthenticated ? (
274
- <Button
275
- aria-label="Generate Sample JSON"
276
- size="sm"
277
- variant="outline"
278
- className="bg-none font-normal"
279
- onClick={handleGenerateSample}
280
- disabled={isGeneratingSample || !isAuthenticated}
281
- >
282
- {isGeneratingSample ? (
283
- <Loader2Icon className="size-4 animate-spin" />
284
- ) : (
285
- <Sparkles className="size-4" />
286
- )}{' '}
287
- Sample
288
- </Button>
289
- ) : (
290
- <Tooltip>
291
- <TooltipTrigger asChild>
292
- <span className="inline-flex">
293
- <Button
294
- aria-label="Generate Sample JSON"
295
- size="sm"
296
- variant="outline"
297
- className="bg-none font-normal"
298
- onClick={handleGenerateSample}
299
- disabled={isGeneratingSample || !isAuthenticated}
300
- >
301
- {isGeneratingSample ? (
302
- <Loader2Icon className="size-4 animate-spin" />
298
+ {isObjectSchema && (
299
+ <Popover open={prefillOpen} onOpenChange={setPrefillOpen}>
300
+ <PopoverTrigger asChild>
301
+ <Button
302
+ aria-expanded={prefillOpen}
303
+ aria-label="Pre-fill input"
304
+ size="sm"
305
+ variant="outline"
306
+ className="font-normal bg-background dark:bg-background hover:bg-background dark:hover:bg-background dark:hover:border-border/70"
307
+ >
308
+ <ListPlus className="size-4" />
309
+ Pre-fill
310
+ <ChevronDownIcon className="size-4 shrink-0 opacity-50" />
311
+ </Button>
312
+ </PopoverTrigger>
313
+ <PopoverContent side="top" align="start" className="w-fit max-w-xl p-0 z-101">
314
+ <Command>
315
+ <CommandList>
316
+ <CommandGroup>
317
+ <CommandItem
318
+ onSelect={() => {
319
+ const template = generateTemplateFromSchema(
320
+ selectedAgentData?.schema?.input?.json
321
+ );
322
+
323
+ onChange(template);
324
+ setPrefillOpen(false);
325
+ }}
326
+ >
327
+ <SquareCode className="size-4" />
328
+ <span>Template</span>
329
+ <span className="ml-auto text-xs text-muted-foreground">
330
+ Empty schema structure
331
+ </span>
332
+ </CommandItem>
333
+
334
+ {isAuthenticated ? (
335
+ <CommandItem
336
+ disabled={isGeneratingSample}
337
+ onSelect={() => {
338
+ handleGenerateSample();
339
+ setPrefillOpen(false);
340
+ }}
341
+ >
342
+ {isGeneratingSample ? (
343
+ <Loader2Icon className="size-4 animate-spin" />
344
+ ) : (
345
+ <Sparkles className="size-4" />
346
+ )}
347
+ <span>Mock Input</span>
348
+ <span className="ml-auto text-xs text-muted-foreground">
349
+ AI-generated data
350
+ </span>
351
+ </CommandItem>
303
352
  ) : (
304
- <Sparkles className="size-4" />
305
- )}{' '}
306
- Sample
307
- </Button>
308
- </span>
309
- </TooltipTrigger>
310
- <TooltipContent>
311
- <p>Login to generate a sample</p>
312
- </TooltipContent>
313
- </Tooltip>
314
- ))}
315
-
316
- <Button
317
- aria-label={isSchemaOpen ? 'Hide Schema' : 'View Schema'}
318
- size="sm"
319
- variant={isSchemaOpen ? 'default' : 'outline'}
320
- className={cn('font-normal', isSchemaOpen ? 'bg-primary' : 'bg-none')}
321
- onClick={onSchemaToggle}
322
- >
323
- <FileJson className="size-4" /> Schema
324
- </Button>
353
+ <Tooltip>
354
+ <TooltipTrigger asChild>
355
+ <CommandItem disabled className="opacity-50">
356
+ <Sparkles className="size-4" />
357
+ <span>Mock Input</span>
358
+ <span className="ml-auto text-xs text-muted-foreground">
359
+ Login required
360
+ </span>
361
+ </CommandItem>
362
+ </TooltipTrigger>
363
+ <TooltipContent>
364
+ Login to generate a mock input using AI
365
+ </TooltipContent>
366
+ </Tooltip>
367
+ )}
368
+ </CommandGroup>
369
+ </CommandList>
370
+ </Command>
371
+ </PopoverContent>
372
+ </Popover>
373
+ )}
325
374
 
326
375
  {clearAgentState && selectedAgent && (
327
376
  <Button
328
377
  aria-label="Clear conversation history"
329
378
  size="sm"
330
379
  variant="outline"
331
- className="bg-none font-normal text-muted-foreground hover:text-destructive"
380
+ className="ml-auto font-normal bg-background dark:bg-background hover:bg-background dark:hover:bg-background dark:hover:border-border/50 text-foreground hover:text-destructive"
332
381
  onClick={() => clearAgentState(selectedAgent)}
333
382
  >
334
- <Trash2 className="size-4" /> Clear
383
+ <Trash2 className="size-4" />
384
+ Clear Thread
335
385
  </Button>
336
386
  )}
337
387
  </div>
338
388
 
339
- <PromptInput onSubmit={onSubmit} className="px-3 pb-3">
389
+ <PromptInput onSubmit={onSubmit}>
340
390
  <PromptInputBody>
341
391
  {!selectedAgent ? (
342
- <div className="flex flex-col items-center justify-center py-8 px-4 text-center">
343
- <p className="text-sm text-muted-foreground">
392
+ <div className="flex flex-col items-center justify-center py-6 px-4 text-center">
393
+ <p className="text-sm text-muted-foreground/70">
344
394
  Select an agent to get started.
345
395
  </p>
346
396
  </div>
@@ -349,22 +399,23 @@ export function InputSection({
349
399
  switch (inputType) {
350
400
  case 'object':
351
401
  return (
352
- <MonacoJsonEditor
353
- value={value}
402
+ <JsonEditor
403
+ aria-invalid={!isValidInput}
354
404
  onChange={onChange}
405
+ onSubmit={onSubmit}
406
+ onValidationChange={setMonacoHasErrors}
355
407
  schema={selectedAgentData?.schema.input?.json}
356
408
  schemaUri={`agentuity://schema/${selectedAgentData?.metadata.id}/input`}
357
- aria-invalid={!isValidInput}
358
- onValidationChange={setMonacoHasErrors}
409
+ value={value}
359
410
  />
360
411
  );
361
412
 
362
413
  case 'string':
363
414
  return (
364
415
  <PromptInputTextarea
416
+ onChange={(e) => onChange(e.target.value)}
365
417
  placeholder="Enter a message to send..."
366
418
  value={value}
367
- onChange={(e) => onChange(e.target.value)}
368
419
  />
369
420
  );
370
421
  default:
@@ -372,9 +423,10 @@ export function InputSection({
372
423
  <div className="flex flex-col items-center justify-center py-8 px-4 text-center ">
373
424
  <p className="text-sm text-muted-foreground">
374
425
  <span className="font-medium">
375
- This agent has no input schema.{' '}
426
+ This agent has no input schema.
376
427
  </span>
377
428
  </p>
429
+
378
430
  <Button
379
431
  aria-label="Run Agent"
380
432
  size="sm"
@@ -396,7 +448,8 @@ export function InputSection({
396
448
  })()
397
449
  )}
398
450
  </PromptInputBody>
399
- <PromptInputFooter>
451
+
452
+ <PromptInputFooter className={cn('pt-0', !selectedAgent && 'pb-0')}>
400
453
  {selectedAgent && inputType !== 'none' && (
401
454
  <Button
402
455
  aria-label="Submit"
@@ -410,19 +463,20 @@ export function InputSection({
410
463
  'value:',
411
464
  value
412
465
  );
466
+
413
467
  onSubmit();
414
468
  }}
415
- className="ml-auto"
469
+ className={cn('ml-auto', isSubmitDisabled && 'opacity-10!')}
416
470
  >
417
471
  {isLoading ? (
418
472
  <Loader2Icon className="size-4 animate-spin" />
419
473
  ) : (
420
- <SendIcon className="size-4" />
474
+ <ArrowUp className="size-4" />
421
475
  )}
422
476
  </Button>
423
477
  )}
424
478
  </PromptInputFooter>
425
479
  </PromptInput>
426
- </>
480
+ </div>
427
481
  );
428
482
  }