@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,82 @@
|
|
|
1
|
+
import { isRecord } from './json.js';
|
|
2
|
+
import { toolEntry } from './tool-catalog.js';
|
|
3
|
+
function str(value) {
|
|
4
|
+
return typeof value === 'string' ? value : null;
|
|
5
|
+
}
|
|
6
|
+
/* The one line that says what a tool call is about: the command, the file, the pattern. */
|
|
7
|
+
export function toolSummary(name, input) {
|
|
8
|
+
if (!isRecord(input)) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
const known = toolEntry(name);
|
|
12
|
+
if (known === undefined) {
|
|
13
|
+
// A tool nobody wrote down, an MCP one above all, gets its best guess from the first string it was given.
|
|
14
|
+
const first = Object.values(input).find((value) => typeof value === 'string');
|
|
15
|
+
return typeof first === 'string' ? first : '';
|
|
16
|
+
}
|
|
17
|
+
for (const key of known.summary) {
|
|
18
|
+
const value = str(input[key]);
|
|
19
|
+
if (value !== null) {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
// What `GET /fs/file` will serve; a path with another suffix is not worth asking the host about.
|
|
26
|
+
const IMAGE_SUFFIXES = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'];
|
|
27
|
+
/* The image file a tool call looked at, so the row can draw it; null for every other call. */
|
|
28
|
+
export function readImagePath(name, input) {
|
|
29
|
+
if (toolEntry(name)?.readsImage !== true) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const path = isRecord(input) ? str(input.file_path) : null;
|
|
33
|
+
if (path === null) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const lowered = path.toLowerCase();
|
|
37
|
+
return IMAGE_SUFFIXES.some((suffix) => lowered.endsWith(suffix)) ? path : null;
|
|
38
|
+
}
|
|
39
|
+
/* The before and after text of a file-changing tool call, so the thread can show it as a diff. */
|
|
40
|
+
export function fileChanges(name, input) {
|
|
41
|
+
if (!isRecord(input)) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
const path = str(input.file_path) ?? '';
|
|
45
|
+
if (name === 'Edit') {
|
|
46
|
+
return [{ path, before: str(input.old_string) ?? '', after: str(input.new_string) ?? '' }];
|
|
47
|
+
}
|
|
48
|
+
if (name === 'Write') {
|
|
49
|
+
return [{ path, before: '', after: str(input.content) ?? '' }];
|
|
50
|
+
}
|
|
51
|
+
if (name === 'MultiEdit' && Array.isArray(input.edits)) {
|
|
52
|
+
return input.edits.filter(isRecord).map((edit) => ({ path, before: str(edit.old_string) ?? '', after: str(edit.new_string) ?? '' }));
|
|
53
|
+
}
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
export function isFileChange(name) {
|
|
57
|
+
return toolEntry(name)?.changesFiles === true;
|
|
58
|
+
}
|
|
59
|
+
/* The unified diffs a provider put next to a tool call; empty for one that reports before and after. */
|
|
60
|
+
export function unifiedChanges(tool) {
|
|
61
|
+
return (tool.changes ?? []).filter((change) => change.diff !== '');
|
|
62
|
+
}
|
|
63
|
+
/* The same, for the copy an approval carries so the person can read what they are approving. */
|
|
64
|
+
export function approvalChanges(input) {
|
|
65
|
+
const changes = isRecord(input) ? input.changes : null;
|
|
66
|
+
if (!Array.isArray(changes)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
return changes.filter((change) => isRecord(change) && typeof change.path === 'string' && typeof change.diff === 'string' && change.diff !== '');
|
|
70
|
+
}
|
|
71
|
+
/* Whether a settled call is worth a row in the turn's changed files card. */
|
|
72
|
+
export function hasFileChanges(tool) {
|
|
73
|
+
return unifiedChanges(tool).length > 0 || fileChanges(tool.name, tool.input).length > 0;
|
|
74
|
+
}
|
|
75
|
+
/* When a running call started: what the CLI reported, or the moment the call appeared. */
|
|
76
|
+
export function toolStartedAt(tool) {
|
|
77
|
+
return tool.progress?.startedAt ?? tool.createdAt;
|
|
78
|
+
}
|
|
79
|
+
// Keep the full buffer so the renderer can carry ANSI state into the visible tail.
|
|
80
|
+
export function liveOutput(tool) {
|
|
81
|
+
return tool.progress?.output || null;
|
|
82
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ChatSubagentStatus, ChatWorkflow, ChatWorkflowAgent } from '@adecore/agent-contracts';
|
|
2
|
+
export type WorkflowAgentState = ChatSubagentStatus | 'waiting' | 'stopped';
|
|
3
|
+
export interface WorkflowAgentView {
|
|
4
|
+
agent: ChatWorkflowAgent;
|
|
5
|
+
state: WorkflowAgentState;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkflowPhaseView {
|
|
8
|
+
key: string;
|
|
9
|
+
title: string | null;
|
|
10
|
+
agents: WorkflowAgentView[];
|
|
11
|
+
}
|
|
12
|
+
export declare function workflowAgentState(agent: ChatWorkflowAgent, workflowRunning: boolean): WorkflowAgentState;
|
|
13
|
+
export declare function workflowPhases(workflow: ChatWorkflow, workflowRunning: boolean): WorkflowPhaseView[];
|
|
14
|
+
export declare function workflowAgentTime(view: WorkflowAgentView): string | null;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import i18next from 'i18next';
|
|
2
|
+
import { formatElapsedShort } from '@adecore/ui/format';
|
|
3
|
+
export function workflowAgentState(agent, workflowRunning) {
|
|
4
|
+
if (agent.status !== 'running') {
|
|
5
|
+
return agent.status;
|
|
6
|
+
}
|
|
7
|
+
if (!workflowRunning) {
|
|
8
|
+
return 'stopped';
|
|
9
|
+
}
|
|
10
|
+
return agent.startedAt === null ? 'waiting' : 'running';
|
|
11
|
+
}
|
|
12
|
+
/*
|
|
13
|
+
* The phases in the order the script announced them, each with the agents it started in it. A phase
|
|
14
|
+
* announced ahead of its agents is there without any, and agents of no known phase come first, untitled.
|
|
15
|
+
*/
|
|
16
|
+
export function workflowPhases(workflow, workflowRunning) {
|
|
17
|
+
const known = new Map(workflow.phases.map((phase) => [phase.index, phase]));
|
|
18
|
+
const loose = [];
|
|
19
|
+
const byPhase = new Map();
|
|
20
|
+
for (const agent of workflow.agents) {
|
|
21
|
+
const view = { agent, state: workflowAgentState(agent, workflowRunning) };
|
|
22
|
+
if (agent.phaseIndex === null || !known.has(agent.phaseIndex)) {
|
|
23
|
+
loose.push(view);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
byPhase.set(agent.phaseIndex, [...(byPhase.get(agent.phaseIndex) ?? []), view]);
|
|
27
|
+
}
|
|
28
|
+
const phases = workflow.phases.map((phase) => ({ key: `phase-${phase.index}`, title: phase.title, agents: byPhase.get(phase.index) ?? [] }));
|
|
29
|
+
return loose.length > 0 ? [{ key: 'loose', title: null, agents: loose }, ...phases] : phases;
|
|
30
|
+
}
|
|
31
|
+
/* What the line of an agent that is not at work says about its time; one at work counts on by itself. */
|
|
32
|
+
export function workflowAgentTime(view) {
|
|
33
|
+
const duration = view.agent.durationMs === null ? null : formatElapsedShort(view.agent.durationMs);
|
|
34
|
+
switch (view.state) {
|
|
35
|
+
case 'running':
|
|
36
|
+
return null;
|
|
37
|
+
case 'waiting':
|
|
38
|
+
return i18next.t('agent-chat:rows.workflow.waiting');
|
|
39
|
+
case 'stopped':
|
|
40
|
+
return i18next.t('agent-chat:rows.workflow.stopped');
|
|
41
|
+
case 'done':
|
|
42
|
+
case 'failed':
|
|
43
|
+
return duration === null
|
|
44
|
+
? i18next.t(`agent-chat:common.status.${view.state}`)
|
|
45
|
+
: i18next.t(`agent-chat:rows.subagent.${view.state}In`, { duration });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export declare const MENTION_DRAG_TYPE = "application/x-adecore-mention";
|
|
2
|
+
export declare const LEGACY_MENTION_DRAG_TYPE = "application/x-ruimte-mention";
|
|
3
|
+
export declare const MENTION_DRAG_TYPES: readonly ["application/x-adecore-mention", "application/x-ruimte-mention"];
|
|
4
|
+
export declare function carriesMentions(types: readonly string[]): boolean;
|
|
5
|
+
export declare function droppedMentions(data: Pick<DataTransfer, 'getData'>): string[];
|
|
6
|
+
export declare function writeMentionDrag(data: Pick<DataTransfer, 'setData'>, paths: readonly string[], legacy?: boolean): void;
|
|
7
|
+
export interface MentionQuery {
|
|
8
|
+
start: number;
|
|
9
|
+
query: string;
|
|
10
|
+
}
|
|
11
|
+
export type ChipSegment = {
|
|
12
|
+
kind: 'text';
|
|
13
|
+
text: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'mention';
|
|
16
|
+
path: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'skill';
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function findMentionQuery(text: string, caret: number): MentionQuery | null;
|
|
22
|
+
export declare function findSkillQuery(text: string, caret: number): MentionQuery | null;
|
|
23
|
+
export declare function insertToken(text: string, query: MentionQuery, sigil: string, value: string): {
|
|
24
|
+
text: string;
|
|
25
|
+
caret: number;
|
|
26
|
+
};
|
|
27
|
+
export declare function dropQuery(text: string, query: MentionQuery): {
|
|
28
|
+
text: string;
|
|
29
|
+
caret: number;
|
|
30
|
+
};
|
|
31
|
+
export declare function insertMention(text: string, query: MentionQuery, path: string): {
|
|
32
|
+
text: string;
|
|
33
|
+
caret: number;
|
|
34
|
+
};
|
|
35
|
+
export declare function insertSkill(text: string, query: MentionQuery, name: string): {
|
|
36
|
+
text: string;
|
|
37
|
+
caret: number;
|
|
38
|
+
};
|
|
39
|
+
export interface MentionSearch {
|
|
40
|
+
query: string | null;
|
|
41
|
+
files: string[];
|
|
42
|
+
}
|
|
43
|
+
export declare const NO_MENTION_SEARCH: MentionSearch;
|
|
44
|
+
export type MentionPick<T> = {
|
|
45
|
+
kind: 'chat';
|
|
46
|
+
chat: T;
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'file';
|
|
49
|
+
path: string;
|
|
50
|
+
};
|
|
51
|
+
export declare function mentionPick<T>(index: number, chats: readonly T[], search: MentionSearch, query: string): MentionPick<T> | null;
|
|
52
|
+
export declare function presentMentions(text: string, chosen: string[]): string[];
|
|
53
|
+
export declare function presentSkills(text: string, chosen: string[]): string[];
|
|
54
|
+
export declare function chipText(segment: ChipSegment): string;
|
|
55
|
+
export declare function pastedMentions(text: string): string[];
|
|
56
|
+
export interface TextRange {
|
|
57
|
+
from: number;
|
|
58
|
+
to: number;
|
|
59
|
+
}
|
|
60
|
+
export interface ChipRange extends TextRange {
|
|
61
|
+
kind: 'mention' | 'skill';
|
|
62
|
+
value: string;
|
|
63
|
+
}
|
|
64
|
+
export declare function chipRanges(text: string, mentions: string[], skills?: string[], excluded?: readonly TextRange[]): ChipRange[];
|
|
65
|
+
export declare function tokenizeChips(text: string, mentions: string[], skills?: string[]): ChipSegment[];
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/* What a file dragged out of an app's own list of files carries: the paths, space separated, relative
|
|
2
|
+
to the folder. The composer takes it next to the image files it already accepts. */
|
|
3
|
+
export const MENTION_DRAG_TYPE = 'application/x-adecore-mention';
|
|
4
|
+
export const LEGACY_MENTION_DRAG_TYPE = 'application/x-ruimte-mention';
|
|
5
|
+
export const MENTION_DRAG_TYPES = [MENTION_DRAG_TYPE, LEGACY_MENTION_DRAG_TYPE];
|
|
6
|
+
export function carriesMentions(types) {
|
|
7
|
+
return MENTION_DRAG_TYPES.some((type) => types.includes(type));
|
|
8
|
+
}
|
|
9
|
+
export function droppedMentions(data) {
|
|
10
|
+
const text = data.getData(MENTION_DRAG_TYPE) || data.getData(LEGACY_MENTION_DRAG_TYPE);
|
|
11
|
+
return text.trim() === '' ? [] : text.trim().split(/\s+/);
|
|
12
|
+
}
|
|
13
|
+
export function writeMentionDrag(data, paths, legacy = true) {
|
|
14
|
+
const text = paths.join(' ');
|
|
15
|
+
data.setData(MENTION_DRAG_TYPE, text);
|
|
16
|
+
if (legacy) {
|
|
17
|
+
data.setData(LEGACY_MENTION_DRAG_TYPE, text);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function isBoundary(char) {
|
|
21
|
+
return char === undefined || /\s/.test(char);
|
|
22
|
+
}
|
|
23
|
+
// A path at the end of a sentence still counts, so "open @a.ts." is a mention of a.ts.
|
|
24
|
+
function isTokenEnd(char) {
|
|
25
|
+
return isBoundary(char) || /[.,;:!?)]/.test(char);
|
|
26
|
+
}
|
|
27
|
+
/*
|
|
28
|
+
* The `<sigil>word` the caret sits in, if any. The sigil has to open a word (start of text or after
|
|
29
|
+
* whitespace) so an email address never opens the picker, and the word may not have been
|
|
30
|
+
* closed with whitespace yet.
|
|
31
|
+
*/
|
|
32
|
+
function findQuery(text, caret, sigil) {
|
|
33
|
+
const before = text.slice(0, caret);
|
|
34
|
+
const at = before.lastIndexOf(sigil);
|
|
35
|
+
if (at < 0 || !isBoundary(before[at - 1])) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const query = before.slice(at + 1);
|
|
39
|
+
if (/\s/.test(query) || !isBoundary(text[caret])) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return { start: at, query };
|
|
43
|
+
}
|
|
44
|
+
export function findMentionQuery(text, caret) {
|
|
45
|
+
return findQuery(text, caret, '@');
|
|
46
|
+
}
|
|
47
|
+
/* The `$word` the caret sits in. The name has to start with a letter, so `$20` and `$1e6` stay text. */
|
|
48
|
+
export function findSkillQuery(text, caret) {
|
|
49
|
+
const found = findQuery(text, caret, '$');
|
|
50
|
+
return found === null || (found.query !== '' && !/^[A-Za-z]/.test(found.query)) ? null : found;
|
|
51
|
+
}
|
|
52
|
+
/* Replaces the `<sigil>query` under the caret with the chosen token and a space, and says where the caret goes. */
|
|
53
|
+
export function insertToken(text, query, sigil, value) {
|
|
54
|
+
const end = query.start + 1 + query.query.length;
|
|
55
|
+
const token = `${sigil}${value} `;
|
|
56
|
+
return { text: `${text.slice(0, query.start)}${token}${text.slice(end)}`, caret: query.start + token.length };
|
|
57
|
+
}
|
|
58
|
+
/* Takes the `<sigil>query` under the caret out, for a pick that lands beside the text instead of in it. */
|
|
59
|
+
export function dropQuery(text, query) {
|
|
60
|
+
return {
|
|
61
|
+
text: `${text.slice(0, query.start)}${text.slice(query.start + 1 + query.query.length)}`,
|
|
62
|
+
caret: query.start
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function insertMention(text, query, path) {
|
|
66
|
+
return insertToken(text, query, '@', path);
|
|
67
|
+
}
|
|
68
|
+
export function insertSkill(text, query, name) {
|
|
69
|
+
return insertToken(text, query, '$', name);
|
|
70
|
+
}
|
|
71
|
+
export const NO_MENTION_SEARCH = { query: null, files: [] };
|
|
72
|
+
/* What Enter or Tab takes from the `@` list at `index`. Files still on screen from an older query are never taken. */
|
|
73
|
+
export function mentionPick(index, chats, search, query) {
|
|
74
|
+
const chat = chats[index];
|
|
75
|
+
if (chat !== undefined) {
|
|
76
|
+
return { kind: 'chat', chat };
|
|
77
|
+
}
|
|
78
|
+
if (search.query !== query) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const path = search.files[index - chats.length] ?? search.files[0];
|
|
82
|
+
return path === undefined ? null : { kind: 'file', path };
|
|
83
|
+
}
|
|
84
|
+
function findToken(text, sigil, value, from) {
|
|
85
|
+
const token = `${sigil}${value}`;
|
|
86
|
+
let index = text.indexOf(token, from);
|
|
87
|
+
while (index >= 0) {
|
|
88
|
+
if (isBoundary(text[index - 1]) && isTokenEnd(text[index + token.length])) {
|
|
89
|
+
return index;
|
|
90
|
+
}
|
|
91
|
+
index = text.indexOf(token, index + 1);
|
|
92
|
+
}
|
|
93
|
+
return -1;
|
|
94
|
+
}
|
|
95
|
+
function present(text, sigil, chosen) {
|
|
96
|
+
const found = [];
|
|
97
|
+
for (const value of new Set(chosen)) {
|
|
98
|
+
const index = findToken(text, sigil, value, 0);
|
|
99
|
+
if (index >= 0) {
|
|
100
|
+
found.push({ index, value });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return found.sort((a, b) => a.index - b.index).map((entry) => entry.value);
|
|
104
|
+
}
|
|
105
|
+
/* The chosen mentions that still sit in the text as a whole `@path` token, in text order and without doubles. */
|
|
106
|
+
export function presentMentions(text, chosen) {
|
|
107
|
+
return present(text, '@', chosen);
|
|
108
|
+
}
|
|
109
|
+
/* The chosen skills that still sit in the text as a whole `$name` token, in text order and without doubles. */
|
|
110
|
+
export function presentSkills(text, chosen) {
|
|
111
|
+
return present(text, '$', chosen);
|
|
112
|
+
}
|
|
113
|
+
/*
|
|
114
|
+
* The characters a segment stands for, sigil included. Joined, the segments spell the text they
|
|
115
|
+
* were cut from.
|
|
116
|
+
*/
|
|
117
|
+
export function chipText(segment) {
|
|
118
|
+
if (segment.kind === 'mention') {
|
|
119
|
+
return `@${segment.path}`;
|
|
120
|
+
}
|
|
121
|
+
if (segment.kind === 'skill') {
|
|
122
|
+
return `$${segment.name}`;
|
|
123
|
+
}
|
|
124
|
+
return segment.text;
|
|
125
|
+
}
|
|
126
|
+
/*
|
|
127
|
+
* The paths in a pasted text that is nothing but `@path` tokens, which is what copying mentions from
|
|
128
|
+
* a list of files puts on the clipboard. Any other text, an email address included, is text.
|
|
129
|
+
*/
|
|
130
|
+
export function pastedMentions(text) {
|
|
131
|
+
const tokens = text.trim().split(/\s+/);
|
|
132
|
+
if (tokens.some((token) => !/^@[^\s@]+$/.test(token))) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
return [...new Set(tokens.map((token) => token.slice(1)))];
|
|
136
|
+
}
|
|
137
|
+
/*
|
|
138
|
+
* Where the chosen mentions and skills sit in the text, in text order; longer values win when one
|
|
139
|
+
* prefixes another. A token that overlaps an excluded range (a code span, say) is text.
|
|
140
|
+
*/
|
|
141
|
+
export function chipRanges(text, mentions, skills = [], excluded = []) {
|
|
142
|
+
const tokens = [
|
|
143
|
+
...[...new Set(mentions)].map((value) => ({ sigil: '@', kind: 'mention', value })),
|
|
144
|
+
...[...new Set(skills)].map((value) => ({ sigil: '$', kind: 'skill', value }))
|
|
145
|
+
].sort((a, b) => b.value.length - a.value.length);
|
|
146
|
+
const allowed = (from, to) => !excluded.some((range) => from < range.to && to > range.from);
|
|
147
|
+
const ranges = [];
|
|
148
|
+
let cursor = 0;
|
|
149
|
+
while (cursor < text.length) {
|
|
150
|
+
let best = null;
|
|
151
|
+
for (const token of tokens) {
|
|
152
|
+
const length = token.value.length + 1;
|
|
153
|
+
let index = findToken(text, token.sigil, token.value, cursor);
|
|
154
|
+
while (index >= 0 && !allowed(index, index + length)) {
|
|
155
|
+
index = findToken(text, token.sigil, token.value, index + 1);
|
|
156
|
+
}
|
|
157
|
+
if (index >= 0 && (best === null || index < best.from)) {
|
|
158
|
+
best = { from: index, to: index + length, kind: token.kind, value: token.value };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (best === null) {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
ranges.push(best);
|
|
165
|
+
cursor = best.to;
|
|
166
|
+
}
|
|
167
|
+
return ranges;
|
|
168
|
+
}
|
|
169
|
+
/* Splits the text so a renderer can draw the mentions and skills as chips. */
|
|
170
|
+
export function tokenizeChips(text, mentions, skills = []) {
|
|
171
|
+
const segments = [];
|
|
172
|
+
let cursor = 0;
|
|
173
|
+
for (const range of chipRanges(text, mentions, skills)) {
|
|
174
|
+
if (range.from > cursor) {
|
|
175
|
+
segments.push({ kind: 'text', text: text.slice(cursor, range.from) });
|
|
176
|
+
}
|
|
177
|
+
segments.push(range.kind === 'mention' ? { kind: 'mention', path: range.value } : { kind: 'skill', name: range.value });
|
|
178
|
+
cursor = range.to;
|
|
179
|
+
}
|
|
180
|
+
if (cursor < text.length) {
|
|
181
|
+
segments.push({ kind: 'text', text: text.slice(cursor) });
|
|
182
|
+
}
|
|
183
|
+
return segments;
|
|
184
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { chatStorageAdapter, hydrateChatStorage } from '../storage.js';
|
|
2
|
+
export function persistedJson(key, parse, fallback, legacyKeys = () => []) {
|
|
3
|
+
let memory = fallback;
|
|
4
|
+
let unwritten = false;
|
|
5
|
+
const currentKey = () => (typeof key === 'string' ? key : key());
|
|
6
|
+
return {
|
|
7
|
+
read: () => {
|
|
8
|
+
hydrateChatStorage();
|
|
9
|
+
if (unwritten) {
|
|
10
|
+
return memory;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const storage = chatStorageAdapter();
|
|
14
|
+
if (!storage) {
|
|
15
|
+
return memory;
|
|
16
|
+
}
|
|
17
|
+
let raw = storage.getItem(currentKey());
|
|
18
|
+
if (raw === null) {
|
|
19
|
+
for (const legacy of legacyKeys()) {
|
|
20
|
+
raw = storage.getItem(legacy);
|
|
21
|
+
if (raw !== null) {
|
|
22
|
+
// Keep the old key for clients still using it, and migrate without changing the record.
|
|
23
|
+
try {
|
|
24
|
+
storage.setItem(currentKey(), raw);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// A full storage still lets the existing record be read.
|
|
28
|
+
}
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
memory = parse(raw);
|
|
34
|
+
return memory;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return memory;
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
write: (value) => {
|
|
41
|
+
hydrateChatStorage();
|
|
42
|
+
memory = value;
|
|
43
|
+
unwritten = true;
|
|
44
|
+
try {
|
|
45
|
+
const storage = chatStorageAdapter();
|
|
46
|
+
if (!storage) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
storage.setItem(currentKey(), JSON.stringify(value));
|
|
50
|
+
unwritten = false;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AgentKind, ChatPreferencesPayload, ModelSelection, ProviderInfo, ProviderAccounts, RuntimeMode } from '@adecore/agent-contracts';
|
|
2
|
+
export interface ChatPreferences {
|
|
3
|
+
selectionByProvider: Partial<Record<AgentKind, ModelSelection>>;
|
|
4
|
+
lastProvider: AgentKind | null;
|
|
5
|
+
runtimeMode: RuntimeMode;
|
|
6
|
+
terminalRuntimeMode: RuntimeMode;
|
|
7
|
+
accountByMachine: Record<string, Partial<Record<AgentKind, string>>>;
|
|
8
|
+
changedAt: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const DEFAULT_CHAT_PREFERENCES: ChatPreferences;
|
|
11
|
+
export declare function parseChatPreferences(raw: string | null): ChatPreferences;
|
|
12
|
+
export declare function defaultProvider(preferences: ChatPreferences): AgentKind | null;
|
|
13
|
+
export declare function selectionFor(preferences: ChatPreferences, provider: AgentKind | null | undefined): ModelSelection | null;
|
|
14
|
+
export declare function startingSelection(preferences: ChatPreferences, provider: ProviderInfo): ModelSelection | null;
|
|
15
|
+
export declare function withSelection(preferences: ChatPreferences, provider: AgentKind, selection: ModelSelection): ChatPreferences;
|
|
16
|
+
export declare function accountFor(preferences: ChatPreferences, scopeId: string, provider: AgentKind, accounts?: ProviderAccounts | null): string | null;
|
|
17
|
+
export declare function withAccount(preferences: ChatPreferences, scopeId: string, provider: AgentKind, account: string | null): ChatPreferences;
|
|
18
|
+
export declare function chatPreferencesPayload(preferences: ChatPreferences, scopeId: string, accounts?: ProviderAccounts | null): ChatPreferencesPayload;
|
|
19
|
+
export declare const useChatPreferences: import("zustand").UseBoundStore<import("zustand").StoreApi<ChatPreferences>>;
|
|
20
|
+
export declare function readChatPreferences(): ChatPreferences;
|
|
21
|
+
export declare let CHAT_PREFERENCES_KEY: string;
|
|
22
|
+
export declare function chatPreferencesKey(): string;
|
|
23
|
+
export declare function reloadChatPreferences(): void;
|
|
24
|
+
export declare function rememberChatPreferences(patch: Partial<ChatPreferences>): void;
|
|
25
|
+
export declare function rememberChatSelection(provider: AgentKind, selection: ModelSelection): void;
|
|
26
|
+
export declare function rememberChatAccount(scopeId: string, provider: AgentKind, account: string | null): void;
|
|
27
|
+
export declare function forgetChatSelection(provider: AgentKind): void;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { chatStorageKey, chatStorageLegacyKeys, createChatStore, onChatStorageConfiguration } from '../storage.js';
|
|
2
|
+
import { persistedJson } from './persisted-json.js';
|
|
3
|
+
const storageKey = () => chatStorageKey('preferences');
|
|
4
|
+
export const DEFAULT_CHAT_PREFERENCES = {
|
|
5
|
+
selectionByProvider: {},
|
|
6
|
+
lastProvider: null,
|
|
7
|
+
runtimeMode: 'full-access',
|
|
8
|
+
terminalRuntimeMode: 'full-access',
|
|
9
|
+
accountByMachine: {},
|
|
10
|
+
changedAt: 0
|
|
11
|
+
};
|
|
12
|
+
/*
|
|
13
|
+
* Only the fields we know today, so what an older build wrote (one global `selection`, the plan
|
|
14
|
+
* toggle's `interactionMode`) falls away here instead of riding along in every later write. A
|
|
15
|
+
* global selection cannot be mapped back onto a provider, so it is dropped: one lost pick.
|
|
16
|
+
*/
|
|
17
|
+
export function parseChatPreferences(raw) {
|
|
18
|
+
if (raw === null) {
|
|
19
|
+
return DEFAULT_CHAT_PREFERENCES;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const stored = JSON.parse(raw);
|
|
23
|
+
return {
|
|
24
|
+
selectionByProvider: { ...stored.selectionByProvider },
|
|
25
|
+
lastProvider: stored.lastProvider ?? null,
|
|
26
|
+
runtimeMode: stored.runtimeMode ?? DEFAULT_CHAT_PREFERENCES.runtimeMode,
|
|
27
|
+
terminalRuntimeMode: stored.terminalRuntimeMode ?? DEFAULT_CHAT_PREFERENCES.terminalRuntimeMode,
|
|
28
|
+
accountByMachine: { ...stored.accountByMachine },
|
|
29
|
+
changedAt: typeof stored.changedAt === 'number' ? stored.changedAt : 0
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return DEFAULT_CHAT_PREFERENCES;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/* Which CLI a chat opens on when its node names none: the last one a model was picked for. */
|
|
37
|
+
export function defaultProvider(preferences) {
|
|
38
|
+
return preferences.lastProvider;
|
|
39
|
+
}
|
|
40
|
+
/* The model a chat of this provider starts with; null lets the host fall back to the CLI's own default. */
|
|
41
|
+
export function selectionFor(preferences, provider) {
|
|
42
|
+
const owner = provider ?? preferences.lastProvider;
|
|
43
|
+
if (owner === null) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return preferences.selectionByProvider[owner] ?? null;
|
|
47
|
+
}
|
|
48
|
+
export function startingSelection(preferences, provider) {
|
|
49
|
+
return selectionFor(preferences, provider.kind) ?? (provider.defaultModel === null ? null : { model: provider.defaultModel, options: {} });
|
|
50
|
+
}
|
|
51
|
+
/* The pick lands in its provider's slot and makes that provider the global default. */
|
|
52
|
+
export function withSelection(preferences, provider, selection) {
|
|
53
|
+
return {
|
|
54
|
+
...preferences,
|
|
55
|
+
selectionByProvider: { ...preferences.selectionByProvider, [provider]: selection },
|
|
56
|
+
lastProvider: provider
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/*
|
|
60
|
+
* The account a new agent of this CLI starts under on this machine; null is the CLI's default account.
|
|
61
|
+
* Given the machine's accounts, a pick it turned off or removed is the default account again, so a new
|
|
62
|
+
* chat is never refused over it; `undefined` is a machine that did not say yet, where the pick stands.
|
|
63
|
+
*/
|
|
64
|
+
export function accountFor(preferences, scopeId, provider, accounts) {
|
|
65
|
+
const picked = preferences.accountByMachine[scopeId]?.[provider] ?? null;
|
|
66
|
+
if (picked === null || accounts === undefined) {
|
|
67
|
+
return picked;
|
|
68
|
+
}
|
|
69
|
+
const account = accounts?.accounts[picked];
|
|
70
|
+
return account?.kind === provider && account.enabled !== false ? picked : null;
|
|
71
|
+
}
|
|
72
|
+
/* The default account is what an absent pick means, so picking it takes the pick away. */
|
|
73
|
+
export function withAccount(preferences, scopeId, provider, account) {
|
|
74
|
+
const { [provider]: _previous, ...others } = preferences.accountByMachine[scopeId] ?? {};
|
|
75
|
+
const picks = account === null || account === provider ? others : { ...others, [provider]: account };
|
|
76
|
+
const { [scopeId]: _machine, ...machines } = preferences.accountByMachine;
|
|
77
|
+
return { ...preferences, accountByMachine: Object.keys(picks).length === 0 ? machines : { ...machines, [scopeId]: picks } };
|
|
78
|
+
}
|
|
79
|
+
/* What a machine starts a chat with when it starts one with no client mounting it; `accounts` as `accountFor` takes them. */
|
|
80
|
+
export function chatPreferencesPayload(preferences, scopeId, accounts) {
|
|
81
|
+
const picks = Object.keys(preferences.accountByMachine[scopeId] ?? {}).flatMap((provider) => {
|
|
82
|
+
const account = accountFor(preferences, scopeId, provider, accounts);
|
|
83
|
+
return account === null ? [] : [[provider, account]];
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
runtimeMode: preferences.runtimeMode,
|
|
87
|
+
terminalRuntimeMode: preferences.terminalRuntimeMode,
|
|
88
|
+
selections: preferences.selectionByProvider,
|
|
89
|
+
...(picks.length === 0 ? {} : { accounts: Object.fromEntries(picks) }),
|
|
90
|
+
changedAt: preferences.changedAt
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const storage = persistedJson(storageKey, parseChatPreferences, DEFAULT_CHAT_PREFERENCES, () => chatStorageLegacyKeys('preferences'));
|
|
94
|
+
/* What a new agent starts with: the last model and modes the person picked, like a remembered default. */
|
|
95
|
+
export const useChatPreferences = createChatStore(() => DEFAULT_CHAT_PREFERENCES, (store) => store.setState(storage.read(), true));
|
|
96
|
+
export function readChatPreferences() {
|
|
97
|
+
return useChatPreferences.getState();
|
|
98
|
+
}
|
|
99
|
+
/* Where the remembered default is kept, which an app with more than one window of the same origin listens for. */
|
|
100
|
+
export let CHAT_PREFERENCES_KEY = storageKey();
|
|
101
|
+
onChatStorageConfiguration(() => {
|
|
102
|
+
CHAT_PREFERENCES_KEY = storageKey();
|
|
103
|
+
});
|
|
104
|
+
export function chatPreferencesKey() {
|
|
105
|
+
return storageKey();
|
|
106
|
+
}
|
|
107
|
+
/* Reads the remembered default again, once another window of the same origin wrote it. */
|
|
108
|
+
export function reloadChatPreferences() {
|
|
109
|
+
useChatPreferences.setState(storage.read(), true);
|
|
110
|
+
}
|
|
111
|
+
function write(preferences) {
|
|
112
|
+
const next = { ...preferences, changedAt: Date.now() };
|
|
113
|
+
useChatPreferences.setState(next);
|
|
114
|
+
storage.write(next);
|
|
115
|
+
}
|
|
116
|
+
/* The composer writes here on every change and the settings dialog too; both edit the same remembered default. */
|
|
117
|
+
export function rememberChatPreferences(patch) {
|
|
118
|
+
write({ ...useChatPreferences.getState(), ...patch });
|
|
119
|
+
}
|
|
120
|
+
export function rememberChatSelection(provider, selection) {
|
|
121
|
+
const current = useChatPreferences.getState();
|
|
122
|
+
const previous = current.selectionByProvider[provider];
|
|
123
|
+
if (current.lastProvider === provider &&
|
|
124
|
+
previous?.model === selection.model &&
|
|
125
|
+
Object.keys(previous.options).length === Object.keys(selection.options).length &&
|
|
126
|
+
Object.entries(selection.options).every(([key, value]) => previous.options[key] === value)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
write(withSelection(current, provider, selection));
|
|
130
|
+
}
|
|
131
|
+
export function rememberChatAccount(scopeId, provider, account) {
|
|
132
|
+
write(withAccount(useChatPreferences.getState(), scopeId, provider, account));
|
|
133
|
+
}
|
|
134
|
+
/* Back to the CLI's own default for this provider; the other providers keep what they had. */
|
|
135
|
+
export function forgetChatSelection(provider) {
|
|
136
|
+
const current = useChatPreferences.getState();
|
|
137
|
+
const { [provider]: _dropped, ...rest } = current.selectionByProvider;
|
|
138
|
+
write({ ...current, selectionByProvider: rest, lastProvider: current.lastProvider === provider ? null : current.lastProvider });
|
|
139
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The text a selection in an answer quotes: its lines without trailing spaces or the blank lines
|
|
3
|
+
* around them, and at most one blank line in a row. A selection of only whitespace quotes nothing.
|
|
4
|
+
*/
|
|
5
|
+
export function quoteOf(selected) {
|
|
6
|
+
const text = selected
|
|
7
|
+
.replace(/\r\n?/g, '\n')
|
|
8
|
+
.split('\n')
|
|
9
|
+
.map((line) => line.replace(/\s+$/, ''))
|
|
10
|
+
.join('\n')
|
|
11
|
+
.replace(/^\n+|\n+$/g, '')
|
|
12
|
+
.replace(/\n{3,}/g, '\n\n');
|
|
13
|
+
return text.trim() === '' ? null : text;
|
|
14
|
+
}
|
|
15
|
+
/* The message as it goes out: the quote as a markdown blockquote, a blank line, then what was typed. */
|
|
16
|
+
export function withQuote(quote, message) {
|
|
17
|
+
if (quote === '') {
|
|
18
|
+
return message;
|
|
19
|
+
}
|
|
20
|
+
const block = quote
|
|
21
|
+
.split('\n')
|
|
22
|
+
.map((line) => (line === '' ? '>' : `> ${line}`))
|
|
23
|
+
.join('\n');
|
|
24
|
+
return message === '' ? block : `${block}\n\n${message}`;
|
|
25
|
+
}
|