@inkeep/agents-manage-ui 0.1.1 → 0.1.3

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 (101) hide show
  1. package/.env.example +10 -0
  2. package/.turbo/turbo-build.log +48 -54
  3. package/.turbo/turbo-test.log +7 -7
  4. package/.turbo/turbo-typecheck.log +1 -1
  5. package/LICENSE.md +22 -17
  6. package/README.md +3 -3
  7. package/biome.json +3 -0
  8. package/package.json +10 -9
  9. package/src/app/api/signoz/conversations/[conversationId]/route.ts +95 -34
  10. package/src/app/api/signoz/route.ts +8 -6
  11. package/src/components/api-keys/form/api-key-form.tsx +2 -0
  12. package/src/components/api-keys/form/validation.ts +1 -1
  13. package/src/components/artifact-components/form/artifact-component-form.tsx +20 -6
  14. package/src/components/artifact-components/form/validation.ts +3 -3
  15. package/src/components/credentials/views/credential-form-validation.ts +1 -1
  16. package/src/components/credentials/views/credential-form.tsx +2 -0
  17. package/src/components/credentials/views/edit-credential-form.tsx +1 -1
  18. package/src/components/credentials/views/generic-auth-form.tsx +1 -1
  19. package/src/components/data-components/form/data-component-form.tsx +19 -1
  20. package/src/components/data-components/form/validation.ts +3 -2
  21. package/src/components/form/expandable-field.tsx +6 -1
  22. package/src/components/form/form-field-wrapper.tsx +3 -1
  23. package/src/components/form/generic-combo-box.tsx +3 -1
  24. package/src/components/form/generic-input.tsx +9 -1
  25. package/src/components/form/generic-select.tsx +3 -1
  26. package/src/components/form/generic-textarea.tsx +3 -1
  27. package/src/components/form/json-schema-input.tsx +9 -1
  28. package/src/components/graph/configuration/node-types.tsx +2 -4
  29. package/src/components/graph/graph.tsx +4 -26
  30. package/src/components/graph/nodes/agent-node.tsx +1 -1
  31. package/src/components/graph/nodes/external-agent-node.tsx +1 -1
  32. package/src/components/graph/playground/chat-widget.tsx +31 -2
  33. package/src/components/graph/playground/ikp-message.tsx +16 -16
  34. package/src/components/graph/playground/playground.tsx +12 -6
  35. package/src/components/graph/sidepane/metadata/metadata-editor.tsx +62 -45
  36. package/src/components/graph/sidepane/nodes/agent-node-editor.tsx +56 -27
  37. package/src/components/graph/sidepane/nodes/expandable-text-area.tsx +3 -1
  38. package/src/components/graph/sidepane/nodes/external-agent-node-editor.tsx +31 -11
  39. package/src/components/graph/sidepane/nodes/form-fields.tsx +10 -1
  40. package/src/components/graph/sidepane/nodes/mcp-node-editor.tsx +4 -9
  41. package/src/components/graph/sidepane/nodes/model-section.tsx +1 -1
  42. package/src/components/graph/toolbar/toolbar.tsx +1 -1
  43. package/src/components/mcp-servers/form/active-tools-selector.tsx +4 -2
  44. package/src/components/mcp-servers/form/mcp-server-form.tsx +8 -1
  45. package/src/components/mcp-servers/form/validation.ts +1 -1
  46. package/src/components/projects/edit-project-dialog.tsx +1 -1
  47. package/src/components/projects/form/project-form.tsx +20 -8
  48. package/src/components/projects/form/project-models-section.tsx +51 -23
  49. package/src/components/projects/form/project-stopwhen-section.tsx +25 -11
  50. package/src/components/projects/form/validation.ts +14 -10
  51. package/src/components/projects/new-project-dialog.tsx +1 -1
  52. package/src/components/traces/ai-calls-breakdown.tsx +1 -1
  53. package/src/components/traces/charts/area-chart-card.tsx +2 -2
  54. package/src/components/traces/charts/area-chart.tsx +2 -2
  55. package/src/components/traces/charts/chart-card.tsx +4 -4
  56. package/src/components/traces/conversation-detail.tsx +10 -8
  57. package/src/components/traces/conversation-stats/conversation-list-item.tsx +48 -37
  58. package/src/components/traces/conversation-stats/conversation-stats-card.tsx +1 -1
  59. package/src/components/traces/filters/date-picker.tsx +6 -6
  60. package/src/components/traces/filters/filter-trigger.tsx +1 -1
  61. package/src/components/traces/filters/graph-filter.tsx +3 -3
  62. package/src/components/traces/timeline/activity-details-sidepane.tsx +1 -1
  63. package/src/components/traces/timeline/activity-timeline.tsx +1 -1
  64. package/src/components/traces/timeline/blocks.tsx +2 -2
  65. package/src/components/traces/timeline/render-panel-content.tsx +11 -11
  66. package/src/components/traces/timeline/timeline-item.tsx +36 -22
  67. package/src/components/traces/timeline/timeline-wrapper.tsx +125 -37
  68. package/src/components/traces/traces-overview.tsx +3 -3
  69. package/src/components/ui/alert.tsx +60 -0
  70. package/src/components/ui/calendar.tsx +3 -4
  71. package/src/components/ui/external-link.tsx +2 -2
  72. package/src/components/ui/form.tsx +11 -4
  73. package/src/components/ui/inheritance-indicator.tsx +20 -17
  74. package/src/components/ui/resizable.tsx +13 -18
  75. package/src/constants/page-descriptions.tsx +2 -5
  76. package/src/constants/signoz.ts +15 -18
  77. package/src/features/graph/domain/__tests__/roundtrip.test.ts +5 -5
  78. package/src/features/graph/domain/serialize.ts +8 -9
  79. package/src/hooks/use-auto-prefill-id-zustand.ts +68 -0
  80. package/src/hooks/use-auto-prefill-id.ts +36 -0
  81. package/src/hooks/use-chat-activities-polling.ts +45 -12
  82. package/src/hooks/use-graph-errors.ts +2 -1
  83. package/src/hooks/use-project-data.ts +2 -2
  84. package/src/lib/actions/graph-full.ts +6 -2
  85. package/src/lib/actions/projects.ts +1 -1
  86. package/src/lib/api/api-config.ts +6 -6
  87. package/src/lib/api/api-keys.ts +4 -1
  88. package/src/lib/api/credentials.ts +1 -1
  89. package/src/lib/api/data-components.ts +1 -1
  90. package/src/lib/api/graph-full-client.ts +6 -3
  91. package/src/lib/api/projects.ts +1 -1
  92. package/src/lib/api/signoz-sql.ts +1 -1
  93. package/src/lib/api/signoz-stats.ts +958 -304
  94. package/src/lib/index.ts +1 -1
  95. package/src/lib/logger.ts +1 -2
  96. package/src/lib/types/graph-full.ts +1 -1
  97. package/src/lib/utils/generate-id.ts +14 -0
  98. package/src/lib/validation.ts +1 -1
  99. package/tsconfig.json +2 -2
  100. package/.env.sample +0 -5
  101. package/eslint.config.mjs +0 -14
