@inkeep/agents-manage-ui 0.1.1 → 0.1.2

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 (43) hide show
  1. package/{.env.sample → .env.example} +6 -1
  2. package/.turbo/turbo-build.log +27 -33
  3. package/.turbo/turbo-test.log +43 -10
  4. package/LICENSE.md +22 -17
  5. package/package.json +5 -5
  6. package/src/app/api/signoz/conversations/[conversationId]/route.ts +43 -4
  7. package/src/app/api/signoz/route.ts +8 -6
  8. package/src/components/api-keys/form/api-key-form.tsx +2 -0
  9. package/src/components/api-keys/form/validation.ts +1 -1
  10. package/src/components/artifact-components/form/artifact-component-form.tsx +5 -0
  11. package/src/components/artifact-components/form/validation.ts +3 -3
  12. package/src/components/credentials/views/credential-form-validation.ts +1 -1
  13. package/src/components/credentials/views/credential-form.tsx +2 -0
  14. package/src/components/credentials/views/edit-credential-form.tsx +1 -1
  15. package/src/components/credentials/views/generic-auth-form.tsx +1 -1
  16. package/src/components/data-components/form/data-component-form.tsx +10 -1
  17. package/src/components/data-components/form/validation.ts +3 -2
  18. package/src/components/form/expandable-field.tsx +6 -1
  19. package/src/components/form/form-field-wrapper.tsx +3 -1
  20. package/src/components/form/generic-combo-box.tsx +3 -1
  21. package/src/components/form/generic-input.tsx +9 -1
  22. package/src/components/form/generic-select.tsx +3 -1
  23. package/src/components/form/generic-textarea.tsx +3 -1
  24. package/src/components/form/json-schema-input.tsx +9 -1
  25. package/src/components/graph/playground/chat-widget.tsx +30 -1
  26. package/src/components/graph/playground/playground.tsx +7 -1
  27. package/src/components/graph/sidepane/metadata/metadata-editor.tsx +38 -38
  28. package/src/components/graph/sidepane/nodes/agent-node-editor.tsx +22 -8
  29. package/src/components/graph/sidepane/nodes/expandable-text-area.tsx +3 -1
  30. package/src/components/graph/sidepane/nodes/form-fields.tsx +10 -1
  31. package/src/components/mcp-servers/form/mcp-server-form.tsx +8 -1
  32. package/src/components/mcp-servers/form/validation.ts +1 -1
  33. package/src/components/projects/edit-project-dialog.tsx +1 -1
  34. package/src/components/projects/form/project-form.tsx +3 -0
  35. package/src/components/projects/form/validation.ts +14 -10
  36. package/src/components/projects/new-project-dialog.tsx +1 -1
  37. package/src/components/traces/timeline/timeline-wrapper.tsx +117 -28
  38. package/src/components/ui/alert.tsx +66 -0
  39. package/src/components/ui/form.tsx +11 -4
  40. package/src/hooks/use-chat-activities-polling.ts +44 -11
  41. package/src/lib/api/signoz-stats.ts +958 -304
  42. package/src/lib/types/graph-full.ts +1 -1
  43. package/src/lib/validation.ts +1 -1
@@ -25,6 +25,7 @@ interface GenericComboBoxProps<T extends FieldValues> {
25
25
  searchPlaceholder?: string;
26
26
  placeholder?: string;
27
27
  disabled?: boolean;
28
+ isRequired?: boolean;
28
29
  }
29
30
 
