@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,546 @@
|
|
|
1
|
+
import { useTranslation } from 'react-i18next';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import {
|
|
4
|
+
Activity,
|
|
5
|
+
TriangleAlert,
|
|
6
|
+
ChevronDown,
|
|
7
|
+
ChevronRight,
|
|
8
|
+
ChevronUp,
|
|
9
|
+
FilePen,
|
|
10
|
+
Gauge,
|
|
11
|
+
Hand,
|
|
12
|
+
Settings,
|
|
13
|
+
Shield,
|
|
14
|
+
ShieldAlert,
|
|
15
|
+
SlidersHorizontal,
|
|
16
|
+
type LucideIcon
|
|
17
|
+
} from 'lucide-react';
|
|
18
|
+
import type { AgentKind, ChatUsage, ModelInfo, ModelOptionDescriptor, ModelSelection, ProviderInfo, RuntimeMode } from '@adecore/agent-contracts';
|
|
19
|
+
import { AccountDot } from '../../agents/AccountDot';
|
|
20
|
+
import { limitsOfAccount, sessionWindow } from '../../agents/account-limits';
|
|
21
|
+
import { canContinueOn } from '../../agents/accounts';
|
|
22
|
+
import { AgentIcon } from '../../agents/AgentIcon';
|
|
23
|
+
import type { AccountChoice } from '../account-choice';
|
|
24
|
+
import { modelName, shortModelName } from '../../agents/model-name';
|
|
25
|
+
import { CONTEXT_OPTION, contextFraction, contextSegments, orderOptions, type ContextPart } from '../logic/context-usage';
|
|
26
|
+
import { RUNTIME_MODES } from '../runtime-modes';
|
|
27
|
+
import { formatClock, formatWeekdayClock, isSameDay, formatPercent, formatTokens } from '@adecore/ui/format';
|
|
28
|
+
import { Icon, Menu, Tooltip, useNow } from '@adecore/ui';
|
|
29
|
+
import { chatHost } from '../../host';
|
|
30
|
+
import { useUsageLimits } from '../../usage/limits';
|
|
31
|
+
|
|
32
|
+
const MINUTE_MS = 60_000;
|
|
33
|
+
|
|
34
|
+
const MODE_ICONS: Record<RuntimeMode, LucideIcon> = {
|
|
35
|
+
supervised: Hand,
|
|
36
|
+
'auto-accept-edits': FilePen,
|
|
37
|
+
auto: Shield,
|
|
38
|
+
'full-access': ShieldAlert
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// More choices than this do not fit beside the label, so they go in a submenu of their own.
|
|
42
|
+
const INLINE_CHOICES = 3;
|
|
43
|
+
|
|
44
|
+
const PART_COLORS: Record<ContextPart, string> = {
|
|
45
|
+
toolOutput: 'bg-chart-context-tools',
|
|
46
|
+
filesRead: 'bg-chart-context-files',
|
|
47
|
+
conversation: 'bg-chart-context-conversation',
|
|
48
|
+
system: 'bg-chart-context-system'
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const RING_RADIUS = 5;
|
|
52
|
+
const RING_CIRCUMFERENCE = 2 * Math.PI * RING_RADIUS;
|
|
53
|
+
|
|
54
|
+
interface RunSettingsProps {
|
|
55
|
+
disabled?: boolean;
|
|
56
|
+
/* Whose models may be picked: every installed chat CLI before the first message, the chat's own after it. */
|
|
57
|
+
providers: ProviderInfo[];
|
|
58
|
+
provider: AgentKind;
|
|
59
|
+
selection: ModelSelection;
|
|
60
|
+
model: ModelInfo | undefined;
|
|
61
|
+
runtimeMode: RuntimeMode;
|
|
62
|
+
effectiveRuntimeMode?: RuntimeMode;
|
|
63
|
+
permissionMode?: string;
|
|
64
|
+
/* Controlled, so `/model` in the composer can open the same menu a click on the pill does. */
|
|
65
|
+
open: boolean;
|
|
66
|
+
onOpenChange(open: boolean): void;
|
|
67
|
+
onModel(provider: AgentKind, slug: string): void;
|
|
68
|
+
onOption(id: string, value: string | boolean): void;
|
|
69
|
+
onMode(mode: RuntimeMode): void;
|
|
70
|
+
usage: ChatUsage;
|
|
71
|
+
/* While a turn runs, or without a machine, compacting has to wait. */
|
|
72
|
+
compactDisabled: boolean;
|
|
73
|
+
onCompact(): void;
|
|
74
|
+
/* Null while the chat's CLI has fewer than two accounts that are on. */
|
|
75
|
+
account: AccountPick | null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface AccountPick {
|
|
79
|
+
choice: AccountChoice;
|
|
80
|
+
/* Once the chat spoke, only an account that reads its conversation can take it over. */
|
|
81
|
+
started: boolean;
|
|
82
|
+
onPick(id: string): void;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function optionSummary(option: ModelOptionDescriptor, selection: ModelSelection): string | null {
|
|
86
|
+
const value = selection.options[option.id];
|
|
87
|
+
if (option.type === 'select') {
|
|
88
|
+
return option.choices.find((choice) => choice.id === (value ?? option.defaultChoice))?.label ?? null;
|
|
89
|
+
}
|
|
90
|
+
return (value ?? option.defaultValue) === true ? option.label : null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function optionIcon(option: ModelOptionDescriptor): LucideIcon {
|
|
94
|
+
return option.type === 'boolean' ? Gauge : option.id === CONTEXT_OPTION ? Activity : SlidersHorizontal;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function contextTone(fraction: number): string {
|
|
98
|
+
return fraction >= 0.9 ? 'text-status-error' : fraction >= 0.7 ? 'text-status-needs-you' : 'text-text';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// A radio group holds one string, so a model is named by its provider and its slug together.
|
|
102
|
+
function modelValue(provider: AgentKind, slug: string): string {
|
|
103
|
+
return `${provider}/${slug}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* Everything that decides how the next turn runs, behind one pill: the model, its own knobs and the
|
|
108
|
+
* permission mode. Model and effective permissions stay visible as the composer narrows.
|
|
109
|
+
*/
|
|
110
|
+
export function RunSettings({
|
|
111
|
+
disabled = false,
|
|
112
|
+
providers,
|
|
113
|
+
provider,
|
|
114
|
+
selection,
|
|
115
|
+
model,
|
|
116
|
+
runtimeMode,
|
|
117
|
+
effectiveRuntimeMode,
|
|
118
|
+
permissionMode,
|
|
119
|
+
open,
|
|
120
|
+
onOpenChange,
|
|
121
|
+
onModel,
|
|
122
|
+
onOption,
|
|
123
|
+
onMode,
|
|
124
|
+
usage,
|
|
125
|
+
compactDisabled,
|
|
126
|
+
onCompact,
|
|
127
|
+
account
|
|
128
|
+
}: RunSettingsProps) {
|
|
129
|
+
const { t } = useTranslation('agent-chat');
|
|
130
|
+
const owner = providers.find((entry) => entry.kind === provider);
|
|
131
|
+
const current = modelName(selection.model, owner?.models);
|
|
132
|
+
const short = shortModelName(current, owner?.models);
|
|
133
|
+
const options = orderOptions(model?.options ?? []);
|
|
134
|
+
const summary = options.flatMap((option) => {
|
|
135
|
+
const label = optionSummary(option, selection);
|
|
136
|
+
return label === null ? [] : [{ id: option.id, label, ring: option.id === CONTEXT_OPTION }];
|
|
137
|
+
});
|
|
138
|
+
// A CLI without a context choice still fills one, so the ring stands on its own next to the size.
|
|
139
|
+
const hasContextOption = options.some((option) => option.id === CONTEXT_OPTION);
|
|
140
|
+
const standaloneContext = !hasContextOption && Boolean(usage.contextWindow);
|
|
141
|
+
if (standaloneContext) {
|
|
142
|
+
summary.push({ id: CONTEXT_OPTION, label: formatTokens(usage.contextWindow ?? 0), ring: true });
|
|
143
|
+
}
|
|
144
|
+
const grouped = providers.length > 1;
|
|
145
|
+
const live = providers.map((entry) => ({ entry, models: entry.models.filter((row) => !row.legacy) })).filter((group) => group.models.length > 0);
|
|
146
|
+
const legacy = providers.map((entry) => ({ entry, models: entry.models.filter((row) => row.legacy) })).filter((group) => group.models.length > 0);
|
|
147
|
+
const chosenLegacy = owner?.models.find((row) => row.legacy && row.slug === selection.model);
|
|
148
|
+
const chosenModel = modelValue(provider, selection.model);
|
|
149
|
+
const shownMode = effectiveRuntimeMode ?? runtimeMode;
|
|
150
|
+
const fullAccess = shownMode === 'full-access';
|
|
151
|
+
const permissionFallback = permissionMode !== undefined && effectiveRuntimeMode !== runtimeMode;
|
|
152
|
+
const effectiveLabel = effectiveRuntimeMode === undefined ? permissionMode : t(`modes.${effectiveRuntimeMode}.label`);
|
|
153
|
+
const permissionHint = permissionFallback ? t('pickers.mode.effective', { effective: effectiveLabel, requested: t(`modes.${runtimeMode}.label`) }) : null;
|
|
154
|
+
|
|
155
|
+
const chooseModel = (value: string): void => {
|
|
156
|
+
const slash = value.indexOf('/');
|
|
157
|
+
onModel(value.slice(0, slash) as AgentKind, value.slice(slash + 1));
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const modelGroups = (groups: typeof live) =>
|
|
161
|
+
groups.map(({ entry, models }) => (
|
|
162
|
+
<Menu.Group key={entry.kind}>
|
|
163
|
+
{grouped && (
|
|
164
|
+
<Menu.GroupLabel className="flex items-center gap-1.5">
|
|
165
|
+
<AgentIcon kind={entry.kind} size={12} />
|
|
166
|
+
{entry.name}
|
|
167
|
+
</Menu.GroupLabel>
|
|
168
|
+
)}
|
|
169
|
+
{models.map((row) => (
|
|
170
|
+
<Menu.RadioItem key={row.slug} value={modelValue(entry.kind, row.slug)} closeOnClick>
|
|
171
|
+
<AgentIcon kind={entry.kind} size={14} className="shrink-0" />
|
|
172
|
+
<span className="min-w-0 truncate">{row.name}</span>
|
|
173
|
+
{row.badge && <span className="rounded bg-accent-soft px-1 text-[11px] leading-5 font-medium uppercase text-accent">{row.badge}</span>}
|
|
174
|
+
</Menu.RadioItem>
|
|
175
|
+
))}
|
|
176
|
+
</Menu.Group>
|
|
177
|
+
));
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<Menu.Root open={open} onOpenChange={onOpenChange}>
|
|
181
|
+
<Tooltip label={permissionHint ?? t('pickers.settings.title')} kbd="/model">
|
|
182
|
+
{/* Styled from `open`: the tooltip puts `data-popup-open` on the same trigger. */}
|
|
183
|
+
<Menu.Trigger
|
|
184
|
+
disabled={disabled}
|
|
185
|
+
className={clsx(
|
|
186
|
+
'flex h-8 min-w-0 items-center gap-2 rounded-full border pr-3 pl-2.5 text-xs whitespace-nowrap text-text-muted @max-xl/composer:gap-1.5 @max-sm/composer:pr-2.5',
|
|
187
|
+
open ? 'border-accent bg-accent-soft' : 'border-border hover:bg-surface-hover'
|
|
188
|
+
)}
|
|
189
|
+
>
|
|
190
|
+
<AgentIcon kind={provider} size={14} className="shrink-0" />
|
|
191
|
+
{/* The composer's width decides how much is said: words give way first, then whole parts. */}
|
|
192
|
+
<span className="flex min-w-0 items-center gap-2 overflow-hidden @max-xl/composer:gap-1.5">
|
|
193
|
+
<span className="truncate font-medium text-text @max-xl/composer:hidden">{current}</span>
|
|
194
|
+
<span className="hidden truncate font-medium text-text @max-xl/composer:inline">{short}</span>
|
|
195
|
+
{account !== null && (
|
|
196
|
+
<span className="flex min-w-0 items-center gap-2 @max-xl/composer:gap-1.5">
|
|
197
|
+
<span className="shrink-0 text-text-faint">·</span>
|
|
198
|
+
<AccountDot color={account.choice.current?.account.color} />
|
|
199
|
+
{/* The account name remains in the menu when the composer is narrow. */}
|
|
200
|
+
<span className="truncate @max-xl/composer:hidden">
|
|
201
|
+
{account.choice.current === null ? account.choice.currentId : account.choice.nameOf(account.choice.current)}
|
|
202
|
+
</span>
|
|
203
|
+
</span>
|
|
204
|
+
)}
|
|
205
|
+
{summary.map((entry) => (
|
|
206
|
+
<span
|
|
207
|
+
key={entry.id}
|
|
208
|
+
className={clsx('flex shrink-0 items-center gap-2 @max-xl/composer:gap-1.5', !entry.ring && '@max-xl/composer:hidden')}
|
|
209
|
+
>
|
|
210
|
+
<span className="text-text-faint">·</span>
|
|
211
|
+
{entry.ring && <ContextRing usage={usage} />}
|
|
212
|
+
<span className={clsx(entry.ring && '@max-sm/composer:hidden')}>{entry.label}</span>
|
|
213
|
+
</span>
|
|
214
|
+
))}
|
|
215
|
+
<span className="shrink-0 text-text-faint">·</span>
|
|
216
|
+
<span className={clsx('flex shrink-0 items-center gap-1', fullAccess && 'text-status-needs-you')}>
|
|
217
|
+
<Icon icon={MODE_ICONS[shownMode]} size={12} className="shrink-0" />
|
|
218
|
+
<span>{effectiveRuntimeMode === undefined && permissionMode !== undefined ? permissionMode : t(`modes.${shownMode}.short`)}</span>
|
|
219
|
+
{permissionFallback && <Icon icon={TriangleAlert} size={12} className="shrink-0 text-status-needs-you" />}
|
|
220
|
+
</span>
|
|
221
|
+
</span>
|
|
222
|
+
<Icon icon={open ? ChevronUp : ChevronDown} size={12} className="shrink-0 @max-sm/composer:hidden" />
|
|
223
|
+
</Menu.Trigger>
|
|
224
|
+
</Tooltip>
|
|
225
|
+
<Menu.Popup side="top" sideOffset={8} align="start" className="w-80">
|
|
226
|
+
{providers.length === 0 && <div className="px-2.5 py-3 text-xs text-text-faint">{t('pickers.model.noProvider')}</div>}
|
|
227
|
+
<Menu.RadioGroup value={chosenModel} onValueChange={chooseModel}>
|
|
228
|
+
{modelGroups(live)}
|
|
229
|
+
</Menu.RadioGroup>
|
|
230
|
+
{legacy.length > 0 && (
|
|
231
|
+
<Menu.SubmenuRoot>
|
|
232
|
+
<Menu.SubmenuTrigger className="text-text-muted">
|
|
233
|
+
<span className="min-w-0 grow truncate">
|
|
234
|
+
{t('pickers.model.legacyGroup', { count: legacy.reduce((count, group) => count + group.models.length, 0) })}
|
|
235
|
+
</span>
|
|
236
|
+
{chosenLegacy && <Menu.Hint className="truncate">{chosenLegacy.name}</Menu.Hint>}
|
|
237
|
+
</Menu.SubmenuTrigger>
|
|
238
|
+
<Menu.Popup className="min-w-56">
|
|
239
|
+
<Menu.RadioGroup value={chosenModel} onValueChange={chooseModel}>
|
|
240
|
+
{modelGroups(legacy)}
|
|
241
|
+
</Menu.RadioGroup>
|
|
242
|
+
</Menu.Popup>
|
|
243
|
+
</Menu.SubmenuRoot>
|
|
244
|
+
)}
|
|
245
|
+
<Menu.Separator />
|
|
246
|
+
{account !== null && <AccountSubmenu provider={provider} account={account} />}
|
|
247
|
+
<Menu.SubmenuRoot>
|
|
248
|
+
<Menu.SubmenuTrigger className="text-text-muted">
|
|
249
|
+
<Icon icon={MODE_ICONS[runtimeMode]} size={14} className={clsx('shrink-0', fullAccess ? 'text-status-needs-you' : 'text-text-faint')} />
|
|
250
|
+
<span className="min-w-0 grow truncate">{t('pickers.mode.label')}</span>
|
|
251
|
+
<Menu.Hint className="truncate">{t(`modes.${runtimeMode}.label`)}</Menu.Hint>
|
|
252
|
+
</Menu.SubmenuTrigger>
|
|
253
|
+
<Menu.Popup className="w-72">
|
|
254
|
+
{permissionHint !== null && <p className="px-2.5 py-2 text-xs text-text-muted">{permissionHint}</p>}
|
|
255
|
+
<Menu.RadioGroup value={runtimeMode} onValueChange={(mode: RuntimeMode) => onMode(mode)}>
|
|
256
|
+
{RUNTIME_MODES.map((mode) => (
|
|
257
|
+
<Menu.RadioItem key={mode} value={mode} className="items-start">
|
|
258
|
+
{/* The hint makes the row two lines high; the box keeps the icon on the label's line. */}
|
|
259
|
+
<span className="grid h-lh w-4 shrink-0 place-items-center">
|
|
260
|
+
<Icon
|
|
261
|
+
icon={MODE_ICONS[mode]}
|
|
262
|
+
size={14}
|
|
263
|
+
className={mode === 'full-access' ? 'text-status-needs-you' : 'text-text-faint'}
|
|
264
|
+
/>
|
|
265
|
+
</span>
|
|
266
|
+
<span className="flex min-w-0 grow flex-col">
|
|
267
|
+
{t(`modes.${mode}.label`)}
|
|
268
|
+
<span className="text-xs text-text-faint">{t(`modes.${mode}.hint`)}</span>
|
|
269
|
+
</span>
|
|
270
|
+
</Menu.RadioItem>
|
|
271
|
+
))}
|
|
272
|
+
</Menu.RadioGroup>
|
|
273
|
+
</Menu.Popup>
|
|
274
|
+
</Menu.SubmenuRoot>
|
|
275
|
+
{options.map((option) => (
|
|
276
|
+
<OptionRow key={option.id} option={option} selection={selection} onChange={(value) => onOption(option.id, value)} />
|
|
277
|
+
))}
|
|
278
|
+
{(hasContextOption || standaloneContext) && (
|
|
279
|
+
<>
|
|
280
|
+
<Menu.Separator />
|
|
281
|
+
<ContextUsage usage={usage} disabled={compactDisabled} onCompact={onCompact} />
|
|
282
|
+
</>
|
|
283
|
+
)}
|
|
284
|
+
</Menu.Popup>
|
|
285
|
+
</Menu.Root>
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* Red where a window is nearly spent, amber where it is worth knowing, as the usage bars have it. */
|
|
290
|
+
function sessionTone(used: number): { bar: string; text: string } {
|
|
291
|
+
return used >= 0.9
|
|
292
|
+
? { bar: 'bg-status-error', text: 'text-status-error' }
|
|
293
|
+
: used >= 0.7
|
|
294
|
+
? { bar: 'bg-status-needs-you', text: 'text-status-needs-you' }
|
|
295
|
+
: { bar: 'bg-text-muted', text: 'text-text-muted' };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/*
|
|
299
|
+
* The account the next turn runs under, for the chat's own CLI. Before the first turn any of them;
|
|
300
|
+
* after it one that reads the conversation, since the others would start it over, and a fork is how
|
|
301
|
+
* the conversation goes along to those. A switch applies from the next turn.
|
|
302
|
+
*/
|
|
303
|
+
function AccountSubmenu({ provider, account }: { provider: AgentKind; account: AccountPick }) {
|
|
304
|
+
const { t } = useTranslation('agent-chat');
|
|
305
|
+
const { choice, started, onPick } = account;
|
|
306
|
+
return (
|
|
307
|
+
<Menu.SubmenuRoot>
|
|
308
|
+
<Menu.SubmenuTrigger className="text-text-muted">
|
|
309
|
+
<span className="grid w-3.5 shrink-0 place-items-center">
|
|
310
|
+
<AccountDot color={choice.current?.account.color} />
|
|
311
|
+
</span>
|
|
312
|
+
<span className="min-w-0 grow truncate">{t('pickers.account.label')}</span>
|
|
313
|
+
<Menu.Hint className="truncate">{choice.current === null ? choice.currentId : choice.nameOf(choice.current)}</Menu.Hint>
|
|
314
|
+
</Menu.SubmenuTrigger>
|
|
315
|
+
<Menu.Popup className="min-w-64">
|
|
316
|
+
<Menu.Group>
|
|
317
|
+
<Menu.GroupLabel className="flex items-center gap-1.5">
|
|
318
|
+
<AgentIcon kind={provider} size={12} />
|
|
319
|
+
{choice.providerName}
|
|
320
|
+
</Menu.GroupLabel>
|
|
321
|
+
<Menu.RadioGroup value={choice.currentId} onValueChange={(id: string) => onPick(id)}>
|
|
322
|
+
<AccountRows choice={choice} locked={(id) => started && !canContinueOn(choice.accounts, provider, choice.currentId, id)} />
|
|
323
|
+
</Menu.RadioGroup>
|
|
324
|
+
</Menu.Group>
|
|
325
|
+
<Menu.Separator />
|
|
326
|
+
<Menu.Item className="text-text-muted" onClick={() => chatHost().openSettings('providers')}>
|
|
327
|
+
<Icon icon={Settings} size={14} className="shrink-0 text-text-faint" />
|
|
328
|
+
{t('pickers.account.manage')}
|
|
329
|
+
</Menu.Item>
|
|
330
|
+
</Menu.Popup>
|
|
331
|
+
</Menu.SubmenuRoot>
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/* Mounted only while the submenu is open, since asking for the plan windows starts a CLI per account. */
|
|
336
|
+
function AccountRows({ choice, locked }: { choice: AccountChoice; locked(id: string): boolean }) {
|
|
337
|
+
const { t } = useTranslation('agent-chat');
|
|
338
|
+
const limits = useUsageLimits();
|
|
339
|
+
const now = useNow(MINUTE_MS);
|
|
340
|
+
return choice.offered.map((entry) => {
|
|
341
|
+
const session = sessionWindow(limitsOfAccount(limits, entry.id));
|
|
342
|
+
const disabled = locked(entry.id);
|
|
343
|
+
const row = (
|
|
344
|
+
<Menu.RadioItem key={entry.id} value={entry.id} disabled={disabled} closeOnClick className="items-start data-disabled:opacity-50">
|
|
345
|
+
<span className="flex min-w-0 grow flex-col">
|
|
346
|
+
<span className="flex min-w-0 items-center gap-2">
|
|
347
|
+
<AccountDot color={entry.account.color} />
|
|
348
|
+
<span className="truncate">{choice.nameOf(entry)}</span>
|
|
349
|
+
</span>
|
|
350
|
+
{session !== null && <SessionLine used={session.used} resetsAt={session.resetsAt} now={now} />}
|
|
351
|
+
</span>
|
|
352
|
+
</Menu.RadioItem>
|
|
353
|
+
);
|
|
354
|
+
return disabled ? (
|
|
355
|
+
<Tooltip key={entry.id} label={t('pickers.account.forkToSwitch', { account: choice.nameOf(entry) })} side="right" sideOffset={12}>
|
|
356
|
+
{row}
|
|
357
|
+
</Tooltip>
|
|
358
|
+
) : (
|
|
359
|
+
row
|
|
360
|
+
);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function SessionLine({ used, resetsAt, now }: { used: number; resetsAt: number | null; now: number }) {
|
|
365
|
+
const { t } = useTranslation('agent-chat');
|
|
366
|
+
const percent = Math.round(used * 100);
|
|
367
|
+
const tone = sessionTone(used);
|
|
368
|
+
return (
|
|
369
|
+
<span className="flex items-center gap-2 text-xs text-text-faint tabular-nums">
|
|
370
|
+
<span aria-hidden className="relative h-1 w-14 shrink-0 overflow-hidden rounded-full bg-surface-sunken">
|
|
371
|
+
<span className={clsx('absolute inset-y-0 left-0 rounded-full', tone.bar)} style={{ width: `${Math.min(100, percent)}%` }} />
|
|
372
|
+
</span>
|
|
373
|
+
<span className={tone.text}>{formatPercent(percent)}</span>
|
|
374
|
+
{resetsAt !== null && (
|
|
375
|
+
<span className="whitespace-nowrap">
|
|
376
|
+
· {t('pickers.account.resets', { time: isSameDay(resetsAt, now) ? formatClock(resetsAt) : formatWeekdayClock(resetsAt) })}
|
|
377
|
+
</span>
|
|
378
|
+
)}
|
|
379
|
+
</span>
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/* How full the context is, drawn small enough to sit in the pill beside the window's size. */
|
|
384
|
+
function ContextRing({ usage }: { usage: ChatUsage }) {
|
|
385
|
+
const fraction = contextFraction(usage);
|
|
386
|
+
return (
|
|
387
|
+
<svg width="14" height="14" viewBox="0 0 14 14" className={clsx('shrink-0', contextTone(fraction))} aria-hidden="true">
|
|
388
|
+
<circle cx="7" cy="7" r={RING_RADIUS} fill="none" strokeWidth="2" className="stroke-border-strong" />
|
|
389
|
+
<circle
|
|
390
|
+
cx="7"
|
|
391
|
+
cy="7"
|
|
392
|
+
r={RING_RADIUS}
|
|
393
|
+
fill="none"
|
|
394
|
+
strokeWidth="2"
|
|
395
|
+
stroke="currentColor"
|
|
396
|
+
strokeDasharray={RING_CIRCUMFERENCE}
|
|
397
|
+
strokeDashoffset={RING_CIRCUMFERENCE * (1 - fraction)}
|
|
398
|
+
transform="rotate(-90 7 7)"
|
|
399
|
+
/>
|
|
400
|
+
</svg>
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* How full the context is and what fills it, and the one thing to do about a full context. */
|
|
405
|
+
function ContextUsage({ usage, disabled, onCompact }: { usage: ChatUsage; disabled: boolean; onCompact(): void }) {
|
|
406
|
+
const { t } = useTranslation('agent-chat');
|
|
407
|
+
const fraction = contextFraction(usage);
|
|
408
|
+
const percent = Math.round(fraction * 100);
|
|
409
|
+
const segments = contextSegments(usage);
|
|
410
|
+
const used = formatTokens(usage.contextTokens);
|
|
411
|
+
return (
|
|
412
|
+
<Menu.Group className="flex flex-col gap-2 px-2.5 py-1.5">
|
|
413
|
+
<div className="flex items-center gap-2">
|
|
414
|
+
<Menu.GroupLabel unstyled className="min-w-0 grow truncate text-sm font-medium text-text">
|
|
415
|
+
{t('contextMeter.title')}
|
|
416
|
+
</Menu.GroupLabel>
|
|
417
|
+
<span className={clsx('shrink-0 text-xs tabular-nums', fraction >= 0.7 ? contextTone(fraction) : 'text-text-faint')}>
|
|
418
|
+
{usage.contextWindow ? t('contextMeter.of', { used, window: formatTokens(usage.contextWindow) }) : t('contextMeter.used', { tokens: used })}
|
|
419
|
+
</span>
|
|
420
|
+
</div>
|
|
421
|
+
{usage.contextWindow ? (
|
|
422
|
+
<div
|
|
423
|
+
role="meter"
|
|
424
|
+
aria-valuenow={percent}
|
|
425
|
+
aria-valuemin={0}
|
|
426
|
+
aria-valuemax={100}
|
|
427
|
+
aria-label={t('contextMeter.aria', { percent })}
|
|
428
|
+
className="flex h-1.5 overflow-hidden rounded-full bg-surface-sunken"
|
|
429
|
+
>
|
|
430
|
+
{segments ? (
|
|
431
|
+
segments.map((segment) => (
|
|
432
|
+
<div
|
|
433
|
+
key={segment.part}
|
|
434
|
+
className={clsx('h-full shrink-0', PART_COLORS[segment.part])}
|
|
435
|
+
style={{ width: `${segment.fraction * 100}%` }}
|
|
436
|
+
/>
|
|
437
|
+
))
|
|
438
|
+
) : (
|
|
439
|
+
<div className={clsx('h-full rounded-full bg-current', contextTone(fraction))} style={{ width: `${percent}%` }} />
|
|
440
|
+
)}
|
|
441
|
+
</div>
|
|
442
|
+
) : null}
|
|
443
|
+
{segments && (
|
|
444
|
+
<div className="flex flex-col gap-0.5 text-xs">
|
|
445
|
+
{segments.map((segment) => (
|
|
446
|
+
<div key={segment.part} className="flex items-center gap-2">
|
|
447
|
+
<span aria-hidden="true" className={clsx('size-2 shrink-0 rounded-xs', PART_COLORS[segment.part])} />
|
|
448
|
+
<span className="min-w-0 grow truncate text-text-muted">{t(`contextMeter.parts.${segment.part}`)}</span>
|
|
449
|
+
<span className="shrink-0 text-text-faint tabular-nums">
|
|
450
|
+
{t('contextMeter.estimate', { tokens: formatTokens(segment.tokens) })}
|
|
451
|
+
</span>
|
|
452
|
+
</div>
|
|
453
|
+
))}
|
|
454
|
+
</div>
|
|
455
|
+
)}
|
|
456
|
+
<div className="flex items-center gap-2 text-xs text-text-faint tabular-nums">
|
|
457
|
+
<span className="min-w-0 grow truncate">
|
|
458
|
+
{usage.contextWindow ? t('contextMeter.percentUsed', { percent: formatPercent(fraction * 100) }) : null}
|
|
459
|
+
</span>
|
|
460
|
+
<Menu.Item
|
|
461
|
+
unstyled
|
|
462
|
+
className="flex shrink-0 cursor-default items-center gap-0.5 rounded font-medium text-accent outline-none data-disabled:opacity-50 data-highlighted:underline"
|
|
463
|
+
disabled={disabled || usage.contextTokens === 0}
|
|
464
|
+
onClick={onCompact}
|
|
465
|
+
>
|
|
466
|
+
{t('contextMeter.compactNow')}
|
|
467
|
+
<Icon icon={ChevronRight} size={12} />
|
|
468
|
+
</Menu.Item>
|
|
469
|
+
</div>
|
|
470
|
+
</Menu.Group>
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/*
|
|
475
|
+
* One of the model's own knobs: a few choices side by side, more of them in a submenu, a checkbox for
|
|
476
|
+
* a boolean. Every choice is a menu item, so the arrow keys reach it.
|
|
477
|
+
*/
|
|
478
|
+
function OptionRow({ option, selection, onChange }: { option: ModelOptionDescriptor; selection: ModelSelection; onChange(value: string | boolean): void }) {
|
|
479
|
+
const icon = <Icon icon={optionIcon(option)} size={14} className="shrink-0 text-text-faint" />;
|
|
480
|
+
if (option.type === 'boolean') {
|
|
481
|
+
const checked = (selection.options[option.id] ?? option.defaultValue) === true;
|
|
482
|
+
const item = (
|
|
483
|
+
<Menu.CheckboxItem indicator="end" className="text-text-muted" checked={checked} onCheckedChange={onChange} closeOnClick={false}>
|
|
484
|
+
{icon}
|
|
485
|
+
<span className="min-w-0 grow truncate">{option.label}</span>
|
|
486
|
+
</Menu.CheckboxItem>
|
|
487
|
+
);
|
|
488
|
+
return option.description ? (
|
|
489
|
+
<Tooltip label={option.description} side="right" sideOffset={12}>
|
|
490
|
+
{item}
|
|
491
|
+
</Tooltip>
|
|
492
|
+
) : (
|
|
493
|
+
item
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
const value = String(selection.options[option.id] ?? option.defaultChoice);
|
|
497
|
+
if (option.choices.length > INLINE_CHOICES) {
|
|
498
|
+
return (
|
|
499
|
+
<Menu.SubmenuRoot>
|
|
500
|
+
<Menu.SubmenuTrigger className="text-text-muted">
|
|
501
|
+
{icon}
|
|
502
|
+
<span className="min-w-0 grow truncate">{option.label}</span>
|
|
503
|
+
<Menu.Hint>{option.choices.find((choice) => choice.id === value)?.label}</Menu.Hint>
|
|
504
|
+
</Menu.SubmenuTrigger>
|
|
505
|
+
<Menu.Popup className="min-w-56">
|
|
506
|
+
<Menu.RadioGroup value={value} onValueChange={(next: string) => onChange(next)}>
|
|
507
|
+
{option.choices.map((choice) => (
|
|
508
|
+
<Menu.RadioItem key={choice.id} value={choice.id} className={choice.description ? 'items-start' : undefined}>
|
|
509
|
+
<span className="flex min-w-0 grow flex-col">
|
|
510
|
+
{choice.label}
|
|
511
|
+
{choice.description && <span className="text-xs text-text-faint">{choice.description}</span>}
|
|
512
|
+
</span>
|
|
513
|
+
</Menu.RadioItem>
|
|
514
|
+
))}
|
|
515
|
+
</Menu.RadioGroup>
|
|
516
|
+
</Menu.Popup>
|
|
517
|
+
</Menu.SubmenuRoot>
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
return (
|
|
521
|
+
<div className="flex items-center gap-2.5 px-2.5 py-1.5 text-sm text-text-muted">
|
|
522
|
+
{icon}
|
|
523
|
+
<span className="min-w-0 grow truncate">{option.label}</span>
|
|
524
|
+
<Menu.RadioGroup
|
|
525
|
+
value={value}
|
|
526
|
+
onValueChange={(next: string) => onChange(next)}
|
|
527
|
+
aria-label={option.label}
|
|
528
|
+
className="flex gap-0.5 rounded-md bg-surface-sunken p-0.5"
|
|
529
|
+
>
|
|
530
|
+
{option.choices.map((choice) => (
|
|
531
|
+
<Menu.RadioItem
|
|
532
|
+
unstyled
|
|
533
|
+
key={choice.id}
|
|
534
|
+
value={choice.id}
|
|
535
|
+
className={clsx(
|
|
536
|
+
'flex h-6 cursor-default items-center rounded px-2 text-xs outline-none',
|
|
537
|
+
choice.id === value ? 'bg-surface-active text-text' : 'text-text-muted data-highlighted:text-text'
|
|
538
|
+
)}
|
|
539
|
+
>
|
|
540
|
+
{choice.label}
|
|
541
|
+
</Menu.RadioItem>
|
|
542
|
+
))}
|
|
543
|
+
</Menu.RadioGroup>
|
|
544
|
+
</div>
|
|
545
|
+
);
|
|
546
|
+
}
|