@adecore/agents-react 0.23.1 → 0.24.1
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 +130 -907
- 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/surface.d.ts +1 -0
- package/dist/chat/ui/composer/surface.js +44 -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 +212 -1358
- 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/surface.ts +45 -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
|
@@ -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')
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { useLayoutEffect, useMemo } from 'react';
|
|
2
2
|
import { diffSyntaxDocument, type DiffSourceTokens } from '@adecore/editor-react';
|
|
3
3
|
import type { DiffDocument } from '@adecore/merge';
|
|
4
|
-
import {
|
|
4
|
+
import { useChatHost } from '../../host';
|
|
5
|
+
import { diffSourceTokens, diffSyntaxRuntime, type DiffSourceTokenSession, type DiffSyntaxRuntime } from './diff-syntax';
|
|
5
6
|
|
|
6
|
-
function createSourceBinding(document: DiffDocument, language: string, theme: string, runtime
|
|
7
|
+
function createSourceBinding(document: DiffDocument, language: string, theme: string, runtime: () => DiffSyntaxRuntime) {
|
|
7
8
|
const mapping = diffSyntaxDocument(document, language, theme);
|
|
8
9
|
const listeners = new Set<() => void>();
|
|
9
10
|
let source: DiffSourceTokenSession | undefined;
|
|
10
11
|
const current = (): DiffSourceTokenSession => {
|
|
11
12
|
if (source === undefined) {
|
|
12
|
-
source = diffSourceTokens(document, mapping, runtime);
|
|
13
|
+
source = diffSourceTokens(document, mapping, runtime());
|
|
13
14
|
source.subscribe(() => {
|
|
14
15
|
for (const listener of [...listeners]) {
|
|
15
16
|
listener();
|
|
@@ -36,8 +37,13 @@ function createSourceBinding(document: DiffDocument, language: string, theme: st
|
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
/* Without a `runtime`, the shared one of the host's `code`. */
|
|
39
41
|
export function useDiffSourceTokens(document: DiffDocument, language: string, theme: string, runtime?: DiffSyntaxRuntime): DiffSourceTokens {
|
|
40
|
-
const
|
|
42
|
+
const { code } = useChatHost();
|
|
43
|
+
const binding = useMemo(
|
|
44
|
+
() => createSourceBinding(document, language, theme, () => runtime ?? diffSyntaxRuntime(code)),
|
|
45
|
+
[document, language, theme, runtime, code]
|
|
46
|
+
);
|
|
41
47
|
useLayoutEffect(() => () => binding.release(), [binding]);
|
|
42
48
|
return binding.tokens;
|
|
43
49
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useLayoutEffect, useState, type RefObject } from 'react';
|
|
2
2
|
import { cleanVisualVariables, type VisualAppearance, type VisualTheme, type VisualThemeVariable } from '@adecore/agent-contracts/visual';
|
|
3
|
-
import {
|
|
3
|
+
import { useChatHost } from '../../host';
|
|
4
4
|
|
|
5
5
|
/* The tokens of the app's theme where a frame stands; each answers '' for a token the theme lacks. */
|
|
6
6
|
export interface VisualTokens {
|
|
@@ -167,7 +167,8 @@ const THEME_ATTRIBUTES = ['class', 'style', 'data-theme'];
|
|
|
167
167
|
* accent or a font a person picks reaches every frame as well.
|
|
168
168
|
*/
|
|
169
169
|
export function useVisualTheme(ref: RefObject<HTMLElement | null>): VisualTheme | null {
|
|
170
|
-
const
|
|
170
|
+
const host = useChatHost();
|
|
171
|
+
const mode = host.code.useMode();
|
|
171
172
|
const [theme, setTheme] = useState<VisualTheme | null>(null);
|
|
172
173
|
useLayoutEffect(() => {
|
|
173
174
|
const element = ref.current;
|
package/src/host.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { createContext, createElement, useContext, useState, type ComponentProps, type ComponentType, type ReactNode, type RefObject } from 'react';
|
|
2
2
|
import type { Extension } from '@codemirror/state';
|
|
3
3
|
import type { EditorView } from '@codemirror/view';
|
|
4
4
|
import type { Highlighter, ThemeRegistration } from 'shiki';
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
AgentKind,
|
|
8
8
|
ChatCheckpointDiff,
|
|
9
9
|
ChatConfigurePayload,
|
|
10
|
+
ChatGoalAction,
|
|
10
11
|
ChatItem,
|
|
11
12
|
ChatSubagentItem,
|
|
12
13
|
ChatUiChoicePayload,
|
|
@@ -21,7 +22,6 @@ import type { FindReveal } from './chat/ui/find-reveal';
|
|
|
21
22
|
import type { PromptAction } from './prompts/logic/prompts';
|
|
22
23
|
import type { HostPrompt, PromptViewProps } from './prompts/logic/subjects';
|
|
23
24
|
import { PlainTextarea } from './ui/PlainTextarea';
|
|
24
|
-
import { configureChatStorage, type ChatStorageOptions } from './storage';
|
|
25
25
|
|
|
26
26
|
/* A color an account may wear, by the name the host stores it under. */
|
|
27
27
|
export interface AccentChoice {
|
|
@@ -58,6 +58,8 @@ export interface ChatActions {
|
|
|
58
58
|
turnDiff(chatId: string, turnId: string): Promise<ChatCheckpointDiff | null>;
|
|
59
59
|
stopSubagent(chatId: string, toolUseId: string): Promise<void>;
|
|
60
60
|
stopTask(chatId: string, taskId: string): Promise<void>;
|
|
61
|
+
/* Pauses, resumes or clears the chat's goal; absent where the host offers none of it, which leaves the goal row without its buttons. */
|
|
62
|
+
goal?(chatId: string, action: ChatGoalAction): Promise<void>;
|
|
61
63
|
approve(chatId: string, requestId: string, decision: 'allow' | 'allow-always' | 'deny', message?: string): Promise<void>;
|
|
62
64
|
answer(chatId: string, requestId: string, answers: Record<string, string>): Promise<void>;
|
|
63
65
|
dismiss(chatId: string, itemId: string): Promise<void>;
|
|
@@ -194,13 +196,11 @@ export interface ReplyAuthor {
|
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
/*
|
|
197
|
-
* What the app around the chat decides and the chat cannot
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* The hooks are called as hooks: an app hands the same function for the life of the page.
|
|
199
|
+
* What the app around the chat decides and the chat cannot, handed to the views by a `ChatHostProvider`.
|
|
200
|
+
* Whatever an app leaves out keeps the default here, which is the chat without that part. One host may
|
|
201
|
+
* serve several scopes, so a function that is about one host of chats is told its scope id.
|
|
201
202
|
*/
|
|
202
203
|
export interface ChatHost {
|
|
203
|
-
storage?: ChatStorageOptions;
|
|
204
204
|
intelligentUi?: {
|
|
205
205
|
subscribe?(scopeId: string, chatId: string, changed: () => void): () => void;
|
|
206
206
|
link?(scopeId: string, payload: ChatUiLinkPayload): Promise<ChatUiLinkReading>;
|
|
@@ -249,7 +249,7 @@ export interface ChatHost {
|
|
|
249
249
|
syntaxWorker?: () => Worker;
|
|
250
250
|
/* Starts legacy highlighting with its first diff; an enclosing DiffPool takes precedence. */
|
|
251
251
|
legacyDiffWorker?: () => Worker;
|
|
252
|
-
/* Borrow the page highlighter for fallback; the host retains ownership. */
|
|
252
|
+
/* Borrow the page highlighter for code blocks and the diff fallback; the host retains ownership. */
|
|
253
253
|
highlighter?: () => Promise<Highlighter>;
|
|
254
254
|
/* Opt in to bounded editor reviews; failures show a status, omitted keeps the legacy renderer. */
|
|
255
255
|
editor?: () => Promise<EditorEngine>;
|
|
@@ -310,6 +310,11 @@ export interface ChatHost {
|
|
|
310
310
|
};
|
|
311
311
|
/* Offers a fork of the chat after one of its turns; null offers none. */
|
|
312
312
|
fork: ((chatId: string, turnId: string) => void) | null;
|
|
313
|
+
/*
|
|
314
|
+
* Opens a new chat beside this one on its CLI, model and settings, with the focus in its composer,
|
|
315
|
+
* once Mod+Alt+Enter sent a message from it; null leaves that key sending the other way, like Alt+Enter.
|
|
316
|
+
*/
|
|
317
|
+
openNewChat: ((scopeId: string, chatId: string) => void) | null;
|
|
313
318
|
openSettings(section: 'providers' | 'agents'): void;
|
|
314
319
|
/* Whether the host lets a chat go on by itself once a limit it stopped on lifts. */
|
|
315
320
|
useResumeAtReset(scopeId: string): boolean;
|
|
@@ -364,6 +369,7 @@ const DEFAULT_HOST: ChatHost = {
|
|
|
364
369
|
tasks: { useTasks: () => undefined, useTask: () => null },
|
|
365
370
|
confirm: { stopSubagents: (_scopeId, _chatId, run) => run(), stopTask: (_scopeId, _childId, _title, run) => run() },
|
|
366
371
|
fork: null,
|
|
372
|
+
openNewChat: null,
|
|
367
373
|
openSettings: () => undefined,
|
|
368
374
|
useResumeAtReset: () => true,
|
|
369
375
|
useComposerPlaceholder: () => null,
|
|
@@ -374,15 +380,25 @@ const DEFAULT_HOST: ChatHost = {
|
|
|
374
380
|
visuals: null
|
|
375
381
|
};
|
|
376
382
|
|
|
377
|
-
|
|
383
|
+
const ChatHostContext = createContext<ChatHost>(DEFAULT_HOST);
|
|
378
384
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
385
|
+
/*
|
|
386
|
+
* Hands the views under it a host: `host` over the one of a provider above it, member by member, and
|
|
387
|
+
* over the defaults at the top. A part of an app that loads later and adds hooks renders a provider of
|
|
388
|
+
* its own around what it draws, so every view under it calls the same hooks from its first render on.
|
|
389
|
+
* The host is read once, as the provider mounts, since a hook that changed under a mounted view would
|
|
390
|
+
* break the order of its hooks: a provider that gets another `host` throws, and a new `key` remounts it.
|
|
391
|
+
*/
|
|
392
|
+
export function ChatHostProvider({ host, children }: { host: Partial<ChatHost>; children?: ReactNode }) {
|
|
393
|
+
const parent = useContext(ChatHostContext);
|
|
394
|
+
const [pinned] = useState(() => ({ host, value: { ...parent, ...host } }));
|
|
395
|
+
if (pinned.host !== host) {
|
|
396
|
+
throw new Error('A ChatHostProvider reads its host once: hand it the same object on every render, or a new key to mount it with another');
|
|
382
397
|
}
|
|
383
|
-
|
|
398
|
+
return createElement(ChatHostContext.Provider, { value: pinned.value }, children);
|
|
384
399
|
}
|
|
385
400
|
|
|
386
|
-
|
|
387
|
-
|
|
401
|
+
/* The host of the nearest `ChatHostProvider`, or the defaults outside one. */
|
|
402
|
+
export function useChatHost(): ChatHost {
|
|
403
|
+
return useContext(ChatHostContext);
|
|
388
404
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Public API: exports.test.ts snapshots this list, so a name added or dropped here is an API change.
|
|
2
|
+
export {
|
|
3
|
+
type ChatActions,
|
|
4
|
+
type FileRef,
|
|
5
|
+
type ShellCodeBlockContext,
|
|
6
|
+
type ChatPlace,
|
|
7
|
+
type SubagentTask,
|
|
8
|
+
type TimelineFindOptions,
|
|
9
|
+
type TimelineFind,
|
|
10
|
+
type ComposerDictationProps,
|
|
11
|
+
type ComposerSlotProps,
|
|
12
|
+
type SubagentSlotProps,
|
|
13
|
+
type ThreadCard,
|
|
14
|
+
type VisualHost,
|
|
15
|
+
type ReplyAuthor,
|
|
16
|
+
type ChatHost,
|
|
17
|
+
ChatHostProvider,
|
|
18
|
+
useChatHost,
|
|
19
|
+
type AccentChoice,
|
|
20
|
+
type ChatToast,
|
|
21
|
+
type TextareaProps,
|
|
22
|
+
type ResourceUrl
|
|
23
|
+
} from './host';
|
|
24
|
+
export { type ChatScope, ChatScopeContext, useChatScope } from './scope';
|
|
25
|
+
export {
|
|
26
|
+
type ChatRequestMap,
|
|
27
|
+
type ChatEventMap,
|
|
28
|
+
type ChatTransportStatus,
|
|
29
|
+
type ChatTransport,
|
|
30
|
+
ChatTransportError,
|
|
31
|
+
errorCode,
|
|
32
|
+
isConnectionError
|
|
33
|
+
} from './transport';
|
|
34
|
+
export { portTransport, type PortTransport } from './port-transport';
|
|
35
|
+
export {
|
|
36
|
+
onChatStorageConfiguration,
|
|
37
|
+
configureChatStorage,
|
|
38
|
+
chatStorageKey,
|
|
39
|
+
chatStorageLegacyKeys,
|
|
40
|
+
chatStorageAdapter,
|
|
41
|
+
hydrateChatStorage,
|
|
42
|
+
createChatStore,
|
|
43
|
+
type ChatStorageRecord,
|
|
44
|
+
type ChatStorageAdapter,
|
|
45
|
+
type ChatStorageOptions
|
|
46
|
+
} from './storage';
|
|
47
|
+
export { setLazyPrefetch, onLazyOpenError } from './lazy';
|
|
48
|
+
export { type MountedEntry, MountedRegistry } from './mounted-registry';
|
|
49
|
+
export { type AgentsSettingsSection, PROVIDERS_SECTION, USAGE_SECTION, settingsSection } from './settings/sections';
|