@agent-native/core 0.154.5 → 0.157.0
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/.agents/skills/account-health/SKILL.md +76 -0
- package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +3 -0
- package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +2 -1
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +6 -5
- package/corpus/templates/analytics/AGENTS.md +3 -0
- package/corpus/templates/analytics/actions/account-deep-dive.ts +3 -2
- package/corpus/templates/analytics/actions/bigquery.ts +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -1
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyCombobox.tsx +12 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyValueCombobox.tsx +5 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer/property-label.ts +32 -0
- package/corpus/templates/analytics/changelog/2026-08-13-account-health-readouts-verify-customer-scope-and-contract-metrics.md +7 -0
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +43 -17
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +17 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +17 -13
- package/corpus/templates/calendar/AGENTS.md +2 -0
- package/corpus/templates/calendar/DEVELOPING.md +4 -4
- package/corpus/templates/calendar/actions/get-settings.ts +4 -11
- package/corpus/templates/calendar/actions/update-availability.ts +15 -4
- package/corpus/templates/calendar/actions/update-settings.ts +15 -4
- package/corpus/templates/calendar/app/components/booking/DatePicker.tsx +9 -3
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +21 -19
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +9 -6
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +25 -3
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +10 -3
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +9 -9
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -3
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +10 -4
- package/corpus/templates/calendar/app/i18n-data.ts +30 -0
- package/corpus/templates/calendar/app/lib/availability-schedule.ts +53 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +5 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +90 -28
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +135 -61
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +30 -15
- package/corpus/templates/calendar/app/pages/Settings.tsx +60 -1
- package/corpus/templates/calendar/changelog/2026-08-13-find-a-time-now-closes-from-a-clear-header-action.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +2 -1
- package/corpus/templates/calendar/server/handlers/settings.ts +12 -16
- package/corpus/templates/calendar/shared/api.ts +1 -0
- package/corpus/templates/calendar/shared/availability-schedule.ts +64 -0
- package/corpus/templates/calendar/shared/calendar-week.ts +21 -0
- package/corpus/templates/calendar/shared/settings.ts +44 -0
- package/corpus/templates/clips/AGENTS.md +2 -0
- package/corpus/templates/clips/actions/add-comment.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +31 -1
- package/corpus/templates/clips/actions/get-recording-player-data.ts +9 -0
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +21 -1
- package/corpus/templates/clips/actions/reply-to-comment.ts +5 -2
- package/corpus/templates/clips/actions/update-comment.ts +9 -2
- package/corpus/templates/clips/app/components/library/search-bar.tsx +26 -13
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +135 -3
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +5 -99
- package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +7 -3
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +102 -59
- package/corpus/templates/clips/app/components/player/video-player.tsx +84 -24
- package/corpus/templates/clips/app/components/workspace/notifications-list.tsx +11 -3
- package/corpus/templates/clips/app/i18n/en-US.ts +12 -0
- package/corpus/templates/clips/app/lib/public-meeting.ts +11 -3
- package/corpus/templates/clips/app/lib/search-focus.ts +15 -0
- package/corpus/templates/clips/app/root.tsx +2 -1
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +94 -26
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +24 -7
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +8 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +29 -8
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +24 -6
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +72 -26
- package/corpus/templates/clips/changelog/2026-08-13-inline-markdown-comments.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-13-private-meeting-agent-links.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +116 -19
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +13 -29
- package/corpus/templates/clips/desktop/src/lib/recording-request.ts +39 -0
- package/corpus/templates/clips/desktop/src/lib/settings-navigation.ts +11 -0
- package/corpus/templates/clips/desktop/src/lib/whisper-model-picker.ts +7 -0
- package/corpus/templates/clips/desktop/src/styles.css +117 -0
- package/corpus/templates/clips/server/db/index.ts +10 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/recordings.ts +3 -1
- package/corpus/templates/clips/server/lib/seekable-media-state.ts +90 -0
- package/corpus/templates/clips/server/plugins/db.ts +5 -0
- package/corpus/templates/clips/server/routes/api/public-meeting.get.ts +37 -4
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +16 -5
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +3 -0
- package/corpus/templates/clips/shared/meeting-agent-access.ts +5 -0
- package/corpus/templates/content/actions/add-comment.ts +2 -1
- package/corpus/templates/content/actions/update-comment.ts +1 -1
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +24 -15
- package/corpus/templates/design/actions/generate-design.ts +10 -7
- package/corpus/templates/design/actions/present-design-variants.ts +35 -6
- package/corpus/templates/design/actions/run-design-audit.ts +33 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-catches-a-screen-that-renders-behind-an.md +6 -0
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/html-integrity.ts +66 -0
- package/corpus/templates/dispatch/.env.example +5 -0
- package/corpus/templates/dispatch/AGENTS.md +24 -19
- package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
- package/corpus/templates/dispatch/server/lib/identity-sso.ts +21 -90
- package/corpus/templates/dispatch/server/plugins/identity-sso.ts +3 -12
- package/corpus/templates/dispatch/shared/feature-flags.ts +4 -0
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +23 -0
- package/corpus/templates/factory/actions/view-screen.ts +17 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +239 -0
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +2 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +130 -7
- package/corpus/templates/factory/app/i18n/en-US.ts +20 -0
- package/corpus/templates/factory/app/routes/factory.tsx +41 -0
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/factory-graph/contracts.ts +2 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -0
- package/corpus/templates/factory/server/plugins/dispatch-db.ts +1 -0
- package/corpus/templates/factory/server/plugins/setup-dispatch.ts +3 -0
- package/corpus/templates/mail/app/lib/native-mcp-exclusions.ts +3 -0
- package/corpus/templates/mail/vite.config.ts +7 -0
- package/corpus/templates/plan/actions/reply-to-plan-comment.ts +7 -2
- package/corpus/templates/plan/actions/resolve-plan-comment.ts +2 -2
- package/corpus/templates/plan/actions/update-visual-plan.ts +1 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +29 -20
- package/corpus/templates/slides/actions/add-slide-comment.ts +1 -1
- package/corpus/templates/slides/actions/update-slide-comment.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +9 -6
- 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/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +42 -2
- 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/pages/DeckEditor.tsx +130 -45
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/production-agent.d.ts +30 -0
- package/dist/agent/production-agent.js +105 -9
- package/dist/agent/thread-data-builder.js +17 -1
- package/dist/agent/types.d.ts +9 -0
- package/dist/cli/skills-content/help.js +6 -4
- package/dist/cli/skills.js +17 -2
- package/dist/cli/workspacify.d.ts +5 -0
- package/dist/cli/workspacify.js +65 -8
- package/dist/client/AgentPanel.d.ts +5 -0
- package/dist/client/AgentPanel.js +32 -13
- package/dist/client/AssistantChat.d.ts +36 -1
- package/dist/client/AssistantChat.js +175 -110
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/active-run-state.d.ts +14 -1
- package/dist/client/active-run-state.js +0 -0
- package/dist/client/agent-chat-adapter.js +107 -5
- package/dist/client/analytics.js +9 -2
- package/dist/client/chat/markdown-renderer.js +4 -2
- 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 +9 -4
- package/dist/client/chat-first/primary-nav.d.ts +2 -1
- package/dist/client/chat-first/primary-nav.js +3 -3
- package/dist/client/chat-first/types.d.ts +5 -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/markdown/InlineMarkdown.d.ts +23 -0
- package/dist/client/markdown/InlineMarkdown.js +65 -0
- package/dist/client/markdown/index.d.ts +1 -0
- package/dist/client/markdown/index.js +1 -0
- package/dist/client/observability/ThumbsFeedback.js +10 -8
- package/dist/client/review/ReviewThreadPanel.js +2 -1
- package/dist/client/run-stream-ownership.d.ts +39 -0
- package/dist/client/run-stream-ownership.js +65 -0
- package/dist/client/sharing/ShareButton.js +160 -54
- 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/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +10 -0
- package/dist/feature-flags/store.js +112 -1
- package/dist/guards/no-env-credentials.js +4 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/integrations/adapters/slack.js +5 -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 +2 -2
- 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/agents.js +40 -5
- package/dist/resources/metadata.d.ts +10 -0
- package/dist/resources/metadata.js +7 -3
- package/dist/review/actions/create-review-comment.js +1 -1
- package/dist/review/actions/reply-review-comment.js +1 -1
- package/dist/review/actions/resolve-review-thread.js +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-routes.js +32 -6
- 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-discovery.js +14 -3
- 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/core-routes-plugin.js +1 -1
- package/dist/server/identity-sso-migrations.d.ts +7 -0
- package/dist/server/identity-sso-migrations.js +36 -0
- package/dist/server/identity-sso-store.d.ts +3 -2
- package/dist/server/identity-sso-store.js +8 -3
- package/dist/server/index.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +4 -0
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/dist/tracking/providers.js +13 -3
- package/dist/workspace-files/tool.js +1 -1
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +3 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconClock, IconPlus, IconPlugConnected, IconSearch, } from "@tabler/icons-react";
|
|
3
3
|
import { defaultChatFirstCopy } from "./copy.js";
|
|
4
|
-
export function ChatFirstPrimaryNavigation({ onNewChat, onOpenIntegrations, onOpenScheduled, onSearch, activeTab, stickyNewChat = false, copy = defaultChatFirstCopy, }) {
|
|
4
|
+
export function ChatFirstPrimaryNavigation({ onNewChat, onOpenIntegrations, onOpenScheduled, onSearch, activeTab, collapsed = false, stickyNewChat = false, copy = defaultChatFirstCopy, }) {
|
|
5
5
|
const tabClassName = (tab) => `flex h-8 w-full items-center gap-2 rounded-md px-2 text-[13px] font-medium transition-[background-color,color] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${activeTab === tab
|
|
6
6
|
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
7
7
|
: "text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"}`;
|
|
8
|
-
const renderTab = (tab, content, onSelect, className) => (_jsx("button", { type: "button", role: "tab", "aria-selected": activeTab === tab, className: [tabClassName(tab), className].filter(Boolean).join(" "), onClick: onSelect, children: content }));
|
|
8
|
+
const renderTab = (tab, content, onSelect, className) => (_jsx("button", { type: "button", role: "tab", "aria-selected": activeTab === tab, "aria-label": tab === "new-chat" ? copy("newChat") : undefined, title: tab === "new-chat" && collapsed ? copy("newChat") : undefined, className: [tabClassName(tab), className].filter(Boolean).join(" "), onClick: onSelect, children: content }));
|
|
9
9
|
const newChatTab = onNewChat
|
|
10
|
-
? renderTab("new-chat", _jsxs(_Fragment, { children: [_jsx(IconPlus, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("newChat") })] }), onNewChat, "code-agents-primary-new-chat")
|
|
10
|
+
? renderTab("new-chat", _jsxs(_Fragment, { children: [_jsx(IconPlus, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: collapsed ? "sr-only" : undefined, children: copy("newChat") })] }), onNewChat, "code-agents-primary-new-chat")
|
|
11
11
|
: null;
|
|
12
12
|
const integrationsTab = renderTab("integrations", _jsxs(_Fragment, { children: [_jsx(IconPlugConnected, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("integrations") })] }), onOpenIntegrations);
|
|
13
13
|
const scheduledTab = renderTab("scheduled", _jsxs(_Fragment, { children: [_jsx(IconClock, { size: 15, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { children: copy("scheduled") })] }), onOpenScheduled);
|
|
@@ -8,6 +8,10 @@ export interface ChatFirstAppItem {
|
|
|
8
8
|
color?: string;
|
|
9
9
|
}
|
|
10
10
|
export type ChatFirstCopy = (key: string, values?: Record<string, string>) => string;
|
|
11
|
+
export interface ChatFirstAppIconRenderOptions {
|
|
12
|
+
isActive: boolean;
|
|
13
|
+
isInactive: boolean;
|
|
14
|
+
}
|
|
11
15
|
export interface ChatFirstEmbedTarget {
|
|
12
16
|
url: string;
|
|
13
17
|
title?: string;
|
|
@@ -51,7 +55,7 @@ export interface ChatFirstAppRailProps {
|
|
|
51
55
|
onOpenAllApps?: () => void;
|
|
52
56
|
onCreateApp?: () => void;
|
|
53
57
|
createAppTrigger?: ReactNode;
|
|
54
|
-
renderIcon: (app: ChatFirstAppItem) => ReactNode;
|
|
58
|
+
renderIcon: (app: ChatFirstAppItem, options?: ChatFirstAppIconRenderOptions) => ReactNode;
|
|
55
59
|
copy?: ChatFirstCopy;
|
|
56
60
|
}
|
|
57
61
|
export interface ChatFirstBrowserPaneProps {
|
|
@@ -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: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { ...buttonProps, className: cn("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": "
|
|
30
|
+
((buttonProps) => (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { ...buttonProps, className: cn("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
|
}
|
|
@@ -2,12 +2,14 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { ContextMeterView } from "@agent-native/toolkit/context-ui";
|
|
3
3
|
import { lazy, Suspense, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { manifestConversationTokens, manifestSystemTokens, } from "../../shared/context-xray.js";
|
|
5
|
+
import { useT } from "../i18n.js";
|
|
5
6
|
import { useActionMutation, useActionQuery } from "../use-action.js";
|
|
6
7
|
import { resolveContextWindow } from "./format.js";
|
|
7
8
|
const ContextXRayPanel = lazy(() => import("./ContextXRayPanel.js").then((m) => ({
|
|
8
9
|
default: m.ContextXRayPanel,
|
|
9
10
|
})));
|
|
10
11
|
export function ContextMeter({ threadId, manifest: providedManifest, enabled = true, }) {
|
|
12
|
+
const t = useT();
|
|
11
13
|
const [open, setOpen] = useState(false);
|
|
12
14
|
const [optimistic, setOptimistic] = useState(new Map());
|
|
13
15
|
const currentThreadId = useRef(threadId);
|
|
@@ -61,5 +63,7 @@ export function ContextMeter({ threadId, manifest: providedManifest, enabled = t
|
|
|
61
63
|
...manifest,
|
|
62
64
|
systemTokens: manifestSystemTokens(manifest),
|
|
63
65
|
conversationTokens: manifestConversationTokens(manifest),
|
|
64
|
-
}, contextWindow: resolveContextWindow(manifest.model), open: open, onOpenChange: setOpen, children: open ? (_jsx(Suspense, { fallback: _jsx("div", { className: "flex h-52 items-center justify-center text-xs text-muted-foreground", children: "
|
|
66
|
+
}, contextWindow: resolveContextWindow(manifest.model), open: open, onOpenChange: setOpen, translate: t, children: open ? (_jsx(Suspense, { fallback: _jsx("div", { className: "flex h-52 items-center justify-center text-xs text-muted-foreground", children: t("agentChat.contextXray.loading", {
|
|
67
|
+
defaultValue: "Loading context view…",
|
|
68
|
+
}) }), children: _jsx(ContextXRayPanel, { manifest: manifest, optimistic: optimistic, onPin: (segmentId) => mutateStatus(segmentId, "pinned", "pin"), onEvict: (segmentId) => mutateStatus(segmentId, "evicted", "evict"), onRestore: (segmentId) => mutateStatus(segmentId, "active", "restore") }) })) : null }));
|
|
65
69
|
}
|
|
@@ -9,18 +9,18 @@ export function ContextXRayPanel({ manifest, optimistic, onPin, onEvict, onResto
|
|
|
9
9
|
...manifest,
|
|
10
10
|
systemTokens: manifestSystemTokens(manifest),
|
|
11
11
|
conversationTokens: manifestConversationTokens(manifest),
|
|
12
|
-
}, contextWindow: resolveContextWindow(manifest.model), optimistic: optimistic, onPin: onPin, onEvict: onEvict, onRestore: onRestore, titleLabel: t("contextXray.panelTitle", {
|
|
12
|
+
}, contextWindow: resolveContextWindow(manifest.model), optimistic: optimistic, onPin: onPin, onEvict: onEvict, onRestore: onRestore, translate: t, titleLabel: t("agentChat.contextXray.panelTitle", {
|
|
13
13
|
defaultValue: "Context X-Ray",
|
|
14
|
-
}), systemOrderedLabel: t("contextXray.systemOrdered", {
|
|
14
|
+
}), systemOrderedLabel: t("agentChat.contextXray.systemOrdered", {
|
|
15
15
|
defaultValue: "System · ordered, not evictable",
|
|
16
16
|
}), governanceLabels: {
|
|
17
|
-
required: t("contextXray.governance.required", {
|
|
17
|
+
required: t("agentChat.contextXray.governance.required", {
|
|
18
18
|
defaultValue: "Required",
|
|
19
19
|
}),
|
|
20
|
-
inherited: t("contextXray.governance.inherited", {
|
|
20
|
+
inherited: t("agentChat.contextXray.governance.inherited", {
|
|
21
21
|
defaultValue: "Inherited",
|
|
22
22
|
}),
|
|
23
|
-
user: t("contextXray.governance.user", {
|
|
23
|
+
user: t("agentChat.contextXray.governance.user", {
|
|
24
24
|
defaultValue: "Your context",
|
|
25
25
|
}),
|
|
26
26
|
} }));
|
|
@@ -18,5 +18,9 @@ export interface NormalizedChatError {
|
|
|
18
18
|
message: string;
|
|
19
19
|
details?: string;
|
|
20
20
|
}
|
|
21
|
+
type ErrorTranslate = (key: string, options?: Record<string, unknown>) => string;
|
|
22
|
+
/** Localize only Core's own normalized error copy; preserve provider details. */
|
|
23
|
+
export declare function localizeKnownChatErrorText(text: string, t: ErrorTranslate): string;
|
|
21
24
|
export declare function isProviderAuthenticationError(text: string, errorCode?: string): boolean;
|
|
22
25
|
export declare function normalizeChatError(errorMessage: string, errorCode?: string): NormalizedChatError;
|
|
26
|
+
export {};
|
|
@@ -16,6 +16,10 @@ export const BUILDER_SPACE_SETTINGS_URL = "https://builder.io/account/space?utm_
|
|
|
16
16
|
// error message. The chat renderer intercepts this href and renders a button
|
|
17
17
|
// that dispatches the `agent-native:new-chat` CustomEvent instead of navigating.
|
|
18
18
|
export const NEW_CHAT_ACTION_HREF = "agent-native:new-chat";
|
|
19
|
+
const OPEN_BUILDER_SPACE_SETTINGS_LABEL = "Open Builder space settings";
|
|
20
|
+
const START_NEW_CHAT_LABEL = "Start new chat";
|
|
21
|
+
const UPGRADE_AT_BUILDER_LABEL = "Upgrade at builder.io";
|
|
22
|
+
const BUILDER_AUTHENTICATION_ERROR = "Builder rejected the connected credentials. Reconnect Builder.io (free tier available) in Settings, then retry.";
|
|
19
23
|
function isSafeUpgradeUrl(url) {
|
|
20
24
|
try {
|
|
21
25
|
const parsed = new URL(url);
|
|
@@ -31,19 +35,103 @@ export function formatChatErrorText(errorMessage, upgradeUrl, errorCode) {
|
|
|
31
35
|
const normalized = normalizeChatError(errorMessage, errorCode);
|
|
32
36
|
if (errorCode === "gateway_not_enabled" ||
|
|
33
37
|
/space has not enabled the LLM gateway/i.test(normalized.message)) {
|
|
34
|
-
return `Error: ${normalized.message}\n\n[
|
|
38
|
+
return `Error: ${normalized.message}\n\n[${OPEN_BUILDER_SPACE_SETTINGS_LABEL}](${BUILDER_SPACE_SETTINGS_URL})`;
|
|
35
39
|
}
|
|
36
40
|
if (errorCode === "builder_gateway_error") {
|
|
37
|
-
return `Error: ${normalized.message}\n\n[
|
|
41
|
+
return `Error: ${normalized.message}\n\n[${START_NEW_CHAT_LABEL}](${NEW_CHAT_ACTION_HREF})`;
|
|
38
42
|
}
|
|
39
43
|
if (errorCode === "context_length_exceeded" ||
|
|
40
44
|
errorCode === "input_too_long") {
|
|
41
|
-
return `Error: ${normalized.message}\n\n[
|
|
45
|
+
return `Error: ${normalized.message}\n\n[${START_NEW_CHAT_LABEL}](${NEW_CHAT_ACTION_HREF})`;
|
|
42
46
|
}
|
|
43
47
|
if (!upgradeUrl || !isSafeUpgradeUrl(upgradeUrl)) {
|
|
44
48
|
return `Error: ${normalized.message}`;
|
|
45
49
|
}
|
|
46
|
-
return `Error: ${normalized.message}\n\n[
|
|
50
|
+
return `Error: ${normalized.message}\n\n[${UPGRADE_AT_BUILDER_LABEL}](${upgradeUrl})`;
|
|
51
|
+
}
|
|
52
|
+
const KNOWN_CHAT_ERROR_KEYS = new Map([
|
|
53
|
+
[
|
|
54
|
+
"No LLM provider is connected. Open this app's Manage agent > LLM, then connect Builder.io or add a provider key.",
|
|
55
|
+
"agentChat.errorMessages.noProviderConnected",
|
|
56
|
+
],
|
|
57
|
+
[
|
|
58
|
+
"The provider behind this model rejected the request. Pick a different model, then retry.",
|
|
59
|
+
"agentChat.errorMessages.builderModelUnauthorized",
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
BUILDER_AUTHENTICATION_ERROR,
|
|
63
|
+
"agentChat.errorMessages.builderAuthentication",
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
"This model can't use tools with the current settings. Switch models in Settings, then retry.",
|
|
67
|
+
"agentChat.errorMessages.providerConfiguration",
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
"The model provider is rate-limiting this chat right now. Wait a moment, then retry.",
|
|
71
|
+
"agentChat.errorMessages.providerRateLimit",
|
|
72
|
+
],
|
|
73
|
+
[
|
|
74
|
+
"The model provider rejected the saved API key. Update the key in Settings → Integrations → API keys, then retry.",
|
|
75
|
+
"agentChat.errorMessages.providerAuthentication",
|
|
76
|
+
],
|
|
77
|
+
[
|
|
78
|
+
"The model provider could not be reached. Check your connection and retry.",
|
|
79
|
+
"agentChat.errorMessages.providerNetwork",
|
|
80
|
+
],
|
|
81
|
+
[
|
|
82
|
+
"The agent connection was interrupted. Check your connection and retry.",
|
|
83
|
+
"agentChat.errorMessages.agentConnection",
|
|
84
|
+
],
|
|
85
|
+
[
|
|
86
|
+
"The model gateway returned no error details and the chat couldn't recover. Wait a moment and retry, or start a new chat if it keeps happening.",
|
|
87
|
+
"agentChat.errorMessages.gatewayNoDetails",
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
"The agent connection timed out before it could finish. You can continue from the partial work or retry.",
|
|
91
|
+
"agentChat.errorMessages.inactivityTimeout",
|
|
92
|
+
],
|
|
93
|
+
[
|
|
94
|
+
"A tool schema was invalid, so the model rejected the request before it started. The invalid tool can be skipped and the request retried.",
|
|
95
|
+
"agentChat.errorMessages.invalidToolSchema",
|
|
96
|
+
],
|
|
97
|
+
[
|
|
98
|
+
"The provider returned an HTML error page.",
|
|
99
|
+
"agentChat.errorMessages.providerHtml",
|
|
100
|
+
],
|
|
101
|
+
]);
|
|
102
|
+
const KNOWN_CHAT_ERROR_ACTION_KEYS = new Map([
|
|
103
|
+
[
|
|
104
|
+
"Open Builder space settings",
|
|
105
|
+
"agentChat.errorMessages.openBuilderSpaceSettings",
|
|
106
|
+
],
|
|
107
|
+
["Start new chat", "agentChat.errorMessages.startNewChat"],
|
|
108
|
+
["Upgrade at builder.io", "agentChat.errorMessages.upgradeAtBuilder"],
|
|
109
|
+
]);
|
|
110
|
+
/** Localize only Core's own normalized error copy; preserve provider details. */
|
|
111
|
+
export function localizeKnownChatErrorText(text, t) {
|
|
112
|
+
const newlineIndex = text.indexOf("\n");
|
|
113
|
+
const firstLine = newlineIndex >= 0 ? text.slice(0, newlineIndex) : text;
|
|
114
|
+
const suffix = newlineIndex >= 0 ? text.slice(newlineIndex) : "";
|
|
115
|
+
const hasPrefix = firstLine.startsWith("Error: ");
|
|
116
|
+
const message = hasPrefix ? firstLine.slice("Error: ".length) : firstLine;
|
|
117
|
+
const key = KNOWN_CHAT_ERROR_KEYS.get(message);
|
|
118
|
+
let localizedFirstLine = firstLine;
|
|
119
|
+
if (key) {
|
|
120
|
+
const translated = t(key, { defaultValue: message });
|
|
121
|
+
localizedFirstLine = hasPrefix
|
|
122
|
+
? t("agentChat.errorMessages.errorPrefix", {
|
|
123
|
+
defaultValue: "Error: {{message}}",
|
|
124
|
+
message: translated,
|
|
125
|
+
})
|
|
126
|
+
: translated;
|
|
127
|
+
}
|
|
128
|
+
const localizedSuffix = suffix.replace(/\[([^\]]+)]\(([^)]+)\)/g, (link, label, href) => {
|
|
129
|
+
const actionKey = KNOWN_CHAT_ERROR_ACTION_KEYS.get(label);
|
|
130
|
+
if (!actionKey)
|
|
131
|
+
return link;
|
|
132
|
+
return `[${t(actionKey, { defaultValue: label })}](${href})`;
|
|
133
|
+
});
|
|
134
|
+
return `${localizedFirstLine}${localizedSuffix}`;
|
|
47
135
|
}
|
|
48
136
|
function normalizeErrorCode(errorCode) {
|
|
49
137
|
return String(errorCode ?? "")
|
|
@@ -124,7 +212,7 @@ export function normalizeChatError(errorMessage, errorCode) {
|
|
|
124
212
|
}
|
|
125
213
|
if (code === "builder_auth_error") {
|
|
126
214
|
return {
|
|
127
|
-
message:
|
|
215
|
+
message: BUILDER_AUTHENTICATION_ERROR,
|
|
128
216
|
details: text,
|
|
129
217
|
};
|
|
130
218
|
}
|
package/dist/client/i18n.js
CHANGED
|
@@ -5,6 +5,7 @@ import { IconCheck, IconChevronDown, IconLanguage } from "@tabler/icons-react";
|
|
|
5
5
|
import i18next from "i18next";
|
|
6
6
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
7
7
|
import { I18nextProvider, initReactI18next, useTranslation, } from "react-i18next";
|
|
8
|
+
import { coreMessagesForLocale, englishAgentChatMessages, loadCoreMessagesForLocale, normalizeCoreMessageOverrides, } from "../localization/core-messages.js";
|
|
8
9
|
import defaultEnglishMessages from "../localization/default-messages.js";
|
|
9
10
|
import { DEFAULT_LOCALE, LOCALE_HYDRATION_GLOBAL, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, localeDirection, normalizeLocalizationPreference, resolveLocaleFromCandidates, resolveLocaleFromPreference, } from "../localization/shared.js";
|
|
10
11
|
import { injectedAgentNativeConfig } from "./app-config.js";
|
|
@@ -138,8 +139,7 @@ function resolveInitialState(args) {
|
|
|
138
139
|
}
|
|
139
140
|
function resolveSupportedLocales(args) {
|
|
140
141
|
const configured = injectedAgentNativeConfig().translations?.locales;
|
|
141
|
-
const candidates = configured ??
|
|
142
|
-
args.catalog?.supportedLocales ?? [args.sourceLocale];
|
|
142
|
+
const candidates = configured ?? args.catalog?.supportedLocales ?? SUPPORTED_LOCALES;
|
|
143
143
|
const supported = candidates.filter((locale) => SUPPORTED_LOCALES.includes(locale));
|
|
144
144
|
return [
|
|
145
145
|
args.sourceLocale,
|
|
@@ -160,16 +160,39 @@ function normalizeLoadedMessages(value) {
|
|
|
160
160
|
}
|
|
161
161
|
return value;
|
|
162
162
|
}
|
|
163
|
+
function mergeLocaleMessages(base, overrides) {
|
|
164
|
+
if (!overrides)
|
|
165
|
+
return base;
|
|
166
|
+
const merged = { ...base };
|
|
167
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
168
|
+
const current = merged[key];
|
|
169
|
+
if (current &&
|
|
170
|
+
value &&
|
|
171
|
+
typeof current === "object" &&
|
|
172
|
+
typeof value === "object" &&
|
|
173
|
+
!Array.isArray(current) &&
|
|
174
|
+
!Array.isArray(value)) {
|
|
175
|
+
merged[key] = mergeLocaleMessages(current, value);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
merged[key] = value;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return merged;
|
|
182
|
+
}
|
|
183
|
+
function composeLocaleMessages(coreMessages, appMessages) {
|
|
184
|
+
return mergeLocaleMessages(mergeLocaleMessages(defaultEnglishMessages, coreMessages), appMessages ? normalizeCoreMessageOverrides(appMessages) : null);
|
|
185
|
+
}
|
|
163
186
|
function createI18nInstance(args) {
|
|
164
187
|
const instance = i18next.createInstance();
|
|
165
188
|
const resources = {
|
|
166
189
|
[args.sourceLocale]: {
|
|
167
|
-
[args.namespace]: args.messages,
|
|
190
|
+
[args.namespace]: composeLocaleMessages(coreMessagesForLocale(args.sourceLocale), args.messages),
|
|
168
191
|
},
|
|
169
192
|
};
|
|
170
|
-
if (args.initialLocale !== args.sourceLocale
|
|
193
|
+
if (args.initialLocale !== args.sourceLocale) {
|
|
171
194
|
resources[args.initialLocale] = {
|
|
172
|
-
[args.namespace]: args.initialMessages,
|
|
195
|
+
[args.namespace]: composeLocaleMessages(coreMessagesForLocale(args.initialLocale), args.initialMessages),
|
|
173
196
|
};
|
|
174
197
|
}
|
|
175
198
|
void instance.use(initReactI18next).init({
|
|
@@ -202,24 +225,37 @@ export function AgentNativeI18nProvider({ children, catalog, initialLocale, init
|
|
|
202
225
|
const [locale, setLocale] = useState(initialState.locale);
|
|
203
226
|
const [loading, setLoading] = useState(false);
|
|
204
227
|
const i18nRef = useRef(null);
|
|
228
|
+
const appMessagesLoadedRef = useRef(null);
|
|
229
|
+
const appMessagesRef = useRef(null);
|
|
230
|
+
const coreMessagesLoadedRef = useRef(null);
|
|
205
231
|
if (!i18nRef.current) {
|
|
206
232
|
const preloadedMessages = normalizeLoadedMessages(hydration.locale === initialState.locale && hydration.messages
|
|
207
233
|
? hydration.messages
|
|
208
234
|
: initialMessages);
|
|
235
|
+
const resolvedSourceMessages = normalizeCoreMessageOverrides(hydration.locale === sourceLocale && hydration.messages
|
|
236
|
+
? hydration.messages
|
|
237
|
+
: sourceMessages);
|
|
209
238
|
i18nRef.current = createI18nInstance({
|
|
210
239
|
namespace,
|
|
211
240
|
sourceLocale,
|
|
212
|
-
messages:
|
|
213
|
-
? hydration.messages
|
|
214
|
-
: sourceMessages,
|
|
241
|
+
messages: resolvedSourceMessages,
|
|
215
242
|
initialLocale: initialState.locale,
|
|
216
243
|
initialMessages: preloadedMessages,
|
|
217
244
|
});
|
|
245
|
+
appMessagesRef.current = new Map([[sourceLocale, resolvedSourceMessages]]);
|
|
246
|
+
appMessagesLoadedRef.current = new Set([sourceLocale]);
|
|
247
|
+
if (initialState.locale !== sourceLocale && preloadedMessages) {
|
|
248
|
+
appMessagesRef.current.set(initialState.locale, normalizeCoreMessageOverrides(preloadedMessages));
|
|
249
|
+
appMessagesLoadedRef.current.add(initialState.locale);
|
|
250
|
+
}
|
|
251
|
+
coreMessagesLoadedRef.current = new Set([sourceLocale, initialState.locale].filter((candidate) => candidate === DEFAULT_LOCALE));
|
|
218
252
|
}
|
|
219
253
|
const i18n = i18nRef.current;
|
|
220
254
|
useEffect(() => {
|
|
221
255
|
if (i18n.hasResourceBundle(sourceLocale, namespace)) {
|
|
222
|
-
|
|
256
|
+
const normalizedSourceMessages = normalizeCoreMessageOverrides(sourceMessages);
|
|
257
|
+
appMessagesRef.current?.set(sourceLocale, normalizedSourceMessages);
|
|
258
|
+
i18n.addResourceBundle(sourceLocale, namespace, normalizedSourceMessages, true, true);
|
|
223
259
|
}
|
|
224
260
|
}, [i18n, namespace, sourceLocale, sourceMessages]);
|
|
225
261
|
useEffect(() => {
|
|
@@ -233,17 +269,37 @@ export function AgentNativeI18nProvider({ children, catalog, initialLocale, init
|
|
|
233
269
|
async function applyLocale() {
|
|
234
270
|
setLoading(true);
|
|
235
271
|
try {
|
|
236
|
-
|
|
237
|
-
|
|
272
|
+
const shouldLoadAppMessages = locale !== sourceLocale && !appMessagesLoadedRef.current?.has(locale);
|
|
273
|
+
const shouldLoadCoreMessages = !coreMessagesLoadedRef.current?.has(locale);
|
|
274
|
+
if (shouldLoadAppMessages || shouldLoadCoreMessages) {
|
|
238
275
|
const preloaded = hydration.locale === locale && hydration.messages
|
|
239
276
|
? hydration.messages
|
|
240
277
|
: initialLocale === locale && initialMessages
|
|
241
278
|
? initialMessages
|
|
242
279
|
: null;
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
280
|
+
const [coreMessages, loadedAppMessages] = await Promise.all([
|
|
281
|
+
shouldLoadCoreMessages
|
|
282
|
+
? loadCoreMessagesForLocale(locale)
|
|
283
|
+
: Promise.resolve({}),
|
|
284
|
+
shouldLoadAppMessages
|
|
285
|
+
? Promise.resolve(preloaded ?? loadMessages?.(locale))
|
|
286
|
+
: Promise.resolve(null),
|
|
287
|
+
]);
|
|
288
|
+
const existingMessages = normalizeLoadedMessages(i18n.getResourceBundle(locale, namespace));
|
|
289
|
+
const loadedMessages = normalizeLoadedMessages(loadedAppMessages);
|
|
290
|
+
if (loadedMessages) {
|
|
291
|
+
appMessagesRef.current?.set(locale, normalizeCoreMessageOverrides(loadedMessages));
|
|
292
|
+
}
|
|
293
|
+
const appMessages = appMessagesRef.current?.get(locale) ?? null;
|
|
294
|
+
const nextMessages = shouldLoadCoreMessages
|
|
295
|
+
? composeLocaleMessages(coreMessages, appMessages)
|
|
296
|
+
: mergeLocaleMessages(existingMessages ?? {}, appMessages);
|
|
297
|
+
i18n.addResourceBundle(locale, namespace, nextMessages, true, true);
|
|
298
|
+
if (shouldLoadCoreMessages) {
|
|
299
|
+
coreMessagesLoadedRef.current?.add(locale);
|
|
300
|
+
}
|
|
301
|
+
if (shouldLoadAppMessages) {
|
|
302
|
+
appMessagesLoadedRef.current?.add(locale);
|
|
247
303
|
}
|
|
248
304
|
}
|
|
249
305
|
if (!cancelled) {
|
|
@@ -369,6 +425,10 @@ export function useOptionalLocale() {
|
|
|
369
425
|
return useContext(LocaleContext);
|
|
370
426
|
}
|
|
371
427
|
const CORE_FALLBACK_MESSAGES = {
|
|
428
|
+
...Object.fromEntries(Object.entries(englishAgentChatMessages).map(([key, value]) => [
|
|
429
|
+
`agentChat.${key}`,
|
|
430
|
+
value,
|
|
431
|
+
])),
|
|
372
432
|
"runsTray.runs": "Runs",
|
|
373
433
|
"runsTray.agentRuns": "Agent runs",
|
|
374
434
|
"runsTray.activeRun_one": "{{count}} active run",
|
|
@@ -497,6 +557,12 @@ function fallbackMessage(key, options) {
|
|
|
497
557
|
? interpolateFallbackMessage(template, options)
|
|
498
558
|
: humanizeFallbackKey(key);
|
|
499
559
|
}
|
|
560
|
+
function preserveTranslatedUserValues(translated, options) {
|
|
561
|
+
const defaultValue = options?.defaultValue;
|
|
562
|
+
return typeof defaultValue === "string" && translated === defaultValue
|
|
563
|
+
? interpolateFallbackMessage(defaultValue, options)
|
|
564
|
+
: translated;
|
|
565
|
+
}
|
|
500
566
|
export function useT() {
|
|
501
567
|
const { i18n, t } = useTranslation();
|
|
502
568
|
const context = useContext(LocaleContext);
|
|
@@ -504,11 +570,11 @@ export function useT() {
|
|
|
504
570
|
return useCallback((key, options) => {
|
|
505
571
|
const translated = t(key, options);
|
|
506
572
|
if (translated !== key)
|
|
507
|
-
return translated;
|
|
573
|
+
return preserveTranslatedUserValues(translated, options);
|
|
508
574
|
const getFixedT = i18n.getFixedT;
|
|
509
575
|
const sourceFallback = getFixedT?.(sourceLocale)(key, options);
|
|
510
576
|
if (sourceFallback && sourceFallback !== key)
|
|
511
|
-
return sourceFallback;
|
|
577
|
+
return preserveTranslatedUserValues(sourceFallback, options);
|
|
512
578
|
return fallbackMessage(key, options);
|
|
513
579
|
}, [i18n, sourceLocale, t]);
|
|
514
580
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface InlineMarkdownProps {
|
|
3
|
+
content: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
linkClassName?: string;
|
|
6
|
+
codeClassName?: string;
|
|
7
|
+
inline?: boolean;
|
|
8
|
+
protectedSpans?: readonly InlineMarkdownProtectedSpan[];
|
|
9
|
+
renderProtectedSpan?: (span: InlineMarkdownProtectedSpan, children: ReactNode) => ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export interface InlineMarkdownProtectedSpan {
|
|
12
|
+
source: string;
|
|
13
|
+
label: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Render user-authored Markdown for compact text surfaces.
|
|
19
|
+
*
|
|
20
|
+
* This intentionally has no block-level Markdown elements: headings, lists,
|
|
21
|
+
* quotes, and raw HTML are either flattened to their text or omitted.
|
|
22
|
+
*/
|
|
23
|
+
export declare function InlineMarkdown({ content, className, linkClassName, codeClassName, inline, protectedSpans, renderProtectedSpan, }: InlineMarkdownProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import ReactMarkdown, { defaultUrlTransform, } from "react-markdown";
|
|
3
|
+
import remarkGfm from "remark-gfm";
|
|
4
|
+
import { cn } from "../utils.js";
|
|
5
|
+
const INLINE_MARKDOWN_ELEMENTS = [
|
|
6
|
+
"a",
|
|
7
|
+
"br",
|
|
8
|
+
"code",
|
|
9
|
+
"del",
|
|
10
|
+
"em",
|
|
11
|
+
"p",
|
|
12
|
+
"s",
|
|
13
|
+
"strong",
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Render user-authored Markdown for compact text surfaces.
|
|
17
|
+
*
|
|
18
|
+
* This intentionally has no block-level Markdown elements: headings, lists,
|
|
19
|
+
* quotes, and raw HTML are either flattened to their text or omitted.
|
|
20
|
+
*/
|
|
21
|
+
export function InlineMarkdown({ content, className, linkClassName, codeClassName, inline = false, protectedSpans = [], renderProtectedSpan, }) {
|
|
22
|
+
const protectedSpanByHref = new Map(protectedSpans
|
|
23
|
+
.map((span, index) => [`${PROTECTED_SPAN_PREFIX}${index}`, span])
|
|
24
|
+
.filter(([, span]) => span.source.length > 0));
|
|
25
|
+
const renderedContent = protectInlineMarkdownSpans(content, protectedSpans);
|
|
26
|
+
const components = {
|
|
27
|
+
a: ({ children, href }) => {
|
|
28
|
+
const protectedSpan = href ? protectedSpanByHref.get(href) : undefined;
|
|
29
|
+
if (protectedSpan) {
|
|
30
|
+
return renderProtectedSpan ? (renderProtectedSpan(protectedSpan, children)) : (_jsx("span", { className: protectedSpan.className, title: protectedSpan.title, children: children }));
|
|
31
|
+
}
|
|
32
|
+
const safeHref = href
|
|
33
|
+
? defaultUrlTransform(normalizeInlineMarkdownHref(href))
|
|
34
|
+
: "";
|
|
35
|
+
if (!safeHref)
|
|
36
|
+
return _jsx(_Fragment, { children: children });
|
|
37
|
+
return (_jsx("a", { href: safeHref, target: "_blank", rel: "noopener noreferrer", className: cn("text-primary underline-offset-2 hover:underline", linkClassName), children: children }));
|
|
38
|
+
},
|
|
39
|
+
code: ({ children, className: syntaxClassName }) => (_jsx("code", { className: cn("rounded bg-muted px-1 py-0.5 font-mono text-[0.9em]", syntaxClassName, codeClassName), children: children })),
|
|
40
|
+
p: ({ children }) => inline ? _jsx("span", { children: children }) : _jsx("p", { className: "m-0", children: children }),
|
|
41
|
+
};
|
|
42
|
+
const Root = inline ? "span" : "div";
|
|
43
|
+
return (_jsx(Root, { className: cn("whitespace-pre-wrap break-words", className), children: _jsx(ReactMarkdown, { allowedElements: INLINE_MARKDOWN_ELEMENTS, components: components, remarkPlugins: [remarkGfm], skipHtml: true, unwrapDisallowed: true, children: renderedContent }) }));
|
|
44
|
+
}
|
|
45
|
+
const PROTECTED_SPAN_PREFIX = "https://inline-markdown-protected.invalid/span/";
|
|
46
|
+
function protectInlineMarkdownSpans(content, spans) {
|
|
47
|
+
return [...spans]
|
|
48
|
+
.map((span, index) => ({ span, index }))
|
|
49
|
+
.filter(({ span }) => span.source.length > 0)
|
|
50
|
+
.sort((a, b) => b.span.source.length - a.span.source.length)
|
|
51
|
+
.reduce((markdown, { span, index }) => markdown
|
|
52
|
+
.split(span.source)
|
|
53
|
+
.join(`[${escapeProtectedSpanLabel(span.label)}](${PROTECTED_SPAN_PREFIX}${index})`), content);
|
|
54
|
+
}
|
|
55
|
+
function escapeProtectedSpanLabel(label) {
|
|
56
|
+
return label.replace(/[\\[\]]/g, "\\$&");
|
|
57
|
+
}
|
|
58
|
+
function normalizeInlineMarkdownHref(href) {
|
|
59
|
+
if (/^www\./i.test(href))
|
|
60
|
+
return `https://${href}`;
|
|
61
|
+
if (/^http:\/\/www\./i.test(href)) {
|
|
62
|
+
return `https://${href.slice("http://".length)}`;
|
|
63
|
+
}
|
|
64
|
+
return href;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InlineMarkdown, type InlineMarkdownProtectedSpan, type InlineMarkdownProps, } from "./InlineMarkdown.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InlineMarkdown, } from "./InlineMarkdown.js";
|
|
@@ -3,14 +3,16 @@ import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
|
3
3
|
import { IconThumbUp, IconThumbDown } from "@tabler/icons-react";
|
|
4
4
|
import { useState, useCallback } from "react";
|
|
5
5
|
import { agentNativePath } from "../api-path.js";
|
|
6
|
+
import { useT } from "../i18n.js";
|
|
6
7
|
import { cn } from "../utils.js";
|
|
7
8
|
const THUMBS_DOWN_CATEGORIES = [
|
|
8
|
-
"Inaccurate",
|
|
9
|
-
"Not helpful",
|
|
10
|
-
"Wrong tool",
|
|
11
|
-
"Too slow",
|
|
9
|
+
{ value: "Inaccurate", key: "agentChat.feedback.inaccurate" },
|
|
10
|
+
{ value: "Not helpful", key: "agentChat.feedback.notHelpful" },
|
|
11
|
+
{ value: "Wrong tool", key: "agentChat.feedback.wrongTool" },
|
|
12
|
+
{ value: "Too slow", key: "agentChat.feedback.tooSlow" },
|
|
12
13
|
];
|
|
13
14
|
export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
15
|
+
const t = useT();
|
|
14
16
|
const [selection, setSelection] = useState(null);
|
|
15
17
|
const [categoryOpen, setCategoryOpen] = useState(false);
|
|
16
18
|
const [submittedCategory, setSubmittedCategory] = useState(null);
|
|
@@ -54,11 +56,11 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
54
56
|
setCategoryOpen(false);
|
|
55
57
|
sendFeedback("category", category);
|
|
56
58
|
}, [sendFeedback]);
|
|
57
|
-
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("button", { type: "button", "aria-label": "
|
|
59
|
+
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsUp"), onClick: handleThumbsUp, className: cn("flex h-6 w-6 items-center justify-center rounded", selection === "up"
|
|
58
60
|
? "text-foreground"
|
|
59
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) }), _jsxs(PopoverPrimitive.Root, { open: categoryOpen, onOpenChange: setCategoryOpen, children: [_jsx(PopoverPrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "
|
|
61
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) }), _jsxs(PopoverPrimitive.Root, { open: categoryOpen, onOpenChange: setCategoryOpen, children: [_jsx(PopoverPrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsDown"), onClick: handleThumbsDown, className: cn("flex h-6 w-6 items-center justify-center rounded", selection === "down"
|
|
60
62
|
? "text-foreground"
|
|
61
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8, className: "z-[300] overflow-hidden rounded-lg border border-border bg-popover p-1 shadow-lg outline-none", children: _jsx("div", { className: "flex flex-col gap-0.5", children: THUMBS_DOWN_CATEGORIES.map((category) => (_jsx("button", { type: "button", onClick: () => handleCategory(category), className: cn("rounded-md px-3 py-1.5 text-
|
|
63
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8, className: "z-[300] overflow-hidden rounded-lg border border-border bg-popover p-1 shadow-lg outline-none", children: _jsx("div", { className: "flex flex-col gap-0.5", children: THUMBS_DOWN_CATEGORIES.map((category) => (_jsx("button", { type: "button", onClick: () => handleCategory(category.value), className: cn("rounded-md px-3 py-1.5 text-start text-xs", submittedCategory === category.value
|
|
62
64
|
? "bg-accent text-foreground font-medium"
|
|
63
|
-
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), children: category }, category))) }) }) })] })] }));
|
|
65
|
+
: "text-muted-foreground hover:bg-accent/50 hover:text-foreground"), children: t(category.key) }, category.value))) }) }) })] })] }));
|
|
64
66
|
}
|