@@ -9,11 +9,12 @@ import { GenericTextarea } from '@/components/form/generic-textarea';
9
9
  import { Button } from '@/components/ui/button';
10
10
  import { Form } from '@/components/ui/form';
11
11
  import { Separator } from '@/components/ui/separator';
12
+ import { useAutoPrefillId } from '@/hooks/use-auto-prefill-id';
12
13
  import { createProjectAction, updateProjectAction } from '@/lib/actions/projects';
13
14
  import { defaultValues } from './form-configuration';
14
- import { type ProjectFormData, projectSchema } from './validation';
15
15
  import { ProjectModelsSection } from './project-models-section';
16
16
  import { ProjectStopWhenSection } from './project-stopwhen-section';
17
+ import { type ProjectFormData, projectSchema } from './validation';
17
18
 
18
19
  interface ProjectFormProps {
19
20
  tenantId: string;
@@ -38,6 +39,14 @@ export function ProjectForm({
38
39
  const { isSubmitting } = form.formState;
39
40
  const router = useRouter();
40
41
 
42
+ // Auto-prefill ID based on name field (only for new components)
43
+ useAutoPrefillId({
44
+ form,
45
+ nameField: 'name',
46
+ idField: 'id',
47
+ isEditing: !!projectId,
48
+ });
49
+
41
50
  const onSubmit = async (data: ProjectFormData) => {
42
51
  try {
43
52
  if (projectId) {
@@ -75,6 +84,14 @@ export function ProjectForm({
75
84
  return (
76
85
  <Form {...form}>
77
86
  <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
87
+ <GenericInput
88
+ control={form.control}
89
+ name="name"
90
+ label="Project Name"
91
+ placeholder="My Project"
92
+ description="A friendly name for your project"
93
+ isRequired
94
+ />
78
95
  <GenericInput
79
96
  control={form.control}
80
97
  name="id"
@@ -82,13 +99,7 @@ export function ProjectForm({
82
99
  placeholder="my-project"
83
100
  description="Choose a unique identifier for this project. This cannot be changed later."
84
101
  disabled={!!projectId}
85
- />
86
- <GenericInput
87
- control={form.control}
88
- name="name"
89
- label="Project Name"
90
- placeholder="My Project"
91
- description="A friendly name for your project"
102
+ isRequired
92
103
  />
93
104
  <GenericTextarea
94
105
  control={form.control}
@@ -96,6 +107,7 @@ export function ProjectForm({
96
107
  label="Description"
97
108
  placeholder="Describe what this project is for..."
98
109
  className="min-h-[100px]"
110
+ isRequired
99
111
  />
100
112
 
101
113
  <Separator />
@@ -1,13 +1,13 @@
1
1
  'use client';
2
2
 
3
- import { useState } from 'react';
4
3
  import { ChevronRight } from 'lucide-react';
5
- import { Control, useController, useWatch } from 'react-hook-form';
4
+ import { useState } from 'react';
5
+ import { type Control, useController, useWatch } from 'react-hook-form';
6
+ import { ExpandableJsonEditor } from '@/components/form/expandable-json-editor';
7
+ import { ModelSelector } from '@/components/graph/sidepane/nodes/model-selector';
6
8
  import { Button } from '@/components/ui/button';
7
9
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
8
- import { ExpandableJsonEditor } from '@/components/form/expandable-json-editor';
9
10
  import { Label } from '@/components/ui/label';
10
- import { ModelSelector } from '@/components/graph/sidepane/nodes/model-selector';
11
11
  import type { ProjectFormData } from './validation';
12
12
 
13
13
  interface ProjectModelsSectionProps {
@@ -16,8 +16,11 @@ interface ProjectModelsSectionProps {
16
16
 
17
17
  function BaseModelSection({ control }: { control: Control<ProjectFormData> }) {
18
18
  const { field: modelField } = useController({ control, name: 'models.base.model' });
19
- const { field: providerOptionsField } = useController({ control, name: 'models.base.providerOptions' });
20
-
19
+ const { field: providerOptionsField } = useController({
20
+ control,
21
+ name: 'models.base.providerOptions',
22
+ });
23
+
21
24
  return (
22
25
  <div className="space-y-2">
23
26
  <ModelSelector
@@ -26,13 +29,13 @@ function BaseModelSection({ control }: { control: Control<ProjectFormData> }) {
26
29
  value={modelField.value || ''}
27
30
  onValueChange={modelField.onChange}
28
31
  />
29
- <p className="text-xs text-muted-foreground">
30
- Primary model for general agent responses
31
- </p>
32
+ <p className="text-xs text-muted-foreground">Primary model for general agent responses</p>
32
33
  <ExpandableJsonEditor
33
34
  name="models.base.providerOptions"
34
35
  label="Provider Options"
35
- value={providerOptionsField.value ? JSON.stringify(providerOptionsField.value, null, 2) : ''}
36
+ value={
37
+ providerOptionsField.value ? JSON.stringify(providerOptionsField.value, null, 2) : ''
38
+ }
36
39
  onChange={(value) => {
37
40
  let parsedOptions;
38
41
  try {
@@ -53,8 +56,11 @@ function BaseModelSection({ control }: { control: Control<ProjectFormData> }) {
53
56
 
54
57
  function StructuredOutputModelSection({ control }: { control: Control<ProjectFormData> }) {
55
58
  const { field: modelField } = useController({ control, name: 'models.structuredOutput.model' });
56
- const { field: providerOptionsField } = useController({ control, name: 'models.structuredOutput.providerOptions' });
57
-
59
+ const { field: providerOptionsField } = useController({
60
+ control,
61
+ name: 'models.structuredOutput.providerOptions',
62
+ });
63
+
58
64
  return (
59
65
  <div className="space-y-2">
60
66
  <ModelSelector
@@ -69,7 +75,9 @@ function StructuredOutputModelSection({ control }: { control: Control<ProjectFor
69
75
  <ExpandableJsonEditor
70
76
  name="models.structuredOutput.providerOptions"
71
77
  label="Provider Options"
72
- value={providerOptionsField.value ? JSON.stringify(providerOptionsField.value, null, 2) : ''}
78
+ value={
79
+ providerOptionsField.value ? JSON.stringify(providerOptionsField.value, null, 2) : ''
80
+ }
73
81
  onChange={(value) => {
74
82
  let parsedOptions;
75
83
  try {
@@ -90,8 +98,11 @@ function StructuredOutputModelSection({ control }: { control: Control<ProjectFor
90
98
 
91
99
  function SummarizerModelSection({ control }: { control: Control<ProjectFormData> }) {
92
100
  const { field: modelField } = useController({ control, name: 'models.summarizer.model' });
93
- const { field: providerOptionsField } = useController({ control, name: 'models.summarizer.providerOptions' });
94
-
101
+ const { field: providerOptionsField } = useController({
102
+ control,
103
+ name: 'models.summarizer.providerOptions',
104
+ });
105
+
95
106
  return (
96
107
  <div className="space-y-2">
97
108
  <ModelSelector
@@ -106,7 +117,9 @@ function SummarizerModelSection({ control }: { control: Control<ProjectFormData>
106
117
  <ExpandableJsonEditor
107
118
  name="models.summarizer.providerOptions"
108
119
  label="Provider Options"
109
- value={providerOptionsField.value ? JSON.stringify(providerOptionsField.value, null, 2) : ''}
120
+ value={
121
+ providerOptionsField.value ? JSON.stringify(providerOptionsField.value, null, 2) : ''
122
+ }
110
123
  onChange={(value) => {
111
124
  let parsedOptions;
112
125
  try {
@@ -145,7 +158,9 @@ export function ProjectModelsSection({ control }: ProjectModelsSectionProps) {
145
158
  size="sm"
146
159
  className="flex items-center justify-start gap-2 w-full"
147
160
  >
148
- <ChevronRight className={`h-4 w-4 transition-transform duration-200 ${isOpen ? 'rotate-90' : ''}`} />
161
+ <ChevronRight
162
+ className={`h-4 w-4 transition-transform duration-200 ${isOpen ? 'rotate-90' : ''}`}
163
+ />
149
164
  Configure Default Models
150
165
  </Button>
151
166
  </CollapsibleTrigger>
@@ -160,16 +175,29 @@ export function ProjectModelsSection({ control }: ProjectModelsSectionProps) {
160
175
  <SummarizerModelSection control={control} />
161
176
 
162
177
  <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">
163
- <p className="font-medium text-blue-900 dark:text-blue-100 mb-2">How model inheritance works:</p>
178
+ <p className="font-medium text-blue-900 dark:text-blue-100 mb-2">
179
+ How model inheritance works:
180
+ </p>
164
181
  <ul className="space-y-1 text-blue-800 dark:text-blue-200">
165
- <li>• <strong>Models</strong>: Project → Graph → Agent (partial inheritance - missing models only)</li>
166
- <li>• <strong>Individual model types</strong> inherit independently (base, structuredOutput, summarizer)</li>
167
- <li>• <strong>Explicit settings</strong> always take precedence over inherited values</li>
168
- <li>• <strong>Provider options</strong> are inherited along with the model if not explicitly set</li>
182
+ <li>
183
+ <strong>Models</strong>: Project Graph → Agent (partial inheritance - missing
184
+ models only)
185
+ </li>
186
+ <li>
187
+ • <strong>Individual model types</strong> inherit independently (base,
188
+ structuredOutput, summarizer)
189
+ </li>
190
+ <li>
191
+ • <strong>Explicit settings</strong> always take precedence over inherited values
192
+ </li>
193
+ <li>
194
+ • <strong>Provider options</strong> are inherited along with the model if not
195
+ explicitly set
196
+ </li>
169
197
  </ul>
170
198
  </div>
171
199
  </CollapsibleContent>
172
200
  </Collapsible>
173
201
  </div>
174
202
  );
175
- }
203
+ }
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
- import { useState } from 'react';
4
3
  import { ChevronRight } from 'lucide-react';
5
- import { Control } from 'react-hook-form';
4
+ import { useState } from 'react';
5
+ import type { Control } from 'react-hook-form';
6
+ import { GenericInput } from '@/components/form/generic-input';
6
7
  import { Button } from '@/components/ui/button';
7
8
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
8
- import { GenericInput } from '@/components/form/generic-input';
9
9
  import { Label } from '@/components/ui/label';
10
10
  import type { ProjectFormData } from './validation';
11
11
 
@@ -33,7 +33,9 @@ export function ProjectStopWhenSection({ control }: ProjectStopWhenSectionProps)
33
33
  size="sm"
34
34
  className="flex items-center justify-start gap-2 w-full"
35
35
  >
36
- <ChevronRight className={`h-4 w-4 transition-transform duration-200 ${isOpen ? 'rotate-90' : ''}`} />
36
+ <ChevronRight
37
+ className={`h-4 w-4 transition-transform duration-200 ${isOpen ? 'rotate-90' : ''}`}
38
+ />
37
39
  Configure Execution Limits
38
40
  </Button>
39
41
  </CollapsibleTrigger>
@@ -73,17 +75,29 @@ export function ProjectStopWhenSection({ control }: ProjectStopWhenSectionProps)
73
75
  </div>
74
76
 
75
77
  <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">
76
- <p className="font-medium text-blue-900 dark:text-blue-100 mb-2">How inheritance works:</p>
78
+ <p className="font-medium text-blue-900 dark:text-blue-100 mb-2">
79
+ How inheritance works:
80
+ </p>
77
81
  <ul className="space-y-1 text-blue-800 dark:text-blue-200">
78
- <li>• <strong>transferCountIs</strong>: Project → Graph only (graph-level limit)</li>
79
- <li>• <strong>stepCountIs</strong>: Project → Agent only (agent-level limit)</li>
80
- <li>• <strong>Explicit settings</strong> always take precedence over inherited values</li>
81
- <li>• <strong>Default fallback</strong>: transferCountIs = 10 if no value is set</li>
82
- <li>• <strong>Error limit</strong> is hardcoded to 3 errors across all levels</li>
82
+ <li>
83
+ <strong>transferCountIs</strong>: Project → Graph only (graph-level limit)
84
+ </li>
85
+ <li>
86
+ <strong>stepCountIs</strong>: Project Agent only (agent-level limit)
87
+ </li>
88
+ <li>
89
+ • <strong>Explicit settings</strong> always take precedence over inherited values
90
+ </li>
91
+ <li>
92
+ • <strong>Default fallback</strong>: transferCountIs = 10 if no value is set
93
+ </li>
94
+ <li>
95
+ • <strong>Error limit</strong> is hardcoded to 3 errors across all levels
96
+ </li>
83
97
  </ul>
84
98
  </div>
85
99
  </CollapsibleContent>
86
100
  </Collapsible>
87
101
  </div>
88
102
  );
89
- }
103
+ }
@@ -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.
@@ -15,9 +15,9 @@ import {
15
15
  SelectValue,
16
16
  } from '@/components/ui/select';
17
17
  import { Skeleton } from '@/components/ui/skeleton';
18
+ import { UNKNOWN_VALUE } from '@/constants/signoz';
18
19
  import { type TimeRange, useAICallsQueryState } from '@/hooks/use-ai-calls-query-state';
19
20
  import { getSigNozStatsClient } from '@/lib/api/signoz-stats';
20
- import { UNKNOWN_VALUE } from '@/constants/signoz';
21
21
 
22
22
  // Time range options
23
23
  const TIME_RANGES = {
@@ -1,7 +1,7 @@
1
- import { Skeleton } from '@/components/ui/skeleton';
1
+ import { AreaChart, type AreaChartProps } from '@/components/traces/charts/area-chart';
2
2
  import { ChartCard, type ChartCardProps } from '@/components/traces/charts/chart-card';
3
3
  import { ChartNoResults } from '@/components/traces/charts/chart-no-results';
4
- import { AreaChart, type AreaChartProps } from '@/components/traces/charts/area-chart';
4
+ import { Skeleton } from '@/components/ui/skeleton';
5
5
 
6
6
  type AreaChartCardProps<TData> = AreaChartProps<TData> &
7
7
  Pick<
@@ -1,10 +1,10 @@
1
+ import { Area, CartesianGrid, AreaChart as RechartsAreaChart, XAxis, YAxis } from 'recharts';
1
2
  import {
3
+ type ChartConfig,
2
4
  ChartContainer,
3
5
  ChartTooltip,
4
6
  ChartTooltipContent,
5
- type ChartConfig,
6
7
  } from '@/components/ui/chart';
7
- import { AreaChart as RechartsAreaChart, Area, XAxis, YAxis, CartesianGrid } from 'recharts';
8
8
 
9
9
  export interface AreaChartProps<TData> {
10
10
  data?: TData[];
@@ -1,3 +1,7 @@
1
+ import type { LucideIcon } from 'lucide-react';
2
+ import { ArrowUpRight, Info } from 'lucide-react';
3
+ import { ErrorBoundary } from 'react-error-boundary';
4
+ import { Button } from '@/components/ui/button';
1
5
  import {
2
6
  Card,
3
7
  CardContent,
@@ -8,11 +12,7 @@ import {
8
12
  } from '@/components/ui/card';
9
13
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
10
14
  import { cn } from '@/lib/utils';
11
- import type { LucideIcon } from 'lucide-react';
12
- import { ArrowUpRight, Info } from 'lucide-react';
13
15
  import { ChartError } from './chart-error';
14
- import { Button } from '@/components/ui/button';
15
- import { ErrorBoundary } from 'react-error-boundary';
16
16
 
17
17
  export interface ChartCardProps {
18
18
  className?: string;
@@ -2,21 +2,20 @@
2
2
 
3
3
  import { Activity, ArrowLeft, MessageSquare, TriangleAlert } from 'lucide-react';
4
4
  import { useEffect, useState } from 'react';
5
- import { Badge } from '@/components/ui/badge';
6
- import { Button } from '@/components/ui/button';
7
- import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
8
- import { Skeleton } from '@/components/ui/skeleton';
5
+ import { formatDateTime, formatDuration } from '@/app/utils/format-date';
9
6
  import type {
10
7
  ActivityItem,
11
8
  ConversationDetail as ConversationDetailType,
12
9
  } from '@/components/traces/timeline/types';
13
- import { formatDateTime } from '@/app/utils/format-date';
10
+ import { Badge } from '@/components/ui/badge';
11
+ import { Button } from '@/components/ui/button';
12
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
13
+ import { ResizablePanelGroup } from '@/components/ui/resizable';
14
+ import { Skeleton } from '@/components/ui/skeleton';
14
15
  import { ConversationErrors } from './conversation-errors';
15
16
  import { SignozLink } from './signoz-link';
16
- import { formatDuration } from '@/app/utils/format-date';
17
17
  import { InfoRow } from './timeline/blocks';
18
18
  import { TimelineWrapper } from './timeline/timeline-wrapper';
19
- import { ResizablePanelGroup } from '@/components/ui/resizable';
20
19
 
21
20
  interface ConversationDetailProps {
22
21
  conversationId: string;
@@ -109,7 +108,10 @@ export function ConversationDetail({ conversationId, onBack }: ConversationDetai
109
108
  </Badge>
110
109
  {(conversation.graphId || conversation.graphName) && (
111
110
  <Badge variant="code" className="text-xs">
112
- Graph: {conversation.graphName ? `${conversation.graphName} (${conversation.graphId})` : conversation.graphId}
111
+ Graph:{' '}
112
+ {conversation.graphName
113
+ ? `${conversation.graphName} (${conversation.graphId})`
114
+ : conversation.graphId}
113
115
  </Badge>
114
116
  )}
115
117
  </div>
@@ -1,8 +1,8 @@
1
- import type { ConversationStats } from '@/lib/api/signoz-stats';
2
- import { Badge } from '@/components/ui/badge';
3
1
  import Link from 'next/link';
4
- import { TooltipContent, Tooltip, TooltipTrigger } from '@/components/ui/tooltip';
5
2
  import { formatDateAgo, formatDateTime } from '@/app/utils/format-date';
3
+ import { Badge } from '@/components/ui/badge';
4
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
5
+ import type { ConversationStats } from '@/lib/api/signoz-stats';
6
6
 
7
7
  interface ConversationListItemProps {
8
8
  conversation: ConversationStats;
@@ -10,8 +10,17 @@ interface ConversationListItemProps {
10
10
  }
11
11
 
12
12
  export function ConversationListItem({ conversation, projectId }: ConversationListItemProps) {
13
- const { conversationId, firstUserMessage, tenantId, graphId, graphName, hasErrors, totalErrors, toolsUsed, startTime } =
14
- conversation;
13
+ const {
14
+ conversationId,
15
+ firstUserMessage,
16
+ tenantId,
17
+ graphId,
18
+ graphName,
19
+ hasErrors,
20
+ totalErrors,
21
+ toolsUsed,
22
+ startTime,
23
+ } = conversation;
15
24
 
16
25
  return (
17
26
  <Link
@@ -26,38 +35,40 @@ export function ConversationListItem({ conversation, projectId }: ConversationLi
26
35
  </div>
27
36
 
28
37
  <div className="flex items-center gap-2 text-xs">
29
- <code className="font-mono text-gray-500 dark:text-white/50">
30
- {conversationId}
31
- </code>
32
- {startTime && (() => {
33
- try {
34
- const date = new Date(startTime);
35
- // Check if the date is valid
36
- if (isNaN(date.getTime())) return null;
37
-
38
- const isoString = date.toISOString();
39
- return (
40
- <>
41
- <span className="text-gray-400 dark:text-white/40">•</span>
42
- <Tooltip>
43
- <TooltipTrigger asChild>
44
- <span className="text-gray-400 dark:text-white/40 cursor-help">
45
- {formatDateAgo(isoString)}
46
- </span>
47
- </TooltipTrigger>
48
- <TooltipContent>
49
- <p className="text-xs">
50
- Started: {formatDateTime(isoString)}
51
- </p>
52
- </TooltipContent>
53
- </Tooltip>
54
- </>
55
- );
56
- } catch (error) {
57
- console.warn('Invalid startTime for conversation:', conversationId, startTime, error);
58
- return null;
59
- }
60
- })()}
38
+ <code className="font-mono text-gray-500 dark:text-white/50">{conversationId}</code>
39
+ {startTime &&
40
+ (() => {
41
+ try {
42
+ const date = new Date(startTime);
43
+ // Check if the date is valid
44
+ if (isNaN(date.getTime())) return null;
45
+
46
+ const isoString = date.toISOString();
47
+ return (
48
+ <>
49
+ <span className="text-gray-400 dark:text-white/40">•</span>
50
+ <Tooltip>
51
+ <TooltipTrigger asChild>
52
+ <span className="text-gray-400 dark:text-white/40 cursor-help">
53
+ {formatDateAgo(isoString)}
54
+ </span>
55
+ </TooltipTrigger>
56
+ <TooltipContent>
57
+ <p className="text-xs">Started: {formatDateTime(isoString)}</p>
58
+ </TooltipContent>
59
+ </Tooltip>
60
+ </>
61
+ );
62
+ } catch (error) {
63
+ console.warn(
64
+ 'Invalid startTime for conversation:',
65
+ conversationId,
66
+ startTime,
67
+ error
68
+ );
69
+ return null;
70
+ }
71
+ })()}
61
72
  </div>
62
73
  </div>
63
74
  <div className="flex items-center gap-2">
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
- import React from 'react';
4
3
  import { ChevronLeft, ChevronRight, MessageSquare, Search, X } from 'lucide-react';
4
+ import React from 'react';
5
5
  import { Badge } from '@/components/ui/badge';
6
6
  import { Button } from '@/components/ui/button';
7
7
  import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@@ -1,18 +1,18 @@
1
1
  'use client';
2
2
 
3
+ import { format } from 'date-fns';
4
+ import { Check } from 'lucide-react';
5
+ import { useMemo, useRef, useState } from 'react';
6
+ import type { DateRange } from 'react-day-picker';
3
7
  import type { SelectOption } from '@/components/form/generic-select';
4
- import { FilterTriggerComponent } from './filter-trigger';
5
8
  import { Button } from '@/components/ui/button';
6
9
  import { Calendar } from '@/components/ui/calendar';
7
10
  import { Command, CommandGroup, CommandItem, CommandList } from '@/components/ui/command';
8
11
  import { Popover, PopoverContent } from '@/components/ui/popover';
9
12
  import { useDisclosure } from '@/hooks/use-disclosure';
10
- import { cn } from '@/lib/utils';
11
- import { format } from 'date-fns';
12
- import { Check } from 'lucide-react';
13
- import { useMemo, useRef, useState } from 'react';
14
- import type { DateRange } from 'react-day-picker';
15
13
  import type { TimeRange } from '@/hooks/use-traces-query-state';
14
+ import { cn } from '@/lib/utils';
15
+ import { FilterTriggerComponent } from './filter-trigger';
16
16
 
17
17
  interface DatePickerWithPresetsProps {
18
18
  label: string;
@@ -1,7 +1,7 @@
1
1
  import { ChevronDown, type LucideIcon, X } from 'lucide-react';
2
2
  import { Button } from '@/components/ui/button';
3
- import { PopoverTrigger } from '@/components/ui/popover';
4
3
  import type { OptionType } from '@/components/ui/combobox';
4
+ import { PopoverTrigger } from '@/components/ui/popover';
5
5
 
6
6
  interface FilterTriggerComponentProps {
7
7
  Icon?: LucideIcon;
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
- import { useState, useEffect } from 'react';
4
3
  import { useParams } from 'next/navigation';
5
- import { getAllGraphsAction } from '@/lib/actions/graph-full';
4
+ import { useEffect, useState } from 'react';
5
+ import type { OptionType } from '@/components/ui/combobox';
6
6
  import { Combobox } from '@/components/ui/combobox';
7
+ import { getAllGraphsAction } from '@/lib/actions/graph-full';
7
8
  import { FilterTriggerComponent } from './filter-trigger';
8
- import type { OptionType } from '@/components/ui/combobox';
9
9
 
10
10
  interface GraphFilterProps {
11
11
  onSelect: (value: string | undefined) => void;
@@ -1,5 +1,5 @@
1
- import { Button } from '@/components/ui/button';
2
1
  import { X } from 'lucide-react';
2
+ import { Button } from '@/components/ui/button';
3
3
 
4
4
  export function ActivityDetailsSidePane({
5
5
  title,
@@ -1,5 +1,5 @@
1
- import type { ActivityItem } from '@/components/traces/timeline/types';
2
1
  import { TimelineItem } from '@/components/traces/timeline/timeline-item';
2
+ import type { ActivityItem } from '@/components/traces/timeline/types';
3
3
 
4
4
  export function ActivityTimeline({
5
5
  activities,
@@ -1,7 +1,7 @@
1
- import { Badge } from '@/components/ui/badge';
2
- import type { ActivityItem } from './types';
3
1
  import { AnthropicIcon } from '@/components/icons/anthropic';
4
2
  import { OpenAIIcon } from '@/components/icons/openai';
3
+ import { Badge } from '@/components/ui/badge';
4
+ import type { ActivityItem } from './types';
5
5
 
6
6
  export function LabeledBlock({ label, children }: { label: string; children: React.ReactNode }) {
7
7
  return (
@@ -1,17 +1,17 @@
1
- import { SelectedPanel } from '@/components/traces/timeline/types';
2
- import { Section } from '@/components/traces/timeline/blocks';
3
- import { Info } from '@/components/traces/timeline/blocks';
4
1
  import { Streamdown } from 'streamdown';
5
- import { LabeledBlock } from '@/components/traces/timeline/blocks';
6
- import { Bubble } from '@/components/traces/timeline/bubble';
7
- import { StatusBadge } from '@/components/traces/timeline/blocks';
8
2
  import { formatDateTime } from '@/app/utils/format-date';
9
- import { Divider } from '@/components/traces/timeline/blocks';
10
- import { Badge } from '@/components/ui/badge';
11
- import type { ConversationDetail } from '@/components/traces/timeline/types';
12
- import { ModelBadge } from '@/components/traces/timeline/blocks';
13
- import { CodeBubble } from '@/components/traces/timeline/bubble';
14
3
  import { SignozSpanLink } from '@/components/traces/signoz-link';
4
+ import {
5
+ Divider,
6
+ Info,
7
+ LabeledBlock,
8
+ ModelBadge,
9
+ Section,
10
+ StatusBadge,
11
+ } from '@/components/traces/timeline/blocks';
12
+ import { Bubble, CodeBubble } from '@/components/traces/timeline/bubble';
13
+ import type { ConversationDetail, SelectedPanel } from '@/components/traces/timeline/types';
14
+ import { Badge } from '@/components/ui/badge';
15
15
 
16
16
  export function renderPanelContent({
17
17
  selected,