@agent-native/toolkit 0.198.2 → 0.198.3-nightly-20260930154911
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +13 -5
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +20 -6
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +211 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +147 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +147 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +147 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +163 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +163 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +147 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +131 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +131 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +163 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +131 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +131 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/observability/ObservabilityDashboard.d.ts.map +1 -1
- package/dist/app/observability/ObservabilityDashboard.js +101 -109
- package/dist/app/observability/ObservabilityDashboard.js.map +1 -1
- package/dist/app/observability/RunInsights.d.ts +22 -0
- package/dist/app/observability/RunInsights.d.ts.map +1 -0
- package/dist/app/observability/RunInsights.js +658 -0
- package/dist/app/observability/RunInsights.js.map +1 -0
- package/dist/composer/RealtimeVoiceMode.d.ts.map +1 -1
- package/dist/composer/RealtimeVoiceMode.js +1 -1
- package/dist/composer/RealtimeVoiceMode.js.map +1 -1
- package/package.json +5 -5
- package/src/app/agent-page/ConnectionsTab.spec.tsx +0 -3
- package/src/app/agentkit/react/components.spec.tsx +2 -1
- package/src/app/agentkit/react/components.tsx +14 -5
- package/src/app/agentkit/react/composer-context.spec.tsx +4 -1
- package/src/app/agentkit/react/suggestions.spec.tsx +51 -1
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +57 -0
- package/src/app/chat/AgentKitAssistantChat.tsx +44 -8
- package/src/app/chat/AgentPanel.header.spec.ts +22 -22
- package/src/app/chat/agentkit-chat/action-widget.spec.tsx +17 -2
- package/src/app/chat/agentkit-chat/approval-card.spec.tsx +2 -2
- package/src/app/chat/agentkit-chat/connections.spec.tsx +1 -1
- package/src/app/chat/chat/markdown-renderer.spec.tsx +1 -1
- package/src/app/chat/chat/tool-call-display.spec.tsx +25 -2
- package/src/app/chat/chat/widgets/DataTableWidget.spec.tsx +38 -26
- package/src/app/chat/chat/widgets/agent-team-progress-widget.spec.tsx +7 -1
- package/src/app/chat/chat/widgets/builtin-connect-required-renderer.spec.tsx +24 -1
- package/src/app/chat/chat/widgets/record-change-widget.spec.tsx +16 -1
- package/src/app/chat/thinking-display.spec.tsx +1 -1
- package/src/app/db-admin/useAgentSync.spec.tsx +1 -1
- package/src/app/extensions/ExtensionViewer.spec.tsx +2 -1
- package/src/app/i18n/catalogs/ar-SA.ts +282 -0
- package/src/app/i18n/catalogs/de-DE.ts +198 -0
- package/src/app/i18n/catalogs/en-US.ts +187 -0
- package/src/app/i18n/catalogs/es-ES.ts +221 -0
- package/src/app/i18n/catalogs/fr-FR.ts +219 -0
- package/src/app/i18n/catalogs/hi-IN.ts +182 -0
- package/src/app/i18n/catalogs/ja-JP.ts +160 -0
- package/src/app/i18n/catalogs/ko-KR.ts +160 -0
- package/src/app/i18n/catalogs/pt-BR.ts +220 -0
- package/src/app/i18n/catalogs/zh-CN.ts +154 -0
- package/src/app/i18n/catalogs/zh-TW.ts +154 -0
- package/src/app/integrations/BuilderIntegrationPage.spec.tsx +3 -3
- package/src/app/integrations/ChannelsPage.spec.tsx +3 -3
- package/src/app/integrations/IntegrationsPage.spec.tsx +3 -3
- package/src/app/integrations/IntegrationsPanel.spec.tsx +7 -4
- package/src/app/observability/ObservabilityDashboard.review.spec.tsx +211 -52
- package/src/app/observability/ObservabilityDashboard.spec.tsx +80 -20
- package/src/app/observability/ObservabilityDashboard.tsx +240 -400
- package/src/app/observability/RunInsights.tsx +1603 -0
- package/src/app/observability/ThumbsFeedback.spec.tsx +29 -12
- package/src/app/onboarding/FirstRunOnboarding.spec.tsx +25 -5
- package/src/app/onboarding/first-run-startup-gate.spec.tsx +12 -7
- package/src/app/resources/McpConnectionSuggestion.render.spec.tsx +43 -5
- package/src/app/resources/McpIntegrationDialog.spec.tsx +20 -14
- package/src/app/resources/ResourcesPanel.spec.ts +9 -7
- package/src/app/review/ReviewThreadPanel.spec.tsx +2 -2
- package/src/app/settings/SecretsSection.spec.tsx +12 -3
- package/src/app/settings/SettingsTabsPage.spec.tsx +4 -1
- package/src/app/settings/VoiceTranscriptionSection.spec.tsx +12 -1
- package/src/app/settings/account/PreferencesSettings.spec.tsx +13 -1
- package/src/app/settings/account/ProfileSettings.spec.tsx +13 -1
- package/src/app/settings/account/SecuritySettings.spec.tsx +12 -1
- package/src/app/settings/shell/SettingsShell.spec.tsx +35 -15
- package/src/app/settings/shell/pages/app-group-pages.spec.tsx +7 -0
- package/src/app/settings/shell/pages/audit.spec.tsx +5 -2
- package/src/app/settings/shell/pages/resource-pages.spec.tsx +25 -16
- package/src/app/settings/shell/pages/sub-agents.spec.tsx +24 -15
- package/src/app/settings/usage/UsagePage.spec.tsx +4 -0
- package/src/app/setup-connections/BuilderConnectCard.spec.tsx +27 -8
- package/src/app/sharing/ShareButton.spec.tsx +7 -3
- package/src/app/sharing/ShareDialog.spec.tsx +4 -4
- package/src/app/sharing/useShareButtonController.spec.tsx +1 -1
- package/src/app/sharing/useShareDialogController.spec.tsx +2 -2
- package/src/app/transcription/BuilderTranscriptionCta.spec.tsx +1 -1
- package/src/composer/RealtimeVoiceMode.spec.tsx +1 -0
- package/src/composer/RealtimeVoiceMode.tsx +1 -5
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
requestAgentChatThreadOpen,
|
|
3
2
|
sendToAgentChat,
|
|
4
3
|
sendToAgentChatAndConfirm,
|
|
5
4
|
} from "@agent-native/core/client/agent-chat";
|
|
@@ -49,8 +48,6 @@ import {
|
|
|
49
48
|
IconMessages,
|
|
50
49
|
IconThumbUp,
|
|
51
50
|
IconThumbDown,
|
|
52
|
-
IconClock,
|
|
53
|
-
IconCoin,
|
|
54
51
|
IconTool,
|
|
55
52
|
IconMoodSmile,
|
|
56
53
|
IconChartBar,
|
|
@@ -78,9 +75,13 @@ import {
|
|
|
78
75
|
type ObservabilityReviewSummaryStatus,
|
|
79
76
|
} from "./ObservabilityReviewSummaryButton.js";
|
|
80
77
|
import { OutputPreview, parseOutputPreview } from "./OutputPreview.js";
|
|
78
|
+
import {
|
|
79
|
+
RunInsightsConversations,
|
|
80
|
+
RunInsightsOverview,
|
|
81
|
+
type RunFilter,
|
|
82
|
+
} from "./RunInsights.js";
|
|
81
83
|
import {
|
|
82
84
|
useObservabilityOverview,
|
|
83
|
-
useTraces,
|
|
84
85
|
useTraceDetail,
|
|
85
86
|
usePromoteTraceEval,
|
|
86
87
|
useFeedbackList,
|
|
@@ -93,23 +94,9 @@ import {
|
|
|
93
94
|
useOutputReviewDetail,
|
|
94
95
|
useSaveInstructionUpdate,
|
|
95
96
|
useSaveReviewFeedback,
|
|
96
|
-
type TraceSummary,
|
|
97
97
|
type Experiment,
|
|
98
98
|
} from "./useObservability.js";
|
|
99
99
|
|
|
100
|
-
function formatCost(centsX100: number): string {
|
|
101
|
-
const cents = centsX100 / 100;
|
|
102
|
-
if (cents < 1) return `${cents.toFixed(3)}¢`;
|
|
103
|
-
if (cents < 100) return `${cents.toFixed(2)}¢`;
|
|
104
|
-
return `$${(cents / 100).toFixed(2)}`;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function formatCostCents(cents: number): string {
|
|
108
|
-
if (cents < 1) return `${cents.toFixed(3)}¢`;
|
|
109
|
-
if (cents < 100) return `${cents.toFixed(2)}¢`;
|
|
110
|
-
return `$${(cents / 100).toFixed(2)}`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
100
|
function formatDuration(ms: number): string {
|
|
114
101
|
if (ms < 1000) return `${Math.round(ms)}ms`;
|
|
115
102
|
if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
|
|
@@ -454,144 +441,58 @@ function LoadingState() {
|
|
|
454
441
|
);
|
|
455
442
|
}
|
|
456
443
|
|
|
457
|
-
function OverviewTab({
|
|
444
|
+
function OverviewTab({
|
|
445
|
+
days,
|
|
446
|
+
onShowRuns,
|
|
447
|
+
}: {
|
|
448
|
+
days: number;
|
|
449
|
+
onShowRuns: (filter: RunFilter) => void;
|
|
450
|
+
}) {
|
|
458
451
|
const t = useT();
|
|
459
|
-
const { data
|
|
460
|
-
|
|
461
|
-
if (isLoading) return <LoadingState />;
|
|
462
|
-
if (!data) return <EmptyState message={t("observability.noData")} />;
|
|
463
|
-
|
|
452
|
+
const { data } = useObservabilityOverview(days);
|
|
464
453
|
return (
|
|
465
|
-
<
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
value={formatPercent(data.toolSuccessRate)}
|
|
484
|
-
icon={<IconTool size={16} />}
|
|
485
|
-
/>
|
|
486
|
-
<MetricCard
|
|
487
|
-
label={t("observability.thumbsUp")}
|
|
488
|
-
value={formatPercent(data.thumbsUpRate)}
|
|
489
|
-
icon={<IconThumbUp size={16} />}
|
|
490
|
-
/>
|
|
491
|
-
<MetricCard
|
|
492
|
-
label={t("observability.avgEvalScore")}
|
|
493
|
-
value={data.avgEvalScore.toFixed(2)}
|
|
494
|
-
icon={<IconMoodSmile size={16} />}
|
|
495
|
-
/>
|
|
496
|
-
</div>
|
|
454
|
+
<RunInsightsOverview
|
|
455
|
+
days={days}
|
|
456
|
+
onShowRuns={onShowRuns}
|
|
457
|
+
extraStats={
|
|
458
|
+
data
|
|
459
|
+
? [
|
|
460
|
+
{
|
|
461
|
+
label: t("observability.thumbsUp"),
|
|
462
|
+
value: formatPercent(data.thumbsUpRate),
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
label: t("observability.avgEvalScore"),
|
|
466
|
+
value: data.avgEvalScore.toFixed(2),
|
|
467
|
+
},
|
|
468
|
+
]
|
|
469
|
+
: []
|
|
470
|
+
}
|
|
471
|
+
/>
|
|
497
472
|
);
|
|
498
473
|
}
|
|
499
474
|
|
|
500
|
-
function ConversationsTab({
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
runId={selectedRunId}
|
|
510
|
-
onBack={() => setSelectedRunId(null)}
|
|
511
|
-
/>
|
|
512
|
-
);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
if (isLoading) return <LoadingState />;
|
|
516
|
-
if (!traces || traces.length === 0)
|
|
517
|
-
return <EmptyState message={t("observability.noConversations")} />;
|
|
518
|
-
|
|
475
|
+
function ConversationsTab({
|
|
476
|
+
days,
|
|
477
|
+
filter,
|
|
478
|
+
onClearFilter,
|
|
479
|
+
}: {
|
|
480
|
+
days: number;
|
|
481
|
+
filter: RunFilter | null;
|
|
482
|
+
onClearFilter: () => void;
|
|
483
|
+
}) {
|
|
519
484
|
return (
|
|
520
|
-
<
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
</th>
|
|
527
|
-
<th className="px-3 py-2 font-medium text-muted-foreground w-[20%]">
|
|
528
|
-
{t("observability.model")}
|
|
529
|
-
</th>
|
|
530
|
-
<th className="px-3 py-2 font-medium text-muted-foreground">
|
|
531
|
-
{t("observability.duration")}
|
|
532
|
-
</th>
|
|
533
|
-
<th className="px-3 py-2 font-medium text-muted-foreground">
|
|
534
|
-
{t("observability.cost")}
|
|
535
|
-
</th>
|
|
536
|
-
<th className="px-3 py-2 font-medium text-muted-foreground">
|
|
537
|
-
{t("observability.tools")}
|
|
538
|
-
</th>
|
|
539
|
-
<th className="px-3 py-2 font-medium text-muted-foreground">
|
|
540
|
-
{t("observability.time")}
|
|
541
|
-
</th>
|
|
542
|
-
<th className="w-8" />
|
|
543
|
-
</tr>
|
|
544
|
-
</thead>
|
|
545
|
-
<tbody>
|
|
546
|
-
{traces.map((trace: TraceSummary) => (
|
|
547
|
-
<tr
|
|
548
|
-
key={trace.runId}
|
|
549
|
-
onClick={() => setSelectedRunId(trace.runId)}
|
|
550
|
-
className="border-b border-border last:border-b-0 cursor-pointer hover:bg-accent/30"
|
|
551
|
-
>
|
|
552
|
-
<td className="px-3 py-2 font-mono text-foreground truncate">
|
|
553
|
-
{truncateId(trace.runId)}
|
|
554
|
-
</td>
|
|
555
|
-
<td className="px-3 py-2 text-muted-foreground truncate">
|
|
556
|
-
{trace.model || "unknown"}
|
|
557
|
-
</td>
|
|
558
|
-
<td className="px-3 py-2 tabular-nums text-muted-foreground">
|
|
559
|
-
{formatDuration(trace.totalDurationMs)}
|
|
560
|
-
</td>
|
|
561
|
-
<td className="px-3 py-2 tabular-nums text-muted-foreground">
|
|
562
|
-
{formatCost(trace.totalCostCentsX100)}
|
|
563
|
-
</td>
|
|
564
|
-
<td className="px-3 py-2 tabular-nums text-muted-foreground">
|
|
565
|
-
{trace.toolCalls}
|
|
566
|
-
{trace.failedTools > 0 && (
|
|
567
|
-
<span className="ml-1 text-red-500">
|
|
568
|
-
{t("observability.failedCount", {
|
|
569
|
-
count: trace.failedTools,
|
|
570
|
-
})}
|
|
571
|
-
</span>
|
|
572
|
-
)}
|
|
573
|
-
</td>
|
|
574
|
-
<td className="px-3 py-2 text-muted-foreground truncate">
|
|
575
|
-
{timeAgo(trace.createdAt)}
|
|
576
|
-
</td>
|
|
577
|
-
<td className="px-3 py-2">
|
|
578
|
-
<IconChevronRight size={14} className="text-muted-foreground" />
|
|
579
|
-
</td>
|
|
580
|
-
</tr>
|
|
581
|
-
))}
|
|
582
|
-
</tbody>
|
|
583
|
-
</table>
|
|
584
|
-
</div>
|
|
485
|
+
<RunInsightsConversations
|
|
486
|
+
days={days}
|
|
487
|
+
filter={filter}
|
|
488
|
+
onClearFilter={onClearFilter}
|
|
489
|
+
renderRawTrace={(runId) => <RawTrace runId={runId} />}
|
|
490
|
+
/>
|
|
585
491
|
);
|
|
586
492
|
}
|
|
587
493
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
onBack,
|
|
591
|
-
}: {
|
|
592
|
-
runId: string;
|
|
593
|
-
onBack: () => void;
|
|
594
|
-
}) {
|
|
494
|
+
/** Every recorded span for a run, with inputs, outputs and metadata when captured. */
|
|
495
|
+
function RawTrace({ runId }: { runId: string }) {
|
|
595
496
|
const t = useT();
|
|
596
497
|
const { data, isLoading } = useTraceDetail(runId);
|
|
597
498
|
const [expandedSpanId, setExpandedSpanId] = useState<string | null>(null);
|
|
@@ -602,280 +503,209 @@ function TraceDetailView({
|
|
|
602
503
|
const canPromote =
|
|
603
504
|
!!data && !promote.isPending && (!needsNeedle || needle.length > 0);
|
|
604
505
|
|
|
506
|
+
if (isLoading) return <LoadingState />;
|
|
507
|
+
if (!data) return null;
|
|
605
508
|
return (
|
|
606
|
-
<div>
|
|
607
|
-
<div className="
|
|
509
|
+
<div className="space-y-3">
|
|
510
|
+
<div className="flex flex-wrap items-center justify-end gap-2">
|
|
511
|
+
<input
|
|
512
|
+
type="text"
|
|
513
|
+
value={mustContain}
|
|
514
|
+
onChange={(event) => setMustContain(event.target.value)}
|
|
515
|
+
disabled={promote.isPending}
|
|
516
|
+
placeholder={t(
|
|
517
|
+
needsNeedle
|
|
518
|
+
? "observability.promoteMustContain"
|
|
519
|
+
: "observability.promoteMustContainOptional",
|
|
520
|
+
)}
|
|
521
|
+
aria-label={t("observability.promoteMustContainLabel", {
|
|
522
|
+
defaultValue: "Text the promoted eval reply must contain",
|
|
523
|
+
})}
|
|
524
|
+
className="w-56 rounded-md border border-border bg-background px-2.5 py-1 text-xs text-foreground placeholder:text-muted-foreground disabled:opacity-50"
|
|
525
|
+
/>
|
|
608
526
|
<button
|
|
609
|
-
|
|
610
|
-
|
|
527
|
+
type="button"
|
|
528
|
+
disabled={!canPromote}
|
|
529
|
+
onClick={() =>
|
|
530
|
+
promote.mutate({
|
|
531
|
+
runId,
|
|
532
|
+
...(needle ? { mustContain: needle } : {}),
|
|
533
|
+
})
|
|
534
|
+
}
|
|
535
|
+
className="rounded-md border border-border bg-background px-2.5 py-1 text-xs font-medium text-foreground hover:bg-accent disabled:opacity-50"
|
|
611
536
|
>
|
|
612
|
-
|
|
613
|
-
|
|
537
|
+
{promote.isPending
|
|
538
|
+
? t("observability.promotingToEval")
|
|
539
|
+
: t("observability.promoteToEval")}
|
|
614
540
|
</button>
|
|
615
|
-
<div className="flex flex-wrap items-center justify-end gap-2">
|
|
616
|
-
<input
|
|
617
|
-
type="text"
|
|
618
|
-
value={mustContain}
|
|
619
|
-
onChange={(event) => setMustContain(event.target.value)}
|
|
620
|
-
disabled={promote.isPending || !data}
|
|
621
|
-
placeholder={t(
|
|
622
|
-
needsNeedle
|
|
623
|
-
? "observability.promoteMustContain"
|
|
624
|
-
: "observability.promoteMustContainOptional",
|
|
625
|
-
)}
|
|
626
|
-
aria-label={t("observability.promoteMustContainLabel", {
|
|
627
|
-
defaultValue: "Text the promoted eval reply must contain",
|
|
628
|
-
})}
|
|
629
|
-
className="w-56 rounded-md border border-border bg-background px-2.5 py-1 text-xs text-foreground placeholder:text-muted-foreground disabled:opacity-50"
|
|
630
|
-
/>
|
|
631
|
-
<button
|
|
632
|
-
type="button"
|
|
633
|
-
disabled={!canPromote}
|
|
634
|
-
onClick={() =>
|
|
635
|
-
promote.mutate({
|
|
636
|
-
runId,
|
|
637
|
-
...(needle ? { mustContain: needle } : {}),
|
|
638
|
-
})
|
|
639
|
-
}
|
|
640
|
-
className="rounded-md border border-border bg-background px-2.5 py-1 text-xs font-medium text-foreground hover:bg-accent disabled:opacity-50"
|
|
641
|
-
>
|
|
642
|
-
{promote.isPending
|
|
643
|
-
? t("observability.promotingToEval")
|
|
644
|
-
: t("observability.promoteToEval")}
|
|
645
|
-
</button>
|
|
646
|
-
</div>
|
|
647
541
|
</div>
|
|
648
542
|
{needsNeedle && needle.length === 0 && (
|
|
649
|
-
<p className="
|
|
543
|
+
<p className="text-xs text-muted-foreground">
|
|
650
544
|
{t("observability.promoteNeedsContains")}
|
|
651
545
|
</p>
|
|
652
546
|
)}
|
|
653
|
-
|
|
654
547
|
{promote.isSuccess && promote.data && (
|
|
655
|
-
<p className="
|
|
548
|
+
<p className="text-xs text-muted-foreground">
|
|
656
549
|
{t("observability.promotedEval", { id: promote.data.dataset.id })}{" "}
|
|
657
550
|
{t("observability.promotedEvalHint", { runId })}
|
|
658
551
|
</p>
|
|
659
552
|
)}
|
|
660
553
|
{promote.isError && (
|
|
661
|
-
<p className="
|
|
554
|
+
<p className="text-xs text-destructive">
|
|
662
555
|
{promote.error instanceof Error
|
|
663
556
|
? promote.error.message
|
|
664
557
|
: t("observability.promoteEvalFailed")}
|
|
665
558
|
</p>
|
|
666
559
|
)}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
<
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
threadId: data.summary.threadId!,
|
|
679
|
-
})
|
|
680
|
-
}
|
|
681
|
-
className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground"
|
|
682
|
-
>
|
|
683
|
-
<IconMessages size={14} />
|
|
684
|
-
{t("observability.openFullConversation")}
|
|
685
|
-
</button>
|
|
686
|
-
)}
|
|
687
|
-
</div>
|
|
688
|
-
|
|
689
|
-
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
|
690
|
-
<div className="rounded-xl border border-border/70 bg-card p-3 text-card-foreground">
|
|
691
|
-
<div className="text-[10px] text-muted-foreground mb-1">
|
|
692
|
-
{t("observability.model")}
|
|
693
|
-
</div>
|
|
694
|
-
<div className="text-sm font-medium text-foreground truncate">
|
|
695
|
-
{data.summary.model || "unknown"}
|
|
696
|
-
</div>
|
|
697
|
-
</div>
|
|
698
|
-
<div className="rounded-xl border border-border/70 bg-card p-3 text-card-foreground">
|
|
699
|
-
<div className="text-[10px] text-muted-foreground mb-1">
|
|
560
|
+
<div className="overflow-hidden rounded-xl border border-border/70 bg-card">
|
|
561
|
+
<table className="w-full table-fixed text-left text-xs">
|
|
562
|
+
<thead>
|
|
563
|
+
<tr className="border-b border-border bg-muted/30">
|
|
564
|
+
<th className="px-3 py-2 font-medium text-muted-foreground w-[15%]">
|
|
565
|
+
{t("observability.type")}
|
|
566
|
+
</th>
|
|
567
|
+
<th className="px-3 py-2 font-medium text-muted-foreground w-[35%]">
|
|
568
|
+
{t("observability.name")}
|
|
569
|
+
</th>
|
|
570
|
+
<th className="px-3 py-2 font-medium text-muted-foreground">
|
|
700
571
|
{t("observability.duration")}
|
|
701
|
-
</
|
|
702
|
-
<
|
|
703
|
-
{
|
|
704
|
-
</
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
<
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
572
|
+
</th>
|
|
573
|
+
<th className="px-3 py-2 font-medium text-muted-foreground">
|
|
574
|
+
{t("observability.tokens")}
|
|
575
|
+
</th>
|
|
576
|
+
<th className="px-3 py-2 font-medium text-muted-foreground">
|
|
577
|
+
{t("observability.status")}
|
|
578
|
+
</th>
|
|
579
|
+
<th className="w-10" />
|
|
580
|
+
</tr>
|
|
581
|
+
</thead>
|
|
582
|
+
<tbody>
|
|
583
|
+
{data.spans.map((span) => {
|
|
584
|
+
const expanded = expandedSpanId === span.id;
|
|
585
|
+
const metadata = span.metadata ?? {};
|
|
586
|
+
const fields: Array<{ label: string; value: unknown }> = [];
|
|
587
|
+
if (Object.hasOwn(metadata, "input")) {
|
|
588
|
+
fields.push({
|
|
589
|
+
label: t("observability.input"),
|
|
590
|
+
value: metadata.input,
|
|
591
|
+
});
|
|
592
|
+
} else if (span.spanType === "tool_call") {
|
|
593
|
+
fields.push({
|
|
594
|
+
label: t("observability.input"),
|
|
595
|
+
value: t("observability.notCaptured"),
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
if (Object.hasOwn(metadata, "output")) {
|
|
599
|
+
fields.push({
|
|
600
|
+
label: t("observability.output"),
|
|
601
|
+
value: metadata.output,
|
|
602
|
+
});
|
|
603
|
+
} else if (span.spanType === "tool_call") {
|
|
604
|
+
fields.push({
|
|
605
|
+
label: t("observability.output"),
|
|
606
|
+
value: t("observability.notCaptured"),
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
if (span.errorMessage || span.status === "error") {
|
|
610
|
+
fields.push({
|
|
611
|
+
label: t("observability.error"),
|
|
612
|
+
value: span.errorMessage ?? t("observability.notCaptured"),
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
const otherMetadata = Object.fromEntries(
|
|
616
|
+
Object.entries(metadata).filter(
|
|
617
|
+
([key]) => key !== "input" && key !== "output",
|
|
618
|
+
),
|
|
619
|
+
);
|
|
620
|
+
if (Object.keys(otherMetadata).length > 0) {
|
|
621
|
+
fields.push({
|
|
622
|
+
label: t("observability.metadata"),
|
|
623
|
+
value: otherMetadata,
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
if (fields.length === 0) {
|
|
627
|
+
fields.push({
|
|
628
|
+
label: t("observability.metadata"),
|
|
629
|
+
value: t("observability.notCaptured"),
|
|
630
|
+
});
|
|
631
|
+
}
|
|
723
632
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
value: otherMetadata,
|
|
789
|
-
});
|
|
790
|
-
}
|
|
791
|
-
if (fields.length === 0) {
|
|
792
|
-
fields.push({
|
|
793
|
-
label: t("observability.metadata"),
|
|
794
|
-
value: t("observability.notCaptured"),
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
return (
|
|
799
|
-
<Fragment key={span.id}>
|
|
800
|
-
<tr className="border-b border-border last:border-b-0">
|
|
801
|
-
<td className="px-3 py-2 truncate">
|
|
802
|
-
<span className="rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
|
803
|
-
{span.spanType.replace("_", " ")}
|
|
804
|
-
</span>
|
|
805
|
-
</td>
|
|
806
|
-
<td className="px-3 py-2 font-medium text-foreground truncate">
|
|
807
|
-
{span.name}
|
|
808
|
-
</td>
|
|
809
|
-
<td className="px-3 py-2 tabular-nums text-muted-foreground">
|
|
810
|
-
{formatDuration(span.durationMs)}
|
|
811
|
-
</td>
|
|
812
|
-
<td className="px-3 py-2 tabular-nums text-muted-foreground">
|
|
813
|
-
{span.inputTokens + span.outputTokens > 0
|
|
814
|
-
? `${span.inputTokens} / ${span.outputTokens}`
|
|
815
|
-
: "-"}
|
|
816
|
-
</td>
|
|
817
|
-
<td className="px-3 py-2">
|
|
818
|
-
<StatusBadge status={span.status} />
|
|
819
|
-
</td>
|
|
820
|
-
<td className="px-2 py-2 text-right">
|
|
821
|
-
<button
|
|
822
|
-
type="button"
|
|
823
|
-
aria-label={t(
|
|
824
|
-
expanded
|
|
825
|
-
? "observability.hideDetails"
|
|
826
|
-
: "observability.viewDetails",
|
|
827
|
-
)}
|
|
828
|
-
aria-expanded={expanded}
|
|
829
|
-
aria-controls={
|
|
830
|
-
expanded ? `span-details-${span.id}` : undefined
|
|
831
|
-
}
|
|
832
|
-
onClick={() =>
|
|
833
|
-
setExpandedSpanId(expanded ? null : span.id)
|
|
834
|
-
}
|
|
835
|
-
className="rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
836
|
-
>
|
|
837
|
-
<IconChevronRight
|
|
838
|
-
size={14}
|
|
839
|
-
className={cn(
|
|
840
|
-
"transition-transform",
|
|
841
|
-
expanded && "rotate-90",
|
|
842
|
-
)}
|
|
843
|
-
/>
|
|
844
|
-
</button>
|
|
845
|
-
</td>
|
|
846
|
-
</tr>
|
|
847
|
-
{expanded && (
|
|
848
|
-
<tr id={`span-details-${span.id}`}>
|
|
849
|
-
<td
|
|
850
|
-
colSpan={6}
|
|
851
|
-
className="border-b border-border p-3"
|
|
852
|
-
>
|
|
853
|
-
<div className="grid gap-3 sm:grid-cols-2">
|
|
854
|
-
{fields.map(({ label, value }) => (
|
|
855
|
-
<div key={label} className="min-w-0">
|
|
856
|
-
<div className="mb-1 text-[10px] font-medium text-muted-foreground">
|
|
857
|
-
{label}
|
|
858
|
-
</div>
|
|
859
|
-
<pre className="max-h-80 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/40 p-2 font-mono text-xs text-foreground">
|
|
860
|
-
{typeof value === "string"
|
|
861
|
-
? value || '""'
|
|
862
|
-
: (JSON.stringify(value, null, 2) ??
|
|
863
|
-
String(value))}
|
|
864
|
-
</pre>
|
|
865
|
-
</div>
|
|
866
|
-
))}
|
|
633
|
+
return (
|
|
634
|
+
<Fragment key={span.id}>
|
|
635
|
+
<tr className="border-b border-border last:border-b-0">
|
|
636
|
+
<td className="px-3 py-2 truncate">
|
|
637
|
+
<span className="rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
|
638
|
+
{span.spanType.replace("_", " ")}
|
|
639
|
+
</span>
|
|
640
|
+
</td>
|
|
641
|
+
<td className="px-3 py-2 font-medium text-foreground truncate">
|
|
642
|
+
{span.name}
|
|
643
|
+
</td>
|
|
644
|
+
<td className="px-3 py-2 tabular-nums text-muted-foreground">
|
|
645
|
+
{formatDuration(span.durationMs)}
|
|
646
|
+
</td>
|
|
647
|
+
<td className="px-3 py-2 tabular-nums text-muted-foreground">
|
|
648
|
+
{span.inputTokens + span.outputTokens > 0
|
|
649
|
+
? `${span.inputTokens} / ${span.outputTokens}`
|
|
650
|
+
: "-"}
|
|
651
|
+
</td>
|
|
652
|
+
<td className="px-3 py-2">
|
|
653
|
+
<StatusBadge status={span.status} />
|
|
654
|
+
</td>
|
|
655
|
+
<td className="px-2 py-2 text-right">
|
|
656
|
+
<button
|
|
657
|
+
type="button"
|
|
658
|
+
aria-label={t(
|
|
659
|
+
expanded
|
|
660
|
+
? "observability.hideDetails"
|
|
661
|
+
: "observability.viewDetails",
|
|
662
|
+
)}
|
|
663
|
+
aria-expanded={expanded}
|
|
664
|
+
aria-controls={
|
|
665
|
+
expanded ? `span-details-${span.id}` : undefined
|
|
666
|
+
}
|
|
667
|
+
onClick={() =>
|
|
668
|
+
setExpandedSpanId(expanded ? null : span.id)
|
|
669
|
+
}
|
|
670
|
+
className="rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
671
|
+
>
|
|
672
|
+
<IconChevronRight
|
|
673
|
+
size={14}
|
|
674
|
+
className={cn(
|
|
675
|
+
"transition-transform",
|
|
676
|
+
expanded && "rotate-90",
|
|
677
|
+
)}
|
|
678
|
+
/>
|
|
679
|
+
</button>
|
|
680
|
+
</td>
|
|
681
|
+
</tr>
|
|
682
|
+
{expanded && (
|
|
683
|
+
<tr id={`span-details-${span.id}`}>
|
|
684
|
+
<td colSpan={6} className="border-b border-border p-3">
|
|
685
|
+
<div className="grid gap-3 sm:grid-cols-2">
|
|
686
|
+
{fields.map(({ label, value }) => (
|
|
687
|
+
<div key={label} className="min-w-0">
|
|
688
|
+
<div className="mb-1 text-[10px] font-medium text-muted-foreground">
|
|
689
|
+
{label}
|
|
690
|
+
</div>
|
|
691
|
+
<pre className="max-h-80 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/40 p-2 font-mono text-xs text-foreground">
|
|
692
|
+
{typeof value === "string"
|
|
693
|
+
? value || '""'
|
|
694
|
+
: (JSON.stringify(value, null, 2) ??
|
|
695
|
+
String(value))}
|
|
696
|
+
</pre>
|
|
867
697
|
</div>
|
|
868
|
-
|
|
869
|
-
</
|
|
870
|
-
|
|
871
|
-
</
|
|
872
|
-
)
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
</
|
|
877
|
-
</
|
|
878
|
-
|
|
698
|
+
))}
|
|
699
|
+
</div>
|
|
700
|
+
</td>
|
|
701
|
+
</tr>
|
|
702
|
+
)}
|
|
703
|
+
</Fragment>
|
|
704
|
+
);
|
|
705
|
+
})}
|
|
706
|
+
</tbody>
|
|
707
|
+
</table>
|
|
708
|
+
</div>
|
|
879
709
|
</div>
|
|
880
710
|
);
|
|
881
711
|
}
|
|
@@ -3219,6 +3049,12 @@ function ObservabilityDashboardContent({
|
|
|
3219
3049
|
const t = useT();
|
|
3220
3050
|
const [localTab, setLocalTab] = useState<TabId>("overview");
|
|
3221
3051
|
const [days, setDays] = useState(7);
|
|
3052
|
+
const [runFilter, setRunFilter] = useState<RunFilter | null>(null);
|
|
3053
|
+
const showRuns = (filter: RunFilter) => {
|
|
3054
|
+
setRunFilter(filter);
|
|
3055
|
+
if (routeBasePath && navigate) navigate(`${routeBasePath}/conversations`);
|
|
3056
|
+
else setLocalTab("conversations");
|
|
3057
|
+
};
|
|
3222
3058
|
const visibleTabs = showHumanReview
|
|
3223
3059
|
? TABS
|
|
3224
3060
|
: TABS.filter((tab) => tab.id !== "review");
|
|
@@ -3303,7 +3139,7 @@ function ObservabilityDashboardContent({
|
|
|
3303
3139
|
</div>
|
|
3304
3140
|
|
|
3305
3141
|
<TabsContent value="overview" className="mt-0">
|
|
3306
|
-
<OverviewTab days={days} />
|
|
3142
|
+
<OverviewTab days={days} onShowRuns={showRuns} />
|
|
3307
3143
|
</TabsContent>
|
|
3308
3144
|
{showHumanReview && (
|
|
3309
3145
|
<TabsContent value="review" className="mt-0">
|
|
@@ -3314,7 +3150,11 @@ function ObservabilityDashboardContent({
|
|
|
3314
3150
|
</TabsContent>
|
|
3315
3151
|
)}
|
|
3316
3152
|
<TabsContent value="conversations" className="mt-0">
|
|
3317
|
-
<ConversationsTab
|
|
3153
|
+
<ConversationsTab
|
|
3154
|
+
days={days}
|
|
3155
|
+
filter={runFilter}
|
|
3156
|
+
onClearFilter={() => setRunFilter(null)}
|
|
3157
|
+
/>
|
|
3318
3158
|
</TabsContent>
|
|
3319
3159
|
<TabsContent value="evals" className="mt-0">
|
|
3320
3160
|
<EvalsTab days={days} />
|