@adecore/agents-react 0.31.12 → 0.33.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 (409) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/AccountDot.js +57 -6
  3. package/dist/agents/AgentIcon.js +88 -12
  4. package/dist/agents/ModelOptionControl.js +153 -18
  5. package/dist/agents/ProviderLogo.js +49 -4
  6. package/dist/agents/account-limits.js +17 -14
  7. package/dist/agents/accounts.js +99 -67
  8. package/dist/agents/agent-marks.js +5 -3
  9. package/dist/agents/model-name.js +42 -31
  10. package/dist/agents/model-options.js +8 -8
  11. package/dist/agents/model-requirement.js +17 -14
  12. package/dist/agents/option-words.d.ts +7 -0
  13. package/dist/agents/option-words.js +35 -0
  14. package/dist/agents/provider-paths.js +6 -6
  15. package/dist/agents/status-look.js +32 -12
  16. package/dist/chat/account-choice.d.ts +13 -0
  17. package/dist/chat/account-choice.js +90 -20
  18. package/dist/chat/actions.js +126 -59
  19. package/dist/chat/activity.js +5 -5
  20. package/dist/chat/attachments.js +74 -53
  21. package/dist/chat/bookmarks.js +58 -48
  22. package/dist/chat/chat-client.js +344 -263
  23. package/dist/chat/chat-references.js +3 -3
  24. package/dist/chat/composer-effort.d.ts +5 -0
  25. package/dist/chat/composer-effort.js +26 -0
  26. package/dist/chat/composer-send.js +13 -13
  27. package/dist/chat/drafts.js +115 -79
  28. package/dist/chat/forks.js +81 -24
  29. package/dist/chat/guards.js +15 -43
  30. package/dist/chat/index.d.ts +3 -1
  31. package/dist/chat/index.js +3 -2
  32. package/dist/chat/logic/ansi.js +170 -167
  33. package/dist/chat/logic/answers.js +2 -2
  34. package/dist/chat/logic/bookmarks.js +19 -19
  35. package/dist/chat/logic/command-looks.js +138 -96
  36. package/dist/chat/logic/context-usage.js +13 -9
  37. package/dist/chat/logic/continue-after-stop.js +15 -19
  38. package/dist/chat/logic/effort.d.ts +14 -0
  39. package/dist/chat/logic/effort.js +34 -0
  40. package/dist/chat/logic/embedded-code.js +387 -326
  41. package/dist/chat/logic/fork.js +134 -110
  42. package/dist/chat/logic/generated-image.js +54 -23
  43. package/dist/chat/logic/goal.js +28 -20
  44. package/dist/chat/logic/handback.js +6 -6
  45. package/dist/chat/logic/json.js +2 -2
  46. package/dist/chat/logic/limit.js +46 -30
  47. package/dist/chat/logic/picker-entries.d.ts +5 -3
  48. package/dist/chat/logic/picker-entries.js +83 -43
  49. package/dist/chat/logic/resume-compaction.d.ts +14 -1
  50. package/dist/chat/logic/resume-compaction.js +93 -24
  51. package/dist/chat/logic/scrubber.js +188 -136
  52. package/dist/chat/logic/thought.js +13 -16
  53. package/dist/chat/logic/thread-cards.js +60 -48
  54. package/dist/chat/logic/timeline-copy.js +30 -38
  55. package/dist/chat/logic/timeline-target.js +92 -63
  56. package/dist/chat/logic/timeline.js +499 -355
  57. package/dist/chat/logic/tool-catalog.js +54 -34
  58. package/dist/chat/logic/tools.js +106 -82
  59. package/dist/chat/logic/visual-height.js +18 -18
  60. package/dist/chat/logic/visual-viewport.js +6 -3
  61. package/dist/chat/logic/welcome.js +9 -9
  62. package/dist/chat/logic/workflow.d.ts +10 -0
  63. package/dist/chat/logic/workflow.js +130 -32
  64. package/dist/chat/mentions.js +149 -109
  65. package/dist/chat/persisted-json.js +51 -54
  66. package/dist/chat/preferences.d.ts +4 -0
  67. package/dist/chat/preferences.js +162 -84
  68. package/dist/chat/prompt-hold.js +9 -9
  69. package/dist/chat/quote.js +21 -30
  70. package/dist/chat/reading-width.js +12 -10
  71. package/dist/chat/recent-messages.js +34 -21
  72. package/dist/chat/resume-compaction-dismissals.js +25 -5
  73. package/dist/chat/runtime-modes.js +3 -3
  74. package/dist/chat/send-key.js +11 -7
  75. package/dist/chat/stash.js +89 -69
  76. package/dist/chat/subagent-conversation.js +181 -139
  77. package/dist/chat/subagent-list.js +65 -67
  78. package/dist/chat/subagent-support.js +12 -7
  79. package/dist/chat/subagent-view.js +132 -44
  80. package/dist/chat/thumbnails.js +88 -60
  81. package/dist/chat/timeline-flash.js +24 -12
  82. package/dist/chat/timeline-scroll.js +116 -86
  83. package/dist/chat/ui/AccountPill.js +126 -15
  84. package/dist/chat/ui/AnsiOutput.js +62 -6
  85. package/dist/chat/ui/BookmarkMarker.js +231 -41
  86. package/dist/chat/ui/BookmarkSubmenu.js +165 -18
  87. package/dist/chat/ui/ChatActivity.js +649 -70
  88. package/dist/chat/ui/ChatReferenceChip.js +104 -9
  89. package/dist/chat/ui/CodeBlock.js +132 -58
  90. package/dist/chat/ui/Composer.js +866 -132
  91. package/dist/chat/ui/ComposerInput.js +309 -120
  92. package/dist/chat/ui/DiffPool.js +75 -14
  93. package/dist/chat/ui/EditDiff.js +160 -21
  94. package/dist/chat/ui/FadingWords.js +32 -3
  95. package/dist/chat/ui/GoalDock.js +235 -42
  96. package/dist/chat/ui/ImageView.js +617 -61
  97. package/dist/chat/ui/LimitState.js +446 -72
  98. package/dist/chat/ui/Markdown.js +991 -173
  99. package/dist/chat/ui/MermaidBlock.js +285 -79
  100. package/dist/chat/ui/MessageActions.js +251 -39
  101. package/dist/chat/ui/ModelMarks.js +55 -5
  102. package/dist/chat/ui/Pickers.js +664 -113
  103. package/dist/chat/ui/PromptComposer.js +281 -51
  104. package/dist/chat/ui/QuoteButton.js +151 -57
  105. package/dist/chat/ui/ResumeCompactionDock.d.ts +6 -2
  106. package/dist/chat/ui/ResumeCompactionDock.js +141 -6
  107. package/dist/chat/ui/RowTime.js +59 -5
  108. package/dist/chat/ui/RunSettings.js +1744 -154
  109. package/dist/chat/ui/Scrubber.js +517 -88
  110. package/dist/chat/ui/ShellCommand.js +183 -107
  111. package/dist/chat/ui/SubagentControls.js +212 -24
  112. package/dist/chat/ui/SubagentInfo.js +170 -13
  113. package/dist/chat/ui/SubagentStopButton.js +115 -24
  114. package/dist/chat/ui/SubagentTimeline.js +357 -91
  115. package/dist/chat/ui/Timeline.js +988 -476
  116. package/dist/chat/ui/TimelineMenu.js +552 -37
  117. package/dist/chat/ui/UnifiedDiff.js +234 -27
  118. package/dist/chat/ui/UploadThumb.js +37 -7
  119. package/dist/chat/ui/VisualDialogs.js +251 -20
  120. package/dist/chat/ui/VisualFrame.js +321 -95
  121. package/dist/chat/ui/Welcome.js +72 -7
  122. package/dist/chat/ui/chips.js +1 -1
  123. package/dist/chat/ui/code-lines.js +36 -36
  124. package/dist/chat/ui/code-streaming.js +1 -1
  125. package/dist/chat/ui/code-theme.js +7 -7
  126. package/dist/chat/ui/composer/ComposerControls.js +329 -21
  127. package/dist/chat/ui/composer/ComposerMenu.js +358 -30
  128. package/dist/chat/ui/composer/DraftParts.js +185 -11
  129. package/dist/chat/ui/composer/QueuedMessages.js +138 -13
  130. package/dist/chat/ui/composer/chips.js +29 -19
  131. package/dist/chat/ui/composer/editor.js +79 -63
  132. package/dist/chat/ui/composer/insert.js +26 -12
  133. package/dist/chat/ui/composer/key-handler.js +180 -127
  134. package/dist/chat/ui/composer/keys.js +90 -73
  135. package/dist/chat/ui/composer/menu-aria.js +18 -9
  136. package/dist/chat/ui/composer/placeholder.js +78 -31
  137. package/dist/chat/ui/composer/surface.js +13 -37
  138. package/dist/chat/ui/composer/use-chat-controls.js +230 -90
  139. package/dist/chat/ui/composer/use-compaction-offer.js +50 -18
  140. package/dist/chat/ui/composer/use-composer-draft.js +65 -34
  141. package/dist/chat/ui/composer/use-composer-menus.js +478 -193
  142. package/dist/chat/ui/composer/use-composer-submit.js +251 -109
  143. package/dist/chat/ui/composer/use-continuable-turn.js +33 -6
  144. package/dist/chat/ui/composer/use-draft-files.js +245 -93
  145. package/dist/chat/ui/composer/use-effort-stepper.d.ts +13 -0
  146. package/dist/chat/ui/composer/use-effort-stepper.js +88 -0
  147. package/dist/chat/ui/composer/use-notice.js +61 -16
  148. package/dist/chat/ui/composer/use-pending-requests.js +38 -17
  149. package/dist/chat/ui/composer/use-prompt-history.js +117 -45
  150. package/dist/chat/ui/composer/use-prompt-hold.js +119 -35
  151. package/dist/chat/ui/composer/use-take-back.js +94 -72
  152. package/dist/chat/ui/diff/ApprovalReview.js +101 -23
  153. package/dist/chat/ui/diff/DiffFallbackBoundary.js +21 -13
  154. package/dist/chat/ui/diff/DiffOmitted.js +56 -6
  155. package/dist/chat/ui/diff/DiffStack.js +92 -8
  156. package/dist/chat/ui/diff/DiffUnavailable.js +56 -6
  157. package/dist/chat/ui/diff/EditorEditDiff.js +263 -51
  158. package/dist/chat/ui/diff/EditorPatchDiff.js +39 -14
  159. package/dist/chat/ui/diff/LegacyDiffPool.js +27 -10
  160. package/dist/chat/ui/diff/LegacyEditDiff.js +97 -20
  161. package/dist/chat/ui/diff/LegacyUnifiedDiff.js +172 -42
  162. package/dist/chat/ui/diff/RawDiff.js +65 -5
  163. package/dist/chat/ui/diff/ReviewDiff.js +77 -5
  164. package/dist/chat/ui/diff/diff-props.js +1 -1
  165. package/dist/chat/ui/diff/diff-source-budget.js +46 -35
  166. package/dist/chat/ui/diff/editor-edit-model.js +18 -14
  167. package/dist/chat/ui/diff/review-plan.js +63 -40
  168. package/dist/chat/ui/diff/review-settle.js +24 -9
  169. package/dist/chat/ui/diff/syntax-runtime.js +236 -201
  170. package/dist/chat/ui/diff/use-review-stack.js +146 -25
  171. package/dist/chat/ui/diff-syntax.js +70 -58
  172. package/dist/chat/ui/diff-theme.js +31 -12
  173. package/dist/chat/ui/file-links.js +39 -10
  174. package/dist/chat/ui/find-reveal.js +29 -8
  175. package/dist/chat/ui/full-diff.js +17 -12
  176. package/dist/chat/ui/highlighter.js +143 -113
  177. package/dist/chat/ui/icons.js +16 -7
  178. package/dist/chat/ui/index.js +1 -1
  179. package/dist/chat/ui/intelligent-ui/UiBlockFrame.js +556 -82
  180. package/dist/chat/ui/intelligent-ui/UiFallbackPart.js +73 -5
  181. package/dist/chat/ui/intelligent-ui/UiReply.js +666 -262
  182. package/dist/chat/ui/intelligent-ui/block-local.js +59 -31
  183. package/dist/chat/ui/intelligent-ui/chart-data.js +77 -67
  184. package/dist/chat/ui/intelligent-ui/node-text.js +77 -91
  185. package/dist/chat/ui/intelligent-ui/registry.js +46 -46
  186. package/dist/chat/ui/intelligent-ui/render-context.js +1 -1
  187. package/dist/chat/ui/intelligent-ui/renderers/base-land.js +1 -1
  188. package/dist/chat/ui/intelligent-ui/renderers/binding.js +3 -3
  189. package/dist/chat/ui/intelligent-ui/renderers/chart.js +1223 -123
  190. package/dist/chat/ui/intelligent-ui/renderers/choices.js +312 -34
  191. package/dist/chat/ui/intelligent-ui/renderers/content.js +1241 -86
  192. package/dist/chat/ui/intelligent-ui/renderers/data.js +619 -54
  193. package/dist/chat/ui/intelligent-ui/renderers/inputs.js +868 -67
  194. package/dist/chat/ui/intelligent-ui/renderers/links.js +366 -62
  195. package/dist/chat/ui/intelligent-ui/renderers/map-slots.js +118 -60
  196. package/dist/chat/ui/intelligent-ui/renderers/map-style.js +85 -78
  197. package/dist/chat/ui/intelligent-ui/renderers/map-view.js +282 -217
  198. package/dist/chat/ui/intelligent-ui/renderers/map.js +621 -69
  199. package/dist/chat/ui/intelligent-ui/renderers/place-point.js +15 -8
  200. package/dist/chat/ui/intelligent-ui/renderers/structure.js +262 -20
  201. package/dist/chat/ui/intelligent-ui/renderers/text.js +674 -49
  202. package/dist/chat/ui/intelligent-ui/reply-parts.js +24 -15
  203. package/dist/chat/ui/intelligent-ui/table-data.js +97 -57
  204. package/dist/chat/ui/intelligent-ui/tones.js +31 -31
  205. package/dist/chat/ui/intelligent-ui/use-in-view.js +30 -12
  206. package/dist/chat/ui/intelligent-ui/use-later.js +28 -13
  207. package/dist/chat/ui/intelligent-ui/use-truncated.js +45 -21
  208. package/dist/chat/ui/intelligent-ui/use-ui-links.js +296 -109
  209. package/dist/chat/ui/intelligent-ui/use-ui-queries.js +256 -246
  210. package/dist/chat/ui/markdown-blocks.js +296 -262
  211. package/dist/chat/ui/mermaid.d.ts +8 -20
  212. package/dist/chat/ui/mermaid.js +47 -84
  213. package/dist/chat/ui/quote-selection.js +32 -29
  214. package/dist/chat/ui/rehype-chips.js +35 -23
  215. package/dist/chat/ui/rehype-fade.js +28 -17
  216. package/dist/chat/ui/remark-html-as-text.js +22 -15
  217. package/dist/chat/ui/reply-context.js +1 -1
  218. package/dist/chat/ui/reveal.js +161 -72
  219. package/dist/chat/ui/rows/ForksRow.js +226 -24
  220. package/dist/chat/ui/rows/GeneratedImageRow.js +541 -87
  221. package/dist/chat/ui/rows/MessageRows.js +1706 -159
  222. package/dist/chat/ui/rows/RowContainer.js +57 -7
  223. package/dist/chat/ui/rows/Rows.js +463 -54
  224. package/dist/chat/ui/rows/SubagentRow.js +577 -60
  225. package/dist/chat/ui/rows/TaskRow.js +359 -40
  226. package/dist/chat/ui/rows/VisualRow.js +233 -11
  227. package/dist/chat/ui/rows/WorkRows.d.ts +3 -0
  228. package/dist/chat/ui/rows/WorkRows.js +1945 -164
  229. package/dist/chat/ui/rows/WorkflowRow.js +756 -37
  230. package/dist/chat/ui/rows/row-rhythm.js +27 -17
  231. package/dist/chat/ui/theme-watch.js +26 -23
  232. package/dist/chat/ui/timestamp-format.js +4 -1
  233. package/dist/chat/ui/use-diff-source-tokens.js +70 -34
  234. package/dist/chat/ui/useToggleSet.js +51 -19
  235. package/dist/chat/ui/visual-theme.js +153 -128
  236. package/dist/chat/visual-bridge.js +123 -123
  237. package/dist/chat/visual-viewport.js +94 -83
  238. package/dist/chat/visuals.js +13 -5
  239. package/dist/host-hooks.d.ts +29 -0
  240. package/dist/host-hooks.js +78 -0
  241. package/dist/host.js +120 -48
  242. package/dist/index.js +1 -1
  243. package/dist/lazy.js +38 -32
  244. package/dist/locales/en/agent-chat.d.ts +42 -0
  245. package/dist/locales/en/agent-chat.js +755 -713
  246. package/dist/locales/en/agent-prompts.js +42 -42
  247. package/dist/locales/en/agent-providers.d.ts +1 -0
  248. package/dist/locales/en/agent-providers.js +166 -165
  249. package/dist/locales/en/agent-usage.d.ts +6 -0
  250. package/dist/locales/en/agent-usage.js +129 -123
  251. package/dist/locales/nl/agent-chat.d.ts +42 -0
  252. package/dist/locales/nl/agent-chat.js +755 -713
  253. package/dist/locales/nl/agent-prompts.js +42 -42
  254. package/dist/locales/nl/agent-providers.d.ts +1 -0
  255. package/dist/locales/nl/agent-providers.js +166 -165
  256. package/dist/locales/nl/agent-usage.d.ts +6 -0
  257. package/dist/locales/nl/agent-usage.js +129 -123
  258. package/dist/locales.js +14 -14
  259. package/dist/mounted-registry.js +31 -30
  260. package/dist/port-transport.js +122 -111
  261. package/dist/prompts/index.js +1 -1
  262. package/dist/prompts/logic/focus.js +15 -14
  263. package/dist/prompts/logic/keys.js +93 -59
  264. package/dist/prompts/logic/prompts.js +27 -14
  265. package/dist/prompts/logic/subjects.js +60 -46
  266. package/dist/prompts/logic/useFocusAfterAnswer.js +60 -20
  267. package/dist/prompts/logic/usePromptSession.js +88 -77
  268. package/dist/prompts/ui/ApprovalBody.js +246 -27
  269. package/dist/prompts/ui/PromptActions.js +215 -9
  270. package/dist/prompts/ui/PromptCard.js +215 -36
  271. package/dist/prompts/ui/PromptView.js +372 -34
  272. package/dist/prompts/ui/QuestionBody.js +269 -73
  273. package/dist/providers/AccountColors.js +36 -5
  274. package/dist/providers/AccountDetail.js +683 -50
  275. package/dist/providers/AccountVariables.js +139 -32
  276. package/dist/providers/AddAccountForm.js +125 -38
  277. package/dist/providers/CliDetail.js +343 -36
  278. package/dist/providers/InstallPage.js +644 -59
  279. package/dist/providers/ProviderList.d.ts +2 -1
  280. package/dist/providers/ProviderList.js +215 -23
  281. package/dist/providers/ProvidersPane.d.ts +4 -2
  282. package/dist/providers/ProvidersPane.js +244 -64
  283. package/dist/providers/account-actions.js +54 -30
  284. package/dist/providers/index.js +1 -1
  285. package/dist/providers/install-steps.js +12 -9
  286. package/dist/providers/pane-target.d.ts +3 -0
  287. package/dist/providers/pane-target.js +34 -13
  288. package/dist/providers/parts.js +62 -12
  289. package/dist/providers/provider-abilities.js +5 -5
  290. package/dist/providers/provider-groups.js +75 -40
  291. package/dist/providers/variables.js +73 -39
  292. package/dist/scope.js +6 -6
  293. package/dist/settings/sections.js +18 -18
  294. package/dist/state/chats.js +404 -192
  295. package/dist/state/index.js +1 -1
  296. package/dist/state/provider-accounts.js +70 -47
  297. package/dist/state/providers.js +45 -16
  298. package/dist/state/usage.js +154 -77
  299. package/dist/storage.js +69 -68
  300. package/dist/testing/index.js +1 -1
  301. package/dist/testing/prompts.js +105 -67
  302. package/dist/transport.js +10 -10
  303. package/dist/ui/PlainTextarea.js +27 -3
  304. package/dist/usage/LimitsList.js +646 -40
  305. package/dist/usage/UsageBreakdown.js +879 -38
  306. package/dist/usage/UsageChart.js +311 -32
  307. package/dist/usage/UsageDialog.js +46 -4
  308. package/dist/usage/UsageLimits.js +467 -34
  309. package/dist/usage/UsageLimitsCard.js +95 -11
  310. package/dist/usage/UsagePage.js +817 -96
  311. package/dist/usage/UsagePane.js +164 -10
  312. package/dist/usage/UsageSummary.js +151 -6
  313. package/dist/usage/UsageTiles.js +164 -14
  314. package/dist/usage/format.js +32 -32
  315. package/dist/usage/index.d.ts +1 -1
  316. package/dist/usage/index.js +2 -1
  317. package/dist/usage/limit-groups.d.ts +2 -0
  318. package/dist/usage/limit-groups.js +77 -59
  319. package/dist/usage/limits.js +78 -43
  320. package/dist/usage/money.js +20 -4
  321. package/dist/usage/summary.js +85 -64
  322. package/package.json +9 -9
  323. package/src/agents/ModelOptionControl.tsx +3 -1
  324. package/src/agents/option-words.ts +27 -0
  325. package/src/chat/account-choice.ts +41 -1
  326. package/src/chat/composer-effort.ts +32 -0
  327. package/src/chat/forks.ts +4 -5
  328. package/src/chat/index.ts +3 -1
  329. package/src/chat/logic/effort.ts +32 -0
  330. package/src/chat/logic/picker-entries.ts +45 -10
  331. package/src/chat/logic/resume-compaction.ts +95 -17
  332. package/src/chat/logic/timeline.ts +11 -3
  333. package/src/chat/logic/workflow.ts +86 -4
  334. package/src/chat/preferences.ts +35 -0
  335. package/src/chat/subagent-view.ts +2 -3
  336. package/src/chat/ui/AnsiOutput.tsx +1 -2
  337. package/src/chat/ui/BookmarkSubmenu.tsx +3 -3
  338. package/src/chat/ui/ChatActivity.tsx +14 -22
  339. package/src/chat/ui/ChatReferenceChip.tsx +2 -3
  340. package/src/chat/ui/Composer.tsx +15 -7
  341. package/src/chat/ui/EditDiff.tsx +2 -3
  342. package/src/chat/ui/LimitState.tsx +2 -2
  343. package/src/chat/ui/Markdown.tsx +10 -8
  344. package/src/chat/ui/MermaidBlock.tsx +57 -49
  345. package/src/chat/ui/Pickers.tsx +49 -29
  346. package/src/chat/ui/PromptComposer.tsx +7 -9
  347. package/src/chat/ui/ResumeCompactionDock.tsx +16 -4
  348. package/src/chat/ui/RunSettings.tsx +67 -28
  349. package/src/chat/ui/Scrubber.tsx +3 -3
  350. package/src/chat/ui/ShellCommand.tsx +2 -0
  351. package/src/chat/ui/SubagentInfo.tsx +2 -3
  352. package/src/chat/ui/SubagentTimeline.tsx +12 -16
  353. package/src/chat/ui/Timeline.tsx +6 -6
  354. package/src/chat/ui/UnifiedDiff.tsx +3 -4
  355. package/src/chat/ui/VisualFrame.tsx +5 -8
  356. package/src/chat/ui/code-theme.ts +4 -4
  357. package/src/chat/ui/composer/placeholder.ts +2 -2
  358. package/src/chat/ui/composer/use-compaction-offer.ts +36 -16
  359. package/src/chat/ui/composer/use-composer-menus.ts +4 -9
  360. package/src/chat/ui/composer/use-composer-submit.ts +2 -1
  361. package/src/chat/ui/composer/use-effort-stepper.ts +56 -0
  362. package/src/chat/ui/composer/use-notice.ts +2 -2
  363. package/src/chat/ui/diff/EditorEditDiff.tsx +9 -13
  364. package/src/chat/ui/diff/LegacyEditDiff.tsx +12 -17
  365. package/src/chat/ui/diff/LegacyUnifiedDiff.tsx +13 -21
  366. package/src/chat/ui/diff/use-review-stack.ts +4 -4
  367. package/src/chat/ui/diff-theme.ts +3 -3
  368. package/src/chat/ui/file-links.ts +2 -2
  369. package/src/chat/ui/intelligent-ui/UiReply.tsx +2 -0
  370. package/src/chat/ui/intelligent-ui/renderers/chart.tsx +3 -3
  371. package/src/chat/ui/intelligent-ui/renderers/content.tsx +5 -6
  372. package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +2 -1
  373. package/src/chat/ui/intelligent-ui/renderers/map.tsx +2 -1
  374. package/src/chat/ui/intelligent-ui/use-truncated.ts +16 -19
  375. package/src/chat/ui/intelligent-ui/use-ui-links.ts +3 -3
  376. package/src/chat/ui/mermaid.ts +52 -96
  377. package/src/chat/ui/rows/ForksRow.tsx +3 -5
  378. package/src/chat/ui/rows/GeneratedImageRow.tsx +2 -1
  379. package/src/chat/ui/rows/MessageRows.tsx +12 -21
  380. package/src/chat/ui/rows/SubagentRow.tsx +3 -3
  381. package/src/chat/ui/rows/TaskRow.tsx +1 -1
  382. package/src/chat/ui/rows/WorkRows.tsx +11 -6
  383. package/src/chat/ui/rows/WorkflowRow.tsx +144 -54
  384. package/src/chat/ui/useToggleSet.ts +15 -18
  385. package/src/chat/ui/visual-theme.ts +2 -3
  386. package/src/host-hooks.ts +113 -0
  387. package/src/lazy.tsx +2 -0
  388. package/src/locales/en/agent-chat.ts +142 -108
  389. package/src/locales/en/agent-prompts.ts +7 -7
  390. package/src/locales/en/agent-providers.ts +35 -34
  391. package/src/locales/en/agent-usage.ts +26 -20
  392. package/src/locales/nl/agent-chat.ts +134 -100
  393. package/src/locales/nl/agent-prompts.ts +5 -5
  394. package/src/locales/nl/agent-providers.ts +33 -32
  395. package/src/locales/nl/agent-usage.ts +25 -20
  396. package/src/providers/CliDetail.tsx +2 -1
  397. package/src/providers/InstallPage.tsx +2 -4
  398. package/src/providers/ProviderList.tsx +12 -2
  399. package/src/providers/ProvidersPane.tsx +45 -15
  400. package/src/providers/pane-target.ts +20 -4
  401. package/src/state/chats.ts +2 -2
  402. package/src/usage/LimitsList.tsx +12 -13
  403. package/src/usage/UsageBreakdown.tsx +17 -6
  404. package/src/usage/UsageLimits.tsx +2 -1
  405. package/src/usage/UsagePage.tsx +3 -3
  406. package/src/usage/index.ts +1 -1
  407. package/src/usage/limit-groups.ts +12 -0
  408. package/src/usage/limits.ts +2 -2
  409. package/src/usage/money.ts +1 -2
