zidane-ui 9.1.13 → 9.1.14

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 (309) hide show
  1. package/dist/adapters/index.d.ts +2 -2
  2. package/dist/adapters/index.js +2 -2
  3. package/dist/adapters/live.d.ts +29 -3
  4. package/dist/adapters/live.js +9 -1
  5. package/dist/adapters/server-composer-host.js +17 -2
  6. package/dist/adapters/server-extensions-host.d.ts +0 -1
  7. package/dist/adapters/server-extensions-host.js +5 -16
  8. package/dist/adapters/server-git-host.js +7 -16
  9. package/dist/adapters/server-host.js +181 -43
  10. package/dist/adapters/server-machines-host.d.ts +2 -0
  11. package/dist/adapters/server-machines-host.js +24 -25
  12. package/dist/adapters/server-onboarding-host.d.ts +1 -1
  13. package/dist/adapters/server-onboarding-host.js +3 -4
  14. package/dist/adapters/server-session-host.js +22 -3
  15. package/dist/adapters/server-settings-accounts.js +2 -2
  16. package/dist/adapters/server-settings-host.js +3 -3
  17. package/dist/adapters/server-settings-performance.js +7 -9
  18. package/dist/adapters/server-settings-sections.js +13 -14
  19. package/dist/adapters/server-sidebar-host.js +2 -2
  20. package/dist/adapters/sse-host.js +68 -3
  21. package/dist/adapters/sse-protocol.d.ts +12 -2
  22. package/dist/adapters/sse-protocol.js +4 -2
  23. package/dist/app/AppHostProvider.js +4 -3
  24. package/dist/app/ModalProvider.d.ts +13 -3
  25. package/dist/app/ModalProvider.js +103 -24
  26. package/dist/app/NoticeStack.d.ts +33 -0
  27. package/dist/app/NoticeStack.js +90 -0
  28. package/dist/app/index.d.ts +3 -2
  29. package/dist/app/index.js +3 -2
  30. package/dist/appearance/AppearanceProvider.js +2 -2
  31. package/dist/appearance/headless/index.js +1 -1
  32. package/dist/approvals/headless/index.js +2 -2
  33. package/dist/chat/SessionFilterMenu.d.ts +1 -1
  34. package/dist/chat/SessionFilterMenu.js +2 -1
  35. package/dist/chat/Transcript.js +1 -1
  36. package/dist/chat/composer/Composer.js +9 -6
  37. package/dist/chat/composer/ComposerEditor.js +1 -1
  38. package/dist/chat/composer/ConversationBadges.js +1 -1
  39. package/dist/chat/composer/ModelChainList.js +17 -8
  40. package/dist/chat/composer/ModelChainTooltip.js +5 -2
  41. package/dist/chat/composer/use-composer-stores.js +1 -1
  42. package/dist/chat/composer/use-draft-target.d.ts +20 -1
  43. package/dist/chat/composer/use-draft-target.js +122 -6
  44. package/dist/chat/composer/use-new-session-defaults.d.ts +5 -1
  45. package/dist/chat/composer/use-new-session-defaults.js +17 -4
  46. package/dist/chat/composer/use-run-meter.js +1 -1
  47. package/dist/chat/composer/use-send-prompt.js +1 -1
  48. package/dist/chat/headless/chip-labels.d.ts +1 -0
  49. package/dist/chat/headless/chip-labels.js +1 -0
  50. package/dist/chat/headless/composer/index.js +2 -2
  51. package/dist/chat/headless/draft-target.d.ts +21 -1
  52. package/dist/chat/headless/fixture-host.js +17 -2
  53. package/dist/chat/headless/host.d.ts +3 -3
  54. package/dist/chat/headless/index.d.ts +9 -9
  55. package/dist/chat/headless/index.js +15 -15
  56. package/dist/chat/headless/labels.d.ts +13 -4
  57. package/dist/chat/headless/labels.js +8 -5
  58. package/dist/chat/headless/session-list.d.ts +20 -6
  59. package/dist/chat/headless/session-list.js +1 -0
  60. package/dist/chat/headless/sidebar/directory.d.ts +56 -14
  61. package/dist/chat/headless/sidebar/directory.js +149 -70
  62. package/dist/chat/headless/sidebar/index.d.ts +3 -3
  63. package/dist/chat/headless/sidebar/index.js +3 -3
  64. package/dist/chat/headless/sidebar/labels.d.ts +15 -6
  65. package/dist/chat/headless/sidebar/types.d.ts +3 -1
  66. package/dist/chat/headless/sidebar/view.d.ts +13 -5
  67. package/dist/chat/headless/sidebar/view.js +31 -11
  68. package/dist/chat/headless/streams/actions.d.ts +5 -3
  69. package/dist/chat/headless/streams/actions.js +3 -2
  70. package/dist/chat/headless/streams/index.d.ts +3 -3
  71. package/dist/chat/headless/streams/merge.d.ts +6 -10
  72. package/dist/chat/headless/streams/merge.js +7 -21
  73. package/dist/chat/headless/streams/session-streams.d.ts +29 -4
  74. package/dist/chat/headless/streams/session-streams.js +86 -0
  75. package/dist/chat/headless/streams/store.d.ts +162 -16
  76. package/dist/chat/headless/streams/store.js +334 -38
  77. package/dist/chat/headless/streams/types.d.ts +10 -7
  78. package/dist/chat/headless/transcript-labels.d.ts +1 -0
  79. package/dist/chat/interactions/PlanCard.js +10 -3
  80. package/dist/chat/interactions/QuestionForm.js +7 -3
  81. package/dist/chat/interactions/card-ui.d.ts +5 -3
  82. package/dist/chat/interactions/card-ui.js +9 -7
  83. package/dist/chat/sidebar/SessionSidebar.js +5 -5
  84. package/dist/chat/sidebar/SidebarFilterMenu.js +3 -1
  85. package/dist/chat/sidebar/SidebarFrame.d.ts +4 -0
  86. package/dist/chat/sidebar/SidebarFrame.js +27 -9
  87. package/dist/chat/sidebar/SidebarGroupHeader.js +1 -1
  88. package/dist/chat/sidebar/SidebarHostProvider.d.ts +8 -5
  89. package/dist/chat/sidebar/SidebarHostProvider.js +13 -9
  90. package/dist/chat/sidebar/SidebarToggleButton.js +7 -3
  91. package/dist/chat/sidebar/index.d.ts +2 -2
  92. package/dist/chat/sidebar/session-menu.js +4 -4
  93. package/dist/chat/sidebar/useSaveViewAsSpace.js +2 -2
  94. package/dist/chat/testing/contract.js +2 -2
  95. package/dist/chat/transcript/AuthFailureCard.js +11 -8
  96. package/dist/chat/transcript/BadgeMenu.js +13 -2
  97. package/dist/chat/transcript/MermaidDiagram.js +7 -3
  98. package/dist/chat/transcript/fold.d.ts +4 -0
  99. package/dist/chat/transcript/fold.js +53 -22
  100. package/dist/chat/transcript/script-input.d.ts +1 -1
  101. package/dist/chat/transcript/shell-block.js +8 -4
  102. package/dist/chat/transcript/useStickToBottom.js +12 -0
  103. package/dist/components/BrowserSignIn.js +23 -21
  104. package/dist/components/Form.d.ts +6 -4
  105. package/dist/components/Form.js +16 -8
  106. package/dist/components/LoadError.d.ts +4 -2
  107. package/dist/components/LoadError.js +13 -9
  108. package/dist/components/Notice.d.ts +29 -0
  109. package/dist/components/Notice.js +63 -0
  110. package/dist/components/PanelEmpty.d.ts +1 -1
  111. package/dist/components/PanelEmpty.js +4 -2
  112. package/dist/components/Restricted.d.ts +1 -1
  113. package/dist/components/palette/PaletteList.js +8 -1
  114. package/dist/components/palette/PalettePanel.js +14 -6
  115. package/dist/core.css +24 -5
  116. package/dist/dist/{index-Bq87OcGy.d.ts → index-C6rzc-tt.d.ts} +28 -3
  117. package/dist/dist/index.d.ts +2 -2
  118. package/dist/dist/{timeout-B5pO5I5a.d.ts → timeout-Cz9dRF8Q.d.ts} +1 -1
  119. package/dist/extensions/ExtensionSettingsPage.js +2 -5
  120. package/dist/extensions/ExtensionSettingsSection.js +5 -4
  121. package/dist/extensions/ExtensionSettingsSidebar.js +3 -7
  122. package/dist/extensions/SettingsWireForm.d.ts +1 -7
  123. package/dist/extensions/SettingsWireForm.js +7 -5
  124. package/dist/extensions/headless/fixture-host.d.ts +1 -5
  125. package/dist/extensions/headless/fixture-host.js +2 -5
  126. package/dist/extensions/headless/host.d.ts +1 -11
  127. package/dist/extensions/headless/index.d.ts +3 -3
  128. package/dist/extensions/headless/index.js +6 -6
  129. package/dist/extensions/headless/select.d.ts +1 -11
  130. package/dist/extensions/headless/select.js +1 -18
  131. package/dist/extensions/hooks.js +1 -1
  132. package/dist/files/EditorColumn.js +13 -2
  133. package/dist/files/MediaDiff.js +1 -1
  134. package/dist/files/TreeColumn.js +13 -20
  135. package/dist/files/useEntryActions.js +1 -1
  136. package/dist/files/useOpenFiles.js +3 -1
  137. package/dist/git/BranchMenu.js +6 -4
  138. package/dist/git/ImportRepoDialog.js +18 -9
  139. package/dist/git/MoveSessionDialog.js +16 -8
  140. package/dist/git/RemoteFolderPicker.js +35 -17
  141. package/dist/git/SyncChip.js +17 -17
  142. package/dist/git/WherePicker.d.ts +16 -1
  143. package/dist/git/WherePicker.js +81 -37
  144. package/dist/git/headless/environment.d.ts +33 -3
  145. package/dist/git/headless/environment.js +33 -5
  146. package/dist/git/headless/index.d.ts +2 -2
  147. package/dist/git/headless/index.js +2 -2
  148. package/dist/git/headless/labels.d.ts +15 -2
  149. package/dist/git/headless/labels.js +17 -4
  150. package/dist/git/useEnvironmentChoices.d.ts +3 -1
  151. package/dist/git/useEnvironmentChoices.js +7 -4
  152. package/dist/index.d.ts +2 -1
  153. package/dist/index.js +2 -1
  154. package/dist/keybindings/KeyCommands.js +1 -1
  155. package/dist/keybindings/KeybindingsProvider.js +1 -1
  156. package/dist/keybindings/headless/index.js +2 -2
  157. package/dist/keybindings/headless/overrides.js +1 -1
  158. package/dist/labels.d.ts +5 -0
  159. package/dist/labels.js +5 -0
  160. package/dist/machines/AddMachineDialog.d.ts +34 -0
  161. package/dist/machines/AddMachineDialog.js +464 -0
  162. package/dist/machines/Banners.d.ts +33 -4
  163. package/dist/machines/Banners.js +64 -3
  164. package/dist/machines/DaemonMenu.js +27 -4
  165. package/dist/machines/HostCapabilities.d.ts +1 -3
  166. package/dist/machines/HostCapabilities.js +24 -45
  167. package/dist/machines/HostSyncPanel.js +124 -130
  168. package/dist/machines/HostsSection.d.ts +4 -1
  169. package/dist/machines/HostsSection.js +30 -7
  170. package/dist/machines/MachinesExplainer.d.ts +17 -0
  171. package/dist/machines/MachinesExplainer.js +71 -0
  172. package/dist/machines/MachinesProvider.d.ts +14 -2
  173. package/dist/machines/MachinesProvider.js +35 -1
  174. package/dist/machines/ServerAddedCard.d.ts +31 -0
  175. package/dist/machines/ServerAddedCard.js +72 -0
  176. package/dist/machines/ServerCard.js +91 -215
  177. package/dist/machines/ServerMachinesPanel.d.ts +2 -2
  178. package/dist/machines/ServerMachinesPanel.js +184 -323
  179. package/dist/machines/ServerUpdatePanel.js +51 -40
  180. package/dist/machines/ShareThisComputerForm.d.ts +19 -0
  181. package/dist/machines/ShareThisComputerForm.js +133 -0
  182. package/dist/machines/SyncOutcomeBadge.js +1 -1
  183. package/dist/machines/TokensPanel.d.ts +5 -3
  184. package/dist/machines/TokensPanel.js +98 -78
  185. package/dist/machines/headless/fixture-host.d.ts +19 -3
  186. package/dist/machines/headless/fixture-host.js +43 -6
  187. package/dist/machines/headless/fixtures.js +4 -6
  188. package/dist/machines/headless/host.d.ts +40 -19
  189. package/dist/machines/headless/index.d.ts +3 -3
  190. package/dist/machines/headless/index.js +3 -3
  191. package/dist/machines/headless/labels.d.ts +63 -20
  192. package/dist/machines/headless/labels.js +88 -25
  193. package/dist/machines/headless/messages.js +8 -0
  194. package/dist/machines/headless/stores.d.ts +9 -2
  195. package/dist/machines/headless/stores.js +28 -1
  196. package/dist/machines/index.d.ts +7 -3
  197. package/dist/machines/index.js +8 -4
  198. package/dist/machines/testing/contract.d.ts +15 -3
  199. package/dist/machines/testing/contract.js +68 -14
  200. package/dist/motion/grow.d.ts +8 -1
  201. package/dist/motion/grow.js +10 -4
  202. package/dist/onboarding/headless/labels.d.ts +13 -0
  203. package/dist/onboarding/headless/labels.js +8 -0
  204. package/dist/onboarding/sources/SourceBrowser.js +11 -7
  205. package/dist/onboarding/steps/ImportStep.js +4 -1
  206. package/dist/onboarding/steps/ReadyStep.js +9 -2
  207. package/dist/onboarding/steps/connect/KeyForm.js +6 -2
  208. package/dist/onboarding/steps/connect/ProviderPanel.js +6 -2
  209. package/dist/onboarding/steps/connect/ProviderReady.js +25 -20
  210. package/dist/onboarding/steps/tasks.js +17 -14
  211. package/dist/palette/app-sources.js +1 -1
  212. package/dist/server/sse-handler.js +141 -19
  213. package/dist/session/ArtifactsPanel.js +40 -18
  214. package/dist/session/PlanTracker.js +13 -8
  215. package/dist/session/ProjectHome.js +13 -11
  216. package/dist/session/RemindersPanel.js +35 -17
  217. package/dist/session/RunningWorkDialog.js +6 -2
  218. package/dist/session/SecretsPanel.js +29 -10
  219. package/dist/session/SessionDetailsDialog.d.ts +1 -1
  220. package/dist/session/SessionDetailsDialog.js +18 -10
  221. package/dist/session/SideChat.js +10 -7
  222. package/dist/session/TurnDetailsDialog.js +19 -5
  223. package/dist/session/UsagePanel.js +10 -4
  224. package/dist/session/headless/host.d.ts +2 -0
  225. package/dist/session/headless/index.js +2 -2
  226. package/dist/session/headless/labels.d.ts +19 -1
  227. package/dist/session/headless/labels.js +15 -1
  228. package/dist/session/headless/queue.js +2 -1
  229. package/dist/session/headless/reminder-labels.d.ts +4 -0
  230. package/dist/session/headless/reminder-labels.js +4 -0
  231. package/dist/settings/SettingsRestricted.d.ts +1 -1
  232. package/dist/settings/SettingsRestricted.js +4 -4
  233. package/dist/settings/SettingsShell.d.ts +7 -0
  234. package/dist/settings/SettingsShell.js +6 -1
  235. package/dist/settings/headless/fixture-performance.d.ts +1 -1
  236. package/dist/settings/headless/host.d.ts +2 -2
  237. package/dist/settings/headless/index.js +1 -1
  238. package/dist/settings/headless/labels.d.ts +3 -3
  239. package/dist/settings/headless/labels.js +3 -3
  240. package/dist/settings/headless/performance.d.ts +3 -4
  241. package/dist/settings/headless/search.d.ts +1 -1
  242. package/dist/settings/index.d.ts +2 -1
  243. package/dist/settings/index.js +2 -1
  244. package/dist/settings/sections/appearance/AppearanceSection.js +2 -2
  245. package/dist/settings/sections/claude-import/ClaudeImportDialog.js +1 -1
  246. package/dist/settings/sections/editor/EditorSection.js +8 -5
  247. package/dist/settings/sections/editor/labels.d.ts +1 -0
  248. package/dist/settings/sections/editor/labels.js +1 -0
  249. package/dist/settings/sections/environments/EnvironmentsSection.js +21 -14
  250. package/dist/settings/sections/environments/labels.d.ts +1 -0
  251. package/dist/settings/sections/environments/labels.js +2 -1
  252. package/dist/settings/sections/extensions/ChangeOriginDialog.js +1 -1
  253. package/dist/settings/sections/extensions/CreateExtensionDialog.js +1 -1
  254. package/dist/settings/sections/extensions/ExtensionConfigRows.d.ts +1 -3
  255. package/dist/settings/sections/extensions/ExtensionConfigRows.js +20 -19
  256. package/dist/settings/sections/extensions/ExtensionOptionsSection.js +2 -1
  257. package/dist/settings/sections/extensions/ExtensionsSection.js +1 -1
  258. package/dist/settings/sections/extensions/options-labels.d.ts +2 -1
  259. package/dist/settings/sections/extensions/options-labels.js +2 -1
  260. package/dist/settings/sections/host-catalog/HostCatalogSection.js +1 -1
  261. package/dist/settings/sections/index.d.ts +2 -1
  262. package/dist/settings/sections/index.js +2 -1
  263. package/dist/settings/sections/instructions/InstructionsSection.js +1 -1
  264. package/dist/settings/sections/logs/LogsSection.d.ts +2 -2
  265. package/dist/settings/sections/logs/LogsSection.js +2 -2
  266. package/dist/settings/sections/mcp/McpSection.d.ts +1 -1
  267. package/dist/settings/sections/mcp/McpSection.js +13 -7
  268. package/dist/settings/sections/mcp/McpServerRow.js +21 -14
  269. package/dist/settings/sections/mcp/labels.d.ts +8 -2
  270. package/dist/settings/sections/mcp/labels.js +8 -2
  271. package/dist/settings/sections/models/ModelRows.js +1 -1
  272. package/dist/settings/sections/models/NewChatPlaceRow.d.ts +26 -0
  273. package/dist/settings/sections/models/NewChatPlaceRow.js +78 -0
  274. package/dist/settings/sections/models/SpacesDefaultsSection.js +15 -3
  275. package/dist/settings/sections/models/labels.d.ts +7 -0
  276. package/dist/settings/sections/models/labels.js +7 -0
  277. package/dist/settings/sections/models/model-test.js +7 -4
  278. package/dist/settings/sections/performance/PerformanceSection.js +16 -6
  279. package/dist/settings/sections/performance/labels.d.ts +1 -1
  280. package/dist/settings/sections/performance/labels.js +1 -1
  281. package/dist/settings/sections/providers/ProvidersSection.d.ts +1 -1
  282. package/dist/settings/sections/providers/ProvidersSection.js +15 -8
  283. package/dist/settings/sections/providers/ServerProvidersSection.d.ts +1 -1
  284. package/dist/settings/sections/providers/ServerProvidersSection.js +12 -6
  285. package/dist/settings/sections/providers/labels.d.ts +2 -2
  286. package/dist/settings/sections/providers/labels.js +2 -2
  287. package/dist/settings/sections/shared/catalog.js +1 -1
  288. package/dist/settings/sections/skills/SkillsSection.js +1 -1
  289. package/dist/settings/testing/performance.contract.js +8 -12
  290. package/dist/styles.css +32 -3
  291. package/dist/terminal/HostTerminalSurface.js +17 -7
  292. package/dist/terminal/TerminalPanel.js +30 -17
  293. package/dist/terminal/TerminalSurface.js +11 -4
  294. package/dist/terminal/headless/labels.d.ts +5 -0
  295. package/dist/terminal/headless/labels.js +5 -0
  296. package/dist/terminal/headless/store.d.ts +1 -1
  297. package/dist/terminal/headless/store.js +6 -3
  298. package/dist/workspace/LayoutBudget.d.ts +5 -1
  299. package/dist/workspace/LayoutBudget.js +14 -1
  300. package/dist/workspace/PanelContentView.d.ts +1 -1
  301. package/dist/workspace/PanelContentView.js +17 -6
  302. package/dist/workspace/WorkspaceProvider.js +4 -3
  303. package/dist/workspace/extension-tabs.js +1 -1
  304. package/dist/workspace/headless/index.js +1 -1
  305. package/dist/workspace/headless/labels.d.ts +1 -0
  306. package/dist/workspace/headless/labels.js +1 -0
  307. package/package.json +3 -3
  308. package/src/styles/motion.css +8 -0
  309. package/src/styles/primitives.css +7 -0
