@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,18 @@
|
|
|
1
|
+
export interface CodeToken {
|
|
2
|
+
content: string;
|
|
3
|
+
color?: string;
|
|
4
|
+
fontStyle?: number;
|
|
5
|
+
}
|
|
6
|
+
export type Tokenize<State> = (code: string, state: State | undefined) => {
|
|
7
|
+
lines: CodeToken[][];
|
|
8
|
+
state: State | undefined;
|
|
9
|
+
};
|
|
10
|
+
export declare class IncrementalLines<State> {
|
|
11
|
+
private readonly tokenize;
|
|
12
|
+
private source;
|
|
13
|
+
private lines;
|
|
14
|
+
private state;
|
|
15
|
+
constructor(tokenize: Tokenize<State>);
|
|
16
|
+
update(code: string, complete: boolean): CodeToken[][];
|
|
17
|
+
private reset;
|
|
18
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The lines of a code block that grows at the end. A line that ended keeps the tokens it got, and
|
|
3
|
+
* the grammar state after it is where the next line starts, so a delta tokenizes the lines that are
|
|
4
|
+
* new plus the one still being written, however long the block already is. The last line is always
|
|
5
|
+
* tokenized again, since the next delta may turn it into anything (the start of a comment, a string).
|
|
6
|
+
*/
|
|
7
|
+
export class IncrementalLines {
|
|
8
|
+
tokenize;
|
|
9
|
+
// The text of the lines that are kept: empty, or ending in a newline while the block grows.
|
|
10
|
+
source = '';
|
|
11
|
+
lines = [];
|
|
12
|
+
state = undefined;
|
|
13
|
+
constructor(tokenize) {
|
|
14
|
+
this.tokenize = tokenize;
|
|
15
|
+
}
|
|
16
|
+
/* The tokens of every line of `code`; `complete` says nothing more arrives, so the last line is kept too. */
|
|
17
|
+
update(code, complete) {
|
|
18
|
+
// A carriage return splits lines in ways a cut at newlines does not see, so that code starts over every time.
|
|
19
|
+
if (code.includes('\r')) {
|
|
20
|
+
this.reset();
|
|
21
|
+
return this.tokenize(code, undefined).lines;
|
|
22
|
+
}
|
|
23
|
+
const end = complete ? code.length : code.lastIndexOf('\n') + 1;
|
|
24
|
+
const stable = code.slice(0, end);
|
|
25
|
+
const continues = (this.source === '' || this.source.endsWith('\n')) && stable.startsWith(this.source);
|
|
26
|
+
if (!continues) {
|
|
27
|
+
this.reset();
|
|
28
|
+
}
|
|
29
|
+
const added = stable.slice(this.source.length);
|
|
30
|
+
if (added !== '') {
|
|
31
|
+
const result = this.tokenize(added.endsWith('\n') ? added.slice(0, -1) : added, this.state);
|
|
32
|
+
this.lines = [...this.lines, ...result.lines];
|
|
33
|
+
this.state = result.state;
|
|
34
|
+
this.source = stable;
|
|
35
|
+
}
|
|
36
|
+
if (complete) {
|
|
37
|
+
return this.lines;
|
|
38
|
+
}
|
|
39
|
+
return [...this.lines, ...this.tokenize(code.slice(end), this.state).lines];
|
|
40
|
+
}
|
|
41
|
+
reset() {
|
|
42
|
+
this.source = '';
|
|
43
|
+
this.lines = [];
|
|
44
|
+
this.state = undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const CodeStreamingContext: import("react").Context<boolean>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { chatHost } from '../../host.js';
|
|
2
|
+
/* The Shiki theme code is drawn in under the app's current light or dark. */
|
|
3
|
+
export function useCodeTheme() {
|
|
4
|
+
const { code } = chatHost();
|
|
5
|
+
const mode = code.useMode();
|
|
6
|
+
const themes = code.useThemes();
|
|
7
|
+
return mode === 'dark' ? themes.dark : themes.light;
|
|
8
|
+
}
|
|
9
|
+
/* What to hand Shiki for a theme id: a theme the app ships itself, or the id of a bundled one for Shiki to load. */
|
|
10
|
+
export function shikiThemeOf(id) {
|
|
11
|
+
return chatHost().code.custom.find((theme) => theme.name === id) ?? id;
|
|
12
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { syntaxTree } from '@codemirror/language';
|
|
2
|
+
import { Facet, RangeSetBuilder, StateField } from '@codemirror/state';
|
|
3
|
+
import { Decoration, EditorView } from '@codemirror/view';
|
|
4
|
+
import { chipRanges } from '../../mentions.js';
|
|
5
|
+
import { CHIP_IN_EDITOR, MENTION_TONE, SKILL_TONE } from '../chips.js';
|
|
6
|
+
import { codeRanges } from './editor.js';
|
|
7
|
+
const NO_CHOICES = { mentions: [], skills: [] };
|
|
8
|
+
const choices = Facet.define({ combine: (values) => values[0] ?? NO_CHOICES });
|
|
9
|
+
const mentionMark = Decoration.mark({ class: `${MENTION_TONE} ${CHIP_IN_EDITOR}` });
|
|
10
|
+
const skillMark = Decoration.mark({ class: `${SKILL_TONE} ${CHIP_IN_EDITOR}` });
|
|
11
|
+
function chipMarks(state) {
|
|
12
|
+
const { mentions, skills } = state.facet(choices);
|
|
13
|
+
const builder = new RangeSetBuilder();
|
|
14
|
+
// `@a.ts` in backticks is code, not a mention.
|
|
15
|
+
for (const range of chipRanges(state.doc.toString(), mentions, skills, codeRanges(state))) {
|
|
16
|
+
builder.add(range.from, range.to, range.kind === 'skill' ? skillMark : mentionMark);
|
|
17
|
+
}
|
|
18
|
+
return builder.finish();
|
|
19
|
+
}
|
|
20
|
+
const chipField = StateField.define({
|
|
21
|
+
create: chipMarks,
|
|
22
|
+
// The parser finishes a long text after the edit that asked for it, and a code span it finds then unmakes a chip.
|
|
23
|
+
update: (marks, tr) => tr.docChanged || tr.startState.facet(choices) !== tr.state.facet(choices) || syntaxTree(tr.startState) !== syntaxTree(tr.state)
|
|
24
|
+
? chipMarks(tr.state)
|
|
25
|
+
: marks,
|
|
26
|
+
provide: (field) => EditorView.decorations.from(field)
|
|
27
|
+
});
|
|
28
|
+
/* Draws the chosen `@path` and `$name` tokens as chips; a new `ChipChoices` object is what redraws them. */
|
|
29
|
+
export function chipDecorations(value) {
|
|
30
|
+
return [choices.of(value), chipField];
|
|
31
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Language } from '@codemirror/language';
|
|
2
|
+
import { type EditorState, type Extension } from '@codemirror/state';
|
|
3
|
+
export declare const externalChange: import("@codemirror/state").AnnotationType<boolean>;
|
|
4
|
+
export declare const markdownLanguage: Language;
|
|
5
|
+
export interface CodeRange {
|
|
6
|
+
from: number;
|
|
7
|
+
to: number;
|
|
8
|
+
kind: 'inline' | 'fence';
|
|
9
|
+
}
|
|
10
|
+
export declare function codeRanges(state: EditorState, from?: number, to?: number): CodeRange[];
|
|
11
|
+
export declare function composerEditorExtensions(): Extension;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { history, historyKeymap, standardKeymap } from '@codemirror/commands';
|
|
2
|
+
import { Language, defineLanguageFacet, indentUnit, syntaxHighlighting, syntaxTree } from '@codemirror/language';
|
|
3
|
+
import { Annotation } from '@codemirror/state';
|
|
4
|
+
import { Decoration, EditorView, ViewPlugin, keymap } from '@codemirror/view';
|
|
5
|
+
import { tagHighlighter, tags } from '@lezer/highlight';
|
|
6
|
+
import { Strikethrough, Table, parser } from '@lezer/markdown';
|
|
7
|
+
/* Marks a transaction that brings the editor in line with a value set from outside, so it is not reported back. */
|
|
8
|
+
export const externalChange = Annotation.define();
|
|
9
|
+
/*
|
|
10
|
+
* The markdown grammar in a Language of our own. `@codemirror/lang-markdown` builds the same thing
|
|
11
|
+
* but creates the HTML language and autocomplete at module level, which tree shaking cannot drop.
|
|
12
|
+
*/
|
|
13
|
+
export const markdownLanguage = new Language(defineLanguageFacet(), parser.configure([Strikethrough, Table]), [], 'markdown');
|
|
14
|
+
/* Classes rather than generated styles, so the look lives in `styles.css` on the theme's tokens. */
|
|
15
|
+
const markdownClasses = tagHighlighter([
|
|
16
|
+
{ tag: tags.strong, class: 'cm-md-strong' },
|
|
17
|
+
{ tag: tags.emphasis, class: 'cm-md-emphasis' },
|
|
18
|
+
{ tag: tags.strikethrough, class: 'cm-md-strike' },
|
|
19
|
+
{ tag: tags.heading, class: 'cm-md-heading' },
|
|
20
|
+
{ tag: [tags.link, tags.url], class: 'cm-md-link' },
|
|
21
|
+
{ tag: tags.processingInstruction, class: 'cm-md-mark' }
|
|
22
|
+
]);
|
|
23
|
+
/* The code spans and fenced blocks between `from` and `to`, as far as the parser has got. */
|
|
24
|
+
export function codeRanges(state, from = 0, to = state.doc.length) {
|
|
25
|
+
const found = [];
|
|
26
|
+
syntaxTree(state).iterate({
|
|
27
|
+
from,
|
|
28
|
+
to,
|
|
29
|
+
enter: (node) => {
|
|
30
|
+
if (node.name === 'InlineCode' || node.name === 'FencedCode') {
|
|
31
|
+
found.push({ from: node.from, to: node.to, kind: node.name === 'InlineCode' ? 'inline' : 'fence' });
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return found;
|
|
38
|
+
}
|
|
39
|
+
const inlineCodeMark = Decoration.mark({ class: 'cm-md-code' });
|
|
40
|
+
function fenceLine(first, last) {
|
|
41
|
+
return Decoration.line({ class: ['cm-md-fence', first ? 'cm-md-fence-start' : '', last ? 'cm-md-fence-end' : ''].join(' ').trim() });
|
|
42
|
+
}
|
|
43
|
+
/*
|
|
44
|
+
* Code is decorated from the tree rather than highlighted per token: the highlighter styles the
|
|
45
|
+
* backticks apart from what they wrap, and a block's background belongs to its whole lines.
|
|
46
|
+
*/
|
|
47
|
+
function codeDecorations(view) {
|
|
48
|
+
const { state } = view;
|
|
49
|
+
const decorations = [];
|
|
50
|
+
const fenceLines = new Set();
|
|
51
|
+
for (const visible of view.visibleRanges) {
|
|
52
|
+
for (const range of codeRanges(state, visible.from, visible.to)) {
|
|
53
|
+
if (range.kind === 'inline') {
|
|
54
|
+
decorations.push(inlineCodeMark.range(range.from, range.to));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const first = state.doc.lineAt(range.from).number;
|
|
58
|
+
const last = state.doc.lineAt(range.to).number;
|
|
59
|
+
const start = state.doc.lineAt(Math.max(range.from, visible.from)).number;
|
|
60
|
+
const end = state.doc.lineAt(Math.min(range.to, visible.to)).number;
|
|
61
|
+
for (let number = start; number <= end; number++) {
|
|
62
|
+
if (!fenceLines.has(number)) {
|
|
63
|
+
fenceLines.add(number);
|
|
64
|
+
decorations.push(fenceLine(number === first, number === last).range(state.doc.line(number).from));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return Decoration.set(decorations, true);
|
|
70
|
+
}
|
|
71
|
+
const codeDecorationPlugin = ViewPlugin.fromClass(class {
|
|
72
|
+
decorations;
|
|
73
|
+
constructor(view) {
|
|
74
|
+
this.decorations = codeDecorations(view);
|
|
75
|
+
}
|
|
76
|
+
update(update) {
|
|
77
|
+
if (update.docChanged || update.viewportChanged || syntaxTree(update.startState) !== syntaxTree(update.state)) {
|
|
78
|
+
this.decorations = codeDecorations(update.view);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}, { decorations: (plugin) => plugin.decorations });
|
|
82
|
+
/*
|
|
83
|
+
* What every composer editor carries. The standard keymap rather than the default one: the default
|
|
84
|
+
* adds code editor commands (move a line, indent, select the syntax parent) on keys a prompt box
|
|
85
|
+
* has no business taking.
|
|
86
|
+
*/
|
|
87
|
+
export function composerEditorExtensions() {
|
|
88
|
+
return [
|
|
89
|
+
history(),
|
|
90
|
+
keymap.of([...standardKeymap, ...historyKeymap]),
|
|
91
|
+
EditorView.lineWrapping,
|
|
92
|
+
// What Tab and Shift+Tab in a fence add and take away, so a selection indents in the same steps as a caret.
|
|
93
|
+
indentUnit.of(' '),
|
|
94
|
+
markdownLanguage,
|
|
95
|
+
syntaxHighlighting(markdownClasses),
|
|
96
|
+
codeDecorationPlugin
|
|
97
|
+
];
|
|
98
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function isSpace(text) {
|
|
2
|
+
return /^\s/.test(text);
|
|
3
|
+
}
|
|
4
|
+
/*
|
|
5
|
+
* Text an app puts in the draft, over the selection, as if it were typed there. A space keeps it apart
|
|
6
|
+
* from a word it would touch, and one after it at the end of the text lets the person type on.
|
|
7
|
+
*/
|
|
8
|
+
export function insertAtSelection(state, text) {
|
|
9
|
+
if (text === '') {
|
|
10
|
+
return {};
|
|
11
|
+
}
|
|
12
|
+
const { from, to } = state.selection.main;
|
|
13
|
+
const before = state.doc.sliceString(Math.max(0, from - 1), from);
|
|
14
|
+
const after = state.doc.sliceString(to, to + 1);
|
|
15
|
+
const lead = before !== '' && !isSpace(before) && !isSpace(text) ? ' ' : '';
|
|
16
|
+
const trail = (after === '' || !isSpace(after)) && !/\s$/.test(text) ? ' ' : '';
|
|
17
|
+
const insert = `${lead}${text}${trail}`;
|
|
18
|
+
return { changes: { from, to, insert }, selection: { anchor: from + insert.length }, scrollIntoView: true, userEvent: 'input' };
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Tree } from '@lezer/common';
|
|
2
|
+
export type EnterAction = 'send' | 'newline' | 'continue-list' | 'leave-list';
|
|
3
|
+
export interface EnterKeys {
|
|
4
|
+
shift: boolean;
|
|
5
|
+
mod: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ListItem {
|
|
8
|
+
prefix: string;
|
|
9
|
+
next: string;
|
|
10
|
+
empty: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface EnterContext {
|
|
13
|
+
inOpenFence: boolean;
|
|
14
|
+
list: ListItem | null;
|
|
15
|
+
column: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function listItemAt(line: string): ListItem | null;
|
|
18
|
+
export declare function enterAction(keys: EnterKeys, { inOpenFence, list, column }: EnterContext): EnterAction;
|
|
19
|
+
export declare function inOpenFence(tree: Tree, pos: number): boolean;
|
|
20
|
+
export declare function inFenceBody(tree: Tree, text: string, pos: number): boolean;
|
|
21
|
+
export declare function tabSpaces(column: number): string;
|
|
22
|
+
export declare function inCode(tree: Tree, text: string, pos: number): boolean;
|
|
23
|
+
export interface RecallContext {
|
|
24
|
+
key: string;
|
|
25
|
+
text: string;
|
|
26
|
+
from: number;
|
|
27
|
+
to: number;
|
|
28
|
+
recalled: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function recallDirection({ key, text, from, to, recalled }: RecallContext): -1 | 1 | null;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const LIST_ITEM = /^([ \t]*)(?:([-*+])|(\d{1,9})([.)]))([ \t]+)(\[[ xX]\](?:[ \t]+|$))?/;
|
|
2
|
+
/* The list item a line starts, if it starts one. */
|
|
3
|
+
export function listItemAt(line) {
|
|
4
|
+
const match = LIST_ITEM.exec(line);
|
|
5
|
+
if (match === null) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
const [prefix, indent, bullet, number, delimiter, space, task] = match;
|
|
9
|
+
const marker = bullet ?? `${Number(number) + 1}${delimiter}`;
|
|
10
|
+
return { prefix, next: `${indent}${marker}${space}${task ? '[ ] ' : ''}`, empty: line.slice(prefix.length).trim() === '' };
|
|
11
|
+
}
|
|
12
|
+
/*
|
|
13
|
+
* Enter sends, except where whoever types is still writing: inside a fence nobody has closed yet
|
|
14
|
+
* it adds a line, and in a list it starts the next item, or leaves the list from an empty one, so
|
|
15
|
+
* a second Enter breaks out. Shift adds a plain line and Mod sends from anywhere.
|
|
16
|
+
*/
|
|
17
|
+
export function enterAction(keys, { inOpenFence, list, column }) {
|
|
18
|
+
if (keys.mod) {
|
|
19
|
+
return 'send';
|
|
20
|
+
}
|
|
21
|
+
if (keys.shift || inOpenFence) {
|
|
22
|
+
return 'newline';
|
|
23
|
+
}
|
|
24
|
+
if (list === null) {
|
|
25
|
+
return 'send';
|
|
26
|
+
}
|
|
27
|
+
// A caret in front of the marker moves the item down rather than splitting its marker.
|
|
28
|
+
if (column < list.prefix.length) {
|
|
29
|
+
return 'newline';
|
|
30
|
+
}
|
|
31
|
+
return list.empty ? 'leave-list' : 'continue-list';
|
|
32
|
+
}
|
|
33
|
+
/* Whether `pos` sits inside a fenced code block that has an opening fence and no closing one yet. */
|
|
34
|
+
export function inOpenFence(tree, pos) {
|
|
35
|
+
for (let node = tree.resolveInner(pos, -1); node !== null; node = node.parent) {
|
|
36
|
+
if (node.name === 'FencedCode') {
|
|
37
|
+
return pos > node.from && node.getChildren('CodeMark').length < 2;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/* Whether `pos` sits in the body of a fenced code block, open or closed: below its opening line and before its end. */
|
|
43
|
+
export function inFenceBody(tree, text, pos) {
|
|
44
|
+
for (let node = tree.resolveInner(pos, -1); node !== null; node = node.parent) {
|
|
45
|
+
if (node.name === 'FencedCode') {
|
|
46
|
+
const openingEnd = text.indexOf('\n', node.from);
|
|
47
|
+
return openingEnd !== -1 && pos > openingEnd && (pos < node.to || node.getChildren('CodeMark').length < 2);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
/* The spaces Tab inserts at `column`, up to the next stop of four, the way a code editor lines up. */
|
|
53
|
+
export function tabSpaces(column) {
|
|
54
|
+
return ' '.repeat(4 - (column % 4));
|
|
55
|
+
}
|
|
56
|
+
const INLINE_BLOCK = /^(Paragraph|ATXHeading\d|SetextHeading\d)$/;
|
|
57
|
+
/*
|
|
58
|
+
* Whether `pos` sits inside code: a fence, open or closed, or a code span. The parser only calls a
|
|
59
|
+
* span code once it is closed, so a backtick nobody has closed yet earlier in the same paragraph
|
|
60
|
+
* counts as well: whoever types after it is writing code.
|
|
61
|
+
*/
|
|
62
|
+
export function inCode(tree, text, pos) {
|
|
63
|
+
let blockFrom = null;
|
|
64
|
+
for (let node = tree.resolveInner(pos, -1); node !== null; node = node.parent) {
|
|
65
|
+
if (node.name === 'FencedCode') {
|
|
66
|
+
return pos > node.from && (pos < node.to || node.getChildren('CodeMark').length < 2);
|
|
67
|
+
}
|
|
68
|
+
if (node.name === 'InlineCode' && pos > node.from && pos < node.to) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (blockFrom === null && INLINE_BLOCK.test(node.name)) {
|
|
72
|
+
blockFrom = node.from;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
let from = blockFrom ?? text.lastIndexOf('\n', pos - 1) + 1;
|
|
76
|
+
tree.iterate({
|
|
77
|
+
from,
|
|
78
|
+
to: pos,
|
|
79
|
+
enter: (node) => {
|
|
80
|
+
if (node.name === 'InlineCode' && node.to <= pos) {
|
|
81
|
+
from = Math.max(from, node.to);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return /(^|[^\\])`/.test(text.slice(from, pos));
|
|
86
|
+
}
|
|
87
|
+
/*
|
|
88
|
+
* Which way the arrow walks through earlier prompts, or null when the arrow just moves the caret.
|
|
89
|
+
* Only an empty box or an unedited recall walks, so an arrow in a prompt being written never
|
|
90
|
+
* throws it away.
|
|
91
|
+
*/
|
|
92
|
+
export function recallDirection({ key, text, from, to, recalled }) {
|
|
93
|
+
if (key === 'ArrowUp' && (text === '' || (recalled && from === 0))) {
|
|
94
|
+
return -1;
|
|
95
|
+
}
|
|
96
|
+
if (key === 'ArrowDown' && recalled && to === text.length) {
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { registerCustomTheme } from '@pierre/diffs';
|
|
3
|
+
import { chatHost } from '../../host.js';
|
|
4
|
+
let registered = false;
|
|
5
|
+
/* The library resolves Shiki's bundled themes by id on its own; the app's own it only knows by registration, done once the host is set. */
|
|
6
|
+
function registerThemes() {
|
|
7
|
+
if (registered) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
registered = true;
|
|
11
|
+
for (const theme of chatHost().code.custom) {
|
|
12
|
+
registerCustomTheme(theme.name, () => Promise.resolve(theme));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/* The code themes a diff is drawn in, the same pair a chat's code blocks use. */
|
|
16
|
+
export function useDiffTheme() {
|
|
17
|
+
registerThemes();
|
|
18
|
+
const { light, dark } = chatHost().code.useThemes();
|
|
19
|
+
return useMemo(() => ({ light, dark }), [light, dark]);
|
|
20
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type FileRef } from '../../host.js';
|
|
2
|
+
export declare const FileLinkContext: import("react").Context<string | null>;
|
|
3
|
+
export declare function useFileLinkCwd(): string | null;
|
|
4
|
+
export declare function useFileLinkTarget(text: string): FileRef | null;
|
|
5
|
+
export declare function openFileLink(cwd: string | null, ref: FileRef): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
2
|
+
import { chatHost } from '../../host.js';
|
|
3
|
+
/*
|
|
4
|
+
* The folder a relative reference in rendered text counts from: a chat's own cwd, which is a
|
|
5
|
+
* worktree as often as it is the project, or the folder of the file an app is drawing. Null where
|
|
6
|
+
* nobody said, and there only an absolute path is a link.
|
|
7
|
+
*/
|
|
8
|
+
export const FileLinkContext = createContext(null);
|
|
9
|
+
export function useFileLinkCwd() {
|
|
10
|
+
return useContext(FileLinkContext);
|
|
11
|
+
}
|
|
12
|
+
/* The reference a piece of text names, only where this spot on screen could open it. */
|
|
13
|
+
export function useFileLinkTarget(text) {
|
|
14
|
+
const cwd = useFileLinkCwd();
|
|
15
|
+
return useMemo(() => chatHost().fileLinks?.target(text, cwd) ?? null, [text, cwd]);
|
|
16
|
+
}
|
|
17
|
+
/* A reference followed, the way the app opens a file or a folder. */
|
|
18
|
+
export function openFileLink(cwd, ref) {
|
|
19
|
+
chatHost().fileLinks?.open(cwd, ref);
|
|
20
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type ChatFindField = 'summary' | 'text' | 'output';
|
|
2
|
+
export interface FindReveal {
|
|
3
|
+
itemId: string;
|
|
4
|
+
field: ChatFindField;
|
|
5
|
+
}
|
|
6
|
+
export declare const FindRevealContext: import("react").Context<FindReveal | null>;
|
|
7
|
+
export declare function useOpenForFind(itemId: string, field: ChatFindField, setOpen: (open: boolean) => void): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect } from 'react';
|
|
2
|
+
/* The hit the find bar is on, so the row that folds it away can open. */
|
|
3
|
+
export const FindRevealContext = createContext(null);
|
|
4
|
+
/* Opens a fold of this item while the find bar is on a hit inside it; it stays open once the bar moves on, as if a person opened it. */
|
|
5
|
+
export function useOpenForFind(itemId, field, setOpen) {
|
|
6
|
+
const reveal = useContext(FindRevealContext);
|
|
7
|
+
const wanted = reveal !== null && reveal.itemId === itemId && reveal.field === field;
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (wanted) {
|
|
10
|
+
setOpen(true);
|
|
11
|
+
}
|
|
12
|
+
}, [wanted, reveal, setOpen]);
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { processFile } from '@pierre/diffs';
|
|
2
|
+
/*
|
|
3
|
+
* A patch laid over the two whole texts it was made between, which is what lets a reader unfold
|
|
4
|
+
* the lines between its hunks. The hunks stay the patch's own, so a patch made without whitespace
|
|
5
|
+
* keeps its counts. Null when there is no hunk to lay over them, and the patch alone is drawn.
|
|
6
|
+
*/
|
|
7
|
+
export function fullFileDiff(patch, name, contents) {
|
|
8
|
+
try {
|
|
9
|
+
const parsed = processFile(patch, {
|
|
10
|
+
oldFile: { name, contents: contents.old },
|
|
11
|
+
newFile: { name, contents: contents.new },
|
|
12
|
+
throwOnError: true
|
|
13
|
+
});
|
|
14
|
+
return parsed === undefined || parsed.isPartial || parsed.hunks.length === 0 ? null : parsed;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Hammer, Wrench } from 'lucide-react';
|
|
3
|
+
import { toolEntry } from '../logic/tool-catalog.js';
|
|
4
|
+
import { Icon } from '@adecore/ui';
|
|
5
|
+
const SIZE = 12;
|
|
6
|
+
/* A pending dock draws its mark a step up from the lines of a transcript, at the size a sidebar
|
|
7
|
+
row uses, because it is a thing to answer rather than a thing to read past. */
|
|
8
|
+
export const DOCK_ICON_SIZE = 14;
|
|
9
|
+
/* The gutter every row in the thread opens with: 16 wide, on the line box of its first row of text,
|
|
10
|
+
so the mark of a tool call, a note and a fold all sit in one column and their labels start at the
|
|
11
|
+
same x. The same box the menu rows and the toasts use. */
|
|
12
|
+
export const ROW_GUTTER = 'grid h-5 w-4 shrink-0 place-items-center';
|
|
13
|
+
/* The icon that says what a tool call is about; unknown tools get the wrench. */
|
|
14
|
+
export function toolIcon(name, size = SIZE) {
|
|
15
|
+
const known = toolEntry(name);
|
|
16
|
+
if (known !== undefined) {
|
|
17
|
+
return _jsx(Icon, { icon: known.icon, size: size });
|
|
18
|
+
}
|
|
19
|
+
return name.startsWith('mcp__') ? _jsx(Icon, { icon: Hammer, size: size }) : _jsx(Icon, { icon: Wrench, size: size });
|
|
20
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const FENCE = /^([ \t]*)(`{3,}|~{3,})(.*)$/;
|
|
2
|
+
// Spaces and tabs only: a line that holds a no-break space is text to markdown, not a blank line.
|
|
3
|
+
const BLANK = /^[ \t]*$/;
|
|
4
|
+
// A line that continues what stood before the blank line: an indented paragraph of a list item, or
|
|
5
|
+
// the next item of a loose list. Splitting there would change what the markdown means.
|
|
6
|
+
const CONTINUES = /^([ \t]|[-*+][ \t]|\d+[.)][ \t])/;
|
|
7
|
+
// A reference or footnote definition may be used anywhere in the text, so a block cannot stand alone.
|
|
8
|
+
const DEFINITION = /^ {0,3}\[[^\]]+\]:/m;
|
|
9
|
+
// How much deeper than its opening a closing fence may sit; deeper than that it is a line of code.
|
|
10
|
+
const CLOSING_INDENT = 3;
|
|
11
|
+
// A section title: an ATX heading, or a line of only bold text, which models write as a heading too.
|
|
12
|
+
const HEADING = /^ {0,3}#{1,6}(?:[ \t]|$)/;
|
|
13
|
+
const BOLD_LINE = /^ {0,3}\*\*(?:[^*]|\*(?!\*))+\*\*:?[ \t]*$/;
|
|
14
|
+
/*
|
|
15
|
+
* A reply cut into blocks at blank lines outside a code fence, so each block parses on its own and
|
|
16
|
+
* only the one still growing is parsed again. Joined back together the blocks are the text.
|
|
17
|
+
*/
|
|
18
|
+
export function splitMarkdownBlocks(text) {
|
|
19
|
+
if (DEFINITION.test(text)) {
|
|
20
|
+
return [{ text, openFence: isFenceOpenAtEnd(text) }];
|
|
21
|
+
}
|
|
22
|
+
const lines = text.split('\n');
|
|
23
|
+
const blocks = [];
|
|
24
|
+
let start = 0;
|
|
25
|
+
let offset = 0;
|
|
26
|
+
let fence = null;
|
|
27
|
+
let afterBlank = false;
|
|
28
|
+
lines.forEach((line, index) => {
|
|
29
|
+
if (fence === null && afterBlank && !BLANK.test(line) && !CONTINUES.test(line)) {
|
|
30
|
+
blocks.push({ text: text.slice(start, offset), openFence: false });
|
|
31
|
+
start = offset;
|
|
32
|
+
}
|
|
33
|
+
fence = nextFence(fence, line);
|
|
34
|
+
afterBlank = fence === null && BLANK.test(line) && index > 0;
|
|
35
|
+
offset += line.length + 1;
|
|
36
|
+
});
|
|
37
|
+
blocks.push({ text: text.slice(start), openFence: fence !== null });
|
|
38
|
+
return blocks;
|
|
39
|
+
}
|
|
40
|
+
/*
|
|
41
|
+
* The blocks of a reply still being written that will not change any more: every block but the last.
|
|
42
|
+
* A block is only known to be closed once the line after its blank line starts, since that line may
|
|
43
|
+
* still turn out to continue it (a list item, an indented paragraph). A section title waits for the
|
|
44
|
+
* block under it, so it never sits alone above a block that is still streaming.
|
|
45
|
+
*/
|
|
46
|
+
export function settledBlocksText(text) {
|
|
47
|
+
return withoutTrailingTitles(splitMarkdownBlocks(text)
|
|
48
|
+
.slice(0, -1)
|
|
49
|
+
.map((block) => block.text)
|
|
50
|
+
.join(''));
|
|
51
|
+
}
|
|
52
|
+
function withoutTrailingTitles(text) {
|
|
53
|
+
const lines = text.split('\n');
|
|
54
|
+
let end = lines.length;
|
|
55
|
+
for (let index = lines.length - 1; index >= 0; index--) {
|
|
56
|
+
const line = lines[index];
|
|
57
|
+
if (BLANK.test(line)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// A bold line right under a line of text continues that paragraph.
|
|
61
|
+
const title = HEADING.test(line) || (BOLD_LINE.test(line) && (index === 0 || BLANK.test(lines[index - 1])));
|
|
62
|
+
if (!title) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
end = index;
|
|
66
|
+
}
|
|
67
|
+
if (end === lines.length) {
|
|
68
|
+
return text;
|
|
69
|
+
}
|
|
70
|
+
return lines
|
|
71
|
+
.slice(0, end)
|
|
72
|
+
.map((line) => `${line}\n`)
|
|
73
|
+
.join('');
|
|
74
|
+
}
|
|
75
|
+
/* The fence a line leaves open: it opens one, closes the one that is open, or changes nothing. */
|
|
76
|
+
function nextFence(fence, line) {
|
|
77
|
+
const match = FENCE.exec(line);
|
|
78
|
+
if (!match) {
|
|
79
|
+
return fence;
|
|
80
|
+
}
|
|
81
|
+
const indent = match[1].length;
|
|
82
|
+
const run = match[2];
|
|
83
|
+
const rest = match[3];
|
|
84
|
+
if (fence === null) {
|
|
85
|
+
// A backtick fence's info string may not hold a backtick, or the line is inline code.
|
|
86
|
+
if (run[0] === '`' && rest.includes('`')) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return { marker: run[0], length: run.length, indent };
|
|
90
|
+
}
|
|
91
|
+
// A closing fence carries no info string, and a line far deeper than the opening is code.
|
|
92
|
+
if (run[0] === fence.marker && run.length >= fence.length && BLANK.test(rest) && indent <= fence.indent + CLOSING_INDENT) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return fence;
|
|
96
|
+
}
|
|
97
|
+
function isFenceOpenAtEnd(text) {
|
|
98
|
+
let fence = null;
|
|
99
|
+
for (const line of text.split('\n')) {
|
|
100
|
+
fence = nextFence(fence, line);
|
|
101
|
+
}
|
|
102
|
+
return fence !== null;
|
|
103
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type QuoteTaker = (quote: string) => void;
|
|
2
|
+
export declare const QuoteTakerContext: import("react").Context<((take: QuoteTaker) => () => void) | null>;
|
|
3
|
+
export declare function selectedAnswerQuote(selection: Selection | null, thread: HTMLElement | null): string | null;
|