@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
|
@@ -10,6 +10,7 @@ export const SHELL_LANGUAGE = 'shellscript';
|
|
|
10
10
|
|
|
11
11
|
// Past this a command is drawn without looking for code inside it; the scan is linear, the highlighting is not.
|
|
12
12
|
export const EMBEDDED_CODE_LIMIT = 20_000;
|
|
13
|
+
|
|
13
14
|
const MAX_DEPTH = 3;
|
|
14
15
|
|
|
15
16
|
/* A stretch of a shell command, as offsets into it. */
|
|
@@ -113,6 +114,7 @@ const INTERPRETERS: Record<string, Interpreter> = {
|
|
|
113
114
|
const WRAPPERS = new Set(['sudo', 'env', 'exec', 'nohup', 'time', 'command', 'nice']);
|
|
114
115
|
// Tools that run a program of a project's environment as `<tool> run <program>`.
|
|
115
116
|
const RUNNERS = new Set(['uv', 'poetry', 'pipenv']);
|
|
117
|
+
|
|
116
118
|
// Where a heredoc written to a file goes, by the file's extension.
|
|
117
119
|
const EXTENSIONS: Record<string, string> = {
|
|
118
120
|
py: 'python',
|
|
@@ -143,6 +145,7 @@ const BLANKS = ' \t\r';
|
|
|
143
145
|
/* The program a command name runs, as the table above knows it: `/usr/bin/python3.12` is `python`. */
|
|
144
146
|
function programOf(word: string): string {
|
|
145
147
|
const name = word.slice(word.lastIndexOf('/') + 1);
|
|
148
|
+
|
|
146
149
|
return /^python\d*(\.\d+)?$/.test(name) ? 'python' : name;
|
|
147
150
|
}
|
|
148
151
|
|
|
@@ -153,17 +156,21 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
153
156
|
const pending: { command: SimpleCommand; delimiter: string; strip: boolean; operator: Span }[] = [];
|
|
154
157
|
// The start of the `2` of a `2>&1` just read, which the redirect after it begins at.
|
|
155
158
|
let descriptorStart: number | null = null;
|
|
159
|
+
|
|
156
160
|
const finish = (): void => {
|
|
157
161
|
if (current.words.length > 0 || current.redirects.length > 0) {
|
|
158
162
|
commands.push(current);
|
|
159
163
|
}
|
|
164
|
+
|
|
160
165
|
current = { words: [], redirects: [], heredocs: [] };
|
|
161
166
|
descriptorStart = null;
|
|
162
167
|
};
|
|
168
|
+
|
|
163
169
|
const skipBlanks = (index: number): number => {
|
|
164
170
|
while (index < to && BLANKS.includes(source[index]!)) {
|
|
165
171
|
index++;
|
|
166
172
|
}
|
|
173
|
+
|
|
167
174
|
return index;
|
|
168
175
|
};
|
|
169
176
|
|
|
@@ -173,12 +180,16 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
173
180
|
let quoted: Span | null = null;
|
|
174
181
|
let parts = 0;
|
|
175
182
|
let bare = true;
|
|
183
|
+
|
|
176
184
|
while (index < to) {
|
|
177
185
|
const char = source[index]!;
|
|
186
|
+
|
|
178
187
|
if (BLANKS.includes(char) || char === '\n' || SEPARATORS.includes(char) || char === '<' || char === '>') {
|
|
179
188
|
break;
|
|
180
189
|
}
|
|
190
|
+
|
|
181
191
|
parts++;
|
|
192
|
+
|
|
182
193
|
if (char === "'") {
|
|
183
194
|
const close = source.indexOf("'", index + 1);
|
|
184
195
|
const end = close === -1 || close >= to ? to : close;
|
|
@@ -188,6 +199,7 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
188
199
|
index = Math.min(end + 1, to);
|
|
189
200
|
} else if (char === '"') {
|
|
190
201
|
let end = index + 1;
|
|
202
|
+
|
|
191
203
|
while (end < to && source[end] !== '"') {
|
|
192
204
|
if (source[end] === '\\' && end + 1 < to && '$`"\\\n'.includes(source[end + 1]!)) {
|
|
193
205
|
text += source[end + 1];
|
|
@@ -197,6 +209,7 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
197
209
|
end++;
|
|
198
210
|
}
|
|
199
211
|
}
|
|
212
|
+
|
|
200
213
|
quoted = { start: index + 1, end };
|
|
201
214
|
bare = false;
|
|
202
215
|
index = Math.min(end + 1, to);
|
|
@@ -213,38 +226,49 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
213
226
|
index++;
|
|
214
227
|
}
|
|
215
228
|
}
|
|
229
|
+
|
|
216
230
|
const end = Math.min(index, to);
|
|
217
231
|
const body = bare ? { start, end } : parts === 1 && quoted !== null ? quoted : null;
|
|
232
|
+
|
|
218
233
|
return { start, end, text, body };
|
|
219
234
|
};
|
|
220
235
|
|
|
221
236
|
const readHeredoc = (start: number, delimiter: string, strip: boolean): { body: Span; next: number } => {
|
|
222
237
|
let index = start;
|
|
238
|
+
|
|
223
239
|
while (index < to) {
|
|
224
240
|
const newline = source.indexOf('\n', index);
|
|
225
241
|
const lineEnd = newline === -1 || newline >= to ? to : newline;
|
|
226
242
|
let line = source.slice(index, lineEnd).replace(/\r$/, '');
|
|
243
|
+
|
|
227
244
|
if (strip) {
|
|
228
245
|
line = line.replace(/^\t+/, '');
|
|
229
246
|
}
|
|
247
|
+
|
|
230
248
|
if (line === delimiter) {
|
|
231
249
|
return { body: { start, end: index }, next: Math.min(lineEnd + 1, to) };
|
|
232
250
|
}
|
|
251
|
+
|
|
233
252
|
index = lineEnd + 1;
|
|
234
253
|
}
|
|
254
|
+
|
|
235
255
|
return { body: { start, end: to }, next: to };
|
|
236
256
|
};
|
|
237
257
|
|
|
238
258
|
let index = from;
|
|
259
|
+
|
|
239
260
|
while (index < to) {
|
|
240
261
|
const char = source[index]!;
|
|
262
|
+
|
|
241
263
|
if (char === '\n') {
|
|
242
264
|
index++;
|
|
265
|
+
|
|
243
266
|
for (const heredoc of pending) {
|
|
244
267
|
const { body, next } = readHeredoc(index, heredoc.delimiter, heredoc.strip);
|
|
245
268
|
heredoc.command.heredocs.push({ ...heredoc.operator, body });
|
|
246
269
|
index = next;
|
|
247
270
|
}
|
|
271
|
+
|
|
248
272
|
pending.length = 0;
|
|
249
273
|
finish();
|
|
250
274
|
} else if (BLANKS.includes(char)) {
|
|
@@ -261,15 +285,19 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
261
285
|
index += 2;
|
|
262
286
|
const strip = source[index] === '-';
|
|
263
287
|
const word = readWord(skipBlanks(strip ? index + 1 : index));
|
|
288
|
+
|
|
264
289
|
if (word.text !== '') {
|
|
265
290
|
pending.push({ command: current, delimiter: word.text, strip, operator: { start, end: word.end } });
|
|
266
291
|
}
|
|
292
|
+
|
|
267
293
|
index = word.end;
|
|
268
294
|
} else if (char === '<' || char === '>' || (char === '&' && source[index + 1] === '>')) {
|
|
269
295
|
let end = index + 1;
|
|
296
|
+
|
|
270
297
|
while (end < to && '<>&|'.includes(source[end]!)) {
|
|
271
298
|
end++;
|
|
272
299
|
}
|
|
300
|
+
|
|
273
301
|
const op = source.slice(index, end);
|
|
274
302
|
const target = readWord(skipBlanks(end));
|
|
275
303
|
current.redirects.push({ start: descriptorStart ?? index, end: Math.max(target.end, end), op, target });
|
|
@@ -282,15 +310,19 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
282
310
|
const word = readWord(index);
|
|
283
311
|
// The `2` of `2>&1` is a file descriptor, not an argument.
|
|
284
312
|
const descriptor = /^\d+$/.test(word.text) && (source[word.end] === '>' || source[word.end] === '<');
|
|
313
|
+
|
|
285
314
|
if (descriptor) {
|
|
286
315
|
descriptorStart = word.start;
|
|
287
316
|
} else {
|
|
288
317
|
current.words.push(word);
|
|
289
318
|
}
|
|
319
|
+
|
|
290
320
|
index = Math.max(word.end, index + 1);
|
|
291
321
|
}
|
|
292
322
|
}
|
|
323
|
+
|
|
293
324
|
finish();
|
|
325
|
+
|
|
294
326
|
return commands;
|
|
295
327
|
}
|
|
296
328
|
|
|
@@ -298,8 +330,10 @@ function parseCommands(source: string, from: number, to: number): SimpleCommand[
|
|
|
298
330
|
function closingParen(source: string, open: number, to: number): number {
|
|
299
331
|
let depth = 0;
|
|
300
332
|
let quote: string | null = null;
|
|
333
|
+
|
|
301
334
|
for (let index = open; index < to; index++) {
|
|
302
335
|
const char = source[index]!;
|
|
336
|
+
|
|
303
337
|
if (quote !== null) {
|
|
304
338
|
if (char === quote) {
|
|
305
339
|
quote = null;
|
|
@@ -312,23 +346,28 @@ function closingParen(source: string, open: number, to: number): number {
|
|
|
312
346
|
depth++;
|
|
313
347
|
} else if (char === ')') {
|
|
314
348
|
depth--;
|
|
349
|
+
|
|
315
350
|
if (depth === 0) {
|
|
316
351
|
return index + 1;
|
|
317
352
|
}
|
|
318
353
|
}
|
|
319
354
|
}
|
|
355
|
+
|
|
320
356
|
return to;
|
|
321
357
|
}
|
|
322
358
|
|
|
323
359
|
/* The index of the word a command runs, past variable assignments, wrappers and runners; -1 for none. */
|
|
324
360
|
function programIndex(words: readonly Word[]): number {
|
|
325
361
|
let index = 0;
|
|
362
|
+
|
|
326
363
|
while (index < words.length) {
|
|
327
364
|
const text = words[index]!.text;
|
|
365
|
+
|
|
328
366
|
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(text)) {
|
|
329
367
|
index++;
|
|
330
368
|
} else if (WRAPPERS.has(programOf(text))) {
|
|
331
369
|
index++;
|
|
370
|
+
|
|
332
371
|
while (index < words.length && words[index]!.text.startsWith('-')) {
|
|
333
372
|
index++;
|
|
334
373
|
}
|
|
@@ -338,6 +377,7 @@ function programIndex(words: readonly Word[]): number {
|
|
|
338
377
|
return index;
|
|
339
378
|
}
|
|
340
379
|
}
|
|
380
|
+
|
|
341
381
|
return -1;
|
|
342
382
|
}
|
|
343
383
|
|
|
@@ -348,49 +388,64 @@ function codeOf(command: SimpleCommand): EmbeddedCode[] {
|
|
|
348
388
|
const program = at === -1 ? '' : programOf(command.words[at]!.text);
|
|
349
389
|
const interpreter = INTERPRETERS[program];
|
|
350
390
|
let readsFile = false;
|
|
391
|
+
|
|
351
392
|
if (interpreter !== undefined) {
|
|
352
393
|
let positional = 0;
|
|
394
|
+
|
|
353
395
|
for (let index = at + 1; index < command.words.length; index++) {
|
|
354
396
|
const word = command.words[index]!;
|
|
397
|
+
|
|
355
398
|
if (word.text.startsWith('-') && word.text !== '-') {
|
|
356
399
|
if (interpreter.script(word.text)) {
|
|
357
400
|
const script = command.words[index + 1];
|
|
401
|
+
|
|
358
402
|
if (script?.body) {
|
|
359
403
|
found.push({ ...script.body, language: interpreter.language });
|
|
360
404
|
}
|
|
405
|
+
|
|
361
406
|
readsFile = true;
|
|
362
407
|
index++;
|
|
363
408
|
} else if (interpreter.takesValue?.has(word.text)) {
|
|
364
409
|
index++;
|
|
365
410
|
} else if (interpreter === PYTHON && word.text === '-m') {
|
|
366
411
|
readsFile = true;
|
|
412
|
+
|
|
367
413
|
break;
|
|
368
414
|
}
|
|
415
|
+
|
|
369
416
|
continue;
|
|
370
417
|
}
|
|
418
|
+
|
|
371
419
|
if (interpreter.client !== true) {
|
|
372
420
|
// A script file; whatever follows is its own arguments.
|
|
373
421
|
readsFile = word.text !== '-';
|
|
422
|
+
|
|
374
423
|
break;
|
|
375
424
|
}
|
|
425
|
+
|
|
376
426
|
if (positional === interpreter.positional && word.body !== null) {
|
|
377
427
|
found.push({ ...word.body, language: interpreter.language });
|
|
378
428
|
}
|
|
429
|
+
|
|
379
430
|
positional++;
|
|
380
431
|
}
|
|
381
432
|
}
|
|
433
|
+
|
|
382
434
|
const heredocLanguage = interpreter !== undefined && (!readsFile || interpreter.client === true) ? interpreter.language : writtenLanguage(command, program);
|
|
435
|
+
|
|
383
436
|
if (heredocLanguage !== null) {
|
|
384
437
|
for (const { body } of command.heredocs) {
|
|
385
438
|
found.push({ ...body, language: heredocLanguage });
|
|
386
439
|
}
|
|
387
440
|
}
|
|
441
|
+
|
|
388
442
|
return found;
|
|
389
443
|
}
|
|
390
444
|
|
|
391
445
|
/* The language of the file a `cat > file` or `tee file` writes, by its extension; null when nothing says. */
|
|
392
446
|
function writtenLanguage(command: SimpleCommand, program: string): string | null {
|
|
393
447
|
const targets = command.redirects.filter(({ op }) => op === '>' || op === '>>' || op === '>|').map(({ target }) => target.text);
|
|
448
|
+
|
|
394
449
|
if (program === 'tee') {
|
|
395
450
|
targets.push(
|
|
396
451
|
...command.words
|
|
@@ -399,13 +454,16 @@ function writtenLanguage(command: SimpleCommand, program: string): string | null
|
|
|
399
454
|
.filter((text) => !text.startsWith('-'))
|
|
400
455
|
);
|
|
401
456
|
}
|
|
457
|
+
|
|
402
458
|
for (const target of targets) {
|
|
403
459
|
const dot = target.lastIndexOf('.');
|
|
404
460
|
const language = dot === -1 ? undefined : EXTENSIONS[target.slice(dot + 1).toLowerCase()];
|
|
461
|
+
|
|
405
462
|
if (language !== undefined) {
|
|
406
463
|
return language;
|
|
407
464
|
}
|
|
408
465
|
}
|
|
466
|
+
|
|
409
467
|
return null;
|
|
410
468
|
}
|
|
411
469
|
|
|
@@ -415,7 +473,9 @@ function collect(source: string, from: number, to: number, depth: number, into:
|
|
|
415
473
|
if (code.end <= code.start) {
|
|
416
474
|
continue;
|
|
417
475
|
}
|
|
476
|
+
|
|
418
477
|
into.push(code);
|
|
478
|
+
|
|
419
479
|
if (code.language === SHELL_LANGUAGE && depth < MAX_DEPTH) {
|
|
420
480
|
collect(source, code.start, code.end, depth + 1, into);
|
|
421
481
|
}
|
|
@@ -431,6 +491,7 @@ export function shellCommands(source: string): ShellSimpleCommand[] {
|
|
|
431
491
|
return parseCommands(source, 0, source.length).map((command) => {
|
|
432
492
|
const index = programIndex(command.words);
|
|
433
493
|
const word = command.words[index];
|
|
494
|
+
|
|
434
495
|
return {
|
|
435
496
|
...command,
|
|
436
497
|
program: word === undefined ? null : { index, name: word.text.slice(word.text.lastIndexOf('/') + 1) }
|
|
@@ -449,7 +510,9 @@ export function embeddedCode(command: string): EmbeddedCode[] {
|
|
|
449
510
|
if (command.length > EMBEDDED_CODE_LIMIT) {
|
|
450
511
|
return [];
|
|
451
512
|
}
|
|
513
|
+
|
|
452
514
|
const found: EmbeddedCode[] = [];
|
|
453
515
|
collect(command, 0, command.length, 0, found);
|
|
516
|
+
|
|
454
517
|
return found.sort((left, right) => left.start - right.start || right.end - left.end);
|
|
455
518
|
}
|
package/src/chat/logic/fork.ts
CHANGED
|
@@ -20,6 +20,7 @@ export interface ForkPoint {
|
|
|
20
20
|
function turnsOf(items: Record<string, ChatItem>, order: readonly string[]): ChatTurnItem[] {
|
|
21
21
|
return order.flatMap((id) => {
|
|
22
22
|
const item = items[id];
|
|
23
|
+
|
|
23
24
|
return item?.kind === 'turn' ? [item] : [];
|
|
24
25
|
});
|
|
25
26
|
}
|
|
@@ -32,15 +33,19 @@ export function forkRefusal(info: ChatInfo | null, turn: ChatItem | undefined):
|
|
|
32
33
|
if (info === null || turn?.kind !== 'turn') {
|
|
33
34
|
return i18next.t('agent-chat:fork.refusal.notInConversation');
|
|
34
35
|
}
|
|
36
|
+
|
|
35
37
|
if (!FORKABLE_PROVIDERS.has(info.provider)) {
|
|
36
38
|
return i18next.t('agent-chat:fork.refusal.cliCannotFork');
|
|
37
39
|
}
|
|
40
|
+
|
|
38
41
|
if (info.agentSessionId === null) {
|
|
39
42
|
return i18next.t('agent-chat:fork.refusal.noConversation');
|
|
40
43
|
}
|
|
44
|
+
|
|
41
45
|
if (turn.state === 'running' || info.activeTurnId !== null) {
|
|
42
46
|
return i18next.t('agent-chat:fork.refusal.turnRunning');
|
|
43
47
|
}
|
|
48
|
+
|
|
44
49
|
return null;
|
|
45
50
|
}
|
|
46
51
|
|
|
@@ -49,31 +54,37 @@ export function summaryRefusal(state: { busy: boolean; originalPresent: boolean
|
|
|
49
54
|
if (!state.originalPresent) {
|
|
50
55
|
return i18next.t('agent-chat:fork.refusal.originalGone');
|
|
51
56
|
}
|
|
57
|
+
|
|
52
58
|
if (state.busy) {
|
|
53
59
|
return i18next.t('agent-chat:fork.refusal.turnRunning');
|
|
54
60
|
}
|
|
61
|
+
|
|
55
62
|
return null;
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
/* The forks this client knows of that went on after this turn of this chat, in the order it holds them. */
|
|
59
66
|
export function forkIdsAfter(infos: Iterable<ChatInfo>, chatId: string, turnId: string): string[] {
|
|
60
67
|
const ids: string[] = [];
|
|
68
|
+
|
|
61
69
|
for (const info of infos) {
|
|
62
70
|
if (info.forkOf?.chatId === chatId && info.forkOf.turnId === turnId) {
|
|
63
71
|
ids.push(info.chatId);
|
|
64
72
|
}
|
|
65
73
|
}
|
|
74
|
+
|
|
66
75
|
return ids;
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
/* The turns of this chat that at least one fork this client knows of went on after. */
|
|
70
79
|
export function forkedTurnIds(infos: Iterable<ChatInfo>, chatId: string): Set<string> {
|
|
71
80
|
const turns = new Set<string>();
|
|
81
|
+
|
|
72
82
|
for (const info of infos) {
|
|
73
83
|
if (info.forkOf?.chatId === chatId) {
|
|
74
84
|
turns.add(info.forkOf.turnId);
|
|
75
85
|
}
|
|
76
86
|
}
|
|
87
|
+
|
|
77
88
|
return turns;
|
|
78
89
|
}
|
|
79
90
|
|
|
@@ -86,16 +97,20 @@ export function forkPointOf(items: Record<string, ChatItem>, order: readonly str
|
|
|
86
97
|
const turns = turnsOf(items, order);
|
|
87
98
|
const index = turns.findIndex((turn) => turn.id === turnId);
|
|
88
99
|
const turn = turns[index];
|
|
100
|
+
|
|
89
101
|
if (turn === undefined) {
|
|
90
102
|
return null;
|
|
91
103
|
}
|
|
104
|
+
|
|
92
105
|
const asked = order.map((id) => items[id]).find((item) => item?.kind === 'user' && item.turnId === turnId);
|
|
93
106
|
const text = asked?.kind === 'user' ? asked.text : (turn.label ?? '');
|
|
107
|
+
|
|
94
108
|
const prompt =
|
|
95
109
|
text
|
|
96
110
|
.split('\n')
|
|
97
111
|
.find((line) => line.trim() !== '')
|
|
98
112
|
?.trim() ?? null;
|
|
113
|
+
|
|
99
114
|
return { turnId, number: index + 1, total: turns.length, counted: whole, last: index === turns.length - 1, prompt };
|
|
100
115
|
}
|
|
101
116
|
|
|
@@ -106,10 +121,13 @@ export function forkPointLabel(point: ForkPoint, maxPrompt = 60): string {
|
|
|
106
121
|
: point.counted
|
|
107
122
|
? i18next.t('agent-chat:fork.point.afterTurn', { number: point.number, total: point.total })
|
|
108
123
|
: i18next.t('agent-chat:fork.point.afterThis');
|
|
124
|
+
|
|
109
125
|
if (point.prompt === null) {
|
|
110
126
|
return where;
|
|
111
127
|
}
|
|
128
|
+
|
|
112
129
|
const prompt = point.prompt.length > maxPrompt ? `${point.prompt.slice(0, maxPrompt - 1)}…` : point.prompt;
|
|
130
|
+
|
|
113
131
|
return i18next.t('agent-chat:fork.point.about', { where, prompt });
|
|
114
132
|
}
|
|
115
133
|
|
|
@@ -177,6 +195,7 @@ export function forkPayload(input: {
|
|
|
177
195
|
const provider = cli !== undefined && cli.chosen.provider !== cli.original.provider ? cli.chosen.provider : null;
|
|
178
196
|
const selection = cli !== undefined && (provider !== null || cli.chosen.selection.model !== cli.original.selection.model) ? cli.chosen.selection : null;
|
|
179
197
|
const account = cli?.chosen.account !== undefined && (provider !== null || cli.chosen.account !== cli.original.account) ? cli.chosen.account : null;
|
|
198
|
+
|
|
180
199
|
return {
|
|
181
200
|
chatId: input.chatId,
|
|
182
201
|
turnId: input.turnId,
|
|
@@ -192,11 +211,14 @@ export function forkPayload(input: {
|
|
|
192
211
|
/* Why a branch cannot be the fork's, or null when it can. */
|
|
193
212
|
export function branchRefusal(branch: string, taken: readonly string[]): string | null {
|
|
194
213
|
const name = branch.trim();
|
|
214
|
+
|
|
195
215
|
if (name === '') {
|
|
196
216
|
return i18next.t('agent-chat:fork.branch.unnamed');
|
|
197
217
|
}
|
|
218
|
+
|
|
198
219
|
if (taken.includes(name)) {
|
|
199
220
|
return i18next.t('agent-chat:fork.branch.taken');
|
|
200
221
|
}
|
|
222
|
+
|
|
201
223
|
return null;
|
|
202
224
|
}
|
|
@@ -23,22 +23,29 @@ export function generatedImageView(tool: ChatToolItem): GeneratedImageView {
|
|
|
23
23
|
if (tool.state === 'running') {
|
|
24
24
|
return { state: 'generating' };
|
|
25
25
|
}
|
|
26
|
+
|
|
26
27
|
const parsed = GeneratedImageInputSchema.safeParse(tool.input);
|
|
27
28
|
const input = parsed.success ? parsed.data : {};
|
|
28
29
|
const output = tool.output?.trim() || null;
|
|
30
|
+
|
|
29
31
|
if (tool.state === 'error' || input.attachment === undefined) {
|
|
30
32
|
return { state: 'failed', failure: output === null && tool.state !== 'error' ? { kind: 'empty' } : { kind: 'provider', message: output } };
|
|
31
33
|
}
|
|
34
|
+
|
|
32
35
|
const attachment = input.attachment;
|
|
36
|
+
|
|
33
37
|
if (attachment.size === 0) {
|
|
34
38
|
return { state: 'failed', failure: { kind: 'empty' } };
|
|
35
39
|
}
|
|
40
|
+
|
|
36
41
|
if (!attachment.mime.startsWith('image/')) {
|
|
37
42
|
return { state: 'failed', failure: { kind: 'not-image' } };
|
|
38
43
|
}
|
|
44
|
+
|
|
39
45
|
if (attachment.size > CHAT_ATTACHMENT_MAX_BYTES) {
|
|
40
46
|
return { state: 'failed', failure: { kind: 'too-large', limit: CHAT_ATTACHMENT_MAX_BYTES } };
|
|
41
47
|
}
|
|
48
|
+
|
|
42
49
|
return { state: 'ready', attachment, prompt: input.revisedPrompt?.trim() || null, transparent: input.transparentBackground === true };
|
|
43
50
|
}
|
|
44
51
|
|
package/src/chat/logic/goal.ts
CHANGED
|
@@ -13,21 +13,28 @@ export interface GoalView {
|
|
|
13
13
|
*/
|
|
14
14
|
export function goalView(info: Pick<ChatInfo, 'goal' | 'activeTurnId'>, goals: ProviderCapabilities['goals'], canAct: boolean): GoalView | null {
|
|
15
15
|
const goal = info.goal;
|
|
16
|
+
|
|
16
17
|
if (goal === undefined) {
|
|
17
18
|
return null;
|
|
18
19
|
}
|
|
20
|
+
|
|
19
21
|
if (!canAct || goals === undefined) {
|
|
20
22
|
return { goal, actions: [] };
|
|
21
23
|
}
|
|
24
|
+
|
|
22
25
|
if (goals === 'command') {
|
|
23
26
|
return { goal, actions: goal.status === 'complete' || info.activeTurnId !== null ? [] : ['clear'] };
|
|
24
27
|
}
|
|
28
|
+
|
|
25
29
|
const actions: ChatGoalAction[] = [];
|
|
30
|
+
|
|
26
31
|
if (goal.status === 'active') {
|
|
27
32
|
actions.push('pause');
|
|
28
33
|
} else if (goal.status !== 'complete') {
|
|
29
34
|
actions.push('resume');
|
|
30
35
|
}
|
|
36
|
+
|
|
31
37
|
actions.push('clear');
|
|
38
|
+
|
|
32
39
|
return { goal, actions };
|
|
33
40
|
}
|
|
@@ -5,6 +5,8 @@ export function handbackReportOf(item: ChatItem): string | null {
|
|
|
5
5
|
if (item.kind !== 'tool' || item.name !== 'SubagentHandback' || typeof item.input !== 'object' || item.input === null) {
|
|
6
6
|
return null;
|
|
7
7
|
}
|
|
8
|
+
|
|
8
9
|
const message = (item.input as { message?: unknown }).message;
|
|
10
|
+
|
|
9
11
|
return typeof message === 'string' && message.trim() !== '' ? message : null;
|
|
10
12
|
}
|
package/src/chat/logic/limit.ts
CHANGED
|
@@ -16,10 +16,13 @@ export interface LimitView {
|
|
|
16
16
|
*/
|
|
17
17
|
export function limitView(info: Pick<ChatInfo, 'limit' | 'resumeAt' | 'activeTurnId'>, now: number): LimitView | null {
|
|
18
18
|
const limit = info.limit;
|
|
19
|
+
|
|
19
20
|
if (limit === undefined || info.activeTurnId !== null) {
|
|
20
21
|
return null;
|
|
21
22
|
}
|
|
23
|
+
|
|
22
24
|
const resumes = info.resumeAt === undefined ? null : formatMoment(info.resumeAt, now);
|
|
25
|
+
|
|
23
26
|
if (limit.kind === 'overload') {
|
|
24
27
|
return {
|
|
25
28
|
pill: resumes === null ? i18next.t('agent-chat:limit.overload.pill') : i18next.t('agent-chat:limit.overload.pillRetry', { time: resumes }),
|
|
@@ -27,7 +30,9 @@ export function limitView(info: Pick<ChatInfo, 'limit' | 'resumeAt' | 'activeTur
|
|
|
27
30
|
detail: resumes === null ? i18next.t('agent-chat:limit.overload.sendAgain') : i18next.t('agent-chat:limit.overload.retries', { time: resumes })
|
|
28
31
|
};
|
|
29
32
|
}
|
|
33
|
+
|
|
30
34
|
const title = i18next.t('agent-chat:limit.usage.title');
|
|
35
|
+
|
|
31
36
|
if (resumes !== null) {
|
|
32
37
|
return {
|
|
33
38
|
pill: i18next.t('agent-chat:limit.usage.pillResumes', { time: resumes }),
|
|
@@ -35,13 +40,16 @@ export function limitView(info: Pick<ChatInfo, 'limit' | 'resumeAt' | 'activeTur
|
|
|
35
40
|
detail: i18next.t('agent-chat:limit.usage.resumes', { time: resumes })
|
|
36
41
|
};
|
|
37
42
|
}
|
|
43
|
+
|
|
38
44
|
if (limit.resetsAt !== undefined) {
|
|
39
45
|
const resets = formatMoment(limit.resetsAt, now);
|
|
46
|
+
|
|
40
47
|
return {
|
|
41
48
|
pill: i18next.t('agent-chat:limit.usage.pillUntil', { time: resets }),
|
|
42
49
|
title,
|
|
43
50
|
detail: i18next.t('agent-chat:limit.usage.resets', { time: resets })
|
|
44
51
|
};
|
|
45
52
|
}
|
|
53
|
+
|
|
46
54
|
return { pill: i18next.t('agent-chat:limit.usage.pill'), title, detail: null };
|
|
47
55
|
}
|
|
@@ -4,6 +4,7 @@ import { nameCollator } from '@adecore/ui/format';
|
|
|
4
4
|
/* The providers in the order a picker lists them: the frontier labs, the rest, then the API providers, each by name. */
|
|
5
5
|
export function inPickerOrder<T extends { kind: AgentKind; name: string }>(providers: readonly T[]): T[] {
|
|
6
6
|
const groups = pickerGroupsOf(providers);
|
|
7
|
+
|
|
7
8
|
return [...groups.frontier, ...groups.others, ...groups.api];
|
|
8
9
|
}
|
|
9
10
|
|
|
@@ -33,6 +34,7 @@ export interface PickerCurrent {
|
|
|
33
34
|
export type FavoritesOf = (kind: AgentKind) => ReadonlySet<string>;
|
|
34
35
|
|
|
35
36
|
const NO_FAVORITES: FavoritesOf = () => new Set();
|
|
37
|
+
|
|
36
38
|
const VENDOR_ORDER: Intl.CollatorOptions = { sensitivity: 'base' };
|
|
37
39
|
const MODEL_ORDER: Intl.CollatorOptions = { sensitivity: 'base', numeric: true };
|
|
38
40
|
|
|
@@ -48,12 +50,15 @@ export function modelsByVendor(models: ModelInfo[]): ModelInfo[] {
|
|
|
48
50
|
if (!models.some((model) => model.vendor !== undefined)) {
|
|
49
51
|
return models;
|
|
50
52
|
}
|
|
53
|
+
|
|
51
54
|
const vendorOrder = nameCollator(VENDOR_ORDER).compare;
|
|
52
55
|
const modelOrder = nameCollator(MODEL_ORDER).compare;
|
|
56
|
+
|
|
53
57
|
return [...models].sort((a, b) => {
|
|
54
58
|
if (a.vendor === undefined || b.vendor === undefined) {
|
|
55
59
|
return a.vendor === b.vendor ? 0 : a.vendor === undefined ? 1 : -1;
|
|
56
60
|
}
|
|
61
|
+
|
|
57
62
|
return vendorOrder(a.vendor, b.vendor) || modelOrder(a.name, b.name);
|
|
58
63
|
});
|
|
59
64
|
}
|
|
@@ -63,6 +68,7 @@ export function favoritesFirst(models: ModelInfo[], favorites: ReadonlySet<strin
|
|
|
63
68
|
if (favorites.size === 0) {
|
|
64
69
|
return modelsByVendor(models);
|
|
65
70
|
}
|
|
71
|
+
|
|
66
72
|
return [...models.filter((model) => favorites.has(model.slug)), ...modelsByVendor(models.filter((model) => !favorites.has(model.slug)))];
|
|
67
73
|
}
|
|
68
74
|
|
|
@@ -79,6 +85,7 @@ export function shortlistOf(
|
|
|
79
85
|
if (models.length <= COMPACT_MODEL_LIMIT) {
|
|
80
86
|
return null;
|
|
81
87
|
}
|
|
88
|
+
|
|
82
89
|
return favoritesFirst(
|
|
83
90
|
models.filter((model) => model.isDefault || favorites.has(model.slug) || (current?.provider === kind && current.model === model.slug)),
|
|
84
91
|
favorites
|
|
@@ -97,6 +104,7 @@ export function searchModels(
|
|
|
97
104
|
favoritesOf: FavoritesOf = NO_FAVORITES
|
|
98
105
|
): Array<{ entry: ProviderInfo; models: ModelInfo[] }> {
|
|
99
106
|
const needle = query.trim().toLowerCase();
|
|
107
|
+
|
|
100
108
|
return providers
|
|
101
109
|
.map((entry) => ({
|
|
102
110
|
entry,
|
|
@@ -126,6 +134,7 @@ export function pickerEntriesOf(
|
|
|
126
134
|
): PickerEntry[] {
|
|
127
135
|
const rowsOf = (entry: ProviderInfo, models: ModelInfo[]): PickerEntry[] =>
|
|
128
136
|
favoritesFirst(models, favoritesOf(entry.kind)).map((model) => ({ kind: 'model', provider: entry, model }));
|
|
137
|
+
|
|
129
138
|
if (query !== '') {
|
|
130
139
|
return providers.flatMap((entry) =>
|
|
131
140
|
rowsOf(
|
|
@@ -134,22 +143,25 @@ export function pickerEntriesOf(
|
|
|
134
143
|
)
|
|
135
144
|
);
|
|
136
145
|
}
|
|
146
|
+
|
|
137
147
|
const legacy = providers.flatMap((entry) =>
|
|
138
148
|
entry.models.filter((model) => model.legacy).map((model) => ({ kind: 'model' as const, provider: entry, model }))
|
|
139
149
|
);
|
|
150
|
+
|
|
140
151
|
const live = providers.flatMap((entry): PickerEntry[] => {
|
|
141
152
|
const models = entry.models.filter((model) => !model.legacy);
|
|
142
153
|
const shortlist = shortlistOf(entry.kind, models, current, favoritesOf(entry.kind));
|
|
154
|
+
|
|
143
155
|
if (shortlist === null) {
|
|
144
156
|
return rowsOf(entry, models);
|
|
145
157
|
}
|
|
158
|
+
|
|
146
159
|
if (expanded.has(entry.kind)) {
|
|
147
160
|
return [{ kind: 'all', provider: entry, count: models.length, open: true }, ...rowsOf(entry, models)];
|
|
148
161
|
}
|
|
162
|
+
|
|
149
163
|
return [...rowsOf(entry, shortlist), { kind: 'all', provider: entry, count: models.length, open: false }];
|
|
150
164
|
});
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
return legacyOpen ? [...live, { kind: 'legacy', count: legacy.length }, ...legacy] : [...live, { kind: 'legacy', count: legacy.length }];
|
|
165
|
+
|
|
166
|
+
return legacy.length === 0 ? live : [...live, { kind: 'legacy', count: legacy.length }, ...(legacyOpen ? legacy : [])];
|
|
155
167
|
}
|