@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.
Files changed (317) hide show
  1. package/dist/agents/AgentModelLabel.js +2 -1
  2. package/dist/agents/model-name.js +2 -1
  3. package/dist/agents/provider-paths.d.ts +2 -1
  4. package/dist/agents/provider-paths.js +7 -3
  5. package/dist/chat/account-choice.js +57 -28
  6. package/dist/chat/bookmarks.js +2 -1
  7. package/dist/chat/drafts.d.ts +0 -1
  8. package/dist/chat/drafts.js +9 -28
  9. package/dist/chat/logic/picker-entries.js +2 -8
  10. package/dist/chat/logic/resume-compaction.js +2 -5
  11. package/dist/chat/logic/timeline-copy.js +2 -8
  12. package/dist/chat/logic/timeline.js +9 -10
  13. package/dist/chat/logic/workflow.js +2 -4
  14. package/dist/chat/subagent-conversation.js +2 -1
  15. package/dist/chat/ui/GoalDock.js +2 -1
  16. package/dist/chat/ui/LimitState.js +4 -6
  17. package/dist/chat/ui/composer/use-continuable-turn.js +0 -1
  18. package/dist/chat/ui/composer/use-notice.js +2 -1
  19. package/dist/chat/ui/composer/use-prompt-history.js +1 -1
  20. package/dist/chat/ui/composer/use-prompt-menus.js +216 -253
  21. package/dist/chat/ui/composer/use-take-back.js +2 -2
  22. package/dist/chat/ui/diff/ApprovalReview.js +1 -1
  23. package/dist/chat/ui/highlighter.d.ts +0 -6
  24. package/dist/chat/ui/highlighter.js +0 -12
  25. package/dist/chat/ui/icons.d.ts +0 -1
  26. package/dist/chat/ui/icons.js +0 -3
  27. package/dist/chat/ui/rows/MessageRows.js +2 -5
  28. package/dist/chat/ui/rows/row-rhythm.js +2 -5
  29. package/dist/chat/ui/theme-watch.js +3 -7
  30. package/dist/prompts/logic/usePromptSession.js +2 -1
  31. package/dist/providers/AddAccountForm.js +2 -1
  32. package/dist/providers/CliDetail.js +104 -130
  33. package/dist/providers/account-actions.js +6 -9
  34. package/dist/state/chats.d.ts +1 -0
  35. package/dist/state/chats.js +6 -11
  36. package/dist/state/provider-accounts.d.ts +1 -1
  37. package/dist/state/provider-accounts.js +2 -8
  38. package/dist/transport.d.ts +2 -0
  39. package/dist/transport.js +14 -0
  40. package/dist/usage/ChartLogo.d.ts +5 -0
  41. package/dist/usage/ChartLogo.js +48 -0
  42. package/dist/usage/LimitsList.js +6 -16
  43. package/dist/usage/UsageBreakdown.js +17 -40
  44. package/dist/usage/UsageLimits.js +183 -211
  45. package/dist/usage/UsagePage.js +3 -17
  46. package/dist/usage/UsageSummary.js +4 -9
  47. package/dist/usage/limits.js +16 -31
  48. package/dist/usage/summary.d.ts +1 -1
  49. package/dist/usage/summary.js +3 -5
  50. package/package.json +26 -26
  51. package/src/agents/AccountDot.tsx +1 -0
  52. package/src/agents/AgentIcon.tsx +2 -0
  53. package/src/agents/AgentModelLabel.tsx +4 -6
  54. package/src/agents/ModelOptionControl.tsx +8 -0
  55. package/src/agents/account-limits.ts +3 -0
  56. package/src/agents/accounts.ts +12 -0
  57. package/src/agents/model-name.ts +13 -1
  58. package/src/agents/model-options.ts +2 -0
  59. package/src/agents/model-requirement.ts +4 -0
  60. package/src/agents/option-words.ts +2 -0
  61. package/src/agents/provider-paths.ts +8 -3
  62. package/src/agents/status-look.ts +1 -0
  63. package/src/chat/account-choice.ts +25 -19
  64. package/src/chat/actions.ts +5 -0
  65. package/src/chat/attachments.ts +8 -0
  66. package/src/chat/bookmarks.ts +13 -1
  67. package/src/chat/chat-client.ts +63 -0
  68. package/src/chat/chat-references.ts +3 -0
  69. package/src/chat/composer-effort.ts +5 -0
  70. package/src/chat/composer-send.ts +4 -0
  71. package/src/chat/drafts.ts +21 -17
  72. package/src/chat/forks.ts +4 -0
  73. package/src/chat/guards.ts +2 -0
  74. package/src/chat/index.ts +7 -0
  75. package/src/chat/logic/ansi.ts +47 -0
  76. package/src/chat/logic/bookmarks.ts +7 -0
  77. package/src/chat/logic/command-looks.ts +29 -0
  78. package/src/chat/logic/context-usage.ts +3 -0
  79. package/src/chat/logic/continue-after-stop.ts +5 -0
  80. package/src/chat/logic/effort.ts +4 -0
  81. package/src/chat/logic/embedded-code.ts +63 -0
  82. package/src/chat/logic/fork.ts +22 -0
  83. package/src/chat/logic/generated-image.ts +7 -0
  84. package/src/chat/logic/goal.ts +7 -0
  85. package/src/chat/logic/handback.ts +2 -0
  86. package/src/chat/logic/limit.ts +8 -0
  87. package/src/chat/logic/picker-entries.ts +16 -4
  88. package/src/chat/logic/resume-compaction.ts +22 -5
  89. package/src/chat/logic/scrubber.ts +38 -5
  90. package/src/chat/logic/thought.ts +5 -0
  91. package/src/chat/logic/thread-cards.ts +6 -0
  92. package/src/chat/logic/timeline-copy.ts +4 -9
  93. package/src/chat/logic/timeline-target.ts +15 -0
  94. package/src/chat/logic/timeline.ts +113 -10
  95. package/src/chat/logic/tools.ts +30 -0
  96. package/src/chat/logic/visual-height.ts +5 -0
  97. package/src/chat/logic/visual-viewport.ts +1 -0
  98. package/src/chat/logic/welcome.ts +3 -0
  99. package/src/chat/logic/workflow.ts +26 -7
  100. package/src/chat/mentions.ts +56 -0
  101. package/src/chat/pending-prompts.ts +16 -0
  102. package/src/chat/persisted-json.ts +15 -0
  103. package/src/chat/preferences.ts +16 -0
  104. package/src/chat/prompt-hold.ts +2 -0
  105. package/src/chat/quote.ts +7 -0
  106. package/src/chat/reading-width.ts +1 -0
  107. package/src/chat/recent-messages.ts +5 -0
  108. package/src/chat/resume-compaction-dismissals.ts +1 -0
  109. package/src/chat/stash.ts +12 -0
  110. package/src/chat/subagent-conversation.ts +24 -4
  111. package/src/chat/subagent-list.ts +14 -0
  112. package/src/chat/subagent-support.ts +1 -0
  113. package/src/chat/subagent-view.ts +9 -0
  114. package/src/chat/thumbnails.ts +14 -0
  115. package/src/chat/timeline-flash.ts +2 -0
  116. package/src/chat/timeline-scroll.ts +23 -0
  117. package/src/chat/ui/AccountPill.tsx +4 -0
  118. package/src/chat/ui/AnsiOutput.tsx +1 -0
  119. package/src/chat/ui/BookmarkMarker.tsx +5 -0
  120. package/src/chat/ui/BookmarkSubmenu.tsx +1 -0
  121. package/src/chat/ui/ChatActivity.tsx +13 -0
  122. package/src/chat/ui/CodeBlock.tsx +8 -0
  123. package/src/chat/ui/Composer.tsx +15 -0
  124. package/src/chat/ui/ComposerInput.tsx +22 -0
  125. package/src/chat/ui/DiffPool.tsx +3 -0
  126. package/src/chat/ui/EditDiff.tsx +5 -0
  127. package/src/chat/ui/GoalDock.tsx +13 -1
  128. package/src/chat/ui/ImageView.tsx +11 -0
  129. package/src/chat/ui/LimitState.tsx +23 -6
  130. package/src/chat/ui/Markdown.tsx +41 -0
  131. package/src/chat/ui/MermaidBlock.tsx +16 -0
  132. package/src/chat/ui/MessageActions.tsx +8 -0
  133. package/src/chat/ui/ModelMarks.tsx +1 -0
  134. package/src/chat/ui/Pickers.tsx +26 -0
  135. package/src/chat/ui/PromptComposer.tsx +2 -0
  136. package/src/chat/ui/PromptEditor.tsx +6 -0
  137. package/src/chat/ui/QuoteButton.tsx +12 -0
  138. package/src/chat/ui/ReferenceChip.tsx +3 -0
  139. package/src/chat/ui/ResumeCompactionDock.tsx +1 -0
  140. package/src/chat/ui/RowTime.tsx +1 -0
  141. package/src/chat/ui/RunSettings.tsx +38 -0
  142. package/src/chat/ui/Scrubber.tsx +14 -0
  143. package/src/chat/ui/SessionLine.tsx +1 -0
  144. package/src/chat/ui/ShellCommand.tsx +32 -0
  145. package/src/chat/ui/SubagentControls.tsx +7 -0
  146. package/src/chat/ui/SubagentInfo.tsx +1 -0
  147. package/src/chat/ui/SubagentStopButton.tsx +6 -0
  148. package/src/chat/ui/SubagentTimeline.tsx +10 -0
  149. package/src/chat/ui/Timeline.tsx +119 -0
  150. package/src/chat/ui/TimelineMenu.tsx +5 -0
  151. package/src/chat/ui/UnifiedDiff.tsx +6 -0
  152. package/src/chat/ui/UploadThumb.tsx +2 -0
  153. package/src/chat/ui/VisualDialogs.tsx +3 -0
  154. package/src/chat/ui/VisualFrame.tsx +15 -0
  155. package/src/chat/ui/Welcome.tsx +1 -0
  156. package/src/chat/ui/chip-clipboard.ts +20 -0
  157. package/src/chat/ui/code-lines.ts +14 -0
  158. package/src/chat/ui/code-theme.ts +1 -0
  159. package/src/chat/ui/composer/ComposerControls.tsx +5 -0
  160. package/src/chat/ui/composer/ComposerMenu.tsx +12 -0
  161. package/src/chat/ui/composer/DraftParts.tsx +2 -0
  162. package/src/chat/ui/composer/QueuedMessages.tsx +4 -0
  163. package/src/chat/ui/composer/chip-paste.ts +16 -0
  164. package/src/chat/ui/composer/chips.ts +6 -0
  165. package/src/chat/ui/composer/editor.ts +9 -0
  166. package/src/chat/ui/composer/insert.ts +2 -0
  167. package/src/chat/ui/composer/key-handler.ts +39 -0
  168. package/src/chat/ui/composer/keys.ts +23 -0
  169. package/src/chat/ui/composer/placeholder.ts +6 -0
  170. package/src/chat/ui/composer/prompt-picks.ts +1 -0
  171. package/src/chat/ui/composer/surface.ts +5 -0
  172. package/src/chat/ui/composer/use-chat-controls.ts +13 -0
  173. package/src/chat/ui/composer/use-compaction-offer.ts +3 -0
  174. package/src/chat/ui/composer/use-composer-menus.ts +2 -0
  175. package/src/chat/ui/composer/use-composer-submit.ts +27 -0
  176. package/src/chat/ui/composer/use-continuable-turn.ts +3 -5
  177. package/src/chat/ui/composer/use-draft-files.ts +24 -0
  178. package/src/chat/ui/composer/use-effort-stepper.ts +8 -0
  179. package/src/chat/ui/composer/use-notice.ts +4 -1
  180. package/src/chat/ui/composer/use-pending-requests.ts +3 -0
  181. package/src/chat/ui/composer/use-prompt-history.ts +20 -11
  182. package/src/chat/ui/composer/use-prompt-hold.ts +3 -0
  183. package/src/chat/ui/composer/use-prompt-menus.ts +34 -14
  184. package/src/chat/ui/composer/use-take-back.ts +20 -2
  185. package/src/chat/ui/diff/ApprovalReview.tsx +18 -15
  186. package/src/chat/ui/diff/DiffFallbackBoundary.tsx +1 -0
  187. package/src/chat/ui/diff/DiffOmitted.tsx +1 -0
  188. package/src/chat/ui/diff/DiffStack.tsx +2 -0
  189. package/src/chat/ui/diff/DiffUnavailable.tsx +1 -0
  190. package/src/chat/ui/diff/EditorEditDiff.tsx +13 -0
  191. package/src/chat/ui/diff/EditorPatchDiff.tsx +4 -0
  192. package/src/chat/ui/diff/LegacyDiffPool.tsx +2 -0
  193. package/src/chat/ui/diff/LegacyEditDiff.tsx +2 -0
  194. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +8 -0
  195. package/src/chat/ui/diff/RawDiff.tsx +1 -0
  196. package/src/chat/ui/diff/ReviewDiff.tsx +1 -0
  197. package/src/chat/ui/diff/diff-source-budget.ts +8 -0
  198. package/src/chat/ui/diff/editor-edit-model.ts +4 -0
  199. package/src/chat/ui/diff/review-plan.ts +9 -0
  200. package/src/chat/ui/diff/review-settle.ts +1 -0
  201. package/src/chat/ui/diff/syntax-runtime.ts +52 -0
  202. package/src/chat/ui/diff/use-review-stack.ts +9 -0
  203. package/src/chat/ui/diff-syntax.ts +12 -0
  204. package/src/chat/ui/diff-theme.ts +2 -0
  205. package/src/chat/ui/file-links.ts +2 -0
  206. package/src/chat/ui/find-reveal.ts +1 -0
  207. package/src/chat/ui/full-diff.ts +1 -0
  208. package/src/chat/ui/highlighter.ts +29 -15
  209. package/src/chat/ui/icons.tsx +2 -4
  210. package/src/chat/ui/index.ts +4 -0
  211. package/src/chat/ui/intelligent-ui/UiBlockFrame.tsx +25 -0
  212. package/src/chat/ui/intelligent-ui/UiFallbackPart.tsx +1 -0
  213. package/src/chat/ui/intelligent-ui/UiReply.tsx +63 -0
  214. package/src/chat/ui/intelligent-ui/block-local.ts +5 -0
  215. package/src/chat/ui/intelligent-ui/chart-data.ts +15 -0
  216. package/src/chat/ui/intelligent-ui/node-text.ts +17 -0
  217. package/src/chat/ui/intelligent-ui/renderers/binding.ts +1 -0
  218. package/src/chat/ui/intelligent-ui/renderers/chart.tsx +31 -0
  219. package/src/chat/ui/intelligent-ui/renderers/choices.tsx +4 -0
  220. package/src/chat/ui/intelligent-ui/renderers/content.tsx +18 -0
  221. package/src/chat/ui/intelligent-ui/renderers/data.tsx +11 -0
  222. package/src/chat/ui/intelligent-ui/renderers/inputs.tsx +13 -0
  223. package/src/chat/ui/intelligent-ui/renderers/links.tsx +9 -0
  224. package/src/chat/ui/intelligent-ui/renderers/map-slots.ts +15 -0
  225. package/src/chat/ui/intelligent-ui/renderers/map-style.ts +15 -0
  226. package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +48 -0
  227. package/src/chat/ui/intelligent-ui/renderers/map.tsx +20 -0
  228. package/src/chat/ui/intelligent-ui/renderers/place-point.ts +3 -0
  229. package/src/chat/ui/intelligent-ui/renderers/structure.tsx +3 -0
  230. package/src/chat/ui/intelligent-ui/renderers/text.tsx +8 -0
  231. package/src/chat/ui/intelligent-ui/reply-parts.ts +5 -0
  232. package/src/chat/ui/intelligent-ui/table-data.ts +17 -0
  233. package/src/chat/ui/intelligent-ui/use-in-view.ts +4 -0
  234. package/src/chat/ui/intelligent-ui/use-later.ts +4 -0
  235. package/src/chat/ui/intelligent-ui/use-truncated.ts +5 -0
  236. package/src/chat/ui/intelligent-ui/use-ui-links.ts +29 -0
  237. package/src/chat/ui/intelligent-ui/use-ui-queries.ts +60 -0
  238. package/src/chat/ui/markdown-blocks.ts +64 -0
  239. package/src/chat/ui/mermaid.ts +4 -0
  240. package/src/chat/ui/quote-selection.ts +10 -0
  241. package/src/chat/ui/rehype-chips.ts +5 -0
  242. package/src/chat/ui/rehype-fade.ts +2 -0
  243. package/src/chat/ui/remark-html-as-text.ts +5 -0
  244. package/src/chat/ui/reveal.ts +18 -0
  245. package/src/chat/ui/rows/ForksRow.tsx +5 -0
  246. package/src/chat/ui/rows/GeneratedImageRow.tsx +10 -0
  247. package/src/chat/ui/rows/MessageRows.tsx +29 -5
  248. package/src/chat/ui/rows/RowContainer.tsx +1 -0
  249. package/src/chat/ui/rows/Rows.tsx +2 -0
  250. package/src/chat/ui/rows/SubagentRow.tsx +13 -0
  251. package/src/chat/ui/rows/TaskRow.tsx +7 -0
  252. package/src/chat/ui/rows/VisualRow.tsx +4 -0
  253. package/src/chat/ui/rows/WorkRows.tsx +46 -0
  254. package/src/chat/ui/rows/WorkflowRow.tsx +10 -0
  255. package/src/chat/ui/rows/row-rhythm.ts +7 -5
  256. package/src/chat/ui/theme-watch.ts +8 -7
  257. package/src/chat/ui/thread-references.ts +7 -0
  258. package/src/chat/ui/use-diff-source-tokens.ts +8 -0
  259. package/src/chat/ui/useToggleSet.ts +3 -0
  260. package/src/chat/ui/visual-theme.ts +30 -0
  261. package/src/chat/visual-bridge.ts +23 -0
  262. package/src/chat/visual-viewport.ts +12 -0
  263. package/src/host-hooks.ts +6 -4
  264. package/src/host.ts +2 -0
  265. package/src/index.ts +3 -0
  266. package/src/lazy.tsx +9 -0
  267. package/src/mounted-registry.ts +4 -0
  268. package/src/port-transport.ts +32 -0
  269. package/src/prompts/index.ts +2 -0
  270. package/src/prompts/logic/focus.ts +5 -0
  271. package/src/prompts/logic/keys.ts +12 -0
  272. package/src/prompts/logic/prompts.ts +8 -0
  273. package/src/prompts/logic/subjects.ts +8 -0
  274. package/src/prompts/logic/useFocusAfterAnswer.ts +2 -0
  275. package/src/prompts/logic/usePromptSession.ts +13 -1
  276. package/src/prompts/ui/ApprovalBody.tsx +2 -0
  277. package/src/prompts/ui/PromptActions.tsx +2 -0
  278. package/src/prompts/ui/PromptCard.tsx +6 -0
  279. package/src/prompts/ui/PromptView.tsx +6 -0
  280. package/src/prompts/ui/QuestionBody.tsx +11 -0
  281. package/src/providers/AccountColors.tsx +1 -0
  282. package/src/providers/AccountDetail.tsx +7 -0
  283. package/src/providers/AccountVariables.tsx +2 -0
  284. package/src/providers/AddAccountForm.tsx +5 -1
  285. package/src/providers/CliDetail.tsx +6 -5
  286. package/src/providers/InstallPage.tsx +11 -0
  287. package/src/providers/ProviderList.tsx +3 -0
  288. package/src/providers/ProvidersPane.tsx +18 -0
  289. package/src/providers/account-actions.ts +10 -8
  290. package/src/providers/install-steps.ts +3 -0
  291. package/src/providers/pane-target.ts +5 -0
  292. package/src/providers/provider-abilities.ts +1 -0
  293. package/src/providers/provider-groups.ts +6 -0
  294. package/src/providers/variables.ts +12 -0
  295. package/src/scope.ts +2 -0
  296. package/src/state/chats.ts +61 -14
  297. package/src/state/index.ts +2 -0
  298. package/src/state/provider-accounts.ts +7 -9
  299. package/src/state/providers.ts +1 -0
  300. package/src/state/usage.ts +6 -0
  301. package/src/storage.ts +18 -0
  302. package/src/testing/prompts.ts +5 -0
  303. package/src/transport.ts +18 -0
  304. package/src/usage/ChartLogo.tsx +12 -0
  305. package/src/usage/LimitsList.tsx +7 -8
  306. package/src/usage/UsageBreakdown.tsx +11 -4
  307. package/src/usage/UsageChart.tsx +5 -0
  308. package/src/usage/UsageLimits.tsx +10 -7
  309. package/src/usage/UsageLimitsCard.tsx +2 -0
  310. package/src/usage/UsagePage.tsx +16 -19
  311. package/src/usage/UsageSummary.tsx +4 -5
  312. package/src/usage/UsageTiles.tsx +2 -0
  313. package/src/usage/format.ts +7 -0
  314. package/src/usage/limit-groups.ts +14 -0
  315. package/src/usage/limits.ts +11 -13
  316. package/src/usage/money.ts +1 -0
  317. package/src/usage/summary.ts +15 -7