@@ -3,41 +3,55 @@ export const SHELL_LANGUAGE = 'shellscript';
3
3
  export const EMBEDDED_CODE_LIMIT = 20_000;
4
4
  const MAX_DEPTH = 3;
5
5
  const SHELL = {
6
- language: SHELL_LANGUAGE,
7
- script: (flag) => /^-[a-zA-Z]*c[a-zA-Z]*$/.test(flag),
8
- takesValue: new Set(['-o', '-O', '--rcfile', '--init-file'])
6
+ language: SHELL_LANGUAGE,
7
+ script: flag => /^-[a-zA-Z]*c[a-zA-Z]*$/.test(flag),
8
+ takesValue: new Set(['-o', '-O', '--rcfile', '--init-file'])
9
+ };
10
+ const PYTHON = {
11
+ language: 'python',
12
+ script: flag => flag === '-c',
13
+ takesValue: new Set(['-W', '-X'])
9
14
  };
10
- const PYTHON = { language: 'python', script: (flag) => flag === '-c', takesValue: new Set(['-W', '-X']) };
11
15
  const NODE = {
12
- language: 'javascript',
13
- script: (flag) => ['-e', '--eval', '-p', '--print'].includes(flag),
14
- takesValue: new Set(['-r', '--require', '--import', '--input-type', '--conditions', '-C'])
16
+ language: 'javascript',
17
+ script: flag => ['-e', '--eval', '-p', '--print'].includes(flag),
18
+ takesValue: new Set(['-r', '--require', '--import', '--input-type', '--conditions', '-C'])
19
+ };
20
+ const BUN = {
21
+ language: 'typescript',
22
+ script: flag => ['-e', '--eval', '-p', '--print'].includes(flag),
23
+ takesValue: NODE.takesValue
15
24
  };
