@adecore/agents-react 0.31.11 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/AccountDot.js +57 -6
- package/dist/agents/AgentIcon.js +88 -12
- package/dist/agents/ModelOptionControl.js +153 -18
- package/dist/agents/ProviderLogo.js +49 -4
- package/dist/agents/account-limits.js +17 -14
- package/dist/agents/accounts.js +99 -67
- package/dist/agents/agent-marks.js +5 -3
- package/dist/agents/model-name.js +42 -31
- package/dist/agents/model-options.js +8 -8
- package/dist/agents/model-requirement.js +17 -14
- package/dist/agents/option-words.d.ts +7 -0
- package/dist/agents/option-words.js +35 -0
- package/dist/agents/provider-paths.js +6 -6
- package/dist/agents/status-look.js +32 -12
- package/dist/chat/account-choice.d.ts +13 -0
- package/dist/chat/account-choice.js +90 -20
- package/dist/chat/actions.js +126 -59
- package/dist/chat/activity.js +5 -5
- package/dist/chat/attachments.js +74 -53
- package/dist/chat/bookmarks.js +58 -48
- package/dist/chat/chat-client.js +344 -263
- package/dist/chat/chat-references.js +3 -3
- package/dist/chat/composer-effort.d.ts +5 -0
- package/dist/chat/composer-effort.js +26 -0
- package/dist/chat/composer-send.js +13 -13
- package/dist/chat/drafts.js +115 -79
- package/dist/chat/forks.js +81 -24
- package/dist/chat/guards.js +15 -43
- package/dist/chat/index.d.ts +3 -1
- package/dist/chat/index.js +3 -2
- package/dist/chat/logic/ansi.js +170 -167
- package/dist/chat/logic/answers.js +2 -2
- package/dist/chat/logic/bookmarks.js +19 -19
- package/dist/chat/logic/command-looks.js +138 -96
- package/dist/chat/logic/context-usage.js +13 -9
- package/dist/chat/logic/continue-after-stop.js +15 -19
- package/dist/chat/logic/effort.d.ts +14 -0
- package/dist/chat/logic/effort.js +34 -0
- package/dist/chat/logic/embedded-code.js +387 -326
- package/dist/chat/logic/fork.js +134 -110
- package/dist/chat/logic/generated-image.js +54 -23
- package/dist/chat/logic/goal.js +28 -20
- package/dist/chat/logic/handback.js +6 -6
- package/dist/chat/logic/json.js +2 -2
- package/dist/chat/logic/limit.js +46 -30
- package/dist/chat/logic/picker-entries.d.ts +5 -3
- package/dist/chat/logic/picker-entries.js +83 -43
- package/dist/chat/logic/resume-compaction.d.ts +14 -1
- package/dist/chat/logic/resume-compaction.js +93 -24
- package/dist/chat/logic/scrubber.js +188 -136
- package/dist/chat/logic/thought.js +13 -16
- package/dist/chat/logic/thread-cards.js +60 -48
- package/dist/chat/logic/timeline-copy.js +30 -38
- package/dist/chat/logic/timeline-target.js +92 -63
- package/dist/chat/logic/timeline.js +499 -355
- package/dist/chat/logic/tool-catalog.js +54 -34
- package/dist/chat/logic/tools.js +106 -82
- package/dist/chat/logic/visual-height.js +18 -18
- package/dist/chat/logic/visual-viewport.js +6 -3
- package/dist/chat/logic/welcome.js +9 -9
- package/dist/chat/logic/workflow.js +45 -34
- package/dist/chat/mentions.js +149 -109
- package/dist/chat/persisted-json.js +51 -54
- package/dist/chat/preferences.d.ts +4 -0
- package/dist/chat/preferences.js +162 -84
- package/dist/chat/prompt-hold.js +9 -9
- package/dist/chat/quote.js +21 -30
- package/dist/chat/reading-width.js +12 -10
- package/dist/chat/recent-messages.js +34 -21
- package/dist/chat/resume-compaction-dismissals.js +25 -5
- package/dist/chat/runtime-modes.js +3 -3
- package/dist/chat/send-key.js +11 -7
- package/dist/chat/stash.js +89 -69
- package/dist/chat/subagent-conversation.js +181 -139
- package/dist/chat/subagent-list.js +65 -67
- package/dist/chat/subagent-support.js +12 -7
- package/dist/chat/subagent-view.js +132 -44
- package/dist/chat/thumbnails.js +88 -60
- package/dist/chat/timeline-flash.js +24 -12
- package/dist/chat/timeline-scroll.js +116 -86
- package/dist/chat/ui/AccountPill.js +126 -15
- package/dist/chat/ui/AnsiOutput.js +62 -6
- package/dist/chat/ui/BookmarkMarker.js +231 -41
- package/dist/chat/ui/BookmarkSubmenu.js +165 -18
- package/dist/chat/ui/ChatActivity.js +649 -70
- package/dist/chat/ui/ChatReferenceChip.js +104 -9
- package/dist/chat/ui/CodeBlock.js +132 -58
- package/dist/chat/ui/Composer.js +866 -132
- package/dist/chat/ui/ComposerInput.js +309 -120
- package/dist/chat/ui/DiffPool.js +75 -14
- package/dist/chat/ui/EditDiff.js +160 -21
- package/dist/chat/ui/FadingWords.js +32 -3
- package/dist/chat/ui/GoalDock.js +235 -42
- package/dist/chat/ui/ImageView.js +617 -61
- package/dist/chat/ui/LimitState.js +446 -72
- package/dist/chat/ui/Markdown.js +991 -173
- package/dist/chat/ui/MermaidBlock.js +238 -68
- package/dist/chat/ui/MessageActions.js +251 -39
- package/dist/chat/ui/ModelMarks.js +55 -5
- package/dist/chat/ui/Pickers.js +664 -113
- package/dist/chat/ui/PromptComposer.js +281 -51
- package/dist/chat/ui/QuoteButton.js +151 -57
- package/dist/chat/ui/ResumeCompactionDock.d.ts +6 -2
- package/dist/chat/ui/ResumeCompactionDock.js +141 -6
- package/dist/chat/ui/RowTime.js +59 -5
- package/dist/chat/ui/RunSettings.js +1744 -154
- package/dist/chat/ui/Scrubber.js +517 -88
- package/dist/chat/ui/ShellCommand.js +183 -107
- package/dist/chat/ui/SubagentControls.js +212 -24
- package/dist/chat/ui/SubagentInfo.js +170 -13
- package/dist/chat/ui/SubagentStopButton.js +115 -24
- package/dist/chat/ui/SubagentTimeline.js +357 -91
- package/dist/chat/ui/Timeline.js +988 -476
- package/dist/chat/ui/TimelineMenu.js +552 -37
- package/dist/chat/ui/UnifiedDiff.js +234 -27
- package/dist/chat/ui/UploadThumb.js +37 -7
- package/dist/chat/ui/VisualDialogs.js +251 -20
- package/dist/chat/ui/VisualFrame.js +321 -95
- package/dist/chat/ui/Welcome.js +72 -7
- package/dist/chat/ui/chips.js +1 -1
- package/dist/chat/ui/code-lines.js +36 -36
- package/dist/chat/ui/code-streaming.js +1 -1
- package/dist/chat/ui/code-theme.js +7 -7
- package/dist/chat/ui/composer/ComposerControls.js +329 -21
- package/dist/chat/ui/composer/ComposerMenu.js +358 -30
- package/dist/chat/ui/composer/DraftParts.js +185 -11
- package/dist/chat/ui/composer/QueuedMessages.js +138 -13
- package/dist/chat/ui/composer/chips.js +29 -19
- package/dist/chat/ui/composer/editor.js +79 -63
- package/dist/chat/ui/composer/insert.js +26 -12
- package/dist/chat/ui/composer/key-handler.js +180 -127
- package/dist/chat/ui/composer/keys.js +90 -73
- package/dist/chat/ui/composer/menu-aria.js +18 -9
- package/dist/chat/ui/composer/placeholder.js +78 -31
- package/dist/chat/ui/composer/surface.js +13 -37
- package/dist/chat/ui/composer/use-chat-controls.js +230 -90
- package/dist/chat/ui/composer/use-compaction-offer.js +50 -18
- package/dist/chat/ui/composer/use-composer-draft.js +65 -34
- package/dist/chat/ui/composer/use-composer-menus.js +478 -193
- package/dist/chat/ui/composer/use-composer-submit.js +251 -109
- package/dist/chat/ui/composer/use-continuable-turn.js +33 -6
- package/dist/chat/ui/composer/use-draft-files.js +245 -93
- package/dist/chat/ui/composer/use-effort-stepper.d.ts +13 -0
- package/dist/chat/ui/composer/use-effort-stepper.js +88 -0
- package/dist/chat/ui/composer/use-notice.js +61 -16
- package/dist/chat/ui/composer/use-pending-requests.js +38 -17
- package/dist/chat/ui/composer/use-prompt-history.js +117 -45
- package/dist/chat/ui/composer/use-prompt-hold.js +119 -35
- package/dist/chat/ui/composer/use-take-back.js +94 -72
- package/dist/chat/ui/diff/ApprovalReview.js +101 -23
- package/dist/chat/ui/diff/DiffFallbackBoundary.js +21 -13
- package/dist/chat/ui/diff/DiffOmitted.js +56 -6
- package/dist/chat/ui/diff/DiffStack.js +92 -8
- package/dist/chat/ui/diff/DiffUnavailable.js +56 -6
- package/dist/chat/ui/diff/EditorEditDiff.js +263 -51
- package/dist/chat/ui/diff/EditorPatchDiff.js +39 -14
- package/dist/chat/ui/diff/LegacyDiffPool.js +27 -10
- package/dist/chat/ui/diff/LegacyEditDiff.js +97 -20
- package/dist/chat/ui/diff/LegacyUnifiedDiff.js +172 -42
- package/dist/chat/ui/diff/RawDiff.js +65 -5
- package/dist/chat/ui/diff/ReviewDiff.js +77 -5
- package/dist/chat/ui/diff/diff-props.js +1 -1
- package/dist/chat/ui/diff/diff-source-budget.js +46 -35
- package/dist/chat/ui/diff/editor-edit-model.js +18 -14
- package/dist/chat/ui/diff/review-plan.js +63 -40
- package/dist/chat/ui/diff/review-settle.js +24 -9
- package/dist/chat/ui/diff/syntax-runtime.js +236 -201
- package/dist/chat/ui/diff/use-review-stack.js +146 -25
- package/dist/chat/ui/diff-syntax.js +70 -58
- package/dist/chat/ui/diff-theme.js +31 -12
- package/dist/chat/ui/file-links.js +39 -10
- package/dist/chat/ui/find-reveal.js +29 -8
- package/dist/chat/ui/full-diff.js +17 -12
- package/dist/chat/ui/highlighter.js +143 -113
- package/dist/chat/ui/icons.js +16 -7
- package/dist/chat/ui/index.js +1 -1
- package/dist/chat/ui/intelligent-ui/UiBlockFrame.js +556 -82
- package/dist/chat/ui/intelligent-ui/UiFallbackPart.js +73 -5
- package/dist/chat/ui/intelligent-ui/UiReply.js +666 -262
- package/dist/chat/ui/intelligent-ui/block-local.js +59 -31
- package/dist/chat/ui/intelligent-ui/chart-data.js +77 -67
- package/dist/chat/ui/intelligent-ui/node-text.js +77 -91
- package/dist/chat/ui/intelligent-ui/registry.js +46 -46
- package/dist/chat/ui/intelligent-ui/render-context.js +1 -1
- package/dist/chat/ui/intelligent-ui/renderers/base-land.js +1 -1
- package/dist/chat/ui/intelligent-ui/renderers/binding.js +3 -3
- package/dist/chat/ui/intelligent-ui/renderers/chart.js +1223 -123
- package/dist/chat/ui/intelligent-ui/renderers/choices.js +312 -34
- package/dist/chat/ui/intelligent-ui/renderers/content.js +1241 -86
- package/dist/chat/ui/intelligent-ui/renderers/data.js +619 -54
- package/dist/chat/ui/intelligent-ui/renderers/inputs.js +868 -67
- package/dist/chat/ui/intelligent-ui/renderers/links.js +366 -62
- package/dist/chat/ui/intelligent-ui/renderers/map-slots.js +118 -60
- package/dist/chat/ui/intelligent-ui/renderers/map-style.js +85 -78
- package/dist/chat/ui/intelligent-ui/renderers/map-view.js +282 -217
- package/dist/chat/ui/intelligent-ui/renderers/map.js +621 -69
- package/dist/chat/ui/intelligent-ui/renderers/place-point.js +15 -8
- package/dist/chat/ui/intelligent-ui/renderers/structure.js +262 -20
- package/dist/chat/ui/intelligent-ui/renderers/text.js +674 -49
- package/dist/chat/ui/intelligent-ui/reply-parts.js +24 -15
- package/dist/chat/ui/intelligent-ui/table-data.js +97 -57
- package/dist/chat/ui/intelligent-ui/tones.js +31 -31
- package/dist/chat/ui/intelligent-ui/use-in-view.js +30 -12
- package/dist/chat/ui/intelligent-ui/use-later.js +28 -13
- package/dist/chat/ui/intelligent-ui/use-truncated.js +45 -21
- package/dist/chat/ui/intelligent-ui/use-ui-links.js +296 -109
- package/dist/chat/ui/intelligent-ui/use-ui-queries.js +256 -246
- package/dist/chat/ui/markdown-blocks.js +296 -262
- package/dist/chat/ui/mermaid.js +60 -72
- package/dist/chat/ui/quote-selection.js +32 -29
- package/dist/chat/ui/rehype-chips.js +35 -23
- package/dist/chat/ui/rehype-fade.js +28 -17
- package/dist/chat/ui/remark-html-as-text.js +22 -15
- package/dist/chat/ui/reply-context.js +1 -1
- package/dist/chat/ui/reveal.js +161 -72
- package/dist/chat/ui/rows/ForksRow.js +226 -24
- package/dist/chat/ui/rows/GeneratedImageRow.js +541 -87
- package/dist/chat/ui/rows/MessageRows.js +1706 -159
- package/dist/chat/ui/rows/RowContainer.js +57 -7
- package/dist/chat/ui/rows/Rows.js +463 -54
- package/dist/chat/ui/rows/SubagentRow.js +577 -60
- package/dist/chat/ui/rows/TaskRow.js +359 -40
- package/dist/chat/ui/rows/VisualRow.js +233 -11
- package/dist/chat/ui/rows/WorkRows.js +1946 -163
- package/dist/chat/ui/rows/WorkflowRow.js +293 -34
- package/dist/chat/ui/rows/row-rhythm.js +27 -17
- package/dist/chat/ui/theme-watch.js +26 -23
- package/dist/chat/ui/timestamp-format.js +4 -1
- package/dist/chat/ui/use-diff-source-tokens.js +70 -34
- package/dist/chat/ui/useToggleSet.js +51 -19
- package/dist/chat/ui/visual-theme.js +153 -128
- package/dist/chat/visual-bridge.js +123 -123
- package/dist/chat/visual-viewport.js +94 -83
- package/dist/chat/visuals.js +13 -5
- package/dist/host-hooks.d.ts +29 -0
- package/dist/host-hooks.js +78 -0
- package/dist/host.js +120 -48
- package/dist/index.js +1 -1
- package/dist/lazy.js +38 -32
- package/dist/locales/en/agent-chat.d.ts +35 -0
- package/dist/locales/en/agent-chat.js +747 -712
- package/dist/locales/en/agent-prompts.js +42 -42
- package/dist/locales/en/agent-providers.d.ts +1 -0
- package/dist/locales/en/agent-providers.js +166 -165
- package/dist/locales/en/agent-usage.d.ts +6 -0
- package/dist/locales/en/agent-usage.js +129 -123
- package/dist/locales/nl/agent-chat.d.ts +35 -0
- package/dist/locales/nl/agent-chat.js +747 -712
- package/dist/locales/nl/agent-prompts.js +42 -42
- package/dist/locales/nl/agent-providers.d.ts +1 -0
- package/dist/locales/nl/agent-providers.js +166 -165
- package/dist/locales/nl/agent-usage.d.ts +6 -0
- package/dist/locales/nl/agent-usage.js +129 -123
- package/dist/locales.js +14 -14
- package/dist/mounted-registry.js +31 -30
- package/dist/port-transport.js +122 -111
- package/dist/prompts/index.js +1 -1
- package/dist/prompts/logic/focus.js +15 -14
- package/dist/prompts/logic/keys.js +93 -59
- package/dist/prompts/logic/prompts.js +27 -14
- package/dist/prompts/logic/subjects.js +60 -46
- package/dist/prompts/logic/useFocusAfterAnswer.js +60 -20
- package/dist/prompts/logic/usePromptSession.js +88 -77
- package/dist/prompts/ui/ApprovalBody.js +246 -25
- package/dist/prompts/ui/PromptActions.js +215 -9
- package/dist/prompts/ui/PromptCard.js +215 -36
- package/dist/prompts/ui/PromptView.js +372 -34
- package/dist/prompts/ui/QuestionBody.js +269 -73
- package/dist/providers/AccountColors.js +36 -5
- package/dist/providers/AccountDetail.js +683 -50
- package/dist/providers/AccountVariables.js +139 -32
- package/dist/providers/AddAccountForm.js +125 -38
- package/dist/providers/CliDetail.js +343 -36
- package/dist/providers/InstallPage.js +644 -59
- package/dist/providers/ProviderList.d.ts +2 -1
- package/dist/providers/ProviderList.js +215 -23
- package/dist/providers/ProvidersPane.d.ts +4 -2
- package/dist/providers/ProvidersPane.js +244 -64
- package/dist/providers/account-actions.js +54 -30
- package/dist/providers/index.js +1 -1
- package/dist/providers/install-steps.js +12 -9
- package/dist/providers/pane-target.d.ts +3 -0
- package/dist/providers/pane-target.js +34 -13
- package/dist/providers/parts.js +62 -12
- package/dist/providers/provider-abilities.js +5 -5
- package/dist/providers/provider-groups.js +75 -40
- package/dist/providers/variables.js +73 -39
- package/dist/scope.js +6 -6
- package/dist/settings/sections.js +18 -18
- package/dist/state/chats.d.ts +1 -0
- package/dist/state/chats.js +408 -192
- package/dist/state/index.js +1 -1
- package/dist/state/provider-accounts.js +70 -47
- package/dist/state/providers.js +45 -16
- package/dist/state/usage.js +154 -77
- package/dist/storage.js +69 -68
- package/dist/testing/index.js +1 -1
- package/dist/testing/prompts.js +105 -67
- package/dist/transport.js +10 -10
- package/dist/ui/PlainTextarea.js +27 -3
- package/dist/usage/LimitsList.js +646 -40
- package/dist/usage/UsageBreakdown.js +879 -38
- package/dist/usage/UsageChart.js +311 -32
- package/dist/usage/UsageDialog.js +46 -4
- package/dist/usage/UsageLimits.js +467 -34
- package/dist/usage/UsageLimitsCard.js +95 -11
- package/dist/usage/UsagePage.js +817 -96
- package/dist/usage/UsagePane.js +164 -10
- package/dist/usage/UsageSummary.js +151 -6
- package/dist/usage/UsageTiles.js +164 -14
- package/dist/usage/format.js +32 -32
- package/dist/usage/index.d.ts +1 -1
- package/dist/usage/index.js +2 -1
- package/dist/usage/limit-groups.d.ts +2 -0
- package/dist/usage/limit-groups.js +77 -59
- package/dist/usage/limits.js +78 -43
- package/dist/usage/money.js +20 -4
- package/dist/usage/summary.js +85 -64
- package/package.json +8 -8
- package/src/agents/ModelOptionControl.tsx +3 -1
- package/src/agents/option-words.ts +27 -0
- package/src/chat/account-choice.ts +41 -1
- package/src/chat/composer-effort.ts +32 -0
- package/src/chat/forks.ts +4 -5
- package/src/chat/index.ts +3 -1
- package/src/chat/logic/effort.ts +32 -0
- package/src/chat/logic/picker-entries.ts +45 -10
- package/src/chat/logic/resume-compaction.ts +95 -17
- package/src/chat/logic/timeline.ts +11 -3
- package/src/chat/preferences.ts +35 -0
- package/src/chat/subagent-view.ts +2 -3
- package/src/chat/ui/AnsiOutput.tsx +1 -2
- package/src/chat/ui/BookmarkSubmenu.tsx +3 -3
- package/src/chat/ui/ChatActivity.tsx +14 -22
- package/src/chat/ui/ChatReferenceChip.tsx +2 -3
- package/src/chat/ui/Composer.tsx +15 -7
- package/src/chat/ui/EditDiff.tsx +2 -3
- package/src/chat/ui/LimitState.tsx +2 -2
- package/src/chat/ui/Markdown.tsx +10 -8
- package/src/chat/ui/MermaidBlock.tsx +2 -3
- package/src/chat/ui/Pickers.tsx +49 -29
- package/src/chat/ui/PromptComposer.tsx +7 -9
- package/src/chat/ui/ResumeCompactionDock.tsx +16 -4
- package/src/chat/ui/RunSettings.tsx +67 -28
- package/src/chat/ui/Scrubber.tsx +3 -3
- package/src/chat/ui/ShellCommand.tsx +2 -0
- package/src/chat/ui/SubagentInfo.tsx +2 -3
- package/src/chat/ui/SubagentTimeline.tsx +12 -16
- package/src/chat/ui/Timeline.tsx +6 -6
- package/src/chat/ui/UnifiedDiff.tsx +3 -4
- package/src/chat/ui/VisualFrame.tsx +5 -8
- package/src/chat/ui/code-theme.ts +4 -4
- package/src/chat/ui/composer/placeholder.ts +2 -2
- package/src/chat/ui/composer/use-compaction-offer.ts +36 -16
- package/src/chat/ui/composer/use-composer-menus.ts +4 -9
- package/src/chat/ui/composer/use-composer-submit.ts +2 -1
- package/src/chat/ui/composer/use-effort-stepper.ts +56 -0
- package/src/chat/ui/composer/use-notice.ts +2 -2
- package/src/chat/ui/diff/EditorEditDiff.tsx +9 -13
- package/src/chat/ui/diff/LegacyEditDiff.tsx +12 -17
- package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +13 -21
- package/src/chat/ui/diff/use-review-stack.ts +4 -4
- package/src/chat/ui/diff-theme.ts +3 -3
- package/src/chat/ui/file-links.ts +2 -2
- package/src/chat/ui/intelligent-ui/UiReply.tsx +2 -0
- package/src/chat/ui/intelligent-ui/renderers/chart.tsx +3 -3
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +5 -6
- package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +2 -1
- package/src/chat/ui/intelligent-ui/renderers/map.tsx +2 -1
- package/src/chat/ui/intelligent-ui/use-truncated.ts +16 -19
- package/src/chat/ui/intelligent-ui/use-ui-links.ts +3 -3
- package/src/chat/ui/rows/ForksRow.tsx +3 -5
- package/src/chat/ui/rows/GeneratedImageRow.tsx +2 -1
- package/src/chat/ui/rows/MessageRows.tsx +12 -21
- package/src/chat/ui/rows/SubagentRow.tsx +3 -3
- package/src/chat/ui/rows/TaskRow.tsx +1 -1
- package/src/chat/ui/rows/WorkRows.tsx +20 -7
- package/src/chat/ui/useToggleSet.ts +15 -18
- package/src/chat/ui/visual-theme.ts +2 -3
- package/src/host-hooks.ts +113 -0
- package/src/lazy.tsx +2 -0
- package/src/locales/en/agent-chat.ts +135 -108
- package/src/locales/en/agent-prompts.ts +7 -7
- package/src/locales/en/agent-providers.ts +35 -34
- package/src/locales/en/agent-usage.ts +26 -20
- package/src/locales/nl/agent-chat.ts +127 -100
- package/src/locales/nl/agent-prompts.ts +5 -5
- package/src/locales/nl/agent-providers.ts +33 -32
- package/src/locales/nl/agent-usage.ts +25 -20
- package/src/prompts/ui/ApprovalBody.tsx +3 -1
- package/src/providers/CliDetail.tsx +2 -1
- package/src/providers/InstallPage.tsx +2 -4
- package/src/providers/ProviderList.tsx +12 -2
- package/src/providers/ProvidersPane.tsx +45 -15
- package/src/providers/pane-target.ts +20 -4
- package/src/state/chats.ts +7 -2
- package/src/usage/LimitsList.tsx +12 -13
- package/src/usage/UsageBreakdown.tsx +17 -6
- package/src/usage/UsageLimits.tsx +2 -1
- package/src/usage/UsagePage.tsx +3 -3
- package/src/usage/index.ts +1 -1
- package/src/usage/limit-groups.ts +12 -0
- package/src/usage/limits.ts +2 -2
- package/src/usage/money.ts +1 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useEffect, useLayoutEffect,
|
|
1
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import { Bot, LoaderCircle } from 'lucide-react';
|
|
4
4
|
import { deriveTimelineRows } from '../logic/timeline';
|
|
@@ -34,8 +34,8 @@ export function SubagentTimeline({ chatId, toolUseId }: { chatId: string; toolUs
|
|
|
34
34
|
const scope = useChatScope();
|
|
35
35
|
const { commandLooks } = useChatHost();
|
|
36
36
|
const connected = useSyncExternalStore(
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
(changed) => scope.transport.subscribeStatus(changed),
|
|
38
|
+
() => scope.transport.status === 'open',
|
|
39
39
|
() => false
|
|
40
40
|
);
|
|
41
41
|
const { trail, show } = useSubagentTrail(chatId);
|
|
@@ -46,9 +46,9 @@ export function SubagentTimeline({ chatId, toolUseId }: { chatId: string; toolUs
|
|
|
46
46
|
const threadRef = useRef<HTMLDivElement>(null);
|
|
47
47
|
const [target, setTarget] = useState<TimelineTarget>(EMPTY_TARGET);
|
|
48
48
|
const followRef = useRef(true);
|
|
49
|
-
const stopFollowing =
|
|
49
|
+
const stopFollowing = () => {
|
|
50
50
|
followRef.current = false;
|
|
51
|
-
}
|
|
51
|
+
};
|
|
52
52
|
const groups = useToggleSet(stopFollowing);
|
|
53
53
|
const subagents = useToggleSet(stopFollowing);
|
|
54
54
|
// The row being read when an earlier page was asked for, so it stays where it was once that page is in.
|
|
@@ -72,17 +72,13 @@ export function SubagentTimeline({ chatId, toolUseId }: { chatId: string; toolUs
|
|
|
72
72
|
}
|
|
73
73
|
}, [state.unsupported, scope]);
|
|
74
74
|
|
|
75
|
-
const rows =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
commandLooks
|
|
83
|
-
}),
|
|
84
|
-
[state.items, groups.ids, subagents.ids, commandLooks]
|
|
85
|
-
);
|
|
75
|
+
const rows = deriveTimelineRows(state.items, {
|
|
76
|
+
expandedGroups: groups.ids,
|
|
77
|
+
expandedTurns: NO_TURNS,
|
|
78
|
+
expandedSubagents: subagents.ids,
|
|
79
|
+
activeTurnId: null,
|
|
80
|
+
commandLooks
|
|
81
|
+
});
|
|
86
82
|
|
|
87
83
|
useLayoutEffect(() => {
|
|
88
84
|
const element = scrollRef.current;
|
package/src/chat/ui/Timeline.tsx
CHANGED
|
@@ -79,6 +79,7 @@ import { FileLinkContext } from './file-links';
|
|
|
79
79
|
import { AgentIcon } from '../../agents/AgentIcon';
|
|
80
80
|
import { useModelName } from '../../agents/model-name';
|
|
81
81
|
import { ContextMenu, EmptyState, ErrorBoundary, Icon, SectionLabel } from '@adecore/ui';
|
|
82
|
+
import { useHostContextSources, useHostHidesFolder, useHostThreadCards, useHostTimelineFind, useHostWelcome } from '../../host-hooks';
|
|
82
83
|
|
|
83
84
|
const ESTIMATED_ROW_PX = 56;
|
|
84
85
|
// How long a jump waits for a thread that is still loading before it calls the item missing.
|
|
@@ -95,12 +96,11 @@ function showRowAtTop(virtualizer: Virtualizer<HTMLDivElement, Element>, followR
|
|
|
95
96
|
* and the folder it works in, so a first question can lean on all three.
|
|
96
97
|
*/
|
|
97
98
|
function EmptyThread({ chatId }: { chatId: string }) {
|
|
98
|
-
const host = useChatHost();
|
|
99
99
|
const { t } = useTranslation('agent-chat');
|
|
100
100
|
const info = useChatRow(chatId, (row) => row?.info ?? null);
|
|
101
101
|
const model = useModelName(info?.provider, info?.selection.model ?? '');
|
|
102
|
-
const sources =
|
|
103
|
-
const hidesFolder =
|
|
102
|
+
const sources = useHostContextSources(chatId);
|
|
103
|
+
const hidesFolder = useHostHidesFolder(chatId);
|
|
104
104
|
return (
|
|
105
105
|
<div className="flex grow items-center justify-center">
|
|
106
106
|
<div className="flex max-w-sm flex-col items-center gap-3 px-6 py-8 text-center">
|
|
@@ -262,7 +262,7 @@ export function Timeline({ chatId, composer, overlay }: { chatId: string; compos
|
|
|
262
262
|
}
|
|
263
263
|
);
|
|
264
264
|
}, [order, items, groups.ids, turns.ids, subagents.ids, activeTurnId, forkedTurns, host.commandLooks]);
|
|
265
|
-
const cards =
|
|
265
|
+
const cards = useHostThreadCards(scopeId, chatId);
|
|
266
266
|
const drawsVisuals = host.visuals !== null;
|
|
267
267
|
// Where the part of the thread this client holds begins, while there is a page before it.
|
|
268
268
|
const heldFrom = cursor === null ? null : (items?.[order?.[0] ?? '']?.createdAt ?? null);
|
|
@@ -270,7 +270,7 @@ export function Timeline({ chatId, composer, overlay }: { chatId: string; compos
|
|
|
270
270
|
() => withTimedRows(threadRows, timedRowsOf(cards, drawsVisuals ? (visuals ?? []) : null, heldFrom)),
|
|
271
271
|
[threadRows, cards, drawsVisuals, visuals, heldFrom]
|
|
272
272
|
);
|
|
273
|
-
const welcomes =
|
|
273
|
+
const welcomes = useHostWelcome(chatId);
|
|
274
274
|
|
|
275
275
|
const empty = rows.length === 0;
|
|
276
276
|
// A chat that took a turn before is one whose thread has not come in yet, not one to greet.
|
|
@@ -475,7 +475,7 @@ export function Timeline({ chatId, composer, overlay }: { chatId: string; compos
|
|
|
475
475
|
}),
|
|
476
476
|
[chatId, onMainAgent, rows, items, order, virtualizer, turns.add, groups.add, subagents.add, stopFollowing]
|
|
477
477
|
);
|
|
478
|
-
const chatFind =
|
|
478
|
+
const chatFind = useHostTimelineFind(findOptions);
|
|
479
479
|
const searching = chatFind.open;
|
|
480
480
|
// A find covers the whole thread, so every page before this one comes in while it is open.
|
|
481
481
|
useEffect(() => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
1
|
import { LazyBoundary } from '@adecore/ui';
|
|
3
2
|
import { useTranslation } from 'react-i18next';
|
|
4
3
|
import { lazyNamed } from '../../lazy';
|
|
@@ -20,11 +19,11 @@ export default function UnifiedDiff(props: UnifiedDiffProps) {
|
|
|
20
19
|
const loadEngine = host.code.editor;
|
|
21
20
|
const oldText = contents?.old ?? '';
|
|
22
21
|
const newText = contents?.new ?? '';
|
|
23
|
-
const sourceAllowed =
|
|
22
|
+
const sourceAllowed = diffSourceBudget(oldText, newText) && patchSourceBudget(change.diff);
|
|
24
23
|
const legacyMode = !allowEditor || loadEngine === undefined;
|
|
25
24
|
const hasHunks = /^@@/m.test(change.diff);
|
|
26
|
-
const legacyAllowed =
|
|
27
|
-
const rawAllowed =
|
|
25
|
+
const legacyAllowed = legacyMode && legacyDiffBudget(oldText, newText, change.diff);
|
|
26
|
+
const rawAllowed = hasHunks || legacyDiffBudget('', '', change.diff);
|
|
28
27
|
const omitted = <DiffOmitted path={change.path} />;
|
|
29
28
|
const fallback = legacyAllowed ? (
|
|
30
29
|
<DiffFallbackBoundary fallback={omitted} resetKeys={[change.path, change.diff, oldText, newText, diffStyle]}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import { visualThemeFragment, type ChatVisual, type VisualAppearance, type VisualTheme } from '@adecore/agent-contracts/visual';
|
|
@@ -44,13 +44,10 @@ export function VisualFrame({ chatId, visual, fill = false, className }: VisualF
|
|
|
44
44
|
const controllerRef = useRef<VisualViewportController | null>(null);
|
|
45
45
|
const [viewportReady, setViewportReady] = useState(false);
|
|
46
46
|
const [measure, width] = useMeasuredWidth();
|
|
47
|
-
const setBox =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
},
|
|
52
|
-
[measure]
|
|
53
|
-
);
|
|
47
|
+
const setBox = (node: HTMLDivElement | null) => {
|
|
48
|
+
boxRef.current = node;
|
|
49
|
+
measure(node);
|
|
50
|
+
};
|
|
54
51
|
const theme = useVisualTheme(boxRef);
|
|
55
52
|
const widthRef = useRef(width);
|
|
56
53
|
const [reported, setReported] = useState<number | null>(null);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { ThemeRegistration } from 'shiki';
|
|
2
|
-
import {
|
|
2
|
+
import { type ChatHost } from '../../host';
|
|
3
|
+
import { useHostCodeMode, useHostCodeThemes } from '../../host-hooks';
|
|
3
4
|
|
|
4
5
|
/* The Shiki theme code is drawn in under the app's current light or dark. */
|
|
5
6
|
export function useCodeTheme(): string {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const themes = code.useThemes();
|
|
7
|
+
const mode = useHostCodeMode();
|
|
8
|
+
const themes = useHostCodeThemes();
|
|
9
9
|
return mode === 'dark' ? themes.dark : themes.light;
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { useChatHost } from '../../../host';
|
|
4
3
|
import { useChatScope } from '../../../scope';
|
|
4
|
+
import { useHostComposerPlaceholder } from '../../../host-hooks';
|
|
5
5
|
|
|
6
6
|
/* The empty box names its sigils as key caps, so they read as keys to press rather than as punctuation. */
|
|
7
7
|
function hintedPlaceholder(lead: string, joiner: string, hints: ReadonlyArray<{ key: string; label: string }>): HTMLElement {
|
|
@@ -31,7 +31,7 @@ interface PlaceholderInput {
|
|
|
31
31
|
export function useHintedPlaceholder({ chatId, disabled, readOnly, mentionable, hasSkills }: PlaceholderInput): string | HTMLElement {
|
|
32
32
|
const { t } = useTranslation('agent-chat');
|
|
33
33
|
const scope = useChatScope();
|
|
34
|
-
const lead =
|
|
34
|
+
const lead = useHostComposerPlaceholder(scope.id, chatId);
|
|
35
35
|
return useMemo(() => {
|
|
36
36
|
if (disabled) {
|
|
37
37
|
return t('composer.placeholder.disconnected');
|
|
@@ -1,25 +1,45 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
1
2
|
import type { ChatInfo, ChatItem, ProviderCapabilities } from '@adecore/agent-contracts';
|
|
2
|
-
import { useNow } from '@adecore/ui';
|
|
3
3
|
import { useChatRow } from '../../../state/chats';
|
|
4
|
-
import { RESUME_COMPACTION_TOKENS, resumeCompactionOffer } from '../../logic/resume-compaction';
|
|
4
|
+
import { RESUME_COMPACTION_TOKENS, resumeCompactionDueAt, resumeCompactionOffer, watchDueAt, type DueClock } from '../../logic/resume-compaction';
|
|
5
5
|
import { useResumeCompactionDismissal } from '../../resume-compaction-dismissals';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const PAGE_CLOCK: DueClock = {
|
|
8
|
+
now: () => Date.now(),
|
|
9
|
+
setTimer: (run, ms) => setTimeout(run, ms),
|
|
10
|
+
clearTimer: (timer) => clearTimeout(timer as ReturnType<typeof setTimeout>),
|
|
11
|
+
onWake: (wake) => {
|
|
12
|
+
if (typeof window === 'undefined') {
|
|
13
|
+
return () => {};
|
|
14
|
+
}
|
|
15
|
+
window.addEventListener('focus', wake);
|
|
16
|
+
document.addEventListener('visibilitychange', wake);
|
|
17
|
+
return () => {
|
|
18
|
+
window.removeEventListener('focus', wake);
|
|
19
|
+
document.removeEventListener('visibilitychange', wake);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/* The offer to fold a long context before a chat whose cache went cold goes on, or null when there is none. */
|
|
8
25
|
export function useCompactionOffer(chatId: string, info: ChatInfo, compaction: ProviderCapabilities['compaction'] | undefined) {
|
|
9
26
|
const order = useChatRow(chatId, (row) => row?.order);
|
|
10
|
-
const
|
|
27
|
+
const structure = useChatRow(chatId, (row) => row?.structure);
|
|
11
28
|
const dismissedTurnId = useResumeCompactionDismissal(chatId);
|
|
12
|
-
|
|
29
|
+
const [now, setNow] = useState(Date.now);
|
|
30
|
+
// The cheap half of the offer, so a chat that can never make one walks no thread.
|
|
13
31
|
const couldOffer = compaction !== undefined && compaction !== 'none' && info.usage.contextTokens >= RESUME_COMPACTION_TOKENS;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
});
|
|
32
|
+
const items = couldOffer ? (order ?? []).map((id) => structure?.[id]).filter((item): item is ChatItem => item !== undefined) : [];
|
|
33
|
+
const input = { info, compaction, items, dismissedTurnId };
|
|
34
|
+
const dueAt = couldOffer ? resumeCompactionDueAt(input) : null;
|
|
35
|
+
|
|
36
|
+
// A watch for the moment the offer comes due, so a chat that can never make one keeps none.
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (dueAt === null) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
return watchDueAt(dueAt, setNow, PAGE_CLOCK);
|
|
42
|
+
}, [dueAt]);
|
|
43
|
+
|
|
44
|
+
return dueAt === null ? null : resumeCompactionOffer({ ...input, now });
|
|
25
45
|
}
|
|
@@ -23,6 +23,7 @@ import type { ComposerInputHandle } from '../ComposerInput';
|
|
|
23
23
|
import type { ComposerDraft } from './use-composer-draft';
|
|
24
24
|
import { inCode } from './keys';
|
|
25
25
|
import { clampMenuIndex, composerMenuAria } from './menu-aria';
|
|
26
|
+
import { useHostReferableChats } from '../../../host-hooks';
|
|
26
27
|
|
|
27
28
|
const SEARCH_DEBOUNCE_MS = 80;
|
|
28
29
|
// What fits above the composer without turning the picker into a file tree.
|
|
@@ -62,7 +63,7 @@ export function useComposerMenus({ chatId, info, capabilities, providerName, dra
|
|
|
62
63
|
const scope = useChatScope();
|
|
63
64
|
const host = useChatHost();
|
|
64
65
|
const { searchFiles } = host;
|
|
65
|
-
const chats =
|
|
66
|
+
const chats = useHostReferableChats();
|
|
66
67
|
const [menuIndex, setMenuIndex] = useState(0);
|
|
67
68
|
const [mention, setMention] = useState<MentionQuery | null>(null);
|
|
68
69
|
const [skillQuery, setSkillQuery] = useState<MentionQuery | null>(null);
|
|
@@ -156,10 +157,7 @@ export function useComposerMenus({ chatId, info, capabilities, providerName, dra
|
|
|
156
157
|
const mentionMenuOpen = !commandMenuOpen && !skillMenuOpen && mention !== null;
|
|
157
158
|
// Results belong to the query that asked for them; a closed picker shows none while the next answer is on its way.
|
|
158
159
|
const files = mention === null ? [] : searched.files;
|
|
159
|
-
const chatMatches =
|
|
160
|
-
() => (mention === null ? [] : chatSuggestions(chats, mention.query, [chatId, ...draft.chats], CHAT_RESULTS)),
|
|
161
|
-
[chatId, chats, draft.chats, mention]
|
|
162
|
-
);
|
|
160
|
+
const chatMatches = mention === null ? [] : chatSuggestions(chats, mention.query, [chatId, ...draft.chats], CHAT_RESULTS);
|
|
163
161
|
const mentionCount = chatMatches.length + files.length;
|
|
164
162
|
// One menu is open at a time, so they share an id.
|
|
165
163
|
const listId = useId();
|
|
@@ -167,10 +165,7 @@ export function useComposerMenus({ chatId, info, capabilities, providerName, dra
|
|
|
167
165
|
const menuCount = commandMenuOpen ? commands.length : skillMenuOpen ? skillMatches.length : mentionCount;
|
|
168
166
|
// The list can shrink under a stale index; every reader takes the one that still points at an option.
|
|
169
167
|
const activeIndex = clampMenuIndex(menuIndex, menuCount);
|
|
170
|
-
const inputAria =
|
|
171
|
-
() => composerMenuAria({ label: t('composer.inputLabel'), listId, open: menuOpen, activeIndex, count: menuCount }),
|
|
172
|
-
[t, listId, menuOpen, activeIndex, menuCount]
|
|
173
|
-
);
|
|
168
|
+
const inputAria = composerMenuAria({ label: t('composer.inputLabel'), listId, open: menuOpen, activeIndex, count: menuCount });
|
|
174
169
|
|
|
175
170
|
/* Which picker the caret opens: `@` for a file, `$` for a skill, or neither. In code a sigil is just text. */
|
|
176
171
|
const trackTriggers = (value: string, selection: TextRange, state: EditorState): void => {
|
|
@@ -19,6 +19,7 @@ import type { ComposerDraft } from './use-composer-draft';
|
|
|
19
19
|
import type { ComposerMenus } from './use-composer-menus';
|
|
20
20
|
import type { PromptHistory } from './use-prompt-history';
|
|
21
21
|
import type { ComposerPromptHold } from './use-prompt-hold';
|
|
22
|
+
import { useHostReferableChats } from '../../../host-hooks';
|
|
22
23
|
|
|
23
24
|
interface SubmitInput {
|
|
24
25
|
chatId: string;
|
|
@@ -58,7 +59,7 @@ export function useComposerSubmit({
|
|
|
58
59
|
const host = useChatHost();
|
|
59
60
|
const scope = useChatScope();
|
|
60
61
|
const { draft, setDraft } = box;
|
|
61
|
-
const referable =
|
|
62
|
+
const referable = useHostReferableChats();
|
|
62
63
|
|
|
63
64
|
/* Opens the host's new chat once the host took the message; a host that answers nothing took it. */
|
|
64
65
|
const afterSend = (sent: void | Promise<boolean>, andNew: boolean): void => {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import type { ChatInfo, ModelInfo } from '@adecore/agent-contracts';
|
|
4
|
+
import { useChatScope } from '../../../scope';
|
|
5
|
+
import { choiceWord } from '../../../agents/option-words';
|
|
6
|
+
import { registerEffortStepper } from '../../composer-effort';
|
|
7
|
+
import { EFFORT_OPTION, stepEffort, type EffortStep } from '../../logic/effort';
|
|
8
|
+
import type { ChatControls } from './use-chat-controls';
|
|
9
|
+
import type { ComposerNotice } from './use-notice';
|
|
10
|
+
|
|
11
|
+
interface EffortStepperInput {
|
|
12
|
+
chatId: string;
|
|
13
|
+
info: ChatInfo;
|
|
14
|
+
model: ModelInfo | undefined;
|
|
15
|
+
writable: boolean;
|
|
16
|
+
controls: ChatControls;
|
|
17
|
+
setNotice: ComposerNotice['setNotice'];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Lets a command of the host step this chat's reasoning effort, as picking it in the pill's menu does, and says where it landed. */
|
|
21
|
+
export function useEffortStepper({ chatId, info, model, writable, controls, setNotice }: EffortStepperInput): void {
|
|
22
|
+
const { t } = useTranslation('agent-chat');
|
|
23
|
+
const scope = useChatScope();
|
|
24
|
+
|
|
25
|
+
const step = (direction: EffortStep): void => {
|
|
26
|
+
// The pill is disabled then too, and a second configuration would be dropped anyway.
|
|
27
|
+
if (!writable || controls.configurationPending) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const name = model?.name ?? info.selection.model;
|
|
31
|
+
const result = stepEffort(model, info.selection, direction);
|
|
32
|
+
if (result.kind === 'none') {
|
|
33
|
+
setNotice(t('composer.notice.noEffort', { model: name }), 'info');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (result.kind === 'edge') {
|
|
37
|
+
setNotice(
|
|
38
|
+
t(direction === 'up' ? 'composer.notice.effortHighest' : 'composer.notice.effortLowest', {
|
|
39
|
+
effort: choiceWord(EFFORT_OPTION, result.choice),
|
|
40
|
+
model: name
|
|
41
|
+
}),
|
|
42
|
+
'info'
|
|
43
|
+
);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
controls.configure({ selection: result.selection });
|
|
47
|
+
setNotice(t('composer.notice.effort', { effort: choiceWord(EFFORT_OPTION, result.choice) }), 'info');
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// A command means the chat as it stands when it is given, so the registration reads the latest step.
|
|
51
|
+
const stepRef = useRef(step);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
stepRef.current = step;
|
|
54
|
+
});
|
|
55
|
+
useEffect(() => registerEffortStepper(scope.keyOf(chatId), (direction) => stepRef.current(direction)), [scope, chatId]);
|
|
56
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
const NOTICE_MS = 4000;
|
|
4
4
|
|
|
@@ -24,7 +24,7 @@ export function useNotice(): ComposerNotice {
|
|
|
24
24
|
return () => clearTimeout(timer);
|
|
25
25
|
}, [shown]);
|
|
26
26
|
|
|
27
|
-
const setNotice =
|
|
27
|
+
const setNotice = (notice: string | null, tone: NoticeTone = 'error'): void => setShown(notice ? { text: notice, tone } : null);
|
|
28
28
|
|
|
29
29
|
return {
|
|
30
30
|
notice: shown?.text ?? null,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { useReviewSettled } from './review-settle';
|
|
2
|
-
import { useEffect,
|
|
2
|
+
import { useEffect, useState, type ReactNode } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { getFiletypeFromFileName } from '@pierre/diffs';
|
|
5
5
|
import type { EditorEngine } from '@adecore/editor';
|
|
6
6
|
import { DiffView } from '@adecore/editor-react';
|
|
7
7
|
import { diffDocument, patchOf, type DiffDocument } from '@adecore/merge';
|
|
8
|
-
import { useChatHost } from '../../../host';
|
|
9
8
|
import type { FileChange } from '../../logic/tools';
|
|
10
9
|
import { useDiffSourceTokens } from '../use-diff-source-tokens';
|
|
11
10
|
import { diffSourceBudget } from './diff-source-budget';
|
|
12
11
|
import { DiffOmitted } from './DiffOmitted';
|
|
13
12
|
import { canRenderEditorDiff, EDITOR_DIFF_LIMITS, EDITOR_DIFF_WORK } from './editor-edit-model';
|
|
13
|
+
import { useHostCodeMode, useHostCodeThemes } from '../../../host-hooks';
|
|
14
14
|
|
|
15
15
|
type EngineLoader = () => Promise<EditorEngine>;
|
|
16
16
|
|
|
@@ -34,11 +34,10 @@ function ReadyDiff({
|
|
|
34
34
|
layout: 'unified' | 'split';
|
|
35
35
|
maxHeight: number;
|
|
36
36
|
}) {
|
|
37
|
-
const host = useChatHost();
|
|
38
37
|
useReviewSettled();
|
|
39
38
|
const { t } = useTranslation('agent-chat');
|
|
40
|
-
const mode =
|
|
41
|
-
const theme =
|
|
39
|
+
const mode = useHostCodeMode();
|
|
40
|
+
const theme = useHostCodeThemes()[mode];
|
|
42
41
|
const language = getFiletypeFromFileName(path);
|
|
43
42
|
const tokens = useDiffSourceTokens(document, language, theme);
|
|
44
43
|
return (
|
|
@@ -78,7 +77,7 @@ export function EditorDocumentDiff({
|
|
|
78
77
|
maxHeight?: number;
|
|
79
78
|
}) {
|
|
80
79
|
const { t } = useTranslation('agent-chat');
|
|
81
|
-
const withinLimits =
|
|
80
|
+
const withinLimits = canRenderEditorDiff(document);
|
|
82
81
|
const [loaded, setLoaded] = useState<{ load: EngineLoader; engine: EditorEngine | null }>();
|
|
83
82
|
useEffect(() => {
|
|
84
83
|
if (!withinLimits || engines.has(loadEngine)) {
|
|
@@ -132,13 +131,10 @@ export default function EditorEditDiff({
|
|
|
132
131
|
fallback: ReactNode;
|
|
133
132
|
maxHeight?: number;
|
|
134
133
|
}) {
|
|
135
|
-
const document =
|
|
136
|
-
()
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
: undefined,
|
|
140
|
-
[change.before, change.after, sourceChecked]
|
|
141
|
-
);
|
|
134
|
+
const document =
|
|
135
|
+
sourceChecked || diffSourceBudget(change.before, change.after)
|
|
136
|
+
? diffDocument(patchOf(change.before, change.after, 3, { maxWork: EDITOR_DIFF_WORK }), { old: change.before, new: change.after })
|
|
137
|
+
: undefined;
|
|
142
138
|
if (document === undefined) {
|
|
143
139
|
return <DiffOmitted path={change.path} />;
|
|
144
140
|
}
|
|
@@ -1,29 +1,24 @@
|
|
|
1
1
|
import { LegacyDiffPool } from './LegacyDiffPool';
|
|
2
2
|
import { useReviewSettled } from './review-settle';
|
|
3
|
-
import { useMemo } from 'react';
|
|
4
3
|
import { MultiFileDiff } from '@pierre/diffs/react';
|
|
5
|
-
import { useChatHost } from '../../../host';
|
|
6
4
|
import { useDiffTheme } from '../diff-theme';
|
|
7
5
|
import type { FileChange } from '../../logic/tools';
|
|
6
|
+
import { useHostCodeMode } from '../../../host-hooks';
|
|
8
7
|
|
|
9
8
|
export default function LegacyEditDiff({ change, maxHeight }: { change: FileChange; maxHeight?: number }) {
|
|
10
|
-
const host = useChatHost();
|
|
11
9
|
useReviewSettled();
|
|
12
|
-
const resolved =
|
|
10
|
+
const resolved = useHostCodeMode();
|
|
13
11
|
const theme = useDiffTheme();
|
|
14
|
-
const oldFile =
|
|
15
|
-
const newFile =
|
|
16
|
-
const options =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}),
|
|
25
|
-
[theme, resolved]
|
|
26
|
-
);
|
|
12
|
+
const oldFile = { name: change.path, contents: change.before };
|
|
13
|
+
const newFile = { name: change.path, contents: change.after };
|
|
14
|
+
const options = {
|
|
15
|
+
diffStyle: 'unified' as const,
|
|
16
|
+
theme,
|
|
17
|
+
themeType: resolved,
|
|
18
|
+
disableFileHeader: true,
|
|
19
|
+
overflow: 'wrap' as const,
|
|
20
|
+
hunkSeparators: 'simple' as const
|
|
21
|
+
};
|
|
27
22
|
return (
|
|
28
23
|
<div className="chat-diff select-text" style={maxHeight === undefined ? undefined : { maxHeight, overflow: 'auto' }}>
|
|
29
24
|
<LegacyDiffPool>
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { LegacyDiffPool } from './LegacyDiffPool';
|
|
2
2
|
import { useReviewSettled } from './review-settle';
|
|
3
|
-
import { useMemo } from 'react';
|
|
4
3
|
import clsx from 'clsx';
|
|
5
4
|
import { FileDiff, PatchDiff } from '@pierre/diffs/react';
|
|
6
5
|
import type { ChatFileChange } from '@adecore/agent-contracts';
|
|
7
|
-
import { useChatHost } from '../../../host';
|
|
8
6
|
import { useDiffTheme } from '../diff-theme';
|
|
9
7
|
import { fullFileDiff } from '../full-diff';
|
|
10
8
|
import type { UnifiedDiffProps } from './diff-props';
|
|
9
|
+
import { useHostCodeMode } from '../../../host-hooks';
|
|
11
10
|
|
|
12
11
|
/*
|
|
13
12
|
* A patch the CLI reported itself. The renderer needs a file header, which a CLI that only sends hunks
|
|
@@ -45,30 +44,23 @@ function lineClass(line: string): string {
|
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
export default function LegacyUnifiedDiff({ change, overflow = 'wrap', diffStyle = 'unified', fill = false, contents, maxHeight }: UnifiedDiffProps) {
|
|
48
|
-
const host = useChatHost();
|
|
49
47
|
useReviewSettled();
|
|
50
|
-
const resolved =
|
|
48
|
+
const resolved = useHostCodeMode();
|
|
51
49
|
const theme = useDiffTheme();
|
|
52
|
-
const patch =
|
|
50
|
+
const patch = asPatch(change);
|
|
53
51
|
const oldText = contents?.old;
|
|
54
52
|
const newText = contents?.new;
|
|
55
|
-
const full =
|
|
56
|
-
() => (patch === null || oldText === undefined || newText === undefined ? null : fullFileDiff(patch, change.path, { old: oldText, new: newText })),
|
|
57
|
-
[patch, change.path, oldText, newText]
|
|
58
|
-
);
|
|
53
|
+
const full = patch === null || oldText === undefined || newText === undefined ? null : fullFileDiff(patch, change.path, { old: oldText, new: newText });
|
|
59
54
|
const unfolds = full !== null;
|
|
60
|
-
const options =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}),
|
|
70
|
-
[diffStyle, overflow, theme, resolved, fill, unfolds]
|
|
71
|
-
);
|
|
55
|
+
const options = {
|
|
56
|
+
theme,
|
|
57
|
+
themeType: resolved,
|
|
58
|
+
disableFileHeader: true,
|
|
59
|
+
diffStyle,
|
|
60
|
+
overflow,
|
|
61
|
+
hunkSeparators: unfolds ? ('line-info' as const) : ('simple' as const),
|
|
62
|
+
unsafeCSS: fill ? FILL_CSS : undefined
|
|
63
|
+
};
|
|
72
64
|
if (patch === null) {
|
|
73
65
|
return (
|
|
74
66
|
<pre className="max-h-64 overflow-auto px-3 py-2 font-mono text-code select-text" style={fill ? undefined : { maxHeight }}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { planReview, type ReviewEntry, type ReviewSlot } from './review-plan';
|
|
3
3
|
|
|
4
4
|
export interface ReviewStack {
|
|
@@ -10,7 +10,7 @@ export interface ReviewStack {
|
|
|
10
10
|
|
|
11
11
|
export function useReviewStack(entries: readonly ReviewEntry[]): ReviewStack {
|
|
12
12
|
const [promoted, setPromoted] = useState<string | null>(null);
|
|
13
|
-
const slots =
|
|
13
|
+
const slots = planReview(entries, promoted);
|
|
14
14
|
const selected = [...slots].filter(([, slot]) => slot === 'editor').map(([key]) => key);
|
|
15
15
|
const [admitted, setAdmitted] = useState<string[]>(() => selected.slice(0, 1));
|
|
16
16
|
const retained = admitted.filter((key) => selected.includes(key));
|
|
@@ -22,9 +22,9 @@ export function useReviewStack(entries: readonly ReviewEntry[]): ReviewStack {
|
|
|
22
22
|
if ([...settled].some((key) => !selected.includes(key))) {
|
|
23
23
|
setSettled(new Set([...settled].filter((key) => selected.includes(key))));
|
|
24
24
|
}
|
|
25
|
-
const settle =
|
|
25
|
+
const settle = (key: string) => {
|
|
26
26
|
setSettled((previous) => (previous.has(key) ? previous : new Set([...previous, key])));
|
|
27
|
-
}
|
|
27
|
+
};
|
|
28
28
|
const allSettled = live.every((key) => settled.has(key));
|
|
29
29
|
const next = selected.find((key) => !live.includes(key));
|
|
30
30
|
useEffect(() => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
1
|
import { registerCustomTheme, type ThemesType } from '@pierre/diffs';
|
|
3
2
|
import { useChatHost, type ChatHost } from '../../host';
|
|
3
|
+
import { useHostCodeThemes } from '../../host-hooks';
|
|
4
4
|
|
|
5
5
|
// The library's registry is global and refuses a name twice, so what is registered is kept by name.
|
|
6
6
|
const registered = new Set<string>();
|
|
@@ -23,6 +23,6 @@ function registerThemes(custom: ChatHost['code']['custom']): void {
|
|
|
23
23
|
export function useDiffTheme(): ThemesType {
|
|
24
24
|
const { code } = useChatHost();
|
|
25
25
|
registerThemes(code.custom);
|
|
26
|
-
const { light, dark } =
|
|
27
|
-
return
|
|
26
|
+
const { light, dark } = useHostCodeThemes();
|
|
27
|
+
return { light, dark };
|
|
28
28
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
2
|
import { useChatHost, type FileRef } from '../../host';
|
|
3
3
|
import { ChatScopeContext } from '../../scope';
|
|
4
4
|
|
|
@@ -22,7 +22,7 @@ export function useFileLinkTarget(text: string): FileRef | null {
|
|
|
22
22
|
const cwd = useFileLinkCwd();
|
|
23
23
|
const scopeId = useFileLinkScopeId();
|
|
24
24
|
const { fileLinks } = useChatHost();
|
|
25
|
-
return
|
|
25
|
+
return fileLinks?.target(text, cwd, scopeId) ?? null;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/* Follows a reference the way the app opens a file or a folder. */
|
|
@@ -399,6 +399,8 @@ function UiBlockBody({
|
|
|
399
399
|
/* Set for a finished reply the machine keeps no readings for, which nothing will ever look up. */
|
|
400
400
|
unrecorded: boolean;
|
|
401
401
|
}): ReactNode {
|
|
402
|
+
// The block's state changes in place and only its revision says so; compiled, the evaluation of the first revision would stay.
|
|
403
|
+
'use no memo';
|
|
402
404
|
const host = useChatHost();
|
|
403
405
|
const { t } = useTranslation('agent-chat');
|
|
404
406
|
const key = JSON.stringify([context.scopeId, context.chatId, context.itemId, block.id]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useState } from 'react';
|
|
2
2
|
import type { TFunction } from 'i18next';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
@@ -439,7 +439,7 @@ function DrawnChart({
|
|
|
439
439
|
const [measure, width] = useMeasuredWidth();
|
|
440
440
|
const character = useChartCharacter();
|
|
441
441
|
const [measureRows, rowsCut] = useTruncated<HTMLDivElement>(true);
|
|
442
|
-
const values =
|
|
442
|
+
const values = uiChartValues(data);
|
|
443
443
|
const { kind } = chart;
|
|
444
444
|
return (
|
|
445
445
|
<figure className="chat-ui-flat flex flex-col gap-2.5 rounded-xl bg-ui-tile p-3.5">
|
|
@@ -473,7 +473,7 @@ function DrawnChart({
|
|
|
473
473
|
*/
|
|
474
474
|
export function ChartRenderer({ node, context }: UiRendererProps<UiProps<'Chart'>>) {
|
|
475
475
|
const { kind, data, unit } = node.props;
|
|
476
|
-
const chart =
|
|
476
|
+
const chart = node.complete ? uiChartData(data, kind) : null;
|
|
477
477
|
if (!node.complete) {
|
|
478
478
|
return <div aria-hidden className="rounded-xl bg-ui-tile" style={{ height: chartHeight(kind, data.length) }} />;
|
|
479
479
|
}
|