@adecore/agents-react 0.39.0 → 0.40.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/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 +27 -27
- 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
|
@@ -40,6 +40,7 @@ function ReadyDiff({
|
|
|
40
40
|
const theme = useHostCodeThemes()[mode];
|
|
41
41
|
const language = getFiletypeFromFileName(path);
|
|
42
42
|
const tokens = useDiffSourceTokens(document, language, theme);
|
|
43
|
+
|
|
43
44
|
return (
|
|
44
45
|
<DiffView
|
|
45
46
|
engine={engine}
|
|
@@ -79,38 +80,48 @@ export function EditorDocumentDiff({
|
|
|
79
80
|
const { t } = useTranslation('agent-chat');
|
|
80
81
|
const withinLimits = canRenderEditorDiff(document);
|
|
81
82
|
const [loaded, setLoaded] = useState<{ load: EngineLoader; engine: EditorEngine | null }>();
|
|
83
|
+
|
|
82
84
|
useEffect(() => {
|
|
83
85
|
if (!withinLimits || engines.has(loadEngine)) {
|
|
84
86
|
return;
|
|
85
87
|
}
|
|
88
|
+
|
|
86
89
|
let active = true;
|
|
90
|
+
|
|
87
91
|
void Promise.resolve()
|
|
88
92
|
.then(loadEngine)
|
|
89
93
|
.then(
|
|
90
94
|
(engine) => {
|
|
91
95
|
engines.set(loadEngine, engine);
|
|
96
|
+
|
|
92
97
|
if (active) {
|
|
93
98
|
setLoaded({ load: loadEngine, engine });
|
|
94
99
|
}
|
|
95
100
|
},
|
|
96
101
|
() => {
|
|
97
102
|
engines.set(loadEngine, null);
|
|
103
|
+
|
|
98
104
|
if (active) {
|
|
99
105
|
setLoaded({ load: loadEngine, engine: null });
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
);
|
|
109
|
+
|
|
103
110
|
return () => {
|
|
104
111
|
active = false;
|
|
105
112
|
};
|
|
106
113
|
}, [loadEngine, withinLimits]);
|
|
114
|
+
|
|
107
115
|
const engine = loaded?.load === loadEngine ? loaded.engine : engines.get(loadEngine);
|
|
116
|
+
|
|
108
117
|
if (!withinLimits) {
|
|
109
118
|
return <DiffOmitted path={path} />;
|
|
110
119
|
}
|
|
120
|
+
|
|
111
121
|
if (engine === undefined) {
|
|
112
122
|
return <div className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</div>;
|
|
113
123
|
}
|
|
124
|
+
|
|
114
125
|
return engine === null ? (
|
|
115
126
|
fallback
|
|
116
127
|
) : (
|
|
@@ -135,8 +146,10 @@ export default function EditorEditDiff({
|
|
|
135
146
|
sourceChecked || diffSourceBudget(change.before, change.after)
|
|
136
147
|
? diffDocument(patchOf(change.before, change.after, 3, { maxWork: EDITOR_DIFF_WORK }), { old: change.before, new: change.after })
|
|
137
148
|
: undefined;
|
|
149
|
+
|
|
138
150
|
if (document === undefined) {
|
|
139
151
|
return <DiffOmitted path={change.path} />;
|
|
140
152
|
}
|
|
153
|
+
|
|
141
154
|
return <EditorDocumentDiff document={document} path={change.path} loadEngine={loadEngine} fallback={fallback} maxHeight={maxHeight} />;
|
|
142
155
|
}
|
|
@@ -32,19 +32,23 @@ export default function EditorPatchDiff({
|
|
|
32
32
|
}) {
|
|
33
33
|
const oldText = contents?.old;
|
|
34
34
|
const newText = contents?.new;
|
|
35
|
+
|
|
35
36
|
const document = useMemo(() => {
|
|
36
37
|
if (!sourceChecked && (!diffSourceBudget(oldText ?? '', newText ?? '') || !patchSourceBudget(change.diff))) {
|
|
37
38
|
return undefined;
|
|
38
39
|
}
|
|
40
|
+
|
|
39
41
|
return diffDocument(
|
|
40
42
|
parsePatch(change.diff),
|
|
41
43
|
oldText === undefined || newText === undefined ? undefined : { old: oldText, new: newText },
|
|
42
44
|
ignoreWhitespace
|
|
43
45
|
);
|
|
44
46
|
}, [change.diff, oldText, newText, ignoreWhitespace, sourceChecked]);
|
|
47
|
+
|
|
45
48
|
if (document === undefined) {
|
|
46
49
|
return <DiffOmitted path={change.path} />;
|
|
47
50
|
}
|
|
51
|
+
|
|
48
52
|
return (
|
|
49
53
|
<EditorDocumentDiff
|
|
50
54
|
document={document}
|
|
@@ -7,8 +7,10 @@ export function LegacyDiffPool({ children }: { children: ReactNode }) {
|
|
|
7
7
|
const host = useChatHost();
|
|
8
8
|
const outer = useWorkerPool();
|
|
9
9
|
const workerFactory = host.code.legacyDiffWorker;
|
|
10
|
+
|
|
10
11
|
if (outer !== undefined || workerFactory === undefined) {
|
|
11
12
|
return children;
|
|
12
13
|
}
|
|
14
|
+
|
|
13
15
|
return <DiffPool workerFactory={workerFactory}>{children}</DiffPool>;
|
|
14
16
|
}
|
|
@@ -11,6 +11,7 @@ export default function LegacyEditDiff({ change, maxHeight }: { change: FileChan
|
|
|
11
11
|
const theme = useDiffTheme();
|
|
12
12
|
const oldFile = { name: change.path, contents: change.before };
|
|
13
13
|
const newFile = { name: change.path, contents: change.after };
|
|
14
|
+
|
|
14
15
|
const options = {
|
|
15
16
|
diffStyle: 'unified' as const,
|
|
16
17
|
theme,
|
|
@@ -19,6 +20,7 @@ export default function LegacyEditDiff({ change, maxHeight }: { change: FileChan
|
|
|
19
20
|
overflow: 'wrap' as const,
|
|
20
21
|
hunkSeparators: 'simple' as const
|
|
21
22
|
};
|
|
23
|
+
|
|
22
24
|
return (
|
|
23
25
|
<div className="chat-diff select-text" style={maxHeight === undefined ? undefined : { maxHeight, overflow: 'auto' }}>
|
|
24
26
|
<LegacyDiffPool>
|
|
@@ -16,11 +16,14 @@ function asPatch(change: ChatFileChange): string | null {
|
|
|
16
16
|
if (!/^@@/m.test(change.diff)) {
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
|
+
|
|
19
20
|
if (/^\+\+\+ /m.test(change.diff)) {
|
|
20
21
|
return change.diff;
|
|
21
22
|
}
|
|
23
|
+
|
|
22
24
|
const from = change.kind === 'add' ? '/dev/null' : `a/${change.path}`;
|
|
23
25
|
const to = change.kind === 'delete' ? '/dev/null' : `b/${change.path}`;
|
|
26
|
+
|
|
24
27
|
return `--- ${from}\n+++ ${to}\n${change.diff}`;
|
|
25
28
|
}
|
|
26
29
|
|
|
@@ -37,9 +40,11 @@ function lineClass(line: string): string {
|
|
|
37
40
|
if (line.startsWith('+')) {
|
|
38
41
|
return 'text-chat-added';
|
|
39
42
|
}
|
|
43
|
+
|
|
40
44
|
if (line.startsWith('-')) {
|
|
41
45
|
return 'text-chat-removed';
|
|
42
46
|
}
|
|
47
|
+
|
|
43
48
|
return 'text-text-muted';
|
|
44
49
|
}
|
|
45
50
|
|
|
@@ -52,6 +57,7 @@ export default function LegacyUnifiedDiff({ change, overflow = 'wrap', diffStyle
|
|
|
52
57
|
const newText = contents?.new;
|
|
53
58
|
const full = patch === null || oldText === undefined || newText === undefined ? null : fullFileDiff(patch, change.path, { old: oldText, new: newText });
|
|
54
59
|
const unfolds = full !== null;
|
|
60
|
+
|
|
55
61
|
const options = {
|
|
56
62
|
theme,
|
|
57
63
|
themeType: resolved,
|
|
@@ -61,6 +67,7 @@ export default function LegacyUnifiedDiff({ change, overflow = 'wrap', diffStyle
|
|
|
61
67
|
hunkSeparators: unfolds ? ('line-info' as const) : ('simple' as const),
|
|
62
68
|
unsafeCSS: fill ? FILL_CSS : undefined
|
|
63
69
|
};
|
|
70
|
+
|
|
64
71
|
if (patch === null) {
|
|
65
72
|
return (
|
|
66
73
|
<pre className="max-h-64 overflow-auto px-3 py-2 font-mono text-code select-text" style={fill ? undefined : { maxHeight }}>
|
|
@@ -75,6 +82,7 @@ export default function LegacyUnifiedDiff({ change, overflow = 'wrap', diffStyle
|
|
|
75
82
|
</pre>
|
|
76
83
|
);
|
|
77
84
|
}
|
|
85
|
+
|
|
78
86
|
return (
|
|
79
87
|
<div
|
|
80
88
|
className={clsx('chat-diff select-text', fill && 'flex grow flex-col')}
|
|
@@ -8,6 +8,7 @@ const UnifiedDiff = lazyNamed(() => import('../UnifiedDiff'), 'default');
|
|
|
8
8
|
|
|
9
9
|
export function ReviewDiff({ entry, maxHeight = 480 }: { entry: ReviewEntry; maxHeight?: number }) {
|
|
10
10
|
const { t } = useTranslation('agent-chat');
|
|
11
|
+
|
|
11
12
|
return (
|
|
12
13
|
<div data-review-entry={entry.key}>
|
|
13
14
|
<LazyBoundary fallback={<p className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</p>}>
|
|
@@ -13,18 +13,22 @@ export function textFitsBudget(text: string, budget: TextBudget): boolean {
|
|
|
13
13
|
if (text.length > budget.characters) {
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
|
+
|
|
16
17
|
let rows = text.length === 0 ? 0 : 1;
|
|
17
18
|
let length = 0;
|
|
19
|
+
|
|
18
20
|
for (let index = 0; index < text.length; index++) {
|
|
19
21
|
if (text.charCodeAt(index) === 10) {
|
|
20
22
|
if (index < text.length - 1 && ++rows > budget.rows) {
|
|
21
23
|
return false;
|
|
22
24
|
}
|
|
25
|
+
|
|
23
26
|
length = 0;
|
|
24
27
|
} else if (++length > budget.lineLength) {
|
|
25
28
|
return false;
|
|
26
29
|
}
|
|
27
30
|
}
|
|
31
|
+
|
|
28
32
|
return rows <= budget.rows;
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -41,16 +45,20 @@ export function legacyDiffBudget(before: string, after: string, patch = ''): boo
|
|
|
41
45
|
if (before.length + after.length + patch.length > LEGACY_BUDGET.characters) {
|
|
42
46
|
return false;
|
|
43
47
|
}
|
|
48
|
+
|
|
44
49
|
let rows = 2;
|
|
50
|
+
|
|
45
51
|
for (const text of [before, after, patch]) {
|
|
46
52
|
if (!textFitsBudget(text, LEGACY_BUDGET)) {
|
|
47
53
|
return false;
|
|
48
54
|
}
|
|
55
|
+
|
|
49
56
|
for (let index = 0; index < text.length; index++) {
|
|
50
57
|
if (text.charCodeAt(index) === 10 && ++rows > LEGACY_BUDGET.rows) {
|
|
51
58
|
return false;
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
61
|
}
|
|
62
|
+
|
|
55
63
|
return true;
|
|
56
64
|
}
|
|
@@ -7,15 +7,19 @@ export const EDITOR_DIFF_LIMITS = { rows: 2000, characters: 2000000, lineLength:
|
|
|
7
7
|
export function canRenderEditorDiff(document: DiffDocument): boolean {
|
|
8
8
|
let rows = 0;
|
|
9
9
|
let characters = 0;
|
|
10
|
+
|
|
10
11
|
for (const row of diffRows(document, 'unified')) {
|
|
11
12
|
if (row.kind === 'gap') {
|
|
12
13
|
continue;
|
|
13
14
|
}
|
|
15
|
+
|
|
14
16
|
const text = row.new === undefined ? document.sides.old[row.old!.index]! : document.sides.new[row.new.index]!;
|
|
15
17
|
characters += text.length + (rows > 0 ? 1 : 0);
|
|
18
|
+
|
|
16
19
|
if (++rows > EDITOR_DIFF_LIMITS.rows || characters > EDITOR_DIFF_LIMITS.characters || text.length > EDITOR_DIFF_LIMITS.lineLength) {
|
|
17
20
|
return false;
|
|
18
21
|
}
|
|
19
22
|
}
|
|
23
|
+
|
|
20
24
|
return true;
|
|
21
25
|
}
|
|
@@ -17,6 +17,7 @@ export interface ReviewBudget {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const REVIEW_BUDGET: ReviewBudget = { editors: 3, rows: 2000, characters: 2000000 };
|
|
20
|
+
|
|
20
21
|
export type ReviewSlot = 'editor' | 'deferred';
|
|
21
22
|
|
|
22
23
|
export function reviewEntries(patches: readonly ChatFileChange[], edits: readonly FileChange[]): readonly ReviewEntry[] {
|
|
@@ -29,20 +30,25 @@ export function reviewEntries(patches: readonly ChatFileChange[], edits: readonl
|
|
|
29
30
|
export function reviewSize(entry: ReviewEntry, budget: ReviewBudget = REVIEW_BUDGET): { rows: number; characters: number } {
|
|
30
31
|
const texts = entry.change.kind === 'edit' ? [entry.change.edit.before, entry.change.edit.after] : [entry.change.patch.diff];
|
|
31
32
|
const characters = texts.reduce((sum, text) => sum + text.length, 0);
|
|
33
|
+
|
|
32
34
|
if (characters > budget.characters) {
|
|
33
35
|
return { rows: budget.rows + 1, characters };
|
|
34
36
|
}
|
|
37
|
+
|
|
35
38
|
let rows = 0;
|
|
39
|
+
|
|
36
40
|
for (const text of texts) {
|
|
37
41
|
if (text.length > 0) {
|
|
38
42
|
rows++;
|
|
39
43
|
}
|
|
44
|
+
|
|
40
45
|
for (let index = text.indexOf('\n'); index >= 0; index = text.indexOf('\n', index + 1)) {
|
|
41
46
|
if (++rows > budget.rows) {
|
|
42
47
|
return { rows, characters };
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
}
|
|
51
|
+
|
|
46
52
|
return { rows, characters };
|
|
47
53
|
}
|
|
48
54
|
|
|
@@ -53,8 +59,10 @@ export function planReview(entries: readonly ReviewEntry[], promoted: string | n
|
|
|
53
59
|
let editors = 0;
|
|
54
60
|
let rows = 0;
|
|
55
61
|
let characters = 0;
|
|
62
|
+
|
|
56
63
|
for (const entry of ordered) {
|
|
57
64
|
const size = reviewSize(entry, budget);
|
|
65
|
+
|
|
58
66
|
// The first review keeps its own omission and error handling, even when the group estimate exceeds the budget.
|
|
59
67
|
if (editors === 0 || (editors < budget.editors && rows + size.rows <= budget.rows && characters + size.characters <= budget.characters)) {
|
|
60
68
|
slots.set(entry.key, 'editor');
|
|
@@ -65,5 +73,6 @@ export function planReview(entries: readonly ReviewEntry[], promoted: string | n
|
|
|
65
73
|
slots.set(entry.key, 'deferred');
|
|
66
74
|
}
|
|
67
75
|
}
|
|
76
|
+
|
|
68
77
|
return slots;
|
|
69
78
|
}
|
|
@@ -45,10 +45,12 @@ const shared = new WeakMap<ChatHost['code'], DiffSyntaxRuntime>();
|
|
|
45
45
|
/* The runtime of a host's `code`, made on first use and shared by every diff under that host. */
|
|
46
46
|
export function diffSyntaxRuntime(code: ChatHost['code']): DiffSyntaxRuntime {
|
|
47
47
|
let runtime = shared.get(code);
|
|
48
|
+
|
|
48
49
|
if (runtime === undefined) {
|
|
49
50
|
runtime = createDiffSyntaxRuntime({ workerFactory: code.syntaxWorker, themes: () => code.custom, highlighter: code.highlighter });
|
|
50
51
|
shared.set(code, runtime);
|
|
51
52
|
}
|
|
53
|
+
|
|
52
54
|
return runtime;
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -61,13 +63,17 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
61
63
|
let stopped = false;
|
|
62
64
|
// The names of the custom themes the current worker or fallback has, each sent once.
|
|
63
65
|
const sentThemes = new Set<string>();
|
|
66
|
+
|
|
64
67
|
const themes = (): readonly ThemeRegistration[] => (typeof options.themes === 'function' ? options.themes() : options.themes);
|
|
68
|
+
|
|
65
69
|
const settle = (session: Session): void => {
|
|
66
70
|
for (const pending of session.pending.values()) {
|
|
67
71
|
pending.resolve(null);
|
|
68
72
|
}
|
|
73
|
+
|
|
69
74
|
session.pending.clear();
|
|
70
75
|
};
|
|
76
|
+
|
|
71
77
|
const stopWorker = (): void => {
|
|
72
78
|
worker?.removeEventListener('message', onMessage);
|
|
73
79
|
worker?.removeEventListener('error', onError);
|
|
@@ -75,57 +81,75 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
75
81
|
worker?.terminate();
|
|
76
82
|
worker = undefined;
|
|
77
83
|
};
|
|
84
|
+
|
|
78
85
|
const loadHighlighter = (): Promise<Highlighter> => {
|
|
79
86
|
highlighter ??= import('shiki').then(({ createHighlighter }) => createHighlighter({ langs: [], themes: [] }));
|
|
87
|
+
|
|
80
88
|
return highlighter;
|
|
81
89
|
};
|
|
90
|
+
|
|
82
91
|
const start = (): void => {
|
|
83
92
|
const current = themes();
|
|
84
93
|
sentThemes.clear();
|
|
94
|
+
|
|
85
95
|
for (const theme of current) {
|
|
86
96
|
if (theme.name !== undefined) {
|
|
87
97
|
sentThemes.add(theme.name);
|
|
88
98
|
}
|
|
89
99
|
}
|
|
100
|
+
|
|
90
101
|
dispatch({ type: 'start', themes: current, maxLines: 100000 });
|
|
91
102
|
};
|
|
103
|
+
|
|
92
104
|
/* Sends a custom theme the host added after the start, ahead of the first request drawn in it. */
|
|
93
105
|
const sendTheme = (name: string): void => {
|
|
94
106
|
if (sentThemes.has(name)) {
|
|
95
107
|
return;
|
|
96
108
|
}
|
|
109
|
+
|
|
97
110
|
const theme = themes().find((candidate) => candidate.name === name);
|
|
111
|
+
|
|
98
112
|
if (theme !== undefined) {
|
|
99
113
|
sentThemes.add(name);
|
|
100
114
|
dispatch({ type: 'themes', themes: [theme] });
|
|
101
115
|
}
|
|
102
116
|
};
|
|
117
|
+
|
|
103
118
|
const startFallback = (): void => {
|
|
104
119
|
stopWorker();
|
|
120
|
+
|
|
105
121
|
if (fallback !== undefined || stopped) {
|
|
106
122
|
return;
|
|
107
123
|
}
|
|
124
|
+
|
|
108
125
|
fallback = createSyntaxService({ highlighter: options.highlighter ?? loadHighlighter, send: receive });
|
|
109
126
|
start();
|
|
127
|
+
|
|
110
128
|
for (const [generation, session] of sessions) {
|
|
111
129
|
session.sent = false;
|
|
130
|
+
|
|
112
131
|
for (const index of session.pending.keys()) {
|
|
113
132
|
request(generation, session, index);
|
|
114
133
|
}
|
|
115
134
|
}
|
|
116
135
|
};
|
|
136
|
+
|
|
117
137
|
const onError = (event: Event): void => {
|
|
118
138
|
event.preventDefault();
|
|
119
139
|
startFallback();
|
|
120
140
|
};
|
|
141
|
+
|
|
121
142
|
const onMessage = (event: MessageEvent<DiffSyntaxOutput>): void => {
|
|
122
143
|
receive(event.data);
|
|
123
144
|
};
|
|
145
|
+
|
|
124
146
|
const initialize = (): void => {
|
|
125
147
|
if (started || stopped) {
|
|
126
148
|
return;
|
|
127
149
|
}
|
|
150
|
+
|
|
128
151
|
started = true;
|
|
152
|
+
|
|
129
153
|
if (options.workerFactory !== undefined) {
|
|
130
154
|
try {
|
|
131
155
|
worker = options.workerFactory();
|
|
@@ -133,6 +157,7 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
133
157
|
worker.addEventListener('error', onError);
|
|
134
158
|
worker.addEventListener('messageerror', onError);
|
|
135
159
|
start();
|
|
160
|
+
|
|
136
161
|
return;
|
|
137
162
|
} catch {
|
|
138
163
|
startFallback();
|
|
@@ -141,10 +166,12 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
141
166
|
startFallback();
|
|
142
167
|
}
|
|
143
168
|
};
|
|
169
|
+
|
|
144
170
|
const dispatch = (message: DiffSyntaxInput): void => {
|
|
145
171
|
if (stopped) {
|
|
146
172
|
return;
|
|
147
173
|
}
|
|
174
|
+
|
|
148
175
|
if (worker !== undefined) {
|
|
149
176
|
try {
|
|
150
177
|
worker.postMessage(message);
|
|
@@ -159,18 +186,23 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
159
186
|
});
|
|
160
187
|
}
|
|
161
188
|
};
|
|
189
|
+
|
|
162
190
|
const request = (generation: number, session: Session, index: number, resend = false): void => {
|
|
163
191
|
const document = !session.sent || resend ? session.definition : undefined;
|
|
192
|
+
|
|
164
193
|
if (document !== undefined) {
|
|
165
194
|
sendTheme(document.theme);
|
|
166
195
|
}
|
|
196
|
+
|
|
167
197
|
session.sent = true;
|
|
168
198
|
dispatch({ type: 'request', generation, index, ...(document ? { document } : {}) });
|
|
169
199
|
};
|
|
200
|
+
|
|
170
201
|
const receive = (message: DiffSyntaxOutput): void => {
|
|
171
202
|
if (stopped || message.type === 'ready') {
|
|
172
203
|
return;
|
|
173
204
|
}
|
|
205
|
+
|
|
174
206
|
if (message.type === 'error') {
|
|
175
207
|
if (worker !== undefined) {
|
|
176
208
|
startFallback();
|
|
@@ -179,50 +211,66 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
179
211
|
settle(session);
|
|
180
212
|
}
|
|
181
213
|
}
|
|
214
|
+
|
|
182
215
|
return;
|
|
183
216
|
}
|
|
217
|
+
|
|
184
218
|
const session = sessions.get(message.generation);
|
|
185
219
|
const pending = session?.pending.get(message.index);
|
|
220
|
+
|
|
186
221
|
if (session === undefined || pending === undefined) {
|
|
187
222
|
return;
|
|
188
223
|
}
|
|
224
|
+
|
|
189
225
|
if (message.type === 'failed' && message.reason === 'missing' && !pending.resent) {
|
|
190
226
|
pending.resent = true;
|
|
191
227
|
request(message.generation, session, message.index, true);
|
|
228
|
+
|
|
192
229
|
return;
|
|
193
230
|
}
|
|
231
|
+
|
|
194
232
|
session.pending.delete(message.index);
|
|
195
233
|
pending.resolve(message.type === 'tokens' ? message : null);
|
|
196
234
|
};
|
|
235
|
+
|
|
197
236
|
return {
|
|
198
237
|
open(document) {
|
|
199
238
|
const generation = ++nextGeneration;
|
|
200
239
|
const session: Session = { definition: document, pending: new Map(), sent: false };
|
|
201
240
|
sessions.set(generation, session);
|
|
241
|
+
|
|
202
242
|
return {
|
|
203
243
|
request(index) {
|
|
204
244
|
if (stopped || !sessions.has(generation)) {
|
|
205
245
|
return Promise.resolve(null);
|
|
206
246
|
}
|
|
247
|
+
|
|
207
248
|
const existing = session.pending.get(index);
|
|
249
|
+
|
|
208
250
|
if (existing !== undefined) {
|
|
209
251
|
return existing.promise;
|
|
210
252
|
}
|
|
253
|
+
|
|
211
254
|
let resolve!: Pending['resolve'];
|
|
255
|
+
|
|
212
256
|
const promise = new Promise<DiffSyntaxTokens | null>((done) => {
|
|
213
257
|
resolve = done;
|
|
214
258
|
});
|
|
259
|
+
|
|
215
260
|
session.pending.set(index, { promise, resolve, resent: false });
|
|
216
261
|
const initialized = started;
|
|
217
262
|
initialize();
|
|
263
|
+
|
|
218
264
|
// Fallback initialization replays pending requests, including this first one.
|
|
219
265
|
if (initialized || worker !== undefined) {
|
|
220
266
|
request(generation, session, index);
|
|
221
267
|
}
|
|
268
|
+
|
|
222
269
|
return promise;
|
|
223
270
|
},
|
|
224
271
|
cancel() {
|
|
225
272
|
settle(session);
|
|
273
|
+
|
|
226
274
|
if (started) {
|
|
227
275
|
dispatch({ type: 'cancel', generation });
|
|
228
276
|
}
|
|
@@ -230,6 +278,7 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
230
278
|
dispose() {
|
|
231
279
|
settle(session);
|
|
232
280
|
sessions.delete(generation);
|
|
281
|
+
|
|
233
282
|
if (started) {
|
|
234
283
|
dispatch({ type: 'dispose', generation });
|
|
235
284
|
}
|
|
@@ -238,12 +287,15 @@ export function createDiffSyntaxRuntime(options: DiffSyntaxRuntimeOptions): Diff
|
|
|
238
287
|
},
|
|
239
288
|
dispose() {
|
|
240
289
|
stopped = true;
|
|
290
|
+
|
|
241
291
|
for (const session of sessions.values()) {
|
|
242
292
|
settle(session);
|
|
243
293
|
}
|
|
294
|
+
|
|
244
295
|
sessions.clear();
|
|
245
296
|
stopWorker();
|
|
246
297
|
fallback?.dispose();
|
|
298
|
+
|
|
247
299
|
if (options.highlighter === undefined) {
|
|
248
300
|
void highlighter?.then(
|
|
249
301
|
(loaded) => loaded.dispose(),
|
|
@@ -15,24 +15,33 @@ export function useReviewStack(entries: readonly ReviewEntry[]): ReviewStack {
|
|
|
15
15
|
const [admitted, setAdmitted] = useState<string[]>(() => selected.slice(0, 1));
|
|
16
16
|
const retained = admitted.filter((key) => selected.includes(key));
|
|
17
17
|
const live = retained.length === 0 ? selected.slice(0, 1) : retained;
|
|
18
|
+
|
|
18
19
|
if (live.length !== admitted.length || live.some((key, index) => key !== admitted[index])) {
|
|
19
20
|
setAdmitted(live);
|
|
20
21
|
}
|
|
22
|
+
|
|
21
23
|
const [settled, setSettled] = useState<ReadonlySet<string>>(() => new Set());
|
|
24
|
+
|
|
22
25
|
if ([...settled].some((key) => !selected.includes(key))) {
|
|
23
26
|
setSettled(new Set([...settled].filter((key) => selected.includes(key))));
|
|
24
27
|
}
|
|
28
|
+
|
|
25
29
|
const settle = (key: string) => {
|
|
26
30
|
setSettled((previous) => (previous.has(key) ? previous : new Set([...previous, key])));
|
|
27
31
|
};
|
|
32
|
+
|
|
28
33
|
const allSettled = live.every((key) => settled.has(key));
|
|
29
34
|
const next = selected.find((key) => !live.includes(key));
|
|
35
|
+
|
|
30
36
|
useEffect(() => {
|
|
31
37
|
if (next === undefined || !allSettled) {
|
|
32
38
|
return;
|
|
33
39
|
}
|
|
40
|
+
|
|
34
41
|
const frame = window.requestAnimationFrame(() => setAdmitted((previous) => [...previous, next]));
|
|
42
|
+
|
|
35
43
|
return () => window.cancelAnimationFrame(frame);
|
|
36
44
|
}, [next, allSettled]);
|
|
45
|
+
|
|
37
46
|
return { slots, ready: new Set(live), promote: setPromoted, settle };
|
|
38
47
|
}
|
|
@@ -24,31 +24,41 @@ export function diffSourceTokens(document: DiffDocument, mapping: DiffSyntaxMapp
|
|
|
24
24
|
const pending = { old: new Set<number>(), new: new Set<number>() };
|
|
25
25
|
const listeners = new Set<() => void>();
|
|
26
26
|
let disposed = false;
|
|
27
|
+
|
|
27
28
|
return {
|
|
28
29
|
get(side, index) {
|
|
29
30
|
const location = mapping.locate(side, index);
|
|
31
|
+
|
|
30
32
|
if (disposed || location === undefined || document.sides[side][index] === undefined) {
|
|
31
33
|
return null;
|
|
32
34
|
}
|
|
35
|
+
|
|
33
36
|
const { block, line } = location;
|
|
34
37
|
const known = cache[side].get(block);
|
|
38
|
+
|
|
35
39
|
if (known !== undefined) {
|
|
36
40
|
return known[line] ?? null;
|
|
37
41
|
}
|
|
42
|
+
|
|
38
43
|
if (!pending[side].has(block)) {
|
|
39
44
|
pending[side].add(block);
|
|
40
45
|
const text = mapping.documents[side].blocks[block]!.split('\n');
|
|
46
|
+
|
|
41
47
|
const publish = (lines: ReadonlyArray<readonly LineToken[] | null>): void => {
|
|
42
48
|
if (disposed) {
|
|
43
49
|
return;
|
|
44
50
|
}
|
|
51
|
+
|
|
45
52
|
pending[side].delete(block);
|
|
46
53
|
cache[side].set(block, lines);
|
|
54
|
+
|
|
47
55
|
for (const listener of [...listeners]) {
|
|
48
56
|
listener();
|
|
49
57
|
}
|
|
50
58
|
};
|
|
59
|
+
|
|
51
60
|
const count = text.length;
|
|
61
|
+
|
|
52
62
|
void sides[side].request(block).then(
|
|
53
63
|
(packet) => {
|
|
54
64
|
if (!disposed) {
|
|
@@ -58,12 +68,14 @@ export function diffSourceTokens(document: DiffDocument, mapping: DiffSyntaxMapp
|
|
|
58
68
|
() => publish(text.map(() => null))
|
|
59
69
|
);
|
|
60
70
|
}
|
|
71
|
+
|
|
61
72
|
return undefined;
|
|
62
73
|
},
|
|
63
74
|
subscribe(listener) {
|
|
64
75
|
if (!disposed) {
|
|
65
76
|
listeners.add(listener);
|
|
66
77
|
}
|
|
78
|
+
|
|
67
79
|
return () => {
|
|
68
80
|
listeners.delete(listener);
|
|
69
81
|
};
|
|
@@ -14,6 +14,7 @@ function registerThemes(custom: ChatHost['code']['custom']): void {
|
|
|
14
14
|
if (registered.has(theme.name)) {
|
|
15
15
|
continue;
|
|
16
16
|
}
|
|
17
|
+
|
|
17
18
|
registered.add(theme.name);
|
|
18
19
|
registerCustomTheme(theme.name, () => Promise.resolve(theme));
|
|
19
20
|
}
|
|
@@ -24,5 +25,6 @@ export function useDiffTheme(): ThemesType {
|
|
|
24
25
|
const { code } = useChatHost();
|
|
25
26
|
registerThemes(code.custom);
|
|
26
27
|
const { light, dark } = useHostCodeThemes();
|
|
28
|
+
|
|
27
29
|
return { light, dark };
|
|
28
30
|
}
|
|
@@ -22,11 +22,13 @@ export function useFileLinkTarget(text: string): FileRef | null {
|
|
|
22
22
|
const cwd = useFileLinkCwd();
|
|
23
23
|
const scopeId = useFileLinkScopeId();
|
|
24
24
|
const { fileLinks } = useChatHost();
|
|
25
|
+
|
|
25
26
|
return fileLinks?.target(text, cwd, scopeId) ?? null;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/* Follows a reference the way the app opens a file or a folder. */
|
|
29
30
|
export function useOpenFileLink(): (cwd: string | null, ref: FileRef, scopeId?: string | null) => void {
|
|
30
31
|
const { fileLinks } = useChatHost();
|
|
32
|
+
|
|
31
33
|
return (cwd, ref, scopeId = null) => fileLinks?.open(cwd, ref, scopeId);
|
|
32
34
|
}
|
|
@@ -15,6 +15,7 @@ export const FindRevealContext = createContext<FindReveal | null>(null);
|
|
|
15
15
|
export function useOpenForFind(itemId: string, field: ChatFindField, setOpen: (open: boolean) => void): void {
|
|
16
16
|
const reveal = useContext(FindRevealContext);
|
|
17
17
|
const wanted = reveal !== null && reveal.itemId === itemId && reveal.field === field;
|
|
18
|
+
|
|
18
19
|
useEffect(() => {
|
|
19
20
|
if (wanted) {
|
|
20
21
|
setOpen(true);
|