package/src/chat/index.ts CHANGED
@@ -8,6 +8,7 @@ export { stepEffortFromComposer } from './composer-effort';
8
8
  export type { EffortStep } from './logic/effort';
9
9
  export { EMPTY_DRAFT, useDrafts, readDraft, writeDraft, offerDraft, type ChatDraft } from './drafts';
10
10
  export { stripAnsi } from './logic/ansi';
11
+
11
12
  export {
12
13
  FORKABLE_PROVIDERS,
13
14
  forkRefusal,
@@ -23,6 +24,7 @@ export {
23
24
  type ForkPoint,
24
25
  type ForkWorktreeChoice
25
26
  } from './logic/fork';
27
+
26
28
  export { matchCommandLook, type CommandLookRun, type CommandLookWord } from './logic/command-looks';
27
29
  export { handbackReportOf } from './logic/handback';
28
30
  export { limitView, type LimitView } from './logic/limit';
@@ -31,6 +33,7 @@ export { type TimedRow, withTimedRows, timedRowsOf } from './logic/thread-cards'
31
33
  export { EMPTY_TARGET, readTimelineTarget, type TimelineTarget } from './logic/timeline-target';
32
34
  export { type TimelineRow, summarizeGroup, deriveTimelineRows, type SubagentBranch, type BaseMoved } from './logic/timeline';
33
35
  export { toolSummary, type FileChange } from './logic/tools';
36
+
34
37
  export {
35
38
  MENTION_DRAG_TYPE,
36
39
  LEGACY_MENTION_DRAG_TYPE,
@@ -41,6 +44,7 @@ export {
41
44
  type MentionQuery,
42
45
  type ChipSegment
43
46
  } from './mentions';
47
+
44
48
  export {
45
49
  defaultProvider,
46
50
  selectionFor,
@@ -57,6 +61,7 @@ export {
57
61
  rememberChatSelection,
58
62
  type ChatPreferences
59
63
  } from './preferences';
64
+
60
65
  export type { HoldRelease } from './prompt-hold';
61
66
  export { CHAT_READING_WIDTHS, readingWidthLabel, readingWidthHint, type ChatReadingWidth } from './reading-width';
62
67
  export { recentChatMessages, recentSubagentMessages, type RecentChatMessage, type RecentChatMessages } from './recent-messages';
@@ -65,6 +70,7 @@ export { CHAT_SEND_KEYS, SEND_AND_NEW_SHORTCUT, sendKeyLabel, sendKeyHint, type
65
70
  export type { StashedAttachment, StashedPrompt, StashedQuote } from './stash';
66
71
  export { subagentTitle, summaryWordOf, stopOf, type SubagentStop } from './subagent-list';
67
72
  export { useSubagentSupport } from './subagent-support';
73
+
68
74
  export {
69
75
  crumbOf,
70
76
  openFromMain,
@@ -76,6 +82,7 @@ export {
76
82
  type SubagentStep,
77
83
  type SubagentTrail
78
84
  } from './subagent-view';
85
+
79
86
  export { stepTimelineMessage, jumpToTimelineItem, type TurnTarget, registerTurnJumper, jumpToTimelineTurn, type ItemJumpOptions } from './timeline-scroll';
80
87
  export { type StatusWord, statusLookOf, taskStatusWord, type StatusLook, type TaskState } from '../agents/status-look';
81
88
 
@@ -18,6 +18,7 @@ interface AnsiState {
18
18
 
19
19
  const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'];
20
20
  const COLOR_LEVELS = [0, 95, 135, 175, 215, 255];
21
+
21
22
  // Consume non-color controls too, so cursor commands and OSC links never become visible text or HTML.
22
23
  /* oxlint-disable no-control-regex */
23
24
  const ESCAPES =
@@ -32,6 +33,7 @@ function rgb(channels: number[]): string | undefined {
32
33
  if (channels.length !== 3 || channels.some((channel) => !Number.isInteger(channel) || channel < 0 || channel > 255)) {
33
34
  return undefined;
34
35
  }
36
+
35
37
  return `rgb(${channels.join(' ')})`;
36
38
  }
37
39
 
@@ -39,27 +41,36 @@ function paletteColor(index: number): string | undefined {
39
41
  if (!Number.isInteger(index) || index < 0 || index > 255) {
40
42
  return undefined;
41
43
  }
44
+
42
45
  if (index < 16) {
43
46
  return `var(--term-ansi-${index >= 8 ? 'bright-' : ''}${COLORS[index % 8]})`;
44
47
  }
48
+
45
49
  if (index < 232) {
46
50
  const cube = index - 16;
51
+
47
52
  return rgb([COLOR_LEVELS[Math.floor(cube / 36)]!, COLOR_LEVELS[Math.floor(cube / 6) % 6]!, COLOR_LEVELS[cube % 6]!]);
48
53
  }
54
+
49
55
  const gray = 8 + (index - 232) * 10;
56
+
50
57
  return rgb([gray, gray, gray]);
51
58
  }
52
59
 
53
60
  function extendedColor(parameters: string[]): string | undefined {
54
61
  const mode = parameters[0];
62
+
55
63
  if (mode === '5' && parameters.length === 2 && parameters[1] !== '') {
56
64
  return paletteColor(Number(parameters[1]));
57
65
  }
66
+
58
67
  if (mode === '2') {
59
68
  // Colon-form RGB may include an empty color-space parameter before its three channels.
60
69
  const channels = parameters.length === 5 ? parameters.slice(2) : parameters.slice(1);
70
+
61
71
  return rgb(channels.map((channel) => (channel === '' ? NaN : Number(channel))));
62
72
  }
73
+
63
74
  return undefined;
64
75
  }
65
76
 
@@ -67,12 +78,16 @@ function applyRendition(state: AnsiState, parameters: string): AnsiState {
67
78
  if (!/^[\d;:]*$/.test(parameters)) {
68
79
  return state;
69
80
  }
81
+
70
82
  const values = parameters.split(';');
83
+
71
84
  for (let i = 0; i < values.length; i++) {
72
85
  const parts = values[i]!.split(':');
73
86
  const code = Number(parts[0]);
87
+
74
88
  if (code === 38 || code === 48) {
75
89
  let color: string | undefined;
90
+
76
91
  if (parts.length > 1) {
77
92
  color = extendedColor(parts.slice(1));
78
93
  } else {
@@ -80,6 +95,7 @@ function applyRendition(state: AnsiState, parameters: string): AnsiState {
80
95
  color = extendedColor(values.slice(i + 1, i + 1 + count));
81
96
  i += count;
82
97
  }
98
+
83
99
  if (color !== undefined) {
84
100
  state[code === 38 ? 'foreground' : 'background'] = color;
85
101
  }
@@ -95,50 +111,65 @@ function applyRendition(state: AnsiState, parameters: string): AnsiState {
95
111
  switch (code) {
96
112
  case 0:
97
113
  state = {};
114
+
98
115
  break;
99
116
  case 1:
100
117
  state.bold = true;
118
+
101
119
  break;
102
120
  case 2:
103
121
  state.dim = true;
122
+
104
123
  break;
105
124
  case 3:
106
125
  state.italic = true;
126
+
107
127
  break;
108
128
  case 4:
109
129
  state.underline = parts[1] !== '0';
130
+
110
131
  break;
111
132
  case 7:
112
133
  state.inverse = true;
134
+
113
135
  break;
114
136
  case 9:
115
137
  state.strike = true;
138
+
116
139
  break;
117
140
  case 22:
118
141
  state.bold = false;
119
142
  state.dim = false;
143
+
120
144
  break;
121
145
  case 23:
122
146
  state.italic = false;
147
+
123
148
  break;
124
149
  case 24:
125
150
  state.underline = false;
151
+
126
152
  break;
127
153
  case 27:
128
154
  state.inverse = false;
155
+
129
156
  break;
130
157
  case 29:
131
158
  state.strike = false;
159
+
132
160
  break;
133
161
  case 39:
134
162
  state.foreground = undefined;
163
+
135
164
  break;
136
165
  case 49:
137
166
  state.background = undefined;
167
+
138
168
  break;
139
169
  }
140
170
  }
141
171
  }
172
+
142
173
  return state;
143
174
  }
144
175
 
@@ -146,21 +177,27 @@ function styleOf(state: AnsiState): CSSProperties {
146
177
  const style: CSSProperties = {};
147
178
  const color = state.inverse ? (state.background ?? 'var(--chat-code-bg)') : state.foreground;
148
179
  const background = state.inverse ? (state.foreground ?? 'var(--chat-output)') : state.background;
180
+
149
181
  if (color !== undefined || state.dim) {
150
182
  style.color = state.dim ? `color-mix(in srgb, ${color ?? 'currentColor'} 65%, transparent)` : color;
151
183
  }
184
+
152
185
  if (background !== undefined) {
153
186
  style.backgroundColor = background;
154
187
  }
188
+
155
189
  if (state.bold) {
156
190
  style.fontWeight = 'bold';
157
191
  }
192
+
158
193
  if (state.italic) {
159
194
  style.fontStyle = 'italic';
160
195
  }
196
+
161
197
  if (state.underline || state.strike) {
162
198
  style.textDecorationLine = [state.underline && 'underline', state.strike && 'line-through'].filter(Boolean).join(' ');
163
199
  }
200
+
164
201
  return style;
165
202
  }
166
203
 
@@ -168,18 +205,23 @@ function styledTokens(text: string): AnsiToken[] {
168
205
  const tokens: AnsiToken[] = [];
169
206
  let state: AnsiState = {};
170
207
  let position = 0;
208
+
171
209
  for (const match of text.matchAll(ESCAPES)) {
172
210
  if (match.index > position) {
173
211
  tokens.push({ content: text.slice(position, match.index), style: styleOf(state) });
174
212
  }
213
+
175
214
  if (match[2] === 'm') {
176
215
  state = applyRendition(state, match[1]!);
177
216
  }
217
+
178
218
  position = match.index + match[0].length;
179
219
  }
220
+
180
221
  if (position < text.length) {
181
222
  tokens.push({ content: text.slice(position), style: styleOf(state) });
182
223
  }
224
+
183
225
  return tokens;
184
226
  }
185
227
 
@@ -188,21 +230,26 @@ export function parseAnsi(text: string, options: { limit?: number; tailLines?: n
188
230
  const plain = tokens.map((token) => token.content).join('');
189
231
  let start = 0;
190
232
  let end = plain.length;
233
+
191
234
  if (options.tailLines !== undefined) {
192
235
  if (plain.endsWith('\n')) {
193
236
  end--;
194
237
  }
238
+
195
239
  const tail = plain.slice(0, end).split('\n').slice(-options.tailLines).join('\n');
196
240
  start = end - tail.length;
197
241
  }
242
+
198
243
  const omitted = options.limit === undefined ? 0 : Math.max(0, end - start - options.limit);
199
244
  end -= omitted;
200
245
  let offset = 0;
246
+
201
247
  return {
202
248
  tokens: tokens.flatMap((token) => {
203
249
  const from = Math.max(0, start - offset);
204
250
  const to = Math.min(token.content.length, end - offset);
205
251
  offset += token.content.length;
252
+
206
253
  return to > from ? [{ ...token, content: token.content.slice(from, to) }] : [];
207
254
  }),
208
255
  omitted
@@ -9,7 +9,9 @@ export function bookmarkLabel(bookmark: ChatBookmark): string {
9
9
  /* The bookmarks in the order of the thread; one whose message this client does not hold goes last. */
10
10
  export function bookmarksInThreadOrder(bookmarks: readonly ChatBookmark[], order: readonly string[]): ChatBookmark[] {
11
11
  const places = new Map(order.map((id, index) => [id, index]));
12
+
12
13
  const place = (bookmark: ChatBookmark): number => places.get(bookmark.itemId) ?? order.length;
14
+
13
15
  return [...bookmarks].sort((left, right) => place(left) - place(right) || left.createdAt - right.createdAt);
14
16
  }
15
17
 
@@ -25,18 +27,23 @@ export function bookmarkRows(
25
27
  ): Map<string, ChatBookmark> {
26
28
  const rowIds = new Set(rows.map((row) => row.id));
27
29
  const folds = new Map<string, string>();
30
+
28
31
  for (const row of rows) {
29
32
  if (row.kind === 'turn-fold') {
30
33
  folds.set(row.turn.id, row.id);
31
34
  }
32
35
  }
36
+
33
37
  const marked = new Map<string, ChatBookmark>();
38
+
34
39
  for (const bookmark of bookmarks) {
35
40
  const turnId = items[bookmark.itemId]?.turnId ?? null;
36
41
  const rowId = rowIds.has(bookmark.itemId) ? bookmark.itemId : turnId === null ? undefined : folds.get(turnId);
42
+
37
43
  if (rowId !== undefined && !marked.has(rowId)) {
38
44
  marked.set(rowId, bookmark);
39
45
  }
40
46
  }
47
+
41
48
  return marked;
42
49
  }
@@ -39,19 +39,25 @@ const caches = new WeakMap<readonly CommandLook[], Map<string, CommandLookRun |
39
39
  /* The look of a simple command and what it says about it, or null when no look knows it. */
40
40
  function lookOf(command: ShellSimpleCommand, looks: readonly CommandLook[]): { look: CommandLook; match: CommandLookMatch } | null {
41
41
  const program = command.program;
42
+
42
43
  if (program === null) {
43
44
  return null;
44
45
  }
46
+
45
47
  const args = command.words.slice(program.index + 1).map(({ text }) => text);
48
+
46
49
  for (const look of looks) {
47
50
  if (look.program !== program.name) {
48
51
  continue;
49
52
  }
53
+
50
54
  const match = look.describe(args);
55
+
51
56
  if (match !== null) {
52
57
  return { look, match };
53
58
  }
54
59
  }
60
+
55
61
  return null;
56
62
  }
57
63
 
@@ -59,16 +65,21 @@ function lookOf(command: ShellSimpleCommand, looks: readonly CommandLook[]): { l
59
65
  function foldedWord(source: string, word: ShellWord, fold: boolean): { text: string; body: { start: number; end: number } | null } {
60
66
  const text = source.slice(word.start, word.end);
61
67
  const body = word.body === null ? null : { start: word.body.start - word.start, end: word.body.end - word.start };
68
+
62
69
  if (!fold) {
63
70
  return { text, body };
64
71
  }
72
+
65
73
  if (body !== null && body.end - body.start > FOLD_LENGTH) {
66
74
  const cut = body.start + FOLD_LENGTH;
75
+
67
76
  return { text: `${text.slice(0, cut)}…${text.slice(body.end)}`, body: { start: body.start, end: cut + 1 } };
68
77
  }
78
+
69
79
  if (body === null && text.length > FOLD_LENGTH) {
70
80
  return { text: `${text.slice(0, FOLD_LENGTH)}…`, body: null };
71
81
  }
82
+
72
83
  return { text, body };
73
84
  }
74
85
 
@@ -81,25 +92,32 @@ function detailOf(source: string, command: ShellSimpleCommand, match: CommandLoo
81
92
  let previous: ShellWord | null = null;
82
93
  // The option the word before was, whose value this word may be.
83
94
  let option: string | null = null;
95
+
84
96
  for (const word of command.words.slice(first)) {
85
97
  if (previous !== null) {
86
98
  const gap = source.slice(previous.end, word.start);
87
99
  detail += /^[ \t]*$/.test(gap) ? gap : ' ';
88
100
  }
101
+
89
102
  const start = detail.length;
90
103
  const { text, body } = foldedWord(source, word, option !== null && match.fold?.includes(option) === true);
91
104
  const language = option === null ? undefined : match.languages?.[option];
105
+
92
106
  if (language !== undefined && body !== null && body.end > body.start) {
93
107
  code.push({ start: start + body.start, end: start + body.end, language });
94
108
  }
109
+
95
110
  detail += text;
96
111
  const isOption = word.text.startsWith('-') && word.text !== '-';
112
+
97
113
  if (!isOption) {
98
114
  words.push({ start, end: detail.length, text: word.text, option });
99
115
  }
116
+
100
117
  option = isOption ? word.text : null;
101
118
  previous = word;
102
119
  }
120
+
103
121
  return { detail, code, words };
104
122
  }
105
123
 
@@ -107,8 +125,10 @@ function read(command: string, looks: readonly CommandLook[]): CommandLookRun |
107
125
  let found: { command: ShellSimpleCommand; look: CommandLook; match: CommandLookMatch } | null = null;
108
126
  let more = 0;
109
127
  const others: string[] = [];
128
+
110
129
  for (const simple of shellCommands(command)) {
111
130
  const known = lookOf(simple, looks);
131
+
112
132
  if (known !== null && found === null) {
113
133
  found = { command: simple, ...known };
114
134
  } else if (known !== null) {
@@ -117,9 +137,11 @@ function read(command: string, looks: readonly CommandLook[]): CommandLookRun |
117
137
  others.push(simple.program.name);
118
138
  }
119
139
  }
140
+
120
141
  if (found === null) {
121
142
  return null;
122
143
  }
144
+
123
145
  return {
124
146
  look: found.look,
125
147
  match: found.match,
@@ -139,19 +161,26 @@ export function matchCommandLook(command: string, looks: readonly CommandLook[]
139
161
  if (looks === undefined || looks.length === 0 || command.length > EMBEDDED_CODE_LIMIT || !looks.some(({ program }) => command.includes(program))) {
140
162
  return null;
141
163
  }
164
+
142
165
  let cache = caches.get(looks);
166
+
143
167
  if (cache === undefined) {
144
168
  cache = new Map();
145
169
  caches.set(looks, cache);
146
170
  }
171
+
147
172
  const known = cache.get(command);
173
+
148
174
  if (known !== undefined) {
149
175
  return known;
150
176
  }
177
+
151
178
  const run = read(command, looks);
152
179
  cache.set(command, run);
180
+
153
181
  if (cache.size > CACHE_LIMIT) {
154
182
  cache.delete(cache.keys().next().value!);
155
183
  }
184
+
156
185
  return run;
157
186
  }
@@ -20,10 +20,13 @@ export function contextFraction(usage: ChatUsage): number {
20
20
  /* The stretches of the bar, in the legend's order; null from a host that does not estimate, which draws the plain bar. */
21
21
  export function contextSegments(usage: ChatUsage): ContextSegment[] | null {
22
22
  const breakdown = usage.breakdown;
23
+
23
24
  if (!breakdown || usage.contextTokens === 0) {
24
25
  return null;
25
26
  }
27
+
26
28
  const whole = Math.max(usage.contextWindow ?? 0, usage.contextTokens);
29
+
27
30
  return CONTEXT_PARTS.map((part) => ({ part, tokens: breakdown[part], fraction: breakdown[part] / whole }));
28
31
  }
29
32
 
@@ -18,15 +18,20 @@ export function continuableTurn(info: ChatInfo, items: readonly ChatItem[]): str
18
18
  ) {
19
19
  return null;
20
20
  }
21
+
21
22
  const index = items.findLastIndex((item) => item.kind === 'turn');
22
23
  const turn = items[index];
24
+
23
25
  if (turn?.kind !== 'turn' || turn.state !== 'aborted' || turn.limit !== undefined || abortedByMachine(turn, items) || abortedByEnd(turn, items)) {
24
26
  return null;
25
27
  }
28
+
26
29
  // A message of this turn sits after the turn item too, so only one sent after the turn ended counts.
27
30
  const endedAt = turn.endedAt ?? turn.createdAt;
31
+
28
32
  if (items.slice(index + 1).some((item) => item.kind === 'user' && item.createdAt > endedAt)) {
29
33
  return null;
30
34
  }
35
+
31
36
  return turn.id;
32
37
  }
@@ -16,17 +16,21 @@ export type EffortStepResult =
16
16
  /* One step of effort within what the model offers. A value the model no longer offers counts as its default. */
17
17
  export function stepEffort(model: ModelInfo | undefined, selection: ModelSelection, step: EffortStep): EffortStepResult {
18
18
  const option = model?.options.find((candidate) => candidate.id === EFFORT_OPTION);
19
+
19
20
  if (option === undefined || option.type !== 'select') {
20
21
  return { kind: 'none' };
21
22
  }
23
+
22
24
  const chosen = selection.options[EFFORT_OPTION];
23
25
  const index = option.choices.findIndex((choice) => choice.id === chosen);
24
26
  const from = index === -1 ? option.choices.findIndex((choice) => choice.id === option.defaultChoice) : index;
25
27
  const current = Math.max(0, from);
26
28
  const next = current + (step === 'up' ? 1 : -1);
27
29
  const choice = option.choices[next];
30
+
28
31
  if (choice === undefined) {
29
32
  return { kind: 'edge', choice: option.choices[current]! };
30
33
  }
34
+
31
35
  return { kind: 'stepped', selection: { ...selection, options: { ...selection.options, [EFFORT_OPTION]: choice.id } }, choice };
32
36
  }