@agent-native/core 0.155.0 → 0.157.1
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +19 -4
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +7 -2
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/global.css +4 -0
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +18 -15
- package/corpus/templates/brain/app/routes/sources.tsx +1 -2
- package/corpus/templates/calendar/app/hooks/use-bookings.ts +12 -2
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +64 -2
- package/corpus/templates/calendar/server/handlers/bookings.ts +219 -93
- package/corpus/templates/calendar/server/plugins/auth.ts +0 -2
- package/corpus/templates/clips/actions/create-folder.ts +7 -1
- package/corpus/templates/clips/actions/create-meeting.ts +6 -2
- package/corpus/templates/clips/actions/create-recording.ts +5 -3
- package/corpus/templates/clips/actions/finalize-recording.ts +97 -65
- package/corpus/templates/clips/actions/import-loom-recording.ts +5 -3
- package/corpus/templates/clips/actions/request-recording-access.ts +272 -0
- package/corpus/templates/clips/actions/stitch-recordings.ts +5 -3
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +38 -63
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +177 -134
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +3 -21
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +13 -30
- package/corpus/templates/clips/app/i18n/en-US.ts +10 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -5
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +24 -17
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +151 -20
- package/corpus/templates/clips/changelog/2026-08-14-long-resumable-uploads-now-abort-cleanly-and-show-errors.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-14-standardized-share-popovers.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +11 -3
- package/corpus/templates/clips/chrome-extension/src/github-preview-content.ts +37 -8
- package/corpus/templates/clips/chrome-extension/src/github-preview.ts +3 -3
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -25
- package/corpus/templates/clips/desktop/src/app.tsx +24 -0
- package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +42 -13
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +11 -18
- package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +1 -0
- package/corpus/templates/clips/desktop/src/shared/config.ts +1 -0
- package/corpus/templates/clips/desktop/src/styles.css +24 -9
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/config.rs +8 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +154 -176
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +115 -31
- package/corpus/templates/clips/desktop/src-tauri/src/rewind_clip.rs +7 -0
- package/corpus/templates/clips/server/db/index.ts +1 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +6 -1
- package/corpus/templates/clips/server/lib/emails.ts +23 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +55 -0
- package/corpus/templates/clips/server/lib/recordings.ts +2 -1
- package/corpus/templates/clips/server/lib/resumable-upload-cleanup.ts +49 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +34 -7
- package/corpus/templates/clips/server/lib/upload-interruption.ts +15 -1
- package/corpus/templates/clips/server/lib/upload-lease.ts +94 -9
- package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +82 -7
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +1 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +71 -12
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +4 -3
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +19 -0
- package/corpus/templates/clips/server/routes/api/uploads/reap.post.ts +8 -1
- package/corpus/templates/clips/shared/recording-link.ts +4 -0
- package/corpus/templates/clips/shared/share-loader-response.ts +2 -1
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +7 -16
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +6 -2
- package/corpus/templates/factory/actions/view-screen.ts +15 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +58 -189
- package/corpus/templates/factory/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +7 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +3 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +3 -1
- package/corpus/templates/factory/app/routes/agents.tsx +9 -0
- package/corpus/templates/mail/server/plugins/auth.ts +0 -2
- package/corpus/templates/plan/app/components/plan/LocalCodebasePicker.tsx +50 -14
- package/corpus/templates/plan/app/pages/PlansPage.tsx +9 -19
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +98 -29
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +45 -91
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +94 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +17 -29
- package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +7 -1
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +108 -19
- package/corpus/templates/slides/app/global.css +7 -40
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/editor-shortcuts.ts +46 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +143 -45
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/production-agent.d.ts +30 -0
- package/dist/agent/production-agent.js +100 -8
- package/dist/agent/types.d.ts +9 -0
- package/dist/client/AgentPanel.d.ts +13 -1
- package/dist/client/AgentPanel.js +22 -17
- package/dist/client/AssistantChat.d.ts +15 -1
- package/dist/client/AssistantChat.js +135 -48
- package/dist/client/HighlightedCodeBlock.js +12 -2
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/chat/markdown-renderer.js +20 -5
- package/dist/client/chat/message-components.d.ts +2 -2
- package/dist/client/chat/message-components.js +69 -35
- package/dist/client/chat/run-recovery.d.ts +4 -1
- package/dist/client/chat/run-recovery.js +62 -30
- package/dist/client/chat/tool-call-display.d.ts +12 -3
- package/dist/client/chat/tool-call-display.js +79 -40
- package/dist/client/chat/widgets/DataChartRenderer.js +3 -1
- package/dist/client/chat/widgets/DataChartWidget.js +8 -2
- package/dist/client/chat/widgets/DataInsightsWidget.js +3 -1
- package/dist/client/chat/widgets/DataTableWidget.js +23 -9
- package/dist/client/chat/widgets/builtin-tool-renderers.js +3 -1
- package/dist/client/chat-first/apps-rail.js +1 -1
- package/dist/client/components/ui/message-scroller.d.ts +1 -1
- package/dist/client/components/ui/message-scroller.js +7 -3
- package/dist/client/composer/runtime-adapters.js +3 -2
- package/dist/client/context-xray/ContextMeter.js +5 -1
- package/dist/client/context-xray/ContextXRayPanel.js +5 -5
- package/dist/client/error-format.d.ts +4 -0
- package/dist/client/error-format.js +93 -5
- package/dist/client/i18n.js +83 -17
- package/dist/client/observability/ThumbsFeedback.js +10 -8
- package/dist/client/settings/AccountSettingsCard.js +48 -19
- package/dist/client/sharing/ShareButton.d.ts +1 -2
- package/dist/client/sharing/ShareButton.js +151 -81
- package/dist/client/sharing/ShareDialog.js +5 -4
- package/dist/client/use-chat-threads.js +10 -14
- package/dist/coding-tools/run-code.js +2 -1
- package/dist/coding-tools/sandbox/background.d.ts +1 -0
- package/dist/coding-tools/sandbox/background.js +8 -1
- package/dist/coding-tools/sandbox/executions-store.d.ts +2 -0
- package/dist/coding-tools/sandbox/executions-store.js +41 -3
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.d.ts +3 -0
- package/dist/localization/core-messages/ar-SA.js +541 -0
- package/dist/localization/core-messages/de-DE.d.ts +3 -0
- package/dist/localization/core-messages/de-DE.js +513 -0
- package/dist/localization/core-messages/en-US.d.ts +513 -0
- package/dist/localization/core-messages/en-US.js +513 -0
- package/dist/localization/core-messages/es-ES.d.ts +3 -0
- package/dist/localization/core-messages/es-ES.js +520 -0
- package/dist/localization/core-messages/fr-FR.d.ts +3 -0
- package/dist/localization/core-messages/fr-FR.js +520 -0
- package/dist/localization/core-messages/hi-IN.d.ts +3 -0
- package/dist/localization/core-messages/hi-IN.js +513 -0
- package/dist/localization/core-messages/ja-JP.d.ts +3 -0
- package/dist/localization/core-messages/ja-JP.js +506 -0
- package/dist/localization/core-messages/ko-KR.d.ts +3 -0
- package/dist/localization/core-messages/ko-KR.js +506 -0
- package/dist/localization/core-messages/pt-BR.d.ts +3 -0
- package/dist/localization/core-messages/pt-BR.js +520 -0
- package/dist/localization/core-messages/zh-CN.d.ts +3 -0
- package/dist/localization/core-messages/zh-CN.js +506 -0
- package/dist/localization/core-messages/zh-TW.d.ts +3 -0
- package/dist/localization/core-messages/zh-TW.js +506 -0
- package/dist/localization/core-messages.d.ts +524 -0
- package/dist/localization/core-messages.js +124 -0
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.js +3 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/plugin-options.d.ts +7 -2
- package/dist/server/agent-chat-plugin.d.ts +10 -0
- package/dist/server/agent-chat-plugin.js +144 -41
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-run-context.d.ts +7 -1
- package/dist/server/agent-run-context.js +9 -2
- package/dist/server/agent-teams-run-queue.d.ts +3 -0
- package/dist/server/agent-teams.js +38 -9
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.js +0 -2
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.js +18 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/onboarding-html.d.ts +1 -0
- package/dist/server/onboarding-html.js +2 -88
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/dist/shared/markdown-block-split.d.ts +16 -0
- package/dist/shared/markdown-block-split.js +81 -5
- package/dist/styles/agent-native.css +13 -0
- package/dist/voice/voice-cleanup-prompt.js +1 -0
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +2 -2
- package/corpus/templates/clips/shared/mic-audio-cleanup.ts +0 -350
|
@@ -72,8 +72,11 @@ export type ToolDetailPayload = {
|
|
|
72
72
|
copyText: string;
|
|
73
73
|
lang: string;
|
|
74
74
|
};
|
|
75
|
-
export declare function toolInputPayload(toolName: string, args: Record<string, unknown
|
|
76
|
-
|
|
75
|
+
export declare function toolInputPayload(toolName: string, args: Record<string, unknown>, labels?: {
|
|
76
|
+
input: string;
|
|
77
|
+
inputWithLabel: (label: string) => string;
|
|
78
|
+
}): ToolDetailPayload | null;
|
|
79
|
+
export declare function toolResultPayload(result: string | undefined, title?: string): ToolDetailPayload | null;
|
|
77
80
|
export declare function AnimatedCollapse({ open, children, }: {
|
|
78
81
|
open: boolean;
|
|
79
82
|
children: React.ReactNode;
|
|
@@ -138,7 +141,13 @@ export declare function ReasoningCell({ text, isStreaming, defaultOpen, autoColl
|
|
|
138
141
|
*/
|
|
139
142
|
durationMs?: number | null;
|
|
140
143
|
}): React.JSX.Element | null;
|
|
141
|
-
export declare function formatWorkedDuration(ms: number
|
|
144
|
+
export declare function formatWorkedDuration(ms: number, options?: {
|
|
145
|
+
locale?: string;
|
|
146
|
+
hour?: string;
|
|
147
|
+
minute?: string;
|
|
148
|
+
second?: string;
|
|
149
|
+
}): string;
|
|
150
|
+
export declare function useLocalizedWorkedDuration(): (ms: number) => string;
|
|
142
151
|
export declare function WorkedForSummary({ durationMs, defaultOpen, autoCollapse, children, }: {
|
|
143
152
|
durationMs?: number | null;
|
|
144
153
|
/** Keep completed work visible when the turn contains interactive UI. */
|
|
@@ -6,7 +6,7 @@ import { writeClipboardText } from "../clipboard.js";
|
|
|
6
6
|
import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
7
7
|
import { ConnectBuilderCard } from "../ConnectBuilderCard.js";
|
|
8
8
|
import { FileStorageSetupCard } from "../FileStorageSetupCard.js";
|
|
9
|
-
import { useT } from "../i18n.js";
|
|
9
|
+
import { useOptionalLocale, useT } from "../i18n.js";
|
|
10
10
|
import { McpAppRenderer } from "../mcp-apps/McpAppRenderer.js";
|
|
11
11
|
import { findMcpIntegrationForToolName } from "../resources/mcp-integration-catalog.js";
|
|
12
12
|
import { McpIntegrationLogo } from "../resources/McpIntegrationLogo.js";
|
|
@@ -41,6 +41,7 @@ export function toolCallHasPendingApproval(part) {
|
|
|
41
41
|
}
|
|
42
42
|
export const TOOL_LONG_RUNNING_HINT_DELAY_MS = 45_000;
|
|
43
43
|
export function ToolActivityPresentation({ toolName, isRunning, toolCallId, suppressLongRunningHint = false, children, }) {
|
|
44
|
+
const t = useT();
|
|
44
45
|
const [showLongRunningHint, setShowLongRunningHint] = useState(false);
|
|
45
46
|
useEffect(() => {
|
|
46
47
|
if (!isRunning || suppressLongRunningHint) {
|
|
@@ -53,7 +54,7 @@ export function ToolActivityPresentation({ toolName, isRunning, toolCallId, supp
|
|
|
53
54
|
}, TOOL_LONG_RUNNING_HINT_DELAY_MS);
|
|
54
55
|
return () => window.clearTimeout(timeout);
|
|
55
56
|
}, [isRunning, suppressLongRunningHint, toolName]);
|
|
56
|
-
return (_jsx("div", { className: "agent-tool-call", "data-agent-tool-call-id": toolCallId, "data-running": isRunning ? "true" : undefined, children: _jsxs("div", { className: "agent-tool-call__content", children: [children, isRunning && showLongRunningHint && (_jsx("div", { className: "mt-0.5 px-2.5 pb-2 text-[11px] leading-snug text-muted-foreground/80", children: "
|
|
57
|
+
return (_jsx("div", { className: "agent-tool-call", "data-agent-tool-call-id": toolCallId, "data-running": isRunning ? "true" : undefined, children: _jsxs("div", { className: "agent-tool-call__content", children: [children, isRunning && showLongRunningHint && (_jsx("div", { className: "mt-0.5 px-2.5 pb-2 text-[11px] leading-snug text-muted-foreground/80", children: t("agentChat.tool.longRunning") }))] }) }));
|
|
57
58
|
}
|
|
58
59
|
function stringifyToolValue(value, pretty = false) {
|
|
59
60
|
if (typeof value === "string")
|
|
@@ -109,7 +110,10 @@ function formatToolTextValue(value, key, toolName) {
|
|
|
109
110
|
}
|
|
110
111
|
return { text: stringifyToolValue(value, true), lang: "json" };
|
|
111
112
|
}
|
|
112
|
-
export function toolInputPayload(toolName, args
|
|
113
|
+
export function toolInputPayload(toolName, args, labels = {
|
|
114
|
+
input: "Input",
|
|
115
|
+
inputWithLabel: (label) => `Input - ${label}`,
|
|
116
|
+
}) {
|
|
113
117
|
const entries = Object.entries(args);
|
|
114
118
|
if (entries.length === 0)
|
|
115
119
|
return null;
|
|
@@ -120,7 +124,7 @@ export function toolInputPayload(toolName, args) {
|
|
|
120
124
|
const keyLabel = normalizedKey === "sql" || normalizedKey.endsWith("sql") ? "SQL" : key;
|
|
121
125
|
return {
|
|
122
126
|
section: "input",
|
|
123
|
-
title:
|
|
127
|
+
title: labels.inputWithLabel(keyLabel),
|
|
124
128
|
text: formatted.text,
|
|
125
129
|
copyText: typeof value === "string" ? value : stringifyToolValue(value, true),
|
|
126
130
|
lang: formatted.lang,
|
|
@@ -128,19 +132,19 @@ export function toolInputPayload(toolName, args) {
|
|
|
128
132
|
}
|
|
129
133
|
return {
|
|
130
134
|
section: "input",
|
|
131
|
-
title:
|
|
135
|
+
title: labels.input,
|
|
132
136
|
text: JSON.stringify(args, null, 2),
|
|
133
137
|
copyText: JSON.stringify(args, null, 2),
|
|
134
138
|
lang: "json",
|
|
135
139
|
};
|
|
136
140
|
}
|
|
137
|
-
export function toolResultPayload(result) {
|
|
141
|
+
export function toolResultPayload(result, title = "Result") {
|
|
138
142
|
if (result === undefined)
|
|
139
143
|
return null;
|
|
140
144
|
const formatted = formatToolTextValue(result);
|
|
141
145
|
return {
|
|
142
146
|
section: "result",
|
|
143
|
-
title
|
|
147
|
+
title,
|
|
144
148
|
text: formatted.text,
|
|
145
149
|
copyText: result,
|
|
146
150
|
lang: formatted.lang,
|
|
@@ -195,6 +199,7 @@ function SimpleCodeViewer({ text, lang, className, maxHeightClass = "max-h-56",
|
|
|
195
199
|
return (_jsxs("div", { className: cn("agent-tool-code overflow-auto rounded-md bg-muted/70 font-mono text-[11px] leading-relaxed text-foreground", maxHeightClass, className), children: [lang !== "text" && (_jsx("div", { className: "sticky top-0 z-[1] flex items-center justify-between border-b border-border/40 bg-muted/90 px-2.5 py-1", children: _jsx("span", { className: "font-mono text-[10px] uppercase tracking-wide text-muted-foreground/80", children: lang }) })), _jsx(HighlightedCodeBlock, { code: text, lang: lang })] }));
|
|
196
200
|
}
|
|
197
201
|
function ToolOutputPopover({ open, onOpenChange, title, payload, children, }) {
|
|
202
|
+
const t = useT();
|
|
198
203
|
const [copied, setCopied] = useState(false);
|
|
199
204
|
const copyResetRef = useRef(null);
|
|
200
205
|
useEffect(() => {
|
|
@@ -216,7 +221,7 @@ function ToolOutputPopover({ open, onOpenChange, title, payload, children, }) {
|
|
|
216
221
|
// Clipboard failures should not interrupt chat rendering.
|
|
217
222
|
}
|
|
218
223
|
}, [payload.copyText]);
|
|
219
|
-
return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: children }), _jsxs(PopoverContent, { align: "start", side: "bottom", sideOffset: 6, collisionPadding: 12, className: "flex max-h-[min(calc(100vh-2rem),var(--radix-popover-content-available-height,75vh))] w-[min(calc(100vw-2rem),var(--radix-popover-content-available-width,760px),760px)] flex-col gap-0 overflow-hidden p-0", children: [_jsxs("div", { className: "flex shrink-0 items-center justify-between gap-3 border-b border-border px-4 py-3", children: [_jsx("div", { className: "truncate text-sm font-medium", children: title }), _jsxs("button", { type: "button", onClick: copyValue, className: "inline-flex h-7 items-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground hover:bg-accent hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 13 }) : _jsx(IconCopy, { size: 13 }), copied ? "
|
|
224
|
+
return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: children }), _jsxs(PopoverContent, { align: "start", side: "bottom", sideOffset: 6, collisionPadding: 12, className: "flex max-h-[min(calc(100vh-2rem),var(--radix-popover-content-available-height,75vh))] w-[min(calc(100vw-2rem),var(--radix-popover-content-available-width,760px),760px)] flex-col gap-0 overflow-hidden p-0", children: [_jsxs("div", { className: "flex shrink-0 items-center justify-between gap-3 border-b border-border px-4 py-3", children: [_jsx("div", { className: "truncate text-sm font-medium", children: title }), _jsxs("button", { type: "button", onClick: copyValue, className: "inline-flex h-7 items-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground hover:bg-accent hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 13 }) : _jsx(IconCopy, { size: 13 }), copied ? t("agentChat.common.copied") : t("agentChat.common.copy")] })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-hidden p-3", children: _jsx(SimpleCodeViewer, { text: payload.text, lang: payload.lang, maxHeightClass: "max-h-[min(70vh,calc(var(--radix-popover-content-available-height,75vh)-4.5rem))]" }) })] })] }));
|
|
220
225
|
}
|
|
221
226
|
// ─── Collapsible height animation ─────────────────────────────────────────────
|
|
222
227
|
export function AnimatedCollapse({ open, children, }) {
|
|
@@ -241,6 +246,7 @@ export function AnimatedCollapse({ open, children, }) {
|
|
|
241
246
|
* the prompt locally (the action stays un-run).
|
|
242
247
|
*/
|
|
243
248
|
function ApprovalAffordance({ toolName, toolCallId, approval, }) {
|
|
249
|
+
const t = useT();
|
|
244
250
|
const ctx = React.useContext(ApprovalContext);
|
|
245
251
|
const [localResolution, setLocalResolution] = useState(null);
|
|
246
252
|
const retainedResolution = ctx?.getApprovalResolution?.(approval.approvalKey, toolCallId) ?? null;
|
|
@@ -250,27 +256,27 @@ function ApprovalAffordance({ toolName, toolCallId, approval, }) {
|
|
|
250
256
|
// Once resolved, collapse to a quiet note so a repository refresh cannot
|
|
251
257
|
// restore the action buttons while the continuation is running.
|
|
252
258
|
if (resolution === "approved") {
|
|
253
|
-
return (
|
|
259
|
+
return (_jsx("div", { className: "mt-1.5 text-xs text-muted-foreground", children: t("agentChat.approval.approved", { tool: toolName }) }));
|
|
254
260
|
}
|
|
255
261
|
// Deny defaults to local-only (the action simply stays un-run). When the
|
|
256
262
|
// host also provided `onDeny` (e.g. a Code session resolving its own
|
|
257
263
|
// pending approval), it fires alongside the local state.
|
|
258
264
|
if (resolution === "denied") {
|
|
259
|
-
return (
|
|
265
|
+
return (_jsx("div", { className: "mt-1.5 text-xs text-muted-foreground", children: t("agentChat.approval.denied", { tool: toolName }) }));
|
|
260
266
|
}
|
|
261
|
-
return (_jsxs("div", { className: "mt-1.5 flex min-w-0 flex-wrap items-center gap-2 rounded-md border border-border bg-muted/40 px-2.5 py-1.5", children: [_jsx(IconShieldCheck, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
267
|
+
return (_jsxs("div", { className: "mt-1.5 flex min-w-0 flex-wrap items-center gap-2 rounded-md border border-border bg-muted/40 px-2.5 py-1.5", children: [_jsx(IconShieldCheck, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "min-w-0 flex-1 text-xs text-muted-foreground", children: t("agentChat.approval.question", { tool: toolName }) }), ctx && (_jsxs("button", { type: "button", onClick: () => {
|
|
262
268
|
setLocalResolution("approved");
|
|
263
269
|
ctx.onApprovalResolved?.(approval.approvalKey, "approved", toolCallId);
|
|
264
270
|
ctx.onApprove(approval.approvalKey);
|
|
265
|
-
}, className: cn("inline-flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90"), children: [_jsx(IconCheck, { className: "h-3.5 w-3.5" }), "
|
|
271
|
+
}, className: cn("inline-flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1 text-xs font-medium transition-colors", "bg-foreground text-background hover:bg-foreground/90"), children: [_jsx(IconCheck, { className: "h-3.5 w-3.5" }), t("agentChat.approval.approve")] })), ctx?.onAlwaysAllow && (_jsxs("button", { type: "button", onClick: () => {
|
|
266
272
|
setLocalResolution("approved");
|
|
267
273
|
ctx.onApprovalResolved?.(approval.approvalKey, "approved", toolCallId);
|
|
268
274
|
ctx.onAlwaysAllow?.(approval.approvalKey);
|
|
269
|
-
}, title: "
|
|
275
|
+
}, title: t("agentChat.approval.alwaysAllowHint"), className: cn("inline-flex shrink-0 items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium transition-colors", "text-foreground hover:bg-muted"), children: [_jsx(IconShieldCheck, { className: "h-3.5 w-3.5" }), t("agentChat.approval.alwaysAllow")] })), _jsxs("button", { type: "button", onClick: () => {
|
|
270
276
|
setLocalResolution("denied");
|
|
271
277
|
ctx?.onApprovalResolved?.(approval.approvalKey, "denied", toolCallId);
|
|
272
278
|
ctx?.onDeny?.(approval.approvalKey);
|
|
273
|
-
}, className: cn("inline-flex shrink-0 items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium transition-colors", "text-foreground hover:bg-muted"), children: [_jsx(IconX, { className: "h-3.5 w-3.5" }), "
|
|
279
|
+
}, className: cn("inline-flex shrink-0 items-center gap-1 rounded-md border border-border px-2.5 py-1 text-xs font-medium transition-colors", "text-foreground hover:bg-muted"), children: [_jsx(IconX, { className: "h-3.5 w-3.5" }), t("agentChat.approval.deny")] })] }));
|
|
274
280
|
}
|
|
275
281
|
// ─── ToolCallDisplay ──────────────────────────────────────────────────────────
|
|
276
282
|
export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, structuredMeta, activity, approval, repeatCount, isLatestRunning = isRunning, isActiveTail, }) {
|
|
@@ -303,6 +309,7 @@ export function ToolCallDisplay({ toolName, toolCallId, argsText, args, result,
|
|
|
303
309
|
return wrapToolDisplay(_jsx(ToolCallDisplayGeneric, { toolName: toolName, toolCallId: toolCallId, argsText: argsText, args: args, result: result, mcpApp: mcpApp, chatUI: chatUI, isRunning: effectiveIsRunning, outcome: outcome, isActiveTail: showActiveTail, structuredMeta: structuredMeta, approval: approval, repeatCount: repeatCount }));
|
|
304
310
|
}
|
|
305
311
|
function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result, mcpApp, chatUI, isRunning, outcome, isActiveTail, structuredMeta, approval, repeatCount, }) {
|
|
312
|
+
const t = useT();
|
|
306
313
|
const suppressInlineOpenApp = React.useContext(SuppressInlineOpenAppContext);
|
|
307
314
|
const isRawCallAgent = toolName === "call-agent";
|
|
308
315
|
const isAgentCall = toolName.startsWith("agent:") || isRawCallAgent;
|
|
@@ -362,7 +369,7 @@ function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result,
|
|
|
362
369
|
if (parsed.taskId && parsed.threadId) {
|
|
363
370
|
return (_jsx(AgentTaskCard, { taskId: parsed.taskId, threadId: parsed.threadId, description: parsed.description ||
|
|
364
371
|
args?.task ||
|
|
365
|
-
"
|
|
372
|
+
t("agentChat.tool.subAgentTask"), onOpen: (tid) => {
|
|
366
373
|
window.dispatchEvent(new CustomEvent("agent-task-open", {
|
|
367
374
|
detail: {
|
|
368
375
|
threadId: tid,
|
|
@@ -398,30 +405,38 @@ function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result,
|
|
|
398
405
|
if (NativeToolRenderer) {
|
|
399
406
|
return (_jsx(ActionChatUiSurface, { context: nativeToolContext, isBuiltinDataWidget: isBuiltinDataWidgetActionRenderer(nativeToolContext), children: _jsx(NativeToolRenderer, { context: nativeToolContext }) }));
|
|
400
407
|
}
|
|
401
|
-
const inputPayload = hasArgs
|
|
402
|
-
|
|
408
|
+
const inputPayload = hasArgs
|
|
409
|
+
? toolInputPayload(toolName, args, {
|
|
410
|
+
input: t("agentChat.tool.input"),
|
|
411
|
+
inputWithLabel: (label) => t("agentChat.tool.inputWithLabel", { label }),
|
|
412
|
+
})
|
|
413
|
+
: null;
|
|
414
|
+
const resultPayload = toolResultPayload(result, t("agentChat.tool.result"));
|
|
403
415
|
const displayName = isAgentCall
|
|
404
416
|
? isRunning
|
|
405
|
-
?
|
|
417
|
+
? t("agentChat.tool.askingAgent", { agent: agentName })
|
|
406
418
|
: isAgentError
|
|
407
|
-
?
|
|
408
|
-
:
|
|
419
|
+
? t("agentChat.tool.askingAgentFailed", { agent: agentName })
|
|
420
|
+
: t("agentChat.tool.askedAgent", { agent: agentName })
|
|
409
421
|
: humanizeToolName(toolName);
|
|
410
422
|
const canExpand = isAgentCall
|
|
411
423
|
? hasStreamText
|
|
412
424
|
: hasArgs || result !== undefined;
|
|
413
425
|
const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
|
|
414
426
|
const ToolIcon = resolveToolIcon(toolName);
|
|
415
|
-
const outputTitle =
|
|
427
|
+
const outputTitle = t("agentChat.tool.rawOutput", { tool: toolName });
|
|
416
428
|
if (isAgentCall) {
|
|
417
|
-
return (_jsx(AgentCallCell, { agentName: agentName ?? "agent", activity: agentActivity, progress: agentProgress, responseText: agentStreamText, isRunning: isRunning, isError: isAgentError, durationMs: typeof structuredMeta?.agentDurationMs === "number"
|
|
429
|
+
return (_jsx(AgentCallCell, { agentName: agentName ?? t("agentChat.common.agent"), activity: agentActivity, progress: agentProgress, responseText: agentStreamText, isRunning: isRunning, isError: isAgentError, durationMs: typeof structuredMeta?.agentDurationMs === "number"
|
|
418
430
|
? structuredMeta.agentDurationMs
|
|
419
431
|
: agentActivity?.durationMs }));
|
|
420
432
|
}
|
|
421
|
-
return (_jsxs("div", { className: "group/tool my-0.5 w-full overflow-hidden", children: [mcpApp && !(suppressInlineOpenApp && toolName === "open_app") && (_jsx(McpAppRenderer, { app: mcpApp, className: "mb-1.5" })), _jsxs("button", { type: "button", onClick: () => canExpand && setExpanded(!isExpanded), "aria-expanded": canExpand ? isExpanded : undefined, className: cn("flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground transition-colors", canExpand && "hover:text-foreground", isRunning && "text-muted-foreground"), children: [_jsx("span", { className: "relative flex size-4 shrink-0 items-center justify-center", children: isRunning ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "size-3.5 text-destructive" })) : isUnknownOutcome ? (_jsx(IconAlertTriangle, { className: "size-3.5 text-muted-foreground" })) : (_jsxs(_Fragment, { children: [_jsx(ToolIcon, { className: cn("size-3.5 transition-opacity", canExpand && "group-hover/tool:opacity-0") }), canExpand && (_jsx(IconChevronRight, { className: cn("absolute size-3.5 opacity-0 transition-[opacity,transform] group-hover/tool:opacity-100", isExpanded && "rotate-90") }))] })) }), _jsx("span", { className: cn("min-w-0 truncate font-normal", isActiveTail && "agent-running-shimmer"), children: displayName }), repeatCount && repeatCount > 1 && (_jsxs("span", { className: "shrink-0 rounded border border-border/60 px-1.5 py-0.5 text-[10px] leading-none text-muted-foreground", title:
|
|
433
|
+
return (_jsxs("div", { className: "group/tool my-0.5 w-full overflow-hidden", children: [mcpApp && !(suppressInlineOpenApp && toolName === "open_app") && (_jsx(McpAppRenderer, { app: mcpApp, className: "mb-1.5" })), _jsxs("button", { type: "button", onClick: () => canExpand && setExpanded(!isExpanded), "aria-expanded": canExpand ? isExpanded : undefined, className: cn("flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground transition-colors", canExpand && "hover:text-foreground", isRunning && "text-muted-foreground"), children: [_jsx("span", { className: "relative flex size-4 shrink-0 items-center justify-center", children: isRunning ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "size-3.5 text-destructive" })) : isUnknownOutcome ? (_jsx(IconAlertTriangle, { className: "size-3.5 text-muted-foreground" })) : (_jsxs(_Fragment, { children: [_jsx(ToolIcon, { className: cn("size-3.5 transition-opacity", canExpand && "group-hover/tool:opacity-0") }), canExpand && (_jsx(IconChevronRight, { className: cn("absolute size-3.5 opacity-0 transition-[opacity,transform] group-hover/tool:opacity-100", isExpanded && "rotate-90") }))] })) }), _jsx("span", { className: cn("min-w-0 truncate font-normal", isActiveTail && "agent-running-shimmer"), children: displayName }), repeatCount && repeatCount > 1 && (_jsxs("span", { className: "shrink-0 rounded border border-border/60 px-1.5 py-0.5 text-[10px] leading-none text-muted-foreground", title: t("agentChat.tool.repeated", { count: repeatCount }), children: [repeatCount, "x"] }))] }), _jsx(AnimatedCollapse, { open: isExpanded && !isAgentCall && (hasArgs || result !== undefined), children: _jsxs("div", { className: "mt-1 space-y-2 pl-5", children: [inputPayload && (_jsx(SimpleCodeViewer, { text: inputPayload.text, lang: inputPayload.lang })), resultPayload && (_jsx(ToolOutputPopover, { open: outputOpen, onOpenChange: setOutputOpen, title: outputTitle, payload: resultPayload, children: _jsx("button", { type: "button", "aria-label": t("agentChat.tool.viewOutput", {
|
|
434
|
+
tool: toolName,
|
|
435
|
+
}), className: "inline-flex size-6 items-center justify-center rounded-md text-muted-foreground/70 transition-colors hover:bg-accent hover:text-foreground", children: _jsx(IconCode, { className: "size-3.5" }) }) }))] }) }), isUnknownOutcome && (_jsx("p", { role: "status", className: "ps-5 text-xs text-muted-foreground", children: t("agentChat.tool.interrupted") })), approval && (_jsx(ApprovalAffordance, { toolName: toolName, toolCallId: toolCallId, approval: approval }))] }));
|
|
422
436
|
}
|
|
423
437
|
function AgentCallCell({ agentName, activity, progress, responseText, isRunning, isError, durationMs, }) {
|
|
424
438
|
const t = useT();
|
|
439
|
+
const formatDuration = useLocalizedWorkedDuration();
|
|
425
440
|
const [open, setOpen] = useState(true);
|
|
426
441
|
const toolCount = activity?.toolCalls?.length ?? 0;
|
|
427
442
|
// Response segments are ordered against the tool calls that preceded them, so
|
|
@@ -434,10 +449,10 @@ function AgentCallCell({ agentName, activity, progress, responseText, isRunning,
|
|
|
434
449
|
const work = activity?.reasoning?.length || toolCount || inlineSegments.length;
|
|
435
450
|
const workItemCount = Math.max(activity?.reasoning?.length ?? 0, toolCount, inlineSegments.length);
|
|
436
451
|
const label = isRunning
|
|
437
|
-
? t("
|
|
452
|
+
? t("agentChat.tool.askingAgent", { agent: agentName })
|
|
438
453
|
: isError
|
|
439
|
-
? t("
|
|
440
|
-
: t("
|
|
454
|
+
? t("agentChat.tool.askingAgentFailed", { agent: agentName })
|
|
455
|
+
: t("agentChat.tool.askedAgent", { agent: agentName });
|
|
441
456
|
const workContent = work ? (_jsx("div", { className: "space-y-1 ps-5", children: Array.from({ length: workItemCount }, (_, index) => {
|
|
442
457
|
const reasoningText = activity?.reasoning?.[index];
|
|
443
458
|
const segment = inlineSegments[index];
|
|
@@ -452,8 +467,8 @@ function AgentCallCell({ agentName, activity, progress, responseText, isRunning,
|
|
|
452
467
|
const progressText = isRunning && !activity && progress && progressState
|
|
453
468
|
? [
|
|
454
469
|
progressState.charAt(0).toUpperCase() + progressState.slice(1),
|
|
455
|
-
t("
|
|
456
|
-
duration:
|
|
470
|
+
t("agentChat.tool.elapsed", {
|
|
471
|
+
duration: formatDuration(progress.elapsedSeconds * 1000),
|
|
457
472
|
}),
|
|
458
473
|
progress.detail,
|
|
459
474
|
]
|
|
@@ -603,6 +618,8 @@ function isReconnectToolSummaryPart(content, index, startIndex) {
|
|
|
603
618
|
*/
|
|
604
619
|
const WorkSummaryContentContext = React.createContext(false);
|
|
605
620
|
export function ReasoningCell({ text, isStreaming = false, defaultOpen, autoCollapse = false, collapseWhenReplaced = false, durationMs, }) {
|
|
621
|
+
const t = useT();
|
|
622
|
+
const formatDuration = useLocalizedWorkedDuration();
|
|
606
623
|
const embeddedInWorkSummary = React.useContext(WorkSummaryContentContext);
|
|
607
624
|
const [open, setOpen] = useState(defaultOpen ?? true);
|
|
608
625
|
const wasStreamingRef = useRef(isStreaming);
|
|
@@ -630,35 +647,54 @@ export function ReasoningCell({ text, isStreaming = false, defaultOpen, autoColl
|
|
|
630
647
|
return (_jsx("div", { className: "pb-1 pl-5 text-[13px] leading-relaxed text-muted-foreground whitespace-pre-wrap", children: visibleText || (isStreaming ? "…" : "") }));
|
|
631
648
|
}
|
|
632
649
|
const label = isStreaming
|
|
633
|
-
? "
|
|
650
|
+
? t("agentChat.status.thinking")
|
|
634
651
|
: durationMs != null
|
|
635
|
-
?
|
|
636
|
-
|
|
652
|
+
? t("agentChat.tool.thoughtFor", {
|
|
653
|
+
duration: formatDuration(durationMs),
|
|
654
|
+
})
|
|
655
|
+
: t("agentChat.tool.thought");
|
|
637
656
|
// Only clamp to a scroll-free "tail" view while actively streaming and
|
|
638
657
|
// expanded — once the run finishes the full text is shown, unclamped.
|
|
639
658
|
const showTail = isStreaming && open;
|
|
640
659
|
return (_jsxs("div", { className: "my-0.5 w-full", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, className: "flex items-center gap-1.5 py-0.5 text-[13px] text-muted-foreground transition-colors hover:text-foreground", children: [_jsx(IconChevronRight, { className: cn("size-3.5 shrink-0 transition-transform", open && "rotate-90") }), isStreaming ? (_jsx("span", { className: "agent-thinking-indicator__text", children: label })) : (_jsx("span", { children: label }))] }), _jsx(AnimatedCollapse, { open: open, children: _jsx("div", { className: cn("pl-5 pb-1", showTail && "reasoning-cell-tail"), children: _jsx("div", { className: "text-[13px] leading-relaxed text-muted-foreground whitespace-pre-wrap", children: visibleText || (isStreaming ? "…" : "") }) }) })] }));
|
|
641
660
|
}
|
|
642
661
|
// ─── Worked-for duration helpers ──────────────────────────────────────────────
|
|
643
|
-
export function formatWorkedDuration(ms) {
|
|
662
|
+
export function formatWorkedDuration(ms, options = {}) {
|
|
663
|
+
const number = new Intl.NumberFormat(options.locale ?? "en-US");
|
|
664
|
+
const hour = options.hour ?? "h";
|
|
665
|
+
const minute = options.minute ?? "m";
|
|
666
|
+
const second = options.second ?? "s";
|
|
667
|
+
const part = (value, unit) => `${number.format(value)}${unit}`;
|
|
644
668
|
const totalSeconds = Math.max(0, Math.round(ms / 1000));
|
|
645
669
|
if (totalSeconds < 60) {
|
|
646
|
-
return
|
|
670
|
+
return part(Math.max(1, totalSeconds), second);
|
|
647
671
|
}
|
|
648
672
|
const minutes = Math.floor(totalSeconds / 60);
|
|
649
673
|
const seconds = totalSeconds % 60;
|
|
650
674
|
if (minutes < 60) {
|
|
651
675
|
if (seconds === 0)
|
|
652
|
-
return
|
|
653
|
-
return `${minutes}
|
|
676
|
+
return part(minutes, minute);
|
|
677
|
+
return `${part(minutes, minute)} ${part(seconds, second)}`;
|
|
654
678
|
}
|
|
655
679
|
const hours = Math.floor(minutes / 60);
|
|
656
680
|
const remMinutes = minutes % 60;
|
|
657
681
|
if (remMinutes === 0)
|
|
658
|
-
return
|
|
659
|
-
return `${hours}
|
|
682
|
+
return part(hours, hour);
|
|
683
|
+
return `${part(hours, hour)} ${part(remMinutes, minute)}`;
|
|
684
|
+
}
|
|
685
|
+
export function useLocalizedWorkedDuration() {
|
|
686
|
+
const t = useT();
|
|
687
|
+
const locale = useOptionalLocale()?.locale ?? "en-US";
|
|
688
|
+
return useCallback((ms) => formatWorkedDuration(ms, {
|
|
689
|
+
locale,
|
|
690
|
+
hour: t("agentChat.duration.hourShort"),
|
|
691
|
+
minute: t("agentChat.duration.minuteShort"),
|
|
692
|
+
second: t("agentChat.duration.secondShort"),
|
|
693
|
+
}), [locale, t]);
|
|
660
694
|
}
|
|
661
695
|
export function WorkedForSummary({ durationMs, defaultOpen = false, autoCollapse = false, children, }) {
|
|
696
|
+
const t = useT();
|
|
697
|
+
const formatDuration = useLocalizedWorkedDuration();
|
|
662
698
|
// Ordinary completed work starts closed so a remount never flashes details
|
|
663
699
|
// while auto-collapse settles. Interactive UI opts into an open summary.
|
|
664
700
|
const [open, setOpen] = useState(defaultOpen);
|
|
@@ -671,13 +707,16 @@ export function WorkedForSummary({ durationMs, defaultOpen = false, autoCollapse
|
|
|
671
707
|
}
|
|
672
708
|
}, [autoCollapse, defaultOpen]);
|
|
673
709
|
const label = durationMs != null && durationMs >= 1000
|
|
674
|
-
?
|
|
675
|
-
|
|
710
|
+
? t("agentChat.tool.workedFor", {
|
|
711
|
+
duration: formatDuration(durationMs),
|
|
712
|
+
})
|
|
713
|
+
: t("agentChat.tool.worked");
|
|
676
714
|
return (_jsxs("div", { className: "my-1 w-full", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, className: "flex items-center gap-1.5 py-0.5 text-[13px] text-muted-foreground transition-colors hover:text-foreground", children: [_jsx("span", { children: label }), _jsx(IconChevronRight, { className: cn("size-3.5 shrink-0 transition-transform", open && "rotate-90") })] }), _jsx(AnimatedCollapse, { open: open, children: _jsx(WorkSummaryContentContext.Provider, { value: true, children: _jsx("div", { className: "pt-1", children: children }) }) })] }));
|
|
677
715
|
}
|
|
678
716
|
export function RanToolsSummary({ toolCount, motionKey = "summary", children, }) {
|
|
717
|
+
const t = useT();
|
|
679
718
|
const [open, setOpen] = useState(false);
|
|
680
|
-
const label =
|
|
719
|
+
const label = t("agentChat.tool.ranTools", { count: toolCount });
|
|
681
720
|
return (_jsxs("div", { className: "agent-tool-summary my-1 w-full", "data-agent-tool-summary": motionKey, children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, className: "flex items-center gap-1.5 py-0.5 text-[13px] text-muted-foreground transition-colors hover:text-foreground", children: [_jsx("span", { className: "agent-tool-summary__label", children: label }), _jsx(IconChevronRight, { className: cn("size-3.5 shrink-0 transition-transform", open && "rotate-90") })] }), _jsx(AnimatedCollapse, { open: open, children: _jsx("div", { className: "pt-1", children: children }) })] }));
|
|
682
721
|
}
|
|
683
722
|
// ─── Re-export for AssistantMessage ───────────────────────────────────────────
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useT } from "../../i18n.js";
|
|
2
3
|
const DEFAULT_COLORS = [
|
|
3
4
|
"hsl(var(--primary))",
|
|
4
5
|
"hsl(199 89% 48%)",
|
|
@@ -105,5 +106,6 @@ function ChartBody({ chart }) {
|
|
|
105
106
|
return (_jsxs(_Fragment, { children: [axes, paths.map(({ series, color, areaPath }) => chart.type === "area" && areaPath ? (_jsx("path", { d: areaPath, fill: color, opacity: "0.18", stroke: "none" }, series.key)) : null), paths.map(({ series, color, linePath, points }) => (_jsxs("g", { children: [_jsx("path", { d: linePath, fill: "none", stroke: color, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }), points.map((point, index) => (_jsx("circle", { cx: point.x, cy: point.y, r: "3", fill: "hsl(var(--background))", stroke: color, strokeWidth: "2" }, index)))] }, series.key)))] }));
|
|
106
107
|
}
|
|
107
108
|
export function DataChartRenderer({ chart }) {
|
|
108
|
-
|
|
109
|
+
const t = useT();
|
|
110
|
+
return (_jsx("div", { className: "h-60 w-full min-w-0 overflow-hidden", children: _jsx("svg", { className: "agent-data-chart-renderer h-full w-full", viewBox: `0 0 ${WIDTH} ${HEIGHT}`, role: "img", "aria-label": chart.title ?? t("agentChat.widget.dataChart"), preserveAspectRatio: "none", children: _jsx(ChartBody, { chart: chart }) }) }));
|
|
109
111
|
}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconChartBar } from "@tabler/icons-react";
|
|
3
3
|
import { lazy, Suspense, useEffect, useState } from "react";
|
|
4
|
+
import { DEFAULT_LOCALE, useOptionalLocale, useT } from "../../i18n.js";
|
|
4
5
|
const LazyDataChartRenderer = lazy(() => import("./DataChartRenderer.js").then((module) => ({
|
|
5
6
|
default: module.DataChartRenderer,
|
|
6
7
|
})));
|
|
7
8
|
export function DataChartWidget({ chart }) {
|
|
9
|
+
const t = useT();
|
|
10
|
+
const locale = useOptionalLocale()?.locale ?? DEFAULT_LOCALE;
|
|
8
11
|
const [mounted, setMounted] = useState(false);
|
|
9
12
|
useEffect(() => {
|
|
10
13
|
setMounted(true);
|
|
11
14
|
}, []);
|
|
12
|
-
const fallback = (_jsx("div", { className: "flex h-60 items-center justify-center rounded-md bg-muted/30 text-xs text-muted-foreground", children: "
|
|
13
|
-
return (_jsxs("div", { className: "my-1.5 overflow-hidden rounded-lg border border-border bg-background text-foreground shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [_jsx(IconChartBar, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: chart.title ?? "
|
|
15
|
+
const fallback = (_jsx("div", { className: "flex h-60 items-center justify-center rounded-md bg-muted/30 text-xs text-muted-foreground", children: t("agentChat.widget.chart") }));
|
|
16
|
+
return (_jsxs("div", { className: "my-1.5 overflow-hidden rounded-lg border border-border bg-background text-foreground shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [_jsx(IconChartBar, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: chart.title ?? t("agentChat.widget.dataChart") }), _jsxs("div", { className: "text-[11px] text-muted-foreground", children: [t("agentChat.widget.points", {
|
|
17
|
+
count: chart.data.length,
|
|
18
|
+
formattedCount: chart.data.length.toLocaleString(locale),
|
|
19
|
+
}), chart.sampled ? ` ${t("agentChat.widget.sampled")}` : ""] })] })] }), _jsx("div", { className: "p-3", children: !mounted ? (fallback) : (_jsx(Suspense, { fallback: fallback, children: _jsx(LazyDataChartRenderer, { chart: chart }) })) })] }));
|
|
14
20
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconDatabase } from "@tabler/icons-react";
|
|
3
|
+
import { useT } from "../../i18n.js";
|
|
3
4
|
import { DataChartWidget } from "./DataChartWidget.js";
|
|
4
5
|
import { DataTableWidget } from "./DataTableWidget.js";
|
|
5
6
|
function SummaryPill({ label, value }) {
|
|
@@ -8,7 +9,8 @@ function SummaryPill({ label, value }) {
|
|
|
8
9
|
return (_jsxs("div", { className: "rounded-md border border-border bg-muted/30 px-2 py-1", children: [_jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: label }), _jsx("div", { className: "text-xs font-medium text-foreground", children: typeof value === "number" ? value.toLocaleString() : String(value) })] }));
|
|
9
10
|
}
|
|
10
11
|
export function DataInsightsWidget({ result }) {
|
|
11
|
-
const
|
|
12
|
+
const t = useT();
|
|
13
|
+
const title = result.display?.title ?? result.title ?? t("agentChat.widget.dataInsights");
|
|
12
14
|
const summary = result.summary ?? {};
|
|
13
15
|
return (_jsxs("div", { className: "my-1.5 space-y-2", children: [_jsxs("div", { className: "rounded-lg border border-border bg-background p-3 text-foreground shadow-sm", children: [_jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(IconDatabase, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate text-sm font-medium", children: title }), result.display?.description ? (_jsx("div", { className: "text-xs text-muted-foreground", children: result.display.description })) : null] })] }), _jsx("div", { className: "grid grid-cols-2 gap-2 sm:grid-cols-4", children: Object.entries(summary)
|
|
14
16
|
.filter(([, value]) => typeof value !== "object")
|
|
@@ -4,23 +4,26 @@ import { requestAgentSidebarOpen } from "../../agent-sidebar-state.js";
|
|
|
4
4
|
import { appPath } from "../../api-path.js";
|
|
5
5
|
import { startAgentChatViewTransition } from "../../chat-view-transition.js";
|
|
6
6
|
import { downloadFile, toCSVTable } from "../../db-admin/export-utils.js";
|
|
7
|
+
import { DEFAULT_LOCALE, useOptionalLocale, useT } from "../../i18n.js";
|
|
7
8
|
import { cn } from "../../utils.js";
|
|
8
9
|
const SAFE_ACTION_PROTOCOLS = new Set(["http:", "https:", "mailto:"]);
|
|
9
|
-
function formatCell(value) {
|
|
10
|
+
function formatCell(value, locale, booleanLabels = { yes: "Yes", no: "No" }) {
|
|
10
11
|
if (value === undefined || value === null || value === "")
|
|
11
12
|
return "—";
|
|
12
13
|
if (typeof value === "boolean")
|
|
13
|
-
return value ?
|
|
14
|
+
return value ? booleanLabels.yes : booleanLabels.no;
|
|
14
15
|
if (typeof value === "number")
|
|
15
|
-
return value.toLocaleString();
|
|
16
|
+
return value.toLocaleString(locale);
|
|
16
17
|
if (Array.isArray(value))
|
|
17
|
-
return value
|
|
18
|
+
return value
|
|
19
|
+
.map((item) => formatCell(item, locale, booleanLabels))
|
|
20
|
+
.join(", ");
|
|
18
21
|
if (typeof value === "object")
|
|
19
22
|
return JSON.stringify(value);
|
|
20
23
|
const text = String(value);
|
|
21
24
|
const timestamp = Date.parse(text);
|
|
22
25
|
if (Number.isFinite(timestamp) && /^\d{4}-\d{2}-\d{2}T/.test(text)) {
|
|
23
|
-
return new Intl.DateTimeFormat(
|
|
26
|
+
return new Intl.DateTimeFormat(locale, {
|
|
24
27
|
month: "short",
|
|
25
28
|
day: "numeric",
|
|
26
29
|
hour: "numeric",
|
|
@@ -83,6 +86,8 @@ function slugifyFilenamePart(value) {
|
|
|
83
86
|
return slug || "data-table";
|
|
84
87
|
}
|
|
85
88
|
export function DataTableWidget({ table, action, }) {
|
|
89
|
+
const t = useT();
|
|
90
|
+
const locale = useOptionalLocale()?.locale ?? DEFAULT_LOCALE;
|
|
86
91
|
const rows = table.rows ?? [];
|
|
87
92
|
const actionHref = action ? normalizeActionHref(action.href) : null;
|
|
88
93
|
const canExportCsv = table.columns.length > 0;
|
|
@@ -92,9 +97,15 @@ export function DataTableWidget({ table, action, }) {
|
|
|
92
97
|
const stamp = new Date().toISOString().slice(0, 10);
|
|
93
98
|
downloadFile(`${slugifyFilenamePart(table.title)}-${stamp}.csv`, "text/csv;charset=utf-8", toCSVTable(table.columns.map((column) => column.label), rows.map((row) => table.columns.map((column) => row[column.key]))));
|
|
94
99
|
};
|
|
95
|
-
return (_jsxs("div", { className: "my-1.5 overflow-hidden rounded-lg border border-border bg-background text-foreground shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [_jsx(IconTable, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: table.title ?? "
|
|
96
|
-
?
|
|
97
|
-
|
|
100
|
+
return (_jsxs("div", { className: "my-1.5 overflow-hidden rounded-lg border border-border bg-background text-foreground shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [_jsx(IconTable, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: table.title ?? t("agentChat.widget.dataTable") }), _jsxs("div", { className: "text-[11px] text-muted-foreground", children: [typeof table.totalRows === "number"
|
|
101
|
+
? t("agentChat.widget.rows", {
|
|
102
|
+
count: table.totalRows,
|
|
103
|
+
formattedCount: table.totalRows.toLocaleString(locale),
|
|
104
|
+
})
|
|
105
|
+
: t("agentChat.widget.rows", {
|
|
106
|
+
count: rows.length,
|
|
107
|
+
formattedCount: rows.length.toLocaleString(locale),
|
|
108
|
+
}), table.truncated ? ` ${t("agentChat.widget.sampled")}` : ""] })] }), action && actionHref ? (_jsxs("a", { href: actionHref, onClick: (event) => {
|
|
98
109
|
if (event.defaultPrevented ||
|
|
99
110
|
event.button !== 0 ||
|
|
100
111
|
event.metaKey ||
|
|
@@ -106,5 +117,8 @@ export function DataTableWidget({ table, action, }) {
|
|
|
106
117
|
}
|
|
107
118
|
event.preventDefault();
|
|
108
119
|
navigateSameAppHref(actionHref);
|
|
109
|
-
}, className: "inline-flex shrink-0 items-center gap-1 rounded-md border border-border px-2 py-1 text-[11px] font-medium text-foreground no-underline hover:bg-muted hover:no-underline", children: [action.label, _jsx(IconExternalLink, { className: "h-3 w-3" })] })) : null, _jsxs("button", { type: "button", onClick: exportCsv, disabled: !canExportCsv, className: "inline-flex shrink-0 items-center gap-1 rounded-md bg-primary px-2 py-1 text-[11px] font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50", children: [_jsx(IconDownload, { className: "h-3 w-3" }), "
|
|
120
|
+
}, className: "inline-flex shrink-0 items-center gap-1 rounded-md border border-border px-2 py-1 text-[11px] font-medium text-foreground no-underline hover:bg-muted hover:no-underline", children: [action.label, _jsx(IconExternalLink, { className: "h-3 w-3" })] })) : null, _jsxs("button", { type: "button", onClick: exportCsv, disabled: !canExportCsv, className: "inline-flex shrink-0 items-center gap-1 rounded-md bg-primary px-2 py-1 text-[11px] font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50", children: [_jsx(IconDownload, { className: "h-3 w-3" }), t("agentChat.widget.downloadCsv")] })] }), _jsx("div", { className: "max-h-[360px] overflow-auto", children: _jsxs("table", { className: "w-full min-w-[420px] border-collapse text-xs", children: [_jsx("thead", { className: "sticky top-0 z-10 bg-muted/70 backdrop-blur", children: _jsx("tr", { children: table.columns.map((column) => (_jsx("th", { className: cn("border-b border-border px-3 py-2 font-medium text-muted-foreground", column.align === "right" ? "text-right" : "text-left"), children: column.label }, column.key))) }) }), _jsx("tbody", { children: rows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: Math.max(1, table.columns.length), className: "px-3 py-8 text-center text-muted-foreground", children: t("agentChat.widget.noRows") }) })) : (rows.map((row, rowIndex) => (_jsx("tr", { className: "border-b border-border/70 last:border-0", children: table.columns.map((column) => (_jsx("td", { className: cn("max-w-[260px] px-3 py-2 align-top text-foreground", column.align === "right" ? "text-right" : "text-left"), children: _jsx("span", { className: "line-clamp-3 break-words", children: formatCell(row[column.key], locale, {
|
|
121
|
+
yes: t("agentChat.common.yes"),
|
|
122
|
+
no: t("agentChat.common.no"),
|
|
123
|
+
}) }) }, `${rowIndex}-${column.key}`))) }, String(row.id ?? rowIndex))))) })] }) })] }));
|
|
110
124
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { lazy, Suspense } from "react";
|
|
3
3
|
import { ACTION_CHAT_UI_DATA_CHART_RENDERER, ACTION_CHAT_UI_DATA_INSIGHTS_RENDERER, ACTION_CHAT_UI_DATA_TABLE_RENDERER, ACTION_CHAT_UI_DATA_WIDGET_RENDERER, ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER, ACTION_CHAT_UI_WORKSPACE_FILE_RENDERER, } from "../../../action-ui.js";
|
|
4
|
+
import { useT } from "../../i18n.js";
|
|
4
5
|
import { registerReservedActionChatRenderer, registerReservedFallbackToolRenderer, } from "../tool-render-registry.js";
|
|
5
6
|
import { DATA_CHART_WIDGET, DATA_INSIGHTS_WIDGET, DATA_TABLE_WIDGET, normalizeDataWidgetKind, normalizeDataWidgetResult, } from "./data-widget-types.js";
|
|
6
7
|
import { normalizeInlineExtensionToolResult } from "./inline-extension-result.js";
|
|
@@ -80,7 +81,8 @@ function renderDataWidget(context) {
|
|
|
80
81
|
return null;
|
|
81
82
|
}
|
|
82
83
|
function BuiltinToolRendererSkeleton({ framed = true }) {
|
|
83
|
-
|
|
84
|
+
const t = useT();
|
|
85
|
+
return (_jsx("div", { "aria-label": t("agentChat.widget.loadingToolResult"), className: framed
|
|
84
86
|
? "my-1.5 h-24 animate-pulse rounded-lg border border-border bg-muted/30"
|
|
85
87
|
: "h-24 animate-pulse bg-muted/30" }));
|
|
86
88
|
}
|
|
@@ -98,7 +98,7 @@ export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, activeA
|
|
|
98
98
|
persistLayout({ ...layout, orderedIds: nextOrder });
|
|
99
99
|
}
|
|
100
100
|
if (collapsed) {
|
|
101
|
-
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "flex flex-col items-center gap-1 px-1.5 pt-2", "aria-label": copy("workspaceApps"), children: [
|
|
101
|
+
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "flex flex-col items-center gap-1 px-1.5 pt-2", "aria-label": copy("workspaceApps"), children: [loading && apps.length === 0
|
|
102
102
|
? [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "size-9 rounded-md" }, index)))
|
|
103
103
|
: visibleApps.map((app) => (_jsx("button", { type: "button", "data-chat-first-app": true, "data-app-id": app.id, className: cn("flex size-9 items-center justify-center rounded-md", activeAppId === app.id
|
|
104
104
|
? "text-sidebar-foreground"
|
|
@@ -8,7 +8,7 @@ type MessageScrollerItemProps = React.ComponentProps<typeof ShadcnMessageScrolle
|
|
|
8
8
|
type MessageScrollerButtonProps = React.ComponentProps<typeof ShadcnMessageScroller.Button>;
|
|
9
9
|
declare function MessageScrollerProvider(props: MessageScrollerProviderProps): React.JSX.Element;
|
|
10
10
|
declare function MessageScroller({ className, ...props }: MessageScrollerRootProps): React.JSX.Element;
|
|
11
|
-
declare function MessageScrollerViewport({ className, children, ...props }: MessageScrollerViewportProps): React.JSX.Element;
|
|
11
|
+
declare function MessageScrollerViewport({ className, children, "aria-label": ariaLabel, ...props }: MessageScrollerViewportProps): React.JSX.Element;
|
|
12
12
|
declare function MessageScrollerContent({ className, spacerClassName, ...props }: MessageScrollerContentProps): React.JSX.Element;
|
|
13
13
|
declare function MessageScrollerItem(props: MessageScrollerItemProps): React.JSX.Element;
|
|
14
14
|
declare function MessageScrollerButton({ className, children, render, ...props }: MessageScrollerButtonProps): React.JSX.Element;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { MessageScroller as ShadcnMessageScroller, useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility, } from "@shadcn/react/message-scroller";
|
|
3
3
|
import { IconChevronDown } from "@tabler/icons-react";
|
|
4
|
+
import { useT } from "../../i18n.js";
|
|
4
5
|
import { cn } from "../../utils.js";
|
|
5
6
|
function MessageScrollerProvider(props) {
|
|
6
7
|
return _jsx(ShadcnMessageScroller.Provider, { ...props });
|
|
@@ -8,12 +9,14 @@ function MessageScrollerProvider(props) {
|
|
|
8
9
|
function MessageScroller({ className, ...props }) {
|
|
9
10
|
return (_jsx(ShadcnMessageScroller.Root, { className: cn("relative flex min-h-0 flex-1 flex-col", className), ...props }));
|
|
10
11
|
}
|
|
11
|
-
function MessageScrollerViewport({ className, children, ...props }) {
|
|
12
|
+
function MessageScrollerViewport({ className, children, "aria-label": ariaLabel, ...props }) {
|
|
13
|
+
const t = useT();
|
|
12
14
|
const { start: hasContentAbove } = useMessageScrollerScrollable();
|
|
13
15
|
return (_jsx(ShadcnMessageScroller.Viewport, { className: cn("min-h-0 flex-1 overflow-y-auto overflow-x-hidden",
|
|
14
16
|
// The base class carries the mask itself so it is never added or
|
|
15
17
|
// removed; the modifier only widens the fade. See agent-native.css.
|
|
16
|
-
"message-scroller-viewport", hasContentAbove && "message-scroller-viewport--top-fade", className),
|
|
18
|
+
"message-scroller-viewport", hasContentAbove && "message-scroller-viewport--top-fade", className), "aria-label": ariaLabel ??
|
|
19
|
+
t("agentChat.message.messages", { defaultValue: "Messages" }), ...props, children: children }));
|
|
17
20
|
}
|
|
18
21
|
function MessageScrollerContent({ className, spacerClassName, ...props }) {
|
|
19
22
|
return (_jsx(ShadcnMessageScroller.Content, { className: cn("flex flex-col", className), spacerClassName: cn("shrink-0", spacerClassName), ...props }));
|
|
@@ -22,7 +25,8 @@ function MessageScrollerItem(props) {
|
|
|
22
25
|
return _jsx(ShadcnMessageScroller.Item, { ...props });
|
|
23
26
|
}
|
|
24
27
|
function MessageScrollerButton({ className, children, render, ...props }) {
|
|
28
|
+
const t = useT();
|
|
25
29
|
return (_jsx(ShadcnMessageScroller.Button, { render: render ??
|
|
26
|
-
((buttonProps) => (_jsx("div", { className: "
|
|
30
|
+
((buttonProps) => (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-2 z-10 flex justify-center", children: _jsx("button", { ...buttonProps, className: cn("pointer-events-auto flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "data-[active=false]:hidden", className, buttonProps.className), "aria-label": t("agentChat.composer.scrollToBottom"), children: children ?? (_jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })) }) }))), ...props }));
|
|
27
31
|
}
|
|
28
32
|
export { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility, };
|
|
@@ -12,7 +12,7 @@ import { getBrowserTabId } from "../browser-tab-id.js";
|
|
|
12
12
|
import { isTrustedBuilderMessage, tryDelegateBuildRequestToBuilder, } from "../builder-frame.js";
|
|
13
13
|
import { BuilderSetupCard, BuilderSetupContent } from "../chat/run-recovery.js";
|
|
14
14
|
import { isTrustedFrameMessage } from "../frame.js";
|
|
15
|
-
import { useT } from "../i18n.js";
|
|
15
|
+
import { useFormatters, useT } from "../i18n.js";
|
|
16
16
|
import { useOrg } from "../org/hooks.js";
|
|
17
17
|
import { isMcpIntegrationCatalogAvailable } from "../resources/mcp-integration-catalog.js";
|
|
18
18
|
import { McpIntegrationDialog } from "../resources/McpIntegrationDialog.js";
|
|
@@ -79,6 +79,7 @@ const coreComposerAdapters = {
|
|
|
79
79
|
};
|
|
80
80
|
export function CoreComposerRuntimeProvider({ children, }) {
|
|
81
81
|
const translate = useT();
|
|
82
|
-
const
|
|
82
|
+
const { formatNumber } = useFormatters();
|
|
83
|
+
const adapters = useMemo(() => ({ ...coreComposerAdapters, formatNumber, translate }), [formatNumber, translate]);
|
|
83
84
|
return (_jsx(ComposerRuntimeAdaptersProvider, { adapters: adapters, children: children }));
|
|
84
85
|
}
|