@@ -1,4 +1,5 @@
1
1
  import { buttonClass } from "../../components/button.js";
2
+ import { Notice } from "../../components/Notice.js";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  import { useEffect, useRef } from "react";
4
5
  //#region src/chat/interactions/card-ui.tsx
@@ -27,15 +28,16 @@ const INPUT = `${FIELD} w-full placeholder:text-[var(--zg-text-subtle)]`;
27
28
  /**
28
29
  * Renders an inline error message, or nothing when there is none.
29
30
  *
30
- * @param props - Component props: the `error` text.
31
+ * @param props - Component props: the `error` message and its raw `detail`.
31
32
  */
32
- function CardError({ error, className, style }) {
33
+ function CardError({ error, detail, className, style }) {
33
34
  if (!error) return null;
34
- return /* @__PURE__ */ jsx("span", {
35
- role: "alert",
36
- className: ["min-w-0 truncate text-zg-meta text-[var(--zg-error)]", className].filter(Boolean).join(" "),
37
- style,
38
- title: error,
35
+ return /* @__PURE__ */ jsx(Notice, {
36
+ tone: "error",
37
+ compact: true,
38
+ ...detail ? { detail } : {},
39
+ className: ["min-w-0", className].filter(Boolean).join(" "),
40
+ ...style ? { style } : {},
39
41
  children: error
40
42
  });
41
43
  }
@@ -1,4 +1,5 @@
1
1
  import { useWithFade } from "../../motion/springs.js";
2
+ import { errorMessage } from "../../components/report-error.js";
2
3
  import { basename } from "../../path.js";
3
4
  import { useExtensionsHost } from "../../extensions/ExtensionsProvider.js";
4
5
  import { useSidebarNotice } from "./SidebarHostProvider.js";
@@ -133,7 +134,6 @@ function NewSessionButton({ onNewSession, isActive, className = "", style }) {
133
134
  })
134
135
  });
