@adecore/agents-react 0.23.0 → 0.24.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 +14 -11
- package/dist/agents/AccountDot.js +3 -1
- package/dist/agents/accounts.d.ts +3 -2
- package/dist/agents/accounts.js +5 -6
- package/dist/chat/actions.d.ts +2 -2
- package/dist/chat/actions.js +8 -5
- package/dist/chat/bookmarks.d.ts +5 -3
- package/dist/chat/bookmarks.js +13 -14
- package/dist/chat/chat-client.d.ts +1 -0
- package/dist/chat/chat-client.js +7 -0
- package/dist/chat/composer-send.d.ts +3 -0
- package/dist/chat/composer-send.js +22 -0
- package/dist/chat/forks.js +22 -5
- package/dist/chat/index.d.ts +31 -0
- package/dist/chat/index.js +28 -0
- package/dist/chat/logic/embedded-code.d.ts +8 -0
- package/dist/chat/logic/embedded-code.js +371 -0
- package/dist/chat/logic/fork.js +1 -0
- package/dist/chat/logic/goal.d.ts +6 -0
- package/dist/chat/logic/goal.js +26 -0
- package/dist/chat/logic/scrubber.d.ts +1 -1
- package/dist/chat/logic/scrubber.js +6 -5
- package/dist/chat/logic/thought.d.ts +3 -0
- package/dist/chat/logic/thought.js +35 -0
- package/dist/chat/logic/thread-cards.js +2 -0
- package/dist/chat/logic/timeline.d.ts +5 -0
- package/dist/chat/logic/timeline.js +22 -1
- package/dist/chat/logic/tool-catalog.d.ts +1 -0
- package/dist/chat/logic/tool-catalog.js +3 -1
- package/dist/chat/logic/tools.d.ts +14 -0
- package/dist/chat/logic/tools.js +57 -0
- package/dist/chat/preferences.d.ts +6 -0
- package/dist/chat/preferences.js +19 -3
- package/dist/chat/reading-width.d.ts +9 -0
- package/dist/chat/reading-width.js +27 -0
- package/dist/chat/send-key.d.ts +10 -0
- package/dist/chat/send-key.js +24 -0
- package/dist/chat/ui/BookmarkMarker.js +4 -2
- package/dist/chat/ui/BookmarkSubmenu.js +4 -3
- package/dist/chat/ui/ChatActivity.js +14 -10
- package/dist/chat/ui/ChatReferenceChip.js +3 -4
- package/dist/chat/ui/CodeBlock.d.ts +2 -1
- package/dist/chat/ui/CodeBlock.js +14 -96
- package/dist/chat/ui/Composer.d.ts +1 -1
- package/dist/chat/ui/Composer.js +117 -906
- package/dist/chat/ui/ComposerInput.js +5 -4
- package/dist/chat/ui/EditDiff.js +3 -2
- package/dist/chat/ui/GoalDock.d.ts +9 -0
- package/dist/chat/ui/GoalDock.js +63 -0
- package/dist/chat/ui/LimitState.js +5 -3
- package/dist/chat/ui/Markdown.d.ts +2 -1
- package/dist/chat/ui/Markdown.js +70 -31
- package/dist/chat/ui/MermaidBlock.d.ts +3 -0
- package/dist/chat/ui/MermaidBlock.js +73 -0
- package/dist/chat/ui/MessageActions.js +12 -7
- package/dist/chat/ui/Pickers.js +6 -5
- package/dist/chat/ui/PromptComposer.js +4 -3
- package/dist/chat/ui/RowTime.d.ts +3 -0
- package/dist/chat/ui/RowTime.js +12 -0
- package/dist/chat/ui/RunSettings.js +5 -4
- package/dist/chat/ui/ShellCommand.d.ts +3 -0
- package/dist/chat/ui/ShellCommand.js +110 -0
- package/dist/chat/ui/SubagentInfo.js +4 -3
- package/dist/chat/ui/SubagentStopButton.js +4 -3
- package/dist/chat/ui/SubagentTimeline.js +4 -1
- package/dist/chat/ui/Timeline.js +70 -40
- package/dist/chat/ui/TimelineMenu.d.ts +2 -1
- package/dist/chat/ui/TimelineMenu.js +18 -8
- package/dist/chat/ui/UnifiedDiff.js +3 -2
- package/dist/chat/ui/VisualFrame.js +6 -7
- package/dist/chat/ui/code-theme.d.ts +2 -1
- package/dist/chat/ui/code-theme.js +4 -4
- package/dist/chat/ui/composer/ComposerControls.d.ts +27 -0
- package/dist/chat/ui/composer/ComposerControls.js +34 -0
- package/dist/chat/ui/composer/ComposerMenu.d.ts +4 -0
- package/dist/chat/ui/composer/ComposerMenu.js +46 -0
- package/dist/chat/ui/composer/DraftParts.d.ts +18 -0
- package/dist/chat/ui/composer/DraftParts.js +25 -0
- package/dist/chat/ui/composer/QueuedMessages.d.ts +10 -0
- package/dist/chat/ui/composer/QueuedMessages.js +20 -0
- package/dist/chat/ui/composer/key-handler.d.ts +20 -0
- package/dist/chat/ui/composer/key-handler.js +150 -0
- package/dist/chat/ui/composer/keys.d.ts +7 -2
- package/dist/chat/ui/composer/keys.js +19 -9
- package/dist/chat/ui/composer/placeholder.d.ts +9 -0
- package/dist/chat/ui/composer/placeholder.js +38 -0
- package/dist/chat/ui/composer/use-chat-controls.d.ts +28 -0
- package/dist/chat/ui/composer/use-chat-controls.js +112 -0
- package/dist/chat/ui/composer/use-compaction-offer.d.ts +2 -0
- package/dist/chat/ui/composer/use-compaction-offer.js +23 -0
- package/dist/chat/ui/composer/use-composer-draft.d.ts +14 -0
- package/dist/chat/ui/composer/use-composer-draft.js +39 -0
- package/dist/chat/ui/composer/use-composer-menus.d.ts +52 -0
- package/dist/chat/ui/composer/use-composer-menus.js +232 -0
- package/dist/chat/ui/composer/use-composer-submit.d.ts +32 -0
- package/dist/chat/ui/composer/use-composer-submit.js +113 -0
- package/dist/chat/ui/composer/use-draft-files.d.ts +27 -0
- package/dist/chat/ui/composer/use-draft-files.js +111 -0
- package/dist/chat/ui/composer/use-notice.d.ts +6 -0
- package/dist/chat/ui/composer/use-notice.js +18 -0
- package/dist/chat/ui/composer/use-pending-requests.d.ts +2 -0
- package/dist/chat/ui/composer/use-pending-requests.js +22 -0
- package/dist/chat/ui/composer/use-prompt-history.d.ts +8 -0
- package/dist/chat/ui/composer/use-prompt-history.js +57 -0
- package/dist/chat/ui/composer/use-prompt-hold.d.ts +6 -0
- package/dist/chat/ui/composer/use-prompt-hold.js +48 -0
- package/dist/chat/ui/composer/use-take-back.d.ts +13 -0
- package/dist/chat/ui/composer/use-take-back.js +82 -0
- package/dist/chat/ui/diff/EditorEditDiff.js +4 -3
- package/dist/chat/ui/diff/LegacyDiffPool.js +3 -2
- package/dist/chat/ui/diff/LegacyEditDiff.js +3 -2
- package/dist/chat/ui/diff/LegacyUnifiedDiff.js +3 -2
- package/dist/chat/ui/diff/syntax-runtime.d.ts +2 -1
- package/dist/chat/ui/diff/syntax-runtime.js +9 -5
- package/dist/chat/ui/diff-syntax.d.ts +2 -2
- package/dist/chat/ui/diff-syntax.js +1 -2
- package/dist/chat/ui/diff-theme.js +10 -9
- package/dist/chat/ui/file-links.d.ts +1 -1
- package/dist/chat/ui/file-links.js +7 -5
- package/dist/chat/ui/highlighter.d.ts +27 -0
- package/dist/chat/ui/highlighter.js +151 -0
- package/dist/chat/ui/index.d.ts +67 -0
- package/dist/chat/ui/index.js +64 -0
- package/dist/chat/ui/intelligent-ui/UiReply.js +3 -2
- package/dist/chat/ui/intelligent-ui/renderers/content.js +3 -2
- package/dist/chat/ui/intelligent-ui/use-ui-links.js +2 -2
- package/dist/chat/ui/intelligent-ui/use-ui-queries.js +4 -3
- package/dist/chat/ui/markdown-blocks.d.ts +8 -0
- package/dist/chat/ui/markdown-blocks.js +260 -12
- package/dist/chat/ui/mermaid.d.ts +23 -0
- package/dist/chat/ui/mermaid.js +93 -0
- package/dist/chat/ui/rows/ForksRow.js +5 -3
- package/dist/chat/ui/rows/GeneratedImageRow.js +6 -4
- package/dist/chat/ui/rows/MessageRows.d.ts +4 -0
- package/dist/chat/ui/rows/MessageRows.js +36 -13
- package/dist/chat/ui/rows/Rows.js +3 -1
- package/dist/chat/ui/rows/SubagentRow.js +3 -2
- package/dist/chat/ui/rows/VisualRow.js +3 -2
- package/dist/chat/ui/rows/WorkRows.d.ts +6 -3
- package/dist/chat/ui/rows/WorkRows.js +57 -20
- package/dist/chat/ui/rows/WorkflowRow.js +3 -2
- package/dist/chat/ui/timestamp-format.d.ts +1 -0
- package/dist/chat/ui/timestamp-format.js +2 -0
- package/dist/chat/ui/use-diff-source-tokens.js +6 -3
- package/dist/chat/ui/visual-theme.js +3 -2
- package/dist/host.d.ts +9 -6
- package/dist/host.js +19 -8
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -0
- package/dist/locales/en/agent-chat.d.ts +658 -0
- package/dist/locales/en/agent-chat.js +657 -0
- package/dist/locales/en/agent-prompts.d.ts +44 -0
- package/dist/locales/en/agent-prompts.js +43 -0
- package/dist/locales/en/agent-providers.d.ts +132 -0
- package/dist/locales/en/agent-providers.js +131 -0
- package/dist/locales/en/agent-usage.d.ts +132 -0
- package/dist/locales/en/agent-usage.js +131 -0
- package/dist/locales/nl/agent-chat.d.ts +658 -0
- package/dist/locales/nl/agent-chat.js +657 -0
- package/dist/locales/nl/agent-prompts.d.ts +44 -0
- package/dist/locales/nl/agent-prompts.js +43 -0
- package/dist/locales/nl/agent-providers.d.ts +132 -0
- package/dist/locales/nl/agent-providers.js +131 -0
- package/dist/locales/nl/agent-usage.d.ts +132 -0
- package/dist/locales/nl/agent-usage.js +131 -0
- package/dist/locales.js +9 -8
- package/dist/prompts/index.d.ts +11 -0
- package/dist/prompts/index.js +12 -0
- package/dist/prompts/logic/subjects.d.ts +2 -1
- package/dist/prompts/logic/subjects.js +6 -4
- package/dist/prompts/ui/ApprovalBody.js +6 -4
- package/dist/prompts/ui/PromptCard.js +5 -4
- package/dist/prompts/ui/PromptView.js +3 -2
- package/dist/prompts/ui/QuestionBody.js +3 -2
- package/dist/providers/AccountColors.js +2 -2
- package/dist/providers/AccountDetail.js +7 -6
- package/dist/providers/AccountVariables.js +3 -1
- package/dist/providers/AddAccountForm.js +3 -2
- package/dist/providers/ProvidersPane.js +4 -3
- package/dist/providers/account-actions.d.ts +4 -3
- package/dist/providers/account-actions.js +6 -7
- package/dist/providers/index.d.ts +16 -0
- package/dist/providers/index.js +17 -0
- package/dist/providers/provider-abilities.d.ts +2 -1
- package/dist/providers/provider-abilities.js +4 -0
- package/dist/state/chats.js +4 -2
- package/dist/state/index.d.ts +4 -0
- package/dist/state/index.js +5 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +2 -0
- package/dist/{prompts/logic/prompts.fixtures.d.ts → testing/prompts.d.ts} +1 -1
- package/dist/theme.css +13 -3
- package/dist/usage/UsageBreakdown.js +3 -2
- package/dist/usage/UsageLimits.js +4 -3
- package/dist/usage/UsagePage.js +3 -2
- package/dist/usage/index.d.ts +15 -0
- package/dist/usage/index.js +15 -0
- package/package.json +53 -1031
- package/src/agents/AccountDot.tsx +3 -1
- package/src/agents/accounts.ts +6 -6
- package/src/chat/actions.ts +8 -5
- package/src/chat/bookmarks.ts +23 -14
- package/src/chat/chat-client.ts +8 -0
- package/src/chat/composer-send.ts +27 -0
- package/src/chat/forks.ts +27 -6
- package/src/chat/index.ts +98 -0
- package/src/chat/logic/embedded-code.ts +409 -0
- package/src/chat/logic/fork.ts +1 -0
- package/src/chat/logic/goal.ts +33 -0
- package/src/chat/logic/scrubber.ts +6 -5
- package/src/chat/logic/thought.ts +40 -0
- package/src/chat/logic/thread-cards.ts +2 -0
- package/src/chat/logic/timeline.ts +25 -1
- package/src/chat/logic/tool-catalog.ts +5 -1
- package/src/chat/logic/tools.ts +76 -0
- package/src/chat/preferences.ts +26 -3
- package/src/chat/reading-width.ts +39 -0
- package/src/chat/send-key.ts +38 -0
- package/src/chat/ui/BookmarkMarker.tsx +4 -2
- package/src/chat/ui/BookmarkSubmenu.tsx +4 -3
- package/src/chat/ui/ChatActivity.tsx +14 -10
- package/src/chat/ui/ChatReferenceChip.tsx +3 -4
- package/src/chat/ui/CodeBlock.tsx +33 -124
- package/src/chat/ui/Composer.tsx +162 -1324
- package/src/chat/ui/ComposerInput.tsx +5 -4
- package/src/chat/ui/EditDiff.tsx +3 -2
- package/src/chat/ui/GoalDock.tsx +104 -0
- package/src/chat/ui/LimitState.tsx +5 -3
- package/src/chat/ui/Markdown.tsx +113 -39
- package/src/chat/ui/MermaidBlock.tsx +119 -0
- package/src/chat/ui/MessageActions.tsx +13 -8
- package/src/chat/ui/Pickers.tsx +8 -7
- package/src/chat/ui/PromptComposer.tsx +4 -3
- package/src/chat/ui/RowTime.tsx +21 -0
- package/src/chat/ui/RunSettings.tsx +9 -4
- package/src/chat/ui/ShellCommand.tsx +134 -0
- package/src/chat/ui/SubagentInfo.tsx +4 -3
- package/src/chat/ui/SubagentStopButton.tsx +4 -3
- package/src/chat/ui/SubagentTimeline.tsx +5 -1
- package/src/chat/ui/Timeline.tsx +167 -105
- package/src/chat/ui/TimelineMenu.tsx +42 -7
- package/src/chat/ui/UnifiedDiff.tsx +3 -2
- package/src/chat/ui/VisualFrame.tsx +6 -7
- package/src/chat/ui/code-theme.ts +4 -4
- package/src/chat/ui/composer/ComposerControls.tsx +147 -0
- package/src/chat/ui/composer/ComposerMenu.tsx +138 -0
- package/src/chat/ui/composer/DraftParts.tsx +86 -0
- package/src/chat/ui/composer/QueuedMessages.tsx +64 -0
- package/src/chat/ui/composer/key-handler.ts +174 -0
- package/src/chat/ui/composer/keys.ts +32 -10
- package/src/chat/ui/composer/placeholder.ts +48 -0
- package/src/chat/ui/composer/use-chat-controls.ts +134 -0
- package/src/chat/ui/composer/use-compaction-offer.ts +25 -0
- package/src/chat/ui/composer/use-composer-draft.ts +71 -0
- package/src/chat/ui/composer/use-composer-menus.ts +289 -0
- package/src/chat/ui/composer/use-composer-submit.ts +163 -0
- package/src/chat/ui/composer/use-draft-files.ts +135 -0
- package/src/chat/ui/composer/use-notice.ts +28 -0
- package/src/chat/ui/composer/use-pending-requests.ts +23 -0
- package/src/chat/ui/composer/use-prompt-history.ts +76 -0
- package/src/chat/ui/composer/use-prompt-hold.ts +58 -0
- package/src/chat/ui/composer/use-take-back.ts +91 -0
- package/src/chat/ui/diff/DiffFallbackBoundary.tsx +2 -2
- package/src/chat/ui/diff/EditorEditDiff.tsx +4 -3
- package/src/chat/ui/diff/LegacyDiffPool.tsx +3 -2
- package/src/chat/ui/diff/LegacyEditDiff.tsx +3 -2
- package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +3 -2
- package/src/chat/ui/diff/syntax-runtime.ts +10 -5
- package/src/chat/ui/diff-syntax.ts +2 -2
- package/src/chat/ui/diff-theme.ts +10 -9
- package/src/chat/ui/file-links.ts +7 -5
- package/src/chat/ui/highlighter.ts +185 -0
- package/src/chat/ui/index.ts +109 -0
- package/src/chat/ui/intelligent-ui/UiReply.tsx +5 -4
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +3 -2
- package/src/chat/ui/intelligent-ui/use-ui-links.ts +2 -2
- package/src/chat/ui/intelligent-ui/use-ui-queries.ts +4 -3
- package/src/chat/ui/markdown-blocks.ts +300 -12
- package/src/chat/ui/mermaid.ts +118 -0
- package/src/chat/ui/rows/ForksRow.tsx +5 -3
- package/src/chat/ui/rows/GeneratedImageRow.tsx +6 -4
- package/src/chat/ui/rows/MessageRows.tsx +73 -18
- package/src/chat/ui/rows/Rows.tsx +14 -1
- package/src/chat/ui/rows/SubagentRow.tsx +3 -2
- package/src/chat/ui/rows/VisualRow.tsx +3 -2
- package/src/chat/ui/rows/WorkRows.tsx +148 -47
- package/src/chat/ui/rows/WorkflowRow.tsx +3 -2
- package/src/chat/ui/timestamp-format.ts +2 -0
- package/src/chat/ui/use-diff-source-tokens.ts +10 -4
- package/src/chat/ui/visual-theme.ts +3 -2
- package/src/host.ts +31 -15
- package/src/index.ts +49 -0
- package/src/locales/en/agent-chat.ts +657 -0
- package/src/locales/en/agent-prompts.ts +43 -0
- package/src/locales/en/agent-providers.ts +131 -0
- package/src/locales/en/agent-usage.ts +131 -0
- package/src/locales/nl/agent-chat.ts +657 -0
- package/src/locales/nl/agent-prompts.ts +43 -0
- package/src/locales/nl/agent-providers.ts +131 -0
- package/src/locales/nl/agent-usage.ts +132 -0
- package/src/locales.ts +9 -8
- package/src/prompts/index.ts +35 -0
- package/src/prompts/logic/subjects.ts +12 -4
- package/src/prompts/ui/ApprovalBody.tsx +6 -4
- package/src/prompts/ui/PromptCard.tsx +11 -4
- package/src/prompts/ui/PromptView.tsx +3 -2
- package/src/prompts/ui/QuestionBody.tsx +3 -2
- package/src/providers/AccountColors.tsx +2 -2
- package/src/providers/AccountDetail.tsx +13 -7
- package/src/providers/AccountVariables.tsx +3 -1
- package/src/providers/AddAccountForm.tsx +3 -2
- package/src/providers/ProvidersPane.tsx +4 -3
- package/src/providers/account-actions.ts +7 -7
- package/src/providers/index.ts +17 -0
- package/src/providers/provider-abilities.ts +6 -1
- package/src/state/chats.ts +4 -2
- package/src/state/index.ts +39 -0
- package/src/testing/index.ts +2 -0
- package/src/{prompts/logic/prompts.fixtures.ts → testing/prompts.ts} +1 -1
- package/src/theme.css +13 -3
- package/src/usage/UsageBreakdown.tsx +3 -2
- package/src/usage/UsageLimits.tsx +4 -3
- package/src/usage/UsagePage.tsx +3 -2
- package/src/usage/index.ts +16 -0
- package/dist/locales/en/agent-chat.json +0 -597
- package/dist/locales/en/agent-prompts.json +0 -43
- package/dist/locales/en/agent-providers.json +0 -131
- package/dist/locales/en/agent-usage.json +0 -131
- package/dist/locales/nl/agent-chat.json +0 -597
- package/dist/locales/nl/agent-prompts.json +0 -43
- package/dist/locales/nl/agent-providers.json +0 -131
- package/dist/locales/nl/agent-usage.json +0 -131
- package/src/locales/en/agent-chat.json +0 -597
- package/src/locales/en/agent-prompts.json +0 -43
- package/src/locales/en/agent-providers.json +0 -131
- package/src/locales/en/agent-usage.json +0 -131
- package/src/locales/nl/agent-chat.json +0 -597
- package/src/locales/nl/agent-prompts.json +0 -43
- package/src/locales/nl/agent-providers.json +0 -131
- package/src/locales/nl/agent-usage.json +0 -131
- /package/dist/{prompts/logic/prompts.fixtures.js → testing/prompts.js} +0 -0
|
@@ -14,21 +14,22 @@ import type {
|
|
|
14
14
|
import { WAITING_NOTE_PREFIX } from '@adecore/agent-contracts';
|
|
15
15
|
import { fileBadge, formatBytes, isImageAttachment } from '../../attachments';
|
|
16
16
|
import { useChatRow, useCurrentItem } from '../../../state/chats';
|
|
17
|
-
import {
|
|
17
|
+
import { useChatHost } from '../../../host';
|
|
18
18
|
import { useChatScope } from '../../../scope';
|
|
19
19
|
import { splitQuote } from '../../quote';
|
|
20
20
|
import { jumpToTimelineItem } from '../../timeline-scroll';
|
|
21
21
|
import { useProviders } from '../../../state/providers';
|
|
22
22
|
import { ChatReferenceChip } from '../ChatReferenceChip';
|
|
23
23
|
import { ImageThumb } from '../ImageView';
|
|
24
|
-
import { MessageMarkdown, ReplyMarkdown } from '../Markdown';
|
|
24
|
+
import { Markdown, MessageMarkdown, ReplyMarkdown } from '../Markdown';
|
|
25
25
|
import { FadingWords } from '../FadingWords';
|
|
26
26
|
import { settledBlocksText } from '../markdown-blocks';
|
|
27
27
|
import { WHOLE_FADE_CLASS } from '../rehype-fade';
|
|
28
28
|
import { useRevealedText } from '../reveal';
|
|
29
29
|
import { formatAgo, formatElapsedShort, formatMoment, formatTokens } from '@adecore/ui/format';
|
|
30
|
-
import { Icon, Tooltip, useTickingText } from '@adecore/ui';
|
|
31
|
-
import {
|
|
30
|
+
import { Icon, MiddleTruncate, Tooltip, useTickingText } from '@adecore/ui';
|
|
31
|
+
import { thoughtLine, thoughtPreview } from '../../logic/thought';
|
|
32
|
+
import { toolSummary, toolSummaryIsPath } from '../../logic/tools';
|
|
32
33
|
import { ROW_GUTTER } from '../icons';
|
|
33
34
|
import { useOpenForFind } from '../find-reveal';
|
|
34
35
|
import { ReplyContext, UiReplyNavigationContext } from '../reply-context';
|
|
@@ -42,9 +43,10 @@ const USER_FOLD_CHARS = 600;
|
|
|
42
43
|
const FOLD = 'max-h-[10em] overflow-hidden [mask-image:linear-gradient(to_bottom,black_70%,transparent)]';
|
|
43
44
|
|
|
44
45
|
function useReplyAuthor(chatId: string) {
|
|
46
|
+
const host = useChatHost();
|
|
45
47
|
const { id } = useChatScope();
|
|
46
48
|
const context = useContext(ReplyContext);
|
|
47
|
-
const author =
|
|
49
|
+
const author = host.useReplyAuthor(id, context?.chatId ?? chatId);
|
|
48
50
|
return context !== null && context.chatId === undefined ? null : author;
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -53,8 +55,9 @@ function useReplyAuthor(chatId: string) {
|
|
|
53
55
|
* hands a link that opens a window to the system browser, which cannot reach a blob of this page.
|
|
54
56
|
*/
|
|
55
57
|
function AttachmentLink({ chatId, attachment }: { chatId: string; attachment: ChatAttachment }) {
|
|
58
|
+
const host = useChatHost();
|
|
56
59
|
const { id } = useChatScope();
|
|
57
|
-
const { url } =
|
|
60
|
+
const { url } = host.attachments.useUrl(id, chatId, attachment.id);
|
|
58
61
|
const badge = fileBadge(attachment.name);
|
|
59
62
|
return (
|
|
60
63
|
<Tooltip label={attachment.name}>
|
|
@@ -78,8 +81,9 @@ function AttachmentLink({ chatId, attachment }: { chatId: string; attachment: Ch
|
|
|
78
81
|
|
|
79
82
|
/* A picture attached to a message, which opens large. */
|
|
80
83
|
function AttachmentThumb({ chatId, attachment }: { chatId: string; attachment: ChatAttachment }) {
|
|
84
|
+
const host = useChatHost();
|
|
81
85
|
const { id } = useChatScope();
|
|
82
|
-
const source =
|
|
86
|
+
const source = host.attachments.useUrl(id, chatId, attachment.id);
|
|
83
87
|
return <ImageThumb source={source} alt={attachment.name} className="max-h-32 max-w-48 object-cover" />;
|
|
84
88
|
}
|
|
85
89
|
|
|
@@ -264,6 +268,7 @@ function Writing() {
|
|
|
264
268
|
* written fades anything: an old reply scrolled back into view just stands there.
|
|
265
269
|
*/
|
|
266
270
|
export function AssistantRow({ chatId, item: derived }: { chatId: string; item: ChatAssistantItem }) {
|
|
271
|
+
const host = useChatHost();
|
|
267
272
|
const item = useCurrentItem(chatId, derived);
|
|
268
273
|
const scope = useChatScope();
|
|
269
274
|
const context = useContext(ReplyContext);
|
|
@@ -271,7 +276,7 @@ export function AssistantRow({ chatId, item: derived }: { chatId: string; item:
|
|
|
271
276
|
() => (context === null && !item.parentToolUseId ? { scopeId: scope.id, chatId, itemId: item.id, streaming: item.streaming } : undefined),
|
|
272
277
|
[context, item.parentToolUseId, scope.id, chatId, item.id, item.streaming]
|
|
273
278
|
);
|
|
274
|
-
const mode =
|
|
279
|
+
const mode = host.useStreaming();
|
|
275
280
|
const [sawWriting] = useState(item.streaming);
|
|
276
281
|
const live = mode === 'words' && item.streaming;
|
|
277
282
|
const reveal = useRevealedText(item.text, live);
|
|
@@ -329,12 +334,14 @@ export function AssistantRow({ chatId, item: derived }: { chatId: string; item:
|
|
|
329
334
|
|
|
330
335
|
/*
|
|
331
336
|
* What the model thought before it answered. It shimmers while it streams and folds itself away
|
|
332
|
-
* once the answer starts, because the thought is worth a glance and rarely worth reading twice
|
|
337
|
+
* once the answer starts, because the thought is worth a glance and rarely worth reading twice:
|
|
338
|
+
* folded, it shows the heading it opens with or itself on one line, and opened, it reads as Markdown.
|
|
333
339
|
*/
|
|
334
340
|
export function ThinkingRow({ chatId, item: derived }: { chatId: string; item: ChatThinkingItem }) {
|
|
341
|
+
const host = useChatHost();
|
|
335
342
|
const { t } = useTranslation('agent-chat');
|
|
336
343
|
const item = useCurrentItem(chatId, derived);
|
|
337
|
-
const mode =
|
|
344
|
+
const mode = host.useStreaming();
|
|
338
345
|
const [open, setOpen] = useState(false);
|
|
339
346
|
const reveal = useRevealedText(item.text, mode === 'words' && item.streaming);
|
|
340
347
|
// A block at a time, the paragraphs of the thought that closed are shown as they land.
|
|
@@ -342,31 +349,72 @@ export function ThinkingRow({ chatId, item: derived }: { chatId: string; item: C
|
|
|
342
349
|
// Whole, the thought stays behind "Thinking…" until it is done and then folds like any other.
|
|
343
350
|
const shown = open || reveal.active || (settled !== null && settled !== '');
|
|
344
351
|
const text = settled ?? reveal.text;
|
|
352
|
+
const live = useMemo(() => (item.streaming && mode !== 'whole' ? thoughtLine(text) : ''), [item.streaming, mode, text]);
|
|
353
|
+
const preview = useMemo(() => (item.streaming ? '' : thoughtPreview(item.text)), [item.streaming, item.text]);
|
|
354
|
+
const duration = formatElapsedShort((item.endedAt ?? item.createdAt) - item.createdAt);
|
|
345
355
|
useOpenForFind(item.id, 'text', setOpen);
|
|
346
356
|
return (
|
|
347
357
|
<div data-find-item={item.id} className="-mx-1 px-1 pb-2">
|
|
348
|
-
<button
|
|
358
|
+
<button
|
|
359
|
+
className="flex w-full min-w-0 items-center gap-2 text-left text-xs text-text-muted hover:text-text"
|
|
360
|
+
disabled={item.streaming}
|
|
361
|
+
aria-expanded={item.streaming ? undefined : open}
|
|
362
|
+
onClick={() => setOpen((o) => !o)}
|
|
363
|
+
>
|
|
349
364
|
<span className={ROW_GUTTER}>
|
|
350
365
|
<Icon icon={Brain} size={12} />
|
|
351
366
|
</span>
|
|
352
367
|
{item.streaming ? (
|
|
353
|
-
<span className="chat-live-text">{t('rows.thinking.live')}</span>
|
|
368
|
+
<span className="chat-live-text min-w-0 truncate">{live || t('rows.thinking.live')}</span>
|
|
369
|
+
) : preview === '' ? (
|
|
370
|
+
<>
|
|
371
|
+
<span>{t('rows.thinking.thoughtFor', { duration })}</span>
|
|
372
|
+
<Icon icon={ChevronDown} size={12} className={clsx('shrink-0 transition-transform', open && 'rotate-180')} />
|
|
373
|
+
</>
|
|
354
374
|
) : (
|
|
355
375
|
<>
|
|
356
|
-
<span>{t('rows.thinking.
|
|
357
|
-
<
|
|
376
|
+
<span className="min-w-0 truncate">{open ? t('rows.thinking.thought') : preview}</span>
|
|
377
|
+
<span className="grow" />
|
|
378
|
+
<span className="shrink-0 text-text-faint tabular-nums">{duration}</span>
|
|
379
|
+
<Icon icon={ChevronDown} size={12} className={clsx('shrink-0 transition-transform', open && 'rotate-180')} />
|
|
358
380
|
</>
|
|
359
381
|
)}
|
|
360
382
|
</button>
|
|
361
383
|
{shown && text !== '' && (
|
|
362
|
-
<div data-find-field="text" className="mt-1 border-l border-border pl-2.5
|
|
363
|
-
{reveal.active ?
|
|
384
|
+
<div data-find-field="text" className="mt-1 border-l border-border pl-2.5 select-text">
|
|
385
|
+
{reveal.active ? (
|
|
386
|
+
<div className="text-sm whitespace-pre-wrap text-text-faint">
|
|
387
|
+
<FadingWords text={reveal.text} />
|
|
388
|
+
</div>
|
|
389
|
+
) : (
|
|
390
|
+
<Markdown text={text} muted />
|
|
391
|
+
)}
|
|
364
392
|
</div>
|
|
365
393
|
)}
|
|
366
394
|
</div>
|
|
367
395
|
);
|
|
368
396
|
}
|
|
369
397
|
|
|
398
|
+
/*
|
|
399
|
+
* The latest thought of a running turn over the call it led to, as its heading or first sentence,
|
|
400
|
+
* so what the model found stays in view while it checks it. Nothing while the thought has no line yet.
|
|
401
|
+
*/
|
|
402
|
+
export function LiveThoughtRow({ chatId, item: derived }: { chatId: string; item: ChatThinkingItem }) {
|
|
403
|
+
const item = useCurrentItem(chatId, derived);
|
|
404
|
+
const line = useMemo(() => thoughtLine(item.text), [item.text]);
|
|
405
|
+
if (line === '') {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
return (
|
|
409
|
+
<div className="-mx-1 mb-0.5 flex min-h-7 items-start gap-2 px-1 py-1 text-xs text-text-muted">
|
|
410
|
+
<span className={ROW_GUTTER}>
|
|
411
|
+
<Icon icon={Brain} size={12} />
|
|
412
|
+
</span>
|
|
413
|
+
<span className="line-clamp-4 min-w-0 wrap-anywhere select-text">{line}</span>
|
|
414
|
+
</div>
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
370
418
|
const NOTE_ICON = {
|
|
371
419
|
info: <Icon icon={Info} size={12} />,
|
|
372
420
|
warning: <Icon icon={TriangleAlert} size={12} />,
|
|
@@ -417,8 +465,9 @@ export function NoteRow({ id, level, text, from }: { id: string; level: 'info' |
|
|
|
417
465
|
|
|
418
466
|
/* "Open fork" on a note a fork sent, or "Open to answer" on one about a waiting child, while that chat is still in the project. */
|
|
419
467
|
function OpenChatButton({ chatId, label }: { chatId: string; label: 'openFork' | 'openWaiting' }) {
|
|
468
|
+
const host = useChatHost();
|
|
420
469
|
const { t } = useTranslation('agent-chat');
|
|
421
|
-
const place =
|
|
470
|
+
const place = host.useChatPlace(chatId);
|
|
422
471
|
if (place.title === null) {
|
|
423
472
|
return null;
|
|
424
473
|
}
|
|
@@ -486,7 +535,13 @@ export function ApprovalHistoryRow({ item }: { item: ChatApprovalItem }) {
|
|
|
486
535
|
<span className={clsx(ROW_GUTTER, item.decision === 'deny' && 'text-status-error')}>{DECISION_ICON[item.decision]}</span>
|
|
487
536
|
<span className={clsx(item.decision === 'deny' && 'text-status-error')}>{t(`rows.approval.${item.decision}`)}</span>
|
|
488
537
|
<span className="text-text-muted">{item.toolName}</span>
|
|
489
|
-
<span className="min-w-0 truncate font-mono">
|
|
538
|
+
<span className="min-w-0 truncate font-mono">
|
|
539
|
+
{toolSummaryIsPath(item.toolName, item.input) ? (
|
|
540
|
+
<MiddleTruncate text={toolSummary(item.toolName, item.input)} />
|
|
541
|
+
) : (
|
|
542
|
+
toolSummary(item.toolName, item.input)
|
|
543
|
+
)}
|
|
544
|
+
</span>
|
|
490
545
|
</div>
|
|
491
546
|
);
|
|
492
547
|
}
|
|
@@ -3,7 +3,18 @@ import { ErrorBoundary } from '@adecore/ui';
|
|
|
3
3
|
import type { ThreadCard } from '../../../host';
|
|
4
4
|
import type { TimelineRow } from '../../logic/timeline';
|
|
5
5
|
import type { SubagentStep } from '../../subagent-view';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
AgentTurnRow,
|
|
8
|
+
ApprovalHistoryRow,
|
|
9
|
+
AssistantRow,
|
|
10
|
+
CompactionRow,
|
|
11
|
+
LiveThoughtRow,
|
|
12
|
+
NoteRow,
|
|
13
|
+
QuestionHistoryRow,
|
|
14
|
+
ReportRow,
|
|
15
|
+
ThinkingRow,
|
|
16
|
+
UserRow
|
|
17
|
+
} from './MessageRows';
|
|
7
18
|
import { isImageGeneration } from '../../logic/generated-image';
|
|
8
19
|
import { ForksRow } from './ForksRow';
|
|
9
20
|
import { GeneratedImageRow } from './GeneratedImageRow';
|
|
@@ -52,6 +63,8 @@ export function Row({ row, chatId, toggleGroup, toggleTurn, toggleSubagent, open
|
|
|
52
63
|
return <ReportRow id={row.id} text={row.text} />;
|
|
53
64
|
case 'thinking':
|
|
54
65
|
return <ThinkingRow chatId={chatId} item={row.item} />;
|
|
66
|
+
case 'live-thought':
|
|
67
|
+
return <LiveThoughtRow chatId={chatId} item={row.item} />;
|
|
55
68
|
case 'work':
|
|
56
69
|
return isImageGeneration(row.tool) ? <GeneratedImageRow chatId={chatId} tool={row.tool} /> : <WorkRow tool={row.tool} />;
|
|
57
70
|
case 'work-live':
|
|
@@ -15,7 +15,7 @@ import { RunningFor, ToggleLine, WorkLiveRow, WorkRow } from './WorkRows';
|
|
|
15
15
|
import { entryTimeOf, statusWordOf, taskIdOf } from '../../subagent-list';
|
|
16
16
|
import { useSubagentSupport } from '../../subagent-support';
|
|
17
17
|
import { canOpenSubagent, crumbOf, type SubagentStep } from '../../subagent-view';
|
|
18
|
-
import {
|
|
18
|
+
import { useChatHost, type SubagentTask } from '../../../host';
|
|
19
19
|
import { useChatScope } from '../../../scope';
|
|
20
20
|
import { useCurrentItem } from '../../../state/chats';
|
|
21
21
|
|
|
@@ -135,10 +135,11 @@ export function SubagentRow({
|
|
|
135
135
|
/* Opens everything it did in the thread's place, for a surface that has somewhere to open it. */
|
|
136
136
|
onOpenConversation?(): void;
|
|
137
137
|
}) {
|
|
138
|
+
const host = useChatHost();
|
|
138
139
|
const { t } = useTranslation('agent-chat');
|
|
139
140
|
const { id } = useChatScope();
|
|
140
141
|
const taskId = taskIdOf(item);
|
|
141
|
-
const task =
|
|
142
|
+
const task = host.tasks.useTask(id, taskId);
|
|
142
143
|
// A task paused on its child's limit is still a running row on the wire, but nothing is at work.
|
|
143
144
|
const running = item.status === 'running' && statusWordOf(item, task) !== 'paused';
|
|
144
145
|
const detail = item.description || item.summary || item.subagentType || '';
|
|
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
2
2
|
import { Ellipsis, Maximize2, Trash2 } from 'lucide-react';
|
|
3
3
|
import type { ChatVisual } from '@adecore/agent-contracts';
|
|
4
4
|
import { ButtonGroup, ErrorBoundary, Icon, IconButton, Menu, Surface } from '@adecore/ui';
|
|
5
|
-
import {
|
|
5
|
+
import { useChatHost } from '../../../host';
|
|
6
6
|
import { useChatScope } from '../../../scope';
|
|
7
7
|
import { useVisualDialog } from '../../visuals';
|
|
8
8
|
import { VisualFrame } from '../VisualFrame';
|
|
@@ -14,9 +14,10 @@ import { VisualFrame } from '../VisualFrame';
|
|
|
14
14
|
* sit here.
|
|
15
15
|
*/
|
|
16
16
|
export function VisualRow({ chatId, visual }: { chatId: string; visual: ChatVisual }) {
|
|
17
|
+
const host = useChatHost();
|
|
17
18
|
const { t } = useTranslation('agent-chat');
|
|
18
19
|
const { keyOf } = useChatScope();
|
|
19
|
-
if (
|
|
20
|
+
if (host.visuals === null) {
|
|
20
21
|
return null;
|
|
21
22
|
}
|
|
22
23
|
const open = (kind: 'expand' | 'remove'): void => useVisualDialog.getState().open(keyOf(chatId), visual.id, kind);
|
|
@@ -1,22 +1,38 @@
|
|
|
1
|
-
import { Suspense, useEffect, useState, type Dispatch, type ReactNode, type SetStateAction } from 'react';
|
|
1
|
+
import { Fragment, Suspense, useEffect, useState, type Dispatch, type ReactNode, type SetStateAction } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import i18next from 'i18next';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { ChevronRight, FileDiff, X } from 'lucide-react';
|
|
6
6
|
import type { ChatCheckpointDiff, ChatCheckpointFile, ChatFileChange, ChatToolItem, ChatTurnItem } from '@adecore/agent-contracts';
|
|
7
7
|
import type { BaseMoved } from '../../logic/timeline';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
exitCodeOf,
|
|
10
|
+
fileChanges,
|
|
11
|
+
hasOutput,
|
|
12
|
+
hasToolBody,
|
|
13
|
+
liveOutput,
|
|
14
|
+
readImagePath,
|
|
15
|
+
shellCommand,
|
|
16
|
+
toolCallLines,
|
|
17
|
+
toolStartedAt,
|
|
18
|
+
toolSummary,
|
|
19
|
+
toolSummaryIsPath,
|
|
20
|
+
unifiedChanges,
|
|
21
|
+
type FileChange
|
|
22
|
+
} from '../../logic/tools';
|
|
9
23
|
import { useOpenForFind } from '../find-reveal';
|
|
10
|
-
import {
|
|
24
|
+
import { useChatHost } from '../../../host';
|
|
11
25
|
import { lazyNamed } from '../../../lazy';
|
|
12
26
|
import { useChatActions } from '../../actions';
|
|
13
27
|
import { useChatScope } from '../../../scope';
|
|
14
28
|
import { useCurrentItem } from '../../../state/chats';
|
|
15
29
|
import { useTimelineFlash } from '../../timeline-flash';
|
|
16
30
|
import { formatClockDuration, formatElapsedShort } from '@adecore/ui/format';
|
|
17
|
-
import { Icon, Spinner, useTickingText } from '@adecore/ui';
|
|
31
|
+
import { Icon, MiddleTruncate, Spinner, useTickingText } from '@adecore/ui';
|
|
18
32
|
import { ROW_GUTTER, toolIcon } from '../icons';
|
|
19
33
|
import { AnsiOutput } from '../AnsiOutput';
|
|
34
|
+
import { RowTime } from '../RowTime';
|
|
35
|
+
import { ShellCommand } from '../ShellCommand';
|
|
20
36
|
import { DiffStack, ReviewStackView } from '../diff/DiffStack';
|
|
21
37
|
import { reviewEntries, type ReviewEntry } from '../diff/review-plan';
|
|
22
38
|
import { useReviewStack } from '../diff/use-review-stack';
|
|
@@ -26,54 +42,79 @@ const UnifiedDiff = lazyNamed(() => import('../UnifiedDiff'), 'default');
|
|
|
26
42
|
|
|
27
43
|
const OUTPUT_LIMIT = 4000;
|
|
28
44
|
|
|
45
|
+
/* The line that says how much of a text past the limit is left out; empty for a text within it. */
|
|
46
|
+
function clipNotice(text: string): string {
|
|
47
|
+
return text.length > OUTPUT_LIMIT ? `\n${i18next.t('agent-chat:work.moreCharacters', { count: text.length - OUTPUT_LIMIT })}` : '';
|
|
48
|
+
}
|
|
49
|
+
|
|
29
50
|
function clip(text: string): string {
|
|
30
|
-
return text.
|
|
31
|
-
? `${text.slice(0, OUTPUT_LIMIT)}\n${i18next.t('agent-chat:work.moreCharacters', { count: text.length - OUTPUT_LIMIT })}`
|
|
32
|
-
: text;
|
|
51
|
+
return text.slice(0, OUTPUT_LIMIT) + clipNotice(text);
|
|
33
52
|
}
|
|
34
53
|
|
|
54
|
+
/*
|
|
55
|
+
* The line of a call, a subagent or a group. Without `onToggle` it has nothing to open: no chevron, and
|
|
56
|
+
* not a button. `time` shows at the right edge while the line is hovered or focused.
|
|
57
|
+
*/
|
|
35
58
|
export function ToggleLine({
|
|
36
59
|
icon,
|
|
37
60
|
label,
|
|
38
61
|
detail,
|
|
39
|
-
|
|
62
|
+
command,
|
|
63
|
+
path,
|
|
64
|
+
open = false,
|
|
40
65
|
onToggle,
|
|
41
66
|
failed,
|
|
42
67
|
live,
|
|
43
68
|
trailing,
|
|
69
|
+
time,
|
|
44
70
|
className
|
|
45
71
|
}: {
|
|
46
72
|
icon: ReactNode;
|
|
47
73
|
label: string;
|
|
48
74
|
detail?: string;
|
|
49
|
-
|
|
50
|
-
|
|
75
|
+
/* Draws `detail` as a shell command, in the colors of the code theme. */
|
|
76
|
+
command?: boolean;
|
|
77
|
+
/* `detail` is the path of a file, cut in the middle so its name stays in sight. */
|
|
78
|
+
path?: boolean;
|
|
79
|
+
open?: boolean;
|
|
80
|
+
onToggle?(): void;
|
|
51
81
|
failed?: boolean;
|
|
52
82
|
live?: boolean;
|
|
53
83
|
trailing?: ReactNode;
|
|
84
|
+
time?: number;
|
|
54
85
|
className?: string;
|
|
55
86
|
}) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
>
|
|
87
|
+
const classes = clsx(
|
|
88
|
+
// Fix the width so long commands reach the truncation inside the negative margins.
|
|
89
|
+
'group/line -mx-1 mb-0.5 flex h-7 w-[calc(100%+8px)] items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted',
|
|
90
|
+
onToggle !== undefined && 'hover:bg-surface-hover',
|
|
91
|
+
failed && 'text-status-error',
|
|
92
|
+
className
|
|
93
|
+
);
|
|
94
|
+
const content = (
|
|
95
|
+
<>
|
|
66
96
|
<span className={clsx(ROW_GUTTER, live && 'text-accent')}>{icon}</span>
|
|
67
97
|
<span className={clsx('shrink-0', live && 'chat-live-text')}>{label}</span>
|
|
68
98
|
{detail && (
|
|
69
99
|
<span data-find-field="summary" className="min-w-0 truncate font-mono text-text-faint">
|
|
70
|
-
{detail}
|
|
100
|
+
{command ? <ShellCommand command={detail} /> : path ? <MiddleTruncate text={detail} /> : detail}
|
|
71
101
|
</span>
|
|
72
102
|
)}
|
|
73
103
|
<span className="grow" />
|
|
74
104
|
{trailing}
|
|
105
|
+
{time !== undefined && <RowTime at={time} />}
|
|
75
106
|
{failed && <Icon icon={X} size={12} className="shrink-0" />}
|
|
76
|
-
|
|
107
|
+
{onToggle !== undefined && (
|
|
108
|
+
<Icon icon={ChevronRight} size={12} className={clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90')} />
|
|
109
|
+
)}
|
|
110
|
+
</>
|
|
111
|
+
);
|
|
112
|
+
if (onToggle === undefined) {
|
|
113
|
+
return <div className={classes}>{content}</div>;
|
|
114
|
+
}
|
|
115
|
+
return (
|
|
116
|
+
<button className={classes} onClick={onToggle}>
|
|
117
|
+
{content}
|
|
77
118
|
</button>
|
|
78
119
|
);
|
|
79
120
|
}
|
|
@@ -106,7 +147,7 @@ function ChangedFileLine({
|
|
|
106
147
|
onClick={onToggle}
|
|
107
148
|
>
|
|
108
149
|
<Icon icon={ChevronRight} size={12} className={clsx('shrink-0 text-text-faint transition-transform', open && 'rotate-90')} />
|
|
109
|
-
<
|
|
150
|
+
<MiddleTruncate text={path} className="font-mono text-text" />
|
|
110
151
|
<span className="grow" />
|
|
111
152
|
{trailing}
|
|
112
153
|
</button>
|
|
@@ -115,19 +156,12 @@ function ChangedFileLine({
|
|
|
115
156
|
);
|
|
116
157
|
}
|
|
117
158
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const changes = patches.length > 0 ? [] : fileChanges(tool.name, tool.input);
|
|
159
|
+
/* A diff keeps its card, with what the call answered under it. */
|
|
160
|
+
function DiffBody({ tool, entries, patched }: { tool: ChatToolItem; entries: readonly ReviewEntry[]; patched: boolean }) {
|
|
121
161
|
return (
|
|
122
162
|
<div className="mt-1.5 mb-2 ml-6 overflow-hidden rounded-md border border-border bg-surface-raised">
|
|
123
|
-
{
|
|
124
|
-
|
|
125
|
-
) : (
|
|
126
|
-
<pre className="max-h-64 overflow-auto px-3 py-2 font-mono text-code text-text-muted select-text">
|
|
127
|
-
{clip(JSON.stringify(tool.input, null, 2) ?? '')}
|
|
128
|
-
</pre>
|
|
129
|
-
)}
|
|
130
|
-
{tool.output !== null && tool.output !== '' && patches.length === 0 && (
|
|
163
|
+
<DiffStack entries={entries} />
|
|
164
|
+
{hasOutput(tool.output) && !patched && (
|
|
131
165
|
<pre
|
|
132
166
|
data-find-field="output"
|
|
133
167
|
className={clsx(
|
|
@@ -142,9 +176,64 @@ function ToolBody({ tool }: { tool: ChatToolItem }) {
|
|
|
142
176
|
);
|
|
143
177
|
}
|
|
144
178
|
|
|
179
|
+
/* What a call answered, muted under the call; a failure in the error color, or its exit code when the tool names one. */
|
|
180
|
+
function ToolOutput({ tool }: { tool: ChatToolItem }) {
|
|
181
|
+
const { t } = useTranslation('agent-chat');
|
|
182
|
+
if (!hasOutput(tool.output)) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
const failed = tool.state === 'error';
|
|
186
|
+
const { code, rest } = failed ? exitCodeOf(tool.output) : { code: null, rest: tool.output };
|
|
187
|
+
return (
|
|
188
|
+
<>
|
|
189
|
+
{hasOutput(rest) && (
|
|
190
|
+
<pre
|
|
191
|
+
data-find-field="output"
|
|
192
|
+
className={clsx('max-h-64 overflow-auto whitespace-pre-wrap', failed && code === null ? 'text-status-error' : 'text-text-muted')}
|
|
193
|
+
>
|
|
194
|
+
<AnsiOutput text={rest} limit={OUTPUT_LIMIT} />
|
|
195
|
+
</pre>
|
|
196
|
+
)}
|
|
197
|
+
{code !== null && <div className="text-status-error">{t('work.exitCode', { code: String(code) })}</div>}
|
|
198
|
+
</>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* An opened call without a card: what it was asked in the foreground, what it answered muted below. */
|
|
203
|
+
function ToolBody({ tool }: { tool: ChatToolItem }) {
|
|
204
|
+
const patches = unifiedChanges(tool);
|
|
205
|
+
const changes = patches.length > 0 ? [] : fileChanges(tool.name, tool.input);
|
|
206
|
+
if (patches.length + changes.length > 0) {
|
|
207
|
+
return <DiffBody tool={tool} entries={reviewEntries(patches, changes)} patched={patches.length > 0} />;
|
|
208
|
+
}
|
|
209
|
+
const lines = toolCallLines(tool.name, tool.input);
|
|
210
|
+
return (
|
|
211
|
+
<div className="mt-0.5 mb-2 ml-6 flex flex-col gap-1.5 font-mono text-code select-text">
|
|
212
|
+
{lines.command !== null && (
|
|
213
|
+
<pre className="max-h-64 overflow-auto whitespace-pre-wrap wrap-anywhere text-text">
|
|
214
|
+
<ShellCommand command={lines.command.slice(0, OUTPUT_LIMIT)} />
|
|
215
|
+
{clipNotice(lines.command)}
|
|
216
|
+
</pre>
|
|
217
|
+
)}
|
|
218
|
+
{lines.args.length > 0 && (
|
|
219
|
+
<dl className="grid max-h-64 grid-cols-[auto_minmax(0,1fr)] gap-x-3 overflow-auto">
|
|
220
|
+
{lines.args.map(([key, value]) => (
|
|
221
|
+
<Fragment key={key}>
|
|
222
|
+
<dt className="text-text-faint">{key}</dt>
|
|
223
|
+
<dd className="whitespace-pre-wrap wrap-anywhere text-text">{clip(value)}</dd>
|
|
224
|
+
</Fragment>
|
|
225
|
+
))}
|
|
226
|
+
</dl>
|
|
227
|
+
)}
|
|
228
|
+
{lines.text !== null && <pre className="max-h-64 overflow-auto whitespace-pre-wrap wrap-anywhere text-text">{clip(lines.text)}</pre>}
|
|
229
|
+
<ToolOutput tool={tool} />
|
|
230
|
+
</div>
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
145
234
|
/*
|
|
146
|
-
* One settled tool call: a line, and
|
|
147
|
-
* drawn under the line. `icon`, `label` and `failed` let a row that knows the call better name it.
|
|
235
|
+
* One settled tool call: a line, and what it was asked and answered behind it. An image the call
|
|
236
|
+
* looked at is drawn under the line. `icon`, `label` and `failed` let a row that knows the call better name it.
|
|
148
237
|
*/
|
|
149
238
|
export function WorkRow({
|
|
150
239
|
tool,
|
|
@@ -161,22 +250,28 @@ export function WorkRow({
|
|
|
161
250
|
label?: string;
|
|
162
251
|
failed?: boolean;
|
|
163
252
|
}) {
|
|
253
|
+
const host = useChatHost();
|
|
164
254
|
const [open, setOpen] = useState(false);
|
|
165
255
|
const image = tool.state === 'done' ? readImagePath(tool.name, tool.input) : null;
|
|
166
|
-
const { ReadImage } =
|
|
256
|
+
const { ReadImage } = host;
|
|
167
257
|
useOpenForFind(tool.id, 'output', setOpen);
|
|
258
|
+
const summary = detail ?? toolSummary(tool.name, tool.input);
|
|
259
|
+
const opens = hasToolBody(tool);
|
|
168
260
|
return (
|
|
169
261
|
<div data-find-item={tool.id} className={nested ? 'ml-6' : undefined}>
|
|
170
262
|
<ToggleLine
|
|
171
263
|
icon={icon ?? toolIcon(tool.name)}
|
|
172
264
|
label={label ?? tool.name}
|
|
173
|
-
detail={
|
|
174
|
-
|
|
175
|
-
|
|
265
|
+
detail={summary}
|
|
266
|
+
command={detail === undefined && summary === shellCommand(tool.name, tool.input)}
|
|
267
|
+
path={detail === undefined && toolSummaryIsPath(tool.name, tool.input)}
|
|
268
|
+
open={open && opens}
|
|
269
|
+
onToggle={opens ? () => setOpen((o) => !o) : undefined}
|
|
176
270
|
failed={failed ?? tool.state === 'error'}
|
|
271
|
+
time={tool.createdAt}
|
|
177
272
|
/>
|
|
178
273
|
{image !== null && ReadImage !== null && <ReadImage path={image} />}
|
|
179
|
-
{open && <ToolBody tool={tool} />}
|
|
274
|
+
{open && opens && <ToolBody tool={tool} />}
|
|
180
275
|
</div>
|
|
181
276
|
);
|
|
182
277
|
}
|
|
@@ -193,18 +288,22 @@ export function WorkLiveRow({ chatId, tool: derived }: { chatId: string; tool: C
|
|
|
193
288
|
const [open, setOpen] = useState(false);
|
|
194
289
|
const tool = useCurrentItem(chatId, derived);
|
|
195
290
|
const tail = liveOutput(tool);
|
|
291
|
+
const summary = toolSummary(tool.name, tool.input);
|
|
292
|
+
const opens = hasToolBody(tool);
|
|
196
293
|
return (
|
|
197
294
|
<div>
|
|
198
295
|
<ToggleLine
|
|
199
296
|
icon={toolIcon(tool.name)}
|
|
200
297
|
label={tool.name}
|
|
201
|
-
detail={
|
|
202
|
-
|
|
203
|
-
|
|
298
|
+
detail={summary || tool.progress?.description || ''}
|
|
299
|
+
command={summary !== '' && summary === shellCommand(tool.name, tool.input)}
|
|
300
|
+
path={summary !== '' && toolSummaryIsPath(tool.name, tool.input)}
|
|
301
|
+
open={open && opens}
|
|
302
|
+
onToggle={opens ? () => setOpen((o) => !o) : undefined}
|
|
204
303
|
trailing={<RunningFor startedAt={toolStartedAt(tool)} />}
|
|
205
304
|
live
|
|
206
305
|
/>
|
|
207
|
-
{open && <ToolBody tool={tool} />}
|
|
306
|
+
{open && opens && <ToolBody tool={tool} />}
|
|
208
307
|
{tail !== null && !open && (
|
|
209
308
|
<pre className="mt-1.5 mb-2 ml-6 max-h-48 overflow-auto rounded-md border border-border bg-surface-raised px-3 py-2 font-mono text-code whitespace-pre-wrap text-chat-output select-text">
|
|
210
309
|
<AnsiOutput text={tail} tailLines={12} />
|
|
@@ -219,7 +318,7 @@ export function WorkGroupRow({ tools, summary, expanded, onToggle }: { tools: Ch
|
|
|
219
318
|
const failed = tools.some((tool) => tool.state === 'error');
|
|
220
319
|
return (
|
|
221
320
|
<div>
|
|
222
|
-
<ToggleLine icon={toolIcon(tools[0]!.name)} label={summary} open={expanded} onToggle={onToggle} failed={failed} />
|
|
321
|
+
<ToggleLine icon={toolIcon(tools[0]!.name)} label={summary} open={expanded} onToggle={onToggle} failed={failed} time={tools[0]!.createdAt} />
|
|
223
322
|
</div>
|
|
224
323
|
);
|
|
225
324
|
}
|
|
@@ -244,7 +343,7 @@ export function TurnFoldRow({
|
|
|
244
343
|
return (
|
|
245
344
|
<button
|
|
246
345
|
className={clsx(
|
|
247
|
-
'group -mx-1 mb-2 flex h-7 w-[calc(100%+8px)] min-w-0 items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted hover:bg-surface-hover',
|
|
346
|
+
'group group/line -mx-1 mb-2 flex h-7 w-[calc(100%+8px)] min-w-0 items-center gap-2 rounded-md px-1 text-left text-xs text-text-muted hover:bg-surface-hover',
|
|
248
347
|
turn.state === 'error' && 'text-status-error'
|
|
249
348
|
)}
|
|
250
349
|
aria-expanded={expanded}
|
|
@@ -255,6 +354,8 @@ export function TurnFoldRow({
|
|
|
255
354
|
</span>
|
|
256
355
|
<span className="shrink-0 group-hover:text-text">{label}</span>
|
|
257
356
|
{work.length > 0 && <span className="min-w-0 truncate text-text-faint">{work.map((part) => ` · ${part}`).join('')}</span>}
|
|
357
|
+
<span className="grow" />
|
|
358
|
+
<RowTime at={turn.createdAt} />
|
|
258
359
|
</button>
|
|
259
360
|
);
|
|
260
361
|
}
|
|
@@ -9,7 +9,7 @@ import { RunningFor, ToggleLine, WorkLiveRow, WorkRow } from './WorkRows';
|
|
|
9
9
|
import { useChatScope } from '../../../scope';
|
|
10
10
|
import { Icon, IconButton } from '@adecore/ui';
|
|
11
11
|
import { useChatActions } from '../../actions';
|
|
12
|
-
import {
|
|
12
|
+
import { useChatHost } from '../../../host';
|
|
13
13
|
|
|
14
14
|
function AgentLine({ view, onOpen }: { view: WorkflowAgentView; onOpen?(step: SubagentStep): void }) {
|
|
15
15
|
const { agent, state } = view;
|
|
@@ -75,6 +75,7 @@ export function WorkflowRow({
|
|
|
75
75
|
chatId?: string;
|
|
76
76
|
onOpenAgent?(step: SubagentStep): void;
|
|
77
77
|
}) {
|
|
78
|
+
const host = useChatHost();
|
|
78
79
|
const { t } = useTranslation('agent-chat');
|
|
79
80
|
const { id } = useChatScope();
|
|
80
81
|
// A host that does not answer `chat.subagent` has no conversation to open for anyone.
|
|
@@ -86,7 +87,7 @@ export function WorkflowRow({
|
|
|
86
87
|
const stop = (): void => {
|
|
87
88
|
if (chatId && workflow.taskId) {
|
|
88
89
|
void actions.stopTask(chatId, workflow.taskId).catch((error: unknown) => {
|
|
89
|
-
|
|
90
|
+
host.notify({
|
|
90
91
|
kind: 'error',
|
|
91
92
|
title: t('activity.stopFailed'),
|
|
92
93
|
description: error instanceof Error ? error.message : t('subagents.noAnswer')
|