@adecore/agents-react 0.38.0 → 0.40.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/AgentModelLabel.d.ts +10 -0
- package/dist/agents/AgentModelLabel.js +98 -0
- package/dist/agents/model-name.js +2 -1
- package/dist/agents/provider-paths.d.ts +2 -1
- package/dist/agents/provider-paths.js +7 -3
- package/dist/chat/account-choice.js +57 -28
- package/dist/chat/bookmarks.js +2 -1
- package/dist/chat/drafts.d.ts +0 -1
- package/dist/chat/drafts.js +9 -28
- package/dist/chat/logic/picker-entries.js +2 -8
- package/dist/chat/logic/resume-compaction.js +2 -5
- package/dist/chat/logic/timeline-copy.js +2 -8
- package/dist/chat/logic/timeline.js +9 -10
- package/dist/chat/logic/workflow.js +2 -4
- package/dist/chat/subagent-conversation.js +2 -1
- package/dist/chat/ui/Composer.js +385 -360
- package/dist/chat/ui/GoalDock.js +2 -1
- package/dist/chat/ui/LimitState.js +4 -6
- package/dist/chat/ui/Pickers.d.ts +2 -1
- package/dist/chat/ui/Pickers.js +126 -123
- package/dist/chat/ui/PromptEditor.d.ts +19 -0
- package/dist/chat/ui/PromptEditor.js +115 -0
- package/dist/chat/ui/Timeline.d.ts +2 -1
- package/dist/chat/ui/Timeline.js +13 -1
- package/dist/chat/ui/composer/ComposerControls.d.ts +3 -0
- package/dist/chat/ui/composer/ComposerControls.js +235 -38
- package/dist/chat/ui/composer/key-handler.d.ts +1 -1
- package/dist/chat/ui/composer/key-handler.js +3 -11
- package/dist/chat/ui/composer/prompt-picks.d.ts +4 -0
- package/dist/chat/ui/composer/prompt-picks.js +14 -0
- package/dist/chat/ui/composer/use-composer-menus.d.ts +4 -49
- package/dist/chat/ui/composer/use-composer-menus.js +65 -519
- package/dist/chat/ui/composer/use-continuable-turn.js +0 -1
- package/dist/chat/ui/composer/use-notice.js +2 -1
- package/dist/chat/ui/composer/use-prompt-history.js +1 -1
- package/dist/chat/ui/composer/use-prompt-menus.d.ts +73 -0
- package/dist/chat/ui/composer/use-prompt-menus.js +499 -0
- package/dist/chat/ui/composer/use-take-back.js +2 -2
- package/dist/chat/ui/diff/ApprovalReview.js +1 -1
- package/dist/chat/ui/highlighter.d.ts +0 -6
- package/dist/chat/ui/highlighter.js +0 -12
- package/dist/chat/ui/icons.d.ts +0 -1
- package/dist/chat/ui/icons.js +0 -3
- package/dist/chat/ui/index.d.ts +3 -0
- package/dist/chat/ui/index.js +2 -0
- package/dist/chat/ui/rows/MessageRows.js +2 -5
- package/dist/chat/ui/rows/row-rhythm.js +2 -5
- package/dist/chat/ui/theme-watch.js +3 -7
- package/dist/host-hooks.d.ts +2 -1
- package/dist/host-hooks.js +6 -0
- package/dist/host.d.ts +17 -1
- package/dist/index.d.ts +1 -1
- package/dist/locales/en/agent-chat.d.ts +1 -0
- package/dist/locales/en/agent-chat.js +1 -0
- package/dist/locales/nl/agent-chat.d.ts +1 -0
- package/dist/locales/nl/agent-chat.js +1 -0
- package/dist/prompts/logic/usePromptSession.js +2 -1
- package/dist/providers/AddAccountForm.js +2 -1
- package/dist/providers/CliDetail.js +104 -130
- package/dist/providers/account-actions.js +6 -9
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.js +1 -0
- package/dist/state/chats.d.ts +1 -0
- package/dist/state/chats.js +6 -11
- package/dist/state/provider-accounts.d.ts +1 -1
- package/dist/state/provider-accounts.js +2 -8
- package/dist/theme.css +3 -0
- package/dist/transport.d.ts +2 -0
- package/dist/transport.js +14 -0
- package/dist/usage/ChartLogo.d.ts +5 -0
- package/dist/usage/ChartLogo.js +48 -0
- package/dist/usage/LimitsList.js +6 -16
- package/dist/usage/UsageBreakdown.js +17 -40
- package/dist/usage/UsageLimits.js +183 -211
- package/dist/usage/UsagePage.js +3 -17
- package/dist/usage/UsageSummary.js +4 -9
- package/dist/usage/limits.js +16 -31
- package/dist/usage/summary.d.ts +1 -1
- package/dist/usage/summary.js +3 -5
- package/package.json +26 -26
- package/src/agents/AccountDot.tsx +1 -0
- package/src/agents/AgentIcon.tsx +2 -0
- package/src/agents/AgentModelLabel.tsx +38 -0
- package/src/agents/ModelOptionControl.tsx +8 -0
- package/src/agents/account-limits.ts +3 -0
- package/src/agents/accounts.ts +12 -0
- package/src/agents/model-name.ts +13 -1
- package/src/agents/model-options.ts +2 -0
- package/src/agents/model-requirement.ts +4 -0
- package/src/agents/option-words.ts +2 -0
- package/src/agents/provider-paths.ts +8 -3
- package/src/agents/status-look.ts +1 -0
- package/src/chat/account-choice.ts +25 -19
- package/src/chat/actions.ts +5 -0
- package/src/chat/attachments.ts +8 -0
- package/src/chat/bookmarks.ts +13 -1
- package/src/chat/chat-client.ts +63 -0
- package/src/chat/chat-references.ts +3 -0
- package/src/chat/composer-effort.ts +5 -0
- package/src/chat/composer-send.ts +4 -0
- package/src/chat/drafts.ts +21 -17
- package/src/chat/forks.ts +4 -0
- package/src/chat/guards.ts +2 -0
- package/src/chat/index.ts +7 -0
- package/src/chat/logic/ansi.ts +47 -0
- package/src/chat/logic/bookmarks.ts +7 -0
- package/src/chat/logic/command-looks.ts +29 -0
- package/src/chat/logic/context-usage.ts +3 -0
- package/src/chat/logic/continue-after-stop.ts +5 -0
- package/src/chat/logic/effort.ts +4 -0
- package/src/chat/logic/embedded-code.ts +63 -0
- package/src/chat/logic/fork.ts +22 -0
- package/src/chat/logic/generated-image.ts +7 -0
- package/src/chat/logic/goal.ts +7 -0
- package/src/chat/logic/handback.ts +2 -0
- package/src/chat/logic/limit.ts +8 -0
- package/src/chat/logic/picker-entries.ts +16 -4
- package/src/chat/logic/resume-compaction.ts +22 -5
- package/src/chat/logic/scrubber.ts +38 -5
- package/src/chat/logic/thought.ts +5 -0
- package/src/chat/logic/thread-cards.ts +6 -0
- package/src/chat/logic/timeline-copy.ts +4 -9
- package/src/chat/logic/timeline-target.ts +15 -0
- package/src/chat/logic/timeline.ts +113 -10
- package/src/chat/logic/tools.ts +30 -0
- package/src/chat/logic/visual-height.ts +5 -0
- package/src/chat/logic/visual-viewport.ts +1 -0
- package/src/chat/logic/welcome.ts +3 -0
- package/src/chat/logic/workflow.ts +26 -7
- package/src/chat/mentions.ts +56 -0
- package/src/chat/pending-prompts.ts +16 -0
- package/src/chat/persisted-json.ts +15 -0
- package/src/chat/preferences.ts +16 -0
- package/src/chat/prompt-hold.ts +2 -0
- package/src/chat/quote.ts +7 -0
- package/src/chat/reading-width.ts +1 -0
- package/src/chat/recent-messages.ts +5 -0
- package/src/chat/resume-compaction-dismissals.ts +1 -0
- package/src/chat/stash.ts +12 -0
- package/src/chat/subagent-conversation.ts +24 -4
- package/src/chat/subagent-list.ts +14 -0
- package/src/chat/subagent-support.ts +1 -0
- package/src/chat/subagent-view.ts +9 -0
- package/src/chat/thumbnails.ts +14 -0
- package/src/chat/timeline-flash.ts +2 -0
- package/src/chat/timeline-scroll.ts +23 -0
- package/src/chat/ui/AccountPill.tsx +4 -0
- package/src/chat/ui/AnsiOutput.tsx +1 -0
- package/src/chat/ui/BookmarkMarker.tsx +5 -0
- package/src/chat/ui/BookmarkSubmenu.tsx +1 -0
- package/src/chat/ui/ChatActivity.tsx +13 -0
- package/src/chat/ui/CodeBlock.tsx +8 -0
- package/src/chat/ui/Composer.tsx +27 -3
- package/src/chat/ui/ComposerInput.tsx +22 -0
- package/src/chat/ui/DiffPool.tsx +3 -0
- package/src/chat/ui/EditDiff.tsx +5 -0
- package/src/chat/ui/GoalDock.tsx +13 -1
- package/src/chat/ui/ImageView.tsx +11 -0
- package/src/chat/ui/LimitState.tsx +23 -6
- package/src/chat/ui/Markdown.tsx +41 -0
- package/src/chat/ui/MermaidBlock.tsx +16 -0
- package/src/chat/ui/MessageActions.tsx +8 -0
- package/src/chat/ui/ModelMarks.tsx +1 -0
- package/src/chat/ui/Pickers.tsx +30 -1
- package/src/chat/ui/PromptComposer.tsx +2 -0
- package/src/chat/ui/PromptEditor.tsx +136 -0
- package/src/chat/ui/QuoteButton.tsx +12 -0
- package/src/chat/ui/ReferenceChip.tsx +3 -0
- package/src/chat/ui/ResumeCompactionDock.tsx +1 -0
- package/src/chat/ui/RowTime.tsx +1 -0
- package/src/chat/ui/RunSettings.tsx +38 -0
- package/src/chat/ui/Scrubber.tsx +14 -0
- package/src/chat/ui/SessionLine.tsx +1 -0
- package/src/chat/ui/ShellCommand.tsx +32 -0
- package/src/chat/ui/SubagentControls.tsx +7 -0
- package/src/chat/ui/SubagentInfo.tsx +1 -0
- package/src/chat/ui/SubagentStopButton.tsx +6 -0
- package/src/chat/ui/SubagentTimeline.tsx +10 -0
- package/src/chat/ui/Timeline.tsx +141 -1
- package/src/chat/ui/TimelineMenu.tsx +5 -0
- package/src/chat/ui/UnifiedDiff.tsx +6 -0
- package/src/chat/ui/UploadThumb.tsx +2 -0
- package/src/chat/ui/VisualDialogs.tsx +3 -0
- package/src/chat/ui/VisualFrame.tsx +15 -0
- package/src/chat/ui/Welcome.tsx +1 -0
- package/src/chat/ui/chip-clipboard.ts +20 -0
- package/src/chat/ui/code-lines.ts +14 -0
- package/src/chat/ui/code-theme.ts +1 -0
- package/src/chat/ui/composer/ComposerControls.tsx +70 -15
- package/src/chat/ui/composer/ComposerMenu.tsx +12 -0
- package/src/chat/ui/composer/DraftParts.tsx +2 -0
- package/src/chat/ui/composer/QueuedMessages.tsx +4 -0
- package/src/chat/ui/composer/chip-paste.ts +16 -0
- package/src/chat/ui/composer/chips.ts +6 -0
- package/src/chat/ui/composer/editor.ts +9 -0
- package/src/chat/ui/composer/insert.ts +2 -0
- package/src/chat/ui/composer/key-handler.ts +42 -9
- package/src/chat/ui/composer/keys.ts +23 -0
- package/src/chat/ui/composer/placeholder.ts +6 -0
- package/src/chat/ui/composer/prompt-picks.ts +18 -0
- package/src/chat/ui/composer/surface.ts +5 -0
- package/src/chat/ui/composer/use-chat-controls.ts +13 -0
- package/src/chat/ui/composer/use-compaction-offer.ts +3 -0
- package/src/chat/ui/composer/use-composer-menus.ts +20 -275
- package/src/chat/ui/composer/use-composer-submit.ts +27 -0
- package/src/chat/ui/composer/use-continuable-turn.ts +3 -5
- package/src/chat/ui/composer/use-draft-files.ts +24 -0
- package/src/chat/ui/composer/use-effort-stepper.ts +8 -0
- package/src/chat/ui/composer/use-notice.ts +4 -1
- package/src/chat/ui/composer/use-pending-requests.ts +3 -0
- package/src/chat/ui/composer/use-prompt-history.ts +20 -11
- package/src/chat/ui/composer/use-prompt-hold.ts +3 -0
- package/src/chat/ui/composer/use-prompt-menus.ts +361 -0
- package/src/chat/ui/composer/use-take-back.ts +20 -2
- package/src/chat/ui/diff/ApprovalReview.tsx +18 -15
- package/src/chat/ui/diff/DiffFallbackBoundary.tsx +1 -0
- package/src/chat/ui/diff/DiffOmitted.tsx +1 -0
- package/src/chat/ui/diff/DiffStack.tsx +2 -0
- package/src/chat/ui/diff/DiffUnavailable.tsx +1 -0
- package/src/chat/ui/diff/EditorEditDiff.tsx +13 -0
- package/src/chat/ui/diff/EditorPatchDiff.tsx +4 -0
- package/src/chat/ui/diff/LegacyDiffPool.tsx +2 -0
- package/src/chat/ui/diff/LegacyEditDiff.tsx +2 -0
- package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +8 -0
- package/src/chat/ui/diff/RawDiff.tsx +1 -0
- package/src/chat/ui/diff/ReviewDiff.tsx +1 -0
- package/src/chat/ui/diff/diff-source-budget.ts +8 -0
- package/src/chat/ui/diff/editor-edit-model.ts +4 -0
- package/src/chat/ui/diff/review-plan.ts +9 -0
- package/src/chat/ui/diff/review-settle.ts +1 -0
- package/src/chat/ui/diff/syntax-runtime.ts +52 -0
- package/src/chat/ui/diff/use-review-stack.ts +9 -0
- package/src/chat/ui/diff-syntax.ts +12 -0
- package/src/chat/ui/diff-theme.ts +2 -0
- package/src/chat/ui/file-links.ts +2 -0
- package/src/chat/ui/find-reveal.ts +1 -0
- package/src/chat/ui/full-diff.ts +1 -0
- package/src/chat/ui/highlighter.ts +29 -15
- package/src/chat/ui/icons.tsx +2 -4
- package/src/chat/ui/index.ts +7 -0
- package/src/chat/ui/intelligent-ui/UiBlockFrame.tsx +25 -0
- package/src/chat/ui/intelligent-ui/UiFallbackPart.tsx +1 -0
- package/src/chat/ui/intelligent-ui/UiReply.tsx +63 -0
- package/src/chat/ui/intelligent-ui/block-local.ts +5 -0
- package/src/chat/ui/intelligent-ui/chart-data.ts +15 -0
- package/src/chat/ui/intelligent-ui/node-text.ts +17 -0
- package/src/chat/ui/intelligent-ui/renderers/binding.ts +1 -0
- package/src/chat/ui/intelligent-ui/renderers/chart.tsx +31 -0
- package/src/chat/ui/intelligent-ui/renderers/choices.tsx +4 -0
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +18 -0
- package/src/chat/ui/intelligent-ui/renderers/data.tsx +11 -0
- package/src/chat/ui/intelligent-ui/renderers/inputs.tsx +13 -0
- package/src/chat/ui/intelligent-ui/renderers/links.tsx +9 -0
- package/src/chat/ui/intelligent-ui/renderers/map-slots.ts +15 -0
- package/src/chat/ui/intelligent-ui/renderers/map-style.ts +15 -0
- package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +48 -0
- package/src/chat/ui/intelligent-ui/renderers/map.tsx +20 -0
- package/src/chat/ui/intelligent-ui/renderers/place-point.ts +3 -0
- package/src/chat/ui/intelligent-ui/renderers/structure.tsx +3 -0
- package/src/chat/ui/intelligent-ui/renderers/text.tsx +8 -0
- package/src/chat/ui/intelligent-ui/reply-parts.ts +5 -0
- package/src/chat/ui/intelligent-ui/table-data.ts +17 -0
- package/src/chat/ui/intelligent-ui/use-in-view.ts +4 -0
- package/src/chat/ui/intelligent-ui/use-later.ts +4 -0
- package/src/chat/ui/intelligent-ui/use-truncated.ts +5 -0
- package/src/chat/ui/intelligent-ui/use-ui-links.ts +29 -0
- package/src/chat/ui/intelligent-ui/use-ui-queries.ts +60 -0
- package/src/chat/ui/markdown-blocks.ts +64 -0
- package/src/chat/ui/mermaid.ts +4 -0
- package/src/chat/ui/quote-selection.ts +10 -0
- package/src/chat/ui/rehype-chips.ts +5 -0
- package/src/chat/ui/rehype-fade.ts +2 -0
- package/src/chat/ui/remark-html-as-text.ts +5 -0
- package/src/chat/ui/reveal.ts +18 -0
- package/src/chat/ui/rows/ForksRow.tsx +5 -0
- package/src/chat/ui/rows/GeneratedImageRow.tsx +10 -0
- package/src/chat/ui/rows/MessageRows.tsx +29 -5
- package/src/chat/ui/rows/RowContainer.tsx +1 -0
- package/src/chat/ui/rows/Rows.tsx +2 -0
- package/src/chat/ui/rows/SubagentRow.tsx +13 -0
- package/src/chat/ui/rows/TaskRow.tsx +7 -0
- package/src/chat/ui/rows/VisualRow.tsx +4 -0
- package/src/chat/ui/rows/WorkRows.tsx +46 -0
- package/src/chat/ui/rows/WorkflowRow.tsx +10 -0
- package/src/chat/ui/rows/row-rhythm.ts +7 -5
- package/src/chat/ui/theme-watch.ts +8 -7
- package/src/chat/ui/thread-references.ts +7 -0
- package/src/chat/ui/use-diff-source-tokens.ts +8 -0
- package/src/chat/ui/useToggleSet.ts +3 -0
- package/src/chat/ui/visual-theme.ts +30 -0
- package/src/chat/visual-bridge.ts +23 -0
- package/src/chat/visual-viewport.ts +12 -0
- package/src/host-hooks.ts +15 -5
- package/src/host.ts +29 -1
- package/src/index.ts +5 -0
- package/src/lazy.tsx +9 -0
- package/src/locales/en/agent-chat.ts +1 -0
- package/src/locales/nl/agent-chat.ts +1 -0
- package/src/mounted-registry.ts +4 -0
- package/src/port-transport.ts +32 -0
- package/src/prompts/index.ts +2 -0
- package/src/prompts/logic/focus.ts +5 -0
- package/src/prompts/logic/keys.ts +12 -0
- package/src/prompts/logic/prompts.ts +8 -0
- package/src/prompts/logic/subjects.ts +8 -0
- package/src/prompts/logic/useFocusAfterAnswer.ts +2 -0
- package/src/prompts/logic/usePromptSession.ts +13 -1
- package/src/prompts/ui/ApprovalBody.tsx +2 -0
- package/src/prompts/ui/PromptActions.tsx +2 -0
- package/src/prompts/ui/PromptCard.tsx +6 -0
- package/src/prompts/ui/PromptView.tsx +6 -0
- package/src/prompts/ui/QuestionBody.tsx +11 -0
- package/src/providers/AccountColors.tsx +1 -0
- package/src/providers/AccountDetail.tsx +7 -0
- package/src/providers/AccountVariables.tsx +2 -0
- package/src/providers/AddAccountForm.tsx +5 -1
- package/src/providers/CliDetail.tsx +6 -5
- package/src/providers/InstallPage.tsx +11 -0
- package/src/providers/ProviderList.tsx +3 -0
- package/src/providers/ProvidersPane.tsx +18 -0
- package/src/providers/account-actions.ts +10 -8
- package/src/providers/index.ts +1 -0
- package/src/providers/install-steps.ts +3 -0
- package/src/providers/pane-target.ts +5 -0
- package/src/providers/provider-abilities.ts +1 -0
- package/src/providers/provider-groups.ts +6 -0
- package/src/providers/variables.ts +12 -0
- package/src/scope.ts +2 -0
- package/src/state/chats.ts +61 -14
- package/src/state/index.ts +2 -0
- package/src/state/provider-accounts.ts +7 -9
- package/src/state/providers.ts +1 -0
- package/src/state/usage.ts +6 -0
- package/src/storage.ts +18 -0
- package/src/testing/prompts.ts +5 -0
- package/src/theme.css +3 -0
- package/src/transport.ts +18 -0
- package/src/usage/ChartLogo.tsx +12 -0
- package/src/usage/LimitsList.tsx +7 -8
- package/src/usage/UsageBreakdown.tsx +11 -4
- package/src/usage/UsageChart.tsx +5 -0
- package/src/usage/UsageLimits.tsx +10 -7
- package/src/usage/UsageLimitsCard.tsx +2 -0
- package/src/usage/UsagePage.tsx +16 -19
- package/src/usage/UsageSummary.tsx +4 -5
- package/src/usage/UsageTiles.tsx +2 -0
- package/src/usage/format.ts +7 -0
- package/src/usage/limit-groups.ts +14 -0
- package/src/usage/limits.ts +11 -13
- package/src/usage/money.ts +1 -0
- package/src/usage/summary.ts +15 -7
|
@@ -39,6 +39,7 @@ export function BookmarkMarker({ chatId, itemId, bookmark }: BookmarkMarkerProps
|
|
|
39
39
|
initial={bookmark?.name ?? ''}
|
|
40
40
|
onDone={(name) => {
|
|
41
41
|
useBookmarkNaming.getState().close();
|
|
42
|
+
|
|
42
43
|
if (name !== null) {
|
|
43
44
|
void nameBookmark(scope, host, chatId, itemId, name, bookmark?.name);
|
|
44
45
|
}
|
|
@@ -73,6 +74,7 @@ function NameField({ initial, onDone }: { initial: string; onDone: (name: string
|
|
|
73
74
|
useEffect(() => {
|
|
74
75
|
ref.current?.focus();
|
|
75
76
|
const frame = requestAnimationFrame(() => ref.current?.focus());
|
|
77
|
+
|
|
76
78
|
return () => cancelAnimationFrame(frame);
|
|
77
79
|
}, []);
|
|
78
80
|
|
|
@@ -80,6 +82,7 @@ function NameField({ initial, onDone }: { initial: string; onDone: (name: string
|
|
|
80
82
|
if (settled.current) {
|
|
81
83
|
return;
|
|
82
84
|
}
|
|
85
|
+
|
|
83
86
|
settled.current = true;
|
|
84
87
|
onDone(name);
|
|
85
88
|
};
|
|
@@ -98,9 +101,11 @@ function NameField({ initial, onDone }: { initial: string; onDone: (name: string
|
|
|
98
101
|
onBlur={(e) => settle(e.currentTarget.value)}
|
|
99
102
|
onKeyDown={(e) => {
|
|
100
103
|
e.stopPropagation();
|
|
104
|
+
|
|
101
105
|
if (e.key === 'Enter') {
|
|
102
106
|
settle(e.currentTarget.value);
|
|
103
107
|
}
|
|
108
|
+
|
|
104
109
|
if (e.key === 'Escape') {
|
|
105
110
|
settle(null);
|
|
106
111
|
}
|
|
@@ -18,6 +18,7 @@ export function BookmarkSubmenu({ chatId }: { chatId: string }) {
|
|
|
18
18
|
const host = useChatHost();
|
|
19
19
|
const place = useHostChatPlace(chatId);
|
|
20
20
|
const sorted = bookmarksInThreadOrder(bookmarks ?? [], order ?? []);
|
|
21
|
+
|
|
21
22
|
if (sorted.length === 0) {
|
|
22
23
|
return null;
|
|
23
24
|
}
|
|
@@ -36,28 +36,37 @@ export function ChatActivity({ chatId }: { chatId: string }) {
|
|
|
36
36
|
const tasks = useHostTasks(id);
|
|
37
37
|
// The infos of these sub-agents' own chats, so the info of any other chat changing does not draw this again.
|
|
38
38
|
const children = useChats(useShallow((s) => subagents.map((item) => (item.childId === undefined ? undefined : s.statusByKey[keyOf(item.childId)]?.info))));
|
|
39
|
+
|
|
39
40
|
const progress = progressOf(
|
|
40
41
|
subagents.map((item, index) => {
|
|
41
42
|
const taskId = taskIdOf(item);
|
|
43
|
+
|
|
42
44
|
return taskRowStateOf(item, taskId === null ? null : (tasks?.[taskId] ?? null), children[index]);
|
|
43
45
|
})
|
|
44
46
|
);
|
|
47
|
+
|
|
45
48
|
const words = subagents.map((item) => {
|
|
46
49
|
const taskId = taskIdOf(item);
|
|
50
|
+
|
|
47
51
|
return statusWordOf(item, taskId === null ? null : (tasks?.[taskId] ?? null));
|
|
48
52
|
});
|
|
53
|
+
|
|
49
54
|
const background = useChatRow(chatId, (row) => row?.info.background) ?? NO_TASKS;
|
|
55
|
+
|
|
50
56
|
if (subagents.length === 0 && background.length === 0) {
|
|
51
57
|
return null;
|
|
52
58
|
}
|
|
59
|
+
|
|
53
60
|
const { shells, monitors } = backgroundCounts(background);
|
|
54
61
|
const Slot = host.SubagentSlot;
|
|
55
62
|
const counting = progress.active > 0 && progress.total > 1;
|
|
63
|
+
|
|
56
64
|
const label = counting
|
|
57
65
|
? [t('activity.progress', { done: progress.done, total: progress.total }), progress.waiting > 0 && t('activity.needsYou', { count: progress.waiting })]
|
|
58
66
|
.filter(Boolean)
|
|
59
67
|
.join(', ')
|
|
60
68
|
: t('activity.subagents', { count: badgeCountOf(words) });
|
|
69
|
+
|
|
61
70
|
return (
|
|
62
71
|
<div className="mb-3 flex flex-wrap items-center gap-2">
|
|
63
72
|
{subagents.length > 0 &&
|
|
@@ -94,6 +103,7 @@ export function ChatActivity({ chatId }: { chatId: string }) {
|
|
|
94
103
|
|
|
95
104
|
export function StatusIcon({ word }: { word: StatusWord }) {
|
|
96
105
|
const look = statusLookOf(word);
|
|
106
|
+
|
|
97
107
|
return <Icon icon={look.icon} size={14} className={clsx('shrink-0', look.tone, look.spins && 'animate-spin')} />;
|
|
98
108
|
}
|
|
99
109
|
|
|
@@ -142,6 +152,7 @@ function ActivityRow({
|
|
|
142
152
|
{time !== '' && <span className="shrink-0 text-xs text-text-faint tabular-nums">{time}</span>}
|
|
143
153
|
</>
|
|
144
154
|
);
|
|
155
|
+
|
|
145
156
|
// The stop is a button of its own beside the line, since a button cannot hold another.
|
|
146
157
|
return (
|
|
147
158
|
<div className={clsx('flex items-center gap-1 rounded-md', onOpen && 'hover:bg-surface-hover')}>
|
|
@@ -163,6 +174,7 @@ function SubagentRows({ chatId, items }: { chatId: string; items: readonly ChatS
|
|
|
163
174
|
1000,
|
|
164
175
|
items.some((item) => item.status === 'running')
|
|
165
176
|
);
|
|
177
|
+
|
|
166
178
|
return items.map((item) => <SubagentEntry key={item.id} chatId={chatId} item={item} now={now} />);
|
|
167
179
|
}
|
|
168
180
|
|
|
@@ -175,6 +187,7 @@ function SubagentEntry({ chatId, item, now }: { chatId: string; item: ChatSubage
|
|
|
175
187
|
const child = useChats((s) => (item.childId === undefined ? undefined : s.statusByKey[keyOf(item.childId)]?.info));
|
|
176
188
|
const word = statusWordOf(item, task);
|
|
177
189
|
const state = taskRowStateOf(item, task, child);
|
|
190
|
+
|
|
178
191
|
return (
|
|
179
192
|
<ActivityRow
|
|
180
193
|
icon={<StatusIcon word={word} />}
|
|
@@ -51,7 +51,9 @@ export function CodeBlock({ code, lang, actions, view }: { code: string; lang: s
|
|
|
51
51
|
if (copyState !== 'copied') {
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
+
|
|
54
55
|
const timer = setTimeout(() => setCopyState('idle'), COPIED_MS);
|
|
56
|
+
|
|
55
57
|
return () => clearTimeout(timer);
|
|
56
58
|
}, [copyState]);
|
|
57
59
|
|
|
@@ -59,8 +61,10 @@ export function CodeBlock({ code, lang, actions, view }: { code: string; lang: s
|
|
|
59
61
|
if (copying.current) {
|
|
60
62
|
return;
|
|
61
63
|
}
|
|
64
|
+
|
|
62
65
|
copying.current = true;
|
|
63
66
|
setCopyState('copying');
|
|
67
|
+
|
|
64
68
|
try {
|
|
65
69
|
// The best-effort clipboard helper cannot distinguish a refusal from success.
|
|
66
70
|
await navigator.clipboard.writeText(code);
|
|
@@ -76,16 +80,20 @@ export function CodeBlock({ code, lang, actions, view }: { code: string; lang: s
|
|
|
76
80
|
if (tokenizer !== null) {
|
|
77
81
|
return;
|
|
78
82
|
}
|
|
83
|
+
|
|
79
84
|
let cancelled = false;
|
|
85
|
+
|
|
80
86
|
Promise.all([highlighter.loadLanguage(lang), highlighter.loadTheme(theme, custom)])
|
|
81
87
|
.then(() => !cancelled && setLoaded(`${lang}:${theme}`))
|
|
82
88
|
.catch(() => !cancelled && setLoaded('failed'));
|
|
89
|
+
|
|
83
90
|
return () => {
|
|
84
91
|
cancelled = true;
|
|
85
92
|
};
|
|
86
93
|
}, [highlighter, lang, theme, custom, tokenizer]);
|
|
87
94
|
|
|
88
95
|
const pending = (tokenizer === null || tokens === null) && loaded !== 'failed';
|
|
96
|
+
|
|
89
97
|
return (
|
|
90
98
|
<div className="chat-code" data-copy-state={copyState}>
|
|
91
99
|
{view ?? (
|
package/src/chat/ui/Composer.tsx
CHANGED
|
@@ -44,7 +44,7 @@ import { usePromptHistory } from './composer/use-prompt-history';
|
|
|
44
44
|
import { usePromptHold } from './composer/use-prompt-hold';
|
|
45
45
|
import { surfacePartOf } from './composer/surface';
|
|
46
46
|
import { useTakeBack } from './composer/use-take-back';
|
|
47
|
-
import { useHostExtraPrompts, useHostSendDelivery } from '../../host-hooks';
|
|
47
|
+
import { useHostComposerSendActions, useHostExtraPrompts, useHostSendDelivery } from '../../host-hooks';
|
|
48
48
|
|
|
49
49
|
interface ComposerProps {
|
|
50
50
|
chatId: string;
|
|
@@ -70,9 +70,11 @@ function sendLabelKey(busy: boolean, steerable: boolean, delivery: 'queue' | 'st
|
|
|
70
70
|
if (!busy) {
|
|
71
71
|
return 'composer.send';
|
|
72
72
|
}
|
|
73
|
+
|
|
73
74
|
if (!steerable) {
|
|
74
75
|
return 'composer.queueButton';
|
|
75
76
|
}
|
|
77
|
+
|
|
76
78
|
return delivery === 'steer' ? 'composer.steerButton' : 'composer.queueWithSteerButton';
|
|
77
79
|
}
|
|
78
80
|
|
|
@@ -96,6 +98,7 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
96
98
|
const notice = useNotice();
|
|
97
99
|
const history = usePromptHistory(chatId, box.setText);
|
|
98
100
|
const menus = useComposerMenus({ chatId, info, capabilities, providerName: provider?.name, draft: box, inputRef });
|
|
101
|
+
|
|
99
102
|
const files = useDraftFiles({
|
|
100
103
|
capabilities,
|
|
101
104
|
providerName: provider?.name,
|
|
@@ -107,7 +110,9 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
107
110
|
referables: menus.referables.chatsOnly ? menus.referables.items.filter((item) => item.kind === 'chat') : menus.referables.items,
|
|
108
111
|
referenceChips: menus.referenceChips
|
|
109
112
|
});
|
|
113
|
+
|
|
110
114
|
const controls = useChatControls({ chatId, info, notice, onRetarget });
|
|
115
|
+
|
|
111
116
|
useEffortStepper({
|
|
112
117
|
chatId,
|
|
113
118
|
info,
|
|
@@ -116,11 +121,14 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
116
121
|
controls,
|
|
117
122
|
setNotice: notice.setNotice
|
|
118
123
|
});
|
|
124
|
+
|
|
119
125
|
const guard = promptGuard(withQuote(draft.quote, draft.text));
|
|
120
126
|
const continuable = useContinuableTurn(chatId, info);
|
|
121
127
|
// The stopped turn something went out for, since the chat takes a moment to answer and Continue must not stand there meanwhile.
|
|
122
128
|
const [sentFor, setSentFor] = useState<string | null>(null);
|
|
123
129
|
const extraPrompts = useHostExtraPrompts(scope.id, chatId);
|
|
130
|
+
const sendActions = useHostComposerSendActions(scope.id, chatId);
|
|
131
|
+
|
|
124
132
|
const { submit, continueTurn, restoreStashed, toggleStash } = useComposerSubmit({
|
|
125
133
|
chatId,
|
|
126
134
|
writable,
|
|
@@ -137,6 +145,7 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
137
145
|
onSend: (text, extras) => {
|
|
138
146
|
setSentFor(continuable);
|
|
139
147
|
const sent = onSend(text, extras);
|
|
148
|
+
|
|
140
149
|
// A send the host did not take leaves Continue where it was; the original promise still reaches its caller.
|
|
141
150
|
void Promise.resolve(sent).then(
|
|
142
151
|
(taken) => {
|
|
@@ -146,12 +155,15 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
146
155
|
},
|
|
147
156
|
(error: unknown) => {
|
|
148
157
|
setSentFor(null);
|
|
158
|
+
|
|
149
159
|
throw error;
|
|
150
160
|
}
|
|
151
161
|
);
|
|
162
|
+
|
|
152
163
|
return sent;
|
|
153
164
|
}
|
|
154
165
|
});
|
|
166
|
+
|
|
155
167
|
const { takingBack, takeBack } = useTakeBack({
|
|
156
168
|
chatId,
|
|
157
169
|
draft: box,
|
|
@@ -161,16 +173,19 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
161
173
|
inputRef.current?.focus();
|
|
162
174
|
}
|
|
163
175
|
});
|
|
176
|
+
|
|
164
177
|
const pending = usePendingRequests(chatId);
|
|
165
178
|
const compactionOffer = useCompactionOffer(chatId, info, capabilities?.compaction);
|
|
166
179
|
const placeholder = useHintedPlaceholder({ chatId, disabled, readOnly, mentionable: capabilities?.mentions !== false, hasSkills: menus.hasSkills });
|
|
167
180
|
const editorExtensions = [chipDecorations({ mentions: draft.mentions, skills: draft.skills, references: menus.referenceChips }), LEAVE_DROPS_TO_THE_CARD];
|
|
181
|
+
|
|
168
182
|
/* The timeline owns the scroller; this is the one bit of it the composer needs to know. */
|
|
169
183
|
const atEnd = useSyncExternalStore(
|
|
170
184
|
subscribeTimelineEnd,
|
|
171
185
|
() => timelineAtEnd(chatId),
|
|
172
186
|
() => true
|
|
173
187
|
);
|
|
188
|
+
|
|
174
189
|
const queue = info.queue ?? [];
|
|
175
190
|
const empty = isEmptyDraft(draft);
|
|
176
191
|
|
|
@@ -189,7 +204,6 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
189
204
|
history,
|
|
190
205
|
noteKey: files.noteKey,
|
|
191
206
|
toggleStash,
|
|
192
|
-
setText: (next) => box.setText(next),
|
|
193
207
|
submit
|
|
194
208
|
});
|
|
195
209
|
|
|
@@ -201,6 +215,7 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
201
215
|
if (!writable || event.button !== 0 || event.defaultPrevented || surfacePartOf(event.target, event.currentTarget) !== 'surface') {
|
|
202
216
|
return;
|
|
203
217
|
}
|
|
218
|
+
|
|
204
219
|
// Nothing around the field selects, so the default would only blur it on the way, closing its picker and lifting a held prompt card.
|
|
205
220
|
event.preventDefault();
|
|
206
221
|
inputRef.current?.setCaret(Infinity);
|
|
@@ -336,7 +351,16 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
336
351
|
onContinue:
|
|
337
352
|
continuable !== null && continuable !== sentFor && empty && writable && pending.length === 0 && extraPrompts.length === 0
|
|
338
353
|
? continueTurn
|
|
339
|
-
: null
|
|
354
|
+
: null,
|
|
355
|
+
actions: sendActions,
|
|
356
|
+
draft: {
|
|
357
|
+
scopeId: scope.id,
|
|
358
|
+
chatId,
|
|
359
|
+
text: withQuote(draft.quote, draft.text.trim()),
|
|
360
|
+
provider: info.provider,
|
|
361
|
+
selection: info.selection,
|
|
362
|
+
runtimeMode: info.runtimeMode
|
|
363
|
+
}
|
|
340
364
|
}}
|
|
341
365
|
dictationToolbar={setDictationToolbar}
|
|
342
366
|
onFiles={(picked) => {
|
|
@@ -69,12 +69,14 @@ export function ComposerInput({
|
|
|
69
69
|
const hostRef = useRef<HTMLDivElement>(null);
|
|
70
70
|
const targetRef = useRef<HTMLDivElement>(null);
|
|
71
71
|
const viewRef = useRef<EditorView | null>(null);
|
|
72
|
+
|
|
72
73
|
const [compartments] = useState(() => ({
|
|
73
74
|
attributes: new Compartment(),
|
|
74
75
|
editable: new Compartment(),
|
|
75
76
|
placeholder: new Compartment(),
|
|
76
77
|
extensions: new Compartment()
|
|
77
78
|
}));
|
|
79
|
+
|
|
78
80
|
const latest = useRef({ value, handlers });
|
|
79
81
|
// What the editor last reported. The parent handing that back is catching up, not setting a value of its own.
|
|
80
82
|
const reported = useRef(value);
|
|
@@ -85,10 +87,13 @@ export function ComposerInput({
|
|
|
85
87
|
|
|
86
88
|
useLayoutEffect(() => {
|
|
87
89
|
const host = hostRef.current;
|
|
90
|
+
|
|
88
91
|
if (!host) {
|
|
89
92
|
return;
|
|
90
93
|
}
|
|
94
|
+
|
|
91
95
|
const initial = latest.current.value;
|
|
96
|
+
|
|
92
97
|
const view = new EditorView({
|
|
93
98
|
parent: host,
|
|
94
99
|
state: EditorState.create({
|
|
@@ -109,24 +114,30 @@ export function ComposerInput({
|
|
|
109
114
|
cut: (event, target) => latest.current.handlers.onCopy?.(event, target) ?? false,
|
|
110
115
|
compositionstart: () => {
|
|
111
116
|
latest.current.handlers.onComposing?.(true);
|
|
117
|
+
|
|
112
118
|
return false;
|
|
113
119
|
},
|
|
114
120
|
compositionend: () => {
|
|
115
121
|
latest.current.handlers.onComposing?.(false);
|
|
122
|
+
|
|
116
123
|
return false;
|
|
117
124
|
}
|
|
118
125
|
})
|
|
119
126
|
),
|
|
120
127
|
EditorView.updateListener.of((update) => {
|
|
121
128
|
const current = latest.current.handlers;
|
|
129
|
+
|
|
122
130
|
if (update.focusChanged && !update.view.hasFocus) {
|
|
123
131
|
current.onBlur?.();
|
|
124
132
|
}
|
|
133
|
+
|
|
125
134
|
if ((!update.docChanged && !update.selectionSet) || update.transactions.some((tr) => tr.annotation(externalChange))) {
|
|
126
135
|
return;
|
|
127
136
|
}
|
|
137
|
+
|
|
128
138
|
const text = update.state.doc.toString();
|
|
129
139
|
const { from, to } = update.state.selection.main;
|
|
140
|
+
|
|
130
141
|
if (update.docChanged) {
|
|
131
142
|
reported.current = text;
|
|
132
143
|
current.onChange(text, { from, to }, update.state);
|
|
@@ -137,7 +148,9 @@ export function ComposerInput({
|
|
|
137
148
|
]
|
|
138
149
|
})
|
|
139
150
|
});
|
|
151
|
+
|
|
140
152
|
viewRef.current = view;
|
|
153
|
+
|
|
141
154
|
return () => {
|
|
142
155
|
view.destroy();
|
|
143
156
|
viewRef.current = null;
|
|
@@ -158,14 +171,18 @@ export function ComposerInput({
|
|
|
158
171
|
|
|
159
172
|
useLayoutEffect(() => {
|
|
160
173
|
const view = viewRef.current;
|
|
174
|
+
|
|
161
175
|
if (!view || value === reported.current) {
|
|
162
176
|
return;
|
|
163
177
|
}
|
|
178
|
+
|
|
164
179
|
reported.current = value;
|
|
165
180
|
const doc = view.state.doc.toString();
|
|
181
|
+
|
|
166
182
|
if (value === doc) {
|
|
167
183
|
return;
|
|
168
184
|
}
|
|
185
|
+
|
|
169
186
|
view.dispatch({
|
|
170
187
|
changes: { from: 0, to: doc.length, insert: value },
|
|
171
188
|
selection: { anchor: value.length },
|
|
@@ -179,17 +196,21 @@ export function ComposerInput({
|
|
|
179
196
|
focus: () => viewRef.current?.focus(),
|
|
180
197
|
setCaret: (pos: number) => {
|
|
181
198
|
const view = viewRef.current;
|
|
199
|
+
|
|
182
200
|
if (!view) {
|
|
183
201
|
return;
|
|
184
202
|
}
|
|
203
|
+
|
|
185
204
|
view.dispatch({ selection: { anchor: Math.min(pos, view.state.doc.length) }, scrollIntoView: true });
|
|
186
205
|
view.focus();
|
|
187
206
|
},
|
|
188
207
|
insert: (text: string) => {
|
|
189
208
|
const view = viewRef.current;
|
|
209
|
+
|
|
190
210
|
if (!view) {
|
|
191
211
|
return;
|
|
192
212
|
}
|
|
213
|
+
|
|
193
214
|
view.dispatch(insertAtSelection(view.state, text));
|
|
194
215
|
view.focus();
|
|
195
216
|
}
|
|
@@ -198,6 +219,7 @@ export function ComposerInput({
|
|
|
198
219
|
);
|
|
199
220
|
|
|
200
221
|
const Dictation = dictation.composer?.Control;
|
|
222
|
+
|
|
201
223
|
return (
|
|
202
224
|
<div ref={targetRef} className="min-w-0">
|
|
203
225
|
<div ref={hostRef} className={className} />
|
package/src/chat/ui/DiffPool.tsx
CHANGED
|
@@ -9,9 +9,11 @@ const POOL_SIZE = 2;
|
|
|
9
9
|
function ThemeSync() {
|
|
10
10
|
const pool = useWorkerPool();
|
|
11
11
|
const theme = useDiffTheme();
|
|
12
|
+
|
|
12
13
|
useEffect(() => {
|
|
13
14
|
void pool?.setRenderOptions({ theme });
|
|
14
15
|
}, [pool, theme]);
|
|
16
|
+
|
|
15
17
|
return null;
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -21,6 +23,7 @@ function ThemeSync() {
|
|
|
21
23
|
*/
|
|
22
24
|
export default function DiffPool({ workerFactory, children }: { workerFactory: () => Worker; children: ReactNode }) {
|
|
23
25
|
const theme = useDiffTheme();
|
|
26
|
+
|
|
24
27
|
return (
|
|
25
28
|
<WorkerPoolContextProvider
|
|
26
29
|
poolOptions={{
|
package/src/chat/ui/EditDiff.tsx
CHANGED
|
@@ -20,6 +20,7 @@ export default function EditDiff({ change, allowEditor = true, maxHeight }: { ch
|
|
|
20
20
|
const legacyMode = !allowEditor || loadEngine === undefined;
|
|
21
21
|
const legacyAllowed = legacyMode && legacyDiffBudget(change.before, change.after);
|
|
22
22
|
const omitted = <DiffOmitted path={change.path} />;
|
|
23
|
+
|
|
23
24
|
const fallback = legacyAllowed ? (
|
|
24
25
|
<DiffFallbackBoundary fallback={omitted} resetKeys={[change.path, change.before, change.after]}>
|
|
25
26
|
<LazyBoundary fallback={<div className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</div>}>
|
|
@@ -29,13 +30,17 @@ export default function EditDiff({ change, allowEditor = true, maxHeight }: { ch
|
|
|
29
30
|
) : (
|
|
30
31
|
omitted
|
|
31
32
|
);
|
|
33
|
+
|
|
32
34
|
if (!sourceAllowed) {
|
|
33
35
|
return omitted;
|
|
34
36
|
}
|
|
37
|
+
|
|
35
38
|
if (legacyMode) {
|
|
36
39
|
return fallback;
|
|
37
40
|
}
|
|
41
|
+
|
|
38
42
|
const unavailable = <DiffUnavailable path={change.path} />;
|
|
43
|
+
|
|
39
44
|
return (
|
|
40
45
|
<DiffFallbackBoundary fallback={unavailable} resetKeys={[change.path, change.before, change.after, loadEngine]}>
|
|
41
46
|
<LazyBoundary fallback={<div className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</div>}>
|
package/src/chat/ui/GoalDock.tsx
CHANGED
|
@@ -11,13 +11,16 @@ import { useChatScope } from '../../scope';
|
|
|
11
11
|
import { useChats } from '../../state/chats';
|
|
12
12
|
import { useChatActions } from '../actions';
|
|
13
13
|
import { goalView } from '../logic/goal';
|
|
14
|
+
import { errorMessage } from '../../transport';
|
|
14
15
|
|
|
15
16
|
/* How far the goal got, in what its CLI counts: the checks that sent the agent on, or the tokens it spent. */
|
|
16
17
|
function progressOf(goal: ChatGoal, t: TFunction<'agent-chat'>): string | null {
|
|
17
18
|
const parts: string[] = [];
|
|
19
|
+
|
|
18
20
|
if (goal.checks !== undefined && goal.checks > 0) {
|
|
19
21
|
parts.push(t('goal.checks', { count: goal.checks }));
|
|
20
22
|
}
|
|
23
|
+
|
|
21
24
|
if (goal.tokensUsed !== undefined && (goal.tokensUsed > 0 || goal.tokenBudget !== undefined)) {
|
|
22
25
|
parts.push(
|
|
23
26
|
goal.tokenBudget === undefined
|
|
@@ -25,6 +28,7 @@ function progressOf(goal: ChatGoal, t: TFunction<'agent-chat'>): string | null {
|
|
|
25
28
|
: t('goal.budget', { tokens: formatTokens(goal.tokensUsed), budget: formatTokens(goal.tokenBudget) })
|
|
26
29
|
);
|
|
27
30
|
}
|
|
31
|
+
|
|
28
32
|
return parts.length === 0 ? null : parts.join(' · ');
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -39,21 +43,27 @@ export function GoalDock({ chatId, info, goals }: { chatId: string; info: ChatIn
|
|
|
39
43
|
const actions = useChatActions();
|
|
40
44
|
const [changing, setChanging] = useState(false);
|
|
41
45
|
const view = goalView(info, goals, actions.goal !== undefined);
|
|
46
|
+
|
|
42
47
|
if (view === null) {
|
|
43
48
|
return null;
|
|
44
49
|
}
|
|
50
|
+
|
|
45
51
|
const { goal } = view;
|
|
46
52
|
const progress = progressOf(goal, t);
|
|
53
|
+
|
|
47
54
|
const act = (action: ChatGoalAction): void => {
|
|
48
55
|
if (!actions.goal) {
|
|
49
56
|
return;
|
|
50
57
|
}
|
|
58
|
+
|
|
51
59
|
setChanging(true);
|
|
60
|
+
|
|
52
61
|
actions
|
|
53
62
|
.goal(chatId, action)
|
|
54
|
-
.catch((e: unknown) => host.notify({ kind: 'error', title: t('goal.failed'), description:
|
|
63
|
+
.catch((e: unknown) => host.notify({ kind: 'error', title: t('goal.failed'), description: errorMessage(e) }))
|
|
55
64
|
.finally(() => setChanging(false));
|
|
56
65
|
};
|
|
66
|
+
|
|
57
67
|
return (
|
|
58
68
|
<div className="flex items-center gap-2 border-b border-border px-3.5 py-2.5">
|
|
59
69
|
<Icon icon={Target} size={16} className={clsx('shrink-0', goal.status === 'active' ? 'text-accent' : 'text-text-faint')} />
|
|
@@ -91,9 +101,11 @@ export function GoalPill({ chatId }: { chatId: string }) {
|
|
|
91
101
|
const { t } = useTranslation('agent-chat');
|
|
92
102
|
const { keyOf } = useChatScope();
|
|
93
103
|
const goal = useChats((s) => s.statusByKey[keyOf(chatId)]?.info.goal);
|
|
104
|
+
|
|
94
105
|
if (goal?.status !== 'active') {
|
|
95
106
|
return null;
|
|
96
107
|
}
|
|
108
|
+
|
|
97
109
|
return (
|
|
98
110
|
<Tooltip label={`${t('goal.status.active')}: ${goal.objective}`}>
|
|
99
111
|
<Pill tone="accent" icon={<Icon icon={Target} size={12} />}>
|
|
@@ -26,10 +26,13 @@ const START: View = { scale: 1, x: 0, y: 0 };
|
|
|
26
26
|
*/
|
|
27
27
|
function zoomed(view: View, factor: number, pointX: number, pointY: number): View {
|
|
28
28
|
const scale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, view.scale * factor));
|
|
29
|
+
|
|
29
30
|
if (scale === MIN_SCALE) {
|
|
30
31
|
return START;
|
|
31
32
|
}
|
|
33
|
+
|
|
32
34
|
const ratio = scale / view.scale;
|
|
35
|
+
|
|
33
36
|
return { scale, x: pointX - (pointX - view.x) * ratio, y: pointY - (pointY - view.y) * ratio };
|
|
34
37
|
}
|
|
35
38
|
|
|
@@ -62,9 +65,11 @@ function Lightbox({
|
|
|
62
65
|
/* Where the pointer sits against the middle of the frame, which is what the transform counts from. */
|
|
63
66
|
const pointIn = (event: { clientX: number; clientY: number }): { x: number; y: number } => {
|
|
64
67
|
const rect = frameRef.current?.getBoundingClientRect();
|
|
68
|
+
|
|
65
69
|
if (!rect) {
|
|
66
70
|
return { x: 0, y: 0 };
|
|
67
71
|
}
|
|
72
|
+
|
|
68
73
|
return { x: event.clientX - rect.left - rect.width / 2, y: event.clientY - rect.top - rect.height / 2 };
|
|
69
74
|
};
|
|
70
75
|
|
|
@@ -114,11 +119,13 @@ function Lightbox({
|
|
|
114
119
|
if (view.scale <= MIN_SCALE) {
|
|
115
120
|
return;
|
|
116
121
|
}
|
|
122
|
+
|
|
117
123
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
118
124
|
dragRef.current = { pointerId: e.pointerId, x: e.clientX - view.x, y: e.clientY - view.y };
|
|
119
125
|
}}
|
|
120
126
|
onPointerMove={(e) => {
|
|
121
127
|
const drag = dragRef.current;
|
|
128
|
+
|
|
122
129
|
if (drag?.pointerId === e.pointerId) {
|
|
123
130
|
setView((current) => ({ ...current, x: e.clientX - drag.x, y: e.clientY - drag.y }));
|
|
124
131
|
}
|
|
@@ -163,12 +170,15 @@ export interface ImageThumbProps {
|
|
|
163
170
|
export function ImageThumb({ source, alt, className, aspect, actions, open: openProp, onOpenChange }: ImageThumbProps) {
|
|
164
171
|
const [ownOpen, setOwnOpen] = useState(false);
|
|
165
172
|
const open = openProp ?? ownOpen;
|
|
173
|
+
|
|
166
174
|
const setOpen = (next: boolean): void => {
|
|
167
175
|
setOwnOpen(next);
|
|
168
176
|
onOpenChange?.(next);
|
|
169
177
|
};
|
|
178
|
+
|
|
170
179
|
const { url: src, failure } = source;
|
|
171
180
|
const ratio = aspect === undefined ? undefined : { aspectRatio: aspect };
|
|
181
|
+
|
|
172
182
|
if (src === null) {
|
|
173
183
|
return (
|
|
174
184
|
<span
|
|
@@ -186,6 +196,7 @@ export function ImageThumb({ source, alt, className, aspect, actions, open: open
|
|
|
186
196
|
</span>
|
|
187
197
|
);
|
|
188
198
|
}
|
|
199
|
+
|
|
189
200
|
return (
|
|
190
201
|
<>
|
|
191
202
|
<button
|