@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
|
@@ -32,9 +32,11 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./com
|
|
|
32
32
|
import { AgentComposerFrame, TiptapComposer, } from "./composer/index.js";
|
|
33
33
|
import { useAgentDynamicSuggestionsResult, } from "./dynamic-suggestions.js";
|
|
34
34
|
import { GuidedQuestionFlow, useGuidedQuestionFlow, } from "./guided-questions.js";
|
|
35
|
+
import { useT } from "./i18n.js";
|
|
35
36
|
import { buildSignInReturnHref } from "./require-session.js";
|
|
36
37
|
import { addMcpConnectionCompleteListener, consumeMcpConnectionResume, } from "./resources/mcp-connection-resume.js";
|
|
37
38
|
import { McpConnectionSuggestion } from "./resources/McpConnectionSuggestion.js";
|
|
39
|
+
import { claimRunStream, createRunStreamToken, ownsRunStream, releaseRunStream, } from "./run-stream-ownership.js";
|
|
38
40
|
import { AgentAutoContinueSignal, readSSEStreamRaw, settleInterruptedToolCalls, } from "./sse-event-processor.js";
|
|
39
41
|
import { useAgentEngineConfigured } from "./use-agent-engine-configured.js";
|
|
40
42
|
import { useDevMode } from "./use-dev-mode.js";
|
|
@@ -364,6 +366,7 @@ function getImageAttachmentSrc(attachment) {
|
|
|
364
366
|
return imagePart && "image" in imagePart ? imagePart.image : null;
|
|
365
367
|
}
|
|
366
368
|
function ComposerAttachmentPreviewCard({ attachment, onRemove, }) {
|
|
369
|
+
const t = useT();
|
|
367
370
|
const [imageSrc, setImageSrc] = useState(null);
|
|
368
371
|
useEffect(() => {
|
|
369
372
|
const nextSrc = getImageAttachmentSrc(attachment);
|
|
@@ -382,7 +385,9 @@ function ComposerAttachmentPreviewCard({ attachment, onRemove, }) {
|
|
|
382
385
|
? "h-20 w-20 rounded-xl shadow-[0_12px_30px_-18px_rgba(0,0,0,0.7)]"
|
|
383
386
|
: "inline-flex max-w-[220px] items-center gap-2 rounded-lg px-2.5 py-2 text-xs"), children: [isImage ? (_jsxs(_Fragment, { children: [_jsx("img", { src: imageSrc, alt: attachment.name, className: "h-full w-full object-cover" }), _jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/80 via-black/30 to-transparent px-2 py-1.5", children: _jsx("div", { className: "truncate text-[10px] font-medium text-white/95", children: attachment.name }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-background text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: attachment.name.split(".").pop() || "file" }), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "truncate font-medium", children: attachment.name }), _jsx("div", { className: "text-[11px] text-muted-foreground", children: attachment.contentType || attachment.type })] })] })), _jsx("button", { type: "button", onClick: () => onRemove(attachment.id), className: cn("absolute flex h-6 w-6 items-center justify-center rounded-full border border-border/60 bg-background/95 text-muted-foreground shadow-sm transition hover:text-foreground", isImage
|
|
384
387
|
? "end-1.5 top-1.5 opacity-100 md:opacity-0 md:group-hover:opacity-100"
|
|
385
|
-
: "end-1.5 top-1.5"), "aria-label":
|
|
388
|
+
: "end-1.5 top-1.5"), "aria-label": t("agentChat.composer.removeAttachment", {
|
|
389
|
+
name: attachment.name,
|
|
390
|
+
}), children: _jsx(IconX, { className: "h-3 w-3" }) })] }));
|
|
386
391
|
}
|
|
387
392
|
function ComposerAttachmentPreviewStrip() {
|
|
388
393
|
const attachments = useComposer((state) => state.attachments);
|
|
@@ -786,6 +791,27 @@ function trimReconnectTextAlreadyRendered(content, renderedAssistantText, option
|
|
|
786
791
|
}
|
|
787
792
|
return changed ? next : content;
|
|
788
793
|
}
|
|
794
|
+
/**
|
|
795
|
+
* Whether the reconnect overlay — a SECOND fold of a run, rendered as a sibling
|
|
796
|
+
* of the message list — may appear.
|
|
797
|
+
*
|
|
798
|
+
* The adapter runtime and the reconnect reader both fold the same SSE events
|
|
799
|
+
* into their own accumulator. Whenever both are on screen the user sees the
|
|
800
|
+
* turn twice: duplicate tool cards (one spinning, one static) and the final
|
|
801
|
+
* message streaming in two places. Content-similarity dedupe cannot reliably
|
|
802
|
+
* hide the second copy, because the two readers disagree on tool-call identity
|
|
803
|
+
* (id-less activity cards get reader-local ids) and on how a turn is split
|
|
804
|
+
* across assistant messages.
|
|
805
|
+
*
|
|
806
|
+
* So ownership decides visibility, not similarity: if a runtime owns the turn,
|
|
807
|
+
* the overlay does not render. Keep this a pure function — it is the invariant
|
|
808
|
+
* the duplicate-render bug kept violating, and it must stay falsifiable.
|
|
809
|
+
*/
|
|
810
|
+
export function shouldShowReconnectOverlay(state) {
|
|
811
|
+
if (state.isRuntimeRunning)
|
|
812
|
+
return false;
|
|
813
|
+
return state.isReconnecting || state.reconnectFrozen;
|
|
814
|
+
}
|
|
789
815
|
export function dedupeReconnectContentAgainstMessages(content, messages, options) {
|
|
790
816
|
if (content.length === 0)
|
|
791
817
|
return content;
|
|
@@ -958,14 +984,38 @@ export function resolveAssistantChatRunningState({ forceStopped, isRuntimeRunnin
|
|
|
958
984
|
showRunningInUI: !forceStopped && !hasTerminalRunError && (isRunning || isAutoResuming),
|
|
959
985
|
};
|
|
960
986
|
}
|
|
961
|
-
export function resolveAssistantChatRunningStatusLabel({ runningActivityLabel, isAutoResuming, isReconnecting, hasReconnectContent,
|
|
962
|
-
|
|
987
|
+
export function resolveAssistantChatRunningStatusLabel({ runningActivityLabel, isAutoResuming, isReconnecting, hasReconnectContent, labels = {
|
|
988
|
+
thinking: "Thinking",
|
|
989
|
+
resuming: "Resuming",
|
|
990
|
+
stillWorking: "Still working",
|
|
991
|
+
}, }) {
|
|
992
|
+
if (runningActivityLabel) {
|
|
993
|
+
if (runningActivityLabel === "Thinking")
|
|
994
|
+
return labels.thinking;
|
|
995
|
+
if (runningActivityLabel === "Working") {
|
|
996
|
+
return labels.working ?? "Working";
|
|
997
|
+
}
|
|
998
|
+
if (runningActivityLabel === "Contacting model") {
|
|
999
|
+
return labels.contactingModel ?? "Contacting model";
|
|
1000
|
+
}
|
|
1001
|
+
const localizedActivityPatterns = [
|
|
1002
|
+
[/^Starting (.+)\.\.\.$/, labels.starting],
|
|
1003
|
+
[/^Preparing (.+)\.\.\.$/, labels.preparing],
|
|
1004
|
+
[/^Writing (.+)\.\.\.$/, labels.writing],
|
|
1005
|
+
[/^Still generating (.+)$/, labels.stillGenerating],
|
|
1006
|
+
];
|
|
1007
|
+
for (const [pattern, translateActivity] of localizedActivityPatterns) {
|
|
1008
|
+
const match = runningActivityLabel.match(pattern);
|
|
1009
|
+
if (match?.[1] && translateActivity)
|
|
1010
|
+
return translateActivity(match[1]);
|
|
1011
|
+
}
|
|
963
1012
|
return runningActivityLabel;
|
|
1013
|
+
}
|
|
964
1014
|
if (isAutoResuming)
|
|
965
|
-
return
|
|
1015
|
+
return labels.resuming;
|
|
966
1016
|
if (isReconnecting && hasReconnectContent)
|
|
967
|
-
return
|
|
968
|
-
return
|
|
1017
|
+
return labels.stillWorking;
|
|
1018
|
+
return labels.thinking;
|
|
969
1019
|
}
|
|
970
1020
|
export function resolveAssistantChatComposerPlaceholder(composerPlaceholder) {
|
|
971
1021
|
return composerPlaceholder ?? DEFAULT_ASSISTANT_CHAT_COMPOSER_PLACEHOLDER;
|
|
@@ -1087,6 +1137,9 @@ function AssistantChatScrollerControls({ resumeFollowingRef, }) {
|
|
|
1087
1137
|
}, [resumeFollowingRef, scrollToEnd]);
|
|
1088
1138
|
return null;
|
|
1089
1139
|
}
|
|
1140
|
+
export function shouldShowAssistantChatModelSelector(showModelSelector) {
|
|
1141
|
+
return showModelSelector !== false;
|
|
1142
|
+
}
|
|
1090
1143
|
export const CHAT_STORAGE_PREFIX = "agent-chat:";
|
|
1091
1144
|
const THREAD_SNAPSHOT_CACHE_PREFIX = `${CHAT_STORAGE_PREFIX}thread-snapshot:`;
|
|
1092
1145
|
function threadSnapshotCacheKey(apiUrl, threadId) {
|
|
@@ -1322,7 +1375,8 @@ export function useAutoResumeStatus(tabId, forceStopped) {
|
|
|
1322
1375
|
function approvalResolutionIdentity(approvalKey, toolCallId) {
|
|
1323
1376
|
return `${toolCallId ?? ""}\u0000${approvalKey}`;
|
|
1324
1377
|
}
|
|
1325
|
-
const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, dynamicSuggestions, threadFooterSlot, emptyStateAddon, showHeader = true, onSwitchToCli, className, apiUrl, tabId, browserTabId, threadId, contextScope, isActiveComposer = true, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, onComposerTextChange, composerAreaClassName, composerPlaceholder, missingApiKeySetupLayout = "default", composerLayoutVariant = "default", centerComposerWhenEmpty = false, emptyStateDisplay = "default", composerToolbarSlot, composerExtraActionButton, composerDisabled = false, composerDisabledPlaceholder, isNewThread, isThreadStateLoading, onSlashCommand, execMode, onExecModeChange, approvalActions, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, modelListLoading, onModelChange, onEffortChange, imageModelMenu, onForkChat, onConnectProvider, onConnectLocalRuntime, plusMenuMode = "full", providerStatusChecksEnabled = true, loadHistoryRepository, historyReloadKey, externalStreaming = false, agentChatSurface = "app", suppressInlineOpenApp = false, }, ref) {
|
|
1378
|
+
const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, dynamicSuggestions, threadFooterSlot, emptyStateAddon, showHeader = true, onSwitchToCli, className, apiUrl, tabId, browserTabId, threadId, contextScope, isActiveComposer = true, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, onComposerTextChange, composerAreaClassName, composerPlaceholder, missingApiKeySetupLayout = "default", composerLayoutVariant = "default", centerComposerWhenEmpty = false, emptyStateDisplay = "default", composerToolbarSlot, composerExtraActionButton, showModelSelector = true, composerDisabled = false, composerDisabledPlaceholder, isNewThread, isThreadStateLoading, onSlashCommand, execMode, onExecModeChange, approvalActions, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, modelListLoading, onModelChange, onEffortChange, imageModelMenu, onForkChat, onConnectProvider, onConnectLocalRuntime, plusMenuMode = "full", providerStatusChecksEnabled = true, loadHistoryRepository, historyReloadKey, externalStreaming = false, agentChatSurface = "app", suppressInlineOpenApp = false, }, ref) {
|
|
1379
|
+
const t = useT();
|
|
1326
1380
|
const thread = useThread();
|
|
1327
1381
|
const threadRuntime = useThreadRuntime();
|
|
1328
1382
|
const composerRuntime = useComposerRuntime();
|
|
@@ -1419,10 +1473,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1419
1473
|
void Promise.all(attachments.map((file) => composerRuntime.addAttachment(file))).catch((error) => {
|
|
1420
1474
|
const msg = error instanceof Error
|
|
1421
1475
|
? error.message
|
|
1422
|
-
: "
|
|
1476
|
+
: t("agentChat.composer.droppedFileError");
|
|
1423
1477
|
setComposerError(msg);
|
|
1424
1478
|
});
|
|
1425
|
-
}, [composerRuntime, setComposerError]);
|
|
1479
|
+
}, [composerRuntime, setComposerError, t]);
|
|
1426
1480
|
// Patch the underlying assistant-ui MessageRepository so addOrUpdateMessage
|
|
1427
1481
|
// can't throw "Parent message not found" mid-run. assistant-ui calls
|
|
1428
1482
|
// `repository.clear()` from `runtime.import()` and from `resetHead(null)`,
|
|
@@ -1605,7 +1659,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1605
1659
|
const [reconnectFrozen, setReconnectFrozen] = useState(false);
|
|
1606
1660
|
// Adapter took over while reconnect still had visible tool cards — keep the
|
|
1607
1661
|
// overlay until the adapter message catches up so we don't flash an empty gap.
|
|
1608
|
-
const [adapterHandoffPending, setAdapterHandoffPending] = useState(false);
|
|
1609
1662
|
const reconnectRunIdRef = useRef(null);
|
|
1610
1663
|
const reconnectTurnIdRef = useRef(null);
|
|
1611
1664
|
const reconnectTailOnlyRef = useRef(false);
|
|
@@ -1624,7 +1677,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1624
1677
|
setIsReconnecting(false);
|
|
1625
1678
|
setReconnectFrozen(false);
|
|
1626
1679
|
setReconnectContent([]);
|
|
1627
|
-
setAdapterHandoffPending(false);
|
|
1628
1680
|
setPendingReconnectRecovery(null);
|
|
1629
1681
|
resetRunningActivity();
|
|
1630
1682
|
}, [resetRunningActivity]);
|
|
@@ -1701,15 +1753,21 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1701
1753
|
isAutoResuming,
|
|
1702
1754
|
isReconnecting,
|
|
1703
1755
|
hasReconnectContent: reconnectContent.length > 0,
|
|
1756
|
+
labels: {
|
|
1757
|
+
thinking: t("agentChat.status.thinking"),
|
|
1758
|
+
resuming: t("agentChat.status.resuming"),
|
|
1759
|
+
stillWorking: t("agentChat.status.stillWorking"),
|
|
1760
|
+
working: t("agentChat.status.working"),
|
|
1761
|
+
contactingModel: t("agentChat.status.contactingModel"),
|
|
1762
|
+
starting: (activity) => t("agentChat.status.starting", { activity }),
|
|
1763
|
+
preparing: (activity) => t("agentChat.status.preparing", { activity }),
|
|
1764
|
+
writing: (activity) => t("agentChat.status.writing", { activity }),
|
|
1765
|
+
stillGenerating: (activity) => t("agentChat.status.stillGenerating", { activity }),
|
|
1766
|
+
},
|
|
1704
1767
|
});
|
|
1705
|
-
const reconnectActivityContent = useMemo(() => isReconnecting || reconnectFrozen
|
|
1768
|
+
const reconnectActivityContent = useMemo(() => isReconnecting || reconnectFrozen
|
|
1706
1769
|
? reconnectActivityFallbackContent(runningActivityTool)
|
|
1707
|
-
: [], [
|
|
1708
|
-
adapterHandoffPending,
|
|
1709
|
-
isReconnecting,
|
|
1710
|
-
reconnectFrozen,
|
|
1711
|
-
runningActivityTool,
|
|
1712
|
-
]);
|
|
1770
|
+
: [], [isReconnecting, reconnectFrozen, runningActivityTool]);
|
|
1713
1771
|
const lastBroadcastRunningRef = useRef(isRunning);
|
|
1714
1772
|
const tiptapRef = useRef(null);
|
|
1715
1773
|
const focusComposerAfterConnectRef = useRef(false);
|
|
@@ -2010,6 +2068,13 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2010
2068
|
if (isRuntimeRunningRef.current || isAutoResumingRef.current) {
|
|
2011
2069
|
return false;
|
|
2012
2070
|
}
|
|
2071
|
+
// The refs above lag a render and are per-component-instance, while
|
|
2072
|
+
// MultiTabAssistantChat mounts several instances against one run. The
|
|
2073
|
+
// claim is the actual mutual exclusion: module-scoped, synchronous, and
|
|
2074
|
+
// re-checked on every state write below.
|
|
2075
|
+
const ownershipToken = createRunStreamToken(`reconnect:${runId}`);
|
|
2076
|
+
if (!claimRunStream(threadId, runId, ownershipToken))
|
|
2077
|
+
return false;
|
|
2013
2078
|
// SUPERSEDE THE PREVIOUS RECONNECT GENERATION. A turn that keeps failing
|
|
2014
2079
|
// (e.g. repeated stale_run at "Contacting model") produces a new runId
|
|
2015
2080
|
// every few seconds; each call here used to OVERWRITE the single-slot
|
|
@@ -2050,7 +2115,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2050
2115
|
});
|
|
2051
2116
|
setIsReconnecting(true);
|
|
2052
2117
|
setReconnectFrozen(false);
|
|
2053
|
-
setAdapterHandoffPending(false);
|
|
2054
2118
|
setReconnectContent([]);
|
|
2055
2119
|
window.dispatchEvent(new CustomEvent("agentNative.chatRunning", {
|
|
2056
2120
|
detail: { isRunning: true, tabId: tabId || threadId },
|
|
@@ -2197,7 +2261,8 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2197
2261
|
requestAnimationFrame(() => {
|
|
2198
2262
|
rafPending = false;
|
|
2199
2263
|
if (!reconnectOwnerMountedRef.current ||
|
|
2200
|
-
reconnectRunIdRef.current !== runId
|
|
2264
|
+
reconnectRunIdRef.current !== runId ||
|
|
2265
|
+
!ownsRunStream(threadId, runId, ownershipToken)) {
|
|
2201
2266
|
return;
|
|
2202
2267
|
}
|
|
2203
2268
|
setReconnectContent(latestSnapshot);
|
|
@@ -2205,9 +2270,14 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2205
2270
|
};
|
|
2206
2271
|
try {
|
|
2207
2272
|
await readSSEStreamRaw(sseRes.body, content, toolCallCounter, tabId, scheduleUpdate, (seq, isProgress) => {
|
|
2273
|
+
// The adapter can preempt this reader mid-stream. Advancing
|
|
2274
|
+
// the cursor after that would move a run this reader no
|
|
2275
|
+
// longer represents.
|
|
2276
|
+
if (!ownsRunStream(threadId, runId, ownershipToken))
|
|
2277
|
+
return;
|
|
2208
2278
|
markReconnectProgress();
|
|
2209
2279
|
reconnectRetryCount = 0;
|
|
2210
|
-
updateActiveRunSeq(seq, isProgress);
|
|
2280
|
+
updateActiveRunSeq(threadId, runId, seq, isProgress);
|
|
2211
2281
|
}, { preparingActionState });
|
|
2212
2282
|
if (reconnectAfterSeq === 0) {
|
|
2213
2283
|
setReconnectContent([...content]);
|
|
@@ -2255,6 +2325,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2255
2325
|
threadPollEngine?.stop();
|
|
2256
2326
|
watchdog.stop();
|
|
2257
2327
|
clearInterval(idleCheck);
|
|
2328
|
+
releaseRunStream(threadId, runId, ownershipToken);
|
|
2258
2329
|
}
|
|
2259
2330
|
// A newer reader, live adapter, stop action, or component unmount took
|
|
2260
2331
|
// ownership while this async loop was unwinding. Do not let the stale
|
|
@@ -2347,10 +2418,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2347
2418
|
}
|
|
2348
2419
|
setRunErrorInfo({
|
|
2349
2420
|
message: reconnectErrorCode === "run_timeout"
|
|
2350
|
-
? "
|
|
2421
|
+
? t("agentChat.recovery.backgroundTimeout")
|
|
2351
2422
|
: reconnectErrorCode === "reconnect_stream_ended"
|
|
2352
|
-
? "
|
|
2353
|
-
: "
|
|
2423
|
+
? t("agentChat.recovery.streamEnded")
|
|
2424
|
+
: t("agentChat.recovery.noProgress"),
|
|
2354
2425
|
errorCode: reconnectErrorCode,
|
|
2355
2426
|
recoverable: true,
|
|
2356
2427
|
runId,
|
|
@@ -2425,7 +2496,14 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2425
2496
|
};
|
|
2426
2497
|
void streamReconnect();
|
|
2427
2498
|
return true;
|
|
2428
|
-
}, [
|
|
2499
|
+
}, [
|
|
2500
|
+
apiUrl,
|
|
2501
|
+
refreshThreadFromServer,
|
|
2502
|
+
t,
|
|
2503
|
+
tabId,
|
|
2504
|
+
threadId,
|
|
2505
|
+
wasRecentlyStoppedRun,
|
|
2506
|
+
]);
|
|
2429
2507
|
const reconnectActiveRunForThread = useCallback(async () => {
|
|
2430
2508
|
if (!threadId)
|
|
2431
2509
|
return false;
|
|
@@ -2461,7 +2539,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2461
2539
|
clearActiveRunIfMatches(threadId, storedActiveRun.runId);
|
|
2462
2540
|
window.dispatchEvent(new CustomEvent("agent-chat:run-error", {
|
|
2463
2541
|
detail: {
|
|
2464
|
-
message: "
|
|
2542
|
+
message: t("agentChat.recovery.statusCheckFailed"),
|
|
2465
2543
|
errorCode: "run_status_unavailable",
|
|
2466
2544
|
recoverable: true,
|
|
2467
2545
|
...(storedActiveRun.runId
|
|
@@ -2492,7 +2570,14 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2492
2570
|
catch {
|
|
2493
2571
|
return false;
|
|
2494
2572
|
}
|
|
2495
|
-
}, [
|
|
2573
|
+
}, [
|
|
2574
|
+
apiUrl,
|
|
2575
|
+
refreshThreadFromServer,
|
|
2576
|
+
startReconnectToRun,
|
|
2577
|
+
t,
|
|
2578
|
+
tabId,
|
|
2579
|
+
threadId,
|
|
2580
|
+
]);
|
|
2496
2581
|
useEffect(() => {
|
|
2497
2582
|
if (!threadId || !isNewThread)
|
|
2498
2583
|
return;
|
|
@@ -3192,11 +3277,14 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3192
3277
|
prevIsRuntimeRunningRef.current = isRuntimeRunning;
|
|
3193
3278
|
if (isRuntimeRunning && !wasRunning) {
|
|
3194
3279
|
// SINGLE-READER OWNERSHIP: the adapter runtime just took over (a new run
|
|
3195
|
-
// started or an adopted run resumed)
|
|
3196
|
-
//
|
|
3197
|
-
// UI
|
|
3280
|
+
// started or an adopted run resumed), so it is now the only owner of this
|
|
3281
|
+
// turn's rendering. The overlay used to be kept alive here for up to
|
|
3282
|
+
// 2500ms so the UI would not flash a gap — but that deliberately put two
|
|
3283
|
+
// independent folds of the same run on screen at once, and the only thing
|
|
3284
|
+
// hiding the second was content-similarity guessing that fails whenever
|
|
3285
|
+
// the two readers disagree (id-less activity cards, a turn split across
|
|
3286
|
+
// several assistant messages). One owner, one surface: drop the overlay.
|
|
3198
3287
|
if (reconnectRunIdRef.current !== null) {
|
|
3199
|
-
const keepOverlay = reconnectContent.length > 0;
|
|
3200
3288
|
reconnectRunIdRef.current = null;
|
|
3201
3289
|
reconnectAbortRef.current?.abort();
|
|
3202
3290
|
reconnectAbortRef.current = null;
|
|
@@ -3204,56 +3292,18 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3204
3292
|
setReconnectFrozen(false);
|
|
3205
3293
|
reconnectCanMaterializeRef.current = false;
|
|
3206
3294
|
reconnectTailOnlyRef.current = false;
|
|
3207
|
-
|
|
3208
|
-
setAdapterHandoffPending(true);
|
|
3209
|
-
}
|
|
3210
|
-
else {
|
|
3211
|
-
setReconnectContent([]);
|
|
3212
|
-
setAdapterHandoffPending(false);
|
|
3213
|
-
}
|
|
3295
|
+
setReconnectContent([]);
|
|
3214
3296
|
}
|
|
3215
3297
|
else if (reconnectFrozen) {
|
|
3216
3298
|
setReconnectFrozen(false);
|
|
3217
3299
|
setReconnectContent([]);
|
|
3218
|
-
setAdapterHandoffPending(false);
|
|
3219
3300
|
reconnectCanMaterializeRef.current = false;
|
|
3220
3301
|
}
|
|
3221
3302
|
if (forceStopped) {
|
|
3222
3303
|
setForceStopped(false);
|
|
3223
3304
|
}
|
|
3224
3305
|
}
|
|
3225
|
-
}, [
|
|
3226
|
-
isRuntimeRunning,
|
|
3227
|
-
reconnectFrozen,
|
|
3228
|
-
forceStopped,
|
|
3229
|
-
reconnectContent.length,
|
|
3230
|
-
]);
|
|
3231
|
-
// Release the deferred reconnect overlay once thread messages have caught
|
|
3232
|
-
// up enough that dedupe would hide the overlay, or after a short timeout so
|
|
3233
|
-
// a stuck handoff cannot leave duplicate tool cards forever.
|
|
3234
|
-
useEffect(() => {
|
|
3235
|
-
if (!adapterHandoffPending)
|
|
3236
|
-
return;
|
|
3237
|
-
if (!isRuntimeRunning) {
|
|
3238
|
-
setReconnectContent([]);
|
|
3239
|
-
setAdapterHandoffPending(false);
|
|
3240
|
-
return;
|
|
3241
|
-
}
|
|
3242
|
-
const stillNeeded = dedupeReconnectContentAgainstMessages(reconnectContent, messages, {
|
|
3243
|
-
suppressToolRepeats: true,
|
|
3244
|
-
trimTailTextOverlap: true,
|
|
3245
|
-
}).length > 0;
|
|
3246
|
-
if (!stillNeeded) {
|
|
3247
|
-
setReconnectContent([]);
|
|
3248
|
-
setAdapterHandoffPending(false);
|
|
3249
|
-
return;
|
|
3250
|
-
}
|
|
3251
|
-
const timer = window.setTimeout(() => {
|
|
3252
|
-
setReconnectContent([]);
|
|
3253
|
-
setAdapterHandoffPending(false);
|
|
3254
|
-
}, 2500);
|
|
3255
|
-
return () => window.clearTimeout(timer);
|
|
3256
|
-
}, [adapterHandoffPending, isRuntimeRunning, messages, reconnectContent]);
|
|
3306
|
+
}, [isRuntimeRunning, reconnectFrozen, forceStopped]);
|
|
3257
3307
|
// Same transition guard for isReconnecting: only clear forceStopped on
|
|
3258
3308
|
// the false→true edge (a new reconnect starting on page load).
|
|
3259
3309
|
const prevIsReconnectingRef = useRef(isReconnecting);
|
|
@@ -3270,7 +3320,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3270
3320
|
if (!reconnectCanMaterializeRef.current) {
|
|
3271
3321
|
setReconnectFrozen(false);
|
|
3272
3322
|
setReconnectContent([]);
|
|
3273
|
-
setAdapterHandoffPending(false);
|
|
3274
3323
|
return;
|
|
3275
3324
|
}
|
|
3276
3325
|
try {
|
|
@@ -3316,7 +3365,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3316
3365
|
threadRuntime.import(ensureMessageMetadata(repo));
|
|
3317
3366
|
setReconnectFrozen(false);
|
|
3318
3367
|
setReconnectContent([]);
|
|
3319
|
-
setAdapterHandoffPending(false);
|
|
3320
3368
|
reconnectCanMaterializeRef.current = false;
|
|
3321
3369
|
reconnectTurnIdRef.current = null;
|
|
3322
3370
|
}
|
|
@@ -3453,7 +3501,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3453
3501
|
reconnectAbortRef.current = null;
|
|
3454
3502
|
reconnectRunIdRef.current = null;
|
|
3455
3503
|
setIsReconnecting(false);
|
|
3456
|
-
setAdapterHandoffPending(false);
|
|
3457
3504
|
const shouldFreezeReconnectContent = !reconnectTailOnlyRef.current &&
|
|
3458
3505
|
reconnectCanMaterializeRef.current &&
|
|
3459
3506
|
reconnectContent.length > 0;
|
|
@@ -3539,7 +3586,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3539
3586
|
catch (err) {
|
|
3540
3587
|
const msg = err instanceof Error
|
|
3541
3588
|
? err.message
|
|
3542
|
-
: "
|
|
3589
|
+
: t("agentChat.composer.attachmentError");
|
|
3543
3590
|
setComposerError(msg);
|
|
3544
3591
|
reportAgentChatSubmitResult(submitMessageId, false, "attachment-error");
|
|
3545
3592
|
return;
|
|
@@ -3731,6 +3778,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3731
3778
|
selectedEffort,
|
|
3732
3779
|
selectedEngine,
|
|
3733
3780
|
selectedModel,
|
|
3781
|
+
t,
|
|
3734
3782
|
updateComposerContextItems,
|
|
3735
3783
|
]);
|
|
3736
3784
|
const mcpResumeTimerRef = useRef(null);
|
|
@@ -3844,8 +3892,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3844
3892
|
// an ahead-of-the-thread reconnect copy visible creates the familiar
|
|
3845
3893
|
// two-card stack while the adapter catches up, so prefer one row and
|
|
3846
3894
|
// let the live message advance in place.
|
|
3847
|
-
suppressToolRepeats:
|
|
3848
|
-
trimTailTextOverlap:
|
|
3895
|
+
suppressToolRepeats: isReconnecting || reconnectFrozen,
|
|
3896
|
+
trimTailTextOverlap: reconnectTailOnlyRef.current,
|
|
3897
|
+
});
|
|
3898
|
+
// The reconnect overlay is a SECOND fold of the same run, rendered as a
|
|
3899
|
+
// sibling of the message list. It may only appear while no adapter runtime
|
|
3900
|
+
// owns the turn. Deriving it from `isRuntimeRunning` at render time — rather
|
|
3901
|
+
// than relying on an effect to clear the overlay's own flags afterwards —
|
|
3902
|
+
// is what makes two streaming copies structurally impossible instead of
|
|
3903
|
+
// merely unlikely; the effect below runs a frame too late to prevent it.
|
|
3904
|
+
const showReconnectOverlay = shouldShowReconnectOverlay({
|
|
3905
|
+
isRuntimeRunning,
|
|
3906
|
+
isReconnecting,
|
|
3907
|
+
reconnectFrozen,
|
|
3849
3908
|
});
|
|
3850
3909
|
const latestMessage = messages[messages.length - 1];
|
|
3851
3910
|
const reconnectStatusContent = visibleReconnectContent.length > 0
|
|
@@ -4039,7 +4098,9 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4039
4098
|
getApprovalResolution,
|
|
4040
4099
|
onApprovalResolved: recordApprovalResolution,
|
|
4041
4100
|
onApprove: (approvalKey) => {
|
|
4042
|
-
void addToQueue("Approved. Go ahead and run the requested action.",
|
|
4101
|
+
void addToQueue("Approved. Go ahead and run the requested action.", // i18n-ignore -- stable hidden agent instruction, not UI copy.
|
|
4102
|
+
undefined, undefined, undefined, undefined, "queued", undefined, false, false, false, true, // hideUserMessage: this is a protocol continuation, not a new prompt
|
|
4103
|
+
undefined, [approvalKey]);
|
|
4043
4104
|
},
|
|
4044
4105
|
...(approvalActions?.onDeny ? { onDeny: approvalActions.onDeny } : {}),
|
|
4045
4106
|
...(approvalActions?.onAlwaysAllow
|
|
@@ -4068,19 +4129,19 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4068
4129
|
? "centered"
|
|
4069
4130
|
: compactMissingKeyEmptyState
|
|
4070
4131
|
? "compact-setup"
|
|
4071
|
-
: undefined, className: cn("relative flex flex-1 flex-col h-full min-h-0 text-foreground", className), onDragEnter: handleChatDragEnter, onDragOver: handleChatDragOver, onDragLeave: handleChatDragLeave, onDropCapture: handleChatDropCapture, onDrop: handleChatDrop, children: [dropActive && (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-50 flex items-center justify-center rounded-md border-2 border-dashed border-primary/70 bg-primary/5 backdrop-blur-[1px]", children: _jsx("span", { className: "rounded-md bg-background/90 px-3 py-1.5 text-xs font-medium text-foreground shadow-sm", children: "
|
|
4072
|
-
? "
|
|
4132
|
+
: undefined, className: cn("relative flex flex-1 flex-col h-full min-h-0 text-foreground", className), onDragEnter: handleChatDragEnter, onDragOver: handleChatDragOver, onDragLeave: handleChatDragLeave, onDropCapture: handleChatDropCapture, onDrop: handleChatDrop, children: [dropActive && (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-50 flex items-center justify-center rounded-md border-2 border-dashed border-primary/70 bg-primary/5 backdrop-blur-[1px]", children: _jsx("span", { className: "rounded-md bg-background/90 px-3 py-1.5 text-xs font-medium text-foreground shadow-sm", children: t("agentChat.composer.dropToAttach") }) })), showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { onClick: onSwitchToCli, "aria-label": t("agentChat.header.switchToCli"), className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] }) }), _jsx(TooltipContent, { children: t("agentChat.header.switchToCli") })] }) })) })] })), _jsxs(MessageScrollerProvider, { autoScroll: true, children: [_jsx(AssistantChatScrollerControls, { resumeFollowingRef: resumeFollowingRef }), _jsxs(MessageScroller, { className: "agent-chat-scroll", children: [_jsx(MessageScrollerViewport, { children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: authSessionAvailable ? (_jsx(IconRefresh, { className: "h-5 w-5 text-muted-foreground" })) : (_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" })) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authSessionAvailable
|
|
4133
|
+
? t("agentChat.auth.refreshTitle")
|
|
4073
4134
|
: authError.sessionExpired
|
|
4074
|
-
? "
|
|
4075
|
-
: "
|
|
4076
|
-
? "
|
|
4135
|
+
? t("agentChat.auth.expiredTitle")
|
|
4136
|
+
: t("agentChat.auth.requiredTitle") }), _jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: authSessionAvailable
|
|
4137
|
+
? t("agentChat.auth.refreshDescription")
|
|
4077
4138
|
: authError.sessionExpired
|
|
4078
|
-
? "
|
|
4079
|
-
: "
|
|
4139
|
+
? t("agentChat.auth.expiredDescription")
|
|
4140
|
+
: t("agentChat.auth.requiredDescription") })] }), _jsxs("div", { className: "flex gap-2", children: [!authError.sessionExpired &&
|
|
4080
4141
|
!authSessionAvailable && (_jsx("button", { onClick: () => {
|
|
4081
4142
|
window.location.href =
|
|
4082
4143
|
buildSignInReturnHref();
|
|
4083
|
-
}, className: "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md", children: "
|
|
4144
|
+
}, className: "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md", children: t("agentChat.auth.logIn") })), authError.sessionExpired &&
|
|
4084
4145
|
!authSessionAvailable && (_jsx("button", { onClick: async () => {
|
|
4085
4146
|
try {
|
|
4086
4147
|
await fetch(agentNativePath("/_agent-native/auth/logout"), {
|
|
@@ -4091,16 +4152,18 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4091
4152
|
console.error("Failed to log out before reloading the chat", error);
|
|
4092
4153
|
}
|
|
4093
4154
|
window.location.reload();
|
|
4094
|
-
}, className: "text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10", children: "
|
|
4155
|
+
}, className: "text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10", children: t("agentChat.auth.logOut") })), _jsx("button", { onClick: () => {
|
|
4095
4156
|
setAuthError(null);
|
|
4096
4157
|
window.location.reload();
|
|
4097
4158
|
}, className: authSessionAvailable
|
|
4098
4159
|
? "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
|
|
4099
|
-
: "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "
|
|
4160
|
+
: "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: t("agentChat.auth.refreshChat") })] })] })) : isRestoring && centeredRestoringState ? (_jsxs("div", { className: cn("agent-empty-state", emptyStateDisplay === "hidden"
|
|
4100
4161
|
? "sr-only"
|
|
4101
|
-
: "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), "aria-busy": "true", children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ??
|
|
4162
|
+
: "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), "aria-busy": "true", children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ??
|
|
4163
|
+
t("agentChat.empty.loadingChat") })] })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : showEmptyState ? (_jsxs("div", { className: cn("agent-empty-state", emptyStateDisplay === "hidden"
|
|
4102
4164
|
? "sr-only"
|
|
4103
|
-
: "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ??
|
|
4165
|
+
: "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ??
|
|
4166
|
+
t("agentChat.empty.prompt") }), emptyStateAddon, resolvedSuggestions &&
|
|
4104
4167
|
resolvedSuggestions.length > 0 ? (_jsx("div", { className: "flex w-full max-w-[280px] flex-col gap-1", children: resolvedSuggestions.map((suggestion) => (_jsx("button", { onClick: () => {
|
|
4105
4168
|
if (engineSetupRequired) {
|
|
4106
4169
|
requestMissingKeySetup();
|
|
@@ -4126,18 +4189,16 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4126
4189
|
setDismissedRunErrorKey(visibleRunErrorKey);
|
|
4127
4190
|
}
|
|
4128
4191
|
setRunErrorInfo(null);
|
|
4129
|
-
} }) })),
|
|
4130
|
-
reconnectFrozen
|
|
4131
|
-
adapterHandoffPending) &&
|
|
4132
|
-
visibleReconnectContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: visibleReconnectContent, allowActivitySpinner: !reconnectFrozen }) })), (isReconnecting ||
|
|
4133
|
-
reconnectFrozen ||
|
|
4134
|
-
adapterHandoffPending) &&
|
|
4192
|
+
} }) })), showReconnectOverlay &&
|
|
4193
|
+
visibleReconnectContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: visibleReconnectContent, allowActivitySpinner: !reconnectFrozen }) })), showReconnectOverlay &&
|
|
4135
4194
|
visibleReconnectContent.length === 0 &&
|
|
4136
4195
|
reconnectContent.length === 0 &&
|
|
4137
|
-
reconnectActivityContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: reconnectActivityContent, allowActivitySpinner: !reconnectFrozen }) })), showGlobalRunningStatus && (_jsx(MessageScrollerItem, { children: _jsx(RunningActivityStatus, { label: runningStatusLabel }) })), visibleQueuedMessages.length > 0 && (_jsx(MessageScrollerItem, { children: _jsxs("div", { className: "flex items-center justify-end gap-1.5 pr-0.5 text-xs text-muted-foreground", children: [_jsx(IconClock, { className: "h-3 w-3" }),
|
|
4196
|
+
reconnectActivityContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: reconnectActivityContent, allowActivitySpinner: !reconnectFrozen }) })), showGlobalRunningStatus && (_jsx(MessageScrollerItem, { children: _jsx(RunningActivityStatus, { label: runningStatusLabel }) })), visibleQueuedMessages.length > 0 && (_jsx(MessageScrollerItem, { children: _jsxs("div", { className: "flex items-center justify-end gap-1.5 pr-0.5 text-xs text-muted-foreground", children: [_jsx(IconClock, { className: "h-3 w-3" }), _jsx("span", { children: t("agentChat.queue.count", {
|
|
4197
|
+
count: visibleQueuedMessages.length,
|
|
4198
|
+
}) })] }) })), visibleQueuedMessages.map((msg) => {
|
|
4138
4199
|
const displayText = displayableUserMessageText(msg.text);
|
|
4139
4200
|
const imageSources = queuedMessageImageSources(msg);
|
|
4140
|
-
return (_jsx(MessageScrollerItem, { messageId: msg.id, children: _jsxs("div", { className: "group flex items-start justify-end gap-1.5", children: [isRunning && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => sendQueuedMessageNow(msg.id), "aria-label": "
|
|
4201
|
+
return (_jsx(MessageScrollerItem, { messageId: msg.id, children: _jsxs("div", { className: "group flex items-start justify-end gap-1.5", children: [isRunning && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => sendQueuedMessageNow(msg.id), "aria-label": t("agentChat.queue.sendNow"), className: "mt-1.5 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100", children: _jsx(IconArrowUp, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: t("agentChat.queue.sendNowHint") })] })), _jsx("button", { type: "button", onClick: () => applyLocalQueuedMessages((prev) => prev.filter((m) => m.id !== msg.id)), "aria-label": t("agentChat.queue.remove"), className: "mt-1.5 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) }), _jsxs("div", { className: "max-w-[85%] rounded-lg bg-accent/50 px-3 py-2 text-sm leading-relaxed text-foreground/60 whitespace-pre-wrap break-words", children: [displayText, imageSources.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: imageSources.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) }))] })] }) }, msg.id));
|
|
4141
4202
|
}), resolvedThreadFooterSlot ? (_jsx(MessageScrollerItem, { children: _jsx("div", { className: "agent-thread-footer-slot", children: resolvedThreadFooterSlot }) })) : null] })) }), !authError && !isRestoring && !showEmptyState ? (_jsx(MessageScrollerButton, {})) : null] })] }, chatScrollResetKey), showComposerSlot ? composerSlot : null, isActiveComposer && (_jsx(McpConnectionSuggestion, { text: composerText })), showCenteredEmptyThreadFooterSlot ? (_jsx("div", { className: "agent-thread-footer-slot agent-thread-footer-slot--centered-empty", children: resolvedThreadFooterSlot })) : null, guidedQuestions && guidedQuestions.length > 0 && (_jsx("div", { className: "shrink-0 px-3 pb-2", children: _jsx(GuidedQuestionFlow, { questions: guidedQuestions, onSubmit: handleGuidedQuestionsSubmit, onSkip: handleGuidedQuestionsSkip, ...(guidedQuestionsTitle
|
|
4142
4203
|
? { title: guidedQuestionsTitle }
|
|
4143
4204
|
: {}), ...(guidedQuestionsDescription
|
|
@@ -4146,7 +4207,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4146
4207
|
? { skipLabel: guidedQuestionsSkipLabel }
|
|
4147
4208
|
: {}), ...(guidedQuestionsSubmitLabel
|
|
4148
4209
|
? { submitLabel: guidedQuestionsSubmitLabel }
|
|
4149
|
-
: {}), className: "h-auto items-stretch justify-stretch bg-transparent" }) })), composerError && (_jsxs("div", { role: "alert", className: "shrink-0 mx-3 mb-1.5 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [_jsx(IconAlertTriangle, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), _jsx("span", { className: "flex-1 leading-snug", children: composerError }), _jsx("button", { type: "button", "aria-label": "
|
|
4210
|
+
: {}), className: "h-auto items-stretch justify-stretch bg-transparent" }) })), composerError && (_jsxs("div", { role: "alert", className: "shrink-0 mx-3 mb-1.5 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [_jsx(IconAlertTriangle, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), _jsx("span", { className: "flex-1 leading-snug", children: composerError }), _jsx("button", { type: "button", "aria-label": t("agentChat.common.dismissError"), onClick: () => setComposerError(null), className: "shrink-0 opacity-70 hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) })] })), _jsxs("div", { className: "agent-composer-stack", "data-agent-composer-adjacent-ui": hasComposerAccessoryAboveStack
|
|
4150
4211
|
? "true"
|
|
4151
4212
|
: undefined, children: [_jsx(SelectionAttachedPill, {}), showPlanModeCallout && (_jsx(PlanModeCallout, { canImplementPlan: canImplementPlan, onImplementPlan: handleImplementPlan, onSwitchToAct: handleSwitchToAct })), showInlineMissingKeySetup ? (_jsx(BuilderSetupCard, { fullWidth: true, layout: "sidebar", onConnected: handleBuilderConnected })) : null, _jsxs(Popover, { open: showMissingKeySetup &&
|
|
4152
4213
|
!showInlineMissingKeySetup &&
|
|
@@ -4154,24 +4215,26 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4154
4215
|
!showMissingKeySetup &&
|
|
4155
4216
|
"opacity-70"), rootClassName: cn(showMissingKeySetup &&
|
|
4156
4217
|
"agent-composer-root--missing-key"), children: showMissingKeySetup &&
|
|
4157
|
-
!showInlineMissingKeySetup ? (_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "agent-composer-missing-key-trigger", "aria-label": "
|
|
4218
|
+
!showInlineMissingKeySetup ? (_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "agent-composer-missing-key-trigger", "aria-label": t("agentChat.setup.connectToStart"), children: _jsxs("span", { className: "agent-composer-missing-key-content", children: [_jsxs("span", { className: "agent-composer-missing-key-copy", children: [_jsx("span", { className: "agent-composer-missing-key-title", children: missingApiKeySetupLayout ===
|
|
4158
4219
|
"sidebar"
|
|
4159
|
-
? "
|
|
4160
|
-
: "
|
|
4161
|
-
"sidebar" ? (_jsx("span", { className: "agent-composer-missing-key-description", children: "
|
|
4220
|
+
? t("agentChat.setup.connectToChat")
|
|
4221
|
+
: t("agentChat.setup.connectToStart") }), missingApiKeySetupLayout !==
|
|
4222
|
+
"sidebar" ? (_jsx("span", { className: "agent-composer-missing-key-description", children: t("agentChat.setup.builderCredits") })) : null] }), _jsx("span", { className: "agent-composer-missing-key-cta", children: t("agentChat.setup.connectAi") })] }) }) })) : (_jsxs(_Fragment, { children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, onTextChange: isActiveComposer
|
|
4162
4223
|
? handleComposerTextChange
|
|
4163
4224
|
: undefined, disabled: isComposerDisabled ||
|
|
4164
4225
|
showInlineMissingKeySetup, placeholder: showInlineMissingKeySetup
|
|
4165
|
-
? "
|
|
4226
|
+
? t("agentChat.setup.connectPlaceholder")
|
|
4166
4227
|
: engineSetupRequired
|
|
4167
|
-
? "
|
|
4228
|
+
? t("agentChat.setup.connectPlaceholder")
|
|
4168
4229
|
: composerDisabled
|
|
4169
4230
|
? (composerDisabledPlaceholder ??
|
|
4170
|
-
"
|
|
4231
|
+
t("agentChat.composer.openDesktop"))
|
|
4171
4232
|
: isRunning
|
|
4172
4233
|
? queuedMessages.length > 0
|
|
4173
|
-
?
|
|
4174
|
-
|
|
4234
|
+
? t("agentChat.queue.followUpWithCount", {
|
|
4235
|
+
count: queuedMessages.length,
|
|
4236
|
+
})
|
|
4237
|
+
: t("agentChat.queue.followUp")
|
|
4175
4238
|
: resolveAssistantChatComposerPlaceholder(composerPlaceholder), onSubmit: isRunning ||
|
|
4176
4239
|
composerContextItems.length > 0
|
|
4177
4240
|
? (text, references, attachments, options) => void addToQueue(text, undefined, references.length > 0
|
|
@@ -4180,9 +4243,11 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4180
4243
|
isRunning,
|
|
4181
4244
|
requestedIntent: options?.intent,
|
|
4182
4245
|
}), undefined, true)
|
|
4183
|
-
: undefined, willQueue: engineSetupRequired || isRunning, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason, selectedModel: selectedModel ?? defaultModel, selectedEffort: selectedEffort, availableModels: availableModels, modelListLoading: modelListLoading, onModelChange:
|
|
4246
|
+
: undefined, willQueue: engineSetupRequired || isRunning, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason, selectedModel: selectedModel ?? defaultModel, selectedEffort: selectedEffort, availableModels: availableModels, modelListLoading: modelListLoading, onModelChange: shouldShowAssistantChatModelSelector(showModelSelector)
|
|
4247
|
+
? onModelChange
|
|
4248
|
+
: undefined, onEffortChange: onEffortChange, imageModelMenu: imageModelMenu, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, toolbarSlot: composerToolbarSlot, contextItems: composerContextItems, onRemoveContextItem: removeComposerContextItem, plusMenuMode: plusMenuMode, layoutVariant: composerLayoutVariant, providerConnectStatusEnabled: providerStatusChecksEnabled, voiceEnabled: true, draftScope: threadId || tabId, interceptBuildRequestsForBuilder: true, onAttachmentError: setComposerError, extraActionButton: composerExtraActionButton, stopButton: showRunningInUI ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => stopActiveRun({
|
|
4184
4249
|
preserveQueuedMessages: true,
|
|
4185
|
-
}), "aria-label": "
|
|
4250
|
+
}), "aria-label": t("agentChat.composer.stopResponse"), "data-agent-composer-slot": "stop-button", className: "shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-full bg-primary text-primary-foreground shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(IconPlayerStopFilled, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: t("agentChat.composer.stopResponse") })] })) : undefined })] })) }), showMissingKeySetup &&
|
|
4186
4251
|
!showInlineMissingKeySetup ? (_jsx(PopoverContent, { side: missingApiKeySetupLayout === "sidebar"
|
|
4187
4252
|
? "top"
|
|
4188
4253
|
: "bottom", align: "center", sideOffset: 8, collisionPadding: 12, "data-agent-native-composer-popover": "true", className: "z-[260] box-border w-[min(calc(100vw-2rem),var(--radix-popover-content-available-width,26rem),26rem)] rounded-lg border-border p-3 shadow-lg", children: _jsx(BuilderSetupContent, { onConnected: handleBuilderConnected, layout: missingApiKeySetupLayout }) })) : null] })] })] }) }) }) }) }) }) }) }) }) }) }));
|