@agent-native/toolkit 0.198.2 → 0.198.3-nightly-20260930124743
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 +4 -1
- 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/package.json +5 -5
- package/src/app/agent-page/ConnectionsTab.spec.tsx +0 -3
- package/src/app/agentkit/react/components.tsx +4 -1
- package/src/app/agentkit/react/composer-context.spec.tsx +4 -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
|
@@ -22,7 +22,7 @@ vi.mock("../resources/McpIntegrationDialog.js", () => ({
|
|
|
22
22
|
McpIntegrationDialog: () => null,
|
|
23
23
|
}));
|
|
24
24
|
|
|
25
|
-
vi.mock("
|
|
25
|
+
vi.mock("@agent-native/core/client/resources/mcp-integration-catalog", () => ({
|
|
26
26
|
isMcpIntegrationCatalogAvailable: () => false,
|
|
27
27
|
getDefaultMcpIntegrations: () => [
|
|
28
28
|
{
|
|
@@ -54,11 +54,14 @@ vi.mock("../resources/mcp-integration-catalog.js", () => ({
|
|
|
54
54
|
],
|
|
55
55
|
}));
|
|
56
56
|
|
|
57
|
-
vi.mock("
|
|
57
|
+
vi.mock("@agent-native/core/client/resources/use-mcp-servers", () => mcpMocks);
|
|
58
58
|
|
|
59
|
-
vi.mock(
|
|
59
|
+
vi.mock(
|
|
60
|
+
"@agent-native/core/client/integrations/useIntegrationStatus",
|
|
61
|
+
() => integrationMocks,
|
|
62
|
+
);
|
|
60
63
|
|
|
61
|
-
vi.mock("
|
|
64
|
+
vi.mock("@agent-native/core/client/i18n", () => ({
|
|
62
65
|
useT: () => (key: string, options?: Record<string, unknown>) => {
|
|
63
66
|
const messages: Record<string, string> = {
|
|
64
67
|
"mcpIntegrations.connectionError": "Connection error",
|
|
@@ -12,7 +12,6 @@ const {
|
|
|
12
12
|
mockSubmitFeedback,
|
|
13
13
|
mockSaveInstructionUpdate,
|
|
14
14
|
mockSendToAgentChat,
|
|
15
|
-
mockTraces,
|
|
16
15
|
mockTraceDetail,
|
|
17
16
|
mockOpenThread,
|
|
18
17
|
mockUseActionQuery,
|
|
@@ -24,7 +23,6 @@ const {
|
|
|
24
23
|
mockSubmitFeedback: vi.fn(),
|
|
25
24
|
mockSaveInstructionUpdate: vi.fn(),
|
|
26
25
|
mockSendToAgentChat: vi.fn(),
|
|
27
|
-
mockTraces: vi.fn(),
|
|
28
26
|
mockTraceDetail: vi.fn(),
|
|
29
27
|
mockOpenThread: vi.fn(),
|
|
30
28
|
mockUseActionQuery: vi.fn(),
|
|
@@ -76,7 +74,6 @@ vi.mock("./useObservability.js", () => ({
|
|
|
76
74
|
},
|
|
77
75
|
isLoading: false,
|
|
78
76
|
}),
|
|
79
|
-
useTraces: (...args: unknown[]) => mockTraces(...args),
|
|
80
77
|
useTraceDetail: (...args: unknown[]) => mockTraceDetail(...args),
|
|
81
78
|
usePromoteTraceEval: () => ({
|
|
82
79
|
mutate: vi.fn(),
|
|
@@ -125,12 +122,15 @@ vi.mock("./useObservability.js", () => ({
|
|
|
125
122
|
|
|
126
123
|
import { AgentNativeI18nProvider } from "@agent-native/core/client/i18n";
|
|
127
124
|
|
|
125
|
+
import { createToolkitI18nCatalog } from "../i18n.js";
|
|
128
126
|
import {
|
|
129
127
|
ObservabilityDashboard,
|
|
130
128
|
resolveReviewArtifactHref,
|
|
131
129
|
resolveReviewArtifactOpenHref,
|
|
132
130
|
} from "./ObservabilityDashboard.js";
|
|
133
131
|
|
|
132
|
+
const toolkitI18nCatalog = createToolkitI18nCatalog({ messages: {} });
|
|
133
|
+
|
|
134
134
|
describe("human review artifact links", () => {
|
|
135
135
|
it("keeps artifact links on the matching first-party app and environment", () => {
|
|
136
136
|
expect(
|
|
@@ -442,50 +442,84 @@ describe("ObservabilityDashboard human review", () => {
|
|
|
442
442
|
vi.unstubAllGlobals();
|
|
443
443
|
});
|
|
444
444
|
|
|
445
|
-
it("
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
445
|
+
it("explains a prompt in plain language and still exposes its raw spans and conversation", async () => {
|
|
446
|
+
const run = {
|
|
447
|
+
runId: "run-1",
|
|
448
|
+
threadId: "thread-1",
|
|
449
|
+
createdAt: Date.now(),
|
|
450
|
+
ownerEmail: "owner@example.com",
|
|
451
|
+
label: "chat",
|
|
452
|
+
model: "test-model",
|
|
453
|
+
prompt: "Find the latest releases",
|
|
454
|
+
status: "success",
|
|
455
|
+
tokens: {
|
|
456
|
+
inputTokens: 2,
|
|
457
|
+
outputTokens: 3,
|
|
458
|
+
cacheReadTokens: 0,
|
|
459
|
+
cacheWriteTokens: 0,
|
|
460
|
+
},
|
|
461
|
+
cost: {
|
|
462
|
+
cacheReadCents: 0,
|
|
463
|
+
cacheWriteCents: 0,
|
|
464
|
+
uncachedInputCents: 1,
|
|
465
|
+
outputCents: 1,
|
|
466
|
+
totalCents: 2,
|
|
467
|
+
estimatedCents: 2,
|
|
468
|
+
noCacheCents: 2,
|
|
469
|
+
},
|
|
470
|
+
modelCalls: 1,
|
|
471
|
+
tools: [
|
|
472
|
+
{ name: "search", calls: 1, failed: 0, error: null },
|
|
449
473
|
{
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
toolCalls: 1,
|
|
455
|
-
successfulTools: 1,
|
|
456
|
-
failedTools: 0,
|
|
457
|
-
totalDurationMs: 100,
|
|
458
|
-
totalCostCentsX100: 0,
|
|
459
|
-
totalInputTokens: 2,
|
|
460
|
-
totalOutputTokens: 3,
|
|
461
|
-
model: "test-model",
|
|
462
|
-
createdAt: Date.now(),
|
|
474
|
+
name: "broken-search",
|
|
475
|
+
calls: 1,
|
|
476
|
+
failed: 1,
|
|
477
|
+
error: "Search provider returned 503",
|
|
463
478
|
},
|
|
464
479
|
],
|
|
465
|
-
|
|
480
|
+
restarts: {
|
|
481
|
+
count: 0,
|
|
482
|
+
cents: 0,
|
|
483
|
+
byCause: {
|
|
484
|
+
"tool-lookup": { count: 0, cents: 0 },
|
|
485
|
+
"prefix-changed": { count: 0, cents: 0 },
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
parallel: { calls: 0, savedMs: 0 },
|
|
489
|
+
recoveredErrors: 1,
|
|
490
|
+
durationMs: 100,
|
|
491
|
+
feedback: null,
|
|
492
|
+
};
|
|
493
|
+
mockUseActionQuery.mockImplementation((actionName) =>
|
|
494
|
+
actionName === "get-usage-insights"
|
|
495
|
+
? {
|
|
496
|
+
data: {
|
|
497
|
+
sinceDays: 7,
|
|
498
|
+
current: { runs: 1, tokens: run.tokens, cost: run.cost },
|
|
499
|
+
previous: { runs: 0, tokens: run.tokens, cost: run.cost },
|
|
500
|
+
runs: [run],
|
|
501
|
+
},
|
|
502
|
+
}
|
|
503
|
+
: actionName === "get-usage-run"
|
|
504
|
+
? {
|
|
505
|
+
isLoading: false,
|
|
506
|
+
data: {
|
|
507
|
+
...run,
|
|
508
|
+
reply: "Here are the three latest releases.",
|
|
509
|
+
turns: [],
|
|
510
|
+
scores: [],
|
|
511
|
+
},
|
|
512
|
+
}
|
|
513
|
+
: { data: undefined, isError: false, isSuccess: false },
|
|
514
|
+
);
|
|
466
515
|
mockTraceDetail.mockReturnValue({
|
|
467
516
|
isLoading: false,
|
|
468
517
|
data: {
|
|
469
|
-
summary: {
|
|
470
|
-
runId: "run-1",
|
|
471
|
-
threadId: "thread-1",
|
|
472
|
-
totalSpans: 2,
|
|
473
|
-
llmCalls: 1,
|
|
474
|
-
toolCalls: 1,
|
|
475
|
-
successfulTools: 1,
|
|
476
|
-
failedTools: 0,
|
|
477
|
-
totalDurationMs: 100,
|
|
478
|
-
totalCostCentsX100: 0,
|
|
479
|
-
totalInputTokens: 2,
|
|
480
|
-
totalOutputTokens: 3,
|
|
481
|
-
model: "test-model",
|
|
482
|
-
createdAt: Date.now(),
|
|
483
|
-
},
|
|
518
|
+
summary: { runId: "run-1", threadId: "thread-1" },
|
|
484
519
|
spans: [
|
|
485
520
|
{
|
|
486
521
|
id: "span-success",
|
|
487
522
|
runId: "run-1",
|
|
488
|
-
orgId: "org-a",
|
|
489
523
|
threadId: "thread-1",
|
|
490
524
|
parentSpanId: null,
|
|
491
525
|
spanType: "tool_call",
|
|
@@ -529,13 +563,21 @@ describe("ObservabilityDashboard human review", () => {
|
|
|
529
563
|
await act(async () => {
|
|
530
564
|
root.render(
|
|
531
565
|
<QueryClientProvider client={queryClient}>
|
|
532
|
-
<AgentNativeI18nProvider
|
|
566
|
+
<AgentNativeI18nProvider
|
|
567
|
+
catalog={toolkitI18nCatalog}
|
|
568
|
+
persistPreference={false}
|
|
569
|
+
>
|
|
533
570
|
<ObservabilityDashboard />
|
|
534
571
|
</AgentNativeI18nProvider>
|
|
535
572
|
</QueryClientProvider>,
|
|
536
573
|
);
|
|
537
574
|
});
|
|
538
575
|
|
|
576
|
+
const buttonWithText = (text: string) =>
|
|
577
|
+
Array.from(document.querySelectorAll<HTMLButtonElement>("button")).find(
|
|
578
|
+
(button) => button.textContent?.includes(text),
|
|
579
|
+
);
|
|
580
|
+
|
|
539
581
|
const experimentsTab = Array.from(
|
|
540
582
|
container.querySelectorAll<HTMLButtonElement>("button"),
|
|
541
583
|
).find((button) => button.textContent?.includes("Experiments"));
|
|
@@ -552,33 +594,150 @@ describe("ObservabilityDashboard human review", () => {
|
|
|
552
594
|
container.querySelector<HTMLAnchorElement>('a[href*="#conversations"]'),
|
|
553
595
|
).toBeTruthy();
|
|
554
596
|
|
|
555
|
-
|
|
556
|
-
|
|
597
|
+
await act(async () => buttonWithText("Find the latest releases")?.click());
|
|
598
|
+
expect(document.body.textContent).toContain(
|
|
599
|
+
"Here are the three latest releases.",
|
|
600
|
+
);
|
|
601
|
+
expect(document.body.textContent).toContain(
|
|
602
|
+
"but the agent kept going and finished",
|
|
557
603
|
);
|
|
558
|
-
await act(async () => (runRow as HTMLTableRowElement | undefined)?.click());
|
|
559
604
|
|
|
605
|
+
await act(async () => buttonWithText("Raw trace")?.click());
|
|
560
606
|
const detailsButton = (spanName: string) =>
|
|
561
607
|
Array.from(
|
|
562
|
-
|
|
608
|
+
document.querySelectorAll<HTMLButtonElement>(
|
|
563
609
|
'button[aria-label="View details"]',
|
|
564
610
|
),
|
|
565
611
|
).find((button) => button.closest("tr")?.textContent?.includes(spanName));
|
|
566
612
|
|
|
567
613
|
await act(async () => detailsButton("search")?.click());
|
|
568
|
-
expect(
|
|
569
|
-
expect(
|
|
614
|
+
expect(document.body.textContent).toContain('"latest releases"');
|
|
615
|
+
expect(document.body.textContent).toContain("Found 3 results");
|
|
570
616
|
|
|
571
617
|
await act(async () => detailsButton("broken-search")?.click());
|
|
572
|
-
expect(
|
|
618
|
+
expect(document.body.textContent).toContain("Search provider returned 503");
|
|
573
619
|
|
|
574
|
-
await act(async () =>
|
|
575
|
-
Array.from(container.querySelectorAll<HTMLButtonElement>("button"))
|
|
576
|
-
.find((button) =>
|
|
577
|
-
button.textContent?.includes("Open full conversation"),
|
|
578
|
-
)
|
|
579
|
-
?.click(),
|
|
580
|
-
);
|
|
620
|
+
await act(async () => buttonWithText("Open full conversation")?.click());
|
|
581
621
|
expect(mockOpenThread).toHaveBeenCalledWith({ threadId: "thread-1" });
|
|
622
|
+
expect(buttonWithText("Open full conversation")).toBeUndefined();
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
it("reports a failed insights load with a retry instead of loading forever", async () => {
|
|
626
|
+
const refetch = vi.fn();
|
|
627
|
+
mockUseActionQuery.mockImplementation((actionName) =>
|
|
628
|
+
actionName === "get-usage-insights"
|
|
629
|
+
? {
|
|
630
|
+
data: undefined,
|
|
631
|
+
isError: true,
|
|
632
|
+
isSuccess: false,
|
|
633
|
+
isFetching: false,
|
|
634
|
+
refetch,
|
|
635
|
+
}
|
|
636
|
+
: { data: undefined, isError: false, isSuccess: false },
|
|
637
|
+
);
|
|
638
|
+
|
|
639
|
+
await act(async () => {
|
|
640
|
+
root.render(
|
|
641
|
+
<QueryClientProvider client={queryClient}>
|
|
642
|
+
<AgentNativeI18nProvider
|
|
643
|
+
catalog={toolkitI18nCatalog}
|
|
644
|
+
persistPreference={false}
|
|
645
|
+
>
|
|
646
|
+
<ObservabilityDashboard />
|
|
647
|
+
</AgentNativeI18nProvider>
|
|
648
|
+
</QueryClientProvider>,
|
|
649
|
+
);
|
|
650
|
+
});
|
|
651
|
+
expect(container.querySelector('[role="alert"]')?.textContent).toBe(
|
|
652
|
+
"Couldn't load this. Please try again.",
|
|
653
|
+
);
|
|
654
|
+
|
|
655
|
+
const buttonWithText = (text: string) =>
|
|
656
|
+
Array.from(container.querySelectorAll("button")).find((button) =>
|
|
657
|
+
button.textContent?.includes(text),
|
|
658
|
+
);
|
|
659
|
+
await act(async () => buttonWithText("Retry")?.click());
|
|
660
|
+
expect(refetch).toHaveBeenCalledTimes(1);
|
|
661
|
+
|
|
662
|
+
await act(async () => activateTab(buttonWithText("Conversations")));
|
|
663
|
+
expect(container.querySelector('[role="alert"]')?.textContent).toBe(
|
|
664
|
+
"Couldn't load this. Please try again.",
|
|
665
|
+
);
|
|
666
|
+
expect(buttonWithText("Retry")).toBeTruthy();
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
it("says the overview stats cover only the latest prompts when the period has more", async () => {
|
|
670
|
+
const tokens = {
|
|
671
|
+
inputTokens: 2,
|
|
672
|
+
outputTokens: 3,
|
|
673
|
+
cacheReadTokens: 0,
|
|
674
|
+
cacheWriteTokens: 0,
|
|
675
|
+
};
|
|
676
|
+
const cost = {
|
|
677
|
+
cacheReadCents: 0,
|
|
678
|
+
cacheWriteCents: 0,
|
|
679
|
+
uncachedInputCents: 1,
|
|
680
|
+
outputCents: 1,
|
|
681
|
+
totalCents: 2,
|
|
682
|
+
estimatedCents: 2,
|
|
683
|
+
noCacheCents: 2,
|
|
684
|
+
};
|
|
685
|
+
mockUseActionQuery.mockImplementation((actionName) =>
|
|
686
|
+
actionName === "get-usage-insights"
|
|
687
|
+
? {
|
|
688
|
+
data: {
|
|
689
|
+
sinceDays: 7,
|
|
690
|
+
current: { runs: 30, tokens, cost },
|
|
691
|
+
previous: { runs: 0, tokens, cost },
|
|
692
|
+
runs: [
|
|
693
|
+
{
|
|
694
|
+
runId: "run-1",
|
|
695
|
+
threadId: "thread-1",
|
|
696
|
+
createdAt: Date.now(),
|
|
697
|
+
ownerEmail: "owner@example.com",
|
|
698
|
+
label: "chat",
|
|
699
|
+
model: "test-model",
|
|
700
|
+
prompt: "Find the latest releases",
|
|
701
|
+
status: "success",
|
|
702
|
+
tokens,
|
|
703
|
+
cost,
|
|
704
|
+
modelCalls: 1,
|
|
705
|
+
tools: [],
|
|
706
|
+
restarts: {
|
|
707
|
+
count: 0,
|
|
708
|
+
cents: 0,
|
|
709
|
+
byCause: {
|
|
710
|
+
"tool-lookup": { count: 0, cents: 0 },
|
|
711
|
+
"prefix-changed": { count: 0, cents: 0 },
|
|
712
|
+
},
|
|
713
|
+
},
|
|
714
|
+
parallel: { calls: 0, savedMs: 0 },
|
|
715
|
+
recoveredErrors: 0,
|
|
716
|
+
durationMs: 100,
|
|
717
|
+
feedback: null,
|
|
718
|
+
},
|
|
719
|
+
],
|
|
720
|
+
},
|
|
721
|
+
}
|
|
722
|
+
: { data: undefined, isError: false, isSuccess: false },
|
|
723
|
+
);
|
|
724
|
+
|
|
725
|
+
await act(async () => {
|
|
726
|
+
root.render(
|
|
727
|
+
<QueryClientProvider client={queryClient}>
|
|
728
|
+
<AgentNativeI18nProvider
|
|
729
|
+
catalog={toolkitI18nCatalog}
|
|
730
|
+
persistPreference={false}
|
|
731
|
+
>
|
|
732
|
+
<ObservabilityDashboard />
|
|
733
|
+
</AgentNativeI18nProvider>
|
|
734
|
+
</QueryClientProvider>,
|
|
735
|
+
);
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
expect(container.textContent).toContain(
|
|
739
|
+
"Completion, typical time, what Agent-Native handled and the findings use the latest 1 of 30 prompts.",
|
|
740
|
+
);
|
|
582
741
|
});
|
|
583
742
|
|
|
584
743
|
it("hides organization human review outside the admin settings surface", async () => {
|
|
@@ -24,6 +24,46 @@ const TRACE = {
|
|
|
24
24
|
createdAt: Date.now(),
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
const RUN = {
|
|
28
|
+
runId: TRACE.runId,
|
|
29
|
+
threadId: TRACE.threadId,
|
|
30
|
+
createdAt: TRACE.createdAt,
|
|
31
|
+
ownerEmail: "owner@example.com",
|
|
32
|
+
label: "chat",
|
|
33
|
+
model: TRACE.model,
|
|
34
|
+
prompt: "Say hello",
|
|
35
|
+
status: "success",
|
|
36
|
+
tokens: {
|
|
37
|
+
inputTokens: 8,
|
|
38
|
+
outputTokens: 4,
|
|
39
|
+
cacheReadTokens: 0,
|
|
40
|
+
cacheWriteTokens: 0,
|
|
41
|
+
},
|
|
42
|
+
cost: {
|
|
43
|
+
cacheReadCents: 0,
|
|
44
|
+
cacheWriteCents: 0,
|
|
45
|
+
uncachedInputCents: 0.05,
|
|
46
|
+
outputCents: 0.05,
|
|
47
|
+
totalCents: 0.1,
|
|
48
|
+
estimatedCents: 0.1,
|
|
49
|
+
noCacheCents: 0.1,
|
|
50
|
+
},
|
|
51
|
+
modelCalls: 1,
|
|
52
|
+
tools: [{ name: "search-docs", calls: 1, failed: 0, error: null }],
|
|
53
|
+
restarts: {
|
|
54
|
+
count: 0,
|
|
55
|
+
cents: 0,
|
|
56
|
+
byCause: {
|
|
57
|
+
"tool-lookup": { count: 0, cents: 0 },
|
|
58
|
+
"prefix-changed": { count: 0, cents: 0 },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
parallel: { calls: 0, savedMs: 0 },
|
|
62
|
+
recoveredErrors: 0,
|
|
63
|
+
durationMs: TRACE.totalDurationMs,
|
|
64
|
+
feedback: null,
|
|
65
|
+
};
|
|
66
|
+
|
|
27
67
|
function jsonResponse(body: unknown, status = 200): Response {
|
|
28
68
|
return new Response(JSON.stringify(body), {
|
|
29
69
|
status,
|
|
@@ -42,6 +82,21 @@ beforeEach(() => {
|
|
|
42
82
|
(input: RequestInfo | URL, init?: RequestInit) => {
|
|
43
83
|
const url = String(input);
|
|
44
84
|
const method = (init?.method ?? "GET").toUpperCase();
|
|
85
|
+
if (url.includes("/_agent-native/actions/get-usage-insights")) {
|
|
86
|
+
return Promise.resolve(
|
|
87
|
+
jsonResponse({
|
|
88
|
+
sinceDays: 7,
|
|
89
|
+
current: { runs: 1, tokens: RUN.tokens, cost: RUN.cost },
|
|
90
|
+
previous: { runs: 0, tokens: RUN.tokens, cost: RUN.cost },
|
|
91
|
+
runs: [RUN],
|
|
92
|
+
}),
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
if (url.includes("/_agent-native/actions/get-usage-run")) {
|
|
96
|
+
return Promise.resolve(
|
|
97
|
+
jsonResponse({ ...RUN, reply: "hello", turns: [], scores: [] }),
|
|
98
|
+
);
|
|
99
|
+
}
|
|
45
100
|
if (url.includes("/traces/run-promote-1/promote") && method === "POST") {
|
|
46
101
|
return Promise.resolve(
|
|
47
102
|
jsonResponse({
|
|
@@ -119,6 +174,12 @@ afterEach(() => {
|
|
|
119
174
|
queryClient.clear();
|
|
120
175
|
});
|
|
121
176
|
|
|
177
|
+
function bodyButton(text: string) {
|
|
178
|
+
return Array.from(document.body.querySelectorAll("button")).find((button) =>
|
|
179
|
+
button.textContent?.startsWith(text),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
122
183
|
function renderDashboard() {
|
|
123
184
|
act(() => {
|
|
124
185
|
root.render(
|
|
@@ -154,38 +215,37 @@ describe("ObservabilityDashboard promote control", () => {
|
|
|
154
215
|
);
|
|
155
216
|
|
|
156
217
|
await vi.waitFor(() => {
|
|
157
|
-
expect(container.textContent).toContain("
|
|
218
|
+
expect(container.textContent).toContain("Say hello");
|
|
158
219
|
});
|
|
159
220
|
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
221
|
+
const promptRow = Array.from(container.querySelectorAll("button")).find(
|
|
222
|
+
(button) => button.textContent?.startsWith("Say hello"),
|
|
223
|
+
);
|
|
224
|
+
act(() => promptRow!.click());
|
|
225
|
+
|
|
226
|
+
await vi.waitFor(() => {
|
|
227
|
+
expect(bodyButton("Raw trace")).toBeTruthy();
|
|
228
|
+
});
|
|
229
|
+
act(() => bodyButton("Raw trace")!.click());
|
|
163
230
|
|
|
164
231
|
await vi.waitFor(() => {
|
|
165
|
-
const promote =
|
|
166
|
-
(button) => button.textContent === "Promote to eval",
|
|
167
|
-
);
|
|
232
|
+
const promote = bodyButton("Promote to eval");
|
|
168
233
|
expect(promote).toBeTruthy();
|
|
169
234
|
expect(promote?.disabled).toBe(false);
|
|
170
235
|
});
|
|
171
236
|
|
|
172
|
-
const promote =
|
|
173
|
-
|
|
237
|
+
const promote = bodyButton("Promote to eval");
|
|
238
|
+
const mustContain = document.body.querySelector<HTMLInputElement>(
|
|
239
|
+
'input[aria-label="Text to check for in the promoted eval reply"]',
|
|
240
|
+
);
|
|
241
|
+
expect(mustContain?.placeholder).toBe(
|
|
242
|
+
"Optional text to check for in the reply…",
|
|
174
243
|
);
|
|
175
|
-
expect(promote).toBeTruthy();
|
|
176
|
-
expect(
|
|
177
|
-
container.querySelector<HTMLInputElement>("input")?.placeholder,
|
|
178
|
-
).toBe("Optional text to check for in the reply…");
|
|
179
|
-
expect(
|
|
180
|
-
container
|
|
181
|
-
.querySelector<HTMLInputElement>("input")
|
|
182
|
-
?.getAttribute("aria-label"),
|
|
183
|
-
).toBe("Text to check for in the promoted eval reply");
|
|
184
244
|
act(() => promote!.click());
|
|
185
245
|
|
|
186
246
|
await vi.waitFor(() => {
|
|
187
|
-
expect(
|
|
188
|
-
expect(
|
|
247
|
+
expect(document.body.textContent).toContain("Eval dataset ds-99");
|
|
248
|
+
expect(document.body.textContent).toContain(
|
|
189
249
|
"agent-native eval promote run-promote-1 --write evals/from-trace.eval.ts",
|
|
190
250
|
);
|
|
191
251
|
});
|