135
136
  }
136
- const messageOf = (err) => err?.message ?? String(err);
137
137
  const NO_ITEMS = [];
138
138
  const NO_DECORATIONS = [];
139
139
  /**
@@ -339,14 +339,14 @@ function SessionSidebar(props) {
339
339
  });
340
340
  }, [onDelete]);
341
341
  const onRowMoveToSpace = useCallback((sessionId, spaceId) => {
342
- onMoveToSpace?.(sessionId, spaceId).catch((err) => notify(labels.moveSessionFailed(messageOf(err))));
342
+ onMoveToSpace?.(sessionId, spaceId).catch((err) => notify(labels.moveSessionFailed(errorMessage(err))));
343
343
  }, [
344
344
  onMoveToSpace,
345
345
  notify,
346
346
  labels
347
347
  ]);
348
348
  const onRowMoveProjectToSpace = useCallback((project, spaceId) => {
349
- onMoveProjectToSpace?.(project, spaceId).catch((err) => notify(labels.moveProjectFailed(messageOf(err))));
349
+ onMoveProjectToSpace?.(project, spaceId).catch((err) => notify(labels.moveProjectFailed(errorMessage(err))));
350
350
  }, [
351
351
  onMoveProjectToSpace,
352
352
  notify,
@@ -361,7 +361,7 @@ function SessionSidebar(props) {
361
361
  if (!open) return;
362
362
  if (onOpenItem) return onOpenItem(open, entry);
363
363
  if ("session" in open) commitImmediate(open.session);
364
- else if ("command" in open) runCommand?.(open.command, { args: entry.item.args }).catch((err) => notify(labels.itemOpenFailed(messageOf(err))));
364
+ else if ("command" in open) runCommand?.(open.command, { args: entry.item.args }).catch((err) => notify(labels.itemOpenFailed(errorMessage(err))));
365
365
  else if ("panel" in open) workspace?.focusTab(open.panel);
366
366
  else openScreen(open.screen);
367
367
  }, [
@@ -375,7 +375,7 @@ function SessionSidebar(props) {
375
375
  ]);
376
376
  const onRunItemAction = useCallback((entry, action) => {
377
377
  if (!action.command || !runCommand) return;
378
- runCommand(action.command, { args: entry.item.args }).catch((err) => notify(labels.itemOpenFailed(messageOf(err))));
378
+ runCommand(action.command, { args: entry.item.args }).catch((err) => notify(labels.itemOpenFailed(errorMessage(err))));
379
379
  }, [
380
380
  runCommand,
381
381
  notify,
@@ -1,6 +1,7 @@
1
1
  import { useChatLabels } from "../useChatLabels.js";
2
2
  import { SessionFilterMenu } from "../SessionFilterMenu.js";
3
3
  import { VIEW_CHOICE } from "../headless/sidebar/types.js";
4
+ import { DEFAULT_SIDEBAR_VIEW } from "../headless/sidebar/view.js";
4
5
  import { useAgentNames } from "./useAgentNames.js";
5
6
  import { jsx } from "react/jsx-runtime";
6
7
  import { useMemo } from "react";
@@ -23,6 +24,7 @@ const VIEWS_WITH_HOST = [
23
24
  const SORTS = [
24
25
  "alphabetical",
25
26
  "createdTime",
27
+ "lastUserMessage",
26
28
  "recency"
27
29
  ];
28
30
  const ALL_AGENTS = "__all__";
@@ -179,7 +181,7 @@ function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, ag
179
181
  label: labels.filterSort,
180
182
  placement: "sort",
181
183
  value: options.find((o) => o.id === current)?.label ?? current,
182
- atDefault: current === (space?.sortBy ? SPACE : "recency"),
184
+ atDefault: current === (space?.sortBy ? SPACE : DEFAULT_SIDEBAR_VIEW.sortBy),
183
185
  options,
184
186
  current,
185
187
  onChange: (next) => {
@@ -22,6 +22,10 @@ interface SidebarFrameState {
22
22
  mounted: boolean;
23
23
  /** Fully open (not entering or closing). */
