@agent-native/core 0.98.4 → 0.98.5
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 +2 -2
- package/corpus/core/CHANGELOG.md +16 -0
- package/corpus/core/docs/content/durable-background-runs.mdx +37 -0
- package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/de-DE/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/es-ES/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +4 -2
- package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +2 -0
- package/corpus/core/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
- package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +2 -0
- package/corpus/core/docs/content/tracking.mdx +2 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/durable-background.ts +16 -16
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +25 -8
- package/corpus/core/src/agent/engine/anthropic-engine.ts +17 -3
- package/corpus/core/src/agent/engine/output-tokens.ts +6 -6
- package/corpus/core/src/agent/production-agent.ts +200 -27
- package/corpus/core/src/agent/run-manager.ts +81 -1
- package/corpus/core/src/agent/run-store.ts +301 -41
- package/corpus/core/src/client/AgentPanel.tsx +6 -2
- package/corpus/core/src/client/AssistantChat.tsx +364 -69
- package/corpus/core/src/client/agent-chat-adapter.ts +169 -1
- package/corpus/core/src/client/chat/message-components.tsx +3 -0
- package/corpus/core/src/client/chat/tool-call-display.tsx +20 -36
- package/corpus/core/src/client/conversation/use-near-bottom-autoscroll.ts +7 -0
- package/corpus/core/src/client/extensions/AgentNativeExtensionFrame.tsx +2 -0
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +2 -0
- package/corpus/core/src/client/extensions/ExtensionEditor.tsx +9 -2
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +2 -0
- package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +2 -0
- package/corpus/core/src/client/extensions/portable-extension.ts +2 -0
- package/corpus/core/src/client/session-replay.ts +361 -29
- package/corpus/core/src/client/sse-event-processor.ts +43 -1
- package/corpus/core/src/demo/actions/toggle-demo-mode.ts +1 -1
- package/corpus/core/src/demo/config.ts +6 -6
- package/corpus/core/src/demo/fetch-interceptor.ts +13 -4
- package/corpus/core/src/demo/redact.ts +13 -149
- package/corpus/core/src/extensions/html-shell.ts +3 -0
- package/corpus/core/src/extensions/session-replay-iframe.ts +131 -0
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +1 -20
- package/corpus/core/src/session-replay-iframe-protocol.ts +58 -0
- package/corpus/core/src/shared/reasoning-effort.ts +35 -0
- package/corpus/core/src/styles/agent-conversation.css +26 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +30 -21
- package/corpus/templates/analytics/AGENTS.md +12 -0
- package/corpus/templates/analytics/actions/get-error-issue.ts +1 -0
- package/corpus/templates/analytics/actions/get-session-replay-events.ts +1 -0
- package/corpus/templates/analytics/actions/get-session-replay-summary.ts +1 -0
- package/corpus/templates/analytics/actions/list-error-issues.ts +1 -0
- package/corpus/templates/analytics/actions/list-session-recordings.ts +1 -0
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +2 -1
- package/corpus/templates/analytics/app/global.css +2 -2
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +41 -4
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +52 -203
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +34 -12
- package/corpus/templates/analytics/changelog/2026-07-12-analytics-chat-retries-before-showing-a-generic-no-data-mess.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-analytics-sessions-search-no-longer-loses-fast-keystrokes-an.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-chart-selection-respects-chat-state.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-anonymizes-error-reporting-emails.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-replays-show-iframe-content.md +6 -0
- package/corpus/templates/analytics/netlify.toml +0 -3
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +14 -0
- package/corpus/templates/analytics/server/lib/error-capture.ts +59 -2
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +24 -0
- package/corpus/templates/analytics/server/lib/session-replay.ts +2 -9
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +39 -6
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/brain/app/global.css +2 -2
- package/corpus/templates/brain/changelog/2026-07-12-fix-long-response-progress.md +6 -0
- package/corpus/templates/forms/app/components/CloudUpgrade.tsx +1 -1
- package/corpus/templates/forms/app/components/ThemeToggle.tsx +22 -6
- package/corpus/templates/forms/app/components/builder/FieldPropertiesPanel.tsx +5 -5
- package/corpus/templates/forms/app/components/builder/FieldRenderer.tsx +3 -3
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +16 -16
- package/corpus/templates/forms/app/global.css +110 -5
- package/corpus/templates/forms/app/pages/AskPage.tsx +3 -3
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +134 -52
- package/corpus/templates/forms/app/pages/FormFillPage.tsx +44 -11
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +42 -24
- package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +28 -15
- package/corpus/templates/forms/app/pages/ResponsesPage.tsx +38 -15
- package/corpus/templates/forms/app/routes/_app.settings.tsx +1 -1
- package/corpus/templates/forms/changelog/2026-07-12-form-builder-surfaces-are-calmer-fields-stay-stable-on-hover.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-12-smoother-more-tactile-controls-throughout-animated-icon-and-.md +6 -0
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +21 -13
- package/corpus/templates/mail/app/components/email/email-iframe-document.ts +18 -0
- package/dist/agent/durable-background.d.ts +10 -10
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +16 -16
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +19 -8
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +11 -3
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/output-tokens.js +6 -6
- package/dist/agent/engine/output-tokens.js.map +1 -1
- package/dist/agent/production-agent.d.ts +52 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +154 -26
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +9 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +71 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +9 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +243 -48
- package/dist/agent/run-store.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +21 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +298 -67
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +146 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +2 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +3 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +13 -37
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts +1 -0
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.js +6 -0
- package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.js +2 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +2 -1
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionEditor.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionEditor.js +5 -2
- package/dist/client/extensions/ExtensionEditor.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +2 -1
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +2 -1
- package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js +2 -0
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +308 -29
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +5 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +37 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/demo/actions/toggle-demo-mode.js +1 -1
- package/dist/demo/actions/toggle-demo-mode.js.map +1 -1
- package/dist/demo/config.js +6 -6
- package/dist/demo/config.js.map +1 -1
- package/dist/demo/fetch-interceptor.d.ts.map +1 -1
- package/dist/demo/fetch-interceptor.js +13 -4
- package/dist/demo/fetch-interceptor.js.map +1 -1
- package/dist/demo/redact.d.ts +7 -7
- package/dist/demo/redact.d.ts.map +1 -1
- package/dist/demo/redact.js +8 -145
- package/dist/demo/redact.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +2 -0
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/extensions/session-replay-iframe.d.ts +10 -0
- package/dist/extensions/session-replay-iframe.d.ts.map +1 -0
- package/dist/extensions/session-replay-iframe.js +121 -0
- package/dist/extensions/session-replay-iframe.js.map +1 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -19
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/session-replay-iframe-protocol.d.ts +36 -0
- package/dist/session-replay-iframe-protocol.d.ts.map +1 -0
- package/dist/session-replay-iframe-protocol.js +24 -0
- package/dist/session-replay-iframe-protocol.js.map +1 -0
- package/dist/shared/reasoning-effort.d.ts +11 -0
- package/dist/shared/reasoning-effort.d.ts.map +1 -1
- package/dist/shared/reasoning-effort.js +36 -0
- package/dist/shared/reasoning-effort.js.map +1 -1
- package/dist/styles/agent-conversation.css +26 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/docs/content/durable-background-runs.mdx +37 -0
- package/docs/content/locales/ar-SA/tracking.mdx +2 -0
- package/docs/content/locales/de-DE/tracking.mdx +2 -0
- package/docs/content/locales/es-ES/tracking.mdx +2 -0
- package/docs/content/locales/fr-FR/tracking.mdx +4 -2
- package/docs/content/locales/hi-IN/tracking.mdx +2 -0
- package/docs/content/locales/ja-JP/tracking.mdx +2 -0
- package/docs/content/locales/ko-KR/tracking.mdx +2 -0
- package/docs/content/locales/pt-BR/tracking.mdx +2 -0
- package/docs/content/locales/zh-CN/tracking.mdx +2 -0
- package/docs/content/locales/zh-TW/durable-background-runs.mdx +14 -0
- package/docs/content/locales/zh-TW/tracking.mdx +2 -0
- package/docs/content/tracking.mdx +2 -0
- package/package.json +2 -2
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +0 -15
- package/corpus/core/src/observability/hosted-model-experiment.ts +0 -118
- package/dist/observability/hosted-model-experiment.d.ts +0 -39
- package/dist/observability/hosted-model-experiment.d.ts.map +0 -1
- package/dist/observability/hosted-model-experiment.js +0 -90
- package/dist/observability/hosted-model-experiment.js.map +0 -1
|
@@ -317,5 +317,26 @@ export declare const CHAT_STORAGE_PREFIX = "agent-chat:";
|
|
|
317
317
|
export declare function clearChatStorage(tabId?: string): void;
|
|
318
318
|
import { extractThreadMeta } from "../agent/thread-data-builder.js";
|
|
319
319
|
export { extractThreadMeta };
|
|
320
|
+
/**
|
|
321
|
+
* Owns the "Resuming…" status shown during the adapter's auto-continuation
|
|
322
|
+
* window — the gap between the end of one serverless chunk and the POST for
|
|
323
|
+
* the next. Set true the moment the adapter dispatches
|
|
324
|
+
* `agent-chat:auto-continue`. Cleared here as soon as the successor chunk
|
|
325
|
+
* produces real output (`agent-chat:stream-progress` — dispatched by the SSE
|
|
326
|
+
* processor for non-empty text/reasoning deltas) or the run is force-stopped;
|
|
327
|
+
* a 30s failsafe timer covers any case neither fires. The caller clears it
|
|
328
|
+
* via the returned `clearAutoResume` for other real-progress signals (tool
|
|
329
|
+
* activity, an accepted run error, an explicit stop) that live outside this
|
|
330
|
+
* hook.
|
|
331
|
+
*
|
|
332
|
+
* Deliberately NOT cleared by `agent-chat:activity-clear` or merely-idle
|
|
333
|
+
* `isRunning`: both also fire for old-chunk `tool_done` replays / server
|
|
334
|
+
* retries, and clearing on those would re-expose terminal message controls
|
|
335
|
+
* during the exact gap this state exists to cover.
|
|
336
|
+
*/
|
|
337
|
+
export declare function useAutoResumeStatus(tabId: string | undefined, forceStopped: boolean): {
|
|
338
|
+
isAutoResuming: boolean;
|
|
339
|
+
clearAutoResume: () => void;
|
|
340
|
+
};
|
|
320
341
|
export declare const AssistantChat: React.ForwardRefExoticComponent<AssistantChatProps & React.RefAttributes<AssistantChatHandle>>;
|
|
321
342
|
//# sourceMappingURL=AssistantChat.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAEV,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { AssistantRuntimeProvider, useLocalRuntime, useThreadRuntime, useThread, useAui, useComposer, useComposerRuntime, useMessageRuntime, ThreadPrimitive, } from "@assistant-ui/react";
|
|
3
3
|
import { CompositeAttachmentAdapter } from "@assistant-ui/react";
|
|
4
|
-
import { IconMessage, IconX, IconPlayerStopFilled, IconTerminal, IconAlertTriangle, IconRefresh, } from "@tabler/icons-react";
|
|
4
|
+
import { IconMessage, IconX, IconPlayerStopFilled, IconTerminal, IconAlertTriangle, IconChevronDown, IconRefresh, } from "@tabler/icons-react";
|
|
5
5
|
import { useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, forwardRef, useImperativeHandle, } from "react";
|
|
6
6
|
import { ACTIVE_RUN_STATE_EVENT, clearActiveRunIfMatches, getActiveRunActivityTool, getActiveRun, resolveReconnectAfterSeq, setActiveRun, updateActiveRunActivity, updateActiveRunSeq, } from "./active-run-state.js";
|
|
7
7
|
import { createAgentChatAdapter, } from "./agent-chat-adapter.js";
|
|
@@ -19,7 +19,7 @@ import { BuilderSetupContent, LoopLimitContinueCard, RunErrorRecoveryCard, PlanM
|
|
|
19
19
|
import { createAgentChatRuntimeAdapter, } from "./chat/runtime.js";
|
|
20
20
|
import { ChatRunningContext, ApprovalContext, ReconnectStreamMessage, } from "./chat/tool-call-display.js";
|
|
21
21
|
import { useReconnectReaderOwner } from "./chat/use-reconnect-reader-owner.js";
|
|
22
|
-
import { MessageScroller,
|
|
22
|
+
import { MessageScroller, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, } from "./components/ui/message-scroller.js";
|
|
23
23
|
import { Popover, PopoverContent, PopoverTrigger, } from "./components/ui/popover.js";
|
|
24
24
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./components/ui/tooltip.js";
|
|
25
25
|
import { AgentComposerFrame } from "./composer/AgentComposerFrame.js";
|
|
@@ -29,6 +29,7 @@ import { PastedTextChip } from "./composer/PastedTextChip.js";
|
|
|
29
29
|
import { appendRealtimeVoiceTranscriptToRepository, realtimeVoiceTranscriptRegistry, } from "./composer/realtime-voice-transcript.js";
|
|
30
30
|
import { TiptapComposer, } from "./composer/TiptapComposer.js";
|
|
31
31
|
import { ContextMeter } from "./context-xray/ContextMeter.js";
|
|
32
|
+
import { useNearBottomAutoscroll } from "./conversation/index.js";
|
|
32
33
|
import { useAgentDynamicSuggestionsResult, } from "./dynamic-suggestions.js";
|
|
33
34
|
import { GuidedQuestionFlow, useGuidedQuestionFlow, } from "./guided-questions.js";
|
|
34
35
|
import { useT } from "./i18n.js";
|
|
@@ -351,6 +352,60 @@ function getMessageText(message) {
|
|
|
351
352
|
}
|
|
352
353
|
return typeof content === "string" ? displayableUserMessageText(content) : "";
|
|
353
354
|
}
|
|
355
|
+
function contentPartFollowKey(part) {
|
|
356
|
+
if (!part || typeof part !== "object")
|
|
357
|
+
return "unknown";
|
|
358
|
+
const candidate = part;
|
|
359
|
+
const type = typeof candidate.type === "string" ? candidate.type : "unknown";
|
|
360
|
+
if (type === "text" || type === "reasoning") {
|
|
361
|
+
return `${type}:${String(candidate.text ?? "").length}`;
|
|
362
|
+
}
|
|
363
|
+
if (type === "tool-call") {
|
|
364
|
+
return [
|
|
365
|
+
type,
|
|
366
|
+
candidate.toolCallId ?? "",
|
|
367
|
+
candidate.toolName ?? "",
|
|
368
|
+
candidate.status?.type ?? "",
|
|
369
|
+
String(candidate.argsText ?? "").length,
|
|
370
|
+
String(candidate.result ?? "").length,
|
|
371
|
+
].join(":");
|
|
372
|
+
}
|
|
373
|
+
if (type === "image")
|
|
374
|
+
return `image:${String(candidate.image ?? "").length}`;
|
|
375
|
+
return `${type}:${String(candidate.text ?? candidate.result ?? "").length}`;
|
|
376
|
+
}
|
|
377
|
+
function contentFollowKey(content) {
|
|
378
|
+
if (typeof content === "string")
|
|
379
|
+
return `text:${content.length}`;
|
|
380
|
+
if (!Array.isArray(content))
|
|
381
|
+
return "";
|
|
382
|
+
return content.map(contentPartFollowKey).join("|");
|
|
383
|
+
}
|
|
384
|
+
function messageFollowKey(message) {
|
|
385
|
+
const candidate = (message?.message ??
|
|
386
|
+
message);
|
|
387
|
+
return [
|
|
388
|
+
candidate.id ?? "",
|
|
389
|
+
candidate.role ?? "",
|
|
390
|
+
candidate.status?.type ?? "",
|
|
391
|
+
candidate.status?.reason ?? "",
|
|
392
|
+
contentFollowKey(candidate.content),
|
|
393
|
+
].join(",");
|
|
394
|
+
}
|
|
395
|
+
function queuedMessageFollowKey(message) {
|
|
396
|
+
return [
|
|
397
|
+
message.id,
|
|
398
|
+
message.text.length,
|
|
399
|
+
message.images?.length ?? 0,
|
|
400
|
+
message.attachments?.length ?? 0,
|
|
401
|
+
message.references?.length ?? 0,
|
|
402
|
+
message.requestMode ?? "",
|
|
403
|
+
message.recoveryAction ?? "",
|
|
404
|
+
].join(":");
|
|
405
|
+
}
|
|
406
|
+
function reconnectContentFollowKey(content) {
|
|
407
|
+
return content.map(contentPartFollowKey).join("|");
|
|
408
|
+
}
|
|
354
409
|
export function reconnectActivityFallbackContent(toolName) {
|
|
355
410
|
const tool = toolName?.trim();
|
|
356
411
|
if (!tool)
|
|
@@ -523,6 +578,75 @@ function latestRenderedAssistantText(messages) {
|
|
|
523
578
|
return "";
|
|
524
579
|
return assistantTextFromContent(latestMessage.content);
|
|
525
580
|
}
|
|
581
|
+
function latestRenderedAssistantReasoning(messages) {
|
|
582
|
+
const latestEntry = messages.at(-1);
|
|
583
|
+
const latestMessage = getRepoMessage(latestEntry);
|
|
584
|
+
if (latestMessage?.role !== "assistant" ||
|
|
585
|
+
!Array.isArray(latestMessage.content)) {
|
|
586
|
+
return [];
|
|
587
|
+
}
|
|
588
|
+
return latestMessage.content.flatMap((part) => part?.type === "reasoning" &&
|
|
589
|
+
typeof part.text === "string" &&
|
|
590
|
+
part.text.length > 0
|
|
591
|
+
? [part.text]
|
|
592
|
+
: []);
|
|
593
|
+
}
|
|
594
|
+
function trimReconnectReasoningAlreadyRendered(content, renderedReasoning, options) {
|
|
595
|
+
if (renderedReasoning.length === 0)
|
|
596
|
+
return content;
|
|
597
|
+
const firstReconnectReasoning = content.find((part) => part.type === "reasoning" && part.text.length > 0)?.text;
|
|
598
|
+
let renderedOffset = 0;
|
|
599
|
+
if (options?.trimTailOverlap && firstReconnectReasoning) {
|
|
600
|
+
for (let index = renderedReasoning.length - 1; index >= 0; index -= 1) {
|
|
601
|
+
const rendered = renderedReasoning[index];
|
|
602
|
+
if (rendered === firstReconnectReasoning ||
|
|
603
|
+
rendered.startsWith(firstReconnectReasoning) ||
|
|
604
|
+
firstReconnectReasoning.startsWith(rendered) ||
|
|
605
|
+
longestSuffixPrefixOverlap(rendered, firstReconnectReasoning) > 0) {
|
|
606
|
+
renderedOffset = index;
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
let reasoningIndex = 0;
|
|
612
|
+
let changed = false;
|
|
613
|
+
const next = [];
|
|
614
|
+
for (const part of content) {
|
|
615
|
+
if (part.type !== "reasoning") {
|
|
616
|
+
next.push(part);
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
const rendered = renderedReasoning[renderedOffset + reasoningIndex];
|
|
620
|
+
reasoningIndex += 1;
|
|
621
|
+
if (!rendered) {
|
|
622
|
+
next.push(part);
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
if (rendered === part.text || rendered.startsWith(part.text)) {
|
|
626
|
+
changed = true;
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
if (part.text.startsWith(rendered)) {
|
|
630
|
+
const tail = part.text.slice(rendered.length);
|
|
631
|
+
if (tail)
|
|
632
|
+
next.push({ ...part, text: tail });
|
|
633
|
+
changed = true;
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
if (options?.trimTailOverlap) {
|
|
637
|
+
const overlap = longestSuffixPrefixOverlap(rendered, part.text);
|
|
638
|
+
if (overlap > 0) {
|
|
639
|
+
const tail = part.text.slice(overlap);
|
|
640
|
+
if (tail)
|
|
641
|
+
next.push({ ...part, text: tail });
|
|
642
|
+
changed = true;
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
next.push(part);
|
|
647
|
+
}
|
|
648
|
+
return changed ? next : content;
|
|
649
|
+
}
|
|
526
650
|
function dedupePendingToolCallReplaysWithinContent(content) {
|
|
527
651
|
const laterStatesByFingerprint = new Map();
|
|
528
652
|
let changed = false;
|
|
@@ -673,10 +797,12 @@ export function dedupeReconnectContentAgainstMessages(content, messages, options
|
|
|
673
797
|
return changed ? snapshotDeduped : content;
|
|
674
798
|
const { byId, latestAssistantByFingerprint, latestAssistantByName } = collectRenderedToolCallStates(messages);
|
|
675
799
|
const renderedAssistantText = latestRenderedAssistantText(messages);
|
|
800
|
+
const renderedAssistantReasoning = latestRenderedAssistantReasoning(messages);
|
|
676
801
|
if (byId.size === 0 &&
|
|
677
802
|
latestAssistantByFingerprint.size === 0 &&
|
|
678
803
|
latestAssistantByName.size === 0 &&
|
|
679
|
-
!renderedAssistantText
|
|
804
|
+
!renderedAssistantText &&
|
|
805
|
+
renderedAssistantReasoning.length === 0) {
|
|
680
806
|
return changed ? snapshotDeduped : content;
|
|
681
807
|
}
|
|
682
808
|
const filtered = byId.size > 0 ||
|
|
@@ -776,8 +902,11 @@ export function dedupeReconnectContentAgainstMessages(content, messages, options
|
|
|
776
902
|
return true;
|
|
777
903
|
})
|
|
778
904
|
: snapshotDeduped;
|
|
779
|
-
const
|
|
780
|
-
if (
|
|
905
|
+
const reasoningDeduped = trimReconnectReasoningAlreadyRendered(filtered, renderedAssistantReasoning, { trimTailOverlap: options?.trimTailTextOverlap });
|
|
906
|
+
if (reasoningDeduped !== filtered)
|
|
907
|
+
changed = true;
|
|
908
|
+
const textDeduped = trimReconnectTextAlreadyRendered(reasoningDeduped, renderedAssistantText, { trimTailOverlap: options?.trimTailTextOverlap });
|
|
909
|
+
if (textDeduped !== reasoningDeduped)
|
|
781
910
|
changed = true;
|
|
782
911
|
return changed ? textDeduped : content;
|
|
783
912
|
}
|
|
@@ -897,7 +1026,7 @@ function AssistantChatUserMessageItem() {
|
|
|
897
1026
|
const message = messageRuntime.getState();
|
|
898
1027
|
if (isHiddenUserMessage(message))
|
|
899
1028
|
return null;
|
|
900
|
-
return (_jsx(MessageScrollerItem, { messageId: message.id,
|
|
1029
|
+
return (_jsx(MessageScrollerItem, { messageId: message.id, children: _jsx(UserMessage, {}) }));
|
|
901
1030
|
}
|
|
902
1031
|
function AssistantChatAssistantMessageItem() {
|
|
903
1032
|
const messageRuntime = useMessageRuntime();
|
|
@@ -1063,6 +1192,79 @@ function stripBase64FromRepo(repo) {
|
|
|
1063
1192
|
});
|
|
1064
1193
|
return { ...r, messages };
|
|
1065
1194
|
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Owns the "Resuming…" status shown during the adapter's auto-continuation
|
|
1197
|
+
* window — the gap between the end of one serverless chunk and the POST for
|
|
1198
|
+
* the next. Set true the moment the adapter dispatches
|
|
1199
|
+
* `agent-chat:auto-continue`. Cleared here as soon as the successor chunk
|
|
1200
|
+
* produces real output (`agent-chat:stream-progress` — dispatched by the SSE
|
|
1201
|
+
* processor for non-empty text/reasoning deltas) or the run is force-stopped;
|
|
1202
|
+
* a 30s failsafe timer covers any case neither fires. The caller clears it
|
|
1203
|
+
* via the returned `clearAutoResume` for other real-progress signals (tool
|
|
1204
|
+
* activity, an accepted run error, an explicit stop) that live outside this
|
|
1205
|
+
* hook.
|
|
1206
|
+
*
|
|
1207
|
+
* Deliberately NOT cleared by `agent-chat:activity-clear` or merely-idle
|
|
1208
|
+
* `isRunning`: both also fire for old-chunk `tool_done` replays / server
|
|
1209
|
+
* retries, and clearing on those would re-expose terminal message controls
|
|
1210
|
+
* during the exact gap this state exists to cover.
|
|
1211
|
+
*/
|
|
1212
|
+
export function useAutoResumeStatus(tabId, forceStopped) {
|
|
1213
|
+
const [isAutoResuming, setIsAutoResuming] = useState(false);
|
|
1214
|
+
const autoResumeTimerRef = useRef(null);
|
|
1215
|
+
const clearAutoResume = useCallback(() => {
|
|
1216
|
+
if (autoResumeTimerRef.current !== null) {
|
|
1217
|
+
window.clearTimeout(autoResumeTimerRef.current);
|
|
1218
|
+
autoResumeTimerRef.current = null;
|
|
1219
|
+
}
|
|
1220
|
+
setIsAutoResuming(false);
|
|
1221
|
+
}, []);
|
|
1222
|
+
useEffect(() => {
|
|
1223
|
+
const handler = (e) => {
|
|
1224
|
+
const detail = e.detail;
|
|
1225
|
+
if (tabId && detail?.tabId && detail.tabId !== tabId)
|
|
1226
|
+
return;
|
|
1227
|
+
if (autoResumeTimerRef.current !== null) {
|
|
1228
|
+
window.clearTimeout(autoResumeTimerRef.current);
|
|
1229
|
+
}
|
|
1230
|
+
setIsAutoResuming(true);
|
|
1231
|
+
autoResumeTimerRef.current = window.setTimeout(() => {
|
|
1232
|
+
autoResumeTimerRef.current = null;
|
|
1233
|
+
setIsAutoResuming(false);
|
|
1234
|
+
}, AUTO_RESUME_STATUS_TIMEOUT_MS);
|
|
1235
|
+
};
|
|
1236
|
+
window.addEventListener("agent-chat:auto-continue", handler);
|
|
1237
|
+
return () => {
|
|
1238
|
+
if (autoResumeTimerRef.current !== null) {
|
|
1239
|
+
window.clearTimeout(autoResumeTimerRef.current);
|
|
1240
|
+
autoResumeTimerRef.current = null;
|
|
1241
|
+
}
|
|
1242
|
+
window.removeEventListener("agent-chat:auto-continue", handler);
|
|
1243
|
+
};
|
|
1244
|
+
}, [tabId]);
|
|
1245
|
+
// Real forward progress in the current chunk (visible text or reasoning
|
|
1246
|
+
// deltas) means the run is not stuck between chunks — clear the indicator
|
|
1247
|
+
// immediately rather than waiting on the 30s failsafe. This is the
|
|
1248
|
+
// plain-text-continuation case: no tool call fires `agent-chat:activity`
|
|
1249
|
+
// to clear it, so without this listener "Resuming" would linger for up to
|
|
1250
|
+
// AUTO_RESUME_STATUS_TIMEOUT_MS after the run already resumed or finished.
|
|
1251
|
+
useEffect(() => {
|
|
1252
|
+
const handler = (e) => {
|
|
1253
|
+
const detail = e.detail;
|
|
1254
|
+
if (tabId && detail?.tabId && detail.tabId !== tabId)
|
|
1255
|
+
return;
|
|
1256
|
+
clearAutoResume();
|
|
1257
|
+
};
|
|
1258
|
+
window.addEventListener("agent-chat:stream-progress", handler);
|
|
1259
|
+
return () => window.removeEventListener("agent-chat:stream-progress", handler);
|
|
1260
|
+
}, [clearAutoResume, tabId]);
|
|
1261
|
+
useEffect(() => {
|
|
1262
|
+
if (forceStopped) {
|
|
1263
|
+
clearAutoResume();
|
|
1264
|
+
}
|
|
1265
|
+
}, [clearAutoResume, forceStopped]);
|
|
1266
|
+
return { isAutoResuming, clearAutoResume };
|
|
1267
|
+
}
|
|
1066
1268
|
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, onSlashCommand, execMode, onExecModeChange, approvalActions, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEffort, availableModels, onModelChange, onEffortChange, imageModelMenu, onForkChat, onConnectProvider, plusMenuMode = "full", providerStatusChecksEnabled = true, loadHistoryRepository, historyReloadKey, externalStreaming = false, }, ref) {
|
|
1067
1269
|
const thread = useThread();
|
|
1068
1270
|
const threadRuntime = useThreadRuntime();
|
|
@@ -1329,15 +1531,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1329
1531
|
const [dismissedRunErrorKey, setDismissedRunErrorKey] = useState(null);
|
|
1330
1532
|
const userStoppedRunRef = useRef(null);
|
|
1331
1533
|
const [isReconnecting, setIsReconnecting] = useState(false);
|
|
1332
|
-
// True during the 250ms continuation window and startup of the next chunk
|
|
1333
|
-
// (adapter's auto-continue delay before POSTing the next chunk).
|
|
1334
|
-
const [isAutoResuming, setIsAutoResuming] = useState(false);
|
|
1335
|
-
// Latest-value ref for the same single-reader checks as isRuntimeRunningRef:
|
|
1336
|
-
// during an adapter auto-continuation the runtime can flick false between
|
|
1337
|
-
// chunks while the adapter is still driving the turn.
|
|
1338
|
-
const isAutoResumingRef = useRef(isAutoResuming);
|
|
1339
|
-
isAutoResumingRef.current = isAutoResuming;
|
|
1340
|
-
const autoResumeTimerRef = useRef(null);
|
|
1341
1534
|
const [optimisticRunning, setOptimisticRunning] = useState(false);
|
|
1342
1535
|
const [runningActivityLabel, setRunningActivityLabel] = useState(null);
|
|
1343
1536
|
const [runningActivityTool, setRunningActivityTool] = useState(null);
|
|
@@ -1376,6 +1569,14 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1376
1569
|
// queueing forever" state where isReconnecting or isRuntimeRunning gets
|
|
1377
1570
|
// wedged (e.g. after a tab refresh + stop during reconnect).
|
|
1378
1571
|
const [forceStopped, setForceStopped] = useState(false);
|
|
1572
|
+
// True during the 250ms continuation window and startup of the next chunk
|
|
1573
|
+
// (adapter's auto-continue delay before POSTing the next chunk).
|
|
1574
|
+
const { isAutoResuming, clearAutoResume } = useAutoResumeStatus(tabId, forceStopped);
|
|
1575
|
+
// Latest-value ref for the same single-reader checks as isRuntimeRunningRef:
|
|
1576
|
+
// during an adapter auto-continuation the runtime can flick false between
|
|
1577
|
+
// chunks while the adapter is still driving the turn.
|
|
1578
|
+
const isAutoResumingRef = useRef(isAutoResuming);
|
|
1579
|
+
isAutoResumingRef.current = isAutoResuming;
|
|
1379
1580
|
const [hasActiveServerRun, setHasActiveServerRun] = useState(() => activeRunMatchesThread(getActiveRun(), threadId));
|
|
1380
1581
|
useEffect(() => {
|
|
1381
1582
|
const syncActiveRun = (state = getActiveRun()) => {
|
|
@@ -1430,6 +1631,10 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
1430
1631
|
// Stable ref to the "stop active run" action so addToQueue can abort
|
|
1431
1632
|
// a running turn without adding many unstable closure deps to its dep list.
|
|
1432
1633
|
const stopActiveRunRef = useRef(() => { });
|
|
1634
|
+
// addToQueue is declared before the autoscroll hook because it also feeds
|
|
1635
|
+
// the reconnect/imperative APIs. Keep a stable bridge so an accepted visible
|
|
1636
|
+
// submit can explicitly reattach bottom-following without closure churn.
|
|
1637
|
+
const resumeFollowingRef = useRef(() => { });
|
|
1433
1638
|
const markOptimisticRunning = useCallback(() => {
|
|
1434
1639
|
setOptimisticRunning(true);
|
|
1435
1640
|
if (typeof window === "undefined")
|
|
@@ -2585,10 +2790,13 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2585
2790
|
...(detail.recoverable ? { recoverable: detail.recoverable } : {}),
|
|
2586
2791
|
});
|
|
2587
2792
|
setDismissedRunErrorKey(null);
|
|
2793
|
+
// An errored continuation must not keep showing "Resuming" — there is
|
|
2794
|
+
// no further chunk coming to clear it.
|
|
2795
|
+
clearAutoResume();
|
|
2588
2796
|
};
|
|
2589
2797
|
window.addEventListener("agent-chat:run-error", handler);
|
|
2590
2798
|
return () => window.removeEventListener("agent-chat:run-error", handler);
|
|
2591
|
-
}, [latestAssistantRunId, tabId, threadId]);
|
|
2799
|
+
}, [clearAutoResume, latestAssistantRunId, tabId, threadId]);
|
|
2592
2800
|
// Real activity means the next chunk has started. Surface longer-lived
|
|
2593
2801
|
// activity such as "Still generating image" so active-run reconnects do not
|
|
2594
2802
|
// look like failures while the server is still making progress.
|
|
@@ -2601,7 +2809,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2601
2809
|
if (!label)
|
|
2602
2810
|
return;
|
|
2603
2811
|
const tool = typeof detail?.tool === "string" ? detail.tool.trim() : "";
|
|
2604
|
-
|
|
2812
|
+
clearAutoResume();
|
|
2605
2813
|
setRunningActivityTool(tool || null);
|
|
2606
2814
|
updateActiveRunActivity(tool || null);
|
|
2607
2815
|
latestActivityLabelRef.current = label;
|
|
@@ -2637,49 +2845,22 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2637
2845
|
window.removeEventListener("agent-chat:activity", handler);
|
|
2638
2846
|
window.removeEventListener("agent-chat:activity-clear", clear);
|
|
2639
2847
|
};
|
|
2640
|
-
}, [resetRunningActivity, tabId]);
|
|
2641
|
-
//
|
|
2642
|
-
//
|
|
2643
|
-
// next
|
|
2848
|
+
}, [clearAutoResume, resetRunningActivity, tabId]);
|
|
2849
|
+
// "Resuming…" itself (auto-continue → stream-progress/forceStopped clear,
|
|
2850
|
+
// plus the 30s failsafe) is owned by useAutoResumeStatus above. Real
|
|
2851
|
+
// next-chunk activity (tool start/activity events) clears it in the
|
|
2852
|
+
// activity handler above; real streamed output (text/reasoning) clears it
|
|
2853
|
+
// via that hook's own stream-progress listener. This effect only handles
|
|
2854
|
+
// the running-activity reset once both running signals go idle — it does
|
|
2855
|
+
// NOT clear auto-resume merely because `isRunning` is still true: the
|
|
2856
|
+
// adapter dispatches auto-continue before the old chunk's runtime flips
|
|
2857
|
+
// idle, so doing that would expose terminal message controls during the
|
|
2858
|
+
// exact gap this state is meant to cover.
|
|
2644
2859
|
useEffect(() => {
|
|
2645
|
-
const handler = (e) => {
|
|
2646
|
-
const detail = e.detail;
|
|
2647
|
-
if (tabId && detail?.tabId && detail.tabId !== tabId)
|
|
2648
|
-
return;
|
|
2649
|
-
if (autoResumeTimerRef.current !== null) {
|
|
2650
|
-
window.clearTimeout(autoResumeTimerRef.current);
|
|
2651
|
-
}
|
|
2652
|
-
setIsAutoResuming(true);
|
|
2653
|
-
autoResumeTimerRef.current = window.setTimeout(() => {
|
|
2654
|
-
autoResumeTimerRef.current = null;
|
|
2655
|
-
setIsAutoResuming(false);
|
|
2656
|
-
}, AUTO_RESUME_STATUS_TIMEOUT_MS);
|
|
2657
|
-
};
|
|
2658
|
-
window.addEventListener("agent-chat:auto-continue", handler);
|
|
2659
|
-
return () => {
|
|
2660
|
-
if (autoResumeTimerRef.current !== null) {
|
|
2661
|
-
window.clearTimeout(autoResumeTimerRef.current);
|
|
2662
|
-
autoResumeTimerRef.current = null;
|
|
2663
|
-
}
|
|
2664
|
-
window.removeEventListener("agent-chat:auto-continue", handler);
|
|
2665
|
-
};
|
|
2666
|
-
}, [tabId]);
|
|
2667
|
-
// Clear auto-resume once the next chunk has visibly started or the user stops.
|
|
2668
|
-
// Do not clear solely because `isRunning` is false: auto-resume intentionally
|
|
2669
|
-
// covers that between-chunk gap so the chat never looks idle while work is
|
|
2670
|
-
// still scheduled.
|
|
2671
|
-
useEffect(() => {
|
|
2672
|
-
if (isRunning || forceStopped) {
|
|
2673
|
-
if (autoResumeTimerRef.current !== null) {
|
|
2674
|
-
window.clearTimeout(autoResumeTimerRef.current);
|
|
2675
|
-
autoResumeTimerRef.current = null;
|
|
2676
|
-
}
|
|
2677
|
-
setIsAutoResuming(false);
|
|
2678
|
-
}
|
|
2679
2860
|
if (!isRunning && !isAutoResuming) {
|
|
2680
2861
|
resetRunningActivity();
|
|
2681
2862
|
}
|
|
2682
|
-
}, [
|
|
2863
|
+
}, [isAutoResuming, isRunning, resetRunningActivity]);
|
|
2683
2864
|
// Auto-dequeue: when the agent is idle, send the next queued message. This
|
|
2684
2865
|
// intentionally does not depend on observing the running -> idle transition:
|
|
2685
2866
|
// restored queues can exist after a reload where this component never saw the
|
|
@@ -2961,11 +3142,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2961
3142
|
setOptimisticRunning(false);
|
|
2962
3143
|
setHasActiveServerRun(false);
|
|
2963
3144
|
setPendingReconnectRecovery(null);
|
|
2964
|
-
|
|
2965
|
-
if (autoResumeTimerRef.current !== null) {
|
|
2966
|
-
window.clearTimeout(autoResumeTimerRef.current);
|
|
2967
|
-
autoResumeTimerRef.current = null;
|
|
2968
|
-
}
|
|
3145
|
+
clearAutoResume();
|
|
2969
3146
|
resetRunningActivity();
|
|
2970
3147
|
if (!options?.preserveQueuedMessages) {
|
|
2971
3148
|
queueStopVersionRef.current += 1;
|
|
@@ -3021,6 +3198,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3021
3198
|
}, [
|
|
3022
3199
|
apiUrl,
|
|
3023
3200
|
applyLocalQueuedMessages,
|
|
3201
|
+
clearAutoResume,
|
|
3024
3202
|
isReconnecting,
|
|
3025
3203
|
resetRunningActivity,
|
|
3026
3204
|
reconnectContent,
|
|
@@ -3052,9 +3230,6 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3052
3230
|
// Selection context attached via Cmd+I is one-shot — clear it as soon
|
|
3053
3231
|
// as the user actually sends a message so it can't be re-used.
|
|
3054
3232
|
clearPendingSelection();
|
|
3055
|
-
// Sending a message is an explicit user action. The scroller anchors the
|
|
3056
|
-
// appended user turn so the new message and reply land in view without
|
|
3057
|
-
// re-pinning the viewport during ordinary streaming.
|
|
3058
3233
|
const submitted = includeComposerContext
|
|
3059
3234
|
? buildComposerContextSubmission(text)
|
|
3060
3235
|
: { text, includesContext: false };
|
|
@@ -3224,6 +3399,11 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3224
3399
|
// intentionally reported before the agent's response resolves: a
|
|
3225
3400
|
// caller like sendToAgentChatAndConfirm only needs to know the submit
|
|
3226
3401
|
// wasn't silently dropped, not whether the run itself later succeeds.
|
|
3402
|
+
// A visible submit is explicit user intent to see the new turn. Reattach
|
|
3403
|
+
// following only after the message was queued/appended successfully;
|
|
3404
|
+
// hidden reconnect recovery turns must leave the user's viewport alone.
|
|
3405
|
+
if (!hideUserMessage)
|
|
3406
|
+
resumeFollowingRef.current();
|
|
3227
3407
|
reportAgentChatSubmitResult(submitMessageId, true);
|
|
3228
3408
|
if (submitted.includesContext) {
|
|
3229
3409
|
updateComposerContextItems(() => []);
|
|
@@ -3326,6 +3506,53 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3326
3506
|
suppressToolRepeats: adapterHandoffPending,
|
|
3327
3507
|
trimTailTextOverlap: adapterHandoffPending || reconnectTailOnlyRef.current,
|
|
3328
3508
|
});
|
|
3509
|
+
const autoscrollFollowKey = [
|
|
3510
|
+
messages.map(messageFollowKey).join(";"),
|
|
3511
|
+
`q:${queuedMessages.map(queuedMessageFollowKey).join("|")}`,
|
|
3512
|
+
`r:${reconnectContentFollowKey(visibleReconnectContent)}`,
|
|
3513
|
+
`status:${showRunningInUI ? runningStatusLabel : "idle"}`,
|
|
3514
|
+
].join(";;");
|
|
3515
|
+
const { scrollRef, isNearBottomRef, showScrollToBottom, scrollToBottom, scrollToBottomAfterPaint, resumeFollowing, } = useNearBottomAutoscroll({
|
|
3516
|
+
followKey: autoscrollFollowKey,
|
|
3517
|
+
streaming: textStreaming,
|
|
3518
|
+
});
|
|
3519
|
+
resumeFollowingRef.current = resumeFollowing;
|
|
3520
|
+
const scrollToBottomWhileLayoutSettles = useCallback(() => {
|
|
3521
|
+
scrollToBottomAfterPaint();
|
|
3522
|
+
const element = scrollRef.current;
|
|
3523
|
+
if (!element || typeof ResizeObserver === "undefined")
|
|
3524
|
+
return undefined;
|
|
3525
|
+
let stopped = false;
|
|
3526
|
+
const observer = new ResizeObserver(() => {
|
|
3527
|
+
if (!stopped && isNearBottomRef.current)
|
|
3528
|
+
scrollToBottom();
|
|
3529
|
+
});
|
|
3530
|
+
observer.observe(element);
|
|
3531
|
+
const timeout = window.setTimeout(() => {
|
|
3532
|
+
stopped = true;
|
|
3533
|
+
observer.disconnect();
|
|
3534
|
+
if (isNearBottomRef.current)
|
|
3535
|
+
scrollToBottom();
|
|
3536
|
+
}, 1600);
|
|
3537
|
+
return () => {
|
|
3538
|
+
stopped = true;
|
|
3539
|
+
window.clearTimeout(timeout);
|
|
3540
|
+
observer.disconnect();
|
|
3541
|
+
};
|
|
3542
|
+
}, [isNearBottomRef, scrollRef, scrollToBottom, scrollToBottomAfterPaint]);
|
|
3543
|
+
const wasRestoringRef = useRef(isRestoring);
|
|
3544
|
+
useEffect(() => {
|
|
3545
|
+
const wasRestoring = wasRestoringRef.current;
|
|
3546
|
+
wasRestoringRef.current = isRestoring;
|
|
3547
|
+
if (wasRestoring && !isRestoring) {
|
|
3548
|
+
return scrollToBottomWhileLayoutSettles();
|
|
3549
|
+
}
|
|
3550
|
+
}, [isRestoring, scrollToBottomWhileLayoutSettles]);
|
|
3551
|
+
useEffect(() => {
|
|
3552
|
+
if (!textStreaming && isNearBottomRef.current) {
|
|
3553
|
+
scrollToBottomAfterPaint();
|
|
3554
|
+
}
|
|
3555
|
+
}, [isNearBottomRef, scrollToBottomAfterPaint, textStreaming]);
|
|
3329
3556
|
const chatScrollResetKey = `${tabId ?? ""}:${threadId ?? ""}`;
|
|
3330
3557
|
const { isDevMode: cpDevMode } = useDevMode(apiUrl);
|
|
3331
3558
|
const checkpointCtx = useMemo(() => ({ apiUrl, devMode: cpDevMode, threadId }), [apiUrl, cpDevMode, threadId]);
|
|
@@ -3438,6 +3665,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3438
3665
|
showComposerSlot ||
|
|
3439
3666
|
showCenteredEmptyThreadFooterSlot ||
|
|
3440
3667
|
(guidedQuestions && guidedQuestions.length > 0) ||
|
|
3668
|
+
showScrollToBottom ||
|
|
3441
3669
|
composerContextItems.length > 0 ||
|
|
3442
3670
|
showPlanModeCallout);
|
|
3443
3671
|
// Human-in-the-loop approvals: when the user approves a paused `needsApproval`
|
|
@@ -3471,7 +3699,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3471
3699
|
? "centered"
|
|
3472
3700
|
: compactMissingKeyEmptyState
|
|
3473
3701
|
? "compact-setup"
|
|
3474
|
-
: 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: "Drop to attach" }) })), 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": "Switch to CLI", 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: "Switch to CLI" })] }) })) })] })), _jsx(MessageScrollerProvider, { autoScroll:
|
|
3702
|
+
: 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: "Drop to attach" }) })), 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": "Switch to CLI", 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: "Switch to CLI" })] }) })) })] })), _jsx(MessageScrollerProvider, { autoScroll: false, children: _jsxs(MessageScroller, { className: "agent-chat-scroll", children: [_jsx(MessageScrollerViewport, { ref: scrollRef, 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
|
|
3475
3703
|
? "Chat session needs refresh"
|
|
3476
3704
|
: authError.sessionExpired
|
|
3477
3705
|
? "Session expired"
|
|
@@ -3542,8 +3770,11 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
3542
3770
|
.filter((msg) => !msg.hideUserMessage)
|
|
3543
3771
|
.map((msg) => {
|
|
3544
3772
|
const displayText = displayableUserMessageText(msg.text);
|
|
3545
|
-
return (_jsx(MessageScrollerItem, { messageId: msg.id,
|
|
3546
|
-
}), resolvedThreadFooterSlot ? (_jsx(MessageScrollerItem, { children: _jsx("div", { className: "agent-thread-footer-slot", children: resolvedThreadFooterSlot }) })) : null] })) }), !authError &&
|
|
3773
|
+
return (_jsx(MessageScrollerItem, { messageId: msg.id, children: _jsxs("div", { className: "group flex items-start justify-end gap-1.5", children: [_jsx("button", { type: "button", onClick: () => applyLocalQueuedMessages((prev) => prev.filter((m) => m.id !== msg.id)), "aria-label": "Remove from queue", className: "mt-1.5 flex h-5 w-5 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, msg.images && msg.images.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: msg.images.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) }))] })] }) }, msg.id));
|
|
3774
|
+
}), resolvedThreadFooterSlot ? (_jsx(MessageScrollerItem, { children: _jsx("div", { className: "agent-thread-footer-slot", children: resolvedThreadFooterSlot }) })) : null] })) }), !authError &&
|
|
3775
|
+
!isRestoring &&
|
|
3776
|
+
!showEmptyState &&
|
|
3777
|
+
showScrollToBottom ? (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { type: "button", onClick: scrollToBottom, className: "flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "aria-label": "Scroll to bottom", children: _jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) }) })) : null] }) }, chatScrollResetKey), showComposerSlot ? composerSlot : null, 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
|
|
3547
3778
|
? { title: guidedQuestionsTitle }
|
|
3548
3779
|
: {}), ...(guidedQuestionsDescription
|
|
3549
3780
|
? { description: guidedQuestionsDescription }
|