@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.
- package/.env.example +10 -0
- package/.turbo/turbo-build.log +48 -54
- package/.turbo/turbo-test.log +7 -7
- package/.turbo/turbo-typecheck.log +1 -1
- package/LICENSE.md +22 -17
- package/README.md +3 -3
- package/biome.json +3 -0
- package/package.json +10 -9
- package/src/app/api/signoz/conversations/[conversationId]/route.ts +95 -34
- package/src/app/api/signoz/route.ts +8 -6
- package/src/components/api-keys/form/api-key-form.tsx +2 -0
- package/src/components/api-keys/form/validation.ts +1 -1
- package/src/components/artifact-components/form/artifact-component-form.tsx +20 -6
- package/src/components/artifact-components/form/validation.ts +3 -3
- package/src/components/credentials/views/credential-form-validation.ts +1 -1
- package/src/components/credentials/views/credential-form.tsx +2 -0
- package/src/components/credentials/views/edit-credential-form.tsx +1 -1
- package/src/components/credentials/views/generic-auth-form.tsx +1 -1
- package/src/components/data-components/form/data-component-form.tsx +19 -1
- package/src/components/data-components/form/validation.ts +3 -2
- package/src/components/form/expandable-field.tsx +6 -1
- package/src/components/form/form-field-wrapper.tsx +3 -1
- package/src/components/form/generic-combo-box.tsx +3 -1
- package/src/components/form/generic-input.tsx +9 -1
- package/src/components/form/generic-select.tsx +3 -1
- package/src/components/form/generic-textarea.tsx +3 -1
- package/src/components/form/json-schema-input.tsx +9 -1
- package/src/components/graph/configuration/node-types.tsx +2 -4
- package/src/components/graph/graph.tsx +4 -26
- package/src/components/graph/nodes/agent-node.tsx +1 -1
- package/src/components/graph/nodes/external-agent-node.tsx +1 -1
- package/src/components/graph/playground/chat-widget.tsx +31 -2
- package/src/components/graph/playground/ikp-message.tsx +16 -16
- package/src/components/graph/playground/playground.tsx +12 -6
- package/src/components/graph/sidepane/metadata/metadata-editor.tsx +62 -45
- package/src/components/graph/sidepane/nodes/agent-node-editor.tsx +56 -27
- package/src/components/graph/sidepane/nodes/expandable-text-area.tsx +3 -1
- package/src/components/graph/sidepane/nodes/external-agent-node-editor.tsx +31 -11
- package/src/components/graph/sidepane/nodes/form-fields.tsx +10 -1
- package/src/components/graph/sidepane/nodes/mcp-node-editor.tsx +4 -9
- package/src/components/graph/sidepane/nodes/model-section.tsx +1 -1
- package/src/components/graph/toolbar/toolbar.tsx +1 -1
- package/src/components/mcp-servers/form/active-tools-selector.tsx +4 -2
- package/src/components/mcp-servers/form/mcp-server-form.tsx +8 -1
- package/src/components/mcp-servers/form/validation.ts +1 -1
- package/src/components/projects/edit-project-dialog.tsx +1 -1
- package/src/components/projects/form/project-form.tsx +20 -8
- package/src/components/projects/form/project-models-section.tsx +51 -23
- package/src/components/projects/form/project-stopwhen-section.tsx +25 -11
- package/src/components/projects/form/validation.ts +14 -10
- package/src/components/projects/new-project-dialog.tsx +1 -1
- package/src/components/traces/ai-calls-breakdown.tsx +1 -1
- package/src/components/traces/charts/area-chart-card.tsx +2 -2
- package/src/components/traces/charts/area-chart.tsx +2 -2
- package/src/components/traces/charts/chart-card.tsx +4 -4
- package/src/components/traces/conversation-detail.tsx +10 -8
- package/src/components/traces/conversation-stats/conversation-list-item.tsx +48 -37
- package/src/components/traces/conversation-stats/conversation-stats-card.tsx +1 -1
- package/src/components/traces/filters/date-picker.tsx +6 -6
- package/src/components/traces/filters/filter-trigger.tsx +1 -1
- package/src/components/traces/filters/graph-filter.tsx +3 -3
- package/src/components/traces/timeline/activity-details-sidepane.tsx +1 -1
- package/src/components/traces/timeline/activity-timeline.tsx +1 -1
- package/src/components/traces/timeline/blocks.tsx +2 -2
- package/src/components/traces/timeline/render-panel-content.tsx +11 -11
- package/src/components/traces/timeline/timeline-item.tsx +36 -22
- package/src/components/traces/timeline/timeline-wrapper.tsx +125 -37
- package/src/components/traces/traces-overview.tsx +3 -3
- package/src/components/ui/alert.tsx +60 -0
- package/src/components/ui/calendar.tsx +3 -4
- package/src/components/ui/external-link.tsx +2 -2
- package/src/components/ui/form.tsx +11 -4
- package/src/components/ui/inheritance-indicator.tsx +20 -17
- package/src/components/ui/resizable.tsx +13 -18
- package/src/constants/page-descriptions.tsx +2 -5
- package/src/constants/signoz.ts +15 -18
- package/src/features/graph/domain/__tests__/roundtrip.test.ts +5 -5
- package/src/features/graph/domain/serialize.ts +8 -9
- package/src/hooks/use-auto-prefill-id-zustand.ts +68 -0
- package/src/hooks/use-auto-prefill-id.ts +36 -0
- package/src/hooks/use-chat-activities-polling.ts +45 -12
- package/src/hooks/use-graph-errors.ts +2 -1
- package/src/hooks/use-project-data.ts +2 -2
- package/src/lib/actions/graph-full.ts +6 -2
- package/src/lib/actions/projects.ts +1 -1
- package/src/lib/api/api-config.ts +6 -6
- package/src/lib/api/api-keys.ts +4 -1
- package/src/lib/api/credentials.ts +1 -1
- package/src/lib/api/data-components.ts +1 -1
- package/src/lib/api/graph-full-client.ts +6 -3
- package/src/lib/api/projects.ts +1 -1
- package/src/lib/api/signoz-sql.ts +1 -1
- package/src/lib/api/signoz-stats.ts +958 -304
- package/src/lib/index.ts +1 -1
- package/src/lib/logger.ts +1 -2
- package/src/lib/types/graph-full.ts +1 -1
- package/src/lib/utils/generate-id.ts +14 -0
- package/src/lib/validation.ts +1 -1
- package/tsconfig.json +2 -2
- package/.env.sample +0 -5
- 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 {
|
|
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({
|
|
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={
|
|
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({
|
|
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={
|
|
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({
|
|
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={
|
|
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
|
|
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">
|
|
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
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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 {
|
|
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
|
|
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">
|
|
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
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
<li
|
|
82
|
-
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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:
|
|
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 {
|
|
14
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
</
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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 {
|
|
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 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,
|