24
24
  open: boolean;
25
+ /** Open over the chat: the window is too narrow to dock it (`LayoutBudget.sidebarPeek`). */
26
+ overlay: boolean;
27
+ /** Closes it when it is open over the chat. */
28
+ closeOverlay: () => void;
25
29
  /** The width shown (px). */
26
30
  width: number;
27
31
  /** The aside, for the drag's live CSS var. */
@@ -2,8 +2,8 @@ import { readPanelMs, usePresence } from "../../motion/presence.js";
2
2
  import { useResizeDrag } from "../../hooks/useResizeDrag.js";
3
3
  import { DEFAULT_APPEARANCE, LIMITS } from "../../appearance/headless/prefs.js";
4
4
  import { useLayoutBudgetOptional } from "../../workspace/LayoutBudget.js";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- import { useRef } from "react";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import { useEffect, useRef } from "react";
7
7
  //#region src/chat/sidebar/SidebarFrame.tsx
8
8
  /**
9
9
  * The frame's presence, width and drag.
@@ -13,11 +13,13 @@ import { useRef } from "react";
13
13
  function useSidebarFrame(options) {
14
14
  const { collapsed, width: wanted, onWidthCommit, minWidth = LIMITS.sidebarWidth.min, maxWidth = LIMITS.sidebarWidth.max, defaultWidth = DEFAULT_APPEARANCE.sidebarWidth } = options;
15
15
  const budget = useLayoutBudgetOptional();
16
- const presence = usePresence(!collapsed && !(budget?.sidebarForcedCollapsed ?? false), {
16
+ const forced = budget?.sidebarForcedCollapsed ?? false;
17
+ const overlay = forced && (budget?.sidebarPeek ?? false);
18
+ const presence = usePresence(forced ? overlay : !collapsed, {
17
19
  enter: true,
18
20
  exitMs: readPanelMs
19
21
  });
20
- const width = budget && budget.sidebarWidth > 0 ? budget.sidebarWidth : wanted;
22
+ const width = overlay ? Math.min(wanted, Math.max(minWidth, (budget?.chatWidth ?? wanted) - 48)) : budget && budget.sidebarWidth > 0 ? budget.sidebarWidth : wanted;
21
23
  const asideRef = useRef(null);
22
24
  const max = budget ? Math.max(minWidth, budget.getCaps().sidebarMax) : maxWidth;
23
25
  const drag = useResizeDrag({
@@ -32,9 +34,12 @@ function useSidebarFrame(options) {
32
34
  },
33
35
  onCommit: onWidthCommit
34
36
  });
37
+ const closeOverlay = () => budget?.peekSidebar(false);
35
38
  return {
36
39
  mounted: presence.mounted,
37
40
  open: presence.state === "open",
41
+ overlay,
42
+ closeOverlay,
38
43
  width,
39
44
  asideRef,
40
45
  drag
@@ -46,13 +51,26 @@ function useSidebarFrame(options) {
46
51
  * @param props - The frame state, the chrome inset, the content, its name, `className` and `style`.
47
52
  */