16
- const BUN = { language: 'typescript', script: (flag) => ['-e', '--eval', '-p', '--print'].includes(flag), takesValue: NODE.takesValue };
17
25
  const MYSQL = {
18
- language: 'sql',
19
- client: true,
20
- script: (flag) => flag === '-e' || flag === '--execute',
21
- takesValue: new Set(['-u', '-h', '-P', '-D', '-S', '--user', '--host', '--port', '--database'])
26
+ language: 'sql',
27
+ client: true,
28
+ script: flag => flag === '-e' || flag === '--execute',
29
+ takesValue: new Set(['-u', '-h', '-P', '-D', '-S', '--user', '--host', '--port', '--database'])
22
30
  };
23
31
  const INTERPRETERS = {
24
- bash: SHELL,
25
- sh: SHELL,
26
- zsh: SHELL,
27
- dash: SHELL,
28
- ksh: SHELL,
29
- python: PYTHON,
30
- node: NODE,
31
- bun: BUN,
32
- psql: {
33
- language: 'sql',
34
- client: true,
35
- script: (flag) => flag === '-c' || flag === '--command',
36
- takesValue: new Set(['-d', '-h', '-p', '-U', '-f', '-v', '-o', '--dbname', '--host', '--port', '--username', '--file', '--set'])
37
- },
38
- mysql: MYSQL,
39
- mariadb: MYSQL,
40
- sqlite3: { language: 'sql', client: true, script: () => false, takesValue: new Set(['-cmd', '-separator', '-newline', '-nullvalue']), positional: 1 }
32
+ bash: SHELL,
33
+ sh: SHELL,
34
+ zsh: SHELL,
35
+ dash: SHELL,
36
+ ksh: SHELL,
37
+ python: PYTHON,
38
+ node: NODE,
39
+ bun: BUN,
40
+ psql: {
41
+ language: 'sql',
42
+ client: true,
43
+ script: flag => flag === '-c' || flag === '--command',
44
+ takesValue: new Set(['-d', '-h', '-p', '-U', '-f', '-v', '-o', '--dbname', '--host', '--port', '--username', '--file', '--set'])
45
+ },
46
+ mysql: MYSQL,
47
+ mariadb: MYSQL,
48
+ sqlite3: {
49
+ language: 'sql',
50
+ client: true,
51
+ script: () => false,
52
+ takesValue: new Set(['-cmd', '-separator', '-newline', '-nullvalue']),
53
+ positional: 1
54
+ }
41
55
  };
