@adecore/agents-react 0.39.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/AgentModelLabel.js +2 -1
- package/dist/agents/model-name.js +2 -1
- package/dist/agents/provider-paths.d.ts +2 -1
- package/dist/agents/provider-paths.js +7 -3
- package/dist/chat/account-choice.js +57 -28
- package/dist/chat/bookmarks.js +2 -1
- package/dist/chat/drafts.d.ts +0 -1
- package/dist/chat/drafts.js +9 -28
- package/dist/chat/logic/picker-entries.js +2 -8
- package/dist/chat/logic/resume-compaction.js +2 -5
- package/dist/chat/logic/timeline-copy.js +2 -8
- package/dist/chat/logic/timeline.js +9 -10
- package/dist/chat/logic/workflow.js +2 -4
- package/dist/chat/subagent-conversation.js +2 -1
- package/dist/chat/ui/GoalDock.js +2 -1
- package/dist/chat/ui/LimitState.js +4 -6
- package/dist/chat/ui/composer/use-continuable-turn.js +0 -1
- package/dist/chat/ui/composer/use-notice.js +2 -1
- package/dist/chat/ui/composer/use-prompt-history.js +1 -1
- package/dist/chat/ui/composer/use-prompt-menus.js +216 -253
- package/dist/chat/ui/composer/use-take-back.js +2 -2
- package/dist/chat/ui/diff/ApprovalReview.js +1 -1
- package/dist/chat/ui/highlighter.d.ts +0 -6
- package/dist/chat/ui/highlighter.js +0 -12
- package/dist/chat/ui/icons.d.ts +0 -1
- package/dist/chat/ui/icons.js +0 -3
- package/dist/chat/ui/rows/MessageRows.js +2 -5
- package/dist/chat/ui/rows/row-rhythm.js +2 -5
- package/dist/chat/ui/theme-watch.js +3 -7
- package/dist/prompts/logic/usePromptSession.js +2 -1
- package/dist/providers/AddAccountForm.js +2 -1
- package/dist/providers/CliDetail.js +104 -130
- package/dist/providers/account-actions.js +6 -9
- package/dist/state/chats.d.ts +1 -0
- package/dist/state/chats.js +6 -11
- package/dist/state/provider-accounts.d.ts +1 -1
- package/dist/state/provider-accounts.js +2 -8
- package/dist/transport.d.ts +2 -0
- package/dist/transport.js +14 -0
- package/dist/usage/ChartLogo.d.ts +5 -0
- package/dist/usage/ChartLogo.js +48 -0
- package/dist/usage/LimitsList.js +6 -16
- package/dist/usage/UsageBreakdown.js +17 -40
- package/dist/usage/UsageLimits.js +183 -211
- package/dist/usage/UsagePage.js +3 -17
- package/dist/usage/UsageSummary.js +4 -9
- package/dist/usage/limits.js +16 -31
- package/dist/usage/summary.d.ts +1 -1
- package/dist/usage/summary.js +3 -5
- package/package.json +26 -26
- package/src/agents/AccountDot.tsx +1 -0
- package/src/agents/AgentIcon.tsx +2 -0
- package/src/agents/AgentModelLabel.tsx +4 -6
- package/src/agents/ModelOptionControl.tsx +8 -0
- package/src/agents/account-limits.ts +3 -0
- package/src/agents/accounts.ts +12 -0
- package/src/agents/model-name.ts +13 -1
- package/src/agents/model-options.ts +2 -0
- package/src/agents/model-requirement.ts +4 -0
- package/src/agents/option-words.ts +2 -0
- package/src/agents/provider-paths.ts +8 -3
- package/src/agents/status-look.ts +1 -0
- package/src/chat/account-choice.ts +25 -19
- package/src/chat/actions.ts +5 -0
- package/src/chat/attachments.ts +8 -0
- package/src/chat/bookmarks.ts +13 -1
- package/src/chat/chat-client.ts +63 -0
- package/src/chat/chat-references.ts +3 -0
- package/src/chat/composer-effort.ts +5 -0
- package/src/chat/composer-send.ts +4 -0
- package/src/chat/drafts.ts +21 -17
- package/src/chat/forks.ts +4 -0
- package/src/chat/guards.ts +2 -0
- package/src/chat/index.ts +7 -0
- package/src/chat/logic/ansi.ts +47 -0
- package/src/chat/logic/bookmarks.ts +7 -0
- package/src/chat/logic/command-looks.ts +29 -0
- package/src/chat/logic/context-usage.ts +3 -0
- package/src/chat/logic/continue-after-stop.ts +5 -0
- package/src/chat/logic/effort.ts +4 -0
- package/src/chat/logic/embedded-code.ts +63 -0
- package/src/chat/logic/fork.ts +22 -0
- package/src/chat/logic/generated-image.ts +7 -0
- package/src/chat/logic/goal.ts +7 -0
- package/src/chat/logic/handback.ts +2 -0
- package/src/chat/logic/limit.ts +8 -0
- package/src/chat/logic/picker-entries.ts +16 -4
- package/src/chat/logic/resume-compaction.ts +22 -5
- package/src/chat/logic/scrubber.ts +38 -5
- package/src/chat/logic/thought.ts +5 -0
- package/src/chat/logic/thread-cards.ts +6 -0
- package/src/chat/logic/timeline-copy.ts +4 -9
- package/src/chat/logic/timeline-target.ts +15 -0
- package/src/chat/logic/timeline.ts +113 -10
- package/src/chat/logic/tools.ts +30 -0
- package/src/chat/logic/visual-height.ts +5 -0
- package/src/chat/logic/visual-viewport.ts +1 -0
- package/src/chat/logic/welcome.ts +3 -0
- package/src/chat/logic/workflow.ts +26 -7
- package/src/chat/mentions.ts +56 -0
- package/src/chat/pending-prompts.ts +16 -0
- package/src/chat/persisted-json.ts +15 -0
- package/src/chat/preferences.ts +16 -0
- package/src/chat/prompt-hold.ts +2 -0
- package/src/chat/quote.ts +7 -0
- package/src/chat/reading-width.ts +1 -0
- package/src/chat/recent-messages.ts +5 -0
- package/src/chat/resume-compaction-dismissals.ts +1 -0
- package/src/chat/stash.ts +12 -0
- package/src/chat/subagent-conversation.ts +24 -4
- package/src/chat/subagent-list.ts +14 -0
- package/src/chat/subagent-support.ts +1 -0
- package/src/chat/subagent-view.ts +9 -0
- package/src/chat/thumbnails.ts +14 -0
- package/src/chat/timeline-flash.ts +2 -0
- package/src/chat/timeline-scroll.ts +23 -0
- package/src/chat/ui/AccountPill.tsx +4 -0
- package/src/chat/ui/AnsiOutput.tsx +1 -0
- package/src/chat/ui/BookmarkMarker.tsx +5 -0
- package/src/chat/ui/BookmarkSubmenu.tsx +1 -0
- package/src/chat/ui/ChatActivity.tsx +13 -0
- package/src/chat/ui/CodeBlock.tsx +8 -0
- package/src/chat/ui/Composer.tsx +15 -0
- package/src/chat/ui/ComposerInput.tsx +22 -0
- package/src/chat/ui/DiffPool.tsx +3 -0
- package/src/chat/ui/EditDiff.tsx +5 -0
- package/src/chat/ui/GoalDock.tsx +13 -1
- package/src/chat/ui/ImageView.tsx +11 -0
- package/src/chat/ui/LimitState.tsx +23 -6
- package/src/chat/ui/Markdown.tsx +41 -0
- package/src/chat/ui/MermaidBlock.tsx +16 -0
- package/src/chat/ui/MessageActions.tsx +8 -0
- package/src/chat/ui/ModelMarks.tsx +1 -0
- package/src/chat/ui/Pickers.tsx +26 -0
- package/src/chat/ui/PromptComposer.tsx +2 -0
- package/src/chat/ui/PromptEditor.tsx +6 -0
- package/src/chat/ui/QuoteButton.tsx +12 -0
- package/src/chat/ui/ReferenceChip.tsx +3 -0
- package/src/chat/ui/ResumeCompactionDock.tsx +1 -0
- package/src/chat/ui/RowTime.tsx +1 -0
- package/src/chat/ui/RunSettings.tsx +38 -0
- package/src/chat/ui/Scrubber.tsx +14 -0
- package/src/chat/ui/SessionLine.tsx +1 -0
- package/src/chat/ui/ShellCommand.tsx +32 -0
- package/src/chat/ui/SubagentControls.tsx +7 -0
- package/src/chat/ui/SubagentInfo.tsx +1 -0
- package/src/chat/ui/SubagentStopButton.tsx +6 -0
- package/src/chat/ui/SubagentTimeline.tsx +10 -0
- package/src/chat/ui/Timeline.tsx +119 -0
- package/src/chat/ui/TimelineMenu.tsx +5 -0
- package/src/chat/ui/UnifiedDiff.tsx +6 -0
- package/src/chat/ui/UploadThumb.tsx +2 -0
- package/src/chat/ui/VisualDialogs.tsx +3 -0
- package/src/chat/ui/VisualFrame.tsx +15 -0
- package/src/chat/ui/Welcome.tsx +1 -0
- package/src/chat/ui/chip-clipboard.ts +20 -0
- package/src/chat/ui/code-lines.ts +14 -0
- package/src/chat/ui/code-theme.ts +1 -0
- package/src/chat/ui/composer/ComposerControls.tsx +5 -0
- package/src/chat/ui/composer/ComposerMenu.tsx +12 -0
- package/src/chat/ui/composer/DraftParts.tsx +2 -0
- package/src/chat/ui/composer/QueuedMessages.tsx +4 -0
- package/src/chat/ui/composer/chip-paste.ts +16 -0
- package/src/chat/ui/composer/chips.ts +6 -0
- package/src/chat/ui/composer/editor.ts +9 -0
- package/src/chat/ui/composer/insert.ts +2 -0
- package/src/chat/ui/composer/key-handler.ts +39 -0
- package/src/chat/ui/composer/keys.ts +23 -0
- package/src/chat/ui/composer/placeholder.ts +6 -0
- package/src/chat/ui/composer/prompt-picks.ts +1 -0
- package/src/chat/ui/composer/surface.ts +5 -0
- package/src/chat/ui/composer/use-chat-controls.ts +13 -0
- package/src/chat/ui/composer/use-compaction-offer.ts +3 -0
- package/src/chat/ui/composer/use-composer-menus.ts +2 -0
- package/src/chat/ui/composer/use-composer-submit.ts +27 -0
- package/src/chat/ui/composer/use-continuable-turn.ts +3 -5
- package/src/chat/ui/composer/use-draft-files.ts +24 -0
- package/src/chat/ui/composer/use-effort-stepper.ts +8 -0
- package/src/chat/ui/composer/use-notice.ts +4 -1
- package/src/chat/ui/composer/use-pending-requests.ts +3 -0
- package/src/chat/ui/composer/use-prompt-history.ts +20 -11
- package/src/chat/ui/composer/use-prompt-hold.ts +3 -0
- package/src/chat/ui/composer/use-prompt-menus.ts +34 -14
- package/src/chat/ui/composer/use-take-back.ts +20 -2
- package/src/chat/ui/diff/ApprovalReview.tsx +18 -15
- package/src/chat/ui/diff/DiffFallbackBoundary.tsx +1 -0
- package/src/chat/ui/diff/DiffOmitted.tsx +1 -0
- package/src/chat/ui/diff/DiffStack.tsx +2 -0
- package/src/chat/ui/diff/DiffUnavailable.tsx +1 -0
- package/src/chat/ui/diff/EditorEditDiff.tsx +13 -0
- package/src/chat/ui/diff/EditorPatchDiff.tsx +4 -0
- package/src/chat/ui/diff/LegacyDiffPool.tsx +2 -0
- package/src/chat/ui/diff/LegacyEditDiff.tsx +2 -0
- package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +8 -0
- package/src/chat/ui/diff/RawDiff.tsx +1 -0
- package/src/chat/ui/diff/ReviewDiff.tsx +1 -0
- package/src/chat/ui/diff/diff-source-budget.ts +8 -0
- package/src/chat/ui/diff/editor-edit-model.ts +4 -0
- package/src/chat/ui/diff/review-plan.ts +9 -0
- package/src/chat/ui/diff/review-settle.ts +1 -0
- package/src/chat/ui/diff/syntax-runtime.ts +52 -0
- package/src/chat/ui/diff/use-review-stack.ts +9 -0
- package/src/chat/ui/diff-syntax.ts +12 -0
- package/src/chat/ui/diff-theme.ts +2 -0
- package/src/chat/ui/file-links.ts +2 -0
- package/src/chat/ui/find-reveal.ts +1 -0
- package/src/chat/ui/full-diff.ts +1 -0
- package/src/chat/ui/highlighter.ts +29 -15
- package/src/chat/ui/icons.tsx +2 -4
- package/src/chat/ui/index.ts +4 -0
- package/src/chat/ui/intelligent-ui/UiBlockFrame.tsx +25 -0
- package/src/chat/ui/intelligent-ui/UiFallbackPart.tsx +1 -0
- package/src/chat/ui/intelligent-ui/UiReply.tsx +63 -0
- package/src/chat/ui/intelligent-ui/block-local.ts +5 -0
- package/src/chat/ui/intelligent-ui/chart-data.ts +15 -0
- package/src/chat/ui/intelligent-ui/node-text.ts +17 -0
- package/src/chat/ui/intelligent-ui/renderers/binding.ts +1 -0
- package/src/chat/ui/intelligent-ui/renderers/chart.tsx +31 -0
- package/src/chat/ui/intelligent-ui/renderers/choices.tsx +4 -0
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +18 -0
- package/src/chat/ui/intelligent-ui/renderers/data.tsx +11 -0
- package/src/chat/ui/intelligent-ui/renderers/inputs.tsx +13 -0
- package/src/chat/ui/intelligent-ui/renderers/links.tsx +9 -0
- package/src/chat/ui/intelligent-ui/renderers/map-slots.ts +15 -0
- package/src/chat/ui/intelligent-ui/renderers/map-style.ts +15 -0
- package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +48 -0
- package/src/chat/ui/intelligent-ui/renderers/map.tsx +20 -0
- package/src/chat/ui/intelligent-ui/renderers/place-point.ts +3 -0
- package/src/chat/ui/intelligent-ui/renderers/structure.tsx +3 -0
- package/src/chat/ui/intelligent-ui/renderers/text.tsx +8 -0
- package/src/chat/ui/intelligent-ui/reply-parts.ts +5 -0
- package/src/chat/ui/intelligent-ui/table-data.ts +17 -0
- package/src/chat/ui/intelligent-ui/use-in-view.ts +4 -0
- package/src/chat/ui/intelligent-ui/use-later.ts +4 -0
- package/src/chat/ui/intelligent-ui/use-truncated.ts +5 -0
- package/src/chat/ui/intelligent-ui/use-ui-links.ts +29 -0
- package/src/chat/ui/intelligent-ui/use-ui-queries.ts +60 -0
- package/src/chat/ui/markdown-blocks.ts +64 -0
- package/src/chat/ui/mermaid.ts +4 -0
- package/src/chat/ui/quote-selection.ts +10 -0
- package/src/chat/ui/rehype-chips.ts +5 -0
- package/src/chat/ui/rehype-fade.ts +2 -0
- package/src/chat/ui/remark-html-as-text.ts +5 -0
- package/src/chat/ui/reveal.ts +18 -0
- package/src/chat/ui/rows/ForksRow.tsx +5 -0
- package/src/chat/ui/rows/GeneratedImageRow.tsx +10 -0
- package/src/chat/ui/rows/MessageRows.tsx +29 -5
- package/src/chat/ui/rows/RowContainer.tsx +1 -0
- package/src/chat/ui/rows/Rows.tsx +2 -0
- package/src/chat/ui/rows/SubagentRow.tsx +13 -0
- package/src/chat/ui/rows/TaskRow.tsx +7 -0
- package/src/chat/ui/rows/VisualRow.tsx +4 -0
- package/src/chat/ui/rows/WorkRows.tsx +46 -0
- package/src/chat/ui/rows/WorkflowRow.tsx +10 -0
- package/src/chat/ui/rows/row-rhythm.ts +7 -5
- package/src/chat/ui/theme-watch.ts +8 -7
- package/src/chat/ui/thread-references.ts +7 -0
- package/src/chat/ui/use-diff-source-tokens.ts +8 -0
- package/src/chat/ui/useToggleSet.ts +3 -0
- package/src/chat/ui/visual-theme.ts +30 -0
- package/src/chat/visual-bridge.ts +23 -0
- package/src/chat/visual-viewport.ts +12 -0
- package/src/host-hooks.ts +6 -4
- package/src/host.ts +2 -0
- package/src/index.ts +3 -0
- package/src/lazy.tsx +9 -0
- package/src/mounted-registry.ts +4 -0
- package/src/port-transport.ts +32 -0
- package/src/prompts/index.ts +2 -0
- package/src/prompts/logic/focus.ts +5 -0
- package/src/prompts/logic/keys.ts +12 -0
- package/src/prompts/logic/prompts.ts +8 -0
- package/src/prompts/logic/subjects.ts +8 -0
- package/src/prompts/logic/useFocusAfterAnswer.ts +2 -0
- package/src/prompts/logic/usePromptSession.ts +13 -1
- package/src/prompts/ui/ApprovalBody.tsx +2 -0
- package/src/prompts/ui/PromptActions.tsx +2 -0
- package/src/prompts/ui/PromptCard.tsx +6 -0
- package/src/prompts/ui/PromptView.tsx +6 -0
- package/src/prompts/ui/QuestionBody.tsx +11 -0
- package/src/providers/AccountColors.tsx +1 -0
- package/src/providers/AccountDetail.tsx +7 -0
- package/src/providers/AccountVariables.tsx +2 -0
- package/src/providers/AddAccountForm.tsx +5 -1
- package/src/providers/CliDetail.tsx +6 -5
- package/src/providers/InstallPage.tsx +11 -0
- package/src/providers/ProviderList.tsx +3 -0
- package/src/providers/ProvidersPane.tsx +18 -0
- package/src/providers/account-actions.ts +10 -8
- package/src/providers/install-steps.ts +3 -0
- package/src/providers/pane-target.ts +5 -0
- package/src/providers/provider-abilities.ts +1 -0
- package/src/providers/provider-groups.ts +6 -0
- package/src/providers/variables.ts +12 -0
- package/src/scope.ts +2 -0
- package/src/state/chats.ts +61 -14
- package/src/state/index.ts +2 -0
- package/src/state/provider-accounts.ts +7 -9
- package/src/state/providers.ts +1 -0
- package/src/state/usage.ts +6 -0
- package/src/storage.ts +18 -0
- package/src/testing/prompts.ts +5 -0
- package/src/transport.ts +18 -0
- package/src/usage/ChartLogo.tsx +12 -0
- package/src/usage/LimitsList.tsx +7 -8
- package/src/usage/UsageBreakdown.tsx +11 -4
- package/src/usage/UsageChart.tsx +5 -0
- package/src/usage/UsageLimits.tsx +10 -7
- package/src/usage/UsageLimitsCard.tsx +2 -0
- package/src/usage/UsagePage.tsx +16 -19
- package/src/usage/UsageSummary.tsx +4 -5
- package/src/usage/UsageTiles.tsx +2 -0
- package/src/usage/format.ts +7 -0
- package/src/usage/limit-groups.ts +14 -0
- package/src/usage/limits.ts +11 -13
- package/src/usage/money.ts +1 -0
- package/src/usage/summary.ts +15 -7
|
@@ -34,9 +34,11 @@ function indentInFence(e: KeyboardEvent, view: EditorView): boolean {
|
|
|
34
34
|
const { state } = view;
|
|
35
35
|
const { from, to, head } = state.selection.main;
|
|
36
36
|
const tree = ensureSyntaxTree(state, state.doc.length, 50) ?? syntaxTree(state);
|
|
37
|
+
|
|
37
38
|
if (!inFenceBody(tree, state.doc.toString(), head)) {
|
|
38
39
|
return false;
|
|
39
40
|
}
|
|
41
|
+
|
|
40
42
|
// Handled even when there is nothing to outdent, so Shift+Tab never throws the focus out of a block.
|
|
41
43
|
if (e.shiftKey) {
|
|
42
44
|
indentLess(view);
|
|
@@ -45,48 +47,62 @@ function indentInFence(e: KeyboardEvent, view: EditorView): boolean {
|
|
|
45
47
|
} else {
|
|
46
48
|
view.dispatch(state.replaceSelection(tabSpaces(head - state.doc.lineAt(head).from)), { scrollIntoView: true, userEvent: 'input' });
|
|
47
49
|
}
|
|
50
|
+
|
|
48
51
|
return true;
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
/* The keys an open picker takes: the arrows walk it, and Tab (or Enter, outside the commands) picks. */
|
|
52
55
|
export function pickInMenu(e: KeyboardEvent, menus: ComposerMenus): boolean {
|
|
53
56
|
const { activeIndex } = menus;
|
|
57
|
+
|
|
54
58
|
if (menus.commandMenuOpen) {
|
|
55
59
|
if (menus.moveInMenu(e.key, menus.commands.length)) {
|
|
56
60
|
return true;
|
|
57
61
|
}
|
|
62
|
+
|
|
58
63
|
if (e.key === 'Tab') {
|
|
59
64
|
menus.completeCommand(menus.commands[activeIndex]!);
|
|
65
|
+
|
|
60
66
|
return true;
|
|
61
67
|
}
|
|
62
68
|
}
|
|
69
|
+
|
|
63
70
|
if (menus.skillMenuOpen) {
|
|
64
71
|
if (menus.moveInMenu(e.key, menus.skillMatches.length)) {
|
|
65
72
|
return true;
|
|
66
73
|
}
|
|
74
|
+
|
|
67
75
|
if (e.key === 'Tab' || e.key === 'Enter') {
|
|
68
76
|
menus.chooseSkill((menus.skillMatches[activeIndex] ?? menus.skillMatches[0]!).name);
|
|
77
|
+
|
|
69
78
|
return true;
|
|
70
79
|
}
|
|
71
80
|
}
|
|
81
|
+
|
|
72
82
|
if (menus.mentionMenuOpen && menus.mentionCount > 0) {
|
|
73
83
|
if (menus.moveInMenu(e.key, menus.mentionCount)) {
|
|
74
84
|
return true;
|
|
75
85
|
}
|
|
86
|
+
|
|
76
87
|
if (e.key === 'Tab' || e.key === 'Enter') {
|
|
77
88
|
menus.chooseMentionAt(activeIndex);
|
|
89
|
+
|
|
78
90
|
return true;
|
|
79
91
|
}
|
|
80
92
|
}
|
|
93
|
+
|
|
81
94
|
if (menus.referenceMenuOpen && menus.referenceMatches.length > 0) {
|
|
82
95
|
if (menus.moveInMenu(e.key, menus.referenceMatches.length)) {
|
|
83
96
|
return true;
|
|
84
97
|
}
|
|
98
|
+
|
|
85
99
|
if (e.key === 'Tab' || e.key === 'Enter') {
|
|
86
100
|
menus.chooseReferenceAt(activeIndex);
|
|
101
|
+
|
|
87
102
|
return true;
|
|
88
103
|
}
|
|
89
104
|
}
|
|
105
|
+
|
|
90
106
|
return false;
|
|
91
107
|
}
|
|
92
108
|
|
|
@@ -98,6 +114,7 @@ function enter(e: KeyboardEvent, view: EditorView, { host, sendKey, submit }: Ke
|
|
|
98
114
|
const tree = ensureSyntaxTree(state, state.doc.length, 50) ?? syntaxTree(state);
|
|
99
115
|
const line = state.doc.lineAt(head);
|
|
100
116
|
const list = from === to && !inCode(tree, state.doc.toString(), head) ? listItemAt(line.text) : null;
|
|
117
|
+
|
|
101
118
|
const action = enterAction(
|
|
102
119
|
{ shift: e.shiftKey, mod: isModHeld(e, host.isApplePlatform()), alt: e.altKey },
|
|
103
120
|
{
|
|
@@ -109,9 +126,11 @@ function enter(e: KeyboardEvent, view: EditorView, { host, sendKey, submit }: Ke
|
|
|
109
126
|
startsNewChat: host.openNewChat !== null
|
|
110
127
|
}
|
|
111
128
|
);
|
|
129
|
+
|
|
112
130
|
if (action === 'newline') {
|
|
113
131
|
return insertNewline(view);
|
|
114
132
|
}
|
|
133
|
+
|
|
115
134
|
if (action === 'continue-list') {
|
|
116
135
|
if (list) {
|
|
117
136
|
view.dispatch({
|
|
@@ -121,57 +140,77 @@ function enter(e: KeyboardEvent, view: EditorView, { host, sendKey, submit }: Ke
|
|
|
121
140
|
userEvent: 'input'
|
|
122
141
|
});
|
|
123
142
|
}
|
|
143
|
+
|
|
124
144
|
return true;
|
|
125
145
|
}
|
|
146
|
+
|
|
126
147
|
if (action === 'leave-list') {
|
|
127
148
|
view.dispatch({ changes: { from: line.from, to: line.to }, selection: { anchor: line.from }, userEvent: 'delete' });
|
|
149
|
+
|
|
128
150
|
return true;
|
|
129
151
|
}
|
|
152
|
+
|
|
130
153
|
submit(SEND_HOW[action]);
|
|
154
|
+
|
|
131
155
|
return true;
|
|
132
156
|
}
|
|
133
157
|
|
|
134
158
|
/* Runs before the editor's own keymap; true means the key is handled and its default prevented. */
|
|
135
159
|
export function composerKeyHandler(input: KeyHandlerInput): (e: KeyboardEvent, view: EditorView) => boolean {
|
|
136
160
|
const { chatId, host, text, history } = input;
|
|
161
|
+
|
|
137
162
|
return (e, view) => {
|
|
138
163
|
input.noteKey(e);
|
|
164
|
+
|
|
139
165
|
// Escape leaves the node, unless it first has a recalled prompt to put back.
|
|
140
166
|
if (e.key === 'Escape' && !e.isComposing) {
|
|
141
167
|
if (!history.leave()) {
|
|
142
168
|
return false;
|
|
143
169
|
}
|
|
170
|
+
|
|
144
171
|
e.stopPropagation();
|
|
172
|
+
|
|
145
173
|
return true;
|
|
146
174
|
}
|
|
175
|
+
|
|
147
176
|
// The app's own shortcuts stay the app's while you type: Mod+Shift+Enter would otherwise send as well.
|
|
148
177
|
if (host.isAppShortcut(e)) {
|
|
149
178
|
return false;
|
|
150
179
|
}
|
|
180
|
+
|
|
151
181
|
e.stopPropagation();
|
|
182
|
+
|
|
152
183
|
// A key inside an IME composition belongs to the composition, Enter and the arrows included.
|
|
153
184
|
if (e.isComposing) {
|
|
154
185
|
return false;
|
|
155
186
|
}
|
|
187
|
+
|
|
156
188
|
// Reading back through a long answer should not mean leaving the box you are typing in.
|
|
157
189
|
if (e.key === 'PageUp' || e.key === 'PageDown') {
|
|
158
190
|
return pageTimeline(chatId, e.key === 'PageUp' ? -1 : 1);
|
|
159
191
|
}
|
|
192
|
+
|
|
160
193
|
if (matchesShortcut(STASH_SHORTCUT, e, host.isApplePlatform())) {
|
|
161
194
|
input.toggleStash();
|
|
195
|
+
|
|
162
196
|
return true;
|
|
163
197
|
}
|
|
198
|
+
|
|
164
199
|
if (pickInMenu(e, input.menus)) {
|
|
165
200
|
return true;
|
|
166
201
|
}
|
|
202
|
+
|
|
167
203
|
if (e.key === 'Tab' && !e.altKey && !e.metaKey && !e.ctrlKey && indentInFence(e, view)) {
|
|
168
204
|
return true;
|
|
169
205
|
}
|
|
206
|
+
|
|
170
207
|
if (e.key === 'Enter') {
|
|
171
208
|
return enter(e, view, input);
|
|
172
209
|
}
|
|
210
|
+
|
|
173
211
|
const { from, to } = view.state.selection.main;
|
|
174
212
|
const direction = recallDirection({ key: e.key, text, from, to, recalled: history.recalled(text) });
|
|
213
|
+
|
|
175
214
|
return direction !== null && history.recall(direction);
|
|
176
215
|
};
|
|
177
216
|
}
|
|
@@ -40,11 +40,14 @@ const LIST_ITEM = /^([ \t]*)(?:([-*+])|(\d{1,9})([.)]))([ \t]+)(\[[ xX]\](?:[ \t
|
|
|
40
40
|
/* The list item a line starts, if it starts one. */
|
|
41
41
|
export function listItemAt(line: string): ListItem | null {
|
|
42
42
|
const match = LIST_ITEM.exec(line);
|
|
43
|
+
|
|
43
44
|
if (match === null) {
|
|
44
45
|
return null;
|
|
45
46
|
}
|
|
47
|
+
|
|
46
48
|
const [prefix, indent, bullet, number, delimiter, space, task] = match;
|
|
47
49
|
const marker = bullet ?? `${Number(number) + 1}${delimiter}`;
|
|
50
|
+
|
|
48
51
|
return { prefix, next: `${indent}${marker}${space}${task ? '[ ] ' : ''}`, empty: line.slice(prefix.length).trim() === '' };
|
|
49
52
|
}
|
|
50
53
|
|
|
@@ -60,25 +63,32 @@ export function enterAction(
|
|
|
60
63
|
{ inOpenFence, list, column, sendKey = 'enter', multiline = false, startsNewChat = false }: EnterContext
|
|
61
64
|
): EnterAction {
|
|
62
65
|
const modOnly = modSends(sendKey, multiline);
|
|
66
|
+
|
|
63
67
|
if (keys.mod) {
|
|
64
68
|
if (keys.alt && startsNewChat) {
|
|
65
69
|
return 'send-and-new';
|
|
66
70
|
}
|
|
71
|
+
|
|
67
72
|
return keys.alt || (modOnly && keys.shift) ? 'send-alternate' : 'send';
|
|
68
73
|
}
|
|
74
|
+
|
|
69
75
|
if (keys.shift || inOpenFence) {
|
|
70
76
|
return 'newline';
|
|
71
77
|
}
|
|
78
|
+
|
|
72
79
|
if (list !== null) {
|
|
73
80
|
// A caret in front of the marker moves the item down rather than splitting its marker.
|
|
74
81
|
if (column < list.prefix.length) {
|
|
75
82
|
return 'newline';
|
|
76
83
|
}
|
|
84
|
+
|
|
77
85
|
return list.empty ? 'leave-list' : 'continue-list';
|
|
78
86
|
}
|
|
87
|
+
|
|
79
88
|
if (keys.alt) {
|
|
80
89
|
return 'send-alternate';
|
|
81
90
|
}
|
|
91
|
+
|
|
82
92
|
return modOnly ? 'newline' : 'send';
|
|
83
93
|
}
|
|
84
94
|
|
|
@@ -89,6 +99,7 @@ function enclosingFence(tree: Tree, pos: number): SyntaxNode | null {
|
|
|
89
99
|
return node;
|
|
90
100
|
}
|
|
91
101
|
}
|
|
102
|
+
|
|
92
103
|
return null;
|
|
93
104
|
}
|
|
94
105
|
|
|
@@ -100,16 +111,20 @@ function isOpenFence(fence: SyntaxNode): boolean {
|
|
|
100
111
|
/* Whether `pos` sits inside a fenced code block that has an opening fence and no closing one yet. */
|
|
101
112
|
export function inOpenFence(tree: Tree, pos: number): boolean {
|
|
102
113
|
const fence = enclosingFence(tree, pos);
|
|
114
|
+
|
|
103
115
|
return fence !== null && pos > fence.from && isOpenFence(fence);
|
|
104
116
|
}
|
|
105
117
|
|
|
106
118
|
/* Whether `pos` sits in the body of a fenced code block, open or closed: below its opening line and before its end. */
|
|
107
119
|
export function inFenceBody(tree: Tree, text: string, pos: number): boolean {
|
|
108
120
|
const fence = enclosingFence(tree, pos);
|
|
121
|
+
|
|
109
122
|
if (fence === null) {
|
|
110
123
|
return false;
|
|
111
124
|
}
|
|
125
|
+
|
|
112
126
|
const openingEnd = text.indexOf('\n', fence.from);
|
|
127
|
+
|
|
113
128
|
return openingEnd !== -1 && pos > openingEnd && (pos < fence.to || isOpenFence(fence));
|
|
114
129
|
}
|
|
115
130
|
|
|
@@ -127,18 +142,23 @@ const INLINE_BLOCK = /^(Paragraph|ATXHeading\d|SetextHeading\d)$/;
|
|
|
127
142
|
*/
|
|
128
143
|
export function inCode(tree: Tree, text: string, pos: number): boolean {
|
|
129
144
|
let blockFrom: number | null = null;
|
|
145
|
+
|
|
130
146
|
for (let node: SyntaxNode | null = tree.resolveInner(pos, -1); node !== null; node = node.parent) {
|
|
131
147
|
if (node.name === 'FencedCode') {
|
|
132
148
|
return pos > node.from && (pos < node.to || isOpenFence(node));
|
|
133
149
|
}
|
|
150
|
+
|
|
134
151
|
if (node.name === 'InlineCode' && pos > node.from && pos < node.to) {
|
|
135
152
|
return true;
|
|
136
153
|
}
|
|
154
|
+
|
|
137
155
|
if (blockFrom === null && INLINE_BLOCK.test(node.name)) {
|
|
138
156
|
blockFrom = node.from;
|
|
139
157
|
}
|
|
140
158
|
}
|
|
159
|
+
|
|
141
160
|
let from = blockFrom ?? text.lastIndexOf('\n', pos - 1) + 1;
|
|
161
|
+
|
|
142
162
|
tree.iterate({
|
|
143
163
|
from,
|
|
144
164
|
to: pos,
|
|
@@ -148,6 +168,7 @@ export function inCode(tree: Tree, text: string, pos: number): boolean {
|
|
|
148
168
|
}
|
|
149
169
|
}
|
|
150
170
|
});
|
|
171
|
+
|
|
151
172
|
return /(^|[^\\])`/.test(text.slice(from, pos));
|
|
152
173
|
}
|
|
153
174
|
|
|
@@ -169,8 +190,10 @@ export function recallDirection({ key, text, from, to, recalled }: RecallContext
|
|
|
169
190
|
if (key === 'ArrowUp' && (text === '' || (recalled && from === 0))) {
|
|
170
191
|
return -1;
|
|
171
192
|
}
|
|
193
|
+
|
|
172
194
|
if (key === 'ArrowDown' && recalled && to === text.length) {
|
|
173
195
|
return 1;
|
|
174
196
|
}
|
|
197
|
+
|
|
175
198
|
return null;
|
|
176
199
|
}
|
|
@@ -10,12 +10,15 @@ function hintedPlaceholder(lead: string, joiner: string, hints: ReadonlyArray<{
|
|
|
10
10
|
const extra = document.createElement('span');
|
|
11
11
|
extra.className = 'composer-hints-extra';
|
|
12
12
|
extra.append(joiner);
|
|
13
|
+
|
|
13
14
|
for (const hint of hints) {
|
|
14
15
|
const cap = document.createElement('kbd');
|
|
15
16
|
cap.textContent = hint.key;
|
|
16
17
|
extra.append(cap, hint.label);
|
|
17
18
|
}
|
|
19
|
+
|
|
18
20
|
root.append(lead, extra);
|
|
21
|
+
|
|
19
22
|
return root;
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -32,13 +35,16 @@ export function useHintedPlaceholder({ chatId, disabled, readOnly, mentionable,
|
|
|
32
35
|
const { t } = useTranslation('agent-chat');
|
|
33
36
|
const scope = useChatScope();
|
|
34
37
|
const lead = useHostComposerPlaceholder(scope.id, chatId);
|
|
38
|
+
|
|
35
39
|
return useMemo(() => {
|
|
36
40
|
if (disabled) {
|
|
37
41
|
return t('composer.placeholder.disconnected');
|
|
38
42
|
}
|
|
43
|
+
|
|
39
44
|
if (readOnly) {
|
|
40
45
|
return t('composer.placeholder.readOnly');
|
|
41
46
|
}
|
|
47
|
+
|
|
42
48
|
return hintedPlaceholder(lead ?? t('composer.placeholder.lead'), t('composer.placeholder.joiner'), [
|
|
43
49
|
{ key: '/', label: t('composer.placeholder.commands') },
|
|
44
50
|
...(mentionable ? [{ key: '@', label: t('composer.placeholder.files') }] : []),
|
|
@@ -7,6 +7,7 @@ import type { PromptDraft } from './use-prompt-menus';
|
|
|
7
7
|
export function promptPicks(value: PromptDraft, referables: Referables): Pick<ChatSendExtras, 'mentions' | 'skills' | 'chats' | 'references'> {
|
|
8
8
|
const text = value.text.trim();
|
|
9
9
|
const tokens = referenceTokens([...value.chats, ...value.references], referables.items, value.referenceNames);
|
|
10
|
+
|
|
10
11
|
return {
|
|
11
12
|
mentions: presentMentions(text, value.mentions),
|
|
12
13
|
skills: presentSkills(text, value.skills),
|
|
@@ -33,13 +33,18 @@ const ACTIONS = [
|
|
|
33
33
|
export function surfacePartOf(target: EventTarget | null, surface: Element): 'input' | 'action' | 'surface' {
|
|
34
34
|
// Not `instanceof Element`, which fails for an element of another window.
|
|
35
35
|
const element = target as Element | null;
|
|
36
|
+
|
|
36
37
|
if (typeof element?.closest !== 'function' || !surface.contains(element)) {
|
|
37
38
|
return 'action';
|
|
38
39
|
}
|
|
40
|
+
|
|
39
41
|
const input = element.closest('.cm-editor');
|
|
42
|
+
|
|
40
43
|
if (input !== null && surface.contains(input)) {
|
|
41
44
|
return 'input';
|
|
42
45
|
}
|
|
46
|
+
|
|
43
47
|
const action = element.closest(ACTIONS);
|
|
48
|
+
|
|
44
49
|
return action !== null && surface.contains(action) ? 'action' : 'surface';
|
|
45
50
|
}
|
|
@@ -32,8 +32,10 @@ export function useChatControls({ chatId, info, notice: { setNotice, showError }
|
|
|
32
32
|
if (configuring.current) {
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
+
|
|
35
36
|
configuring.current = true;
|
|
36
37
|
setConfigurationPending(true);
|
|
38
|
+
|
|
37
39
|
void work()
|
|
38
40
|
.catch(showError)
|
|
39
41
|
.finally(() => {
|
|
@@ -49,6 +51,7 @@ export function useChatControls({ chatId, info, notice: { setNotice, showError }
|
|
|
49
51
|
if (patch.selection) {
|
|
50
52
|
rememberChatSelection(info.provider, patch.selection);
|
|
51
53
|
}
|
|
54
|
+
|
|
52
55
|
if (patch.account) {
|
|
53
56
|
rememberChatAccount(scope.id, info.provider, patch.account);
|
|
54
57
|
}
|
|
@@ -59,18 +62,23 @@ export function useChatControls({ chatId, info, notice: { setNotice, showError }
|
|
|
59
62
|
/* A model of another CLI re-points the whole chat; one of this CLI's own is a configure. */
|
|
60
63
|
const chooseModel = (provider: AgentKind, slug: string): void => {
|
|
61
64
|
const selection: ModelSelection = { model: slug, options: {} };
|
|
65
|
+
|
|
62
66
|
if (provider !== info.provider) {
|
|
63
67
|
runConfiguration(() => onRetarget(provider, selection).then(() => rememberChatSelection(provider, selection)));
|
|
68
|
+
|
|
64
69
|
return;
|
|
65
70
|
}
|
|
71
|
+
|
|
66
72
|
configure({ selection });
|
|
67
73
|
};
|
|
68
74
|
|
|
69
75
|
const stop = (shiftKey: boolean): void => {
|
|
70
76
|
if (composerStopOf(shiftKey) === 'turn') {
|
|
71
77
|
void actions.stopTurn(chatId, false).catch(showError);
|
|
78
|
+
|
|
72
79
|
return;
|
|
73
80
|
}
|
|
81
|
+
|
|
74
82
|
host.confirm.stopSubagents(scope.id, chatId, () => void actions.stopTurn(chatId, true).catch(showError));
|
|
75
83
|
};
|
|
76
84
|
|
|
@@ -81,8 +89,10 @@ export function useChatControls({ chatId, info, notice: { setNotice, showError }
|
|
|
81
89
|
} catch (e) {
|
|
82
90
|
if (errorCode(e) === 'chat-busy') {
|
|
83
91
|
setConfirmClear(true);
|
|
92
|
+
|
|
84
93
|
return;
|
|
85
94
|
}
|
|
95
|
+
|
|
86
96
|
setNotice(t('composer.notice.clearFailed'));
|
|
87
97
|
}
|
|
88
98
|
};
|
|
@@ -101,12 +111,15 @@ export function useChatControls({ chatId, info, notice: { setNotice, showError }
|
|
|
101
111
|
switch (name) {
|
|
102
112
|
case 'model':
|
|
103
113
|
setModelPickerOpen(true);
|
|
114
|
+
|
|
104
115
|
return true;
|
|
105
116
|
case 'compact':
|
|
106
117
|
void actions.compact(chatId).catch(() => undefined);
|
|
118
|
+
|
|
107
119
|
return true;
|
|
108
120
|
case 'clear':
|
|
109
121
|
void clearThread();
|
|
122
|
+
|
|
110
123
|
return true;
|
|
111
124
|
default:
|
|
112
125
|
return false;
|
|
@@ -12,8 +12,10 @@ const PAGE_CLOCK: DueClock = {
|
|
|
12
12
|
if (typeof window === 'undefined') {
|
|
13
13
|
return () => {};
|
|
14
14
|
}
|
|
15
|
+
|
|
15
16
|
window.addEventListener('focus', wake);
|
|
16
17
|
document.addEventListener('visibilitychange', wake);
|
|
18
|
+
|
|
17
19
|
return () => {
|
|
18
20
|
window.removeEventListener('focus', wake);
|
|
19
21
|
document.removeEventListener('visibilitychange', wake);
|
|
@@ -38,6 +40,7 @@ export function useCompactionOffer(chatId: string, info: ChatInfo, compaction: P
|
|
|
38
40
|
if (dueAt === null) {
|
|
39
41
|
return;
|
|
40
42
|
}
|
|
43
|
+
|
|
41
44
|
return watchDueAt(dueAt, setNow, PAGE_CLOCK);
|
|
42
45
|
}, [dueAt]);
|
|
43
46
|
|
|
@@ -34,6 +34,7 @@ export function useComposerMenus({ chatId, info, capabilities, providerName, dra
|
|
|
34
34
|
*/
|
|
35
35
|
useEffect(() => {
|
|
36
36
|
let stale = false;
|
|
37
|
+
|
|
37
38
|
scope.chats
|
|
38
39
|
.listSkills(chatId)
|
|
39
40
|
.then((found) => {
|
|
@@ -42,6 +43,7 @@ export function useComposerMenus({ chatId, info, capabilities, providerName, dra
|
|
|
42
43
|
}
|
|
43
44
|
})
|
|
44
45
|
.catch(() => undefined);
|
|
46
|
+
|
|
45
47
|
return () => {
|
|
46
48
|
stale = true;
|
|
47
49
|
};
|
|
@@ -62,9 +62,11 @@ export function useComposerSubmit({
|
|
|
62
62
|
/* Opens the host's new chat once the host took the message; a host that answers nothing took it. */
|
|
63
63
|
const afterSend = (sent: void | Promise<boolean>, andNew: boolean): void => {
|
|
64
64
|
const openNewChat = host.openNewChat;
|
|
65
|
+
|
|
65
66
|
if (!andNew || openNewChat === null) {
|
|
66
67
|
return;
|
|
67
68
|
}
|
|
69
|
+
|
|
68
70
|
void Promise.resolve(sent)
|
|
69
71
|
.then((taken) => {
|
|
70
72
|
if (taken !== false) {
|
|
@@ -79,39 +81,53 @@ export function useComposerSubmit({
|
|
|
79
81
|
const delivery = steerable && (alternate ? sendDelivery === 'queue' : sendDelivery === 'steer') ? 'steer' : 'queue';
|
|
80
82
|
const { text, quote, quoteSource } = draft;
|
|
81
83
|
const trimmed = text.trim();
|
|
84
|
+
|
|
82
85
|
if (isEmptyDraft(draft) || !writable || guard.tooLong) {
|
|
83
86
|
return;
|
|
84
87
|
}
|
|
88
|
+
|
|
85
89
|
// Recheck restored drafts and files that finished reading concurrently.
|
|
86
90
|
const rejected = checkAttachmentLimits(
|
|
87
91
|
0,
|
|
88
92
|
draft.attachments.map((attachment) => ({ ...attachment, bytes: uploadBytes(attachment) }))
|
|
89
93
|
).rejected[0];
|
|
94
|
+
|
|
90
95
|
if (rejected) {
|
|
91
96
|
setNotice(`${rejected.name}: ${rejected.reason}`);
|
|
97
|
+
|
|
92
98
|
return;
|
|
93
99
|
}
|
|
100
|
+
|
|
94
101
|
hold.release('send');
|
|
95
102
|
const { commandQuery } = menus;
|
|
96
103
|
const chosen = menus.commands[menus.activeIndex];
|
|
104
|
+
|
|
97
105
|
if (commandQuery !== null && chosen?.local && controls.runCommand(chosen.name)) {
|
|
98
106
|
box.clear();
|
|
107
|
+
|
|
99
108
|
return;
|
|
100
109
|
}
|
|
110
|
+
|
|
101
111
|
if (commandQuery !== null && chosen?.skill) {
|
|
102
112
|
menus.chooseSkill(chosen.name);
|
|
113
|
+
|
|
103
114
|
return;
|
|
104
115
|
}
|
|
116
|
+
|
|
105
117
|
// Whoever sends wants to see what comes back, wherever they were reading.
|
|
106
118
|
scrollTimelineToEnd(chatId, 'instant');
|
|
119
|
+
|
|
107
120
|
if (commandQuery !== null && chosen && !chosen.local) {
|
|
108
121
|
afterSend(onSend(`/${chosen.name}`, {}), how === 'and-new');
|
|
109
122
|
box.clear();
|
|
123
|
+
|
|
110
124
|
return;
|
|
111
125
|
}
|
|
126
|
+
|
|
112
127
|
const chats = presentReferences(trimmed, draft.chats, menus.referenceChips);
|
|
113
128
|
// A machine without `viewReferences` drops the field, so only the chats it does know reach it.
|
|
114
129
|
const references = menus.referables.chatsOnly ? [] : presentReferences(trimmed, draft.references, menus.referenceChips);
|
|
130
|
+
|
|
115
131
|
const sent = onSend(withQuote(quote, trimmed), {
|
|
116
132
|
delivery,
|
|
117
133
|
mentions: presentMentions(trimmed, draft.mentions),
|
|
@@ -121,6 +137,7 @@ export function useComposerSubmit({
|
|
|
121
137
|
attachments: draft.attachments,
|
|
122
138
|
references: references.length > 0 ? references : undefined
|
|
123
139
|
});
|
|
140
|
+
|
|
124
141
|
afterSend(sent, how === 'and-new');
|
|
125
142
|
box.clear();
|
|
126
143
|
menus.close();
|
|
@@ -129,9 +146,11 @@ export function useComposerSubmit({
|
|
|
129
146
|
|
|
130
147
|
// A menu row means the draft as it stands when it is picked, so the registration reads the latest submit.
|
|
131
148
|
const submitRef = useRef(submit);
|
|
149
|
+
|
|
132
150
|
useEffect(() => {
|
|
133
151
|
submitRef.current = submit;
|
|
134
152
|
});
|
|
153
|
+
|
|
135
154
|
useEffect(() => registerComposerSender(scope.keyOf(chatId), (how) => submitRef.current(how)), [scope, chatId]);
|
|
136
155
|
|
|
137
156
|
/*
|
|
@@ -142,11 +161,13 @@ export function useComposerSubmit({
|
|
|
142
161
|
const restoreStashed = (prompt: StashedPrompt): void => {
|
|
143
162
|
const stashedQuote = prompt.quote;
|
|
144
163
|
const here = stashedQuote !== undefined && stashedQuote.chatId === chatId;
|
|
164
|
+
|
|
145
165
|
const { chats, dropped } = restorableChats(
|
|
146
166
|
prompt.chats,
|
|
147
167
|
new Set(menus.referables.items.filter((item) => item.kind === 'chat').map((item) => item.id)),
|
|
148
168
|
chatId
|
|
149
169
|
);
|
|
170
|
+
|
|
150
171
|
setDraft((current) => ({
|
|
151
172
|
...current,
|
|
152
173
|
text: stashedQuote === undefined || here ? prompt.text : withQuote(stashedQuote.text, prompt.text),
|
|
@@ -156,9 +177,11 @@ export function useComposerSubmit({
|
|
|
156
177
|
references: [...prompt.references],
|
|
157
178
|
...(here ? { quote: stashedQuote.text, quoteSource: stashedQuote.itemId } : {})
|
|
158
179
|
}));
|
|
180
|
+
|
|
159
181
|
if (dropped > 0) {
|
|
160
182
|
setNotice(t('composer.notice.stashChatsDropped', { count: dropped }), 'info');
|
|
161
183
|
}
|
|
184
|
+
|
|
162
185
|
history.forget();
|
|
163
186
|
inputRef.current?.focus();
|
|
164
187
|
};
|
|
@@ -168,6 +191,7 @@ export function useComposerSubmit({
|
|
|
168
191
|
if (!writable) {
|
|
169
192
|
return;
|
|
170
193
|
}
|
|
194
|
+
|
|
171
195
|
scrollTimelineToEnd(chatId, 'instant');
|
|
172
196
|
afterSend(onSend(CONTINUE_PROMPT, {}), false);
|
|
173
197
|
};
|
|
@@ -176,11 +200,14 @@ export function useComposerSubmit({
|
|
|
176
200
|
const toggleStash = (): void => {
|
|
177
201
|
if (isEmptyDraft(draft)) {
|
|
178
202
|
const newest = useStash.getState().prompts[0];
|
|
203
|
+
|
|
179
204
|
if (newest) {
|
|
180
205
|
restoreStashed(newest);
|
|
181
206
|
}
|
|
207
|
+
|
|
182
208
|
return;
|
|
183
209
|
}
|
|
210
|
+
|
|
184
211
|
if (stashDraft(draft, chatId)) {
|
|
185
212
|
box.clear();
|
|
186
213
|
menus.close();
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
1
|
import type { ChatInfo, ChatItem } from '@adecore/agent-contracts';
|
|
3
2
|
import { useChatRow } from '../../../state/chats';
|
|
4
3
|
import { continuableTurn } from '../../logic/continue-after-stop';
|
|
@@ -7,8 +6,7 @@ import { continuableTurn } from '../../logic/continue-after-stop';
|
|
|
7
6
|
export function useContinuableTurn(chatId: string, info: ChatInfo): string | null {
|
|
8
7
|
const order = useChatRow(chatId, (row) => row?.order);
|
|
9
8
|
const structure = useChatRow(chatId, (row) => row?.structure);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}, [info, order, structure]);
|
|
9
|
+
const items = (order ?? []).map((id) => structure?.[id]).filter((item): item is ChatItem => item !== undefined);
|
|
10
|
+
|
|
11
|
+
return continuableTurn(info, items);
|
|
14
12
|
}
|