48
53
  function SidebarFrame({ frame, chromeInset, children, ariaLabel, className = "", style }) {
49
- const { open, width, asideRef, drag } = frame;
50
- return /* @__PURE__ */ jsxs("aside", {
54
+ const { open, overlay, closeOverlay, width, asideRef, drag } = frame;
55
+ useEffect(() => {
56
+ if (!overlay) return void 0;
57
+ const onKey = (event) => {
58
+ if (event.key === "Escape") closeOverlay();
59
+ };
60
+ window.addEventListener("keydown", onKey);
61
+ return () => window.removeEventListener("keydown", onKey);
62
+ }, [overlay, closeOverlay]);
63
+ return /* @__PURE__ */ jsxs(Fragment, { children: [overlay && /* @__PURE__ */ jsx("div", {
64
+ "aria-hidden": true,
65
+ className: "fixed inset-0 z-40 bg-black/30",
66
+ onClick: closeOverlay
67
+ }), /* @__PURE__ */ jsxs("aside", {
51
68
  ref: asideRef,
52
69
  ...ariaLabel ? { "aria-label": ariaLabel } : {},
53
70
  "data-collapsed": !open,
54
71
  "aria-hidden": !open,
55
- className: `zg-sidebar relative z-[2] shrink-0 h-full bg-[var(--zg-tray)]${className ? ` ${className}` : ""}`,
72
+ "data-overlay": overlay || void 0,
73
+ className: `zg-sidebar ${overlay ? "fixed left-0 top-0 z-zg-overlay shadow-[var(--zg-shadow-float)]" : "relative z-[2]"} shrink-0 h-full bg-[var(--zg-tray)]${className ? ` ${className}` : ""}`,
56
74
  style: {
57
75
  "--zg-sidebar-w": `${width}px`,
58
76
  ...style
@@ -68,12 +86,12 @@ function SidebarFrame({ frame, chromeInset, children, ariaLabel, className = "",
68
86
  style: { width: chromeInset.width }
69
87
  })
70
88
  }), children]
71
- }), open && /* @__PURE__ */ jsx("div", {
89
+ }), open && !overlay && /* @__PURE__ */ jsx("div", {
72
90
  ...drag.handleProps,
73
91
  "data-active": drag.active,
74
92
  className: "zg-resize-handle zg-no-drag -right-1"
75
93
  })]
76
- });
94
+ })] });
77
95
  }
78
96
  //#endregion
79
97
  export { SidebarFrame, useSidebarFrame };