42
56
  // Programs that run the next word as the command; their own options are skipped along with them.
43
57
  const WRAPPERS = new Set(['sudo', 'env', 'exec', 'nohup', 'time', 'command', 'nice']);
@@ -45,336 +59,383 @@ const WRAPPERS = new Set(['sudo', 'env', 'exec', 'nohup', 'time', 'command', 'ni
45
59
  const RUNNERS = new Set(['uv', 'poetry', 'pipenv']);
46
60
  // Where a heredoc written to a file goes, by the file's extension.
47
61
  const EXTENSIONS = {
48
- py: 'python',
49
- js: 'javascript',
50
- mjs: 'javascript',
51
- cjs: 'javascript',
52
- jsx: 'jsx',
53
- ts: 'typescript',
54
- mts: 'typescript',
55
- tsx: 'tsx',
56
- json: 'json',
57
- sql: 'sql',
58
- sh: SHELL_LANGUAGE,
59
- bash: SHELL_LANGUAGE,
60
- zsh: SHELL_LANGUAGE,
61
- yml: 'yaml',
62
- yaml: 'yaml',
63
- md: 'markdown',
64
- css: 'css',
65
- html: 'html',
66
- php: 'php',
67
- xml: 'xml'
62
+ py: 'python',
63
+ js: 'javascript',
64
+ mjs: 'javascript',
65
+ cjs: 'javascript',
66
+ jsx: 'jsx',
67
+ ts: 'typescript',
68
+ mts: 'typescript',
69
+ tsx: 'tsx',
70
+ json: 'json',
71
+ sql: 'sql',
72
+ sh: SHELL_LANGUAGE,
73
+ bash: SHELL_LANGUAGE,
74
+ zsh: SHELL_LANGUAGE,
75
+ yml: 'yaml',
76
+ yaml: 'yaml',
77
+ md: 'markdown',
78
+ css: 'css',
79
+ html: 'html',
80
+ php: 'php',
81
+ xml: 'xml'
68
82
  };
69
83
  const SEPARATORS = ';&|()';
70
84
  const BLANKS = ' \t\r';
71
85
  /* The program a command name runs, as the table above knows it: `/usr/bin/python3.12` is `python`. */
72
86
  function programOf(word) {
73
- const name = word.slice(word.lastIndexOf('/') + 1);
74
- return /^python\d*(\.\d+)?$/.test(name) ? 'python' : name;
87
+ const name = word.slice(word.lastIndexOf('/') + 1);
88
+ return /^python\d*(\.\d+)?$/.test(name) ? 'python' : name;
75
89
  }
76
90
  /* Splits `source[from, to)` into simple commands the way a shell would, enough to find the code in them. */
77
91
  function parseCommands(source, from, to) {
78
- const commands = [];
79
- let current = { words: [], redirects: [], heredocs: [] };
80
- const pending = [];
81
- // The start of the `2` of a `2>&1` just read, which the redirect after it begins at.
82
- let descriptorStart = null;
83
- const finish = () => {
84
- if (current.words.length > 0 || current.redirects.length > 0) {
85
- commands.push(current);
86
- }
87
- current = { words: [], redirects: [], heredocs: [] };
88
- descriptorStart = null;
89
- };
90
- const skipBlanks = (index) => {
91
- while (index < to && BLANKS.includes(source[index])) {
92
- index++;
93
- }
94
- return index;
95
- };
96
- const readWord = (start) => {
97
- let index = start;
98
- let text = '';
99
- let quoted = null;
100
- let parts = 0;
101
- let bare = true;
102
- while (index < to) {
103
- const char = source[index];
104
- if (BLANKS.includes(char) || char === '\n' || SEPARATORS.includes(char) || char === '<' || char === '>') {
105
- break;
106
- }
107
- parts++;
108
- if (char === "'") {
109
- const close = source.indexOf("'", index + 1);
110
- const end = close === -1 || close >= to ? to : close;
111
- text += source.slice(index + 1, end);
112
- quoted = { start: index + 1, end };
113
- bare = false;
114
- index = Math.min(end + 1, to);
115
- }
116
- else if (char === '"') {
117
- let end = index + 1;
118
- while (end < to && source[end] !== '"') {
119
- if (source[end] === '\\' && end + 1 < to && '$`"\\\n'.includes(source[end + 1])) {
120
- text += source[end + 1];
121
- end += 2;
122
- }
123
- else {
124
- text += source[end];
125
- end++;
126
- }
127
- }
128
- quoted = { start: index + 1, end };
129
- bare = false;
130
- index = Math.min(end + 1, to);
131
- }
132
- else if (char === '\\') {
133
- text += source[index + 1] ?? '';
134
- bare = false;
135
- index += 2;
136
- }
137
- else if (char === '$' && source[index + 1] === '(') {
138
- const end = closingParen(source, index + 1, to);
139
- text += source.slice(index, end);
140
- index = end;
141
- }
142
- else {
143
- text += char;
144
- index++;
145
- }
146
- }
147
- const end = Math.min(index, to);
148
- const body = bare ? { start, end } : parts === 1 && quoted !== null ? quoted : null;
149
- return { start, end, text, body };
92
+ const commands = [];
93
+ let current = {
94
+ words: [],
95
+ redirects: [],
96
+ heredocs: []
97
+ };
98
+ const pending = [];
99
+ // The start of the `2` of a `2>&1` just read, which the redirect after it begins at.
100
+ let descriptorStart = null;
101
+ const finish = () => {
102
+ if (current.words.length > 0 || current.redirects.length > 0) {
103
+ commands.push(current);
104
+ }
105
+ current = {
106
+ words: [],
107
+ redirects: [],
108
+ heredocs: []
150
109
  };
151
- const readHeredoc = (start, delimiter, strip) => {
152
- let index = start;
153
- while (index < to) {
154
- const newline = source.indexOf('\n', index);
155
- const lineEnd = newline === -1 || newline >= to ? to : newline;
156
- let line = source.slice(index, lineEnd).replace(/\r$/, '');
157
- if (strip) {
158
- line = line.replace(/^\t+/, '');
159
- }
160
- if (line === delimiter) {
161
- return { body: { start, end: index }, next: Math.min(lineEnd + 1, to) };
162
- }
163
- index = lineEnd + 1;
110
+ descriptorStart = null;
111
+ };
112
+ const skipBlanks = index => {
113
+ while (index < to && BLANKS.includes(source[index])) {
114
+ index++;
115
+ }
116
+ return index;
117
+ };
118
+ const readWord = start => {
119
+ let index = start;
120
+ let text = '';
121
+ let quoted = null;
122
+ let parts = 0;
123
+ let bare = true;
124
+ while (index < to) {
125
+ const char = source[index];
126
+ if (BLANKS.includes(char) || char === '\n' || SEPARATORS.includes(char) || char === '<' || char === '>') {
127
+ break;
128
+ }
129
+ parts++;
130
+ if (char === "'") {
131
+ const close = source.indexOf("'", index + 1);
132
+ const end = close === -1 || close >= to ? to : close;
133
+ text += source.slice(index + 1, end);
134
+ quoted = {
135
+ start: index + 1,
136
+ end
137
+ };
138
+ bare = false;
139
+ index = Math.min(end + 1, to);
140
+ } else if (char === '"') {
141
+ let end = index + 1;
142
+ while (end < to && source[end] !== '"') {
143
+ if (source[end] === '\\' && end + 1 < to && '$`"\\\n'.includes(source[end + 1])) {
144
+ text += source[end + 1];
145
+ end += 2;
146
+ } else {
147
+ text += source[end];
148
+ end++;
149
+ }
164
150
  }
165
- return { body: { start, end: to }, next: to };
151
+ quoted = {
152
+ start: index + 1,
153
+ end
154
+ };
155
+ bare = false;
156
+ index = Math.min(end + 1, to);
157
+ } else if (char === '\\') {
158
+ text += source[index + 1] ?? '';
159
+ bare = false;
160
+ index += 2;
161
+ } else if (char === '$' && source[index + 1] === '(') {
162
+ const end = closingParen(source, index + 1, to);
163
+ text += source.slice(index, end);
164
+ index = end;
165
+ } else {
166
+ text += char;
167
+ index++;
168
+ }
169
+ }
170
+ const end = Math.min(index, to);
171
+ const body = bare ? {
172
+ start,
173
+ end
174
+ } : parts === 1 && quoted !== null ? quoted : null;
175
+ return {
176
+ start,
177
+ end,
178
+ text,
179
+ body
166
180
  };
167
- let index = from;
181
+ };
182
+ const readHeredoc = (start, delimiter, strip) => {
183
+ let index = start;
168
184
  while (index < to) {
169
- const char = source[index];
170
- if (char === '\n') {
171
- index++;
172
- for (const heredoc of pending) {
173
- const { body, next } = readHeredoc(index, heredoc.delimiter, heredoc.strip);
174
- heredoc.command.heredocs.push({ ...heredoc.operator, body });
175
- index = next;
176
- }
177
- pending.length = 0;
178
- finish();
179
- }
180
- else if (BLANKS.includes(char)) {
181
- index++;
182
- }
183
- else if (char === '\\' && source[index + 1] === '\n') {
184
- index += 2;
185
- }
186
- else if (char === '#') {
187
- const newline = source.indexOf('\n', index);
188
- index = newline === -1 || newline >= to ? to : newline;
189
- }
190
- else if (source.startsWith('<<<', index)) {
191
- index = readWord(skipBlanks(index + 3)).end;
192
- }
193
- else if (source.startsWith('<<', index)) {
194
- const start = index;
195
- index += 2;
196
- const strip = source[index] === '-';
197
- const word = readWord(skipBlanks(strip ? index + 1 : index));
198
- if (word.text !== '') {
199
- pending.push({ command: current, delimiter: word.text, strip, operator: { start, end: word.end } });
200
- }
201
- index = word.end;
202
- }
203
- else if (char === '<' || char === '>' || (char === '&' && source[index + 1] === '>')) {
204
- let end = index + 1;
205
- while (end < to && '<>&|'.includes(source[end])) {
206
- end++;
207
- }
208
- const op = source.slice(index, end);
209
- const target = readWord(skipBlanks(end));
210
- current.redirects.push({ start: descriptorStart ?? index, end: Math.max(target.end, end), op, target });
211
- descriptorStart = null;
212
- index = Math.max(target.end, end);
213
- }
214
- else if (SEPARATORS.includes(char)) {
215
- index++;
216
- finish();
217
- }
218
- else {
219
- const word = readWord(index);
220
- // The `2` of `2>&1` is a file descriptor, not an argument.
221
- const descriptor = /^\d+$/.test(word.text) && (source[word.end] === '>' || source[word.end] === '<');
222
- if (descriptor) {
223
- descriptorStart = word.start;
224
- }
225
- else {
226
- current.words.push(word);
227
- }
228
- index = Math.max(word.end, index + 1);
229
- }
185
+ const newline = source.indexOf('\n', index);
186
+ const lineEnd = newline === -1 || newline >= to ? to : newline;
187
+ let line = source.slice(index, lineEnd).replace(/\r$/, '');
188
+ if (strip) {
189
+ line = line.replace(/^\t+/, '');
190
+ }
191
+ if (line === delimiter) {
192
+ return {
193
+ body: {
194
+ start,
195
+ end: index
196
+ },
197
+ next: Math.min(lineEnd + 1, to)
198
+ };
199
+ }
200
+ index = lineEnd + 1;
201
+ }
202
+ return {
203
+ body: {
204
+ start,
205
+ end: to
206
+ },
207
+ next: to
208
+ };
209
+ };
210
+ let index = from;
211
+ while (index < to) {
212
+ const char = source[index];
213
+ if (char === '\n') {
214
+ index++;
215
+ for (const heredoc of pending) {
216
+ const {
217
+ body,
218
+ next
219
+ } = readHeredoc(index, heredoc.delimiter, heredoc.strip);
220
+ heredoc.command.heredocs.push({
221
+ ...heredoc.operator,
222
+ body
223
+ });
224
+ index = next;
225
+ }
226
+ pending.length = 0;
227
+ finish();
228
+ } else if (BLANKS.includes(char)) {
229
+ index++;
230
+ } else if (char === '\\' && source[index + 1] === '\n') {
231
+ index += 2;
232
+ } else if (char === '#') {
233
+ const newline = source.indexOf('\n', index);
234
+ index = newline === -1 || newline >= to ? to : newline;
235
+ } else if (source.startsWith('<<<', index)) {
236
+ index = readWord(skipBlanks(index + 3)).end;
237
+ } else if (source.startsWith('<<', index)) {
238
+ const start = index;
239
+ index += 2;
240
+ const strip = source[index] === '-';
241
+ const word = readWord(skipBlanks(strip ? index + 1 : index));
242
+ if (word.text !== '') {
243
+ pending.push({
244
+ command: current,
245
+ delimiter: word.text,
246
+ strip,
247
+ operator: {
248
+ start,
249
+ end: word.end
250
+ }
251
+ });
252
+ }
253
+ index = word.end;
254
+ } else if (char === '<' || char === '>' || char === '&' && source[index + 1] === '>') {
255
+ let end = index + 1;
256
+ while (end < to && '<>&|'.includes(source[end])) {
257
+ end++;
258
+ }
259
+ const op = source.slice(index, end);
260
+ const target = readWord(skipBlanks(end));
261
+ current.redirects.push({
262
+ start: descriptorStart ?? index,
263
+ end: Math.max(target.end, end),
264
+ op,
265
+ target
266
+ });
267
+ descriptorStart = null;
268
+ index = Math.max(target.end, end);
269
+ } else if (SEPARATORS.includes(char)) {
270
+ index++;
271
+ finish();
272
+ } else {
273
+ const word = readWord(index);
274
+ // The `2` of `2>&1` is a file descriptor, not an argument.
275
+ const descriptor = /^\d+$/.test(word.text) && (source[word.end] === '>' || source[word.end] === '<');
276
+ if (descriptor) {
277
+ descriptorStart = word.start;
278
+ } else {
279
+ current.words.push(word);
280
+ }
281
+ index = Math.max(word.end, index + 1);
230
282
  }
231
- finish();
232
- return commands;
283
+ }
284
+ finish();
285
+ return commands;
233
286
  }
234
287
  /* Where the `)` that closes the `(` at `open` is, past it; quotes inside do not count. */
235
288
  function closingParen(source, open, to) {
236
- let depth = 0;
237
- let quote = null;
238
- for (let index = open; index < to; index++) {
239
- const char = source[index];
240
- if (quote !== null) {
241
- if (char === quote) {
242
- quote = null;
243
- }
244
- else if (char === '\\' && quote === '"') {
245
- index++;
246
- }
247
- }
248
- else if (char === "'" || char === '"') {
249
- quote = char;
250
- }
251
- else if (char === '(') {
252
- depth++;
253
- }
254
- else if (char === ')') {
255
- depth--;
256
- if (depth === 0) {
257
- return index + 1;
258
- }
259
- }
289
+ let depth = 0;
290
+ let quote = null;
291
+ for (let index = open; index < to; index++) {
292
+ const char = source[index];
293
+ if (quote !== null) {
294
+ if (char === quote) {
295
+ quote = null;
296
+ } else if (char === '\\' && quote === '"') {
297
+ index++;
298
+ }
299
+ } else if (char === "'" || char === '"') {
300
+ quote = char;
301
+ } else if (char === '(') {
302
+ depth++;
303
+ } else if (char === ')') {
304
+ depth--;
305
+ if (depth === 0) {
306
+ return index + 1;
307
+ }
260
308
  }
261
- return to;
309
+ }
310
+ return to;
262
311
  }
263
312
  /* The index of the word a command runs, past variable assignments, wrappers and runners; -1 for none. */
264
313
  function programIndex(words) {
265
- let index = 0;
266
- while (index < words.length) {
267
- const text = words[index].text;
268
- if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(text)) {
269
- index++;
270
- }
271
- else if (WRAPPERS.has(programOf(text))) {
272
- index++;
273
- while (index < words.length && words[index].text.startsWith('-')) {
274
- index++;
275
- }
276
- }
277
- else if (RUNNERS.has(programOf(text)) && words[index + 1]?.text === 'run') {
278
- index += 2;
279
- }
280
- else {
281
- return index;
282
- }
314
+ let index = 0;
315
+ while (index < words.length) {
316
+ const text = words[index].text;
317
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(text)) {
318
+ index++;
319
+ } else if (WRAPPERS.has(programOf(text))) {
320
+ index++;
321
+ while (index < words.length && words[index].text.startsWith('-')) {
322
+ index++;
323
+ }
324
+ } else if (RUNNERS.has(programOf(text)) && words[index + 1]?.text === 'run') {
325
+ index += 2;
326
+ } else {
327
+ return index;
283
328
  }
284
- return -1;
329
+ }
330
+ return -1;
285
331
  }
286
332
  /* The code of one simple command: an inline script, or a heredoc fed to an interpreter or written to a file. */
287
333
  function codeOf(command) {
288
- const found = [];
289
- const at = programIndex(command.words);
290
- const program = at === -1 ? '' : programOf(command.words[at].text);
291
- const interpreter = INTERPRETERS[program];
292
- let readsFile = false;
293
- if (interpreter !== undefined) {
294
- let positional = 0;
295
- for (let index = at + 1; index < command.words.length; index++) {
296
- const word = command.words[index];
297
- if (word.text.startsWith('-') && word.text !== '-') {
298
- if (interpreter.script(word.text)) {
299
- const script = command.words[index + 1];
300
- if (script?.body) {
301
- found.push({ ...script.body, language: interpreter.language });
302
- }
303
- readsFile = true;
304
- index++;
305
- }
306
- else if (interpreter.takesValue?.has(word.text)) {
307
- index++;
308
- }
309
- else if (interpreter === PYTHON && word.text === '-m') {
310
- readsFile = true;
311
- break;
312
- }
313
- continue;
314
- }
315
- if (interpreter.client !== true) {
316
- // A script file; whatever follows is its own arguments.
317
- readsFile = word.text !== '-';
318
- break;
319
- }
320
- if (positional === interpreter.positional && word.body !== null) {
321
- found.push({ ...word.body, language: interpreter.language });
322
- }
323
- positional++;
334
+ const found = [];
335
+ const at = programIndex(command.words);
336
+ const program = at === -1 ? '' : programOf(command.words[at].text);
337
+ const interpreter = INTERPRETERS[program];
338
+ let readsFile = false;
339
+ if (interpreter !== undefined) {
340
+ let positional = 0;
341
+ for (let index = at + 1; index < command.words.length; index++) {
342
+ const word = command.words[index];
343
+ if (word.text.startsWith('-') && word.text !== '-') {
344
+ if (interpreter.script(word.text)) {
345
+ const script = command.words[index + 1];
346
+ if (script?.body) {
347
+ found.push({
348
+ ...script.body,
349
+ language: interpreter.language
350
+ });
351
+ }
352
+ readsFile = true;
353
+ index++;
354
+ } else if (interpreter.takesValue?.has(word.text)) {
355
+ index++;
356
+ } else if (interpreter === PYTHON && word.text === '-m') {
357
+ readsFile = true;
358
+ break;
324
359
  }
360
+ continue;
361
+ }
362
+ if (interpreter.client !== true) {
363
+ // A script file; whatever follows is its own arguments.
364
+ readsFile = word.text !== '-';
365
+ break;
366
+ }
367
+ if (positional === interpreter.positional && word.body !== null) {
368
+ found.push({
369
+ ...word.body,
370
+ language: interpreter.language
371
+ });
372
+ }
373
+ positional++;
325
374
  }
326
- const heredocLanguage = interpreter !== undefined && (!readsFile || interpreter.client === true) ? interpreter.language : writtenLanguage(command, program);
327
- if (heredocLanguage !== null) {
328
- for (const { body } of command.heredocs) {
329
- found.push({ ...body, language: heredocLanguage });
330
- }
375
+ }
376
+ const heredocLanguage = interpreter !== undefined && (!readsFile || interpreter.client === true) ? interpreter.language : writtenLanguage(command, program);
377
+ if (heredocLanguage !== null) {
378
+ for (const {
379
+ body
380
+ } of command.heredocs) {
381
+ found.push({
382
+ ...body,
383
+ language: heredocLanguage
384
+ });
331
385
  }
332
- return found;
386
+ }
387
+ return found;
333
388
  }
334
389
  /* The language of the file a `cat > file` or `tee file` writes, by its extension; null when nothing says. */
335
390
  function writtenLanguage(command, program) {
336
- const targets = command.redirects.filter(({ op }) => op === '>' || op === '>>' || op === '>|').map(({ target }) => target.text);
337
- if (program === 'tee') {
338
- targets.push(...command.words
339
- .slice(programIndex(command.words) + 1)
340
- .map(({ text }) => text)
341
- .filter((text) => !text.startsWith('-')));
342
- }
343
- for (const target of targets) {
344
- const dot = target.lastIndexOf('.');
345
- const language = dot === -1 ? undefined : EXTENSIONS[target.slice(dot + 1).toLowerCase()];
346
- if (language !== undefined) {
347
- return language;
348
- }
391
+ const targets = command.redirects.filter(({
392
+ op
393
+ }) => op === '>' || op === '>>' || op === '>|').map(({
394
+ target
395
+ }) => target.text);
396
+ if (program === 'tee') {
397
+ targets.push(...command.words.slice(programIndex(command.words) + 1).map(({
398
+ text
399
+ }) => text).filter(text => !text.startsWith('-')));
400
+ }
401
+ for (const target of targets) {
402
+ const dot = target.lastIndexOf('.');
403
+ const language = dot === -1 ? undefined : EXTENSIONS[target.slice(dot + 1).toLowerCase()];
404
+ if (language !== undefined) {
405
+ return language;
349
406
  }
350
- return null;
407
+ }
408
+ return null;
351
409
  }
352
410
  function collect(source, from, to, depth, into) {
353
- for (const command of parseCommands(source, from, to)) {
354
- for (const code of codeOf(command)) {
355
- if (code.end <= code.start) {
356
- continue;
357
- }
358
- into.push(code);
359
- if (code.language === SHELL_LANGUAGE && depth < MAX_DEPTH) {
360
- collect(source, code.start, code.end, depth + 1, into);
361
- }
362
- }
411
+ for (const command of parseCommands(source, from, to)) {
412
+ for (const code of codeOf(command)) {
413
+ if (code.end <= code.start) {
414
+ continue;
415
+ }
416
+ into.push(code);
417
+ if (code.language === SHELL_LANGUAGE && depth < MAX_DEPTH) {
418
+ collect(source, code.start, code.end, depth + 1, into);
419
+ }
363
420
  }
421
+ }
364
422
  }
365
423
  /*
366
424
  * The simple commands of a shell line, in the order they come: a pipeline, a list and a line each split
367
425
  * apart, a heredoc with the command it feeds. Only the line itself: the script of a `bash -lc '…'` stays a word.
368
426
  */
369
427
  export function shellCommands(source) {
370
- return parseCommands(source, 0, source.length).map((command) => {
371
- const index = programIndex(command.words);
372
- const word = command.words[index];
373
- return {
374
- ...command,
375
- program: word === undefined ? null : { index, name: word.text.slice(word.text.lastIndexOf('/') + 1) }
376
- };
377
- });
428
+ return parseCommands(source, 0, source.length).map(command => {
429
+ const index = programIndex(command.words);
430
+ const word = command.words[index];
431
+ return {
432
+ ...command,
433
+ program: word === undefined ? null : {
434
+ index,
435
+ name: word.text.slice(word.text.lastIndexOf('/') + 1)
436
+ }
437
+ };
438
+ });
378
439
  }
379
440
  /*
380
441
  * The code inside a shell command that is in another language, or a shell script of its own: the
@@ -384,10 +445,10 @@ export function shellCommands(source) {
384
445
  * grammar, not a parser: what it does not recognize stays plain shell.
385
446
  */
386
447
  export function embeddedCode(command) {
387
- if (command.length > EMBEDDED_CODE_LIMIT) {
388
- return [];
389
- }
390
- const found = [];
391
- collect(command, 0, command.length, 0, found);
392
- return found.sort((left, right) => left.start - right.start || right.end - left.end);
393
- }
448
+ if (command.length > EMBEDDED_CODE_LIMIT) {
449
+ return [];
450
+ }
451
+ const found = [];
452
+ collect(command, 0, command.length, 0, found);
453
+ return found.sort((left, right) => left.start - right.start || right.end - left.end);
454
+ }