@circuitwall/jarela 2.3.0 → 2.5.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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +5 -5
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +14 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +16 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/access/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +27 -33
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +9 -2
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js +19 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/events/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/health/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/packages/route.js +28 -4
- package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +27 -12
- package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/profile/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +585 -58
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/state/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +12 -6
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +125 -26
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +1 -2
- package/.next/standalone/.next/server/app/api/v1/threads/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/tools/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +1 -1
- package/.next/standalone/.next/server/app/api/v1/watchers/route.js +1 -1
- package/.next/standalone/.next/server/app/page.js +27323 -27034
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup/page.js +8 -0
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +5 -5
- package/.next/standalone/.next/server/chunks/1388.js +106 -36
- package/.next/standalone/.next/server/chunks/2068.js +47 -10
- package/.next/standalone/.next/server/chunks/210.js +6 -6
- package/.next/standalone/.next/server/chunks/2447.js +10 -5
- package/.next/standalone/.next/server/chunks/2653.js +80 -1
- package/.next/standalone/.next/server/chunks/3042.js +10 -8
- package/.next/standalone/.next/server/chunks/{4540.js → 309.js} +104 -38
- package/.next/standalone/.next/server/chunks/{2350.js → 3272.js} +104 -37
- package/.next/standalone/.next/server/chunks/3524.js +150 -67
- package/.next/standalone/.next/server/chunks/3566.js +1 -1
- package/.next/standalone/.next/server/chunks/4189.js +1 -1
- package/.next/standalone/.next/server/chunks/4596.js +28 -4
- package/.next/standalone/.next/server/chunks/46.js +91 -31
- package/.next/standalone/.next/server/chunks/466.js +53 -7
- package/.next/standalone/.next/server/chunks/4955.js +30 -3
- package/.next/standalone/.next/server/chunks/5585.js +28 -4
- package/.next/standalone/.next/server/chunks/5908.js +63 -42
- package/.next/standalone/.next/server/chunks/6142.js +10 -2
- package/.next/standalone/.next/server/chunks/8461.js +10 -8
- package/.next/standalone/.next/server/chunks/9032.js +5 -5
- package/.next/standalone/.next/server/chunks/9164.js +487 -177
- package/.next/standalone/.next/server/chunks/9304.js +51 -12
- package/.next/standalone/.next/server/chunks/{423.js → 9590.js} +84 -24
- package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
- package/.next/standalone/.next/server/middleware.js +89 -21
- package/.next/standalone/.next/server/pages/404.html +14 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{1395-e4a99912b8f83044.js → 1395-bfe1f3ef760c0f50.js} +54 -8
- package/.next/standalone/.next/static/chunks/app/{layout-9bc0b10127cb7d42.js → layout-7b24ad13faa3944b.js} +69 -2
- package/.next/standalone/.next/static/chunks/app/{page-213a623b37226452.js → page-2ef8d75d40eb4311.js} +10643 -10295
- package/.next/standalone/.next/static/css/c160ea862133acd2.css +5 -0
- package/.next/standalone/docs/adoption/changesets.json +2805 -0
- package/.next/standalone/package.json +1 -1
- package/CHANGELOG.md +52 -0
- package/api/client.models.test.ts +10 -0
- package/api/client.startup.test.ts +129 -0
- package/api/client.ts +51 -9
- package/api/thread-metadata.test.ts +72 -0
- package/api/types.ts +6 -3
- package/app/api/v1/providers/[provider]/models/route.test.ts +216 -6
- package/app/api/v1/providers/[provider]/models/route.ts +259 -40
- package/app/api/v1/threads/[thread_id]/route.ts +26 -23
- package/app/api/v1/threads/[thread_id]/run/route.ts +0 -1
- package/app/globals.css +119 -29
- package/app/layout.tsx +12 -0
- package/components/agents/AgentsPanel.tsx +5 -13
- package/components/chat/ChatView.tsx +9 -18
- package/components/chat/InputBar.tsx +1 -1
- package/components/chat/MessageBubble.tsx +13 -1
- package/components/chat/MessageList.test.tsx +45 -4
- package/components/chat/MessageList.tsx +123 -89
- package/components/chat/ToolList.tsx +88 -84
- package/components/chat/useThreadActivity.test.tsx +2 -2
- package/components/chat/useThreadActivity.ts +2 -2
- package/components/chat/useThreadData.ts +1 -30
- package/components/chat/useThreadMetadataPolling.test.tsx +128 -0
- package/components/chat/useThreadMetadataPolling.ts +50 -0
- package/components/chat/useUserProfileAndAgent.test.tsx +31 -0
- package/components/chat/useUserProfileAndAgent.ts +13 -2
- package/components/dashboard/DashboardPanel.tsx +1 -1
- package/components/dashboard/Series.tsx +34 -21
- package/components/dashboard/SummaryCards.tsx +1 -1
- package/components/integrations/NetworkSection.tsx +2 -2
- package/components/layout/AppShell.tsx +22 -7
- package/components/layout/MenuPanel.tsx +14 -24
- package/components/profile/ProfilePanel.tsx +2 -2
- package/components/settings/AppearancePanel.tsx +70 -3
- package/components/settings/SettingsPanel.tsx +2 -2
- package/components/tools/ToolsPanel.tsx +2 -7
- package/components/ui/AppearancePreferences.test.tsx +68 -0
- package/components/ui/BootScreen.test.tsx +44 -0
- package/components/ui/BootScreen.tsx +24 -11
- package/components/ui/NotificationStatus.test.tsx +2 -2
- package/components/ui/NotificationStatus.tsx +5 -5
- package/components/ui/SubTabBar.tsx +2 -3
- package/contexts/ThemeContext.tsx +84 -1
- package/hooks/useAgentSession.test.ts +12 -1
- package/hooks/useAgentSession.ts +6 -4
- package/hooks/useUrlSync.test.ts +13 -0
- package/hooks/useUrlSync.ts +0 -4
- package/lib/agents/citation-checker.test.ts +40 -2
- package/lib/agents/citation-checker.ts +56 -11
- package/lib/agents/context-boundary.ts +5 -6
- package/lib/agents/instruction-edits.test.ts +120 -0
- package/lib/agents/instruction-edits.ts +65 -42
- package/lib/agents/prepare/request.ts +0 -2
- package/lib/agents/prepare/system-prompt.test.ts +10 -0
- package/lib/agents/prepare/system-prompt.ts +8 -2
- package/lib/agents/proposals.test.ts +76 -0
- package/lib/agents/proposals.ts +13 -5
- package/lib/agents/run-thread.auto-boundary.test.ts +125 -5
- package/lib/agents/run-thread.ts +24 -9
- package/lib/agents/sqlite-checkpoint-saver.test.ts +91 -0
- package/lib/agents/warm-summary-background.ts +22 -2
- package/lib/agents/warm-topics.test.ts +155 -1
- package/lib/agents/warm-topics.ts +27 -7
- package/lib/bridges/dispatcher.ts +1 -0
- package/lib/bridges/message-role.test.ts +81 -0
- package/lib/bridges/message-role.ts +23 -10
- package/lib/bridges/types.ts +6 -0
- package/lib/bridges/whatsapp-link.test.ts +32 -0
- package/lib/bridges/whatsapp-link.ts +21 -0
- package/lib/bridges/whatsapp.inbound.test.ts +239 -0
- package/lib/bridges/whatsapp.sender.test.ts +80 -1
- package/lib/bridges/whatsapp.ts +76 -38
- package/lib/db/migrations.test.ts +61 -0
- package/lib/db/migrations.ts +13 -0
- package/lib/embeddings/performance.test.ts +114 -0
- package/lib/pricing/snapshot.test.ts +70 -0
- package/lib/pricing/snapshot.ts +10 -2
- package/lib/proxy/dispatcher.test.ts +119 -1
- package/lib/proxy/dispatcher.ts +22 -9
- package/lib/stores/agent-configs.ts +10 -5
- package/lib/stores/bridges.test.ts +81 -0
- package/lib/stores/bridges.ts +9 -8
- package/lib/stores/dashboard-metrics-cache.test.ts +99 -0
- package/lib/stores/dashboard-metrics.ts +30 -4
- package/lib/stores/message-embedding-jobs.test.ts +27 -0
- package/lib/stores/message-embedding-jobs.ts +5 -3
- package/lib/stores/message-usage.test.ts +21 -1
- package/lib/stores/pricing-cache.test.ts +31 -0
- package/lib/stores/pricing.ts +3 -0
- package/lib/stores/proxy-config.test.ts +120 -0
- package/lib/stores/proxy-config.ts +22 -4
- package/lib/stores/threads.ts +12 -8
- package/lib/tools/communications/calendar.test.ts +43 -2
- package/lib/tools/communications/calendar.ts +2 -0
- package/lib/tools/communications/gmail.test.ts +51 -1
- package/lib/tools/communications/gmail.ts +44 -2
- package/lib/tools/communications/outlook-calendar.ts +2 -0
- package/lib/tools/communications/outlook.test.ts +33 -2
- package/lib/tools/communications/outlook.ts +2 -0
- package/lib/tools/filesystem/edit-match.test.ts +133 -0
- package/lib/tools/filesystem/edit-match.ts +7 -2
- package/lib/tools/packages/default-packages.test.ts +21 -0
- package/lib/tools/packages/optional-package.test.ts +72 -0
- package/lib/tools/packages/optional-package.ts +33 -4
- package/lib/tools/support/result-refs.test.ts +131 -0
- package/lib/tools/support/result-refs.ts +41 -9
- package/lib/ui/navigate.test.ts +13 -0
- package/lib/ui/navigate.ts +10 -2
- package/lib/utils/source-link.test.ts +51 -0
- package/lib/utils/source-link.ts +45 -0
- package/package.json +1 -1
- package/.next/standalone/.next/static/css/312542a5725ba0d5.css +0 -5
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → 544OFJV-q0RC6Gjgje4LT}/_ssgManifest.js +0 -0
|
@@ -76,8 +76,9 @@ const ALL_FILTERS_SHOWN: Record<MessageFilterKey, boolean> = Object.fromEntries(
|
|
|
76
76
|
MESSAGE_FILTER_KEYS.map((k) => [k, true]),
|
|
77
77
|
) as Record<MessageFilterKey, boolean>;
|
|
78
78
|
const NO_CHANNEL_SUMMARIES: WarmChannelSummary[] = [];
|
|
79
|
+
const NOOP = () => {};
|
|
79
80
|
|
|
80
|
-
export function MessageList({ threadId, messages, steeredSegments, agentConfig, userProfile, streamingContent, thinkingContent, toolEvents, hasMore, loadingMore, onLoadMore, queuedMessages, onRemoveQueued, hotSinceSeq, warmSummary, warmSummaryBeforeSeq, warmSummaryComputedAt, warmSummarySourceMessages, warmSummarySourceChars, warmSummaryTopics, warmChannelSummaries = NO_CHANNEL_SUMMARIES, warmSummaryPending = false, compactionPending = false, onSetContextPin, streaming, contextWindowTokens, onRetryMessage, filters = ALL_FILTERS_SHOWN, onToggleFilter: toggle =
|
|
81
|
+
export function MessageList({ threadId, messages, steeredSegments, agentConfig, userProfile, streamingContent, thinkingContent, toolEvents, hasMore, loadingMore, onLoadMore, queuedMessages, onRemoveQueued, hotSinceSeq, warmSummary, warmSummaryBeforeSeq, warmSummaryComputedAt, warmSummarySourceMessages, warmSummarySourceChars, warmSummaryTopics, warmChannelSummaries = NO_CHANNEL_SUMMARIES, warmSummaryPending = false, compactionPending = false, onSetContextPin, streaming, contextWindowTokens, onRetryMessage, filters = ALL_FILTERS_SHOWN, onToggleFilter: toggle = NOOP, onResetFilters: reset = NOOP }: Props) {
|
|
81
82
|
const hostRef = useRef<HTMLDivElement>(null);
|
|
82
83
|
const maskRegionRef = useRef<HTMLDivElement>(null);
|
|
83
84
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
@@ -102,7 +103,11 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
102
103
|
const [pendingHotSinceSeq, setPendingHotSinceSeq] = useState<number | null>(null);
|
|
103
104
|
const [topControlsOpen, setTopControlsOpen] = useState(false);
|
|
104
105
|
const [summaryPopoverOpen, setSummaryPopoverOpen] = useState(false);
|
|
105
|
-
|
|
106
|
+
const hasStreamingContent = !!streamingContent;
|
|
107
|
+
const hasThinkingContent = !!thinkingContent;
|
|
108
|
+
const hasLiveToolEvents = !!toolEvents?.length;
|
|
109
|
+
const hidePersistedDraft = !!streaming || hasStreamingContent;
|
|
110
|
+
|
|
106
111
|
const retryWorkflowStep = useMemo(
|
|
107
112
|
() => onRetryMessage
|
|
108
113
|
? (request: WorkflowStepRetryRequest) => onRetryMessage(workflowStepRetryMessage(request), [])
|
|
@@ -116,7 +121,7 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
116
121
|
// they're handled below by gating the inline ToolList / ThinkingLine.
|
|
117
122
|
const visibleMessages = useMemo(() => {
|
|
118
123
|
return messages.filter((m) => {
|
|
119
|
-
if (m.role === "assistant" && m.transcript_status === "in_progress" &&
|
|
124
|
+
if (m.role === "assistant" && m.transcript_status === "in_progress" && hidePersistedDraft) return false;
|
|
120
125
|
const cat = m.category;
|
|
121
126
|
if (!cat) return true;
|
|
122
127
|
if (cat === "scheduled_task") return filters.scheduled_task;
|
|
@@ -129,7 +134,53 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
129
134
|
// never silently drop content the server thinks should be visible.
|
|
130
135
|
return true;
|
|
131
136
|
});
|
|
132
|
-
}, [messages,
|
|
137
|
+
}, [messages, hidePersistedDraft, filters.scheduled_task, filters.watcher, filters.bridge, filters.extension, filters.page_capture, filters.synthetic]);
|
|
138
|
+
|
|
139
|
+
const historyRows = useMemo(() => {
|
|
140
|
+
const attachedActivities = new Map<string, AutomationActivityMetadata>();
|
|
141
|
+
const hiddenActivityIds = new Set<string>();
|
|
142
|
+
for (let i = 0; i < visibleMessages.length - 1; i++) {
|
|
143
|
+
const activityMessage = visibleMessages[i];
|
|
144
|
+
const activity = activityMessage.metadata?.automation_activity;
|
|
145
|
+
if (!activity) continue;
|
|
146
|
+
const related = visibleMessages[i + 1];
|
|
147
|
+
const matches = !related.metadata?.automation_activity && (
|
|
148
|
+
activity.source_kind === "bridge"
|
|
149
|
+
? related.role === "user"
|
|
150
|
+
&& related.metadata?.bridge_conversation?.key === activity.source_id
|
|
151
|
+
: related.role === "assistant" && related.category === activity.source_kind
|
|
152
|
+
);
|
|
153
|
+
if (!matches) continue;
|
|
154
|
+
attachedActivities.set(related.id, activity);
|
|
155
|
+
hiddenActivityIds.add(activityMessage.id);
|
|
156
|
+
}
|
|
157
|
+
const segmentsById = new Map(steeredSegments?.map((segment) => [segment.id, segment]));
|
|
158
|
+
let previousRole: Message["role"] | null = null;
|
|
159
|
+
return visibleMessages.map((msg, i) => {
|
|
160
|
+
if (hiddenActivityIds.has(msg.id)) return null;
|
|
161
|
+
const startsTurn = previousRole == null || previousRole !== msg.role;
|
|
162
|
+
previousRole = msg.role;
|
|
163
|
+
const steeredSegment = segmentsById.get(msg.id);
|
|
164
|
+
return (
|
|
165
|
+
<HistoryRow
|
|
166
|
+
key={msg.id}
|
|
167
|
+
message={msg}
|
|
168
|
+
steeredSegment={steeredSegment}
|
|
169
|
+
segmentShowAvatar={i === 0 || visibleMessages[i - 1].role !== "assistant"}
|
|
170
|
+
attachedActivity={attachedActivities.get(msg.id)}
|
|
171
|
+
startsTurn={startsTurn}
|
|
172
|
+
separated={startsTurn && i > 0}
|
|
173
|
+
threadId={threadId ?? null}
|
|
174
|
+
agentConfig={agentConfig}
|
|
175
|
+
userProfile={userProfile}
|
|
176
|
+
showToolEvents={filters.tool_use}
|
|
177
|
+
contextWindowTokens={contextWindowTokens ?? null}
|
|
178
|
+
isLatest={i === visibleMessages.length - 1 && !hasStreamingContent}
|
|
179
|
+
onRetry={onRetryMessage}
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
}, [visibleMessages, steeredSegments, threadId, agentConfig, userProfile, filters.tool_use, contextWindowTokens, hasStreamingContent, onRetryMessage]);
|
|
133
184
|
|
|
134
185
|
const hiddenCount = messages.length - visibleMessages.length;
|
|
135
186
|
const effectiveHotSinceSeq = hotSinceSeq ?? null;
|
|
@@ -536,7 +587,7 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
536
587
|
// perceive this as "chat is empty". Auto-reset once per thread snapshot so
|
|
537
588
|
// content remains visible without requiring manual recovery.
|
|
538
589
|
useEffect(() => {
|
|
539
|
-
if (messages.length === 0 ||
|
|
590
|
+
if (messages.length === 0 || hasStreamingContent) return;
|
|
540
591
|
if (visibleMessages.length > 0) return;
|
|
541
592
|
if (hiddenCount !== messages.length) return;
|
|
542
593
|
const lastId = messages[messages.length - 1]?.id ?? "none";
|
|
@@ -544,7 +595,7 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
544
595
|
if (autoRecoveredRef.current === key) return;
|
|
545
596
|
autoRecoveredRef.current = key;
|
|
546
597
|
reset();
|
|
547
|
-
}, [threadId, messages, visibleMessages.length, hiddenCount,
|
|
598
|
+
}, [threadId, messages, visibleMessages.length, hiddenCount, hasStreamingContent, reset]);
|
|
548
599
|
|
|
549
600
|
// Surface a category chip in the toolbar only if it can actually do
|
|
550
601
|
// something useful right now: scheduled_task/bridge/synthetic chips
|
|
@@ -563,10 +614,10 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
563
614
|
else if (m.category === "synthetic") set.add("synthetic");
|
|
564
615
|
if (m.tool_events && m.tool_events.length > 0) set.add("tool_use");
|
|
565
616
|
}
|
|
566
|
-
if (
|
|
567
|
-
if (
|
|
617
|
+
if (hasThinkingContent) set.add("thinking");
|
|
618
|
+
if (hasLiveToolEvents) set.add("tool_use");
|
|
568
619
|
return MESSAGE_FILTER_KEYS.filter((k) => set.has(k));
|
|
569
|
-
}, [messages,
|
|
620
|
+
}, [messages, hasThinkingContent, hasLiveToolEvents]);
|
|
570
621
|
|
|
571
622
|
// Tracks whether the user was at the bottom on the most recent scroll event.
|
|
572
623
|
// After every render, if true, we snap to bottom — which means: while the
|
|
@@ -920,30 +971,6 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
920
971
|
// "+ N more we don't know about yet" — older pages are likely unloaded.
|
|
921
972
|
const olderCountLabel = olderInVisible + (hasMore ? 1 : 0);
|
|
922
973
|
|
|
923
|
-
const attachedActivities = new Map<string, AutomationActivityMetadata>();
|
|
924
|
-
const hiddenActivityIds = new Set<string>();
|
|
925
|
-
for (let i = 0; i < visibleMessages.length - 1; i++) {
|
|
926
|
-
const activityMessage = visibleMessages[i];
|
|
927
|
-
const activity = activityMessage.metadata?.automation_activity;
|
|
928
|
-
if (!activity) continue;
|
|
929
|
-
const related = visibleMessages[i + 1];
|
|
930
|
-
const matches = !related.metadata?.automation_activity && (
|
|
931
|
-
activity.source_kind === "bridge"
|
|
932
|
-
? related.role === "user"
|
|
933
|
-
&& related.metadata?.bridge_conversation?.key === activity.source_id
|
|
934
|
-
: related.role === "assistant" && related.category === activity.source_kind
|
|
935
|
-
);
|
|
936
|
-
if (!matches) continue;
|
|
937
|
-
attachedActivities.set(related.id, activity);
|
|
938
|
-
hiddenActivityIds.add(activityMessage.id);
|
|
939
|
-
}
|
|
940
|
-
const previousVisibleRoles = new Map<string, Message["role"] | null>();
|
|
941
|
-
let previousVisibleRole: Message["role"] | null = null;
|
|
942
|
-
for (const message of visibleMessages) {
|
|
943
|
-
previousVisibleRoles.set(message.id, previousVisibleRole);
|
|
944
|
-
if (!hiddenActivityIds.has(message.id)) previousVisibleRole = message.role;
|
|
945
|
-
}
|
|
946
|
-
|
|
947
974
|
const renderBoundary = (key: string) => (
|
|
948
975
|
<div
|
|
949
976
|
key={key}
|
|
@@ -969,54 +996,12 @@ export function MessageList({ threadId, messages, steeredSegments, agentConfig,
|
|
|
969
996
|
</div>
|
|
970
997
|
);
|
|
971
998
|
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
const previousRole = previousVisibleRoles.get(msg.id);
|
|
979
|
-
const startsTurn = previousRole == null || previousRole !== msg.role;
|
|
980
|
-
const steeredSegment = steeredSegments?.find((segment) => segment.id === msg.id);
|
|
981
|
-
if (steeredSegment) {
|
|
982
|
-
out.push(
|
|
983
|
-
<StreamingBubble
|
|
984
|
-
key={`steered-${steeredSegment.id}`}
|
|
985
|
-
content={steeredSegment.content}
|
|
986
|
-
threadId={threadId ?? null}
|
|
987
|
-
agentConfig={agentConfig ?? null}
|
|
988
|
-
showAvatar={i === 0 || visibleMessages[i - 1].role !== "assistant"}
|
|
989
|
-
/>,
|
|
990
|
-
);
|
|
991
|
-
}
|
|
992
|
-
out.push(
|
|
993
|
-
<div
|
|
994
|
-
key={msg.id}
|
|
995
|
-
id={typeof msg.seq === "number" ? String(msg.seq) : `msg-${msg.id}`}
|
|
996
|
-
data-message-id={msg.id}
|
|
997
|
-
data-hot-candidate="1"
|
|
998
|
-
data-message-seq={msg.seq}
|
|
999
|
-
data-created-at={msg.created_at}
|
|
1000
|
-
className={startsTurn && i > 0 ? "mt-3" : undefined}
|
|
1001
|
-
>
|
|
1002
|
-
<MessageBubble
|
|
1003
|
-
message={msg}
|
|
1004
|
-
attachedActivity={attachedActivities.get(msg.id)}
|
|
1005
|
-
threadId={threadId ?? null}
|
|
1006
|
-
agentConfig={agentConfig}
|
|
1007
|
-
userProfile={userProfile}
|
|
1008
|
-
showAvatar={startsTurn}
|
|
1009
|
-
showToolEvents={filters.tool_use}
|
|
1010
|
-
contextWindowTokens={contextWindowTokens ?? null}
|
|
1011
|
-
isLatest={i === visibleMessages.length - 1 && !streamingContent}
|
|
1012
|
-
onRetry={onRetryMessage}
|
|
1013
|
-
/>
|
|
1014
|
-
</div>,
|
|
1015
|
-
);
|
|
1016
|
-
return out;
|
|
1017
|
-
});
|
|
1018
|
-
if (hasBoundary && pinAfterAll) nodes.push(renderBoundary("boundary-tail"));
|
|
1019
|
-
return nodes;
|
|
999
|
+
if (!hasBoundary) return historyRows;
|
|
1000
|
+
return [
|
|
1001
|
+
...historyRows.slice(0, boundaryIndex),
|
|
1002
|
+
renderBoundary(pinAfterAll ? "boundary-tail" : `boundary-${visibleMessages[boundaryIndex].id}`),
|
|
1003
|
+
...historyRows.slice(boundaryIndex),
|
|
1004
|
+
];
|
|
1020
1005
|
})()}
|
|
1021
1006
|
<LiveTurnActivity
|
|
1022
1007
|
thinkingContent={thinkingContent}
|
|
@@ -1225,8 +1210,8 @@ function LiveTurnActivity({
|
|
|
1225
1210
|
if (!showThinking && !streamingContent && !showTools && !showDots) return null;
|
|
1226
1211
|
return (
|
|
1227
1212
|
<div data-testid="live-turn-activity" className="mt-1 flex w-full min-w-0 flex-col gap-1">
|
|
1228
|
-
{showDots && <ThinkingDots
|
|
1229
|
-
{showThinking && <ThinkingLine text={thinkingContent}
|
|
1213
|
+
{showDots && <div className="min-w-0 pl-9"><ThinkingDots /></div>}
|
|
1214
|
+
{showThinking && <div className="min-w-0 pl-9"><ThinkingLine text={thinkingContent} /></div>}
|
|
1230
1215
|
{streamingContent && (
|
|
1231
1216
|
<StreamingBubble
|
|
1232
1217
|
content={streamingContent}
|
|
@@ -1235,16 +1220,65 @@ function LiveTurnActivity({
|
|
|
1235
1220
|
showAvatar={showStreamingAvatar}
|
|
1236
1221
|
/>
|
|
1237
1222
|
)}
|
|
1238
|
-
{showTools && <ToolList events={toolEvents}
|
|
1223
|
+
{showTools && <div className="min-w-0 pl-9"><ToolList events={toolEvents} /></div>}
|
|
1239
1224
|
</div>
|
|
1240
1225
|
);
|
|
1241
1226
|
}
|
|
1242
1227
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1228
|
+
const HistoryRow = memo(function HistoryRow({
|
|
1229
|
+
message, steeredSegment, segmentShowAvatar, attachedActivity, startsTurn, separated,
|
|
1230
|
+
threadId, agentConfig, userProfile, showToolEvents, contextWindowTokens, isLatest, onRetry,
|
|
1231
|
+
}: {
|
|
1232
|
+
message: Message;
|
|
1233
|
+
steeredSegment?: SteeredSegment;
|
|
1234
|
+
segmentShowAvatar: boolean;
|
|
1235
|
+
attachedActivity?: AutomationActivityMetadata;
|
|
1236
|
+
startsTurn: boolean;
|
|
1237
|
+
separated: boolean;
|
|
1238
|
+
threadId: string | null;
|
|
1239
|
+
agentConfig?: AgentConfig | null;
|
|
1240
|
+
userProfile?: UserProfile | null;
|
|
1241
|
+
showToolEvents: boolean;
|
|
1242
|
+
contextWindowTokens: number | null;
|
|
1243
|
+
isLatest: boolean;
|
|
1244
|
+
onRetry?: Props["onRetryMessage"];
|
|
1245
|
+
}) {
|
|
1246
|
+
return (
|
|
1247
|
+
<>
|
|
1248
|
+
{steeredSegment && (
|
|
1249
|
+
<StreamingBubble
|
|
1250
|
+
content={steeredSegment.content}
|
|
1251
|
+
threadId={threadId}
|
|
1252
|
+
agentConfig={agentConfig ?? null}
|
|
1253
|
+
showAvatar={segmentShowAvatar}
|
|
1254
|
+
/>
|
|
1255
|
+
)}
|
|
1256
|
+
<div
|
|
1257
|
+
id={typeof message.seq === "number" ? String(message.seq) : `msg-${message.id}`}
|
|
1258
|
+
data-message-id={message.id}
|
|
1259
|
+
data-hot-candidate="1"
|
|
1260
|
+
data-message-seq={message.seq}
|
|
1261
|
+
data-created-at={message.created_at}
|
|
1262
|
+
className={separated ? "mt-3" : undefined}
|
|
1263
|
+
>
|
|
1264
|
+
<MessageBubble
|
|
1265
|
+
message={message}
|
|
1266
|
+
attachedActivity={attachedActivity}
|
|
1267
|
+
threadId={threadId}
|
|
1268
|
+
agentConfig={agentConfig}
|
|
1269
|
+
userProfile={userProfile}
|
|
1270
|
+
showAvatar={startsTurn}
|
|
1271
|
+
showToolEvents={showToolEvents}
|
|
1272
|
+
contextWindowTokens={contextWindowTokens}
|
|
1273
|
+
isLatest={isLatest}
|
|
1274
|
+
onRetry={onRetry}
|
|
1275
|
+
/>
|
|
1276
|
+
</div>
|
|
1277
|
+
</>
|
|
1278
|
+
);
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
// Keep the synthetic message identity stable when only the parent updates.
|
|
1248
1282
|
const StreamingBubble = memo(function StreamingBubble({
|
|
1249
1283
|
content,
|
|
1250
1284
|
threadId,
|
|
@@ -434,83 +434,87 @@ function ToolCallCard({ group, startedAt }: { group: ToolCallGroup; startedAt: n
|
|
|
434
434
|
const transcriptSteps = group.steps.length > 0 ? group.steps : delegateTranscript?.steps ?? stepsFromResult(displayedResult);
|
|
435
435
|
return (
|
|
436
436
|
<div className="min-w-0 max-w-full">
|
|
437
|
-
<MetaRow fullWidth onClick={() => setOpen((v) => !v)} expanded={open}>
|
|
438
|
-
<
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
{summary}
|
|
455
|
-
</span>
|
|
456
|
-
{group.status === "async" && (
|
|
457
|
-
<Badge
|
|
458
|
-
tone="info"
|
|
459
|
-
className="uppercase tracking-wide"
|
|
460
|
-
title="running in the background"
|
|
461
|
-
>
|
|
462
|
-
bg
|
|
463
|
-
</Badge>
|
|
464
|
-
)}
|
|
465
|
-
{codexJob?.status === "running" && (
|
|
466
|
-
<Badge tone="info" className="uppercase tracking-wide" title="Codex job is updating live">
|
|
467
|
-
live
|
|
468
|
-
</Badge>
|
|
469
|
-
)}
|
|
470
|
-
{codexJob?.status === "running" && (
|
|
471
|
-
<button
|
|
472
|
-
type="button"
|
|
473
|
-
onClick={(event) => { event.stopPropagation(); void cancelCodexJob(); }}
|
|
474
|
-
className="control-tap shrink-0 text-fg-faint hover:text-rose-600 dark:hover:text-rose-300"
|
|
475
|
-
title="Cancel Codex task"
|
|
476
|
-
aria-label="Cancel Codex task"
|
|
477
|
-
>
|
|
478
|
-
<X size={12} />
|
|
479
|
-
</button>
|
|
480
|
-
)}
|
|
481
|
-
{group.readByAgent && (
|
|
482
|
-
<Badge
|
|
483
|
-
tone="neutral"
|
|
484
|
-
className="uppercase tracking-wide"
|
|
485
|
-
title="agent read the background result"
|
|
486
|
-
>
|
|
487
|
-
read
|
|
488
|
-
</Badge>
|
|
489
|
-
)}
|
|
490
|
-
{isToolResultRefEnvelope(group.result) && (
|
|
491
|
-
<Badge
|
|
492
|
-
tone="info"
|
|
493
|
-
className="uppercase tracking-wide"
|
|
494
|
-
title="large result is shown as a preview with a file reference"
|
|
495
|
-
>
|
|
496
|
-
preview
|
|
497
|
-
</Badge>
|
|
498
|
-
)}
|
|
499
|
-
{delegateTranscript?.awaitingUserAnswers && (
|
|
500
|
-
<Badge
|
|
501
|
-
tone="warning"
|
|
502
|
-
className="uppercase tracking-wide"
|
|
503
|
-
title="Claude asked design questions and is waiting for the user"
|
|
437
|
+
<MetaRow fullWidth onClick={() => setOpen((v) => !v)} expanded={open} className="flex-wrap">
|
|
438
|
+
<span className="flex min-w-0 flex-1 basis-40 items-center gap-1.5">
|
|
439
|
+
<CollapseChevron open={open} size={9} className="text-fg-faint/70" />
|
|
440
|
+
<ToolIcon toolName={group.name} />
|
|
441
|
+
<span className="min-w-0 max-w-[50%] truncate font-medium text-fg-muted" title={group.name}>{group.name}</span>
|
|
442
|
+
<span
|
|
443
|
+
className="relative truncate text-fg-faint font-normal flex-1 min-w-0"
|
|
444
|
+
title={summaryTitle || undefined}
|
|
445
|
+
style={{
|
|
446
|
+
// Fade the tail of the args summary into the surface so the
|
|
447
|
+
// status pills + progress bar on the right stay legible even
|
|
448
|
+
// when the args fill the available space.
|
|
449
|
+
WebkitMaskImage:
|
|
450
|
+
"linear-gradient(to right, black 0, black calc(100% - 28px), transparent 100%)",
|
|
451
|
+
maskImage:
|
|
452
|
+
"linear-gradient(to right, black 0, black calc(100% - 28px), transparent 100%)",
|
|
453
|
+
}}
|
|
504
454
|
>
|
|
505
|
-
|
|
506
|
-
</
|
|
507
|
-
|
|
508
|
-
<
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
455
|
+
{summary}
|
|
456
|
+
</span>
|
|
457
|
+
</span>
|
|
458
|
+
<span className="ml-auto flex max-w-full flex-wrap items-center gap-1.5">
|
|
459
|
+
{group.status === "async" && (
|
|
460
|
+
<Badge
|
|
461
|
+
tone="info"
|
|
462
|
+
className="uppercase tracking-wide"
|
|
463
|
+
title="running in the background"
|
|
464
|
+
>
|
|
465
|
+
bg
|
|
466
|
+
</Badge>
|
|
467
|
+
)}
|
|
468
|
+
{codexJob?.status === "running" && (
|
|
469
|
+
<Badge tone="info" className="uppercase tracking-wide" title="Codex job is updating live">
|
|
470
|
+
live
|
|
471
|
+
</Badge>
|
|
472
|
+
)}
|
|
473
|
+
{codexJob?.status === "running" && (
|
|
474
|
+
<button
|
|
475
|
+
type="button"
|
|
476
|
+
onClick={(event) => { event.stopPropagation(); void cancelCodexJob(); }}
|
|
477
|
+
className="control-tap shrink-0 text-fg-faint hover:text-rose-600 dark:hover:text-rose-300"
|
|
478
|
+
title="Cancel Codex task"
|
|
479
|
+
aria-label="Cancel Codex task"
|
|
480
|
+
>
|
|
481
|
+
<X size={12} />
|
|
482
|
+
</button>
|
|
483
|
+
)}
|
|
484
|
+
{group.readByAgent && (
|
|
485
|
+
<Badge
|
|
486
|
+
tone="neutral"
|
|
487
|
+
className="uppercase tracking-wide"
|
|
488
|
+
title="agent read the background result"
|
|
489
|
+
>
|
|
490
|
+
read
|
|
491
|
+
</Badge>
|
|
492
|
+
)}
|
|
493
|
+
{isToolResultRefEnvelope(group.result) && (
|
|
494
|
+
<Badge
|
|
495
|
+
tone="info"
|
|
496
|
+
className="uppercase tracking-wide"
|
|
497
|
+
title="large result is shown as a preview with a file reference"
|
|
498
|
+
>
|
|
499
|
+
preview
|
|
500
|
+
</Badge>
|
|
501
|
+
)}
|
|
502
|
+
{delegateTranscript?.awaitingUserAnswers && (
|
|
503
|
+
<Badge
|
|
504
|
+
tone="warning"
|
|
505
|
+
className="uppercase tracking-wide"
|
|
506
|
+
title="Claude asked design questions and is waiting for the user"
|
|
507
|
+
>
|
|
508
|
+
asks
|
|
509
|
+
</Badge>
|
|
510
|
+
)}
|
|
511
|
+
<StatusIndicator
|
|
512
|
+
status={group.status}
|
|
513
|
+
deadlineMs={group.deadlineMs}
|
|
514
|
+
startedAt={startedAt}
|
|
515
|
+
stepCount={transcriptSteps.length}
|
|
516
|
+
/>
|
|
517
|
+
</span>
|
|
514
518
|
</MetaRow>
|
|
515
519
|
{delegateTranscript ? (
|
|
516
520
|
<DelegateTurnCards
|
|
@@ -526,7 +530,7 @@ function ToolCallCard({ group, startedAt }: { group: ToolCallGroup; startedAt: n
|
|
|
526
530
|
<LiveTranscript steps={transcriptSteps} />
|
|
527
531
|
)}
|
|
528
532
|
{open && (
|
|
529
|
-
<div className="mt-0.5 rounded border border-border/40 bg-surface-2/30 px-2 py-1.5 space-y-1.5 text-[10px]">
|
|
533
|
+
<div className="mt-0.5 min-w-0 rounded border border-border/40 bg-surface-2/30 px-2 py-1.5 space-y-1.5 text-[10px] [overflow-wrap:anywhere]">
|
|
530
534
|
<WorkflowProgressDetails group={group} />
|
|
531
535
|
{!hasWorkflowView(group) && (<>
|
|
532
536
|
{hasVisibleArgs(group.args) ? (
|
|
@@ -1073,16 +1077,16 @@ function DetailSection({
|
|
|
1073
1077
|
<div className="min-w-0">
|
|
1074
1078
|
<div className="text-[10px] uppercase tracking-wide text-fg-faint mb-0.5">{label}</div>
|
|
1075
1079
|
{kvEntries ? (
|
|
1076
|
-
<dl className={`grid grid-cols-[
|
|
1080
|
+
<dl className={`grid grid-cols-[fit-content(35%)_minmax(0,1fr)] gap-x-2 gap-y-0.5 text-[11px] font-mono ${toneClass}`}>
|
|
1077
1081
|
{kvEntries.map(([k, v]) => (
|
|
1078
1082
|
<div key={k} className="contents">
|
|
1079
|
-
<dt className="text-fg-faint">{k}</dt>
|
|
1080
|
-
<dd className="min-w-0
|
|
1083
|
+
<dt className="min-w-0 text-fg-faint">{k}</dt>
|
|
1084
|
+
<dd className="min-w-0 whitespace-pre-wrap [overflow-wrap:anywhere]">{renderKvValue(v)}</dd>
|
|
1081
1085
|
</div>
|
|
1082
1086
|
))}
|
|
1083
1087
|
</dl>
|
|
1084
1088
|
) : (
|
|
1085
|
-
<pre className={`text-[11px] font-mono whitespace-pre-wrap
|
|
1089
|
+
<pre className={`text-[11px] font-mono whitespace-pre-wrap [overflow-wrap:anywhere] max-w-full ${toneClass}`}>
|
|
1086
1090
|
{formatPayload(value)}
|
|
1087
1091
|
</pre>
|
|
1088
1092
|
)}
|
|
@@ -1198,11 +1202,11 @@ function renderKvValue(v: unknown): ReactNode {
|
|
|
1198
1202
|
const entries = Object.entries(obj).filter(([k]) => !HIDDEN_ARG_KEYS.has(k));
|
|
1199
1203
|
if (entries.length === 0) return <span className="text-fg-faint">{"{}"}</span>;
|
|
1200
1204
|
return (
|
|
1201
|
-
<dl className="grid grid-cols-[
|
|
1205
|
+
<dl className="grid grid-cols-[fit-content(35%)_minmax(0,1fr)] gap-x-2 gap-y-0.5">
|
|
1202
1206
|
{entries.map(([k, vv]) => (
|
|
1203
1207
|
<div key={k} className="contents">
|
|
1204
|
-
<dt className="text-fg-faint">{k}</dt>
|
|
1205
|
-
<dd className="min-w-0
|
|
1208
|
+
<dt className="min-w-0 text-fg-faint">{k}</dt>
|
|
1209
|
+
<dd className="min-w-0 whitespace-pre-wrap [overflow-wrap:anywhere]">{renderKvValue(vv)}</dd>
|
|
1206
1210
|
</div>
|
|
1207
1211
|
))}
|
|
1208
1212
|
</dl>
|
|
@@ -9,7 +9,7 @@ vi.mock("@/api/client", () => ({
|
|
|
9
9
|
api: {
|
|
10
10
|
threads: {
|
|
11
11
|
activity: (...args: unknown[]) => mocks.activity(...args),
|
|
12
|
-
|
|
12
|
+
metadata: (...args: unknown[]) => mocks.getThread(...args),
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
}));
|
|
@@ -87,7 +87,7 @@ describe("useThreadActivity", () => {
|
|
|
87
87
|
expect(meta.setCompactionPending).toHaveBeenCalledWith(true);
|
|
88
88
|
expect(meta.setManualCompactionPending).toHaveBeenCalledWith(true);
|
|
89
89
|
await tick(1_500);
|
|
90
|
-
expect(mocks.getThread).toHaveBeenCalledWith("t1"
|
|
90
|
+
expect(mocks.getThread).toHaveBeenCalledWith("t1");
|
|
91
91
|
expect(meta.setManualCompactionPending).toHaveBeenLastCalledWith(false);
|
|
92
92
|
});
|
|
93
93
|
|
|
@@ -73,9 +73,9 @@ export function useThreadActivity({ threadId, attach, isLive, lastSettledAt, met
|
|
|
73
73
|
// pull the new boundary and recap.
|
|
74
74
|
d.metaApplier.setCompactionPending?.(false);
|
|
75
75
|
d.metaApplier.setManualCompactionPending?.(false);
|
|
76
|
-
api.threads.
|
|
76
|
+
api.threads.metadata(threadId)
|
|
77
77
|
.then((meta) => { if (!cancelled) applyThreadMeta(deps.current.metaApplier, meta); })
|
|
78
|
-
.catch(() => {
|
|
78
|
+
.catch((err) => { if (!cancelled) console.error("activity metadata refresh failed", err); });
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
schedule(next.busy ? BUSY_POLL_MS : IDLE_POLL_MS);
|
|
@@ -110,7 +110,7 @@ export function useThreadData({ threadId, attach }: Params): ThreadDataApi {
|
|
|
110
110
|
setCompactionPending(false);
|
|
111
111
|
setManualCompactionPending(false);
|
|
112
112
|
setContextWindowTokens(null);
|
|
113
|
-
api.threads.get(threadId).then((d) => {
|
|
113
|
+
api.threads.get(threadId, { startup: true }).then((d) => {
|
|
114
114
|
if (cancelled) return;
|
|
115
115
|
setMessages(d.messages);
|
|
116
116
|
setHasMore(d.has_more);
|
|
@@ -163,35 +163,6 @@ export function useThreadData({ threadId, attach }: Params): ThreadDataApi {
|
|
|
163
163
|
}
|
|
164
164
|
}, [threadId]);
|
|
165
165
|
|
|
166
|
-
useEffect(() => {
|
|
167
|
-
if (!threadId) return;
|
|
168
|
-
const summaryFresh = hotSinceSeq !== null && warmSummaryBeforeSeq === hotSinceSeq;
|
|
169
|
-
const summaryStale = warmSummaryPending && hotSinceSeq !== null && !summaryFresh;
|
|
170
|
-
if (!summaryStale && !compactionPending && !manualCompactionPending) {
|
|
171
|
-
if (warmSummaryPending && hotSinceSeq !== null && summaryFresh) setWarmSummaryPending(false);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
let cancelled = false;
|
|
175
|
-
const timer = window.setInterval(() => {
|
|
176
|
-
void api.threads.get(threadId).then((d) => {
|
|
177
|
-
if (cancelled) return;
|
|
178
|
-
applyThreadMeta(metaApplier, d);
|
|
179
|
-
const refreshedSummaryIsFresh = d.hot_since_seq != null
|
|
180
|
-
&& d.warm_summary_before_seq === d.hot_since_seq;
|
|
181
|
-
if (!d.hot_since_seq || refreshedSummaryIsFresh) {
|
|
182
|
-
setWarmSummaryPending(false);
|
|
183
|
-
}
|
|
184
|
-
}).catch((err) => {
|
|
185
|
-
if (!cancelled) console.error("warm summary refresh poll failed", err);
|
|
186
|
-
});
|
|
187
|
-
}, 1600);
|
|
188
|
-
return () => {
|
|
189
|
-
cancelled = true;
|
|
190
|
-
window.clearInterval(timer);
|
|
191
|
-
};
|
|
192
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
193
|
-
}, [threadId, warmSummaryPending, compactionPending, manualCompactionPending, hotSince, hotSinceSeq, warmSummaryBefore, warmSummaryBeforeSeq]);
|
|
194
|
-
|
|
195
166
|
const loadOlder = useCallback(async () => {
|
|
196
167
|
if (!threadId || loadingMore || !hasMore || messages.length === 0) return;
|
|
197
168
|
setLoadingMore(true);
|