@@ -144,7 +144,7 @@ function SidebarGroupHeader({ row, groupBy, icon, onAssignIcon, onToggle, onNewS
144
144
  label: pinned ? labels.unpinNamed(row.label) : labels.pinNamed(row.label),
145
145
  size: "xs",
146
146
  "aria-pressed": pinned,
147
- className: pinned ? void 0 : "zg-row-dots",
147
+ className: "zg-row-dots",
148
148
  onClick: (event) => {
149
149
  event.stopPropagation();
150
150
  onSetPinned(row.fullPath, !pinned);
@@ -1,12 +1,15 @@
1
1
  import { SidebarHost } from "../headless/sidebar/host.js";
2
+ import { NoticeTone } from "../../components/Notice.js";
2
3
  import { ReactNode } from "react";
3
4
  //#region src/chat/sidebar/SidebarHostProvider.d.ts
5
+ /** Tells the user a command's outcome, worded for people: `error` unless a `tone` says otherwise. */
6
+ type SidebarNotify = (message: string, tone?: NoticeTone) => void;
4
7
  /** Props of {@link SidebarHostProvider}. */
5
8
  interface SidebarHostProviderProps {
6
9
  /** The platform's sidebar capabilities. */
7
10
  host: SidebarHost;
8
- /** Tells the user a command's outcome or failure. Default: the browser's `alert`. */
9
- notify?: (message: string) => void;
11
+ /** Tells the user a command's outcome or failure. Default: the app's notice stack (`useNotify`). */
12
+ notify?: SidebarNotify;
10
13
  /** The app's components. */
11
14
  children: ReactNode;
12
15
  }
@@ -18,7 +21,7 @@ interface SidebarHostProviderProps {
18
21
  declare function SidebarHostProvider({ host, notify, children }: SidebarHostProviderProps): import("react").JSX.Element;
19
22
  /** The nearest {@link SidebarHost}; an empty host (every capability left out) outside a provider. */
20
23
  declare function useSidebarHost(): SidebarHost;
21
- /** How the nearest {@link SidebarHostProvider} tells the user something. */
22
- declare function useSidebarNotice(): (message: string) => void;
24
+ /** How the nearest {@link SidebarHostProvider} tells the user something: its `notify`, else the app's notice stack. */
25
+ declare function useSidebarNotice(): SidebarNotify;
23
26
  //#endregion
24
- export { SidebarHostProvider, SidebarHostProviderProps, useSidebarHost, useSidebarNotice };
27
+ export { SidebarHostProvider, SidebarHostProviderProps, SidebarNotify, useSidebarHost, useSidebarNotice };
@@ -1,27 +1,25 @@
1
+ import { useNotify } from "../../app/NoticeStack.js";
1
2
  import { jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useMemo } from "react";
3
+ import { createContext, useCallback, useContext, useMemo } from "react";
3
4
  //#region src/chat/sidebar/SidebarHostProvider.tsx
4
5
  /**
5
6
  * Puts a `SidebarHost` in context for the sidebar's rows and every other
6
7
  * surface that offers a session's menu (the session header), with the way
7
8
  * the app tells the user a command's outcome (`notify`).
8
9
  */
9
- const browserAlert = (message) => {
10
- globalThis.alert?.(message);
11
- };
12
10
  const SidebarHostContext = createContext({
13
11
  host: {},
14
- notify: browserAlert
12
+ notify: null
15
13
  });
16
14
  /**
17
15
  * Provides a {@link SidebarHost} to the sidebar and the session menus below.
18
16
  *
19
17
  * @param props - The `host`, an optional `notify` and the `children`.
20
18
  */
21
- function SidebarHostProvider({ host, notify = browserAlert, children }) {
19
+ function SidebarHostProvider({ host, notify = void 0, children }) {
22
20
  const value = useMemo(() => ({
23
21
  host,
24
- notify
22
+ notify: notify ?? null
25
23
  }), [host, notify]);
26
24
  return /* @__PURE__ */ jsx(SidebarHostContext.Provider, {
27
25
  value,
@@ -32,9 +30,15 @@ function SidebarHostProvider({ host, notify = browserAlert, children }) {
32
30
  function useSidebarHost() {
33
31
  return useContext(SidebarHostContext).host;
34
32
  }
35
- /** How the nearest {@link SidebarHostProvider} tells the user something. */
33
+ /** How the nearest {@link SidebarHostProvider} tells the user something: its `notify`, else the app's notice stack. */
36
34
  function useSidebarNotice() {
37
- return useContext(SidebarHostContext).notify;
35
+ const own = useContext(SidebarHostContext).notify;
36
+ const notify = useNotify();
37
+ const viaStack = useCallback((message, tone = "error") => notify({
38
+ tone,
39
+ message
40
+ }), [notify]);
41
+ return own ?? viaStack;
38
42
  }
39
43
  //#endregion
40
44
  export { SidebarHostProvider, useSidebarHost, useSidebarNotice };
@@ -11,12 +11,16 @@ import { jsx } from "react/jsx-runtime";
11
11
  function SidebarToggleButton({ collapsed: collapsedProp, onClick, className = "", style }) {
12
12
  const labels = useSidebarLabels();
13
13
  const budget = useLayoutBudgetOptional();
14
- const collapsed = collapsedProp || (budget?.sidebarForcedCollapsed ?? false);
14
+ const forced = budget?.sidebarForcedCollapsed ?? false;
15
+ const collapsed = forced ? !budget?.sidebarPeek : collapsedProp;
15
16
  return /* @__PURE__ */ jsx(IconButton, {
16
17
  icon: "i-ph-sidebar",
17
18
  label: collapsed ? labels.expandSidebar : labels.collapseSidebar,
18
- onClick,
19
- style,
19
+ onClick: forced ? () => budget?.peekSidebar(!budget.sidebarPeek) : onClick,
20
+ style: forced && budget?.sidebarPeek ? {
21
+ ...style,
22
+ zIndex: 51
23
+ } : style,
20
24
  className: `zg-hit-extend ${className}`
21
25
  });
22
26
  }
@@ -10,7 +10,7 @@ import { NewSessionButton, NewSessionButtonProps, SessionSidebar, SessionSidebar
10
10
  import { SidebarChip, SidebarChipProps, SidebarDecoration, SidebarDecorationProps } from "./SidebarDecoration.js";
11
11
  import { SidebarFilterMenu, SidebarFilterMenuProps } from "./SidebarFilterMenu.js";
12
12
  import { SidebarCompactingIndicator, SidebarCompactingIndicatorProps, SidebarFooter, SidebarFooterProps, SidebarSettingsNote, SidebarSignInPrompt, SidebarSignInPromptProps, SidebarUsageIndicator, SidebarUsageIndicatorProps } from "./SidebarFooter.js";
13
- import { SidebarHostProvider, SidebarHostProviderProps, useSidebarHost, useSidebarNotice } from "./SidebarHostProvider.js";
13
+ import { SidebarHostProvider, SidebarHostProviderProps, SidebarNotify, useSidebarHost, useSidebarNotice } from "./SidebarHostProvider.js";
14
14
  import { SidebarRowView, SidebarRowViewProps } from "./SidebarRowView.js";
15
15
  import { SidebarSearchRow, SidebarSearchRowProps } from "./SidebarSearchRow.js";
16
16
  import { SidebarRowHandlers, SidebarSessionRow, SidebarSessionRowProps } from "./SidebarSessionRow.js";
@@ -27,4 +27,4 @@ import { SessionDirectoryView, useSessionDirectoryView } from "./useSessionDirec
27
27
  import { useMainSession } from "./use-main-session.js";
28
28
  import { useSaveViewAsSpace } from "./useSaveViewAsSpace.js";
29
29
  import { SidebarKeyboardNavOptions, useSidebarKeyboardNav } from "./useSidebarKeyboardNav.js";
30
- export { ARRIVAL_MS, type BadgeCardPlacement, EnvironmentChip, type EnvironmentChipProps, ICON_PICKER_WIDTH, IconPicker, type IconPickerProps, MainSessionRow, type MainSessionRowProps, NewSessionButton, type NewSessionButtonProps, ProjectChip, type ProjectChipProps, ProjectIconButton, type ProjectIconButtonProps, ProjectIconGlyph, type ProjectIconGlyphProps, type RowProject, type SessionContentSearch, type SessionDirectoryView, type SessionMenuActions, type SessionMenuContext, type SessionMenuSurfaceActions, type SessionMenuTarget, SessionSidebar, type SessionSidebarProps, type SidebarBadgeFocus, SidebarChip, type SidebarChipProps, type SidebarChromeInset, type SidebarCollapsedStore, SidebarCompactingIndicator, type SidebarCompactingIndicatorProps, SidebarDecoration, type SidebarDecorationProps, SidebarFilterMenu, type SidebarFilterMenuProps, SidebarFooter, type SidebarFooterProps, SidebarFrame, type SidebarFrameOptions, type SidebarFrameProps, type SidebarFrameState, SidebarGroupHeader, type SidebarGroupHeaderProps, type SidebarHeaderRow, SidebarHostProvider, type SidebarHostProviderProps, type SidebarKeyboardNavOptions, type SidebarLive, type SidebarLiveOptions, type SidebarProject, type SidebarProjectRef, type SidebarRowArtifactsProps, type SidebarRowHandlers, type SidebarRowMetaProps, type SidebarRowSession, SidebarRowView, type SidebarRowViewProps, SidebarSearchRow, type SidebarSearchRowProps, SidebarSessionRow, type SidebarSessionRowProps, type SidebarSettingsNote, SidebarSignInPrompt, type SidebarSignInPromptProps, type SidebarSpaceSlide, SidebarToggleButton, type SidebarToggleButtonProps, SidebarUsageIndicator, type SidebarUsageIndicatorProps, SpaceGlyph, type SpaceGlyphProps, SpaceSwitcher, type SpaceSwitcherProps, SpacesSection, type SpacesSectionProps, archiveProjectPrompt, createSidebarCollapsed, createSidebarLive, deleteProjectPrompt, sessionMenuItems, spaceRows, useArrival, useCompactionProgress, useConfirmDeleteSession, useEnvironmentActions, useEnvironmentCommands, useMainSession, usePinnedProjects, useProjectIcons, useProjectSessionActions, useSaveViewAsSpace, useSessionActivity, useSessionBadges, useSessionDirectoryView, useSessionMenuItems, useSessionSearch, useSidebarFrame, useSidebarHost, useSidebarKeyboardNav, useSidebarLabels, useSidebarNotice };
30
+ export { ARRIVAL_MS, type BadgeCardPlacement, EnvironmentChip, type EnvironmentChipProps, ICON_PICKER_WIDTH, IconPicker, type IconPickerProps, MainSessionRow, type MainSessionRowProps, NewSessionButton, type NewSessionButtonProps, ProjectChip, type ProjectChipProps, ProjectIconButton, type ProjectIconButtonProps, ProjectIconGlyph, type ProjectIconGlyphProps, type RowProject, type SessionContentSearch, type SessionDirectoryView, type SessionMenuActions, type SessionMenuContext, type SessionMenuSurfaceActions, type SessionMenuTarget, SessionSidebar, type SessionSidebarProps, type SidebarBadgeFocus, SidebarChip, type SidebarChipProps, type SidebarChromeInset, type SidebarCollapsedStore, SidebarCompactingIndicator, type SidebarCompactingIndicatorProps, SidebarDecoration, type SidebarDecorationProps, SidebarFilterMenu, type SidebarFilterMenuProps, SidebarFooter, type SidebarFooterProps, SidebarFrame, type SidebarFrameOptions, type SidebarFrameProps, type SidebarFrameState, SidebarGroupHeader, type SidebarGroupHeaderProps, type SidebarHeaderRow, SidebarHostProvider, type SidebarHostProviderProps, type SidebarKeyboardNavOptions, type SidebarLive, type SidebarLiveOptions, type SidebarNotify, type SidebarProject, type SidebarProjectRef, type SidebarRowArtifactsProps, type SidebarRowHandlers, type SidebarRowMetaProps, type SidebarRowSession, SidebarRowView, type SidebarRowViewProps, SidebarSearchRow, type SidebarSearchRowProps, SidebarSessionRow, type SidebarSessionRowProps, type SidebarSettingsNote, SidebarSignInPrompt, type SidebarSignInPromptProps, type SidebarSpaceSlide, SidebarToggleButton, type SidebarToggleButtonProps, SidebarUsageIndicator, type SidebarUsageIndicatorProps, SpaceGlyph, type SpaceGlyphProps, SpaceSwitcher, type SpaceSwitcherProps, SpacesSection, type SpacesSectionProps, archiveProjectPrompt, createSidebarCollapsed, createSidebarLive, deleteProjectPrompt, sessionMenuItems, spaceRows, useArrival, useCompactionProgress, useConfirmDeleteSession, useEnvironmentActions, useEnvironmentCommands, useMainSession, usePinnedProjects, useProjectIcons, useProjectSessionActions, useSaveViewAsSpace, useSessionActivity, useSessionBadges, useSessionDirectoryView, useSessionMenuItems, useSessionSearch, useSidebarFrame, useSidebarHost, useSidebarKeyboardNav, useSidebarLabels, useSidebarNotice };
@@ -1,3 +1,4 @@
1
+ import { errorMessage } from "../../components/report-error.js";
1
2
  import { useSidebarHost, useSidebarNotice } from "./SidebarHostProvider.js";
2
3
  import { useLinkRouter } from "../../extensions/links.js";
3
4
  import { useConfirm } from "../../app/useConfirm.js";
@@ -163,7 +164,6 @@ function useEnvironmentActions(sessionId, enabled) {
163
164
  ]);
164
165
  return actions;
165
166
  }
166
- const messageOf = (err) => err?.message ?? String(err);
167
167
  /**
168
168
  * Running an environment command (open what it returns, else say what happened) and setting a failed
169
169
  * environment up again, worded through the labels and told with the provider's `notify`. Stable identities.
@@ -180,8 +180,8 @@ function useEnvironmentCommands() {
180
180
  source: "other",
181
181
  sessionId
182
182
  });
183
- else notify(result.message);
184
- }).catch((err) => notify(labels.environmentActionFailed(label, messageOf(err))));
183
+ else notify(result.message, "info");
184
+ }).catch((err) => notify(labels.environmentActionFailed(label, errorMessage(err))));
185
185
  }, [
186
186
  environment,
187
187
  notify,
@@ -189,7 +189,7 @@ function useEnvironmentCommands() {
189
189
  links
190
190
  ]);
191
191
  const retry = useCallback((sessionId) => {
192
- environment?.retry(sessionId).catch((err) => notify(labels.retryEnvironmentFailed(messageOf(err))));
192
+ environment?.retry(sessionId).catch((err) => notify(labels.retryEnvironmentFailed(errorMessage(err))));
193
193
  }, [
194
194
  environment,
195
195
  notify,
@@ -1,3 +1,4 @@
1
+ import { errorMessage } from "../../components/report-error.js";
1
2
  import { useSidebarNotice } from "./SidebarHostProvider.js";
2
3
  import { useSidebarLabels } from "./useSidebarLabels.js";
3
4
  import { nextSavedViewName } from "../headless/sidebar/query.js";
@@ -9,7 +10,6 @@ import { useCallback, useRef } from "react";
9
10
  * the user when the save fails (`labels.saveViewFailed` through the nearest
10
11
  * `SidebarHostProvider`'s `notify`), so every app saves views the same way.
11
12
  */
12
- const messageOf = (err) => err instanceof Error ? err.message : String(err);
13
13
  /**
14
14
  * The filter menu's `onSaveView` over a directory's `saveViewAsSpace`: saves the shown view under
15
15
  * the next free saved-view name; a failure (an invalid query, a settings write that failed) shows
@@ -36,7 +36,7 @@ function useSaveViewAsSpace(save, spaces) {
36
36
  const onSave = useCallback(() => {
37
37
  const { save: run, spaces: all, labels: words, notify: tell } = latest.current;
38
38
  if (!run) return;
39
- run(nextSavedViewName(all, words.savedViewName)).catch((err) => tell(words.saveViewFailed(messageOf(err))));
39
+ run(nextSavedViewName(all, words.savedViewName)).catch((err) => tell(words.saveViewFailed(errorMessage(err))));
40
40
  }, []);
41
41
  return save ? onSave : void 0;
42
42
  }
@@ -524,9 +524,9 @@ function describeChatHostContract(name, makeHarness, capabilities) {
524
524
  it.skipIf(!has("sessions", "sessions.onChanged", "sessions.rename"))("signals a changed session", async () => {
525
525
  const { host } = await setup();
526
526
  const seen = [];
527
- cleanup.push(host.sessions.onChanged((id) => seen.push(id)));
527
+ cleanup.push(host.sessions.onChanged((change) => seen.push(change.op === "delete" ? "" : change.row?.title ?? "")));
528
528
  await host.sessions.rename("c-2", "Renamed");
529
- await waitFor(() => expect(seen).toContain("c-2"));
529
+ await waitFor(() => expect(seen).toContain("Renamed"));
530
530
  });
531
531
  it.skipIf(!has("sessions", "sessions.views"))("keeps the sidebar views and the shown space", async () => {
532
532
  const { host } = await setup();
@@ -1,4 +1,5 @@
1
1
  import { buttonClass } from "../../components/button.js";
2
+ import { Notice } from "../../components/Notice.js";
2
3
  import "../../components/Form.js";
3
4
  import { useReadable } from "../headless/store.js";
4
5
  import { RoutedLink } from "../../extensions/links.js";
@@ -216,10 +217,11 @@ const AuthFailureCard = memo(function AuthFailureCard({ auth, text, detail, fail
216
217
  onCancel: signIn.cancel
217
218
  }) : flow?.kind === "error" ? /* @__PURE__ */ jsxs("div", {
218
219
  className: "flex flex-col gap-1.5",
219
- children: [/* @__PURE__ */ jsx("div", {
220
- role: "alert",
221
- className: "text-zg-danger break-words",
222
- children: labels.authFailed(flow.message)
220
+ children: [/* @__PURE__ */ jsx(Notice, {
221
+ tone: "error",
222
+ compact: true,
223
+ detail: flow.message,
224
+ children: labels.authSignInFailed
223
225
  }), /* @__PURE__ */ jsxs("div", {
224
226
  className: "flex flex-wrap items-center gap-1.5",
225
227
  children: [/* @__PURE__ */ jsx("button", {
@@ -236,10 +238,11 @@ const AuthFailureCard = memo(function AuthFailureCard({ auth, text, detail, fail
236
238
  })]
237
239
  }) : /* @__PURE__ */ jsxs("div", {
238
240
  className: "flex flex-col gap-1.5",
239
- children: [switching?.error !== void 0 && /* @__PURE__ */ jsx("div", {
240
- role: "alert",
241
- className: "text-zg-danger break-words",
242
- children: labels.authFailed(switching.error)
241
+ children: [switching?.error !== void 0 && /* @__PURE__ */ jsx(Notice, {
242
+ tone: "error",
243
+ compact: true,
244
+ detail: switching.error,
245
+ children: labels.authSignInFailed
243
246
  }), /* @__PURE__ */ jsxs("div", {
244
247
  className: "flex flex-wrap items-center gap-1.5",
245
248
  children: [
@@ -1,6 +1,8 @@
1
+ import { errorMessage } from "../../components/report-error.js";
1
2
  import { RowActionsMenu } from "../../components/RowActionsMenu.js";
2
3
  import { useOptionalChatHost } from "../ChatProvider.js";
3
4
  import { useExtensionsHost } from "../../extensions/ExtensionsProvider.js";
5
+ import { useNotify } from "../../app/NoticeStack.js";
4
6
  import { openInNewTab } from "../../extensions/headless/links.js";
5
7
  import { useLinkRouter } from "../../extensions/links.js";
6
8
  import { extensionsBadgeActions } from "../headless/extension-sources.js";
@@ -67,6 +69,7 @@ function BadgeMenuProvider({ composer, system, browser, children }) {
67
69
  const badges = useOptionalChatHost()?.badges ?? extensionsBadgeActions(extensions);
68
70
  const labels = useChatLabels();
69
71
  const links = useLinkRouter();
72
+ const notify = useNotify();
70
73
  const [open, setOpen] = useState(null);
71
74
  const [notice, setNotice] = useState(null);
72
75
  const seq = useRef(0);
@@ -124,7 +127,14 @@ function BadgeMenuProvider({ composer, system, browser, children }) {
124
127
  return;
125
128
  }
126
129
  (async () => {
127
- const text = await applyBadgeEffect(item.source === "builtin" ? builtinBadgeEffect(item.id, target) ?? {} : await (badges?.run(cwd, item.source, item.id, target) ?? Promise.resolve({})).catch((err) => ({ notice: err instanceof Error ? err.message : String(err) })), {
130
+ const text = await applyBadgeEffect(item.source === "builtin" ? builtinBadgeEffect(item.id, target) ?? {} : await (badges?.run(cwd, item.source, item.id, target) ?? Promise.resolve({})).catch((err) => {
131
+ notify({
132
+ tone: "error",
133
+ message: labels.badgeActionFailed,
134
+ detail: errorMessage(err)
135
+ });
136
+ return {};
137
+ }), {
128
138
  target,
129
139
  cwd,
130
140
  builtin: item.source === "builtin" ? item.id : null,
@@ -148,7 +158,8 @@ function BadgeMenuProvider({ composer, system, browser, children }) {
148
158
  system,
149
159
  browser,
150
160
  labels,
151
- links
161
+ links,
162
+ notify
152
163
  ]);
153
164
  return /* @__PURE__ */ jsxs(BadgeMenuContext.Provider, {
154
165
  value: show,
@@ -1,3 +1,4 @@
1
+ import { Notice } from "../../components/Notice.js";
1
2
  import { CodeFrame } from "../../components/CodeFrame.js";
2
3
  import { useNearViewport } from "../../hooks/useNearViewport.js";
3
4
  import { HighlightedCode } from "../../code/HighlightedCode.js";
@@ -159,9 +160,12 @@ const MermaidDiagram = memo(function MermaidDiagram({ code, streaming = false, c
159
160
  language: "mermaid",
160
161
  className: "mb-1",
161
162
  copyLabel: labels.copyDiagramSource
162
- }), /* @__PURE__ */ jsx("p", {
163
- className: "zg-meta m-0 mb-2 whitespace-pre-wrap",
164
- children: labels.diagramError(failed.message, at)
163
+ }), /* @__PURE__ */ jsx(Notice, {
164
+ tone: "warning",
165
+ compact: true,
166
+ detail: failed.message,
167
+ className: "mb-2",
168
+ children: labels.diagramNotDrawn(at)
165
169
  })]
166
170
  });
167
171
  }
@@ -41,6 +41,10 @@ interface FoldHeaderProps {
41
41
  * a toggle with its caret when opening shows something more, otherwise the
42
42
  * same line, inert. Same box, tone and spacing either way.
43
43
  *
44
+ * One element in both states: swapping a `<div>` for a `<button>` remounted
45
+ * the line's content, so a live fold turning expandable (its 4th step) replayed
46
+ * the enter of everything in it, its elapsed chip popping in again.
47
+ *
44
48
  * @param props - Header props: `expandable`, `open`, `onToggle`, and the `children` of the line.
45
49
  */
46
50
  declare function FoldHeader({ expandable, open, onToggle, children, className, style }: FoldHeaderProps): import("react").JSX.Element;
@@ -187,23 +187,35 @@ function FoldOutcomes({ ok, failed }) {
187
187
  * a toggle with its caret when opening shows something more, otherwise the
188
188
  * same line, inert. Same box, tone and spacing either way.
189
189
  *
190
+ * One element in both states: swapping a `<div>` for a `<button>` remounted
191
+ * the line's content, so a live fold turning expandable (its 4th step) replayed
192
+ * the enter of everything in it, its elapsed chip popping in again.
193
+ *
190
194
  * @param props - Header props: `expandable`, `open`, `onToggle`, and the `children` of the line.
191
195
  */
192
196
  function FoldHeader({ expandable, open, onToggle, children, className, style }) {
193
197
  const line = "flex items-baseline gap-2 h-[22.4px] min-w-0 max-w-full text-[var(--zg-text-muted)]";
194
- if (!expandable) return /* @__PURE__ */ jsx("div", {
195
- "data-testid": "fold-head",
196
- className: [line, className].filter(Boolean).join(" "),
197
- style,
198
- children
199
- });
200
- return /* @__PURE__ */ jsxs("button", {
201
- type: "button",
202
- onClick: onToggle,
198
+ const toggle = expandable ? {
199
+ role: "button",
200
+ tabIndex: 0,
203
201
  "aria-expanded": open,
204
- className: [`zg-disclosure zg-press-subtle ${line}`, className].filter(Boolean).join(" "),
202
+ onClick: onToggle,
203
+ onKeyDown: (e) => {
204
+ if (e.key !== "Enter" && e.key !== " ") return;
205
+ e.preventDefault();
206
+ onToggle();
207
+ }
208
+ } : {};
209
+ return /* @__PURE__ */ jsxs("div", {
210
+ "data-testid": "fold-head",
211
+ className: [
212
+ expandable ? "zg-disclosure zg-press-subtle" : "",
213
+ line,
214
+ className
215
+ ].filter(Boolean).join(" "),
205
216
  style,
206
- children: [children, /* @__PURE__ */ jsx(Caret, {
217
+ ...toggle,
218
+ children: [children, expandable && /* @__PURE__ */ jsx(Caret, {
207
219
  open,
208
220
  className: "shrink-0 self-center"
209
221
  })]
@@ -224,6 +236,7 @@ function FoldActions({ items, all, openIds, onToggle, renderRows }) {
224
236
  children: items.map((item) => /* @__PURE__ */ jsx(Grow, {
225
237
  as: "li",
226
238
  appear: !firstIds.has(item.id),
239
+ symmetric: !all,
227
240
  className: "-mx-1.5 px-1.5",
228
241
  children: /* @__PURE__ */ jsx("div", {
229
242
  className: "pt-[var(--zg-fold-gap)]",
@@ -260,20 +273,38 @@ function ActionWithDetails({ item, openIds, onToggle, renderRows }) {
260
273
  })
261
274
  })
262
275
  }),
263
- item.children && item.children.length > 0 && /* @__PURE__ */ jsx("ul", {
264
- className: "list-none m-0 p-0 pl-7",
265
- "data-testid": "fold-action-children",
266
- children: item.children.map((child) => /* @__PURE__ */ jsx("li", {
267
- className: "pt-[var(--zg-fold-gap)]",
268
- children: /* @__PURE__ */ jsx(ActionWithDetails, {
269
- item: child,
270
- openIds,
271
- onToggle,
272
- renderRows
276
+ item.children && item.children.length > 0 && /* @__PURE__ */ jsx(ActionChildren, {
277
+ items: item.children,
278
+ openIds,
279
+ onToggle,
280
+ renderRows
281
+ })
282
+ ] });
283
+ }
284
+ /** The calls an action made, one step in. A call made after the list showed grows in instead of snapping the rows below down. */
285
+ function ActionChildren({ items, openIds, onToggle, renderRows }) {
286
+ const [firstIds] = useState(() => new Set(items.map((i) => i.id)));
287
+ return /* @__PURE__ */ jsx("ul", {
288
+ className: "list-none m-0 p-0 pl-7",
289
+ "data-testid": "fold-action-children",
290
+ children: /* @__PURE__ */ jsx(GrowPresence, {
291
+ initial: false,
292
+ children: items.map((child) => /* @__PURE__ */ jsx(Grow, {
293
+ as: "li",
294
+ appear: !firstIds.has(child.id),
295
+ className: "-mx-1.5 px-1.5",
296
+ children: /* @__PURE__ */ jsx("div", {
297
+ className: "pt-[var(--zg-fold-gap)]",
298
+ children: /* @__PURE__ */ jsx(ActionWithDetails, {
299
+ item: child,
300
+ openIds,
301
+ onToggle,
302
+ renderRows
303
+ })
273
304
  })
274
305
  }, child.id))
275
306
  })
276
- ] });
307
+ });
277
308
  }
278
309
  /** The item or one of the calls nested under it has its details open. */
279
310
  function openWithin(item, openIds) {
@@ -1,6 +1,6 @@
1
1
  import { ToolRowModel } from "../headless/transcript/rows.js";
2
2
  import "../headless/transcript/index.js";
3
- import { Yw as ScriptProgress } from "../../dist/index-Bq87OcGy.js";
3
+ import { iT as ScriptProgress } from "../../dist/index-C6rzc-tt.js";
4
4
  //#region src/chat/transcript/script-input.d.ts
5
5
  /**
6
6
  * A tool row's progress and how it ended, as `ToolInput` takes them for a Codemode script.