@adecore/agents-react 0.0.1 → 0.17.0-beta.2
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/LICENSE +110 -0
- package/README.md +61 -0
- package/dist/agents/AccountDot.d.ts +4 -0
- package/dist/agents/AccountDot.js +8 -0
- package/dist/agents/AgentIcon.d.ts +6 -0
- package/dist/agents/AgentIcon.js +20 -0
- package/dist/agents/ModelOptionControl.d.ts +15 -0
- package/dist/agents/ModelOptionControl.js +33 -0
- package/dist/agents/ProviderLogo.d.ts +8 -0
- package/dist/agents/ProviderLogo.js +8 -0
- package/dist/agents/account-limits.d.ts +7 -0
- package/dist/agents/account-limits.js +40 -0
- package/dist/agents/accounts.d.ts +22 -0
- package/dist/agents/accounts.js +113 -0
- package/dist/agents/model-name.d.ts +12 -0
- package/dist/agents/model-name.js +56 -0
- package/dist/agents/model-options.d.ts +5 -0
- package/dist/agents/model-options.js +15 -0
- package/dist/agents/provider-paths.d.ts +2 -0
- package/dist/agents/provider-paths.js +8 -0
- package/dist/agents/status-look.d.ts +13 -0
- package/dist/agents/status-look.js +24 -0
- package/dist/chat/account-choice.d.ts +11 -0
- package/dist/chat/account-choice.js +30 -0
- package/dist/chat/actions.d.ts +6 -0
- package/dist/chat/actions.js +68 -0
- package/dist/chat/activity.d.ts +5 -0
- package/dist/chat/activity.js +6 -0
- package/dist/chat/attachments.d.ts +23 -0
- package/dist/chat/attachments.js +86 -0
- package/dist/chat/bookmarks.d.ts +14 -0
- package/dist/chat/bookmarks.js +73 -0
- package/dist/chat/chat-client.d.ts +55 -0
- package/dist/chat/chat-client.js +279 -0
- package/dist/chat/chat-references.d.ts +5 -0
- package/dist/chat/chat-references.js +5 -0
- package/dist/chat/drafts.d.ts +29 -0
- package/dist/chat/drafts.js +116 -0
- package/dist/chat/forks.d.ts +2 -0
- package/dist/chat/forks.js +28 -0
- package/dist/chat/guards.d.ts +12 -0
- package/dist/chat/guards.js +69 -0
- package/dist/chat/logic/ansi.d.ts +13 -0
- package/dist/chat/logic/ansi.js +185 -0
- package/dist/chat/logic/answers.d.ts +1 -0
- package/dist/chat/logic/answers.js +8 -0
- package/dist/chat/logic/bookmarks.d.ts +5 -0
- package/dist/chat/logic/bookmarks.js +33 -0
- package/dist/chat/logic/context-usage.d.ts +12 -0
- package/dist/chat/logic/context-usage.js +21 -0
- package/dist/chat/logic/fork.d.ts +45 -0
- package/dist/chat/logic/fork.js +148 -0
- package/dist/chat/logic/handback.d.ts +2 -0
- package/dist/chat/logic/handback.js +8 -0
- package/dist/chat/logic/json.d.ts +1 -0
- package/dist/chat/logic/json.js +4 -0
- package/dist/chat/logic/limit.d.ts +7 -0
- package/dist/chat/logic/limit.js +34 -0
- package/dist/chat/logic/resume-compaction.d.ts +14 -0
- package/dist/chat/logic/resume-compaction.js +47 -0
- package/dist/chat/logic/scrubber.d.ts +50 -0
- package/dist/chat/logic/scrubber.js +220 -0
- package/dist/chat/logic/thread-cards.d.ts +3 -0
- package/dist/chat/logic/thread-cards.js +59 -0
- package/dist/chat/logic/timeline-copy.d.ts +4 -0
- package/dist/chat/logic/timeline-copy.js +59 -0
- package/dist/chat/logic/timeline-target.d.ts +12 -0
- package/dist/chat/logic/timeline-target.js +34 -0
- package/dist/chat/logic/timeline.d.ts +115 -0
- package/dist/chat/logic/timeline.js +343 -0
- package/dist/chat/logic/tool-catalog.d.ts +10 -0
- package/dist/chat/logic/tool-catalog.js +44 -0
- package/dist/chat/logic/tools.d.ts +15 -0
- package/dist/chat/logic/tools.js +82 -0
- package/dist/chat/logic/welcome.d.ts +2 -0
- package/dist/chat/logic/welcome.js +10 -0
- package/dist/chat/logic/workflow.d.ts +14 -0
- package/dist/chat/logic/workflow.js +47 -0
- package/dist/chat/mentions.d.ts +65 -0
- package/dist/chat/mentions.js +184 -0
- package/dist/chat/persisted-json.d.ts +5 -0
- package/dist/chat/persisted-json.js +58 -0
- package/dist/chat/preferences.d.ts +27 -0
- package/dist/chat/preferences.js +139 -0
- package/dist/chat/quote.d.ts +2 -0
- package/dist/chat/quote.js +25 -0
- package/dist/chat/recent-messages.d.ts +17 -0
- package/dist/chat/recent-messages.js +36 -0
- package/dist/chat/resume-compaction-dismissals.d.ts +3 -0
- package/dist/chat/resume-compaction-dismissals.js +14 -0
- package/dist/chat/runtime-modes.d.ts +4 -0
- package/dist/chat/runtime-modes.js +15 -0
- package/dist/chat/stash.d.ts +24 -0
- package/dist/chat/stash.js +91 -0
- package/dist/chat/subagent-conversation.d.ts +41 -0
- package/dist/chat/subagent-conversation.js +167 -0
- package/dist/chat/subagent-list.d.ts +19 -0
- package/dist/chat/subagent-list.js +106 -0
- package/dist/chat/subagent-support.d.ts +6 -0
- package/dist/chat/subagent-support.js +14 -0
- package/dist/chat/subagent-view.d.ts +35 -0
- package/dist/chat/subagent-view.js +96 -0
- package/dist/chat/thumbnails.d.ts +10 -0
- package/dist/chat/thumbnails.js +89 -0
- package/dist/chat/timeline-flash.d.ts +12 -0
- package/dist/chat/timeline-flash.js +16 -0
- package/dist/chat/timeline-scroll.d.ts +27 -0
- package/dist/chat/timeline-scroll.js +152 -0
- package/dist/chat/ui/AccountPill.d.ts +3 -0
- package/dist/chat/ui/AccountPill.js +23 -0
- package/dist/chat/ui/AnsiOutput.d.ts +5 -0
- package/dist/chat/ui/AnsiOutput.js +9 -0
- package/dist/chat/ui/BookmarkMarker.d.ts +8 -0
- package/dist/chat/ui/BookmarkMarker.js +57 -0
- package/dist/chat/ui/BookmarkSubmenu.d.ts +3 -0
- package/dist/chat/ui/BookmarkSubmenu.js +33 -0
- package/dist/chat/ui/ChatActivity.d.ts +7 -0
- package/dist/chat/ui/ChatActivity.js +84 -0
- package/dist/chat/ui/ChatReferenceChip.d.ts +4 -0
- package/dist/chat/ui/ChatReferenceChip.js +16 -0
- package/dist/chat/ui/CodeBlock.d.ts +4 -0
- package/dist/chat/ui/CodeBlock.js +132 -0
- package/dist/chat/ui/Composer.d.ts +15 -0
- package/dist/chat/ui/Composer.js +856 -0
- package/dist/chat/ui/ComposerInput.d.ts +29 -0
- package/dist/chat/ui/ComposerInput.js +127 -0
- package/dist/chat/ui/DiffPool.d.ts +5 -0
- package/dist/chat/ui/DiffPool.js +26 -0
- package/dist/chat/ui/EditDiff.d.ts +4 -0
- package/dist/chat/ui/EditDiff.js +21 -0
- package/dist/chat/ui/FadingWords.d.ts +3 -0
- package/dist/chat/ui/FadingWords.js +5 -0
- package/dist/chat/ui/ImageView.d.ts +6 -0
- package/dist/chat/ui/ImageView.js +81 -0
- package/dist/chat/ui/LimitState.d.ts +8 -0
- package/dist/chat/ui/LimitState.js +112 -0
- package/dist/chat/ui/Markdown.d.ts +18 -0
- package/dist/chat/ui/Markdown.js +159 -0
- package/dist/chat/ui/MessageActions.d.ts +9 -0
- package/dist/chat/ui/MessageActions.js +53 -0
- package/dist/chat/ui/Pickers.d.ts +21 -0
- package/dist/chat/ui/Pickers.js +111 -0
- package/dist/chat/ui/PromptComposer.d.ts +13 -0
- package/dist/chat/ui/PromptComposer.js +56 -0
- package/dist/chat/ui/QuoteButton.d.ts +7 -0
- package/dist/chat/ui/QuoteButton.js +74 -0
- package/dist/chat/ui/ResumeCompactionDock.d.ts +5 -0
- package/dist/chat/ui/ResumeCompactionDock.js +14 -0
- package/dist/chat/ui/RunSettings.d.ts +28 -0
- package/dist/chat/ui/RunSettings.js +153 -0
- package/dist/chat/ui/Scrubber.d.ts +17 -0
- package/dist/chat/ui/Scrubber.js +118 -0
- package/dist/chat/ui/SubagentControls.d.ts +11 -0
- package/dist/chat/ui/SubagentControls.js +36 -0
- package/dist/chat/ui/SubagentInfo.d.ts +4 -0
- package/dist/chat/ui/SubagentInfo.js +34 -0
- package/dist/chat/ui/SubagentStopButton.d.ts +7 -0
- package/dist/chat/ui/SubagentStopButton.js +34 -0
- package/dist/chat/ui/SubagentTimeline.d.ts +4 -0
- package/dist/chat/ui/SubagentTimeline.js +107 -0
- package/dist/chat/ui/Timeline.d.ts +6 -0
- package/dist/chat/ui/Timeline.js +424 -0
- package/dist/chat/ui/TimelineMenu.d.ts +12 -0
- package/dist/chat/ui/TimelineMenu.js +54 -0
- package/dist/chat/ui/UnifiedDiff.d.ts +11 -0
- package/dist/chat/ui/UnifiedDiff.js +66 -0
- package/dist/chat/ui/UploadThumb.d.ts +4 -0
- package/dist/chat/ui/UploadThumb.js +11 -0
- package/dist/chat/ui/Welcome.d.ts +4 -0
- package/dist/chat/ui/Welcome.js +16 -0
- package/dist/chat/ui/chips.d.ts +4 -0
- package/dist/chat/ui/chips.js +11 -0
- package/dist/chat/ui/code-lines.d.ts +18 -0
- package/dist/chat/ui/code-lines.js +46 -0
- package/dist/chat/ui/code-streaming.d.ts +1 -0
- package/dist/chat/ui/code-streaming.js +3 -0
- package/dist/chat/ui/code-theme.d.ts +3 -0
- package/dist/chat/ui/code-theme.js +12 -0
- package/dist/chat/ui/composer/chips.d.ts +6 -0
- package/dist/chat/ui/composer/chips.js +31 -0
- package/dist/chat/ui/composer/editor.d.ts +11 -0
- package/dist/chat/ui/composer/editor.js +98 -0
- package/dist/chat/ui/composer/insert.d.ts +2 -0
- package/dist/chat/ui/composer/insert.js +19 -0
- package/dist/chat/ui/composer/keys.d.ts +30 -0
- package/dist/chat/ui/composer/keys.js +100 -0
- package/dist/chat/ui/diff-theme.d.ts +2 -0
- package/dist/chat/ui/diff-theme.js +20 -0
- package/dist/chat/ui/file-links.d.ts +5 -0
- package/dist/chat/ui/file-links.js +20 -0
- package/dist/chat/ui/find-reveal.d.ts +7 -0
- package/dist/chat/ui/find-reveal.js +13 -0
- package/dist/chat/ui/full-diff.d.ts +6 -0
- package/dist/chat/ui/full-diff.js +19 -0
- package/dist/chat/ui/icons.d.ts +4 -0
- package/dist/chat/ui/icons.js +20 -0
- package/dist/chat/ui/markdown-blocks.d.ts +6 -0
- package/dist/chat/ui/markdown-blocks.js +103 -0
- package/dist/chat/ui/quote-selection.d.ts +3 -0
- package/dist/chat/ui/quote-selection.js +46 -0
- package/dist/chat/ui/rehype-chips.d.ts +23 -0
- package/dist/chat/ui/rehype-chips.js +32 -0
- package/dist/chat/ui/rehype-fade.d.ts +23 -0
- package/dist/chat/ui/rehype-fade.js +36 -0
- package/dist/chat/ui/remark-html-as-text.d.ts +8 -0
- package/dist/chat/ui/remark-html-as-text.js +26 -0
- package/dist/chat/ui/reply-context.d.ts +5 -0
- package/dist/chat/ui/reply-context.js +2 -0
- package/dist/chat/ui/reveal.d.ts +13 -0
- package/dist/chat/ui/reveal.js +114 -0
- package/dist/chat/ui/rows/ForksRow.d.ts +4 -0
- package/dist/chat/ui/rows/ForksRow.js +38 -0
- package/dist/chat/ui/rows/MessageRows.d.ts +40 -0
- package/dist/chat/ui/rows/MessageRows.js +204 -0
- package/dist/chat/ui/rows/Rows.d.ts +12 -0
- package/dist/chat/ui/rows/Rows.js +61 -0
- package/dist/chat/ui/rows/SubagentRow.d.ts +17 -0
- package/dist/chat/ui/rows/SubagentRow.js +101 -0
- package/dist/chat/ui/rows/TaskRow.d.ts +8 -0
- package/dist/chat/ui/rows/TaskRow.js +63 -0
- package/dist/chat/ui/rows/WorkRows.d.ts +47 -0
- package/dist/chat/ui/rows/WorkRows.js +168 -0
- package/dist/chat/ui/rows/WorkflowRow.d.ts +8 -0
- package/dist/chat/ui/rows/WorkflowRow.js +48 -0
- package/dist/chat/ui/rows/row-rhythm.d.ts +6 -0
- package/dist/chat/ui/rows/row-rhythm.js +34 -0
- package/dist/chat/ui/useToggleSet.d.ts +6 -0
- package/dist/chat/ui/useToggleSet.js +25 -0
- package/dist/host.d.ts +195 -0
- package/dist/host.js +55 -0
- package/dist/lazy.d.ts +6 -0
- package/dist/lazy.js +57 -0
- package/dist/locales/en/agent-chat.json +446 -0
- package/dist/locales/en/agent-prompts.json +42 -0
- package/dist/locales/en/agent-providers.json +131 -0
- package/dist/locales/en/agent-usage.json +131 -0
- package/dist/locales/nl/agent-chat.json +446 -0
- package/dist/locales/nl/agent-prompts.json +42 -0
- package/dist/locales/nl/agent-providers.json +131 -0
- package/dist/locales/nl/agent-usage.json +131 -0
- package/dist/locales.d.ts +5 -0
- package/dist/locales.js +20 -0
- package/dist/mounted-registry.d.ts +7 -0
- package/dist/mounted-registry.js +39 -0
- package/dist/port-transport.d.ts +6 -0
- package/dist/port-transport.js +129 -0
- package/dist/prompts/logic/focus.d.ts +2 -0
- package/dist/prompts/logic/focus.js +23 -0
- package/dist/prompts/logic/keys.d.ts +42 -0
- package/dist/prompts/logic/keys.js +94 -0
- package/dist/prompts/logic/prompts.d.ts +34 -0
- package/dist/prompts/logic/prompts.fixtures.d.ts +5 -0
- package/dist/prompts/logic/prompts.fixtures.js +79 -0
- package/dist/prompts/logic/prompts.js +32 -0
- package/dist/prompts/logic/subjects.d.ts +50 -0
- package/dist/prompts/logic/subjects.js +63 -0
- package/dist/prompts/logic/useFocusAfterAnswer.d.ts +6 -0
- package/dist/prompts/logic/useFocusAfterAnswer.js +28 -0
- package/dist/prompts/logic/usePromptSession.d.ts +24 -0
- package/dist/prompts/logic/usePromptSession.js +87 -0
- package/dist/prompts/ui/ApprovalBody.d.ts +13 -0
- package/dist/prompts/ui/ApprovalBody.js +34 -0
- package/dist/prompts/ui/PromptActions.d.ts +27 -0
- package/dist/prompts/ui/PromptActions.js +18 -0
- package/dist/prompts/ui/PromptCard.d.ts +16 -0
- package/dist/prompts/ui/PromptCard.js +50 -0
- package/dist/prompts/ui/PromptView.d.ts +2 -0
- package/dist/prompts/ui/PromptView.js +47 -0
- package/dist/prompts/ui/QuestionBody.d.ts +9 -0
- package/dist/prompts/ui/QuestionBody.js +87 -0
- package/dist/providers/AccountColors.d.ts +5 -0
- package/dist/providers/AccountColors.js +8 -0
- package/dist/providers/AccountDetail.d.ts +12 -0
- package/dist/providers/AccountDetail.js +69 -0
- package/dist/providers/AccountVariables.d.ts +8 -0
- package/dist/providers/AccountVariables.js +43 -0
- package/dist/providers/AddAccountForm.d.ts +10 -0
- package/dist/providers/AddAccountForm.js +54 -0
- package/dist/providers/CliDetail.d.ts +12 -0
- package/dist/providers/CliDetail.js +54 -0
- package/dist/providers/ProvidersPane.d.ts +9 -0
- package/dist/providers/ProvidersPane.js +86 -0
- package/dist/providers/account-actions.d.ts +7 -0
- package/dist/providers/account-actions.js +57 -0
- package/dist/providers/parts.d.ts +9 -0
- package/dist/providers/parts.js +18 -0
- package/dist/providers/provider-abilities.d.ts +2 -0
- package/dist/providers/provider-abilities.js +7 -0
- package/dist/providers/variables.d.ts +13 -0
- package/dist/providers/variables.js +63 -0
- package/dist/scope.d.ts +11 -0
- package/dist/scope.js +10 -0
- package/dist/settings/sections.d.ts +13 -0
- package/dist/settings/sections.js +32 -0
- package/dist/state/chats.d.ts +44 -0
- package/dist/state/chats.js +199 -0
- package/dist/state/provider-accounts.d.ts +17 -0
- package/dist/state/provider-accounts.js +67 -0
- package/dist/state/providers.d.ts +17 -0
- package/dist/state/providers.js +33 -0
- package/dist/state/usage.d.ts +44 -0
- package/dist/state/usage.js +121 -0
- package/dist/storage.d.ts +20 -0
- package/dist/storage.js +89 -0
- package/dist/theme.css +212 -0
- package/dist/transport.d.ts +24 -0
- package/dist/transport.js +18 -0
- package/dist/ui/PlainTextarea.d.ts +2 -0
- package/dist/ui/PlainTextarea.js +5 -0
- package/dist/usage/LimitsList.d.ts +18 -0
- package/dist/usage/LimitsList.js +73 -0
- package/dist/usage/UsageBreakdown.d.ts +9 -0
- package/dist/usage/UsageBreakdown.js +67 -0
- package/dist/usage/UsageChart.d.ts +10 -0
- package/dist/usage/UsageChart.js +47 -0
- package/dist/usage/UsageDialog.d.ts +6 -0
- package/dist/usage/UsageDialog.js +12 -0
- package/dist/usage/UsageLimits.d.ts +1 -0
- package/dist/usage/UsageLimits.js +57 -0
- package/dist/usage/UsageLimitsCard.d.ts +4 -0
- package/dist/usage/UsageLimitsCard.js +26 -0
- package/dist/usage/UsagePage.d.ts +7 -0
- package/dist/usage/UsagePage.js +154 -0
- package/dist/usage/UsagePane.d.ts +3 -0
- package/dist/usage/UsagePane.js +21 -0
- package/dist/usage/UsageSummary.d.ts +12 -0
- package/dist/usage/UsageSummary.js +15 -0
- package/dist/usage/UsageTiles.d.ts +7 -0
- package/dist/usage/UsageTiles.js +19 -0
- package/dist/usage/format.d.ts +13 -0
- package/dist/usage/format.js +55 -0
- package/dist/usage/limit-groups.d.ts +22 -0
- package/dist/usage/limit-groups.js +86 -0
- package/dist/usage/limits.d.ts +4 -0
- package/dist/usage/limits.js +58 -0
- package/dist/usage/money.d.ts +1 -0
- package/dist/usage/money.js +13 -0
- package/dist/usage/summary.d.ts +34 -0
- package/dist/usage/summary.js +94 -0
- package/package.json +895 -3
- package/src/agents/AccountDot.tsx +14 -0
- package/src/agents/AgentIcon.tsx +26 -0
- package/src/agents/ModelOptionControl.tsx +68 -0
- package/src/agents/ProviderLogo.tsx +20 -0
- package/src/agents/account-limits.ts +61 -0
- package/src/agents/accounts.ts +137 -0
- package/src/agents/model-name.ts +70 -0
- package/src/agents/model-options.ts +21 -0
- package/src/agents/provider-paths.ts +10 -0
- package/src/agents/status-look.ts +43 -0
- package/src/chat/account-choice.ts +44 -0
- package/src/chat/actions.ts +72 -0
- package/src/chat/activity.ts +8 -0
- package/src/chat/attachments.ts +118 -0
- package/src/chat/bookmarks.ts +87 -0
- package/src/chat/chat-client.ts +345 -0
- package/src/chat/chat-references.ts +11 -0
- package/src/chat/drafts.ts +165 -0
- package/src/chat/forks.ts +33 -0
- package/src/chat/guards.ts +84 -0
- package/src/chat/logic/ansi.ts +206 -0
- package/src/chat/logic/answers.ts +8 -0
- package/src/chat/logic/bookmarks.ts +42 -0
- package/src/chat/logic/context-usage.ts +36 -0
- package/src/chat/logic/fork.ts +200 -0
- package/src/chat/logic/handback.ts +10 -0
- package/src/chat/logic/json.ts +4 -0
- package/src/chat/logic/limit.ts +46 -0
- package/src/chat/logic/resume-compaction.ts +71 -0
- package/src/chat/logic/scrubber.ts +289 -0
- package/src/chat/logic/thread-cards.ts +64 -0
- package/src/chat/logic/timeline-copy.ts +65 -0
- package/src/chat/logic/timeline-target.ts +52 -0
- package/src/chat/logic/timeline.ts +419 -0
- package/src/chat/logic/tool-catalog.ts +62 -0
- package/src/chat/logic/tools.ts +102 -0
- package/src/chat/logic/welcome.ts +13 -0
- package/src/chat/logic/workflow.ts +66 -0
- package/src/chat/mentions.ts +232 -0
- package/src/chat/persisted-json.ts +67 -0
- package/src/chat/preferences.ts +179 -0
- package/src/chat/quote.ts +26 -0
- package/src/chat/recent-messages.ts +59 -0
- package/src/chat/resume-compaction-dismissals.ts +17 -0
- package/src/chat/runtime-modes.ts +18 -0
- package/src/chat/stash.ts +122 -0
- package/src/chat/subagent-conversation.ts +203 -0
- package/src/chat/subagent-list.ts +141 -0
- package/src/chat/subagent-support.ts +21 -0
- package/src/chat/subagent-view.ts +137 -0
- package/src/chat/thumbnails.ts +108 -0
- package/src/chat/timeline-flash.ts +33 -0
- package/src/chat/timeline-scroll.ts +199 -0
- package/src/chat/ui/AccountPill.tsx +31 -0
- package/src/chat/ui/AnsiOutput.tsx +18 -0
- package/src/chat/ui/BookmarkMarker.tsx +108 -0
- package/src/chat/ui/BookmarkSubmenu.tsx +53 -0
- package/src/chat/ui/ChatActivity.tsx +198 -0
- package/src/chat/ui/ChatReferenceChip.tsx +28 -0
- package/src/chat/ui/CodeBlock.tsx +175 -0
- package/src/chat/ui/Composer.tsx +1326 -0
- package/src/chat/ui/ComposerInput.tsx +187 -0
- package/src/chat/ui/DiffPool.tsx +36 -0
- package/src/chat/ui/EditDiff.tsx +30 -0
- package/src/chat/ui/FadingWords.tsx +18 -0
- package/src/chat/ui/ImageView.tsx +159 -0
- package/src/chat/ui/LimitState.tsx +165 -0
- package/src/chat/ui/Markdown.tsx +258 -0
- package/src/chat/ui/MessageActions.tsx +88 -0
- package/src/chat/ui/Pickers.tsx +272 -0
- package/src/chat/ui/PromptComposer.tsx +119 -0
- package/src/chat/ui/QuoteButton.tsx +103 -0
- package/src/chat/ui/ResumeCompactionDock.tsx +28 -0
- package/src/chat/ui/RunSettings.tsx +546 -0
- package/src/chat/ui/Scrubber.tsx +262 -0
- package/src/chat/ui/SubagentControls.tsx +66 -0
- package/src/chat/ui/SubagentInfo.tsx +67 -0
- package/src/chat/ui/SubagentStopButton.tsx +45 -0
- package/src/chat/ui/SubagentTimeline.tsx +170 -0
- package/src/chat/ui/Timeline.tsx +628 -0
- package/src/chat/ui/TimelineMenu.tsx +124 -0
- package/src/chat/ui/UnifiedDiff.tsx +99 -0
- package/src/chat/ui/UploadThumb.tsx +13 -0
- package/src/chat/ui/Welcome.tsx +22 -0
- package/src/chat/ui/chips.ts +15 -0
- package/src/chat/ui/code-lines.ts +60 -0
- package/src/chat/ui/code-streaming.ts +4 -0
- package/src/chat/ui/code-theme.ts +15 -0
- package/src/chat/ui/composer/chips.ts +43 -0
- package/src/chat/ui/composer/editor.ts +118 -0
- package/src/chat/ui/composer/insert.ts +22 -0
- package/src/chat/ui/composer/keys.ts +144 -0
- package/src/chat/ui/diff-theme.ts +23 -0
- package/src/chat/ui/file-links.ts +24 -0
- package/src/chat/ui/find-reveal.ts +23 -0
- package/src/chat/ui/full-diff.ts +25 -0
- package/src/chat/ui/icons.tsx +24 -0
- package/src/chat/ui/markdown-blocks.ts +123 -0
- package/src/chat/ui/quote-selection.ts +53 -0
- package/src/chat/ui/rehype-chips.ts +62 -0
- package/src/chat/ui/rehype-fade.ts +64 -0
- package/src/chat/ui/remark-html-as-text.ts +36 -0
- package/src/chat/ui/reply-context.ts +4 -0
- package/src/chat/ui/reveal.ts +135 -0
- package/src/chat/ui/rows/ForksRow.tsx +79 -0
- package/src/chat/ui/rows/MessageRows.tsx +415 -0
- package/src/chat/ui/rows/Rows.tsx +81 -0
- package/src/chat/ui/rows/SubagentRow.tsx +209 -0
- package/src/chat/ui/rows/TaskRow.tsx +91 -0
- package/src/chat/ui/rows/WorkRows.tsx +445 -0
- package/src/chat/ui/rows/WorkflowRow.tsx +120 -0
- package/src/chat/ui/rows/row-rhythm.ts +37 -0
- package/src/chat/ui/useToggleSet.ts +39 -0
- package/src/host.ts +324 -0
- package/src/lazy.tsx +64 -0
- package/src/locales/en/agent-chat.json +446 -0
- package/src/locales/en/agent-prompts.json +42 -0
- package/src/locales/en/agent-providers.json +131 -0
- package/src/locales/en/agent-usage.json +131 -0
- package/src/locales/nl/agent-chat.json +446 -0
- package/src/locales/nl/agent-prompts.json +42 -0
- package/src/locales/nl/agent-providers.json +131 -0
- package/src/locales/nl/agent-usage.json +131 -0
- package/src/locales.ts +33 -0
- package/src/mounted-registry.ts +45 -0
- package/src/port-transport.ts +146 -0
- package/src/prompts/logic/focus.ts +25 -0
- package/src/prompts/logic/keys.ts +116 -0
- package/src/prompts/logic/prompts.fixtures.ts +84 -0
- package/src/prompts/logic/prompts.ts +58 -0
- package/src/prompts/logic/subjects.ts +122 -0
- package/src/prompts/logic/useFocusAfterAnswer.ts +38 -0
- package/src/prompts/logic/usePromptSession.ts +114 -0
- package/src/prompts/ui/ApprovalBody.tsx +109 -0
- package/src/prompts/ui/PromptActions.tsx +109 -0
- package/src/prompts/ui/PromptCard.tsx +101 -0
- package/src/prompts/ui/PromptView.tsx +111 -0
- package/src/prompts/ui/QuestionBody.tsx +174 -0
- package/src/providers/AccountColors.tsx +8 -0
- package/src/providers/AccountDetail.tsx +209 -0
- package/src/providers/AccountVariables.tsx +126 -0
- package/src/providers/AddAccountForm.tsx +121 -0
- package/src/providers/CliDetail.tsx +157 -0
- package/src/providers/ProvidersPane.tsx +236 -0
- package/src/providers/account-actions.ts +67 -0
- package/src/providers/parts.tsx +25 -0
- package/src/providers/provider-abilities.ts +9 -0
- package/src/providers/variables.ts +87 -0
- package/src/scope.ts +30 -0
- package/src/settings/sections.ts +47 -0
- package/src/state/chats.ts +279 -0
- package/src/state/provider-accounts.ts +87 -0
- package/src/state/providers.ts +50 -0
- package/src/state/usage.ts +196 -0
- package/src/storage.ts +113 -0
- package/src/theme.css +212 -0
- package/src/transport.ts +50 -0
- package/src/ui/PlainTextarea.tsx +6 -0
- package/src/usage/LimitsList.tsx +232 -0
- package/src/usage/UsageBreakdown.tsx +210 -0
- package/src/usage/UsageChart.tsx +113 -0
- package/src/usage/UsageDialog.tsx +20 -0
- package/src/usage/UsageLimits.tsx +145 -0
- package/src/usage/UsageLimitsCard.tsx +36 -0
- package/src/usage/UsagePage.tsx +276 -0
- package/src/usage/UsagePane.tsx +52 -0
- package/src/usage/UsageSummary.tsx +50 -0
- package/src/usage/UsageTiles.tsx +34 -0
- package/src/usage/format.ts +71 -0
- package/src/usage/limit-groups.ts +119 -0
- package/src/usage/limits.ts +71 -0
- package/src/usage/money.ts +14 -0
- package/src/usage/summary.ts +137 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TimelineRow } from '../../logic/timeline.js';
|
|
2
|
+
import type { SubagentStep } from '../../subagent-view.js';
|
|
3
|
+
export interface RowProps {
|
|
4
|
+
row: TimelineRow;
|
|
5
|
+
chatId: string;
|
|
6
|
+
toggleGroup(id: string): void;
|
|
7
|
+
toggleTurn(id: string): void;
|
|
8
|
+
toggleSubagent(id: string): void;
|
|
9
|
+
openSubagent(toolUseId: string): void;
|
|
10
|
+
openConversation?(step: SubagentStep): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function Row({ row, chatId, toggleGroup, toggleTurn, toggleSubagent, openSubagent, openConversation }: RowProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { ErrorBoundary } from '@adecore/ui';
|
|
4
|
+
import { AgentTurnRow, ApprovalHistoryRow, AssistantRow, CompactionRow, NoteRow, QuestionHistoryRow, ReportRow, ThinkingRow, UserRow } from './MessageRows.js';
|
|
5
|
+
import { ForksRow } from './ForksRow.js';
|
|
6
|
+
import { SubagentBranchRow } from './SubagentRow.js';
|
|
7
|
+
import { WorkflowRow } from './WorkflowRow.js';
|
|
8
|
+
import { ChangedFilesRow, TurnFoldRow, WorkGroupRow, WorkLiveRow, WorkRow, WorkingRow } from './WorkRows.js';
|
|
9
|
+
/* Its own component, so a card that throws while it renders is caught by the boundary around it. */
|
|
10
|
+
function AppCardBody({ card }) {
|
|
11
|
+
return card.render();
|
|
12
|
+
}
|
|
13
|
+
function AppCardRow({ card }) {
|
|
14
|
+
const { t } = useTranslation('agent-chat');
|
|
15
|
+
return (_jsx(ErrorBoundary, { label: t('timeline.cardFailed'), resetKeys: [card], compact: true, className: "relative rounded-lg", children: _jsx(AppCardBody, { card: card }) }));
|
|
16
|
+
}
|
|
17
|
+
/* One row of a thread, the chat's own or a subagent's read back, drawn the same way in both. */
|
|
18
|
+
export function Row({ row, chatId, toggleGroup, toggleTurn, toggleSubagent, openSubagent, openConversation }) {
|
|
19
|
+
switch (row.kind) {
|
|
20
|
+
case 'user':
|
|
21
|
+
return _jsx(UserRow, { chatId: chatId, item: row.item });
|
|
22
|
+
case 'turn-start': {
|
|
23
|
+
const toolUseId = row.turn.taskToolUseId;
|
|
24
|
+
return _jsx(AgentTurnRow, { label: row.label, onOpen: toolUseId ? () => openSubagent(toolUseId) : undefined });
|
|
25
|
+
}
|
|
26
|
+
case 'assistant':
|
|
27
|
+
return _jsx(AssistantRow, { chatId: chatId, item: row.item });
|
|
28
|
+
case 'report':
|
|
29
|
+
return _jsx(ReportRow, { id: row.id, text: row.text });
|
|
30
|
+
case 'thinking':
|
|
31
|
+
return _jsx(ThinkingRow, { chatId: chatId, item: row.item });
|
|
32
|
+
case 'work':
|
|
33
|
+
return _jsx(WorkRow, { tool: row.tool });
|
|
34
|
+
case 'work-live':
|
|
35
|
+
return _jsx(WorkLiveRow, { chatId: chatId, tool: row.tool });
|
|
36
|
+
case 'workflow':
|
|
37
|
+
return _jsx(WorkflowRow, { chatId: chatId, tool: row.tool, workflow: row.workflow, onOpenAgent: openConversation });
|
|
38
|
+
case 'work-group':
|
|
39
|
+
return _jsx(WorkGroupRow, { tools: row.tools, summary: row.summary, expanded: row.expanded, onToggle: () => toggleGroup(row.id) });
|
|
40
|
+
case 'subagent':
|
|
41
|
+
return _jsx(SubagentBranchRow, { chatId: chatId, branch: row, onToggle: toggleSubagent, onOpenConversation: openConversation });
|
|
42
|
+
case 'turn-fold':
|
|
43
|
+
return _jsx(TurnFoldRow, { turn: row.turn, label: row.label, work: row.work, expanded: row.expanded, onToggle: () => toggleTurn(row.turn.id) });
|
|
44
|
+
case 'forks':
|
|
45
|
+
return _jsx(ForksRow, { chatId: chatId, turnId: row.turnId });
|
|
46
|
+
case 'changed-files':
|
|
47
|
+
return _jsx(ChangedFilesRow, { chatId: chatId, turnId: row.turnId, tools: row.tools, diff: row.diff, checkpoint: row.checkpoint });
|
|
48
|
+
case 'approval':
|
|
49
|
+
return _jsx(ApprovalHistoryRow, { item: row.item });
|
|
50
|
+
case 'question':
|
|
51
|
+
return _jsx(QuestionHistoryRow, { item: row.item });
|
|
52
|
+
case 'note':
|
|
53
|
+
return _jsx(NoteRow, { id: row.id, level: row.level, text: row.text, from: row.from });
|
|
54
|
+
case 'compaction':
|
|
55
|
+
return _jsx(CompactionRow, { preTokens: row.preTokens });
|
|
56
|
+
case 'working':
|
|
57
|
+
return _jsx(WorkingRow, { startedAt: row.startedAt });
|
|
58
|
+
case 'app-card':
|
|
59
|
+
return _jsx(AppCardRow, { card: row.card });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChatItem, ChatSubagentItem } from '@adecore/agent-contracts';
|
|
2
|
+
import type { SubagentBranch } from '../../logic/timeline.js';
|
|
3
|
+
import { type SubagentStep } from '../../subagent-view.js';
|
|
4
|
+
export declare function SubagentRow({ chatId, item, work, expanded, onToggle, onOpenConversation }: {
|
|
5
|
+
chatId: string;
|
|
6
|
+
item: ChatSubagentItem;
|
|
7
|
+
work: ChatItem[];
|
|
8
|
+
expanded: boolean;
|
|
9
|
+
onToggle(): void;
|
|
10
|
+
onOpenConversation?(): void;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
12
|
+
export declare function SubagentBranchRow({ chatId, branch, onToggle, onOpenConversation }: {
|
|
13
|
+
chatId: string;
|
|
14
|
+
branch: SubagentBranch;
|
|
15
|
+
onToggle(id: string): void;
|
|
16
|
+
onOpenConversation?(step: SubagentStep): void;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useLayoutEffect, useRef, useState } from 'react';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { Bot, ChevronDown } from 'lucide-react';
|
|
6
|
+
import { formatElapsedShort } from '@adecore/ui/format';
|
|
7
|
+
import { Icon, useNow } from '@adecore/ui';
|
|
8
|
+
import { useOpenForFind } from '../find-reveal.js';
|
|
9
|
+
import { Markdown } from '../Markdown.js';
|
|
10
|
+
import { TaskRow } from './TaskRow.js';
|
|
11
|
+
import { RunningFor, ToggleLine, WorkLiveRow, WorkRow } from './WorkRows.js';
|
|
12
|
+
import { entryTimeOf, statusWordOf, taskIdOf } from '../../subagent-list.js';
|
|
13
|
+
import { useSubagentSupport } from '../../subagent-support.js';
|
|
14
|
+
import { canOpenSubagent, crumbOf } from '../../subagent-view.js';
|
|
15
|
+
import { chatHost } from '../../../host.js';
|
|
16
|
+
import { useChatScope } from '../../../scope.js';
|
|
17
|
+
import { useCurrentItem } from '../../../state/chats.js';
|
|
18
|
+
// The work of a long-running agent scrolls inside its row instead of pushing the thread away.
|
|
19
|
+
const CHILDREN_MAX_PX = 320;
|
|
20
|
+
/*
|
|
21
|
+
* One step a sub-agent took, inside its parent's row. The thread's own `Row` draws the same kinds,
|
|
22
|
+
* but off a timeline it has already grouped and folded, and it writes an answer at the size of a
|
|
23
|
+
* message; here every step is a line and the text is the aside under it.
|
|
24
|
+
*/
|
|
25
|
+
function ChildRow({ chatId, item }) {
|
|
26
|
+
if (item.kind === 'tool') {
|
|
27
|
+
return item.state === 'running' ? _jsx(WorkLiveRow, { chatId: chatId, tool: item }) : _jsx(WorkRow, { tool: item });
|
|
28
|
+
}
|
|
29
|
+
if (item.kind === 'assistant') {
|
|
30
|
+
return _jsx(ChildText, { chatId: chatId, item: item });
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
function ChildText({ chatId, item: derived }) {
|
|
35
|
+
const item = useCurrentItem(chatId, derived);
|
|
36
|
+
return (_jsx("div", { className: "-mx-1 px-1 pb-2 text-xs text-text-muted select-text", children: _jsx(Markdown, { text: item.text }) }));
|
|
37
|
+
}
|
|
38
|
+
function StatusPill({ item, task }) {
|
|
39
|
+
const { t } = useTranslation('agent-chat');
|
|
40
|
+
const paused = statusWordOf(item, task) === 'paused';
|
|
41
|
+
const now = useNow(60_000, paused);
|
|
42
|
+
if (paused) {
|
|
43
|
+
return _jsx("span", { className: "shrink-0 text-xs text-text-faint tabular-nums", children: entryTimeOf(item, task, now) });
|
|
44
|
+
}
|
|
45
|
+
if (item.status === 'running') {
|
|
46
|
+
return _jsx(RunningFor, { startedAt: item.startedAt });
|
|
47
|
+
}
|
|
48
|
+
const failed = item.status === 'failed';
|
|
49
|
+
const duration = item.finishedAt === null ? null : formatElapsedShort(item.finishedAt - item.startedAt);
|
|
50
|
+
const outcome = failed ? 'failed' : 'done';
|
|
51
|
+
return (_jsx("span", { className: clsx('shrink-0 text-xs tabular-nums', failed ? 'text-status-error' : 'text-text-faint'), children: duration === null ? t(`common.status.${outcome}`) : t(`rows.subagent.${outcome}In`, { duration }) }));
|
|
52
|
+
}
|
|
53
|
+
/* What the sub-agent did, live: its own tool calls and the text it wrote, as ordinary rows. */
|
|
54
|
+
function SubagentWork({ chatId, item, work }) {
|
|
55
|
+
const { t } = useTranslation('agent-chat');
|
|
56
|
+
const scroller = useRef(null);
|
|
57
|
+
const running = item.status === 'running';
|
|
58
|
+
useLayoutEffect(() => {
|
|
59
|
+
// While it works, the newest line is the one worth seeing.
|
|
60
|
+
if (running && scroller.current) {
|
|
61
|
+
scroller.current.scrollTop = scroller.current.scrollHeight;
|
|
62
|
+
}
|
|
63
|
+
}, [work.length, running]);
|
|
64
|
+
if (work.length === 0) {
|
|
65
|
+
// A line inside a chat row, where the centered block of an EmptyState would outweigh the row itself.
|
|
66
|
+
return _jsx("div", { className: "ml-6 pb-1 text-xs text-text-faint", children: t('rows.subagent.nothingYet') });
|
|
67
|
+
}
|
|
68
|
+
return (_jsxs("div", { ref: scroller, className: "ml-6 overflow-y-auto", style: { maxHeight: CHILDREN_MAX_PX }, children: [item.itemsTruncated && _jsx("div", { className: "pb-1 text-xs text-text-faint", children: t('rows.subagent.truncated') }), work.map((child) => (_jsx(ChildRow, { chatId: chatId, item: child }, child.id)))] }));
|
|
69
|
+
}
|
|
70
|
+
/* The report the sub-agent handed back, behind a fold: the row is about the work, this is the answer. */
|
|
71
|
+
function SubagentResult({ itemId, result }) {
|
|
72
|
+
const { t } = useTranslation('agent-chat');
|
|
73
|
+
const [open, setOpen] = useState(false);
|
|
74
|
+
useOpenForFind(itemId, 'output', setOpen);
|
|
75
|
+
return (_jsxs("div", { className: "ml-6 pb-1", children: [_jsxs("button", { className: "flex items-center gap-1.5 text-xs text-text-muted hover:text-text", onClick: () => setOpen((o) => !o), children: [_jsx(Icon, { icon: ChevronDown, size: 12, className: clsx('transition-transform', open && 'rotate-180') }), open ? t('rows.subagent.hideResult') : t('rows.subagent.showResult')] }), open && (_jsx("div", { "data-find-field": "output", className: "mt-1 rounded-md border border-border bg-surface-raised px-3 py-2 select-text", children: _jsx(Markdown, { text: result }) }))] }));
|
|
76
|
+
}
|
|
77
|
+
/*
|
|
78
|
+
* One agent the agent delegated to. The line says what it is doing and for how long; pressing it
|
|
79
|
+
* opens the whole conversation in the thread's place, and where there is none to open it folds out
|
|
80
|
+
* the work the thread kept and, once it settled, the report it wrote.
|
|
81
|
+
*/
|
|
82
|
+
export function SubagentRow({ chatId, item, work, expanded, onToggle, onOpenConversation }) {
|
|
83
|
+
const { t } = useTranslation('agent-chat');
|
|
84
|
+
const { id } = useChatScope();
|
|
85
|
+
const taskId = taskIdOf(item);
|
|
86
|
+
const task = chatHost().tasks.useTask(id, taskId);
|
|
87
|
+
// A task paused on its child's limit is still a running row on the wire, but nothing is at work.
|
|
88
|
+
const running = item.status === 'running' && statusWordOf(item, task) !== 'paused';
|
|
89
|
+
const detail = item.description || item.summary || item.subagentType || '';
|
|
90
|
+
// A row that carries no pointer on a host that already said no has nothing to open.
|
|
91
|
+
const refused = useSubagentSupport((s) => s.unsupported[id] === true);
|
|
92
|
+
const press = onOpenConversation !== undefined && canOpenSubagent(item, refused) ? onOpenConversation : onToggle;
|
|
93
|
+
return (_jsxs("div", { "data-find-item": item.id, children: [item.origin === 'ruimte' ? (_jsx(TaskRow, { item: item, task: task, open: expanded, onPress: press })) : (_jsx(ToggleLine, { icon: _jsx(Icon, { icon: Bot, size: 12 }), label: t('rows.subagent.label'), detail: detail, open: expanded, onToggle: press, failed: item.status === 'failed', live: running, trailing: _jsxs(_Fragment, { children: [item.background && _jsx("span", { className: "shrink-0 text-xs text-text-faint", children: t('rows.subagent.background') }), running && item.lastTool && _jsx("span", { className: "shrink-0 text-xs text-text-faint", children: item.lastTool }), _jsx(StatusPill, { item: item, task: task })] }) })), expanded && (_jsxs("div", { className: "mb-1", children: [_jsx(SubagentWork, { chatId: chatId, item: item, work: work }), item.result !== null && _jsx(SubagentResult, { itemId: item.id, result: item.result })] }))] }));
|
|
94
|
+
}
|
|
95
|
+
/*
|
|
96
|
+
* A sub-agent's row with the agents it opened in turn under it. Those stay in sight whether its own
|
|
97
|
+
* work is folded or not, since opening the parent shows its conversation and not theirs.
|
|
98
|
+
*/
|
|
99
|
+
export function SubagentBranchRow({ chatId, branch, onToggle, onOpenConversation }) {
|
|
100
|
+
return (_jsxs(_Fragment, { children: [_jsx(SubagentRow, { chatId: chatId, item: branch.item, work: branch.children, expanded: branch.expanded, onToggle: () => onToggle(branch.id), onOpenConversation: onOpenConversation ? () => onOpenConversation(crumbOf(branch.item)) : undefined }), branch.nested.length > 0 && (_jsx("div", { className: "ml-6", children: branch.nested.map((child) => (_jsx(SubagentBranchRow, { chatId: chatId, branch: child, onToggle: onToggle, onOpenConversation: onOpenConversation }, child.id))) }))] }));
|
|
101
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ChatSubagentItem } from '@adecore/agent-contracts';
|
|
2
|
+
import type { SubagentTask } from '../../../host.js';
|
|
3
|
+
export declare function TaskRow({ item, task, open, onPress }: {
|
|
4
|
+
item: ChatSubagentItem;
|
|
5
|
+
task: SubagentTask | null;
|
|
6
|
+
open: boolean;
|
|
7
|
+
onPress(): void;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Bot, ChevronRight } from 'lucide-react';
|
|
5
|
+
import { formatElapsedShort, formatMoment } from '@adecore/ui/format';
|
|
6
|
+
import { Icon, useNow, useTickingText } from '@adecore/ui';
|
|
7
|
+
import { AgentIcon } from '../../../agents/AgentIcon.js';
|
|
8
|
+
import { modelName, shortModelName } from '../../../agents/model-name.js';
|
|
9
|
+
import { useChatScope } from '../../../scope.js';
|
|
10
|
+
import { useChats } from '../../../state/chats.js';
|
|
11
|
+
import { useProviders } from '../../../state/providers.js';
|
|
12
|
+
import { taskRowStateOf } from '../../subagent-list.js';
|
|
13
|
+
const DOT = {
|
|
14
|
+
running: 'bg-status-running',
|
|
15
|
+
waiting: 'bg-status-needs-you',
|
|
16
|
+
paused: 'bg-text-faint',
|
|
17
|
+
done: 'bg-status-idle',
|
|
18
|
+
failed: 'bg-status-error',
|
|
19
|
+
cancelled: 'bg-text-faint'
|
|
20
|
+
};
|
|
21
|
+
const STATE_TONE = {
|
|
22
|
+
running: 'text-text-muted chat-live-text',
|
|
23
|
+
waiting: 'text-status-needs-you',
|
|
24
|
+
paused: 'text-text-faint',
|
|
25
|
+
done: 'text-text-faint',
|
|
26
|
+
failed: 'text-status-error',
|
|
27
|
+
cancelled: 'text-text-faint'
|
|
28
|
+
};
|
|
29
|
+
function Elapsed({ startedAt }) {
|
|
30
|
+
const ref = useTickingText(() => formatElapsedShort(Date.now() - startedAt));
|
|
31
|
+
return _jsx("span", { ref: ref, className: "shrink-0 text-xs text-text-faint tabular-nums" });
|
|
32
|
+
}
|
|
33
|
+
function StateLine({ state, task }) {
|
|
34
|
+
const { t } = useTranslation('agent-chat');
|
|
35
|
+
const until = state === 'paused' ? task?.paused?.until : undefined;
|
|
36
|
+
const now = useNow(60_000, until === undefined);
|
|
37
|
+
return (_jsx("span", { className: clsx('truncate text-xs', STATE_TONE[state]), children: until === undefined ? t(`rows.task.${state}`) : t('rows.task.pausedUntil', { time: formatMoment(until, now) }) }));
|
|
38
|
+
}
|
|
39
|
+
/*
|
|
40
|
+
* The row of a task given to another node: that agent's mark and model, what the task is about and
|
|
41
|
+
* where it stands, read from the status every client gets of the child's chat. A child without one,
|
|
42
|
+
* a terminal or a node that is gone, keeps the task's own words.
|
|
43
|
+
*/
|
|
44
|
+
export function TaskRow({ item, task, open, onPress }) {
|
|
45
|
+
const { t } = useTranslation('agent-chat');
|
|
46
|
+
const { keyOf } = useChatScope();
|
|
47
|
+
const child = useChats((s) => (item.childId === undefined ? undefined : s.statusByKey[keyOf(item.childId)]?.info));
|
|
48
|
+
const provider = child?.provider;
|
|
49
|
+
const slug = child?.model ?? child?.selection.model ?? null;
|
|
50
|
+
const model = useProviders((s) => {
|
|
51
|
+
if (slug === null) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const models = s.providers.find((entry) => entry.kind === provider)?.models;
|
|
55
|
+
return shortModelName(modelName(slug, models), models);
|
|
56
|
+
});
|
|
57
|
+
const state = taskRowStateOf(item, task, child);
|
|
58
|
+
const title = item.description || t('rows.subagent.task');
|
|
59
|
+
const startedAt = task?.createdAt ?? item.startedAt;
|
|
60
|
+
const finishedAt = task === null ? item.finishedAt : (task.settledAt ?? item.finishedAt);
|
|
61
|
+
const settled = state === 'done' || state === 'failed' || state === 'cancelled';
|
|
62
|
+
return (_jsxs("button", { className: "-mx-1 mb-0.5 flex w-[calc(100%+8px)] items-center gap-2.5 rounded-md px-1 py-1 text-left hover:bg-surface-hover", onClick: onPress, children: [_jsxs("span", { className: "relative grid size-7 shrink-0 place-items-center rounded-full bg-surface-raised text-text", children: [provider === undefined ? _jsx(Icon, { icon: Bot, size: 14 }) : _jsx(AgentIcon, { kind: provider, size: 14 }), _jsx("span", { className: clsx('absolute -right-0.5 -bottom-0.5 size-2.5 rounded-full ring-2 ring-surface', DOT[state]) })] }), _jsxs("span", { className: "flex min-w-0 grow flex-col", children: [_jsx("span", { "data-find-field": "summary", className: "truncate text-xs font-medium text-text", children: model === null ? title : t('rows.task.named', { model, title }) }), _jsx(StateLine, { state: state, task: task })] }), (state === 'running' || state === 'waiting') && startedAt > 0 && _jsx(Elapsed, { startedAt: startedAt }), settled && startedAt > 0 && finishedAt !== null && finishedAt >= startedAt && (_jsx("span", { className: "shrink-0 text-xs text-text-faint tabular-nums", children: formatElapsedShort(finishedAt - startedAt) })), _jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') })] }));
|
|
63
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ChatCheckpointDiff, ChatToolItem, ChatTurnItem } from '@adecore/agent-contracts';
|
|
2
|
+
export declare function ToggleLine({ icon, label, detail, open, onToggle, failed, live, trailing, className }: {
|
|
3
|
+
icon: React.ReactNode;
|
|
4
|
+
label: string;
|
|
5
|
+
detail?: string;
|
|
6
|
+
open: boolean;
|
|
7
|
+
onToggle(): void;
|
|
8
|
+
failed?: boolean;
|
|
9
|
+
live?: boolean;
|
|
10
|
+
trailing?: React.ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
13
|
+
export declare function WorkRow({ tool, nested, detail }: {
|
|
14
|
+
tool: ChatToolItem;
|
|
15
|
+
nested?: boolean;
|
|
16
|
+
detail?: string;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
export declare function RunningFor({ startedAt }: {
|
|
19
|
+
startedAt: number;
|
|
20
|
+
}): import("react").JSX.Element;
|
|
21
|
+
export declare function WorkLiveRow({ chatId, tool: derived }: {
|
|
22
|
+
chatId: string;
|
|
23
|
+
tool: ChatToolItem;
|
|
24
|
+
}): import("react").JSX.Element;
|
|
25
|
+
export declare function WorkGroupRow({ tools, summary, expanded, onToggle }: {
|
|
26
|
+
tools: ChatToolItem[];
|
|
27
|
+
summary: string;
|
|
28
|
+
expanded: boolean;
|
|
29
|
+
onToggle(): void;
|
|
30
|
+
}): import("react").JSX.Element;
|
|
31
|
+
export declare function TurnFoldRow({ turn, label, work, expanded, onToggle }: {
|
|
32
|
+
turn: ChatTurnItem;
|
|
33
|
+
label: string;
|
|
34
|
+
work: readonly string[];
|
|
35
|
+
expanded: boolean;
|
|
36
|
+
onToggle(): void;
|
|
37
|
+
}): import("react").JSX.Element;
|
|
38
|
+
export declare function ChangedFilesRow({ tools, diff, checkpoint, chatId, turnId }: {
|
|
39
|
+
tools: ChatToolItem[];
|
|
40
|
+
diff: ChatCheckpointDiff | null;
|
|
41
|
+
checkpoint: boolean;
|
|
42
|
+
chatId: string;
|
|
43
|
+
turnId: string;
|
|
44
|
+
}): import("react").JSX.Element;
|
|
45
|
+
export declare function WorkingRow({ startedAt }: {
|
|
46
|
+
startedAt: number;
|
|
47
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Suspense, useEffect, useState } from 'react';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import i18next from 'i18next';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { ChevronRight, FileDiff, X } from 'lucide-react';
|
|
7
|
+
import { fileChanges, liveOutput, readImagePath, toolStartedAt, toolSummary, unifiedChanges } from '../../logic/tools.js';
|
|
8
|
+
import { useOpenForFind } from '../find-reveal.js';
|
|
9
|
+
import { chatHost } from '../../../host.js';
|
|
10
|
+
import { lazyNamed } from '../../../lazy.js';
|
|
11
|
+
import { useChatActions } from '../../actions.js';
|
|
12
|
+
import { useChatScope } from '../../../scope.js';
|
|
13
|
+
import { useCurrentItem } from '../../../state/chats.js';
|
|
14
|
+
import { useTimelineFlash } from '../../timeline-flash.js';
|
|
15
|
+
import { formatClockDuration, formatElapsedShort } from '@adecore/ui/format';
|
|
16
|
+
import { Icon, Spinner, useTickingText } from '@adecore/ui';
|
|
17
|
+
import { ROW_GUTTER, toolIcon } from '../icons.js';
|
|
18
|
+
import { AnsiOutput } from '../AnsiOutput.js';
|
|
19
|
+
// The diff renderers carry shiki; they only load once a thread shows a file change.
|
|
20
|
+
const EditDiff = lazyNamed(() => import('../EditDiff.js'), 'default');
|
|
21
|
+
const UnifiedDiff = lazyNamed(() => import('../UnifiedDiff.js'), 'default');
|
|
22
|
+
const OUTPUT_LIMIT = 4000;
|
|
23
|
+
function clip(text) {
|
|
24
|
+
return text.length > OUTPUT_LIMIT
|
|
25
|
+
? `${text.slice(0, OUTPUT_LIMIT)}\n${i18next.t('agent-chat:work.moreCharacters', { count: text.length - OUTPUT_LIMIT })}`
|
|
26
|
+
: text;
|
|
27
|
+
}
|
|
28
|
+
export function ToggleLine({ icon, label, detail, open, onToggle, failed, live, trailing, className }) {
|
|
29
|
+
return (_jsxs("button", { className: clsx(
|
|
30
|
+
// Fix the width so long commands reach the truncation inside the negative margins.
|
|
31
|
+
'-mx-1 mb-0.5 flex h-7 w-[calc(100%+8px)] items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted hover:bg-surface-hover', failed && 'text-status-error', className), onClick: onToggle, children: [_jsx("span", { className: clsx(ROW_GUTTER, live && 'text-accent'), children: icon }), _jsx("span", { className: clsx('shrink-0', live && 'chat-live-text'), children: label }), detail && (_jsx("span", { "data-find-field": "summary", className: "min-w-0 truncate font-mono text-text-faint", children: detail })), _jsx("span", { className: "grow" }), trailing, failed && _jsx(Icon, { icon: X, size: 12, className: "shrink-0" }), _jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90') })] }));
|
|
32
|
+
}
|
|
33
|
+
function ToolBody({ tool }) {
|
|
34
|
+
const { t } = useTranslation('agent-chat');
|
|
35
|
+
const patches = unifiedChanges(tool);
|
|
36
|
+
const changes = patches.length > 0 ? [] : fileChanges(tool.name, tool.input);
|
|
37
|
+
return (_jsxs("div", { className: "mt-1.5 mb-2 ml-6 overflow-hidden rounded-md border border-border bg-surface-raised", children: [patches.length > 0 ? (_jsx(Suspense, { fallback: _jsx("div", { className: "px-3 py-2 text-xs text-text-faint", children: t('work.loadingDiff') }), children: patches.map((change, index) => (_jsx(UnifiedDiff, { change: change }, index))) })) : changes.length > 0 ? (_jsx(Suspense, { fallback: _jsx("div", { className: "px-3 py-2 text-xs text-text-faint", children: t('work.loadingDiff') }), children: changes.map((change, index) => (_jsx(EditDiff, { change: change }, index))) })) : (_jsx("pre", { className: "max-h-64 overflow-auto px-3 py-2 font-mono text-code text-text-muted select-text", children: clip(JSON.stringify(tool.input, null, 2) ?? '') })), tool.output !== null && tool.output !== '' && patches.length === 0 && (_jsx("pre", { "data-find-field": "output", className: clsx('max-h-64 overflow-auto whitespace-pre-wrap border-t border-border px-3 py-2 font-mono text-code select-text', tool.state === 'error' ? 'text-chat-removed' : 'text-chat-output'), children: _jsx(AnsiOutput, { text: tool.output, limit: OUTPUT_LIMIT }) }))] }));
|
|
38
|
+
}
|
|
39
|
+
/* One settled tool call: a line, and its input and output behind it. An image the call looked at
|
|
40
|
+
is drawn under the line, because a picture says more about that read than its path does. */
|
|
41
|
+
export function WorkRow({ tool, nested, detail }) {
|
|
42
|
+
const [open, setOpen] = useState(false);
|
|
43
|
+
const image = tool.state === 'done' ? readImagePath(tool.name, tool.input) : null;
|
|
44
|
+
const { ReadImage } = chatHost();
|
|
45
|
+
useOpenForFind(tool.id, 'output', setOpen);
|
|
46
|
+
return (_jsxs("div", { "data-find-item": tool.id, className: nested ? 'ml-6' : undefined, children: [_jsx(ToggleLine, { icon: toolIcon(tool.name), label: tool.name, detail: detail ?? toolSummary(tool.name, tool.input), open: open, onToggle: () => setOpen((o) => !o), failed: tool.state === 'error' }), image !== null && ReadImage !== null && _jsx(ReadImage, { path: image }), open && _jsx(ToolBody, { tool: tool })] }));
|
|
47
|
+
}
|
|
48
|
+
/* "running for 12s" next to a live call. */
|
|
49
|
+
export function RunningFor({ startedAt }) {
|
|
50
|
+
const { t } = useTranslation('agent-chat');
|
|
51
|
+
const ref = useTickingText(() => t('work.runningFor', { elapsed: formatElapsedShort(Date.now() - startedAt) }));
|
|
52
|
+
return _jsx("span", { ref: ref, className: "shrink-0 text-xs text-text-faint tabular-nums" });
|
|
53
|
+
}
|
|
54
|
+
/* A call still running: its timer on the line, and for a provider that streams output, the last lines under it. */
|
|
55
|
+
export function WorkLiveRow({ chatId, tool: derived }) {
|
|
56
|
+
const [open, setOpen] = useState(false);
|
|
57
|
+
const tool = useCurrentItem(chatId, derived);
|
|
58
|
+
const tail = liveOutput(tool);
|
|
59
|
+
return (_jsxs("div", { children: [_jsx(ToggleLine, { icon: toolIcon(tool.name), label: tool.name, detail: toolSummary(tool.name, tool.input) || tool.progress?.description || '', open: open, onToggle: () => setOpen((o) => !o), trailing: _jsx(RunningFor, { startedAt: toolStartedAt(tool) }), live: true }), open && _jsx(ToolBody, { tool: tool }), tail !== null && !open && (_jsx("pre", { className: "mt-1.5 mb-2 ml-6 max-h-48 overflow-auto rounded-md border border-border bg-surface-raised px-3 py-2 font-mono text-code whitespace-pre-wrap text-chat-output select-text", children: _jsx(AnsiOutput, { text: tail, tailLines: 12 }) }))] }));
|
|
60
|
+
}
|
|
61
|
+
/* A run of tool calls as one line ("Read 4 files"); opening it lists every call. */
|
|
62
|
+
export function WorkGroupRow({ tools, summary, expanded, onToggle }) {
|
|
63
|
+
const failed = tools.some((tool) => tool.state === 'error');
|
|
64
|
+
return (_jsx("div", { children: _jsx(ToggleLine, { icon: toolIcon(tools[0].name), label: summary, open: expanded, onToggle: onToggle, failed: failed }) }));
|
|
65
|
+
}
|
|
66
|
+
/*
|
|
67
|
+
* A settled turn folded behind how long it took and what it did. A line and not a button, like the
|
|
68
|
+
* tool lines it hides; the work reads fainter than the time so the eye lands on the time first.
|
|
69
|
+
*/
|
|
70
|
+
export function TurnFoldRow({ turn, label, work, expanded, onToggle }) {
|
|
71
|
+
return (_jsxs("button", { className: clsx('group -mx-1 mb-2 flex h-7 w-[calc(100%+8px)] min-w-0 items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted hover:bg-surface-hover', turn.state === 'error' && 'text-status-error'), "aria-expanded": expanded, onClick: onToggle, children: [_jsx("span", { className: ROW_GUTTER, children: _jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('transition-transform', expanded && 'rotate-90') }) }), _jsx("span", { className: "shrink-0 group-hover:text-text", children: label }), work.length > 0 && _jsx("span", { className: "min-w-0 truncate text-text-faint", children: work.map((part) => ` · ${part}`).join('') })] }));
|
|
72
|
+
}
|
|
73
|
+
function omittedLabel(reason) {
|
|
74
|
+
return reason === 'binary' ? i18next.t('agent-chat:work.omitted.binary') : i18next.t('agent-chat:work.omitted.tooLarge');
|
|
75
|
+
}
|
|
76
|
+
/* One file of a turn's checkpoint diff: its patch, or the reason there is none. */
|
|
77
|
+
function CheckpointFileBody({ file }) {
|
|
78
|
+
const { t } = useTranslation('agent-chat');
|
|
79
|
+
if (file.omitted) {
|
|
80
|
+
return _jsx("div", { className: "px-3 py-2 text-xs text-text-faint", children: omittedLabel(file.omitted) });
|
|
81
|
+
}
|
|
82
|
+
return (_jsx(Suspense, { fallback: _jsx("div", { className: "px-3 py-2 text-xs text-text-faint", children: t('work.loadingDiff') }), children: _jsx(UnifiedDiff, { change: file }) }));
|
|
83
|
+
}
|
|
84
|
+
/* The frame of a changed files card: a header that folds the list of files away. */
|
|
85
|
+
function ChangedFilesCard({ count, truncated, added, deleted, revealNonce = 0, children }) {
|
|
86
|
+
const { t } = useTranslation('agent-chat');
|
|
87
|
+
const [expanded, setExpanded] = useState(false);
|
|
88
|
+
// A jump from outside opens the card, also when the jump put the row on screen and so mounted it; the flash is gone by the time the row is scrolled to again.
|
|
89
|
+
const [seenReveal, setSeenReveal] = useState(0);
|
|
90
|
+
if (revealNonce > 0 && revealNonce !== seenReveal) {
|
|
91
|
+
setSeenReveal(revealNonce);
|
|
92
|
+
setExpanded(true);
|
|
93
|
+
}
|
|
94
|
+
return (_jsxs("div", { className: "mb-3 overflow-hidden rounded-lg border border-border bg-surface-raised", children: [_jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-text-muted hover:bg-surface-hover", "aria-expanded": expanded, onClick: () => setExpanded((value) => !value), children: [_jsx(Icon, { icon: FileDiff, size: 12, className: "shrink-0" }), _jsx("span", { className: "shrink-0 font-medium text-text", children: t('work.changedFiles', { count }) }), truncated && _jsx("span", { className: "min-w-0 truncate text-text-faint", children: t('work.andMore') }), _jsx("span", { className: "grow" }), added !== undefined && _jsxs("span", { className: "text-chat-added tabular-nums", children: ["+", added] }), deleted !== undefined && _jsxs("span", { className: "text-chat-removed tabular-nums", children: ["-", deleted] }), _jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', expanded && 'rotate-90') })] }), expanded && children] }));
|
|
95
|
+
}
|
|
96
|
+
/*
|
|
97
|
+
* The files a settled turn changed, as a card; each file opens its diff in place. The host's
|
|
98
|
+
* checkpoint diff comes first (the working tree against the tree the turn started from), then the
|
|
99
|
+
* unified diffs the CLI reported, then the before and after of its own edits. A turn that has a
|
|
100
|
+
* checkpoint but no stored diff asks the host for one, which is also how a running turn gets it.
|
|
101
|
+
*/
|
|
102
|
+
export function ChangedFilesRow({ tools, diff, checkpoint, chatId, turnId }) {
|
|
103
|
+
const [open, setOpen] = useState({});
|
|
104
|
+
const [fetched, setFetched] = useState(null);
|
|
105
|
+
const actions = useChatActions();
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
if (diff !== null || !checkpoint) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
let alive = true;
|
|
111
|
+
void actions
|
|
112
|
+
.turnDiff(chatId, turnId)
|
|
113
|
+
.then((answer) => {
|
|
114
|
+
if (alive) {
|
|
115
|
+
setFetched(answer);
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
.catch(() => undefined);
|
|
119
|
+
return () => {
|
|
120
|
+
alive = false;
|
|
121
|
+
};
|
|
122
|
+
}, [actions, chatId, turnId, diff, checkpoint]);
|
|
123
|
+
const checkpointDiff = diff ?? fetched;
|
|
124
|
+
const { keyOf } = useChatScope();
|
|
125
|
+
const flash = useTimelineFlash((s) => s.target);
|
|
126
|
+
const revealNonce = flash !== null && flash.opens && flash.key === keyOf(chatId) && flash.rowId === `files-${turnId}` ? flash.nonce : 0;
|
|
127
|
+
if (checkpointDiff !== null && checkpointDiff.files.length > 0) {
|
|
128
|
+
const files = checkpointDiff.files;
|
|
129
|
+
return (_jsx(ChangedFilesCard, { revealNonce: revealNonce, count: files.length, truncated: checkpointDiff.truncated, added: files.reduce((sum, file) => sum + file.added, 0), deleted: files.reduce((sum, file) => sum + file.deleted, 0), children: files.map((file) => (_jsxs("div", { className: "border-t border-border", children: [_jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-text-muted hover:bg-surface-hover", "data-file-path": file.path, onClick: () => setOpen((o) => ({ ...o, [file.path]: !o[file.path] })), children: [_jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open[file.path] && 'rotate-90') }), _jsx("span", { className: "min-w-0 truncate font-mono text-text", children: file.path }), _jsx("span", { className: "grow" }), _jsxs("span", { className: "text-chat-added tabular-nums", children: ["+", file.added] }), _jsxs("span", { className: "text-chat-removed tabular-nums", children: ["-", file.deleted] })] }), open[file.path] && (_jsx("div", { className: "border-t border-border", children: _jsx(CheckpointFileBody, { file: file }) }))] }, file.path))) }));
|
|
130
|
+
}
|
|
131
|
+
return _jsx(ProviderChangedFiles, { tools: tools, open: open, setOpen: setOpen, revealNonce: revealNonce });
|
|
132
|
+
}
|
|
133
|
+
/* The fallback card, built from what the CLI itself reported about its edits. */
|
|
134
|
+
function ProviderChangedFiles({ tools, open, setOpen, revealNonce }) {
|
|
135
|
+
const { t } = useTranslation('agent-chat');
|
|
136
|
+
const byPath = new Map();
|
|
137
|
+
const entryFor = (path) => {
|
|
138
|
+
const existing = byPath.get(path);
|
|
139
|
+
if (existing) {
|
|
140
|
+
return existing;
|
|
141
|
+
}
|
|
142
|
+
const created = { edits: [], patches: [] };
|
|
143
|
+
byPath.set(path, created);
|
|
144
|
+
return created;
|
|
145
|
+
};
|
|
146
|
+
for (const tool of tools) {
|
|
147
|
+
const patches = unifiedChanges(tool);
|
|
148
|
+
if (patches.length > 0) {
|
|
149
|
+
for (const patch of patches) {
|
|
150
|
+
entryFor(patch.path).patches.push(patch);
|
|
151
|
+
}
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
for (const change of fileChanges(tool.name, tool.input)) {
|
|
155
|
+
entryFor(change.path || tool.id).edits.push(change);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return (_jsx(ChangedFilesCard, { count: byPath.size, revealNonce: revealNonce, children: [...byPath].map(([path, entry]) => {
|
|
159
|
+
const count = entry.edits.length + entry.patches.length;
|
|
160
|
+
return (_jsxs("div", { className: "border-t border-border", children: [_jsxs("button", { className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-text-muted hover:bg-surface-hover", "data-file-path": path, onClick: () => setOpen((o) => ({ ...o, [path]: !o[path] })), children: [_jsx(Icon, { icon: ChevronRight, size: 12, className: clsx('shrink-0 text-text-faint transition-transform', open[path] && 'rotate-90') }), _jsx("span", { className: "min-w-0 truncate font-mono text-text", children: path }), _jsx("span", { className: "grow" }), _jsx("span", { className: "text-text-faint", children: t('work.edits', { count }) })] }), open[path] && (_jsx("div", { className: "border-t border-border", children: _jsxs(Suspense, { fallback: _jsx("div", { className: "px-3 py-2 text-xs text-text-faint", children: t('work.loadingDiff') }), children: [entry.patches.map((change, index) => (_jsx(UnifiedDiff, { change: change }, `patch-${index}`))), entry.edits.map((change, index) => (_jsx(EditDiff, { change: change }, `edit-${index}`)))] }) }))] }, path));
|
|
161
|
+
}) }));
|
|
162
|
+
}
|
|
163
|
+
/* "Working for 00:14". */
|
|
164
|
+
export function WorkingRow({ startedAt }) {
|
|
165
|
+
const { t } = useTranslation('agent-chat');
|
|
166
|
+
const ref = useTickingText(() => formatClockDuration(Date.now() - startedAt));
|
|
167
|
+
return (_jsxs("div", { className: "-mx-1 mb-0.5 flex h-7 items-center gap-2 px-1 text-xs text-text-muted", children: [_jsx("span", { className: `${ROW_GUTTER} text-status-running`, children: _jsx(Spinner, { size: 12 }) }), _jsx("span", { className: "chat-live-text", children: t('work.workingFor') }), _jsx("span", { ref: ref, className: "tabular-nums" })] }));
|
|
168
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ChatToolItem, type ChatWorkflow } from '@adecore/agent-contracts';
|
|
2
|
+
import type { SubagentStep } from '../../subagent-view.js';
|
|
3
|
+
export declare function WorkflowRow({ tool, workflow, chatId, onOpenAgent }: {
|
|
4
|
+
tool: ChatToolItem;
|
|
5
|
+
workflow: ChatWorkflow;
|
|
6
|
+
chatId?: string;
|
|
7
|
+
onOpenAgent?(step: SubagentStep): void;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Bot, ListTree, TriangleAlert, Square } from 'lucide-react';
|
|
4
|
+
import { workflowAgentRef } from '@adecore/agent-contracts';
|
|
5
|
+
import { workflowAgentTime, workflowPhases } from '../../logic/workflow.js';
|
|
6
|
+
import { useSubagentSupport } from '../../subagent-support.js';
|
|
7
|
+
import { ROW_GUTTER } from '../icons.js';
|
|
8
|
+
import { RunningFor, ToggleLine, WorkLiveRow, WorkRow } from './WorkRows.js';
|
|
9
|
+
import { useChatScope } from '../../../scope.js';
|
|
10
|
+
import { Icon, IconButton } from '@adecore/ui';
|
|
11
|
+
import { useChatActions } from '../../actions.js';
|
|
12
|
+
import { chatHost } from '../../../host.js';
|
|
13
|
+
function AgentLine({ view, onOpen }) {
|
|
14
|
+
const { agent, state } = view;
|
|
15
|
+
const time = workflowAgentTime(view);
|
|
16
|
+
const running = state === 'running';
|
|
17
|
+
const agentId = agent.agentId;
|
|
18
|
+
// One still waiting has no transcript yet.
|
|
19
|
+
const open = onOpen !== undefined && agentId !== null ? () => onOpen({ toolUseId: workflowAgentRef(agentId), description: agent.label }) : () => undefined;
|
|
20
|
+
return (_jsx(ToggleLine, { icon: _jsx(Icon, { icon: Bot, size: 12 }), label: agent.label, detail: running ? (agent.lastTool ?? undefined) : undefined, open: false, onToggle: open, failed: state === 'failed', live: running, trailing: running && agent.startedAt !== null ? (_jsx(RunningFor, { startedAt: agent.startedAt })) : (_jsx("span", { className: "shrink-0 text-xs text-text-faint tabular-nums", children: time })) }));
|
|
21
|
+
}
|
|
22
|
+
function PhaseBlock({ phase, onOpen }) {
|
|
23
|
+
const { t } = useTranslation('agent-chat');
|
|
24
|
+
return (_jsxs("div", { children: [phase.title !== null && (_jsxs("div", { className: "mb-0.5 flex h-7 min-w-0 items-center gap-2 text-xs text-text-muted", children: [_jsx("span", { className: ROW_GUTTER, children: _jsx(Icon, { icon: ListTree, size: 12 }) }), _jsx("span", { className: "min-w-0 truncate", children: phase.title }), _jsx("span", { className: "grow" }), phase.agents.length === 0 && _jsx("span", { className: "shrink-0 text-text-faint", children: t('rows.workflow.notStarted') })] })), phase.agents.length > 0 && (_jsx("div", { className: phase.title === null ? undefined : 'ml-6', children: phase.agents.map((view) => (_jsx(AgentLine, { view: view, onOpen: onOpen }, view.agent.index))) }))] }));
|
|
25
|
+
}
|
|
26
|
+
// Keep background progress visible after the launcher turn ends.
|
|
27
|
+
export function WorkflowRow({ tool, workflow, chatId, onOpenAgent }) {
|
|
28
|
+
const { t } = useTranslation('agent-chat');
|
|
29
|
+
const { id } = useChatScope();
|
|
30
|
+
// A host that does not answer `chat.subagent` has no conversation to open for anyone.
|
|
31
|
+
const refused = useSubagentSupport((s) => s.unsupported[id] === true);
|
|
32
|
+
const running = tool.state === 'running';
|
|
33
|
+
const phases = workflowPhases(workflow, running);
|
|
34
|
+
const onOpen = refused ? undefined : onOpenAgent;
|
|
35
|
+
const actions = useChatActions();
|
|
36
|
+
const stop = () => {
|
|
37
|
+
if (chatId && workflow.taskId) {
|
|
38
|
+
void actions.stopTask(chatId, workflow.taskId).catch((error) => {
|
|
39
|
+
chatHost().notify({
|
|
40
|
+
kind: 'error',
|
|
41
|
+
title: t('activity.stopFailed'),
|
|
42
|
+
description: error instanceof Error ? error.message : t('subagents.noAnswer')
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("div", { className: "min-w-0 grow", children: running ? _jsx(WorkLiveRow, { chatId: chatId ?? '', tool: tool }) : _jsx(WorkRow, { tool: tool, detail: workflow.name ?? undefined }) }), running && chatId && workflow.taskId && _jsx(IconButton, { icon: Square, size: "xs", label: t('activity.stop'), onClick: stop })] }), running && workflow.stalledAt !== undefined && (_jsxs("p", { role: "status", className: "ml-6 mb-1 flex items-start gap-1.5 text-xs text-text-muted", children: [_jsx(Icon, { icon: TriangleAlert, size: 12, className: "mt-0.5 shrink-0 text-status-needs-you" }), _jsx("span", { children: t('rows.workflow.stalled') })] })), phases.length > 0 && (_jsx("div", { className: "ml-6", children: phases.map((phase) => (_jsx(PhaseBlock, { phase: phase, onOpen: onOpen }, phase.key))) }))] }));
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type TimelineRow } from '../../logic/timeline.js';
|
|
2
|
+
export declare const FOLLOW_THRESHOLD_PX = 40;
|
|
3
|
+
export declare function rowRhythm(row: TimelineRow, previous: TimelineRow | null): string;
|
|
4
|
+
export declare function replyHeader(row: TimelineRow, previous: TimelineRow | null): {
|
|
5
|
+
at: number | null;
|
|
6
|
+
} | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { isBlock } from '../../logic/timeline.js';
|
|
3
|
+
/* Below this distance from the bottom a thread follows what the agent writes; above it the reader scrolled back on purpose. */
|
|
4
|
+
export const FOLLOW_THRESHOLD_PX = 40;
|
|
5
|
+
/*
|
|
6
|
+
* The gaps a row wears for where it sits: a question is followed by its answer gap, and a seam where
|
|
7
|
+
* the list rhythm of tool lines meets the block rhythm of prose gets the block gap. A question
|
|
8
|
+
* already carries the gap before it, and the row after one is the answer, so neither takes a seam.
|
|
9
|
+
*/
|
|
10
|
+
export function rowRhythm(row, previous) {
|
|
11
|
+
const question = row.kind === 'user';
|
|
12
|
+
const seam = !question && previous !== null && previous.kind !== 'user' && isBlock(row) !== isBlock(previous);
|
|
13
|
+
return clsx(question && 'pb-(--chat-answer-gap)', seam && 'pt-(--chat-block-gap)');
|
|
14
|
+
}
|
|
15
|
+
/*
|
|
16
|
+
* Whether a reply's header goes over this row, and the time it shows: the first row after the question
|
|
17
|
+
* or the agent's own turn opener, whatever row that is, dated when that turn began. A thread that
|
|
18
|
+
* starts halfway through a reply has no time to show.
|
|
19
|
+
*/
|
|
20
|
+
export function replyHeader(row, previous) {
|
|
21
|
+
if (row.kind === 'user' || row.kind === 'turn-start') {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (previous === null) {
|
|
25
|
+
return { at: null };
|
|
26
|
+
}
|
|
27
|
+
if (previous.kind === 'user') {
|
|
28
|
+
return { at: previous.item.createdAt };
|
|
29
|
+
}
|
|
30
|
+
if (previous.kind === 'turn-start') {
|
|
31
|
+
return { at: previous.turn.createdAt };
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
/*
|
|
3
|
+
* The ids of the folds a thread has open. `onToggle` is what a thread does about a person opening
|
|
4
|
+
* one, which is to stop following the end: a fold is a deliberate look back, not a reason to jump.
|
|
5
|
+
*/
|
|
6
|
+
export function useToggleSet(onToggle) {
|
|
7
|
+
const [ids, setIds] = useState(() => new Set());
|
|
8
|
+
const toggle = useCallback((id) => {
|
|
9
|
+
setIds((current) => {
|
|
10
|
+
const next = new Set(current);
|
|
11
|
+
if (next.has(id)) {
|
|
12
|
+
next.delete(id);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
next.add(id);
|
|
16
|
+
}
|
|
17
|
+
return next;
|
|
18
|
+
});
|
|
19
|
+
onToggle?.();
|
|
20
|
+
}, [onToggle]);
|
|
21
|
+
const add = useCallback((id) => {
|
|
22
|
+
setIds((current) => new Set(current).add(id));
|
|
23
|
+
}, []);
|
|
24
|
+
return { ids, toggle, add };
|
|
25
|
+
}
|