@adecore/agents-react 0.31.12 → 0.33.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/README.md +1 -1
- 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.d.ts +10 -0
- package/dist/chat/logic/workflow.js +130 -32
- 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 +285 -79
- 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.d.ts +8 -20
- package/dist/chat/ui/mermaid.js +47 -84
- 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.d.ts +3 -0
- package/dist/chat/ui/rows/WorkRows.js +1945 -164
- package/dist/chat/ui/rows/WorkflowRow.js +756 -37
- 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 +42 -0
- package/dist/locales/en/agent-chat.js +755 -713
- 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 +42 -0
- package/dist/locales/nl/agent-chat.js +755 -713
- 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 -27
- 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.js +404 -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 +9 -9
- 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/logic/workflow.ts +86 -4
- 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 +57 -49
- 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/mermaid.ts +52 -96
- 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 +11 -6
- package/src/chat/ui/rows/WorkflowRow.tsx +144 -54
- 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 +142 -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 +134 -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/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 +2 -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
|
@@ -2,104 +2,102 @@ import i18next from 'i18next';
|
|
|
2
2
|
import { activeSubagents } from '@adecore/agent-contracts';
|
|
3
3
|
import { formatMoment, formatElapsedShort, formatTokens } from '@adecore/ui/format';
|
|
4
4
|
export function subagentTitle(item) {
|
|
5
|
-
|
|
5
|
+
return item.description || item.summary || item.subagentType || i18next.t('agent-chat:rows.subagent.label');
|
|
6
6
|
}
|
|
7
7
|
/* What the bar over a sub-agent's conversation says of it beside its state and its time; the model is named by the caller, which has the catalog. */
|
|
8
8
|
export function subagentFacts(item, modelName) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
? i18next.t('agent-chat:subagents.info.tokens', { tokens: formatTokens(item.usage.totalTokens) })
|
|
15
|
-
: null,
|
|
16
|
-
item.usage !== null && item.usage.toolUses > 0 ? i18next.t('agent-chat:group.toolCalls', { count: item.usage.toolUses }) : null
|
|
17
|
-
].filter((fact) => fact !== null && fact !== '');
|
|
9
|
+
return [modelName, item.subagentType, item.background ? i18next.t('agent-chat:rows.subagent.background') : null, item.usage !== null && item.usage.totalTokens > 0 ? i18next.t('agent-chat:subagents.info.tokens', {
|
|
10
|
+
tokens: formatTokens(item.usage.totalTokens)
|
|
11
|
+
}) : null, item.usage !== null && item.usage.toolUses > 0 ? i18next.t('agent-chat:group.toolCalls', {
|
|
12
|
+
count: item.usage.toolUses
|
|
13
|
+
}) : null].filter(fact => fact !== null && fact !== '');
|
|
18
14
|
}
|
|
19
15
|
/* The task a row stands for, whose id the host wrote into the row's own. */
|
|
20
16
|
export function taskIdOf(item) {
|
|
21
|
-
|
|
17
|
+
return item.origin === 'ruimte' && item.id.startsWith('task-') ? item.id.slice(5) : null;
|
|
22
18
|
}
|
|
23
19
|
/* A cancelled task is a failed row on the wire and a paused one a running row, and only the task itself still says which it is. */
|
|
24
20
|
export function statusWordOf(item, task) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
if (item.status === 'failed' && task?.status === 'cancelled') {
|
|
22
|
+
return 'cancelled';
|
|
23
|
+
}
|
|
24
|
+
if (item.status === 'running' && task?.status === 'open' && task.paused !== undefined) {
|
|
25
|
+
return 'paused';
|
|
26
|
+
}
|
|
27
|
+
return item.status;
|
|
32
28
|
}
|
|
33
29
|
export function taskRowStateOf(item, task, child) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
const word = statusWordOf(item, task);
|
|
31
|
+
if (word === 'running' && (child?.status === 'needs-you' || (child?.requests?.length ?? 0) > 0)) {
|
|
32
|
+
return 'waiting';
|
|
33
|
+
}
|
|
34
|
+
return word;
|
|
39
35
|
}
|
|
40
36
|
/* How far delegated work is: what settled as done, what still runs or waits, and how many of those wait on a person. */
|
|
41
37
|
export function progressOf(states) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
38
|
+
return {
|
|
39
|
+
done: states.filter(state => state === 'done').length,
|
|
40
|
+
total: states.length,
|
|
41
|
+
waiting: states.filter(state => state === 'waiting').length,
|
|
42
|
+
active: states.filter(state => state === 'running' || state === 'paused' || state === 'waiting').length
|
|
43
|
+
};
|
|
48
44
|
}
|
|
49
45
|
/* What the flyout over the composer lists (`activeSubagents`); `order` puts the rows from before the page first. */
|
|
50
46
|
export function flyoutSubagents(order, structure) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
return activeSubagents(order.flatMap(id => {
|
|
48
|
+
const item = structure[id];
|
|
49
|
+
return item === undefined ? [] : [item];
|
|
50
|
+
}));
|
|
55
51
|
}
|
|
56
52
|
/* The one state the badge shows for all of them: work in progress first, then work held up, then whatever went wrong. */
|
|
57
53
|
export function summaryWordOf(words) {
|
|
58
|
-
|
|
54
|
+
return ['running', 'paused', 'failed', 'cancelled'].find(word => words.includes(word)) ?? 'done';
|
|
59
55
|
}
|
|
60
56
|
/* The number on the badge: the ones still at work, a paused one included, and all of them once none is. */
|
|
61
57
|
export function badgeCountOf(words) {
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
const active = words.filter(word => word === 'running' || word === 'paused').length;
|
|
59
|
+
return active > 0 ? active : words.length;
|
|
64
60
|
}
|
|
65
61
|
/* The time on the right of an entry: how long it has run so far, or how long it took once it settled. */
|
|
66
62
|
export function entryTimeOf(item, task, now) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
63
|
+
// A task's own record says when it was given and settled; the row copies those, but may lag behind it.
|
|
64
|
+
const startedAt = task?.createdAt ?? item.startedAt;
|
|
65
|
+
const finishedAt = task === null ? item.finishedAt : task.settledAt ?? item.finishedAt;
|
|
66
|
+
const word = statusWordOf(item, task);
|
|
67
|
+
if (word === 'paused') {
|
|
68
|
+
const until = task?.paused?.until;
|
|
69
|
+
return until === undefined ? i18next.t('agent-chat:common.status.paused') : i18next.t('agent-chat:activity.pausedUntil', {
|
|
70
|
+
time: formatMoment(until, now)
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (item.status === 'running') {
|
|
74
|
+
return startedAt > 0 ? formatElapsedShort(now - startedAt) : '';
|
|
75
|
+
}
|
|
76
|
+
if (startedAt <= 0 || finishedAt === null || finishedAt < startedAt) {
|
|
77
|
+
return i18next.t(`agent-chat:common.status.${word}`);
|
|
78
|
+
}
|
|
79
|
+
return i18next.t(`agent-chat:activity.took.${word}`, {
|
|
80
|
+
duration: formatElapsedShort(finishedAt - startedAt)
|
|
81
|
+
});
|
|
84
82
|
}
|
|
85
83
|
export function stopOf(item, turnRunning) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
84
|
+
if (item.status !== 'running') {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
if (item.origin === 'ruimte') {
|
|
88
|
+
return item.childId === undefined ? null : 'task';
|
|
89
|
+
}
|
|
90
|
+
if (item.native?.agentId) {
|
|
91
|
+
return 'native';
|
|
92
|
+
}
|
|
93
|
+
return turnRunning ? null : 'mark';
|
|
96
94
|
}
|
|
97
95
|
export function stopLabel(stop) {
|
|
98
|
-
|
|
96
|
+
return i18next.t(`agent-chat:subagents.stop.${stop}`);
|
|
99
97
|
}
|
|
100
98
|
export function composerStopOf(shiftKey) {
|
|
101
|
-
|
|
99
|
+
return shiftKey ? 'turn-and-subagents' : 'turn';
|
|
102
100
|
}
|
|
103
101
|
export function composerStopLabel() {
|
|
104
|
-
|
|
105
|
-
}
|
|
102
|
+
return i18next.t('agent-chat:composer.stop');
|
|
103
|
+
}
|
|
@@ -4,11 +4,16 @@ import { create } from 'zustand';
|
|
|
4
4
|
* version: the first refusal hides the button on that host's rows that carry no pointer of their own.
|
|
5
5
|
*/
|
|
6
6
|
export const useSubagentSupport = create((set, get) => ({
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
set({ unsupported: { ...get().unsupported, [scopeId]: true } });
|
|
7
|
+
unsupported: {},
|
|
8
|
+
markUnsupported(scopeId) {
|
|
9
|
+
if (get().unsupported[scopeId]) {
|
|
10
|
+
return;
|
|
13
11
|
}
|
|
14
|
-
|
|
12
|
+
set({
|
|
13
|
+
unsupported: {
|
|
14
|
+
...get().unsupported,
|
|
15
|
+
[scopeId]: true
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
1
2
|
import i18next from 'i18next';
|
|
2
|
-
import { useMemo } from 'react';
|
|
3
3
|
import { create } from 'zustand';
|
|
4
4
|
import { useChatScope } from '../scope.js';
|
|
5
5
|
import { useChatRow } from '../state/chats.js';
|
|
@@ -7,90 +7,178 @@ import { useSubagentSupport } from './subagent-support.js';
|
|
|
7
7
|
export const MAIN_AGENT = [];
|
|
8
8
|
const NO_ITEMS = [];
|
|
9
9
|
export function crumbOf(item) {
|
|
10
|
-
|
|
10
|
+
return {
|
|
11
|
+
toolUseId: item.toolUseId,
|
|
12
|
+
description: item.description
|
|
13
|
+
};
|
|
11
14
|
}
|
|
12
15
|
function stepLabel(step) {
|
|
13
|
-
|
|
16
|
+
return step.description || i18next.t('agent-chat:rows.subagent.label');
|
|
14
17
|
}
|
|
15
18
|
/* A row in the main agent's thread or an entry of the flyout opens its conversation straight away. */
|
|
16
19
|
export function openFromMain(step) {
|
|
17
|
-
|
|
20
|
+
return [step];
|
|
18
21
|
}
|
|
19
22
|
export function openBelow(trail, step) {
|
|
20
|
-
|
|
23
|
+
return [...trail, step];
|
|
21
24
|
}
|
|
22
25
|
export function trailTo(trail, depth) {
|
|
23
|
-
|
|
26
|
+
return depth <= 0 ? MAIN_AGENT : trail.slice(0, depth);
|
|
24
27
|
}
|
|
25
28
|
export function stepBack(trail) {
|
|
26
|
-
|
|
29
|
+
return trailTo(trail, trail.length - 1);
|
|
27
30
|
}
|
|
28
31
|
/*
|
|
29
32
|
* A sub-agent's conversation is read back, so there is nobody to write to. The composer stays, since
|
|
30
33
|
* the chat's own approvals and questions are answered there.
|
|
31
34
|
*/
|
|
32
35
|
export function composerWrites(trail) {
|
|
33
|
-
|
|
36
|
+
return trail.length === 0;
|
|
34
37
|
}
|
|
35
38
|
/* The crumbs after the chat's own title, which the bar draws as the first crumb and the way back. */
|
|
36
39
|
export function breadcrumbOf(trail) {
|
|
37
|
-
|
|
40
|
+
return trail.map((step, index) => ({
|
|
41
|
+
label: stepLabel(step),
|
|
42
|
+
depth: index + 1,
|
|
43
|
+
current: index === trail.length - 1
|
|
44
|
+
}));
|
|
38
45
|
}
|
|
39
46
|
/* A row without a pointer of its own can only be opened by a machine that answers `chat.subagent` for it. */
|
|
40
47
|
export function canOpenSubagent(item, machineRefused) {
|
|
41
|
-
|
|
48
|
+
return item.native !== undefined || !machineRefused;
|
|
42
49
|
}
|
|
43
50
|
/* The row of the call that opened a conversation, a nested one included, since its row is in the thread too. */
|
|
44
51
|
export function subagentOf(structure, toolUseId) {
|
|
45
|
-
|
|
52
|
+
return Object.values(structure).find(item => item.kind === 'subagent' && item.toolUseId === toolUseId) ?? null;
|
|
46
53
|
}
|
|
47
54
|
/* The subagents a chat can open, in the order the thread has them. */
|
|
48
55
|
export function openableSubagents(order, structure, machineRefused) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
return order.flatMap(id => {
|
|
57
|
+
const item = structure[id];
|
|
58
|
+
return item?.kind === 'subagent' && canOpenSubagent(item, machineRefused) ? [item] : [];
|
|
59
|
+
});
|
|
53
60
|
}
|
|
54
61
|
/*
|
|
55
62
|
* What a chat shows in its place, for this page's life only: a look into a subagent is a moment
|
|
56
63
|
* rather than a place, so it is never written to the project or to the host.
|
|
57
64
|
*/
|
|
58
65
|
export const useSubagentView = create((set, get) => ({
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
66
|
+
trails: {},
|
|
67
|
+
show(key, trail) {
|
|
68
|
+
const trails = {
|
|
69
|
+
...get().trails
|
|
70
|
+
};
|
|
71
|
+
if (trail.length === 0) {
|
|
72
|
+
delete trails[key];
|
|
73
|
+
} else {
|
|
74
|
+
trails[key] = trail;
|
|
75
|
+
}
|
|
76
|
+
set({
|
|
77
|
+
trails
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
back(key) {
|
|
81
|
+
const trail = get().trails[key];
|
|
82
|
+
if (trail === undefined || trail.length === 0) {
|
|
83
|
+
return false;
|
|
77
84
|
}
|
|
85
|
+
get().show(key, stepBack(trail));
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
78
88
|
}));
|
|
79
89
|
/* The trail of a chat in the scope this is rendered in, and a way to set it. */
|
|
80
90
|
export function useSubagentTrail(chatId) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
const $ = _c(10);
|
|
92
|
+
const t0 = useChatScope();
|
|
93
|
+
let t1;
|
|
94
|
+
if ($[0] !== chatId || $[1] !== t0) {
|
|
95
|
+
t1 = t0.keyOf(chatId);
|
|
96
|
+
$[0] = chatId;
|
|
97
|
+
$[1] = t0;
|
|
98
|
+
$[2] = t1;
|
|
99
|
+
} else {
|
|
100
|
+
t1 = $[2];
|
|
101
|
+
}
|
|
102
|
+
const key = t1;
|
|
103
|
+
let t2;
|
|
104
|
+
if ($[3] !== key) {
|
|
105
|
+
t2 = s => s.trails[key] ?? MAIN_AGENT;
|
|
106
|
+
$[3] = key;
|
|
107
|
+
$[4] = t2;
|
|
108
|
+
} else {
|
|
109
|
+
t2 = $[4];
|
|
110
|
+
}
|
|
111
|
+
const trail = useSubagentView(t2);
|
|
112
|
+
let t3;
|
|
113
|
+
if ($[5] !== key) {
|
|
114
|
+
t3 = next => useSubagentView.getState().show(key, next);
|
|
115
|
+
$[5] = key;
|
|
116
|
+
$[6] = t3;
|
|
117
|
+
} else {
|
|
118
|
+
t3 = $[6];
|
|
119
|
+
}
|
|
120
|
+
let t4;
|
|
121
|
+
if ($[7] !== t3 || $[8] !== trail) {
|
|
122
|
+
t4 = {
|
|
123
|
+
trail,
|
|
124
|
+
show: t3
|
|
125
|
+
};
|
|
126
|
+
$[7] = t3;
|
|
127
|
+
$[8] = trail;
|
|
128
|
+
$[9] = t4;
|
|
129
|
+
} else {
|
|
130
|
+
t4 = $[9];
|
|
131
|
+
}
|
|
132
|
+
return t4;
|
|
84
133
|
}
|
|
85
134
|
export function useOpenableSubagents(chatId) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
135
|
+
const $ = _c(6);
|
|
136
|
+
const {
|
|
137
|
+
id
|
|
138
|
+
} = useChatScope();
|
|
139
|
+
let t0;
|
|
140
|
+
if ($[0] !== id) {
|
|
141
|
+
t0 = s => s.unsupported[id] === true;
|
|
142
|
+
$[0] = id;
|
|
143
|
+
$[1] = t0;
|
|
144
|
+
} else {
|
|
145
|
+
t0 = $[1];
|
|
146
|
+
}
|
|
147
|
+
const refused = useSubagentSupport(t0);
|
|
148
|
+
const order = useChatRow(chatId, _temp);
|
|
149
|
+
const structure = useChatRow(chatId, _temp2);
|
|
150
|
+
let t1;
|
|
151
|
+
if ($[2] !== order || $[3] !== refused || $[4] !== structure) {
|
|
152
|
+
t1 = structure === undefined ? [] : openableSubagents(order ?? NO_ITEMS, structure, refused);
|
|
153
|
+
$[2] = order;
|
|
154
|
+
$[3] = refused;
|
|
155
|
+
$[4] = structure;
|
|
156
|
+
$[5] = t1;
|
|
157
|
+
} else {
|
|
158
|
+
t1 = $[5];
|
|
159
|
+
}
|
|
160
|
+
return t1;
|
|
161
|
+
}
|
|
162
|
+
function _temp2(row_0) {
|
|
163
|
+
return row_0?.structure;
|
|
164
|
+
}
|
|
165
|
+
function _temp(row) {
|
|
166
|
+
return row?.order;
|
|
92
167
|
}
|
|
93
168
|
export function useSubagentItem(chatId, toolUseId) {
|
|
94
|
-
|
|
95
|
-
|
|
169
|
+
const $ = _c(3);
|
|
170
|
+
const structure = useChatRow(chatId, _temp3);
|
|
171
|
+
let t0;
|
|
172
|
+
if ($[0] !== structure || $[1] !== toolUseId) {
|
|
173
|
+
t0 = structure === undefined ? null : subagentOf(structure, toolUseId);
|
|
174
|
+
$[0] = structure;
|
|
175
|
+
$[1] = toolUseId;
|
|
176
|
+
$[2] = t0;
|
|
177
|
+
} else {
|
|
178
|
+
t0 = $[2];
|
|
179
|
+
}
|
|
180
|
+
return t0;
|
|
96
181
|
}
|
|
182
|
+
function _temp3(row) {
|
|
183
|
+
return row?.structure;
|
|
184
|
+
}
|
package/dist/chat/thumbnails.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
1
2
|
import i18next from 'i18next';
|
|
2
3
|
import { useEffect, useState } from 'react';
|
|
3
4
|
import { uploadPreviewUrl } from './attachments.js';
|
|
@@ -5,29 +6,29 @@ import { uploadPreviewUrl } from './attachments.js';
|
|
|
5
6
|
export const THUMBNAIL_PX = 256;
|
|
6
7
|
/* The square in the middle of an image that a thumbnail shows, the same part `object-cover` would. */
|
|
7
8
|
export function thumbnailCrop(width, height, max = THUMBNAIL_PX) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const size = Math.max(1, Math.min(width, height));
|
|
10
|
+
return {
|
|
11
|
+
sx: Math.max(0, Math.floor((width - size) / 2)),
|
|
12
|
+
sy: Math.max(0, Math.floor((height - size) / 2)),
|
|
13
|
+
size,
|
|
14
|
+
out: Math.min(max, size)
|
|
15
|
+
};
|
|
15
16
|
}
|
|
16
17
|
function bytesOf(base64) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
const binary = atob(base64);
|
|
19
|
+
const bytes = new Uint8Array(new ArrayBuffer(binary.length));
|
|
20
|
+
for (let i = 0; i < binary.length; i++) {
|
|
21
|
+
bytes[i] = binary.charCodeAt(i);
|
|
22
|
+
}
|
|
23
|
+
return bytes;
|
|
23
24
|
}
|
|
24
25
|
function dataUrlOf(blob) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const reader = new FileReader();
|
|
28
|
+
reader.onerror = () => reject(reader.error ?? new Error(i18next.t('agent-chat:attachments.unreadableThumbnail')));
|
|
29
|
+
reader.onload = () => resolve(String(reader.result));
|
|
30
|
+
reader.readAsDataURL(blob);
|
|
31
|
+
});
|
|
31
32
|
}
|
|
32
33
|
/*
|
|
33
34
|
* A still of the middle of an image, decoded once: a browser decodes a full data URL again on every
|
|
@@ -35,54 +36,81 @@ function dataUrlOf(blob) {
|
|
|
35
36
|
* cannot be decoded this way (an SVG, a browser without `OffscreenCanvas`) falls back to the image.
|
|
36
37
|
*/
|
|
37
38
|
async function makeThumbnail(upload) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
bitmap.close();
|
|
49
|
-
return await dataUrlOf(await canvas.convertToBlob({ type: 'image/png' }));
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return uploadPreviewUrl(upload);
|
|
39
|
+
try {
|
|
40
|
+
const bitmap = await createImageBitmap(new Blob([bytesOf(upload.data)], {
|
|
41
|
+
type: upload.mime
|
|
42
|
+
}));
|
|
43
|
+
const crop = thumbnailCrop(bitmap.width, bitmap.height);
|
|
44
|
+
const canvas = new OffscreenCanvas(crop.out, crop.out);
|
|
45
|
+
const context = canvas.getContext('2d');
|
|
46
|
+
if (!context) {
|
|
47
|
+
bitmap.close();
|
|
48
|
+
return uploadPreviewUrl(upload);
|
|
53
49
|
}
|
|
50
|
+
context.drawImage(bitmap, crop.sx, crop.sy, crop.size, crop.size, 0, 0, crop.out, crop.out);
|
|
51
|
+
bitmap.close();
|
|
52
|
+
return await dataUrlOf(await canvas.convertToBlob({
|
|
53
|
+
type: 'image/png'
|
|
54
|
+
}));
|
|
55
|
+
} catch {
|
|
56
|
+
return uploadPreviewUrl(upload);
|
|
57
|
+
}
|
|
54
58
|
}
|
|
55
59
|
// Keyed by the upload itself, so a composer that mounts again finds it and a removed file lets it go.
|
|
56
60
|
const made = new WeakMap();
|
|
57
61
|
const making = new WeakMap();
|
|
58
62
|
function thumbnailOf(upload) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
let promise = making.get(upload);
|
|
64
|
+
if (!promise) {
|
|
65
|
+
promise = makeThumbnail(upload).then(url => {
|
|
66
|
+
made.set(upload, url);
|
|
67
|
+
return url;
|
|
68
|
+
});
|
|
69
|
+
making.set(upload, promise);
|
|
70
|
+
}
|
|
71
|
+
return promise;
|
|
68
72
|
}
|
|
69
73
|
/* The thumbnail of an image the composer holds, or null while it is being made. */
|
|
70
74
|
export function useUploadThumbnail(upload) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
const $ = _c(5);
|
|
76
|
+
const [ready, setReady] = useState(null);
|
|
77
|
+
let t0;
|
|
78
|
+
if ($[0] !== upload) {
|
|
79
|
+
t0 = made.get(upload);
|
|
80
|
+
$[0] = upload;
|
|
81
|
+
$[1] = t0;
|
|
82
|
+
} else {
|
|
83
|
+
t0 = $[1];
|
|
84
|
+
}
|
|
85
|
+
const cached = t0;
|
|
86
|
+
let t1;
|
|
87
|
+
let t2;
|
|
88
|
+
if ($[2] !== upload) {
|
|
89
|
+
t1 = () => {
|
|
90
|
+
if (made.has(upload)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
let cancelled = false;
|
|
94
|
+
thumbnailOf(upload).then(url => {
|
|
95
|
+
if (!cancelled) {
|
|
96
|
+
setReady({
|
|
97
|
+
upload,
|
|
98
|
+
url
|
|
99
|
+
});
|
|
76
100
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
101
|
+
});
|
|
102
|
+
return () => {
|
|
103
|
+
cancelled = true;
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
t2 = [upload];
|
|
107
|
+
$[2] = upload;
|
|
108
|
+
$[3] = t1;
|
|
109
|
+
$[4] = t2;
|
|
110
|
+
} else {
|
|
111
|
+
t1 = $[3];
|
|
112
|
+
t2 = $[4];
|
|
113
|
+
}
|
|
114
|
+
useEffect(t1, t2);
|
|
115
|
+
return cached ?? (ready?.upload === upload ? ready.url : null);
|
|
116
|
+
}
|
|
@@ -2,15 +2,27 @@ import { create } from 'zustand';
|
|
|
2
2
|
/* A little longer than the animation of `.chat-flash`, so a row that scrolls into view again later is neither lit nor opened a second time. */
|
|
3
3
|
const FLASH_MS = 2000;
|
|
4
4
|
export const useTimelineFlash = create((set, get) => ({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
})
|
|
5
|
+
target: null,
|
|
6
|
+
flash(key, rowId, opens, block) {
|
|
7
|
+
const nonce = (get().target?.nonce ?? 0) + 1;
|
|
8
|
+
set({
|
|
9
|
+
target: {
|
|
10
|
+
key,
|
|
11
|
+
rowId,
|
|
12
|
+
opens,
|
|
13
|
+
nonce,
|
|
14
|
+
...(block ? {
|
|
15
|
+
block
|
|
16
|
+
} : {})
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const timer = setTimeout(() => {
|
|
20
|
+
if (get().target?.nonce === nonce) {
|
|
21
|
+
set({
|
|
22
|
+
target: null
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}, FLASH_MS);
|
|
26
|
+
timer.unref?.();
|
|
27
|
+
}
|
|
28
|
+
}));
|