30
31
  export function GenericComboBox<T extends FieldValues>({
@@ -35,11 +36,12 @@ export function GenericComboBox<T extends FieldValues>({
35
36
  searchPlaceholder = 'Search...',
36
37
  placeholder,
37
38
  disabled = false,
39
+ isRequired = false,
38
40
  }: GenericComboBoxProps<T>) {
39
41
  const [open, setOpen] = useState(false);
40
42
 
41
43
  return (
42
- <FormFieldWrapper control={control} name={name} label={label}>
44
+ <FormFieldWrapper control={control} name={name} label={label} isRequired={isRequired}>
43
45
  {(field) => (
44
46
  <Popover open={open} onOpenChange={setOpen}>
45
47
  <PopoverTrigger asChild>
@@ -13,6 +13,7 @@ interface GenericInputProps<T extends FieldValues> {
13
13
  min?: string;
14
14
  disabled?: boolean;
15
15
  description?: string;
16
+ isRequired?: boolean;
16
17
  }
17
18
 
18
19
  export function GenericInput<T extends FieldValues>({
@@ -24,9 +25,16 @@ export function GenericInput<T extends FieldValues>({
24
25
  min,
25
26
  disabled,
26
27
  description,
28
+ isRequired = false,
27
29
  }: GenericInputProps<T>) {
28
30
  return (
29
- <FormFieldWrapper control={control} name={name} label={label} description={description}>
31
+ <FormFieldWrapper
32
+ control={control}
33
+ name={name}
34
+ label={label}
35
+ description={description}
36
+ isRequired={isRequired}
37
+ >
30
38
  {(field) => (
31
39
  <Input
32
40
  type={type}
@@ -24,6 +24,7 @@ interface GenericSelectProps<T extends FieldValues> {
24
24
  options: SelectOption[];
25
25
  disabled?: boolean;
26
26
  selectTriggerClassName?: string;
27
+ isRequired?: boolean;
27
28
  }
28
29
 
29
30
  export function GenericSelect<T extends FieldValues>({
@@ -34,9 +35,10 @@ export function GenericSelect<T extends FieldValues>({
34
35
  options,
35
36
  disabled = false,
36
37
  selectTriggerClassName,
38
+ isRequired = false,
37
39
  }: GenericSelectProps<T>) {
38
40
  return (
39
- <FormFieldWrapper control={control} name={name} label={label}>
41
+ <FormFieldWrapper control={control} name={name} label={label} isRequired={isRequired}>
40
42
  {(field) => (
41
43
  <Select onValueChange={field.onChange} defaultValue={field.value} disabled={disabled}>
42
44
  <SelectTrigger disabled={disabled} className={selectTriggerClassName}>
@@ -12,6 +12,7 @@ interface GenericTextareaProps<T extends FieldValues> {
12
12
  className?: string;
13
13
  disabled?: boolean;
14
14
  readOnly?: boolean;
15
+ isRequired?: boolean;
15
16
  }
16
17
 
17
18
  export function GenericTextarea<T extends FieldValues>({
@@ -22,9 +23,10 @@ export function GenericTextarea<T extends FieldValues>({
22
23
  className,
23
24
  disabled,
24
25
  readOnly,
26
+ isRequired = false,
25
27
  }: GenericTextareaProps<T>) {
26
28
  return (
27
- <FormFieldWrapper control={control} name={name} label={label}>
29
+ <FormFieldWrapper control={control} name={name} label={label} isRequired={isRequired}>
28
30
  {(field) => (
29
31
  <Textarea
30
32
  placeholder={placeholder}
@@ -12,6 +12,7 @@ interface JsonSchemaInputProps<T extends FieldValues> {
12
12
  disabled?: boolean;
13
13
  description?: string;
14
14
  readOnly?: boolean;
15
+ isRequired?: boolean;
15
16
  }
16
17
 
17
18
  export function JsonSchemaInput<T extends FieldValues>({
@@ -22,9 +23,16 @@ export function JsonSchemaInput<T extends FieldValues>({
22
23
  disabled,
23
24
  description,
24
25
  readOnly,
26
+ isRequired = false,
25
27
  }: JsonSchemaInputProps<T>) {
26
28
  return (
27
- <FormFieldWrapper control={control} name={name} label={label} description={description}>
29
+ <FormFieldWrapper
30
+ control={control}
31
+ name={name}
32
+ label={label}
33
+ description={description}
34
+ isRequired={isRequired}
35
+ >
28
36
  {(field) => (
29
37
  <StandaloneJsonEditor
30
38
  placeholder={placeholder}
@@ -1,4 +1,5 @@
1
1
  'use client';
2
+ import { useRef, useEffect } from 'react';
2
3
  import { InkeepEmbeddedChat } from '@inkeep/cxkit-react-oss';
3
4
  import type { ComponentsConfig, InkeepCallbackEvent } from '@inkeep/cxkit-react-oss/types';
4
5
  import { EXECUTION_API_BASE_URL } from '@/lib/api/api-config';
@@ -107,16 +108,44 @@ export function ChatWidget({
107
108
  startPolling,
108
109
  stopPolling,
109
110
  }: ChatWidgetProps) {
111
+ const stopPollingTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
112
+
113
+ useEffect(() => {
114
+ return () => {
115
+ if (stopPollingTimeoutRef.current) {
116
+ clearTimeout(stopPollingTimeoutRef.current);
117
+ stopPollingTimeoutRef.current = null;
118
+ }
119
+ };
120
+ }, []);
121
+
110
122
  return (
111
123
  <div className="h-full flex flex-row gap-4">
112
124
  <div className="flex-1 min-w-0 h-full">
113
125
  <InkeepEmbeddedChat
114
126
  baseSettings={{
115
127
  onEvent: (event: InkeepCallbackEvent) => {
128
+ if (event.eventName === 'assistant_message_received') {
129
+ // Add a delay before stopping polling to allow activity data to be available
130
+ stopPollingTimeoutRef.current = setTimeout(() => {
131
+ stopPolling();
132
+ stopPollingTimeoutRef.current = null;
133
+ }, 5000);
134
+ }
116
135
  if (event.eventName === 'user_message_submitted') {
136
+ // Cancel any pending stop polling timeout since we need to keep polling
137
+ if (stopPollingTimeoutRef.current) {
138
+ clearTimeout(stopPollingTimeoutRef.current);
139
+ stopPollingTimeoutRef.current = null;
140
+ }
117
141
  startPolling();
118
142
  }
119
143
  if (event.eventName === 'chat_clear_button_clicked') {
144
+ // Cancel any pending stop polling timeout
145
+ if (stopPollingTimeoutRef.current) {
146
+ clearTimeout(stopPollingTimeoutRef.current);
147
+ stopPollingTimeoutRef.current = null;
148
+ }
120
149
  stopPolling();
121
150
  setConversationId(nanoid());
122
151
  }
@@ -171,7 +200,7 @@ export function ChatWidget({
171
200
  components: {
172
201
  IkpMessage,
173
202
  },
174
- introMessage: 'Hi!'
203
+ introMessage: 'Hi!',
175
204
  }}
176
205
  />
177
206
  </div>
@@ -25,9 +25,11 @@ export const Playground = ({
25
25
  const {
26
26
  chatActivities,
27
27
  isPolling,
28
- error: _error,
28
+ error,
29
29
  startPolling,
30
30
  stopPolling,
31
+ retryConnection,
32
+ refreshOnce,
31
33
  } = useChatActivitiesPolling({
32
34
  conversationId,
33
35
  });
@@ -58,6 +60,10 @@ export const Playground = ({
58
60
  isPolling={isPolling}
59
61
  conversation={chatActivities}
60
62
  enableAutoScroll={true}
63
+ error={error}
64
+ retryConnection={retryConnection}
65
+ refreshOnce={refreshOnce}
66
+ showConversationTracesLink={true}
61
67
  />
62
68
  </ResizablePanelGroup>
63
69
  </div>
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { ChevronRight, Info } from 'lucide-react';
4
4
  import { useParams } from 'next/navigation';
5
- import { useCallback, useEffect } from 'react';
5
+ import { useCallback } from 'react';
6
6
  import { ExpandableJsonEditor } from '@/components/form/expandable-json-editor';
7
7
  import { Button } from '@/components/ui/button';
8
8
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
@@ -22,6 +22,8 @@ import { useProjectData } from '@/hooks/use-project-data';
22
22
  import { ModelSelector } from '../nodes/model-selector';
23
23
  import { ContextConfigForm } from './context-config';
24
24
  import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
25
+ import { InputField, TextareaField } from '../nodes/form-fields';
26
+ import { ExpandableTextArea } from '../nodes/expandable-text-area';
25
27
 
26
28
  function MetadataEditor() {
27
29
  const params = useParams();
@@ -64,45 +66,43 @@ function MetadataEditor() {
64
66
  <CopyableSingleLineCode code={graphUrl} />
65
67
  </div>
66
68
  )}
69
+ <InputField
70
+ id="id"
71
+ name="id"
72
+ label="Id"
73
+ value={id || ''}
74
+ onChange={(e) => updateMetadata('id', e.target.value)}
75
+ disabled={!!graphId} // only editable if no graphId is set (i.e. new graph)
76
+ placeholder="my-graph"
77
+ description={
78
+ !graphId
79
+ ? 'Choose a unique identifier for this graph. Using an existing id will replace that graph.'
80
+ : undefined
81
+ }
82
+ />
83
+ <InputField
84
+ id="name"
85
+ name="name"
86
+ label="Name"
87
+ value={name}
88
+ onChange={(e) => updateMetadata('name', e.target.value)}
89
+ placeholder="My graph"
90
+ isRequired
91
+ />
92
+ <TextareaField
93
+ id="description"
94
+ name="description"
95
+ label="Description"
96
+ value={description}
97
+ onChange={(e) => updateMetadata('description', e.target.value)}
98
+ placeholder="This graph is used to..."
99
+ className="max-h-96"
100
+ />
67
101
  <div className="space-y-2">
68
- <Label htmlFor="id">Id</Label>
69
- <Input
70
- id="id"
71
- value={id || ''}
72
- onChange={(e) => updateMetadata('id', e.target.value)}
73
- disabled={!!graphId} // only editable if no graphId is set (i.e. new graph)
74
- placeholder="my-graph"
75
- />
76
- {!graphId && (
77
- <p className="text-sm text-muted-foreground">
78
- Choose a unique identifier for this graph. Using an existing id will replace that graph.
79
- </p>
80
- )}
81
- </div>
82
- <div className="space-y-2">
83
- <Label htmlFor="name">Name</Label>
84
- <Input
85
- id="name"
86
- value={name}
87
- onChange={(e) => updateMetadata('name', e.target.value)}
88
- placeholder="My graph"
89
- />
90
- </div>
91
- <div className="space-y-2">
92
- <Label htmlFor="description">Description</Label>
93
- <Textarea
94
- id="description"
95
- value={description}
96
- onChange={(e) => updateMetadata('description', e.target.value)}
97
- placeholder="This graph is used to..."
98
- className="max-h-96"
99
- />
100
- </div>
101
-
102
- <div className="space-y-2">
103
- <Label htmlFor="graph-prompt">Graph Prompt</Label>
104
- <Textarea
102
+ <ExpandableTextArea
105
103
  id="graph-prompt"
104
+ name="graph-prompt"
105
+ label="Graph Prompt"
106
106
  value={graphPrompt || ''}
107
107
  onChange={(e) => updateMetadata('graphPrompt', e.target.value)}
108
108
  placeholder="System-level instructions for this graph..."
@@ -35,7 +35,7 @@ export function AgentNodeEditor({
35
35
  const { tenantId, projectId } = useParams<{ tenantId: string; projectId: string }>();
36
36
  const selectedDataComponents = selectedNode.data?.dataComponents || [];
37
37
  const selectedArtifactComponents = selectedNode.data?.artifactComponents || [];
38
-
38
+
39
39
  // Get project and graph data for inheritance indicators
40
40
  const { project } = useProjectData();
41
41
  const metadata = useGraphStore((state) => state.metadata);
@@ -76,6 +76,7 @@ export function AgentNodeEditor({
76
76
  onChange={(e) => updatePath('name', e.target.value)}
77
77
  placeholder="Support agent"
78
78
  error={getFieldError('name')}
79
+ isRequired
79
80
  />
80
81
 
81
82
  <TextareaField
@@ -100,14 +101,15 @@ export function AgentNodeEditor({
100
101
  data-invalid={errorHelpers?.hasFieldError('prompt') ? '' : undefined}
101
102
  className="w-full max-h-96 data-invalid:border-red-300 data-invalid:focus-visible:border-red-300 data-invalid:focus-visible:ring-red-300"
102
103
  label="Prompt"
104
+ isRequired
103
105
  />
104
106
  {getFieldError('prompt') && (
105
107
  <p className="text-sm text-red-600">{getFieldError('prompt')}</p>
106
108
  )}
107
109
  </div>
108
110
 
109
- <ModelSection
110
- models={selectedNode.data.models}
111
+ <ModelSection
112
+ models={selectedNode.data.models}
111
113
  updatePath={updateModelPath}
112
114
  projectModels={project?.models}
113
115
  graphModels={metadata?.models}
@@ -156,12 +158,24 @@ export function AgentNodeEditor({
156
158
  </div>
157
159
 
158
160
  <div className="text-xs text-muted-foreground p-3 bg-blue-50 dark:bg-blue-950/20 rounded-md border border-blue-200 dark:border-blue-800">
159
- <p className="font-medium text-blue-900 dark:text-blue-100 mb-2">How execution limit inheritance works:</p>
161
+ <p className="font-medium text-blue-900 dark:text-blue-100 mb-2">
162
+ How execution limit inheritance works:
163
+ </p>
160
164
  <ul className="space-y-1 text-blue-800 dark:text-blue-200">
161
- <li>• <strong>stepCountIs</strong>: Project → Agent only (agent-level execution limit)</li>
162
- <li>• <strong>Explicit settings</strong> always take precedence over inherited values</li>
163
- <li>• <strong>Agent scope</strong>: This limit applies only to this specific agent's execution steps</li>
164
- <li>• <strong>Independent from transfers</strong>: Steps are counted per agent, transfers are counted per conversation</li>
165
+ <li>
166
+ <strong>stepCountIs</strong>: Project Agent only (agent-level execution limit)
167
+ </li>
168
+ <li>
169
+ • <strong>Explicit settings</strong> always take precedence over inherited values
170
+ </li>
171
+ <li>
172
+ • <strong>Agent scope</strong>: This limit applies only to this specific agent's
173
+ execution steps
174
+ </li>
175
+ <li>
176
+ • <strong>Independent from transfers</strong>: Steps are counted per agent, transfers
177
+ are counted per conversation
178
+ </li>
165
179
  </ul>
166
180
  </div>
167
181
  </div>
@@ -17,12 +17,14 @@ function ExpandedTextArea({ ...props }) {
17
17
 
18
18
  export function ExpandableTextArea({
19
19
  label,
20
+ isRequired = false,
20
21
  ...props
21
- }: { label: string } & React.ComponentProps<typeof Textarea>) {
22
+ }: { label: string; isRequired?: boolean } & React.ComponentProps<typeof Textarea>) {
22
23
  return (
23
24
  <ExpandableField
24
25
  name={props.id || 'expandable-textarea'}
25
26
  label={label}
27
+ isRequired={isRequired}
26
28
  compactView={<Textarea {...props} />}
27
29
  expandedView={<ExpandedTextArea {...props} />}
28
30
  />
@@ -4,6 +4,7 @@ import { Input } from '@/components/ui/input';
4
4
  import { Label } from '@/components/ui/label';
5
5
  import { Textarea } from '@/components/ui/textarea';
6
6
  import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
7
+ import { cn } from '@/lib/utils';
7
8
 
8
9
  interface BaseFieldProps {
9
10
  id: string;
@@ -16,6 +17,8 @@ interface BaseFieldProps {
16
17
  className?: string;
17
18
  description?: string;
18
19
  tooltip?: string;
20
+ isRequired?: boolean;
21
+ disabled?: boolean;
19
22
  }
20
23
 
21
24
  interface InputFieldProps extends BaseFieldProps {
@@ -40,13 +43,16 @@ export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(
40
43
  description,
41
44
  tooltip,
42
45
  type = 'text',
46
+ isRequired = false,
47
+ disabled = false,
43
48
  },
44
49
  ref
45
50
  ) => {
46
51
  return (
47
52
  <div className="space-y-2">
48
- <Label htmlFor={id} className={error ? 'text-red-600' : ''}>
53
+ <Label htmlFor={id} className={cn(error ? 'text-red-600' : '', 'gap-1')}>
49
54
  {label}
55
+ {isRequired && <span className="text-red-500">*</span>}
50
56
  {tooltip && (
51
57
  <Tooltip>
52
58
  <TooltipTrigger>
@@ -66,6 +72,7 @@ export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(
66
72
  placeholder={placeholder}
67
73
  data-invalid={error ? '' : undefined}
68
74
  className={`w-full data-invalid:border-red-300 data-invalid:focus-visible:border-red-300 data-invalid:focus-visible:ring-red-300 ${className}`}
75
+ disabled={disabled}
69
76
  />
70
77
  {error && <p className="text-sm text-red-600">{error}</p>}
71
78
  {description && <p className="text-sm text-muted-foreground">{description}</p>}
@@ -89,6 +96,7 @@ export const TextareaField = forwardRef<HTMLTextAreaElement, TextareaFieldProps>
89
96
  className = '',
90
97
  description,
91
98
  maxHeight = 'max-h-96',
99
+ disabled = false,
92
100
  },
93
101
  ref
94
102
  ) => {
@@ -106,6 +114,7 @@ export const TextareaField = forwardRef<HTMLTextAreaElement, TextareaFieldProps>
106
114
  placeholder={placeholder}
107
115
  data-invalid={error ? '' : undefined}
108
116
  className={`w-full ${maxHeight} data-invalid:border-red-300 data-invalid:focus-visible:border-red-300 data-invalid:focus-visible:ring-red-300 ${className}`}
117
+ disabled={disabled}
109
118
  />
110
119
  {error && <p className="text-sm text-red-600">{error}</p>}
111
120
  {description && <p className="text-sm text-muted-foreground">{description}</p>}
@@ -105,12 +105,19 @@ export function MCPServerForm({
105
105
  return (
106
106
  <Form {...form}>
107
107
  <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
108
- <GenericInput control={form.control} name="name" label="Name" placeholder="MCP Server" />
108
+ <GenericInput
109
+ control={form.control}
110
+ name="name"
111
+ label="Name"
112
+ placeholder="MCP Server"
113
+ isRequired
114
+ />
109
115
  <GenericInput
110
116
  control={form.control}
111
117
  name="config.mcp.server.url"
112
118
  label="URL"
113
119
  placeholder="https://api.example.com/mcp"
120
+ isRequired
114
121
  />
115
122
  <GenericSelect
116
123
  control={form.control}
@@ -1,4 +1,4 @@
1
- import { z } from 'zod';
1
+ import { z } from 'zod/v4';
2
2
 
3
3
  // Discriminated union for tool selection
4
4
  const toolsConfigSchema = z.discriminatedUnion('type', [
@@ -33,7 +33,7 @@ export function EditProjectDialog({
33
33
 
34
34
  return (
35
35
  <Dialog open={isOpen} onOpenChange={setIsOpen}>
36
- <DialogContent className="max-w-2xl">
36
+ <DialogContent className="!max-w-2xl">
37
37
  <DialogHeader>
38
38
  <DialogTitle>Edit project</DialogTitle>
39
39
  <DialogDescription className="sr-only">Edit project details.</DialogDescription>
@@ -82,6 +82,7 @@ export function ProjectForm({
82
82
  placeholder="my-project"
83
83
  description="Choose a unique identifier for this project. This cannot be changed later."
84
84
  disabled={!!projectId}
85
+ isRequired
85
86
  />
86
87
  <GenericInput
87
88
  control={form.control}
@@ -89,6 +90,7 @@ export function ProjectForm({
89
90
  label="Project Name"
90
91
  placeholder="My Project"
91
92
  description="A friendly name for your project"
93
+ isRequired
92
94
  />
93
95
  <GenericTextarea
94
96
  control={form.control}
@@ -96,6 +98,7 @@ export function ProjectForm({
96
98
  label="Description"
97
99
  placeholder="Describe what this project is for..."
98
100
  className="min-h-[100px]"
101
+ isRequired
99
102
  />
100
103
 
101
104
  <Separator />
@@ -1,20 +1,24 @@
1
- import { z } from 'zod';
1
+ import { z } from 'zod/v4';
2
2
 
3
3
  const modelSettingsSchema = z.object({
4
4
  model: z.string().optional(), // Allow empty model - system will fall back to defaults
5
5
  providerOptions: z.record(z.string(), z.any()).optional(),
6
6
  });
7
7
 
8
- const projectModelsSchema = z.object({
9
- base: modelSettingsSchema.optional(),
10
- structuredOutput: modelSettingsSchema.optional(),
11
- summarizer: modelSettingsSchema.optional(),
12
- }).optional();
8
+ const projectModelsSchema = z
9
+ .object({
10
+ base: modelSettingsSchema.optional(),
11
+ structuredOutput: modelSettingsSchema.optional(),
12
+ summarizer: modelSettingsSchema.optional(),
13
+ })
14
+ .optional();
13
15
 
14
- const projectStopWhenSchema = z.object({
15
- transferCountIs: z.number().min(1).max(100).optional(),
16
- stepCountIs: z.number().min(1).max(1000).optional(),
17
- }).optional();
16
+ const projectStopWhenSchema = z
17
+ .object({
18
+ transferCountIs: z.number().min(1).max(100).optional(),
19
+ stepCountIs: z.number().min(1).max(1000).optional(),
20
+ })
21
+ .optional();
18
22
 
19
23
  export const projectSchema = z.object({
20
24
  id: z
@@ -52,7 +52,7 @@ export function NewProjectDialog({
52
52
  )}
53
53
  </DialogTrigger>
54
54
  )}
55
- <DialogContent className="max-w-2xl">
55
+ <DialogContent className="!max-w-2xl">
56
56
  <DialogTitle>Create new project</DialogTitle>
57
57
  <DialogDescription>
58
58
  Create a new project to organize your agents, tools, and resources.