@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
|
@@ -14,6 +14,8 @@ import { writeClipboardText } from "../clipboard.js";
|
|
|
14
14
|
import { Dialog, DialogClose, DialogContent, DialogTitle, } from "../components/ui/dialog.js";
|
|
15
15
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "../components/ui/dropdown-menu.js";
|
|
16
16
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
17
|
+
import { localizeKnownChatErrorText } from "../error-format.js";
|
|
18
|
+
import { DEFAULT_LOCALE, useFormatters, useOptionalLocale, useT, } from "../i18n.js";
|
|
17
19
|
import { ThumbsFeedback } from "../observability/ThumbsFeedback.js";
|
|
18
20
|
import { McpConnectionSuggestion } from "../resources/McpConnectionSuggestion.js";
|
|
19
21
|
import { isCallAgentToolCallShadowed, isToolCallActive, shadowedCallAgentToolCallIds, } from "../tool-display.js";
|
|
@@ -21,7 +23,7 @@ import { cn } from "../utils.js";
|
|
|
21
23
|
import { MarkdownText, renderMarkdownToClipboardHtml, SmoothMarkdownText, } from "./markdown-renderer.js";
|
|
22
24
|
import { getAssistantRunDurationMs } from "./repo-helpers.js";
|
|
23
25
|
import { getRunErrorMetadata, runErrorHeadline, runErrorKey, } from "./run-recovery.js";
|
|
24
|
-
import { ToolCallFallback, ToolActivityPresentation, ToolCallStackMotion, FilesChangedSummary, ASSISTANT_VISIBLE_TOOL_CALL_LIMIT, ChatRunningContext, ChatRunningRunIdContext, ChatRunningTurnIdContext, ChatRunDurationContext,
|
|
26
|
+
import { ToolCallFallback, ToolActivityPresentation, ToolCallStackMotion, FilesChangedSummary, ASSISTANT_VISIBLE_TOOL_CALL_LIMIT, ChatRunningContext, ChatRunningRunIdContext, ChatRunningTurnIdContext, ChatRunDurationContext, ReasoningCell, useLocalizedWorkedDuration, WorkedForSummary, toolCallHasPendingApproval, } from "./tool-call-display.js";
|
|
25
27
|
export { toolCallHasPendingApproval };
|
|
26
28
|
// ─── Pending selection context key ───────────────────────────────────────────
|
|
27
29
|
// Mirrored from AssistantChat to avoid a cross-import on a private constant.
|
|
@@ -29,7 +31,7 @@ const PENDING_SELECTION_KEY = "pending-selection-context";
|
|
|
29
31
|
// ─── displayableUserMessageText ───────────────────────────────────────────────
|
|
30
32
|
export function displayableUserMessageText(text) {
|
|
31
33
|
return text
|
|
32
|
-
.replace(/<context\b[^>]*>[\s\S]*?<\/context>\n?/gi, "")
|
|
34
|
+
.replace(/<context\b[^>]*>[\s\S]*?<\/context>\n?/gi, "") // i18n-ignore -- parsing regex, not UI copy.
|
|
33
35
|
.replace(/<context\b[^>]*>[\s\S]*$/gi, "")
|
|
34
36
|
.replace(/<\/context>/gi, "")
|
|
35
37
|
.trim();
|
|
@@ -56,14 +58,14 @@ function isSameCalendarDay(a, b) {
|
|
|
56
58
|
a.getMonth() === b.getMonth() &&
|
|
57
59
|
a.getDate() === b.getDate());
|
|
58
60
|
}
|
|
59
|
-
export function formatMessageTimestamp(value) {
|
|
61
|
+
export function formatMessageTimestamp(value, locale, yesterdayLabel = "Yesterday") {
|
|
60
62
|
const date = coerceMessageDate(value);
|
|
61
63
|
if (!date)
|
|
62
64
|
return null;
|
|
63
65
|
const now = new Date();
|
|
64
66
|
const yesterday = new Date(now);
|
|
65
67
|
yesterday.setDate(now.getDate() - 1);
|
|
66
|
-
const time = new Intl.DateTimeFormat(
|
|
68
|
+
const time = new Intl.DateTimeFormat(locale, {
|
|
67
69
|
hour: "numeric",
|
|
68
70
|
minute: "2-digit",
|
|
69
71
|
}).format(date);
|
|
@@ -72,16 +74,16 @@ export function formatMessageTimestamp(value) {
|
|
|
72
74
|
short = time;
|
|
73
75
|
}
|
|
74
76
|
else if (isSameCalendarDay(date, yesterday)) {
|
|
75
|
-
short =
|
|
77
|
+
short = `${yesterdayLabel} ${time}`;
|
|
76
78
|
}
|
|
77
79
|
else if (date.getFullYear() === now.getFullYear()) {
|
|
78
|
-
short = `${new Intl.DateTimeFormat(
|
|
80
|
+
short = `${new Intl.DateTimeFormat(locale, {
|
|
79
81
|
month: "short",
|
|
80
82
|
day: "numeric",
|
|
81
83
|
}).format(date)}, ${time}`;
|
|
82
84
|
}
|
|
83
85
|
else {
|
|
84
|
-
short = `${new Intl.DateTimeFormat(
|
|
86
|
+
short = `${new Intl.DateTimeFormat(locale, {
|
|
85
87
|
month: "short",
|
|
86
88
|
day: "numeric",
|
|
87
89
|
year: "numeric",
|
|
@@ -89,7 +91,7 @@ export function formatMessageTimestamp(value) {
|
|
|
89
91
|
}
|
|
90
92
|
return {
|
|
91
93
|
short,
|
|
92
|
-
full: new Intl.DateTimeFormat(
|
|
94
|
+
full: new Intl.DateTimeFormat(locale, {
|
|
93
95
|
weekday: "short",
|
|
94
96
|
month: "short",
|
|
95
97
|
day: "numeric",
|
|
@@ -104,6 +106,8 @@ export function MessageTimestamp({ timestamp, className, }) {
|
|
|
104
106
|
}
|
|
105
107
|
// ─── SelectionAttachedPill ────────────────────────────────────────────────────
|
|
106
108
|
export function SelectionAttachedPill() {
|
|
109
|
+
const t = useT();
|
|
110
|
+
const { formatNumber } = useFormatters();
|
|
107
111
|
const [length, setLength] = useState(null);
|
|
108
112
|
useEffect(() => {
|
|
109
113
|
let cancelled = false;
|
|
@@ -140,7 +144,10 @@ export function SelectionAttachedPill() {
|
|
|
140
144
|
}, []);
|
|
141
145
|
if (length === null || length === 0)
|
|
142
146
|
return null;
|
|
143
|
-
return (_jsx("div", { className: "agent-selection-attached-pill shrink-0 px-3 pt-1.5 -mb-1", children: _jsxs("div", { className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-muted/50 px-2 py-0.5 text-[11px] text-muted-foreground", children: [_jsx(IconQuote, { size: 11 }),
|
|
147
|
+
return (_jsx("div", { className: "agent-selection-attached-pill shrink-0 px-3 pt-1.5 -mb-1", children: _jsxs("div", { className: "inline-flex items-center gap-1.5 rounded-full border border-border bg-muted/50 px-2 py-0.5 text-[11px] text-muted-foreground", children: [_jsx(IconQuote, { size: 11 }), _jsx("span", { children: t("agentChat.selection.attached", {
|
|
148
|
+
count: length,
|
|
149
|
+
formattedCount: formatNumber(length),
|
|
150
|
+
}) }), _jsx("button", { type: "button", "aria-label": t("agentChat.selection.clear"), onClick: () => {
|
|
144
151
|
setLength(null);
|
|
145
152
|
// Dispatch clear event; AssistantChat owns the DELETE call.
|
|
146
153
|
window.dispatchEvent(new CustomEvent("agent-panel:selection-clear-requested"));
|
|
@@ -193,7 +200,8 @@ export function resolveAssistantRequestId(message, activeRun, threadId) {
|
|
|
193
200
|
}
|
|
194
201
|
// ─── MessageBranchPicker ──────────────────────────────────────────────────────
|
|
195
202
|
export function MessageBranchPicker() {
|
|
196
|
-
|
|
203
|
+
const t = useT();
|
|
204
|
+
return (_jsxs(BranchPickerPrimitive.Root, { hideWhenSingleBranch: true, className: "flex items-center gap-0.5 text-[11px] text-muted-foreground", children: [_jsx(BranchPickerPrimitive.Previous, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.message.previousBranch"), className: "flex h-6 w-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 transition-colors duration-150 hover:bg-accent hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40", children: _jsx(IconChevronLeft, { className: "h-3.5 w-3.5" }) }) }), _jsxs("span", { className: "tabular-nums select-none", children: [_jsx(BranchPickerPrimitive.Number, {}), "/", _jsx(BranchPickerPrimitive.Count, {})] }), _jsx(BranchPickerPrimitive.Next, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.message.nextBranch"), className: "flex h-6 w-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 transition-colors duration-150 hover:bg-accent hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40", children: _jsx(IconChevronRight, { className: "h-3.5 w-3.5" }) }) })] }));
|
|
197
205
|
}
|
|
198
206
|
// ─── Mention rendering ────────────────────────────────────────────────────────
|
|
199
207
|
const mentionIconProps = {
|
|
@@ -299,23 +307,27 @@ function UserMessageAttachments() {
|
|
|
299
307
|
}) }));
|
|
300
308
|
}
|
|
301
309
|
export function ChatImageAttachmentPreview({ src, alt, }) {
|
|
310
|
+
const t = useT();
|
|
302
311
|
const [open, setOpen] = useState(false);
|
|
303
|
-
return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "aria-label":
|
|
312
|
+
return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "aria-label": t("agentChat.composer.previewAttachment", { name: alt }), title: alt, onClick: () => setOpen(true), className: "h-16 w-16 cursor-zoom-in overflow-hidden rounded-lg border border-border/70 bg-muted/50 p-0 transition-[border-color,box-shadow] hover:border-foreground/40 hover:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx("img", { src: src, alt: alt, className: "h-full w-full object-cover" }) }), _jsx(Dialog, { open: open, onOpenChange: setOpen, children: _jsxs(DialogContent, { hideClose: true, "aria-describedby": undefined, className: "fixed inset-0 left-0 top-0 flex h-screen max-h-none w-screen max-w-none translate-x-0 translate-y-0 items-center justify-center gap-0 overflow-hidden rounded-none border-0 bg-foreground/90 p-0 text-background shadow-none backdrop-blur-sm dark:bg-background/95 dark:text-foreground", onOpenAutoFocus: (event) => event.preventDefault(), children: [_jsx(DialogTitle, { className: "sr-only", children: alt || t("agentChat.composer.imagePreview") }), _jsx("div", { className: "flex h-full w-full items-center justify-center overflow-auto p-6", onClick: (event) => {
|
|
304
313
|
if (event.target === event.currentTarget)
|
|
305
314
|
setOpen(false);
|
|
306
|
-
}, children: _jsx("img", { src: src, alt: alt, draggable: false, className: "max-h-[90vh] max-w-[92vw] rounded-lg object-contain shadow-2xl" }) }), _jsx(DialogClose, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "
|
|
315
|
+
}, children: _jsx("img", { src: src, alt: alt, draggable: false, className: "max-h-[90vh] max-w-[92vw] rounded-lg object-contain shadow-2xl" }) }), _jsx(DialogClose, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.composer.closePreview"), className: "absolute end-4 top-4 inline-flex size-9 items-center justify-center rounded-full border border-background/25 bg-background/10 text-background transition-colors hover:bg-background/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-foreground/25 dark:bg-foreground/10 dark:text-foreground dark:hover:bg-foreground/20", children: _jsx(IconX, { className: "size-4" }) }) })] }) })] }));
|
|
307
316
|
}
|
|
308
317
|
// ─── UserMessageEditComposer ──────────────────────────────────────────────────
|
|
309
318
|
function UserMessageEditComposer() {
|
|
310
|
-
|
|
319
|
+
const t = useT();
|
|
320
|
+
return (_jsxs(ComposerPrimitive.Root, { className: "flex flex-col gap-2 rounded-lg border border-border bg-background px-3 py-2 shadow-sm", children: [_jsx(ComposerPrimitive.Input, { className: "w-full resize-none bg-transparent text-sm leading-relaxed text-foreground placeholder:text-muted-foreground focus:outline-none", rows: 1, submitMode: "enter" }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(ComposerPrimitive.Cancel, { asChild: true, children: _jsx("button", { type: "button", className: "cursor-pointer rounded-md px-2 py-1 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground", children: t("agentChat.common.cancel") }) }), _jsx(ComposerPrimitive.Send, { asChild: true, children: _jsx("button", { type: "submit", className: "cursor-pointer rounded-md bg-foreground px-2 py-1 text-xs font-medium text-background hover:opacity-90 disabled:opacity-50", children: t("agentChat.common.save") }) })] })] }));
|
|
311
321
|
}
|
|
312
322
|
// ─── MessageActionsMenu ────────────────────────────────────────────────────────
|
|
313
323
|
export function MessageActionsMenu({ showRevert, onRevert, threadId = "", } = {}) {
|
|
324
|
+
const t = useT();
|
|
325
|
+
const locale = useOptionalLocale()?.locale ?? DEFAULT_LOCALE;
|
|
314
326
|
const [open, setOpen] = useState(false);
|
|
315
327
|
const [copied, setCopied] = useState(null);
|
|
316
328
|
const messageRuntime = useMessageRuntime();
|
|
317
329
|
const actionsCtx = React.useContext(MessageActionsContext);
|
|
318
|
-
const timestamp = formatMessageTimestamp(messageRuntime.getState().createdAt);
|
|
330
|
+
const timestamp = formatMessageTimestamp(messageRuntime.getState().createdAt, locale, t("agentChat.history.yesterday"));
|
|
319
331
|
const handleCopyMessage = useCallback(() => {
|
|
320
332
|
const m = messageRuntime.getState();
|
|
321
333
|
const text = m.content
|
|
@@ -362,28 +374,32 @@ export function MessageActionsMenu({ showRevert, onRevert, threadId = "", } = {}
|
|
|
362
374
|
setOpen(false);
|
|
363
375
|
onRevert?.();
|
|
364
376
|
}, [onRevert]);
|
|
365
|
-
return (_jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { "aria-label": "
|
|
377
|
+
return (_jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { "aria-label": t("agentChat.message.actions"), className: cn("flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 transition-colors duration-150 hover:bg-accent hover:text-foreground", open && "bg-accent text-foreground"), children: _jsx(IconDots, { className: "h-3.5 w-3.5" }) }) }), _jsxs(DropdownMenuContent, { align: "start", sideOffset: 6, className: "w-48 rounded-lg border-border p-1.5 shadow-xl", children: [actionsCtx?.onForkChat && (_jsxs(DropdownMenuItem, { onSelect: handleForkChat, children: [_jsx(IconGitFork, { className: "h-3.5 w-3.5" }), t("agentChat.message.forkChat")] })), _jsxs(DropdownMenuItem, { onSelect: (e) => {
|
|
366
378
|
e.preventDefault();
|
|
367
379
|
handleCopyMessage();
|
|
368
|
-
}, children: [copied === "message" ? (_jsx(IconCheck, { className: "h-3.5 w-3.5" })) : (_jsx(IconCopy, { className: "h-3.5 w-3.5" })), copied === "message"
|
|
380
|
+
}, children: [copied === "message" ? (_jsx(IconCheck, { className: "h-3.5 w-3.5" })) : (_jsx(IconCopy, { className: "h-3.5 w-3.5" })), copied === "message"
|
|
381
|
+
? t("agentChat.common.copied")
|
|
382
|
+
: t("agentChat.message.copyMessage")] }), _jsxs(DropdownMenuItem, { onSelect: (e) => {
|
|
369
383
|
e.preventDefault();
|
|
370
384
|
handleCopyRequestId();
|
|
371
385
|
}, children: [copied === "id" ? (_jsx(IconCheck, { className: "h-3.5 w-3.5" })) : (_jsx(IconId, { className: "h-3.5 w-3.5" })), copied === "id"
|
|
372
|
-
? "
|
|
386
|
+
? t("agentChat.common.copied")
|
|
373
387
|
: copied === "id-unavailable"
|
|
374
|
-
? "
|
|
388
|
+
? t("agentChat.message.requestIdUnavailable")
|
|
375
389
|
: copied === "id-failed"
|
|
376
|
-
? "
|
|
377
|
-
: "
|
|
390
|
+
? t("agentChat.recovery.copyFailed")
|
|
391
|
+
: t("agentChat.message.copyRequestId")] }), showRevert && (_jsxs(DropdownMenuItem, { onSelect: handleRevert, children: [_jsx(IconArrowBackUp, { className: "h-3.5 w-3.5" }), t("agentChat.message.revertHere")] })), timestamp && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { className: "px-2 py-1 text-[11px] font-normal text-muted-foreground", children: t("agentChat.message.sentAt", { time: timestamp.short }) })] }))] })] }));
|
|
378
392
|
}
|
|
379
393
|
// ─── UserMessage ──────────────────────────────────────────────────────────────
|
|
380
394
|
export function UserMessage() {
|
|
395
|
+
const t = useT();
|
|
396
|
+
const locale = useOptionalLocale()?.locale ?? DEFAULT_LOCALE;
|
|
381
397
|
const [expanded, setExpanded] = useState(false);
|
|
382
398
|
const [isExpandable, setIsExpandable] = useState(false);
|
|
383
399
|
const contentRef = useRef(null);
|
|
384
400
|
const messageRuntime = useMessageRuntime();
|
|
385
401
|
const message = messageRuntime.getState();
|
|
386
|
-
const timestamp = formatMessageTimestamp(message.createdAt);
|
|
402
|
+
const timestamp = formatMessageTimestamp(message.createdAt, locale, t("agentChat.history.yesterday"));
|
|
387
403
|
const isEditing = useComposer((state) => state.isEditing);
|
|
388
404
|
const chatRunning = React.useContext(ChatRunningContext);
|
|
389
405
|
const hidden = isHiddenUserMessage(message);
|
|
@@ -429,7 +445,9 @@ export function UserMessage() {
|
|
|
429
445
|
e.clipboardData.setData("text/plain", div.textContent || "");
|
|
430
446
|
}, children: [_jsx("div", { ref: contentRef, className: cn("whitespace-pre-wrap break-words", !expanded && isExpandable && "max-h-[200px] overflow-hidden"), children: _jsx(MessagePrimitive.Parts, { components: {
|
|
431
447
|
Text: UserMessageText,
|
|
432
|
-
} }) }), !expanded && isExpandable && (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-lg bg-gradient-to-t from-accent via-accent/90 to-transparent" })), !chatRunning && hasDisplayableText && (_jsx(TooltipProvider, { delayDuration: 400, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(ActionBarPrimitive.Edit, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "
|
|
448
|
+
} }) }), !expanded && isExpandable && (_jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-14 rounded-b-lg bg-gradient-to-t from-accent via-accent/90 to-transparent" })), !chatRunning && hasDisplayableText && (_jsx(TooltipProvider, { delayDuration: 400, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(ActionBarPrimitive.Edit, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.message.edit"), className: "absolute -left-8 top-1 flex h-6 w-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground/0 transition-colors duration-150 group-hover:text-muted-foreground/70 group-hover:hover:bg-accent group-hover:hover:text-foreground", children: _jsx(IconPencil, { className: "h-3.5 w-3.5" }) }) }) }), _jsx(TooltipContent, { side: "left", className: "text-xs", children: t("agentChat.message.edit") })] }) }))] })), hasDisplayableText && isExpandable && (_jsxs("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 transition-transform", expanded && "rotate-180") }), expanded
|
|
449
|
+
? t("agentChat.common.collapse")
|
|
450
|
+
: t("agentChat.common.expand")] })), _jsxs("div", { className: "mt-1 flex items-center justify-end gap-1", children: [_jsx(MessageBranchPicker, {}), timestamp && (_jsx(MessageTimestamp, { timestamp: timestamp, className: messageFooterFadeClassName }))] })] }) }));
|
|
433
451
|
}
|
|
434
452
|
// ─── AssistantMessage ─────────────────────────────────────────────────────────
|
|
435
453
|
function assistantMessageHasRenderableContent(message) {
|
|
@@ -790,17 +808,27 @@ export function shouldShowInlineRunError({ runError, bannerRunErrorKey, }) {
|
|
|
790
808
|
return runErrorKey(runError) !== bannerRunErrorKey;
|
|
791
809
|
}
|
|
792
810
|
export function InlineRunErrorNotice({ info, durationMs, onRetry, }) {
|
|
811
|
+
const t = useT();
|
|
812
|
+
const formatDuration = useLocalizedWorkedDuration();
|
|
793
813
|
const [open, setOpen] = useState(false);
|
|
794
|
-
const headline = runErrorHeadline(info
|
|
814
|
+
const headline = runErrorHeadline(info, {
|
|
815
|
+
recoverable: t("agentChat.error.stopped"),
|
|
816
|
+
terminal: t("agentChat.error.failed"),
|
|
817
|
+
});
|
|
795
818
|
const label = durationMs != null && durationMs >= 1000
|
|
796
|
-
?
|
|
819
|
+
? t("agentChat.error.afterDuration", {
|
|
820
|
+
headline,
|
|
821
|
+
duration: formatDuration(durationMs),
|
|
822
|
+
})
|
|
797
823
|
: headline;
|
|
798
|
-
return (_jsxs("div", { className: "my-1 w-full", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, className: "flex cursor-pointer items-center gap-1.5 py-0.5 text-[13px] text-muted-foreground transition-colors hover:text-foreground", children: [_jsx(IconAlertTriangle, { className: "size-3.5 shrink-0 text-amber-500" }), _jsx("span", { className: "truncate", children: label }), _jsx(IconChevronRight, { className: cn("size-3.5 shrink-0 transition-transform", open && "rotate-90") })] }), open && (_jsxs("div", { className: "mt-1 rounded-md border border-border/60 bg-background/70 p-2 text-[11px] leading-relaxed text-muted-foreground", children: [_jsx("p", { className: "whitespace-pre-wrap break-words", children: info.message }), info.errorCode && (_jsxs("div", { className: "mt-1 font-mono", children: ["code: ", info.errorCode] })), info.runId && _jsxs("div", { className: "font-mono", children: ["run: ", info.runId] }), info.details && (_jsx("pre", { className: "mt-1 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details })), onRetry && (_jsxs("button", { type: "button", onClick: onRetry, className: "mt-2 inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { className: "size-3" }), "
|
|
824
|
+
return (_jsxs("div", { className: "my-1 w-full", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, className: "flex cursor-pointer items-center gap-1.5 py-0.5 text-[13px] text-muted-foreground transition-colors hover:text-foreground", children: [_jsx(IconAlertTriangle, { className: "size-3.5 shrink-0 text-amber-500" }), _jsx("span", { className: "truncate", children: label }), _jsx(IconChevronRight, { className: cn("size-3.5 shrink-0 transition-transform", open && "rotate-90") })] }), open && (_jsxs("div", { className: "mt-1 rounded-md border border-border/60 bg-background/70 p-2 text-[11px] leading-relaxed text-muted-foreground", children: [_jsx("p", { className: "whitespace-pre-wrap break-words", children: localizeKnownChatErrorText(info.message, t) }), info.errorCode && (_jsxs("div", { className: "mt-1 font-mono", children: ["code: ", info.errorCode] })), info.runId && _jsxs("div", { className: "font-mono", children: ["run: ", info.runId] }), info.details && (_jsx("pre", { className: "mt-1 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details })), onRetry && (_jsxs("button", { type: "button", onClick: onRetry, className: "mt-2 inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { className: "size-3" }), t("agentChat.common.retry")] }))] }))] }));
|
|
799
825
|
}
|
|
800
826
|
function MissingFinalResponseNotice({ messageId, text, animate, onRevealComplete, }) {
|
|
801
827
|
return (_jsx("div", { className: "my-1 w-full text-muted-foreground", role: "status", "aria-live": "polite", "data-testid": "missing-final-response", children: _jsx(SmoothMarkdownText, { text: text, streaming: animate, resetKey: `missing-final-response:${messageId}`, statusType: animate ? "running" : "complete", onRevealComplete: animate ? onRevealComplete : undefined }) }));
|
|
802
828
|
}
|
|
803
829
|
export function AssistantMessage() {
|
|
830
|
+
const t = useT();
|
|
831
|
+
const locale = useOptionalLocale()?.locale ?? DEFAULT_LOCALE;
|
|
804
832
|
const [restoreState, setRestoreState] = useState("idle");
|
|
805
833
|
const [restoreError, setRestoreError] = useState(null);
|
|
806
834
|
const messageRuntime = useMessageRuntime();
|
|
@@ -811,7 +839,7 @@ export function AssistantMessage() {
|
|
|
811
839
|
const lastRunDurationMs = React.useContext(ChatRunDurationContext);
|
|
812
840
|
const msg = messageRuntime.getState();
|
|
813
841
|
const persistedDurationMs = getAssistantRunDurationMs(msg);
|
|
814
|
-
const timestamp = formatMessageTimestamp(msg.createdAt);
|
|
842
|
+
const timestamp = formatMessageTimestamp(msg.createdAt, locale, t("agentChat.history.yesterday"));
|
|
815
843
|
const isLast = msg.isLast;
|
|
816
844
|
const wasLiveRef = useRef(false);
|
|
817
845
|
const messageRunId = assistantMessageRunId(msg);
|
|
@@ -848,12 +876,12 @@ export function AssistantMessage() {
|
|
|
848
876
|
const showMissingFinalResponse = useSettledFlag(missingFinalResponseCandidate, isLast ? MISSING_FINAL_RESPONSE_SETTLE_MS : 0);
|
|
849
877
|
const shouldShowUserStoppedNotice = isUserStoppedRun && isLast && responseConnectionText.trim().length === 0;
|
|
850
878
|
const missingFinalResponseNoticeText = shouldShowUserStoppedNotice
|
|
851
|
-
? "
|
|
879
|
+
? t("agentChat.error.stopped")
|
|
852
880
|
: isUserStoppedRun
|
|
853
881
|
? null
|
|
854
882
|
: (missingWarningText ??
|
|
855
883
|
(showMissingFinalResponse
|
|
856
|
-
? "
|
|
884
|
+
? t("agentChat.message.missingFinal")
|
|
857
885
|
: null));
|
|
858
886
|
const animateMissingFinalResponse = Boolean(isLast && missingFinalResponseNoticeText && wasLiveRef.current);
|
|
859
887
|
const missingFinalResponseAnimationKey = animateMissingFinalResponse
|
|
@@ -950,7 +978,7 @@ export function AssistantMessage() {
|
|
|
950
978
|
if (restoreState !== "confirming" || !cpCtx)
|
|
951
979
|
return;
|
|
952
980
|
if (!messageRunId) {
|
|
953
|
-
setRestoreError("
|
|
981
|
+
setRestoreError(t("agentChat.message.noRestoreRun"));
|
|
954
982
|
setRestoreState("error");
|
|
955
983
|
return;
|
|
956
984
|
}
|
|
@@ -968,14 +996,18 @@ export function AssistantMessage() {
|
|
|
968
996
|
const payload = (await restoreRes.json().catch(() => null));
|
|
969
997
|
setRestoreError(typeof payload?.error === "string"
|
|
970
998
|
? payload.error
|
|
971
|
-
:
|
|
999
|
+
: t("agentChat.message.restoreFailed", {
|
|
1000
|
+
status: restoreRes.status,
|
|
1001
|
+
}));
|
|
972
1002
|
setRestoreState("error");
|
|
973
1003
|
}
|
|
974
1004
|
catch (err) {
|
|
975
|
-
setRestoreError(err instanceof Error
|
|
1005
|
+
setRestoreError(err instanceof Error
|
|
1006
|
+
? err.message
|
|
1007
|
+
: t("agentChat.message.restoreRequestFailed"));
|
|
976
1008
|
setRestoreState("error");
|
|
977
1009
|
}
|
|
978
|
-
}, [restoreState, cpCtx, messageRunId]);
|
|
1010
|
+
}, [restoreState, cpCtx, messageRunId, t]);
|
|
979
1011
|
const cancelRestore = useCallback(() => {
|
|
980
1012
|
setRestoreError(null);
|
|
981
1013
|
setRestoreState("idle");
|
|
@@ -1050,12 +1082,14 @@ export function AssistantMessage() {
|
|
|
1050
1082
|
? messageActions?.onRetryRunError
|
|
1051
1083
|
: undefined })), missingWarningText == null &&
|
|
1052
1084
|
missingFinalResponseNoticeText != null &&
|
|
1053
|
-
!showInlineRunError && (_jsx(MissingFinalResponseNotice, { messageId: msg.id, text: missingFinalResponseNoticeText, animate: animateMissingFinalResponse, onRevealComplete: handleMissingFinalResponseReveal })), isComplete && hasCodeAgentTools && msgContent && (_jsx(FilesChangedSummary, { parts: msgContent }))] }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore, threadId: cpCtx?.threadId ?? "" }), isLast && (_jsx(TooltipProvider, { delayDuration: 400, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(ActionBarPrimitive.Reload, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "
|
|
1085
|
+
!showInlineRunError && (_jsx(MissingFinalResponseNotice, { messageId: msg.id, text: missingFinalResponseNoticeText, animate: animateMissingFinalResponse, onRevealComplete: handleMissingFinalResponseReveal })), isComplete && hasCodeAgentTools && msgContent && (_jsx(FilesChangedSummary, { parts: msgContent }))] }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore, threadId: cpCtx?.threadId ?? "" }), isLast && (_jsx(TooltipProvider, { delayDuration: 400, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(ActionBarPrimitive.Reload, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.message.regenerate"), className: `flex h-6 w-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground ${messageFooterFadeClassName} disabled:cursor-not-allowed disabled:opacity-40`, children: _jsx(IconRefresh, { className: "h-3.5 w-3.5" }) }) }) }), _jsx(TooltipContent, { side: "top", className: "text-xs", children: t("agentChat.message.regenerate") })] }) })), _jsx(MessageBranchPicker, {}), timestamp && (_jsx(MessageTimestamp, { timestamp: timestamp, className: messageFooterFadeClassName }))] }), showRestore && restoreState === "confirming" ? (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: t("agentChat.message.restoreQuestion") }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: t("agentChat.common.cancel") })] })) : showRestore && restoreState === "restoring" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), t("agentChat.message.restoring")] })) : restoreState === "error" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-destructive", children: [_jsx(IconAlertTriangle, { className: "h-3 w-3 shrink-0" }), _jsx("span", { className: "truncate", children: restoreError }), _jsx("button", { onClick: cancelRestore, className: "cursor-pointer rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: t("agentChat.common.dismiss") })] })) : (_jsx(ThumbsFeedback, { threadId: cpCtx?.threadId ?? "", runId: messageRunId ?? "", messageSeq: msg.index }))] }))] }));
|
|
1054
1086
|
}
|
|
1055
1087
|
// ─── RunningActivityStatus / ThinkingIndicator ────────────────────────────────
|
|
1056
1088
|
export function RunningActivityStatus({ label }) {
|
|
1057
1089
|
return (_jsx("div", { className: "agent-running-activity", children: _jsx(ThinkingIndicator, { label: label }) }));
|
|
1058
1090
|
}
|
|
1059
|
-
export function ThinkingIndicator({ label
|
|
1060
|
-
|
|
1091
|
+
export function ThinkingIndicator({ label } = {}) {
|
|
1092
|
+
const t = useT();
|
|
1093
|
+
const resolvedLabel = label ?? t("agentChat.status.thinking");
|
|
1094
|
+
return (_jsx("div", { className: "agent-thinking-indicator", role: "status", "aria-live": "polite", "aria-label": resolvedLabel, children: _jsx("span", { className: "agent-thinking-indicator__text", children: resolvedLabel }) }));
|
|
1061
1095
|
}
|
|
@@ -16,7 +16,10 @@ export declare function getRunErrorMetadata(message: unknown): RunErrorInfo | nu
|
|
|
16
16
|
* the same run is never announced twice.
|
|
17
17
|
*/
|
|
18
18
|
export declare function runErrorKey(info: RunErrorInfo): string;
|
|
19
|
-
export declare function runErrorHeadline(info: RunErrorInfo
|
|
19
|
+
export declare function runErrorHeadline(info: RunErrorInfo, labels?: {
|
|
20
|
+
recoverable: string;
|
|
21
|
+
terminal: string;
|
|
22
|
+
}): string;
|
|
20
23
|
export declare function getRequestModeMetadata(message: unknown): "act" | "plan" | null;
|
|
21
24
|
export declare function BuilderConnectCta({ variant, onConnected, }: {
|
|
22
25
|
variant?: "primary" | "compact";
|
|
@@ -7,8 +7,8 @@ import { IconLoader2, IconCheck, IconCopy, IconX, IconChevronDown, IconGitFork,
|
|
|
7
7
|
import { useState, useEffect, useCallback, useRef } from "react";
|
|
8
8
|
import { agentNativePath } from "../api-path.js";
|
|
9
9
|
import { writeClipboardText } from "../clipboard.js";
|
|
10
|
-
import { isProviderAuthenticationError } from "../error-format.js";
|
|
11
|
-
import { useT } from "../i18n.js";
|
|
10
|
+
import { isProviderAuthenticationError, localizeKnownChatErrorText, } from "../error-format.js";
|
|
11
|
+
import { useFormatters, useT } from "../i18n.js";
|
|
12
12
|
import { AgentProviderSetupForm } from "../settings/ProviderSetupForm.js";
|
|
13
13
|
import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
|
|
14
14
|
import { cn } from "../utils.js";
|
|
@@ -66,10 +66,11 @@ export function getRunErrorMetadata(message) {
|
|
|
66
66
|
export function runErrorKey(info) {
|
|
67
67
|
return `${info.runId ?? ""}:${info.errorCode ?? ""}:${info.message}`;
|
|
68
68
|
}
|
|
69
|
-
export function runErrorHeadline(info
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
export function runErrorHeadline(info, labels = {
|
|
70
|
+
recoverable: "The agent stopped before finishing",
|
|
71
|
+
terminal: "The agent hit an error",
|
|
72
|
+
}) {
|
|
73
|
+
return info.recoverable === true ? labels.recoverable : labels.terminal;
|
|
73
74
|
}
|
|
74
75
|
export function getRequestModeMetadata(message) {
|
|
75
76
|
const meta = message?.metadata;
|
|
@@ -123,21 +124,28 @@ function isConnectionRecoveryRunError(info) {
|
|
|
123
124
|
// which opens the flow in an Electron BrowserWindow that shares the webview's
|
|
124
125
|
// session. See packages/desktop-app/src/main/index.ts.
|
|
125
126
|
export function BuilderConnectCta({ variant = "primary", onConnected, }) {
|
|
127
|
+
const t = useT();
|
|
126
128
|
const { configured, orgName, connecting, error, start } = useBuilderConnectFlow({
|
|
127
129
|
trackingSource: "assistant_chat_builder_cta",
|
|
128
130
|
onConnected,
|
|
129
131
|
});
|
|
130
132
|
if (variant === "compact") {
|
|
131
133
|
if (configured) {
|
|
132
|
-
return (_jsxs("span", { className: "agent-builder-setup-card__builder-button inline-flex h-8 items-center gap-1.5 whitespace-nowrap rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground", children: [_jsx(IconCheck, { size: 11, className: "text-emerald-500" }), orgName
|
|
134
|
+
return (_jsxs("span", { className: "agent-builder-setup-card__builder-button inline-flex h-8 items-center gap-1.5 whitespace-nowrap rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground", children: [_jsx(IconCheck, { size: 11, className: "text-emerald-500" }), orgName
|
|
135
|
+
? t("agentChat.setup.connectedTo", { organization: orgName })
|
|
136
|
+
: t("agentChat.setup.connected")] }));
|
|
133
137
|
}
|
|
134
|
-
return (_jsxs("div", { className: "agent-builder-setup-card__builder-cta flex min-w-0 flex-col items-start gap-1 sm:items-end", children: [_jsx("button", { type: "button", onClick: () => start(), disabled: connecting, className: "agent-builder-setup-card__builder-button inline-flex h-8 shrink-0 items-center gap-1 whitespace-nowrap rounded-md bg-foreground px-3 text-[11px] font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-60", "aria-busy": connecting, children: connecting ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { size: 10, className: "animate-spin" }), "
|
|
138
|
+
return (_jsxs("div", { className: "agent-builder-setup-card__builder-cta flex min-w-0 flex-col items-start gap-1 sm:items-end", children: [_jsx("button", { type: "button", onClick: () => start(), disabled: connecting, className: "agent-builder-setup-card__builder-button inline-flex h-8 shrink-0 items-center gap-1 whitespace-nowrap rounded-md bg-foreground px-3 text-[11px] font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-60", "aria-busy": connecting, children: connecting ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { size: 10, className: "animate-spin" }), t("agentChat.common.waiting")] })) : (t("agentChat.setup.connectBuilder")) }), error && (_jsx("p", { className: "max-w-[13rem] text-[10px] leading-snug text-destructive sm:text-end", children: error }))] }));
|
|
135
139
|
}
|
|
136
140
|
const containerClass = "flex items-center gap-3 rounded-md border border-border px-3 py-3";
|
|
137
141
|
if (configured) {
|
|
138
|
-
return (_jsxs("div", { className: containerClass, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Builder.io" }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: orgName
|
|
142
|
+
return (_jsxs("div", { className: containerClass, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "Builder.io" }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: orgName
|
|
143
|
+
? t("agentChat.setup.connectedOrganization", {
|
|
144
|
+
organization: orgName,
|
|
145
|
+
})
|
|
146
|
+
: t("agentChat.setup.connected") })] }), _jsxs("span", { className: "ms-auto inline-flex items-center gap-1 shrink-0 rounded-md bg-emerald-500/10 px-2 py-0.5 text-[10px] font-medium text-emerald-500", children: [_jsx(IconCheck, { size: 10 }), t("agentChat.setup.connected")] })] }));
|
|
139
147
|
}
|
|
140
|
-
return (_jsxs("div", { className: containerClass, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: "
|
|
148
|
+
return (_jsxs("div", { className: containerClass, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-xs font-medium text-foreground", children: t("agentChat.setup.connectBuilder") }), _jsx("p", { className: "text-[11px] text-muted-foreground mt-0.5 max-w-[220px]", children: t("agentChat.setup.freeCredits") }), error && _jsx("p", { className: "mt-1 text-[10px] text-destructive", children: error })] }), _jsx("button", { type: "button", onClick: () => start(), disabled: connecting, className: "ms-auto inline-flex items-center gap-1 shrink-0 rounded-md bg-foreground px-3 py-1.5 text-[11px] font-medium no-underline text-background hover:opacity-90 disabled:opacity-60 disabled:cursor-wait", "aria-busy": connecting, children: connecting ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { size: 10, className: "animate-spin" }), t("agentChat.common.waiting")] })) : (t("agentChat.common.connect")) })] }));
|
|
141
149
|
}
|
|
142
150
|
// ─── ApiKeyConnect ────────────────────────────────────────────────────────────
|
|
143
151
|
export function ApiKeyConnect({ onConnected }) {
|
|
@@ -181,6 +189,7 @@ export function BuilderSetupCard({ onConnected, bouncePulse, fullWidth, layout =
|
|
|
181
189
|
}
|
|
182
190
|
// ─── RunErrorRecoveryCard ─────────────────────────────────────────────────────
|
|
183
191
|
export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, onProviderConnected, }) {
|
|
192
|
+
const t = useT();
|
|
184
193
|
const [detailsOpen, setDetailsOpen] = useState(false);
|
|
185
194
|
const [copyState, setCopyState] = useState("idle");
|
|
186
195
|
const [forking, setForking] = useState(false);
|
|
@@ -201,7 +210,9 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
201
210
|
builderReconnect.configured;
|
|
202
211
|
const isQueryError = isProviderQueryRunError(info);
|
|
203
212
|
const isConnectionRecoveryError = isConnectionRecoveryRunError(info);
|
|
204
|
-
const copyLabel = info.runId || info.errorCode || info.details
|
|
213
|
+
const copyLabel = info.runId || info.errorCode || info.details
|
|
214
|
+
? t("agentChat.recovery.copyDebug")
|
|
215
|
+
: t("agentChat.common.copy");
|
|
205
216
|
const copyDetails = useCallback(() => {
|
|
206
217
|
const text = [
|
|
207
218
|
info.message,
|
|
@@ -237,31 +248,40 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
237
248
|
try {
|
|
238
249
|
const result = await onFork();
|
|
239
250
|
if (result === false) {
|
|
240
|
-
setForkError("
|
|
251
|
+
setForkError(t("agentChat.recovery.forkFailed"));
|
|
241
252
|
}
|
|
242
253
|
}
|
|
243
254
|
catch {
|
|
244
|
-
setForkError("
|
|
255
|
+
setForkError(t("agentChat.recovery.forkFailed"));
|
|
245
256
|
}
|
|
246
257
|
finally {
|
|
247
258
|
setForking(false);
|
|
248
259
|
}
|
|
249
|
-
}, [forking, onFork]);
|
|
260
|
+
}, [forking, onFork, t]);
|
|
250
261
|
useEffect(() => {
|
|
251
262
|
if (builderReconnectResolved) {
|
|
252
263
|
onDismiss();
|
|
253
264
|
}
|
|
254
265
|
}, [builderReconnectResolved, onDismiss]);
|
|
255
|
-
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
266
|
+
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info, {
|
|
267
|
+
recoverable: t("agentChat.error.stopped"),
|
|
268
|
+
terminal: t("agentChat.error.failed"),
|
|
269
|
+
}) }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: localizeKnownChatErrorText(info.message, t) }), isProviderAuthError && (_jsx("div", { className: "mt-3 rounded-md border border-border/70 bg-background/60 p-2.5", children: _jsx(BuilderSetupContent, { layout: "sidebar", onConnected: handleProviderConnected }) })), shouldShowBuilderReconnect && !builderReconnectResolved && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: t("agentChat.recovery.credentialRejected") })), isConnectionRecoveryError && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: t("agentChat.recovery.newChatHint") })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), t("agentChat.common.details")] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": t("agentChat.common.dismiss"), className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && !builderReconnectResolved && (_jsxs("button", { type: "button", onClick: () => builderReconnect.start(), disabled: builderReconnect.connecting, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-70", children: [builderReconnect.connecting ? (_jsx(IconLoader2, { size: 13, className: "animate-spin" })) : null, builderReconnect.connecting
|
|
270
|
+
? t("agentChat.recovery.connectingBuilder")
|
|
271
|
+
: t("agentChat.recovery.reconnectBuilder")] })), canRecover && (_jsx(_Fragment, { children: _jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), t("agentChat.common.continue")] }) })), canRetry && (_jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), isQueryError
|
|
272
|
+
? t("agentChat.recovery.diagnoseRetry")
|
|
273
|
+
: t("agentChat.common.retry")] })), canRecover && isConnectionRecoveryError && (_jsxs("button", { type: "button", onClick: startNewChat, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconPlus, { size: 13 }), t("agentChat.tabs.newChat")] })), canRecover && onFork && !isConnectionRecoveryError && (_jsxs("button", { type: "button", onClick: handleFork, disabled: forking, title: t("agentChat.recovery.forkDescription"), "aria-label": t("agentChat.recovery.forkDescription"), className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent disabled:cursor-wait disabled:opacity-70", children: [forking ? (_jsx(IconLoader2, { size: 13, className: "animate-spin" })) : (_jsx(IconGitFork, { size: 13 })), forking
|
|
274
|
+
? t("agentChat.recovery.forking")
|
|
275
|
+
: t("agentChat.message.forkChat")] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ms-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copyState === "copied" ? (_jsx(IconCheck, { size: 13 })) : copyState === "failed" ? (_jsx(IconX, { size: 13 })) : (_jsx(IconCopy, { size: 13 })), _jsx("span", { "aria-live": "polite", children: copyState === "copied"
|
|
276
|
+
? t("agentChat.common.copied")
|
|
259
277
|
: copyState === "failed"
|
|
260
|
-
? "
|
|
278
|
+
? t("agentChat.recovery.copyFailed")
|
|
261
279
|
: copyLabel })] })] }), shouldShowBuilderReconnect && builderReconnect.error && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-red-500", children: builderReconnect.error })), forkError && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-red-500", children: forkError }))] }));
|
|
262
280
|
}
|
|
263
281
|
// ─── LoopLimitContinueCard ────────────────────────────────────────────────────
|
|
264
282
|
export function LoopLimitContinueCard({ info, onContinue, }) {
|
|
283
|
+
const t = useT();
|
|
284
|
+
const { formatNumber } = useFormatters();
|
|
265
285
|
const [settings, setSettings] = useState(null);
|
|
266
286
|
const [value, setValue] = useState("");
|
|
267
287
|
const [saving, setSaving] = useState(false);
|
|
@@ -294,9 +314,11 @@ export function LoopLimitContinueCard({ info, onContinue, }) {
|
|
|
294
314
|
numericValue !== settings.maxIterations;
|
|
295
315
|
const scopeLabel = settings?.scope === "org"
|
|
296
316
|
? settings.orgName
|
|
297
|
-
?
|
|
298
|
-
|
|
299
|
-
|
|
317
|
+
? t("agentChat.limit.namedOrganization", {
|
|
318
|
+
organization: settings.orgName,
|
|
319
|
+
})
|
|
320
|
+
: t("agentChat.limit.organization")
|
|
321
|
+
: t("agentChat.limit.account");
|
|
300
322
|
const saveLimit = useCallback(async () => {
|
|
301
323
|
if (!settings?.canUpdate)
|
|
302
324
|
return false;
|
|
@@ -311,7 +333,8 @@ export function LoopLimitContinueCard({ info, onContinue, }) {
|
|
|
311
333
|
});
|
|
312
334
|
const body = await res.json().catch(() => ({}));
|
|
313
335
|
if (!res.ok) {
|
|
314
|
-
throw new Error(body?.error ??
|
|
336
|
+
throw new Error(body?.error ??
|
|
337
|
+
t("agentChat.common.saveFailedStatus", { status: res.status }));
|
|
315
338
|
}
|
|
316
339
|
setSettings(body);
|
|
317
340
|
setValue(String(body.maxIterations));
|
|
@@ -321,13 +344,13 @@ export function LoopLimitContinueCard({ info, onContinue, }) {
|
|
|
321
344
|
return true;
|
|
322
345
|
}
|
|
323
346
|
catch (err) {
|
|
324
|
-
setError(err instanceof Error ? err.message : "
|
|
347
|
+
setError(err instanceof Error ? err.message : t("agentChat.common.saveFailed"));
|
|
325
348
|
return false;
|
|
326
349
|
}
|
|
327
350
|
finally {
|
|
328
351
|
setSaving(false);
|
|
329
352
|
}
|
|
330
|
-
}, [numericValue, settings?.canUpdate]);
|
|
353
|
+
}, [numericValue, settings?.canUpdate, t]);
|
|
331
354
|
const handleContinue = useCallback(async () => {
|
|
332
355
|
if (hasPendingChange) {
|
|
333
356
|
const ok = await saveLimit();
|
|
@@ -343,12 +366,18 @@ export function LoopLimitContinueCard({ info, onContinue, }) {
|
|
|
343
366
|
catch { }
|
|
344
367
|
window.dispatchEvent(new CustomEvent("agent-panel:open-settings"));
|
|
345
368
|
}, []);
|
|
346
|
-
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] px-3 py-3 shadow-sm", children: [_jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-600 dark:text-amber-400", children: _jsx(IconGauge, { size: 14 }) }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "
|
|
347
|
-
|
|
348
|
-
:
|
|
369
|
+
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] px-3 py-3 shadow-sm", children: [_jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-600 dark:text-amber-400", children: _jsx(IconGauge, { size: 14 }) }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: t("agentChat.limit.reached") }), _jsx("p", { className: "mt-0.5 text-xs leading-relaxed text-muted-foreground", children: currentLimit
|
|
370
|
+
? t("agentChat.limit.descriptionWithCount", {
|
|
371
|
+
count: currentLimit,
|
|
372
|
+
formattedCount: formatNumber(currentLimit),
|
|
373
|
+
scope: scopeLabel,
|
|
374
|
+
})
|
|
375
|
+
: t("agentChat.limit.descriptionAll", { scope: scopeLabel }) })] })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-end gap-2", children: [_jsxs("label", { className: "min-w-[116px] flex-1 space-y-1", children: [_jsx("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: t("agentChat.limit.maxSteps") }), _jsx("input", { type: "number", min: settings?.minMaxIterations ?? 1, max: settings?.maxMaxIterations ?? 1000, value: value, disabled: !settings?.canUpdate || saving, onChange: (e) => {
|
|
349
376
|
setValue(e.target.value);
|
|
350
377
|
setError(null);
|
|
351
|
-
}, className: "h-8 w-full rounded-md border border-border bg-background px-2 text-xs text-foreground outline-none focus:ring-1 focus:ring-ring disabled:opacity-60" })] }), _jsx("button", { type: "button", onClick: saveLimit, disabled: !hasPendingChange || saving, className: "inline-flex h-8 items-center gap-1 rounded-md border border-border px-2.5 text-xs font-medium text-foreground hover:bg-accent disabled:opacity-50", children: saving ? (_jsx(IconLoader2, { size: 12, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: 12 })) : ("
|
|
378
|
+
}, className: "h-8 w-full rounded-md border border-border bg-background px-2 text-xs text-foreground outline-none focus:ring-1 focus:ring-ring disabled:opacity-60" })] }), _jsx("button", { type: "button", onClick: saveLimit, disabled: !hasPendingChange || saving, className: "inline-flex h-8 items-center gap-1 rounded-md border border-border px-2.5 text-xs font-medium text-foreground hover:bg-accent disabled:opacity-50", children: saving ? (_jsx(IconLoader2, { size: 12, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: 12 })) : (t("agentChat.common.save")) }), _jsxs("button", { type: "button", onClick: openSettings, className: "inline-flex h-8 items-center gap-1 rounded-md border border-border px-2.5 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground", children: [_jsx(IconSettings, { size: 12 }), t("agentChat.common.settings")] }), _jsxs("button", { type: "button", onClick: handleContinue, disabled: saving, className: "ms-auto inline-flex h-8 items-center gap-1 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:opacity-60", children: [hasPendingChange
|
|
379
|
+
? t("agentChat.limit.saveAndContinue")
|
|
380
|
+
: t("agentChat.limit.keepGoing"), _jsx(IconArrowRight, { size: 12 })] })] }), settings && !settings.canUpdate && (_jsx("p", { className: "mt-2 text-[11px] text-muted-foreground", children: t("agentChat.limit.ownerOnly") })), error && _jsx("p", { className: "mt-2 text-[11px] text-destructive", children: error })] }));
|
|
352
381
|
}
|
|
353
382
|
// ─── PlanModeCallout ──────────────────────────────────────────────────────────
|
|
354
383
|
//
|
|
@@ -358,5 +387,8 @@ export function LoopLimitContinueCard({ info, onContinue, }) {
|
|
|
358
387
|
// narrow sidebar chats and wide/centered page layouts, instead of floating
|
|
359
388
|
// against the full pane width.
|
|
360
389
|
export function PlanModeCallout({ canImplementPlan, onImplementPlan, onSwitchToAct, }) {
|
|
361
|
-
|
|
390
|
+
const t = useT();
|
|
391
|
+
return (_jsx("div", { className: "agent-plan-mode-callout shrink-0 px-3", children: _jsxs("div", { className: "ms-auto flex w-fit max-w-full items-center gap-2 rounded-full border border-border/70 bg-background/95 px-2 py-1.5 text-xs text-muted-foreground shadow-sm", children: [_jsx(IconClipboardList, { size: 13, className: "shrink-0" }), _jsx("span", { className: "min-w-0 truncate", children: canImplementPlan
|
|
392
|
+
? t("agentChat.plan.ready")
|
|
393
|
+
: t("agentChat.plan.mode") }), canImplementPlan ? (_jsxs("button", { type: "button", onClick: onImplementPlan, className: "inline-flex h-6 shrink-0 items-center gap-1 rounded-full bg-foreground px-2.5 text-[11px] font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 12 }), t("agentChat.plan.implement")] })) : (_jsxs("button", { type: "button", onClick: onSwitchToAct, className: "inline-flex h-6 shrink-0 items-center gap-1 rounded-full border border-border bg-background px-2.5 text-[11px] font-medium text-foreground hover:bg-accent", "aria-label": t("agentChat.plan.switchToAct"), children: [t("agentChat.plan.act"), _jsx(IconArrowRight, { size: 12 })] }))] }) }));
|
|
362
394
|
}
|