@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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Bot, Eye, FolderSearch, Globe, ListTodo, Search, SquarePen, Terminal, Workflow, Zap } from 'lucide-react';
|
|
2
2
|
function entry(icon, summary, rest = {}) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
return {
|
|
4
|
+
icon,
|
|
5
|
+
summary,
|
|
6
|
+
grouped: true,
|
|
7
|
+
changesFiles: false,
|
|
8
|
+
readsImage: false,
|
|
9
|
+
shell: false,
|
|
10
|
+
...rest
|
|
11
|
+
};
|
|
12
12
|
}
|
|
13
13
|
/*
|
|
14
14
|
* Every tool the thread has a word for, in one table so a new name is never missing from a lookup. A
|
|
@@ -16,30 +16,50 @@ function entry(icon, summary, rest = {}) {
|
|
|
16
16
|
* string of its input.
|
|
17
17
|
*/
|
|
18
18
|
export const TOOL_CATALOG = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
19
|
+
Read: entry(Eye, ['file_path'], {
|
|
20
|
+
readsImage: true
|
|
21
|
+
}),
|
|
22
|
+
// Only `readImagePath` ever had this one, which is why it has no sentence of its own yet.
|
|
23
|
+
NotebookRead: entry(Eye, ['file_path', 'notebook_path'], {
|
|
24
|
+
grouped: false,
|
|
25
|
+
readsImage: true
|
|
26
|
+
}),
|
|
27
|
+
// These three read as "Edited 3 files" through `changesFiles`, so they carry no copy of that sentence.
|
|
28
|
+
Edit: entry(SquarePen, ['file_path'], {
|
|
29
|
+
grouped: false,
|
|
30
|
+
changesFiles: true
|
|
31
|
+
}),
|
|
32
|
+
Write: entry(SquarePen, ['file_path'], {
|
|
33
|
+
changesFiles: true
|
|
34
|
+
}),
|
|
35
|
+
MultiEdit: entry(SquarePen, ['file_path'], {
|
|
36
|
+
grouped: false,
|
|
37
|
+
changesFiles: true
|
|
38
|
+
}),
|
|
39
|
+
NotebookEdit: entry(SquarePen, ['file_path', 'notebook_path']),
|
|
40
|
+
// Codex reports a patch as the paths it touches; its own input carries no path of its own.
|
|
41
|
+
ApplyPatch: entry(SquarePen, ['summary'], {
|
|
42
|
+
grouped: false,
|
|
43
|
+
changesFiles: true
|
|
44
|
+
}),
|
|
45
|
+
// Codex's command executions arrive under this name too.
|
|
46
|
+
Bash: entry(Terminal, ['description', 'command'], {
|
|
47
|
+
shell: true
|
|
48
|
+
}),
|
|
49
|
+
Grep: entry(Search, ['pattern']),
|
|
50
|
+
Glob: entry(FolderSearch, ['pattern']),
|
|
51
|
+
WebFetch: entry(Globe, ['url', 'query']),
|
|
52
|
+
WebSearch: entry(Globe, ['url', 'query']),
|
|
53
|
+
Task: entry(Bot, ['description']),
|
|
54
|
+
Agent: entry(Bot, ['description']),
|
|
55
|
+
Skill: entry(Zap, ['skill']),
|
|
56
|
+
// A plan is a list of objects, so there is no line to lift out of it.
|
|
57
|
+
TodoWrite: entry(ListTodo, []),
|
|
58
|
+
// Its input is the whole script; the line takes what the CLI says the workflow is about instead.
|
|
59
|
+
Workflow: entry(Workflow, [], {
|
|
60
|
+
grouped: false
|
|
61
|
+
})
|
|
42
62
|
};
|
|
43
63
|
export function toolEntry(name) {
|
|
44
|
-
|
|
45
|
-
}
|
|
64
|
+
return TOOL_CATALOG[name];
|
|
65
|
+
}
|
package/dist/chat/logic/tools.js
CHANGED
|
@@ -1,139 +1,163 @@
|
|
|
1
1
|
import { isRecord } from './json.js';
|
|
2
2
|
import { toolEntry } from './tool-catalog.js';
|
|
3
3
|
function str(value) {
|
|
4
|
-
|
|
4
|
+
return typeof value === 'string' ? value : null;
|
|
5
5
|
}
|
|
6
6
|
/* The one line that says what a tool call is about: the command, the file, the pattern. */
|
|
7
7
|
export function toolSummary(name, input) {
|
|
8
|
-
|
|
9
|
-
return '';
|
|
10
|
-
}
|
|
11
|
-
const known = toolEntry(name);
|
|
12
|
-
if (known === undefined) {
|
|
13
|
-
// A tool nobody wrote down, an MCP one above all, gets its best guess from the first string it was given.
|
|
14
|
-
const first = Object.values(input).find((value) => typeof value === 'string');
|
|
15
|
-
return typeof first === 'string' ? first : '';
|
|
16
|
-
}
|
|
17
|
-
for (const key of known.summary) {
|
|
18
|
-
const value = str(input[key]);
|
|
19
|
-
if (value !== null) {
|
|
20
|
-
return value;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
8
|
+
if (!isRecord(input)) {
|
|
23
9
|
return '';
|
|
10
|
+
}
|
|
11
|
+
const known = toolEntry(name);
|
|
12
|
+
if (known === undefined) {
|
|
13
|
+
// A tool nobody wrote down, an MCP one above all, gets its best guess from the first string it was given.
|
|
14
|
+
const first = Object.values(input).find(value => typeof value === 'string');
|
|
15
|
+
return typeof first === 'string' ? first : '';
|
|
16
|
+
}
|
|
17
|
+
for (const key of known.summary) {
|
|
18
|
+
const value = str(input[key]);
|
|
19
|
+
if (value !== null) {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
24
|
}
|
|
25
25
|
// The input keys whose value is a file a call is about.
|
|
26
26
|
const PATH_KEYS = new Set(['file_path', 'notebook_path']);
|
|
27
27
|
/* Whether the one line of a call is the path of a file, which a row cuts in the middle so the name stays. */
|
|
28
28
|
export function toolSummaryIsPath(name, input) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
const known = toolEntry(name);
|
|
30
|
+
if (known === undefined || !isRecord(input)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const key = known.summary.find(candidate => str(input[candidate]) !== null);
|
|
34
|
+
return key !== undefined && PATH_KEYS.has(key);
|
|
35
35
|
}
|
|
36
36
|
/* The command of a shell call, as it was run; null for any other call or one without a command. */
|
|
37
37
|
export function shellCommand(name, input) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
if (toolEntry(name)?.shell !== true || !isRecord(input)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const command = str(input.command);
|
|
42
|
+
return command === null || command.trim() === '' ? null : command;
|
|
43
43
|
}
|
|
44
44
|
// A shell call's description is already the detail of its row.
|
|
45
45
|
const SHELL_SHOWN = new Set(['command', 'description']);
|
|
46
46
|
function valueText(value) {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// An empty string can be the point of a call (clearing a field), so it shows as one.
|
|
48
|
+
return typeof value === 'string' && value !== '' ? value : JSON.stringify(value) ?? String(value);
|
|
49
49
|
}
|
|
50
50
|
/* The input of a call as lines: a shell command as itself, every other key as `key value`, null included. */
|
|
51
51
|
export function toolCallLines(name, input) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
if (!isRecord(input)) {
|
|
53
|
+
const text = input === null || input === undefined || input === '' ? null : valueText(input);
|
|
54
|
+
return {
|
|
55
|
+
command: null,
|
|
56
|
+
args: [],
|
|
57
|
+
text
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const command = shellCommand(name, input);
|
|
61
|
+
const args = Object.entries(input).filter(([key, value]) => value !== undefined && !(command !== null && SHELL_SHOWN.has(key))).map(([key, value]) => [key, valueText(value)]);
|
|
62
|
+
return {
|
|
63
|
+
command,
|
|
64
|
+
args,
|
|
65
|
+
text: null
|
|
66
|
+
};
|
|
61
67
|
}
|
|
62
68
|
/* A failed call's output with the exit code its tool put on the first line ("Exit code 1"), as Claude Code's shell does. */
|
|
63
69
|
export function exitCodeOf(output) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
const match = /^Exit code (-?\d+)[ \t]*(?:\r?\n|$)/.exec(output);
|
|
71
|
+
if (match === null || Number(match[1]) === 0) {
|
|
72
|
+
return {
|
|
73
|
+
code: null,
|
|
74
|
+
rest: output
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
code: Number(match[1]),
|
|
79
|
+
rest: output.slice(match[0].length)
|
|
80
|
+
};
|
|
69
81
|
}
|
|
70
82
|
/* Whether an output says anything; whitespace alone does not. */
|
|
71
83
|
export function hasOutput(output) {
|
|
72
|
-
|
|
84
|
+
return output !== null && output.trim() !== '';
|
|
73
85
|
}
|
|
74
86
|
/* Whether opening a call shows anything: a diff, the input it was given or what it answered. */
|
|
75
87
|
export function hasToolBody(tool) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
if (hasFileChanges(tool) || hasOutput(tool.output)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
const lines = toolCallLines(tool.name, tool.input);
|
|
92
|
+
return lines.command !== null || lines.args.length > 0 || lines.text !== null;
|
|
81
93
|
}
|
|
82
94
|
// What `GET /fs/file` will serve; a path with another suffix is not worth asking the host about.
|
|
83
95
|
const IMAGE_SUFFIXES = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'];
|
|
84
96
|
/* The image file a tool call looked at, so the row can draw it; null for every other call. */
|
|
85
97
|
export function readImagePath(name, input) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
if (toolEntry(name)?.readsImage !== true) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const path = isRecord(input) ? str(input.file_path) : null;
|
|
102
|
+
if (path === null) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const lowered = path.toLowerCase();
|
|
106
|
+
return IMAGE_SUFFIXES.some(suffix => lowered.endsWith(suffix)) ? path : null;
|
|
95
107
|
}
|
|
96
108
|
/* The before and after text of a file-changing tool call, so the thread can show it as a diff. */
|
|
97
109
|
export function fileChanges(name, input) {
|
|
98
|
-
|
|
99
|
-
return [];
|
|
100
|
-
}
|
|
101
|
-
const path = str(input.file_path) ?? '';
|
|
102
|
-
if (name === 'Edit') {
|
|
103
|
-
return [{ path, before: str(input.old_string) ?? '', after: str(input.new_string) ?? '' }];
|
|
104
|
-
}
|
|
105
|
-
if (name === 'Write') {
|
|
106
|
-
return [{ path, before: '', after: str(input.content) ?? '' }];
|
|
107
|
-
}
|
|
108
|
-
if (name === 'MultiEdit' && Array.isArray(input.edits)) {
|
|
109
|
-
return input.edits.filter(isRecord).map((edit) => ({ path, before: str(edit.old_string) ?? '', after: str(edit.new_string) ?? '' }));
|
|
110
|
-
}
|
|
110
|
+
if (!isRecord(input)) {
|
|
111
111
|
return [];
|
|
112
|
+
}
|
|
113
|
+
const path = str(input.file_path) ?? '';
|
|
114
|
+
if (name === 'Edit') {
|
|
115
|
+
return [{
|
|
116
|
+
path,
|
|
117
|
+
before: str(input.old_string) ?? '',
|
|
118
|
+
after: str(input.new_string) ?? ''
|
|
119
|
+
}];
|
|
120
|
+
}
|
|
121
|
+
if (name === 'Write') {
|
|
122
|
+
return [{
|
|
123
|
+
path,
|
|
124
|
+
before: '',
|
|
125
|
+
after: str(input.content) ?? ''
|
|
126
|
+
}];
|
|
127
|
+
}
|
|
128
|
+
if (name === 'MultiEdit' && Array.isArray(input.edits)) {
|
|
129
|
+
return input.edits.filter(isRecord).map(edit => ({
|
|
130
|
+
path,
|
|
131
|
+
before: str(edit.old_string) ?? '',
|
|
132
|
+
after: str(edit.new_string) ?? ''
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
return [];
|
|
112
136
|
}
|
|
113
137
|
export function isFileChange(name) {
|
|
114
|
-
|
|
138
|
+
return toolEntry(name)?.changesFiles === true;
|
|
115
139
|
}
|
|
116
140
|
/* The unified diffs a provider put next to a tool call; empty for one that reports before and after. */
|
|
117
141
|
export function unifiedChanges(tool) {
|
|
118
|
-
|
|
142
|
+
return (tool.changes ?? []).filter(change => change.diff !== '');
|
|
119
143
|
}
|
|
120
144
|
/* The same, for the copy an approval carries so the person can read what they are approving. */
|
|
121
145
|
export function approvalChanges(input) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
146
|
+
const changes = isRecord(input) ? input.changes : null;
|
|
147
|
+
if (!Array.isArray(changes)) {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
return changes.filter(change => isRecord(change) && typeof change.path === 'string' && typeof change.diff === 'string' && change.diff !== '');
|
|
127
151
|
}
|
|
128
152
|
/* Whether a settled call is worth a row in the turn's changed files card. */
|
|
129
153
|
export function hasFileChanges(tool) {
|
|
130
|
-
|
|
154
|
+
return unifiedChanges(tool).length > 0 || fileChanges(tool.name, tool.input).length > 0;
|
|
131
155
|
}
|
|
132
156
|
/* When a running call started: what the CLI reported, or the moment the call appeared. */
|
|
133
157
|
export function toolStartedAt(tool) {
|
|
134
|
-
|
|
158
|
+
return tool.progress?.startedAt ?? tool.createdAt;
|
|
135
159
|
}
|
|
136
160
|
// Keep the full buffer so the renderer can carry ANSI state into the visible tail.
|
|
137
161
|
export function liveOutput(tool) {
|
|
138
|
-
|
|
139
|
-
}
|
|
162
|
+
return tool.progress?.output || null;
|
|
163
|
+
}
|
|
@@ -11,36 +11,36 @@ const MAX_CONTENT_HEIGHT_PX = 10_000_000;
|
|
|
11
11
|
*/
|
|
12
12
|
const remembered = new Map();
|
|
13
13
|
function keyOf(visualId, width) {
|
|
14
|
-
|
|
14
|
+
return `${visualId}@${Math.round(width)}`;
|
|
15
15
|
}
|
|
16
16
|
/* A height a page reported, held to the visual's own maximum and the limits, in whole pixels. */
|
|
17
17
|
export function clampVisualHeight(visual, height) {
|
|
18
|
-
|
|
18
|
+
return Math.min(Math.max(Math.ceil(Math.min(height, visual.maxHeight)), VISUAL_LIMITS.minHeight), VISUAL_LIMITS.maxHeight);
|
|
19
19
|
}
|
|
20
20
|
export function visualContentHeight(height) {
|
|
21
|
-
|
|
21
|
+
return Math.min(MAX_CONTENT_HEIGHT_PX, Math.max(VISUAL_LIMITS.minHeight, Math.ceil(height)));
|
|
22
22
|
}
|
|
23
23
|
export function initialVisualContentHeight(visual, width) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
const cached = remembered.get(keyOf(visual.id, width));
|
|
25
|
+
if (cached !== undefined) {
|
|
26
|
+
return cached;
|
|
27
|
+
}
|
|
28
|
+
const below = visual.heights?.filter(([measured]) => measured <= width).sort((left, right) => right[0] - left[0])[0];
|
|
29
|
+
const above = visual.heights?.filter(([measured]) => measured >= width).sort((left, right) => left[0] - right[0])[0];
|
|
30
|
+
return below || above ? visualContentHeight(Math.max(below?.[1] ?? 0, above?.[1] ?? 0)) : DEFAULT_HEIGHT_PX;
|
|
31
31
|
}
|
|
32
32
|
/*
|
|
33
33
|
* The height a frame `width` CSS pixels wide starts at: what the page reported in a frame that wide
|
|
34
34
|
* before, else what the host measured, else a modest default.
|
|
35
35
|
*/
|
|
36
36
|
export function initialVisualHeight(visual, width) {
|
|
37
|
-
|
|
37
|
+
return remembered.get(keyOf(visual.id, width)) ?? visualFrameHeight(visual, width) ?? clampVisualHeight(visual, DEFAULT_HEIGHT_PX);
|
|
38
38
|
}
|
|
39
39
|
export function rememberVisualHeight(visualId, width, height) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
40
|
+
const key = keyOf(visualId, width);
|
|
41
|
+
remembered.delete(key);
|
|
42
|
+
remembered.set(key, height);
|
|
43
|
+
if (remembered.size > REMEMBERED_HEIGHTS) {
|
|
44
|
+
remembered.delete(remembered.keys().next().value);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export function visualViewportGeometry(contentHeight, availableHeight, top) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
const height = Math.max(1, Math.min(contentHeight, availableHeight));
|
|
3
|
+
return {
|
|
4
|
+
height,
|
|
5
|
+
top: Math.max(0, Math.min(-top, contentHeight - height))
|
|
6
|
+
};
|
|
7
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export function dayPartOf(now) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
2
|
+
const hour = now.getHours();
|
|
3
|
+
if (hour < 5) {
|
|
4
|
+
return 'night';
|
|
5
|
+
}
|
|
6
|
+
if (hour < 12) {
|
|
7
|
+
return 'morning';
|
|
8
|
+
}
|
|
9
|
+
return hour < 18 ? 'afternoon' : 'evening';
|
|
10
|
+
}
|
|
@@ -12,3 +12,13 @@ export interface WorkflowPhaseView {
|
|
|
12
12
|
export declare function workflowAgentState(agent: ChatWorkflowAgent, workflowRunning: boolean): WorkflowAgentState;
|
|
13
13
|
export declare function workflowPhases(workflow: ChatWorkflow, workflowRunning: boolean): WorkflowPhaseView[];
|
|
14
14
|
export declare function workflowAgentTime(view: WorkflowAgentView): string | null;
|
|
15
|
+
export interface WorkflowAgentPreview {
|
|
16
|
+
tool: string | null;
|
|
17
|
+
text: string | null;
|
|
18
|
+
}
|
|
19
|
+
export declare function workflowAgentPreview(view: WorkflowAgentView): WorkflowAgentPreview;
|
|
20
|
+
export type WorkflowCounts = Record<WorkflowAgentState, number> & {
|
|
21
|
+
total: number;
|
|
22
|
+
};
|
|
23
|
+
export declare function workflowCounts(phases: WorkflowPhaseView[]): WorkflowCounts;
|
|
24
|
+
export declare function workflowDescription(input: unknown): string | null;
|
|
@@ -1,47 +1,145 @@
|
|
|
1
1
|
import i18next from 'i18next';
|
|
2
2
|
import { formatElapsedShort } from '@adecore/ui/format';
|
|
3
3
|
export function workflowAgentState(agent, workflowRunning) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
if (agent.status !== 'running') {
|
|
5
|
+
return agent.status;
|
|
6
|
+
}
|
|
7
|
+
if (!workflowRunning) {
|
|
8
|
+
return 'stopped';
|
|
9
|
+
}
|
|
10
|
+
return agent.startedAt === null ? 'waiting' : 'running';
|
|
11
11
|
}
|
|
12
12
|
/*
|
|
13
13
|
* The phases in the order the script announced them, each with the agents it started in it. A phase
|
|
14
14
|
* announced ahead of its agents is there without any, and agents of no known phase come first, untitled.
|
|
15
15
|
*/
|
|
16
16
|
export function workflowPhases(workflow, workflowRunning) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
const known = new Map(workflow.phases.map(phase => [phase.index, phase]));
|
|
18
|
+
const loose = [];
|
|
19
|
+
const byPhase = new Map();
|
|
20
|
+
for (const agent of workflow.agents) {
|
|
21
|
+
const view = {
|
|
22
|
+
agent,
|
|
23
|
+
state: workflowAgentState(agent, workflowRunning)
|
|
24
|
+
};
|
|
25
|
+
if (agent.phaseIndex === null || !known.has(agent.phaseIndex)) {
|
|
26
|
+
loose.push(view);
|
|
27
|
+
continue;
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
byPhase.set(agent.phaseIndex, [...(byPhase.get(agent.phaseIndex) ?? []), view]);
|
|
30
|
+
}
|
|
31
|
+
const phases = workflow.phases.map(phase => ({
|
|
32
|
+
key: `phase-${phase.index}`,
|
|
33
|
+
title: phase.title,
|
|
34
|
+
agents: byPhase.get(phase.index) ?? []
|
|
35
|
+
}));
|
|
36
|
+
return loose.length > 0 ? [{
|
|
37
|
+
key: 'loose',
|
|
38
|
+
title: null,
|
|
39
|
+
agents: loose
|
|
40
|
+
}, ...phases] : phases;
|
|
30
41
|
}
|
|
31
42
|
/* What the line of an agent that is not at work says about its time; one at work counts on by itself. */
|
|
32
43
|
export function workflowAgentTime(view) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
switch (view.state) {
|
|
45
|
+
case 'running':
|
|
46
|
+
return null;
|
|
47
|
+
case 'waiting':
|
|
48
|
+
return i18next.t('agent-chat:rows.workflow.waiting');
|
|
49
|
+
case 'stopped':
|
|
50
|
+
return i18next.t('agent-chat:rows.workflow.stopped');
|
|
51
|
+
case 'done':
|
|
52
|
+
case 'failed':
|
|
53
|
+
return view.agent.durationMs === null ? null : formatElapsedShort(view.agent.durationMs);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/* The CLI's previews start with a markdown heading as often as not, which says nothing on one line. */
|
|
57
|
+
function firstLine(text) {
|
|
58
|
+
const line = text?.split('\n').map(part => part.replace(/^#+\s*/, '').trim()).find(part => part !== '');
|
|
59
|
+
return line === undefined ? null : line;
|
|
60
|
+
}
|
|
61
|
+
/* The second line of an agent: what it does while at work, what it answered once it stopped, what it was asked before. */
|
|
62
|
+
export function workflowAgentPreview(view) {
|
|
63
|
+
const {
|
|
64
|
+
agent
|
|
65
|
+
} = view;
|
|
66
|
+
switch (view.state) {
|
|
67
|
+
case 'running':
|
|
68
|
+
return agent.lastTool === null ? {
|
|
69
|
+
tool: null,
|
|
70
|
+
text: firstLine(agent.promptPreview)
|
|
71
|
+
} : {
|
|
72
|
+
tool: agent.lastTool,
|
|
73
|
+
text: firstLine(agent.lastToolSummary)
|
|
74
|
+
};
|
|
75
|
+
case 'waiting':
|
|
76
|
+
return {
|
|
77
|
+
tool: null,
|
|
78
|
+
text: firstLine(agent.promptPreview)
|
|
79
|
+
};
|
|
80
|
+
case 'failed':
|
|
81
|
+
return {
|
|
82
|
+
tool: null,
|
|
83
|
+
text: firstLine(agent.error) ?? firstLine(agent.resultPreview)
|
|
84
|
+
};
|
|
85
|
+
case 'done':
|
|
86
|
+
case 'stopped':
|
|
87
|
+
return {
|
|
88
|
+
tool: null,
|
|
89
|
+
text: firstLine(agent.resultPreview) ?? firstLine(agent.promptPreview)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export function workflowCounts(phases) {
|
|
94
|
+
const counts = {
|
|
95
|
+
total: 0,
|
|
96
|
+
running: 0,
|
|
97
|
+
waiting: 0,
|
|
98
|
+
stopped: 0,
|
|
99
|
+
done: 0,
|
|
100
|
+
failed: 0
|
|
101
|
+
};
|
|
102
|
+
for (const view of phases.flatMap(phase => phase.agents)) {
|
|
103
|
+
counts.total += 1;
|
|
104
|
+
counts[view.state] += 1;
|
|
105
|
+
}
|
|
106
|
+
return counts;
|
|
107
|
+
}
|
|
108
|
+
const META_START = /export\s+const\s+meta\s*=\s*\{/;
|
|
109
|
+
const DESCRIPTION = /\bdescription\s*:\s*(['"`])((?:\\.|(?!\1)[^\\])*)\1/;
|
|
110
|
+
/* The literal from its opening brace to the one that closes it, skipping braces inside strings. */
|
|
111
|
+
function metaLiteral(script) {
|
|
112
|
+
const start = META_START.exec(script);
|
|
113
|
+
if (start === null) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const from = start.index + start[0].length - 1;
|
|
117
|
+
let depth = 0;
|
|
118
|
+
let quote = null;
|
|
119
|
+
for (let i = from; i < script.length; i++) {
|
|
120
|
+
const char = script[i];
|
|
121
|
+
if (quote !== null) {
|
|
122
|
+
if (char === '\\') {
|
|
123
|
+
i++;
|
|
124
|
+
} else if (char === quote) {
|
|
125
|
+
quote = null;
|
|
126
|
+
}
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
130
|
+
quote = char;
|
|
131
|
+
} else if (char === '{') {
|
|
132
|
+
depth++;
|
|
133
|
+
} else if (char === '}' && --depth === 0) {
|
|
134
|
+
return script.slice(from, i + 1);
|
|
46
135
|
}
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
47
138
|
}
|
|
139
|
+
/* The script's `meta` is a pure literal by the CLI's own rule, so its description reads without running anything. A saved workflow called by name has no script here. */
|
|
140
|
+
export function workflowDescription(input) {
|
|
141
|
+
const script = typeof input === 'object' && input !== null && 'script' in input ? input.script : undefined;
|
|
142
|
+
const meta = typeof script === 'string' ? metaLiteral(script) : null;
|
|
143
|
+
const found = meta === null ? undefined : DESCRIPTION.exec(meta)?.[2]?.replace(/\\(.)/g, '$1').trim();
|
|
144
|
+
return found ? found : null;
|
|
145
|
+
}
|