zidane-ui 9.1.3 → 9.1.5

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 (238) hide show
  1. package/dist/adapters/server-extensions-host.js +1 -1
  2. package/dist/adapters/server-host.js +2 -1
  3. package/dist/adapters/server-machines-host.js +1 -1
  4. package/dist/adapters/server-session-host.js +87 -13
  5. package/dist/adapters/server-settings-host.js +1 -1
  6. package/dist/appearance/AppearanceProvider.js +2 -2
  7. package/dist/appearance/headless/index.js +1 -1
  8. package/dist/approvals/headless/index.js +2 -2
  9. package/dist/chat/HostTranscript.d.ts +5 -1
  10. package/dist/chat/HostTranscript.js +16 -4
  11. package/dist/chat/RunEstimateChip.d.ts +5 -3
  12. package/dist/chat/RunEstimateChip.js +33 -3
  13. package/dist/chat/Transcript.js +1 -1
  14. package/dist/chat/composer/ComposerEditor.js +1 -1
  15. package/dist/chat/composer/ConversationBadges.js +16 -10
  16. package/dist/chat/composer/composer-bus.d.ts +2 -2
  17. package/dist/chat/composer/composer-bus.js +2 -2
  18. package/dist/chat/composer/use-composer-stores.js +1 -1
  19. package/dist/chat/composer/use-run-meter.js +1 -1
  20. package/dist/chat/headless/composer/conversation-badges.d.ts +8 -3
  21. package/dist/chat/headless/composer/conversation-badges.js +26 -11
  22. package/dist/chat/headless/composer/index.js +2 -2
  23. package/dist/chat/headless/composer/labels-chrome.d.ts +3 -1
  24. package/dist/chat/headless/composer/labels-chrome.js +3 -1
  25. package/dist/chat/headless/index.d.ts +5 -3
  26. package/dist/chat/headless/index.js +17 -15
  27. package/dist/chat/headless/labels.d.ts +54 -1
  28. package/dist/chat/headless/labels.js +62 -2
  29. package/dist/chat/headless/secrets.d.ts +32 -0
  30. package/dist/chat/headless/secrets.js +43 -0
  31. package/dist/chat/headless/session-list.d.ts +45 -0
  32. package/dist/chat/headless/sidebar/estimates.js +13 -1
  33. package/dist/chat/headless/sidebar/index.d.ts +2 -2
  34. package/dist/chat/headless/sidebar/index.js +1 -1
  35. package/dist/chat/headless/sidebar/labels.d.ts +50 -0
  36. package/dist/chat/headless/sidebar/labels.js +1 -0
  37. package/dist/chat/headless/sidebar/query.d.ts +2 -2
  38. package/dist/chat/headless/sidebar/query.js +6 -3
  39. package/dist/chat/headless/sidebar/types.d.ts +7 -1
  40. package/dist/chat/headless/sidebar/view.js +2 -0
  41. package/dist/chat/headless/transcript/auth-failure.d.ts +67 -0
  42. package/dist/chat/headless/transcript/auth-failure.js +87 -0
  43. package/dist/chat/headless/transcript/index.d.ts +2 -1
  44. package/dist/chat/headless/transcript/index.js +2 -1
  45. package/dist/chat/headless/transcript/nesting.d.ts +3 -3
  46. package/dist/chat/headless/transcript/nesting.js +12 -4
  47. package/dist/chat/index.d.ts +4 -2
  48. package/dist/chat/index.js +3 -1
  49. package/dist/chat/interactions/InboxPanel.d.ts +6 -2
  50. package/dist/chat/interactions/InboxPanel.js +82 -44
  51. package/dist/chat/interactions/PlanCard.d.ts +2 -2
  52. package/dist/chat/interactions/PlanCard.js +1 -1
  53. package/dist/chat/interactions/QuestionField.d.ts +8 -3
  54. package/dist/chat/interactions/QuestionField.js +89 -8
  55. package/dist/chat/interactions/QuestionForm.d.ts +3 -1
  56. package/dist/chat/interactions/QuestionForm.js +48 -10
  57. package/dist/chat/interactions/SecretInput.d.ts +32 -0
  58. package/dist/chat/interactions/SecretInput.js +72 -0
  59. package/dist/chat/interactions/card-ui.d.ts +5 -3
  60. package/dist/chat/interactions/card-ui.js +5 -3
  61. package/dist/chat/interactions/index.d.ts +2 -1
  62. package/dist/chat/interactions/index.js +2 -1
  63. package/dist/chat/sidebar/SessionSidebar.js +2 -0
  64. package/dist/chat/sidebar/SidebarFilterMenu.d.ts +7 -2
  65. package/dist/chat/sidebar/SidebarFilterMenu.js +26 -2
  66. package/dist/chat/sidebar/SidebarSessionRow.d.ts +3 -1
  67. package/dist/chat/sidebar/SidebarSessionRow.js +8 -3
  68. package/dist/chat/sidebar/sidebar-live.js +8 -4
  69. package/dist/chat/transcript/AuthFailureCard.d.ts +34 -0
  70. package/dist/chat/transcript/AuthFailureCard.js +358 -0
  71. package/dist/chat/transcript/InteractionToolBody.js +12 -2
  72. package/dist/chat/transcript/actions.d.ts +24 -1
  73. package/dist/chat/transcript/index.d.ts +3 -2
  74. package/dist/chat/transcript/index.js +2 -1
  75. package/dist/chat/transcript/notices.d.ts +2 -1
  76. package/dist/chat/transcript/notices.js +13 -1
  77. package/dist/chat/transcript/script-input.d.ts +1 -1
  78. package/dist/chat/transcript/shell-block.js +1 -1
  79. package/dist/components/HowItWorks.d.ts +8 -1
  80. package/dist/components/HowItWorks.js +2 -2
  81. package/dist/components/RowActionsMenu.d.ts +6 -1
  82. package/dist/components/RowActionsMenu.js +4 -0
  83. package/dist/core.css +24 -0
  84. package/dist/dist/{index-WlE93Q6d.d.ts → index-BI6RZc60.d.ts} +36 -3
  85. package/dist/dist/index-f-XWIoYo.d.ts +1 -0
  86. package/dist/dist/index.d.ts +6 -0
  87. package/dist/dist/sandbox-B4OW6oNx.d.ts +2 -0
  88. package/dist/dist/timeout-B5pO5I5a.d.ts +30 -0
  89. package/dist/extensions/ExtensionSettingsPage.js +1 -1
  90. package/dist/extensions/ExtensionSettingsSidebar.js +1 -1
  91. package/dist/extensions/headless/fixture-host.js +1 -1
  92. package/dist/extensions/headless/index.js +4 -4
  93. package/dist/extensions/hooks.js +1 -1
  94. package/dist/files/DiffsTab.js +1 -1
  95. package/dist/files/EditorColumn.js +1 -1
  96. package/dist/files/MediaDiff.js +1 -1
  97. package/dist/files/SearchPanel.js +121 -53
  98. package/dist/files/headless/name-match.js +29 -14
  99. package/dist/files/useEntryActions.js +1 -1
  100. package/dist/files/useOpenFiles.js +1 -1
  101. package/dist/git/WherePicker.js +2 -2
  102. package/dist/git/headless/environment.d.ts +6 -1
  103. package/dist/git/headless/environment.js +5 -2
  104. package/dist/git/headless/labels.d.ts +2 -0
  105. package/dist/git/headless/labels.js +2 -0
  106. package/dist/git/index.d.ts +2 -1
  107. package/dist/git/index.js +2 -1
  108. package/dist/git/useStartFromPanel.d.ts +22 -0
  109. package/dist/git/useStartFromPanel.js +91 -0
  110. package/dist/keybindings/KeyCommands.js +1 -1
  111. package/dist/keybindings/KeybindingsProvider.js +1 -1
  112. package/dist/keybindings/headless/catalog.js +2 -2
  113. package/dist/keybindings/headless/index.js +2 -2
  114. package/dist/keybindings/headless/overrides.js +1 -1
  115. package/dist/machines/HostSyncPanel.js +1 -1
  116. package/dist/machines/SyncOutcomeBadge.js +1 -1
  117. package/dist/machines/headless/index.js +1 -1
  118. package/dist/onboarding/demos/features.d.ts +9 -1
  119. package/dist/onboarding/demos/features.js +107 -2
  120. package/dist/onboarding/demos/how-it-works.d.ts +5 -1
  121. package/dist/onboarding/demos/how-it-works.js +120 -2
  122. package/dist/onboarding/headless/labels.d.ts +17 -0
  123. package/dist/onboarding/headless/labels.js +17 -0
  124. package/dist/onboarding/index.js +1 -1
  125. package/dist/onboarding/marks.d.ts +1 -2
  126. package/dist/onboarding/marks.js +4 -12
  127. package/dist/onboarding/steps/ReadyStep.js +1 -1
  128. package/dist/onboarding/steps/connect/ProviderPanel.js +1 -1
  129. package/dist/onboarding/tutorials.d.ts +3 -1
  130. package/dist/onboarding/tutorials.js +2 -1
  131. package/dist/palette/app-sources.js +1 -1
  132. package/dist/session/ArtifactsPanel.js +1 -1
  133. package/dist/session/PanelAttention.d.ts +14 -6
  134. package/dist/session/PanelAttention.js +35 -24
  135. package/dist/session/PlanTracker.d.ts +54 -0
  136. package/dist/session/PlanTracker.js +412 -0
  137. package/dist/session/ProjectHome.d.ts +15 -2
  138. package/dist/session/ProjectHome.js +158 -85
  139. package/dist/session/RemindersPanel.d.ts +25 -0
  140. package/dist/session/RemindersPanel.js +526 -0
  141. package/dist/session/SecretsPanel.d.ts +19 -0
  142. package/dist/session/SecretsPanel.js +241 -0
  143. package/dist/session/SessionProvider.d.ts +26 -5
  144. package/dist/session/SessionProvider.js +51 -6
  145. package/dist/session/StepStatusIcon.d.ts +24 -0
  146. package/dist/session/StepStatusIcon.js +50 -0
  147. package/dist/session/TodoList.d.ts +4 -3
  148. package/dist/session/TodoList.js +6 -5
  149. package/dist/session/headless/fixture-host.d.ts +32 -22
  150. package/dist/session/headless/fixture-host.js +86 -51
  151. package/dist/session/headless/fixture-plans.d.ts +57 -0
  152. package/dist/session/headless/fixture-plans.js +141 -0
  153. package/dist/session/headless/fixture-schedules.d.ts +49 -0
  154. package/dist/session/headless/fixture-schedules.js +133 -0
  155. package/dist/session/headless/home-layout.d.ts +10 -2
  156. package/dist/session/headless/home-layout.js +7 -2
  157. package/dist/session/headless/host.d.ts +85 -13
  158. package/dist/session/headless/index.d.ts +5 -3
  159. package/dist/session/headless/index.js +6 -4
  160. package/dist/session/headless/labels.d.ts +95 -12
  161. package/dist/session/headless/labels.js +67 -18
  162. package/dist/session/headless/plans.d.ts +53 -0
  163. package/dist/session/headless/plans.js +78 -0
  164. package/dist/session/headless/reminder-labels.d.ts +63 -0
  165. package/dist/session/headless/reminder-labels.js +84 -0
  166. package/dist/session/headless/schedules.d.ts +93 -0
  167. package/dist/session/headless/schedules.js +190 -0
  168. package/dist/session/headless/secrets.d.ts +28 -0
  169. package/dist/session/headless/secrets.js +48 -0
  170. package/dist/session/index.d.ts +7 -5
  171. package/dist/session/index.js +6 -4
  172. package/dist/session/testing/contract.d.ts +18 -5
  173. package/dist/session/testing/contract.js +351 -43
  174. package/dist/session/testing/index.d.ts +4 -2
  175. package/dist/session/testing/index.js +4 -2
  176. package/dist/settings/headless/catalog.js +17 -1
  177. package/dist/settings/headless/index.d.ts +2 -2
  178. package/dist/settings/headless/index.js +3 -3
  179. package/dist/settings/headless/labels.d.ts +0 -2
  180. package/dist/settings/headless/labels.js +0 -2
  181. package/dist/settings/headless/layout.js +7 -1
  182. package/dist/settings/headless/providers.d.ts +17 -1
  183. package/dist/settings/headless/providers.js +19 -1
  184. package/dist/settings/headless/search.d.ts +1 -1
  185. package/dist/settings/rows.d.ts +1 -1
  186. package/dist/settings/rows.js +2 -2
  187. package/dist/settings/sections/appearance/AppearanceSection.js +2 -2
  188. package/dist/settings/sections/claude-import/ClaudeImportDialog.js +1 -1
  189. package/dist/settings/sections/editor/EditorSection.js +1 -1
  190. package/dist/settings/sections/environments/EnvironmentsSection.js +1 -1
  191. package/dist/settings/sections/extensions/ChangeOriginDialog.js +1 -1
  192. package/dist/settings/sections/extensions/CreateExtensionDialog.js +1 -1
  193. package/dist/settings/sections/extensions/ExtensionsSection.js +1 -1
  194. package/dist/settings/sections/host-catalog/HostCatalogSection.js +1 -1
  195. package/dist/settings/sections/instructions/InstructionsSection.js +1 -1
  196. package/dist/settings/sections/mcp/McpSection.js +1 -1
  197. package/dist/settings/sections/mcp/McpServerRow.js +1 -1
  198. package/dist/settings/sections/models/ModelRows.js +1 -1
  199. package/dist/settings/sections/providers/ProvidersSection.js +209 -201
  200. package/dist/settings/sections/providers/ServerProvidersSection.js +1 -1
  201. package/dist/settings/sections/shared/catalog.js +1 -1
  202. package/dist/settings/sections/skills/SkillsSection.js +1 -1
  203. package/dist/styles.css +59 -1
  204. package/dist/terminal/HostTerminalSurface.js +2 -2
  205. package/dist/workspace/PanelContentView.d.ts +22 -4
  206. package/dist/workspace/PanelContentView.js +112 -16
  207. package/dist/workspace/PanelGlyph.d.ts +21 -0
  208. package/dist/workspace/PanelGlyph.js +33 -0
  209. package/dist/workspace/PanelHome.js +5 -3
  210. package/dist/workspace/PanelStrip.js +11 -4
  211. package/dist/workspace/PanelToolbar.d.ts +32 -0
  212. package/dist/workspace/PanelToolbar.js +194 -0
  213. package/dist/workspace/WorkspaceProvider.d.ts +3 -1
  214. package/dist/workspace/WorkspaceProvider.js +6 -2
  215. package/dist/workspace/extension-tabs.js +5 -2
  216. package/dist/workspace/headless/host.d.ts +4 -0
  217. package/dist/workspace/headless/index.d.ts +3 -1
  218. package/dist/workspace/headless/index.js +4 -2
  219. package/dist/workspace/headless/labels.d.ts +10 -0
  220. package/dist/workspace/headless/labels.js +11 -1
  221. package/dist/workspace/headless/pages.d.ts +15 -0
  222. package/dist/workspace/headless/pages.js +49 -0
  223. package/dist/workspace/headless/tab-mark.d.ts +14 -0
  224. package/dist/workspace/headless/tab-mark.js +27 -0
  225. package/dist/workspace/headless/view.d.ts +7 -1
  226. package/dist/workspace/index.d.ts +3 -2
  227. package/dist/workspace/index.js +3 -2
  228. package/dist/workspace/testing/index.js +6 -0
  229. package/dist/workspace/workspace-key-commands.js +3 -3
  230. package/package.json +2 -2
  231. package/src/styles/motion.css +13 -0
  232. package/src/styles/onboarding.css +0 -1
  233. package/src/styles/primitives.css +10 -0
  234. package/src/styles/workspace.css +17 -0
  235. package/dist/session/TodosPanel.d.ts +0 -19
  236. package/dist/session/TodosPanel.js +0 -251
  237. package/dist/session/headless/todos.d.ts +0 -22
  238. package/dist/session/headless/todos.js +0 -38
@@ -5,4 +5,5 @@ import { InteractionCard, InteractionCardProps } from "./InteractionCard.js";
5
5
  import { PlanBody, PlanBodyProps, PlanCard, PlanCardProps } from "./PlanCard.js";
6
6
  import { QuestionField, QuestionFieldProps, isRequired } from "./QuestionField.js";
7
7
  import { AnsweredQuestions, AnsweredQuestionsProps, QuestionForm, QuestionFormProps, seedDefaults } from "./QuestionForm.js";
8
- export { AnsweredQuestions, AnsweredQuestionsProps, HostInteractions, HostInteractionsProps, InboxPanel, InboxPanelProps, InteractionCard, InteractionCardProps, PlanBody, PlanBodyProps, PlanCard, PlanCardProps, QuestionField, QuestionFieldProps, QuestionForm, QuestionFormProps, isRequired, seedDefaults, useAllInteractions, useInteractionHead, usePendingInteractions };
8
+ import { SecretInput, SecretInputProps } from "./SecretInput.js";
9
+ export { AnsweredQuestions, AnsweredQuestionsProps, HostInteractions, HostInteractionsProps, InboxPanel, InboxPanelProps, InteractionCard, InteractionCardProps, PlanBody, PlanBodyProps, PlanCard, PlanCardProps, QuestionField, QuestionFieldProps, QuestionForm, QuestionFormProps, SecretInput, SecretInputProps, isRequired, seedDefaults, useAllInteractions, useInteractionHead, usePendingInteractions };
@@ -1,8 +1,9 @@
1
1
  import { useAllInteractions, useInteractionHead, usePendingInteractions } from "./hooks.js";
2
2
  import { PlanBody, PlanCard } from "./PlanCard.js";
3
+ import { SecretInput } from "./SecretInput.js";
3
4
  import { QuestionField, isRequired } from "./QuestionField.js";
4
5
  import { AnsweredQuestions, QuestionForm, seedDefaults } from "./QuestionForm.js";
5
6
  import { InteractionCard } from "./InteractionCard.js";
6
7
  import { HostInteractions } from "./HostInteractions.js";
7
8
  import { InboxPanel } from "./InboxPanel.js";
8
- export { AnsweredQuestions, HostInteractions, InboxPanel, InteractionCard, PlanBody, PlanCard, QuestionField, QuestionForm, isRequired, seedDefaults, useAllInteractions, useInteractionHead, usePendingInteractions };
9
+ export { AnsweredQuestions, HostInteractions, InboxPanel, InteractionCard, PlanBody, PlanCard, QuestionField, QuestionForm, SecretInput, isRequired, seedDefaults, useAllInteractions, useInteractionHead, usePendingInteractions };
@@ -525,6 +525,7 @@ function SessionSidebar(props) {
525
525
  isRenaming,
526
526
  archived: session.archived === true,
527
527
  favorite: session.favorite,
528
+ scheduled: Boolean(session.scheduleId),
528
529
  renameValue: isRenaming ? renameValue : "",
529
530
  menuOpen: menuForId === session.id,
530
531
  ...rowHandlers,
@@ -548,6 +549,7 @@ function SessionSidebar(props) {
548
549
  isRenaming: session.id === renamingId,
549
550
  archived: session.archived === true,
550
551
  favorite: session.favorite,
552
+ scheduled: Boolean(session.scheduleId),
551
553
  renameValue: session.id === renamingId ? renameValue : "",
552
554
  menuOpen: menuForId === session.id,
553
555
  ...rowHandlers,
@@ -20,17 +20,22 @@ interface SidebarFilterMenuProps {
20
20
  * and groupings join the menu, and the space's own grouping and sort are a choice.
21
21
  */
22
22
  query?: Pick<SidebarQueryLayer, 'space' | 'filters' | 'sorts' | 'groups'>;
23
+ /**
24
+ * Offer the Origin filter: All, Scheduled (a reminder started the session), Not scheduled. Pass it while
25
+ * reminders are on. A view that has an origin picked shows the row anyway, so it can be cleared.
26
+ */
27
+ origin?: boolean;
23
28
  /** Saves the view as a space of its own. Absent: no such row. */
24
29
  onSaveView?: () => void;
25
30
  /** Extra classes on the trigger button. */
26
31
  className?: string;
27
32
  }
28
33
  /**
29
- * The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, sort,
34
+ * The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, origin, sort,
30
35
  * and what extensions contribute (filters, sorts, groupings), with Save view as space.
31
36
  *
32
37
  * @param props - The {@link SidebarFilterMenuProps}.
33
38
  */
34
- declare function SidebarFilterMenu({ view, projects, onChange, hosts, agents, agentNames: agentNamesProp, query, onSaveView, className }: SidebarFilterMenuProps): import("react").JSX.Element;
39
+ declare function SidebarFilterMenu({ view, projects, onChange, hosts, agents, agentNames: agentNamesProp, query, origin, onSaveView, className }: SidebarFilterMenuProps): import("react").JSX.Element;
35
40
  //#endregion
36
41
  export { SidebarFilterMenu, SidebarFilterMenuProps };
@@ -26,6 +26,12 @@ const SORTS = [
26
26
  "recency"
27
27
  ];
28
28
  const ALL_AGENTS = "__all__";
29
+ const ALL_ORIGINS = "all";
30
+ const ORIGIN_CHOICES = [
31
+ ALL_ORIGINS,
32
+ "scheduled",
33
+ "unscheduled"
34
+ ];
29
35
  const ANY = "__any__";
30
36
  const SPACE = "@space";
31
37
  const NO_GROUPS = [];
@@ -43,12 +49,12 @@ function withExtension(view, change) {
43
49
  return out;
44
50
  }
45
51
  /**
46
- * The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, sort,
52
+ * The sidebar's filter axes in the kit's filter menu: view, status, project, activity, agent, origin, sort,
47
53
  * and what extensions contribute (filters, sorts, groupings), with Save view as space.
48
54
  *
49
55
  * @param props - The {@link SidebarFilterMenuProps}.
50
56
  */
51
- function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, agentNames: agentNamesProp, query, onSaveView, className }) {
57
+ function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, agentNames: agentNamesProp, query, origin = false, onSaveView, className }) {
52
58
  const labels = useChatLabels();
53
59
  const catalogNames = useAgentNames();
54
60
  const agentNames = agentNamesProp ?? catalogNames;
@@ -209,6 +215,23 @@ function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, ag
209
215
  onChange: (next) => onChange({ agent: next === ALL_AGENTS ? null : next })
210
216
  });
211
217
  }
218
+ if (origin || view.origin) {
219
+ const current = view.origin ?? ALL_ORIGINS;
220
+ out.push({
221
+ kind: "choice",
222
+ id: "origin",
223
+ label: labels.filterOrigin,
224
+ placement: "filter",
225
+ value: labels.filterOrigins[current],
226
+ atDefault: !view.origin,
227
+ options: ORIGIN_CHOICES.map((id) => ({
228
+ id,
229
+ label: labels.filterOrigins[id]
230
+ })),
231
+ current,
232
+ onChange: (next) => onChange({ origin: next === ALL_ORIGINS ? null : next })
233
+ });
234
+ }
212
235
  return out;
213
236
  }, [
214
237
  view,
@@ -222,6 +245,7 @@ function SidebarFilterMenu({ view, projects, onChange, hosts = false, agents, ag
222
245
  query,
223
246
  agents,
224
247
  agentNames,
248
+ origin,
225
249
  labels,
226
250
  onChange
227
251
  ]);
@@ -60,6 +60,8 @@ interface SidebarSessionRowProps extends SidebarRowHandlers {
60
60
  archived: boolean;
61
61
  /** Starred. */
62
62
  favorite?: boolean;
63
+ /** A reminder started it (zidane's `scheduleId`): a clock mark beside the title. */
64
+ scheduled?: boolean;
63
65
  /** The rename field's text. */
64
66
  renameValue: string;
65
67
  /** Its menu is the open one. */
@@ -90,6 +92,6 @@ interface SidebarSessionRowProps extends SidebarRowHandlers {
90
92
  style?: CSSProperties;
91
93
  }
92
94
  /** Renders one session of the sidebar list. Memoized: keep every prop stable. */
93
- declare const SidebarSessionRow: import("react").MemoExoticComponent<({ sessionId, title, cwd, hostId, hostBadge, spaceId, isMain, isActive, isRenaming, archived, favorite, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }: SidebarSessionRowProps) => import("react").JSX.Element>;
95
+ declare const SidebarSessionRow: import("react").MemoExoticComponent<({ sessionId, title, cwd, hostId, hostBadge, spaceId, isMain, isActive, isRenaming, archived, favorite, scheduled, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }: SidebarSessionRowProps) => import("react").JSX.Element>;
94
96
  //#endregion
95
97
  export { SidebarRowHandlers, SidebarSessionRow, SidebarSessionRowProps };
@@ -32,7 +32,7 @@ const ExcerptHighlight = memo(({ text, query }) => {
32
32
  });
33
33
  ExcerptHighlight.displayName = "ExcerptHighlight";
34
34
  /** Renders one session of the sidebar list. Memoized: keep every prop stable. */
35
- const SidebarSessionRow = memo(({ sessionId, title, cwd, hostId, hostBadge = true, spaceId, isMain, isActive, isRenaming, archived, favorite = false, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }) => {
35
+ const SidebarSessionRow = memo(({ sessionId, title, cwd, hostId, hostBadge = true, spaceId, isMain, isActive, isRenaming, archived, favorite = false, scheduled = false, renameValue, menuOpen, onSelect, onRenameValueChange, onRenameCommit, onRenameCancel, onStartRename, onDelete, onSetArchived, onSetFavorite, onRetryEnvironment, onRunEnvironmentAction, onMoveToSpace, onMoveSession, onOpenMenu, onCloseMenu, excerpt, excerptQuery, project, updatedAt, environment, runDetails, artifactBadges, spaces, live, decoration, className, style }) => {
36
36
  const { SessionStatusDot, RowMeta, RowArtifacts } = live;
37
37
  const host = useSidebarHost();
38
38
  const labels = useSidebarLabels();
@@ -106,10 +106,15 @@ const SidebarSessionRow = memo(({ sessionId, title, cwd, hostId, hostBadge = tru
106
106
  surface: "title",
107
107
  links: false
108
108
  }) : void 0,
109
- ...decoration && (decoration.icon || decoration.chips.length > 0 || decoration.component) ? { badges: /* @__PURE__ */ jsx(SidebarDecoration, {
109
+ ...scheduled || decoration && (decoration.icon || decoration.chips.length > 0 || decoration.component) ? { badges: /* @__PURE__ */ jsxs(Fragment, { children: [scheduled && /* @__PURE__ */ jsx("span", {
110
+ role: "img",
111
+ "aria-label": labels.rowScheduled,
112
+ title: labels.rowScheduled,
113
+ className: "i-ph-clock shrink-0 text-zg-label text-[var(--zg-text-muted)]"
114
+ }), decoration && /* @__PURE__ */ jsx(SidebarDecoration, {
110
115
  decoration,
111
116
  sessionId
112
- }) } : {},
117
+ })] }) } : {},
113
118
  meta: typeof updatedAt === "number" ? /* @__PURE__ */ jsx(RowMeta, {
114
119
  sessionId,
115
120
  updatedAt,
@@ -20,7 +20,7 @@ import { useSessionActivity } from "./useSessionActivity.js";
20
20
  import { useSessionBadges } from "./useSessionBadges.js";
21
21
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
22
  import { memo, useCallback, useEffect, useMemo, useReducer, useState } from "react";
23
- import { sessionBadgeTarget } from "zidane/chat/pure";
23
+ import { isRunEstimated, sessionBadgeTarget } from "zidane/chat/pure";
24
24
  //#region src/chat/sidebar/sidebar-live.tsx
25
25
  /**
26
26
  * What a sidebar row says about its session beyond the title, from the
@@ -319,10 +319,14 @@ function createSidebarLive(options) {
319
319
  function useSessionEstimate(sessionId) {
320
320
  return useRunEstimate(estimatesStore ? sessionId : void 0, void 0, estimatesStore);
321
321
  }
322
- /** The run's time: what it has left while the host estimated it, else how long it has gone. */
322
+ /**
323
+ * The run's time: what it has left while the host estimated it, else how long it has gone (with a mark
324
+ * saying why, when the host could not estimate it).
325
+ */
323
326
  function RunTime({ sessionId }) {
324
327
  const estimate = useSessionEstimate(sessionId);
325
- return estimate ? /* @__PURE__ */ jsx(EstimateChip, { estimate }) : /* @__PURE__ */ jsx(Elapsed, { sessionId });
328
+ if (estimate && isRunEstimated(estimate)) return /* @__PURE__ */ jsx(EstimateChip, { estimate });
329
+ return /* @__PURE__ */ jsxs(Fragment, { children: [estimate && /* @__PURE__ */ jsx(RunEstimateChip, { estimate }), /* @__PURE__ */ jsx(Elapsed, { sessionId })] });
326
330
  }
327
331
  /**
328
332
  * The estimate chip. Its tooltip says how long the run has gone, read from the run's start when the
@@ -352,7 +356,7 @@ function createSidebarLive(options) {
352
356
  className: "self-center w-1.5 h-1.5 rounded-full bg-[var(--zg-accent)]"
353
357
  }),
354
358
  labels.rowWorking,
355
- estimate && /* @__PURE__ */ jsx(EstimateChip, { estimate })
359
+ estimate && (isRunEstimated(estimate) ? /* @__PURE__ */ jsx(EstimateChip, { estimate }) : /* @__PURE__ */ jsx(RunEstimateChip, { estimate }))
356
360
  ]
357
361
  }) : /* @__PURE__ */ jsx(Ago, {
358
362
  at: updatedAt,
@@ -0,0 +1,34 @@
1
+ import { RunFailure } from "../headless/transcript/run-failures.js";
2
+ import "../headless/transcript/index.js";
3
+ import { CSSProperties } from "react";
4
+ import { AuthFailure } from "zidane/chat/pure";
5
+ import { StreamEvent } from "zidane/chat";
6
+ //#region src/chat/transcript/AuthFailureCard.d.ts
7
+ /** Props for {@link AuthFailureCard}. */
8
+ interface AuthFailureCardProps {
9
+ /** The sign-in that failed (`detail.auth`). */
10
+ auth: AuthFailure;
11
+ /** The run's stop reason, shown muted under the headline. */
12
+ text: string;
13
+ /** The error's structured detail: the provider's own words, for the tooltip and Copy details. */
14
+ detail?: StreamEvent['detail'];
15
+ /** How the run ended and how it would resume. */
16
+ failure: RunFailure;
17
+ /** The card is the transcript's last word, with no run in progress: it offers its actions. */
18
+ resumable: boolean;
19
+ /** Called with the prompt that resumes the run (Retry, and after a sign-in or a switch). Absent: no Retry. */
20
+ onResume?: (prompt: string) => void;
21
+ /** Extra classes on the root element. */
22
+ className?: string;
23
+ /** Inline styles on the root element, merged after the component's own. */
24
+ style?: CSSProperties;
25
+ }
26
+ /**
27
+ * Renders a sign-in failure as a card with its fixes; see the module
28
+ * comment for the rules.
29
+ *
30
+ * @param props - Component props.
31
+ */
32
+ declare const AuthFailureCard: import("react").MemoExoticComponent<({ auth, text, detail, failure, resumable, onResume, className, style }: AuthFailureCardProps) => import("react").JSX.Element>;
33
+ //#endregion
34
+ export { AuthFailureCard, AuthFailureCardProps };
@@ -0,0 +1,358 @@
1
+ import { buttonClass } from "../../components/button.js";
2
+ import "../../components/Form.js";
3
+ import { useReadable } from "../headless/store.js";
4
+ import { RoutedLink } from "../../extensions/links.js";
5
+ import { useChatLabels } from "../useChatLabels.js";
6
+ import { useTranscriptActions } from "./actions.js";
7
+ import { failureTooltip } from "../headless/transcript/run-failures.js";
8
+ import { authFailureDetails, createAuthFixes, isAuthFixed, planAuthCard } from "../headless/transcript/auth-failure.js";
9
+ import { useSignIn } from "../../onboarding/useSignIn.js";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ import { memo, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
12
+ import { CONTINUE_PROMPT, authOffersSignInFallback, authPrimaryAction } from "zidane/chat/pure";
13
+ //#region src/chat/transcript/AuthFailureCard.tsx
14
+ /**
15
+ * A run that stopped because a sign-in failed (`detail.auth`): instead of the
16
+ * quiet "Stopped" line, a compact card with what failed (the provider's
17
+ * name, the account), the reason, and what fixes it, in place: sign that
18
+ * account in again (the browser flow runs inside the card, a pasted code
19
+ * included), retry, switch to another stored account, open Settings there,
20
+ * or copy the details. A sign-in that succeeds resends the failed prompt
21
+ * when the stop is still the transcript's last word.
22
+ *
23
+ * Only the last stop is interactive (the rule the Retry button follows);
24
+ * older cards keep their headline. Once a sign-in is fixed, every card for
25
+ * it in the session says so. The accounts come from the transcript actions
26
+ * (`TranscriptActions.accounts`): a member the app leaves out hides its
27
+ * button.
28
+ */
29
+ /** The sign-ins fixed from a card in this page's life, per session. */
30
+ const FIXES = createAuthFixes();
31
+ const BODY_TEXT = "text-sm leading-[1.6]";
32
+ const BTN_MAIN = buttonClass({
33
+ variant: "primary",
34
+ size: "xs"
35
+ });
36
+ const BTN_OTHER = buttonClass({
37
+ variant: "secondary",
38
+ size: "xs"
39
+ });
40
+ const BTN_QUIET = buttonClass({
41
+ variant: "ghost",
42
+ size: "xs"
43
+ });
44
+ const COPIED_MS = 1200;
45
+ const noop = () => () => {};
46
+ const idle = () => void 0;
47
+ /** A host's provider list, re-rendering when it changes (`undefined` without one). */
48
+ function useProviderList(resource) {
49
+ return useSyncExternalStore(resource ? resource.subscribe : noop, resource ? resource.get : idle, resource ? resource.get : idle);
50
+ }
51
+ /** A rejected action's words: a `SettingsError`'s detail, an `Error`'s message. */
52
+ function messageOf(error) {
53
+ if (error && typeof error === "object") {
54
+ if ("detail" in error && typeof error.detail === "string" && error.detail) return error.detail;
55
+ if ("message" in error && typeof error.message === "string" && error.message) return error.message;
56
+ if ("kind" in error && typeof error.kind === "string") return error.kind;
57
+ }
58
+ return String(error);
59
+ }
60
+ /**
61
+ * Renders a sign-in failure as a card with its fixes; see the module
62
+ * comment for the rules.
63
+ *
64
+ * @param props - Component props.
65
+ */
66
+ const AuthFailureCard = memo(function AuthFailureCard({ auth, text, detail, failure, resumable, onResume, className, style }) {
67
+ const labels = useChatLabels();
68
+ const { sessionId, accounts } = useTranscriptActions();
69
+ const cwd = accounts?.cwd ?? "";
70
+ const providers = auth.source === "provider" ? accounts?.providers : void 0;
71
+ const list = useProviderList(useMemo(() => providers?.list(cwd) ?? null, [providers, cwd]))?.data;
72
+ const plan = useMemo(() => planAuthCard(auth, list), [auth, list]);
73
+ const fixes = useReadable(FIXES.fixed(sessionId));
74
+ const headline = labels.authHeadline(auth, plan.label);
75
+ const prompt = failure.resume === "retry" && failure.prompt ? failure.prompt : CONTINUE_PROMPT;
76
+ const latest = useRef({
77
+ resumable,
78
+ onResume,
79
+ prompt
80
+ });
81
+ useEffect(() => {
82
+ latest.current = {
83
+ resumable,
84
+ onResume,
85
+ prompt
86
+ };
87
+ });
88
+ /** Resends the failed prompt if the stop is still the last word; says whether it did. */
89
+ const resumeIfLast = () => {
90
+ const now = latest.current;
91
+ if (!now.resumable || !now.onResume) return false;
92
+ now.onResume(now.prompt);
93
+ return true;
94
+ };
95
+ const [outcome, setOutcome] = useState(null);
96
+ const signIn = useSignIn(() => {
97
+ FIXES.add(sessionId, auth);
98
+ setOutcome(resumeIfLast() ? "retrying" : "signed-in");
99
+ });
100
+ const [switching, setSwitching] = useState(null);
101
+ const [copied, setCopied] = useState(false);
102
+ useEffect(() => {
103
+ if (!copied) return void 0;
104
+ const timer = window.setTimeout(() => setCopied(false), COPIED_MS);
105
+ return () => window.clearTimeout(timer);
106
+ }, [copied]);
107
+ const flow = signIn.state;
108
+ const running = flow !== null && flow.kind !== "done" && flow.kind !== "error";
109
+ const fixed = outcome !== null || !resumable && !running && isAuthFixed(fixes, auth);
110
+ const open = resumable || running;
111
+ const begin = useMemo(() => {
112
+ if (auth.source === "provider") {
113
+ const provider = plan.provider;
114
+ if (!providers?.signIn || !provider?.oauth) return null;
115
+ const replaceKey = plan.replaceKey;
116
+ return () => providers.signIn(provider.key, replaceKey ? { replaceKey } : void 0);
117
+ }
118
+ const mcp = accounts?.mcp;
119
+ if (auth.source === "mcp" && mcp?.signIn) return () => mcp.signIn(cwd, auth.provider);
120
+ return null;
121
+ }, [
122
+ auth,
123
+ plan,
124
+ providers,
125
+ accounts?.mcp,
126
+ cwd
127
+ ]);
128
+ const other = plan.otherAccount;
129
+ const canSwitch = Boolean(other?.key && plan.provider && providers?.setPreferred);
130
+ const switchAccount = async () => {
131
+ setSwitching({});
132
+ try {
133
+ await providers.setPreferred(cwd, plan.provider.key, { key: other.key });
134
+ setSwitching(null);
135
+ resumeIfLast();
136
+ } catch (error) {
137
+ setSwitching({ error: messageOf(error) });
138
+ }
139
+ };
140
+ const switchBusy = switching !== null && switching.error === void 0;
141
+ const primary = authPrimaryAction(auth);
142
+ const offerSignIn = begin !== null && (primary === "sign-in" || authOffersSignInFallback(auth));
143
+ const offerRetry = onResume !== void 0 && (primary === "retry" || !offerSignIn);
144
+ const otherLabel = other ? other.label ?? other.detail : "";
145
+ const copy = async () => {
146
+ try {
147
+ await navigator.clipboard.writeText(authFailureDetails(headline, text, detail?.raw));
148
+ setCopied(true);
149
+ } catch {}
150
+ };
151
+ const signInButton = offerSignIn && /* @__PURE__ */ jsxs("button", {
152
+ type: "button",
153
+ className: primary === "sign-in" ? BTN_MAIN : BTN_OTHER,
154
+ onClick: () => signIn.start(begin),
155
+ children: [/* @__PURE__ */ jsx("span", {
156
+ "aria-hidden": true,
157
+ className: "i-ph-sign-in"
158
+ }), labels.authSignInAgain]
159
+ });
160
+ const retryButton = offerRetry && /* @__PURE__ */ jsxs("button", {
161
+ type: "button",
162
+ className: primary === "retry" ? BTN_MAIN : BTN_OTHER,
163
+ title: failure.resume === "retry" ? labels.retryHint : labels.continueHint,
164
+ onClick: () => onResume(prompt),
165
+ children: [/* @__PURE__ */ jsx("span", {
166
+ "aria-hidden": true,
167
+ className: "i-ph-arrow-clockwise"
168
+ }), labels.retry]
169
+ });
170
+ return /* @__PURE__ */ jsxs("div", {
171
+ role: "group",
172
+ "aria-label": labels.authCard,
173
+ "data-testid": "run-failure",
174
+ "data-cause": failure.cause,
175
+ "data-auth": auth.kind,
176
+ "data-fixed": fixed ? "" : void 0,
177
+ className: [`flex flex-col gap-1 min-w-0 pl-3 border-l-2 ${fixed ? "border-zg-success" : "border-zg-danger"} ${BODY_TEXT}`, className].filter(Boolean).join(" "),
178
+ style,
179
+ children: [
180
+ /* @__PURE__ */ jsxs("div", {
181
+ className: "flex items-center gap-2 min-w-0",
182
+ title: failureTooltip(text, detail, labels.resetsAt),
183
+ children: [
184
+ /* @__PURE__ */ jsx("span", {
185
+ "aria-hidden": true,
186
+ className: `shrink-0 ${fixed ? "i-ph-check-circle text-zg-success" : "i-ph-key text-zg-danger"}`
187
+ }),
188
+ /* @__PURE__ */ jsx("span", {
189
+ className: "min-w-0 truncate font-medium text-[var(--zg-text)]",
190
+ children: headline
191
+ }),
192
+ fixed && outcome === null && /* @__PURE__ */ jsxs("span", {
193
+ className: "zg-meta-chip zg-meta shrink-0 gap-1 text-zg-success",
194
+ "data-testid": "auth-fixed",
195
+ children: [/* @__PURE__ */ jsx("span", {
196
+ "aria-hidden": true,
197
+ className: "i-ph-check"
198
+ }), labels.authFixed]
199
+ })
200
+ ]
201
+ }),
202
+ (open || outcome !== null) && text && /* @__PURE__ */ jsx("div", {
203
+ className: "min-w-0 text-[var(--zg-text-muted)] whitespace-pre-wrap break-words",
204
+ children: text
205
+ }),
206
+ outcome !== null ? /* @__PURE__ */ jsxs("div", {
207
+ role: "status",
208
+ className: "flex items-center gap-1.5 text-zg-success",
209
+ children: [/* @__PURE__ */ jsx("span", {
210
+ "aria-hidden": true,
211
+ className: "i-ph-check"
212
+ }), outcome === "retrying" ? labels.authSignedInRetrying : labels.authSignedIn]
213
+ }) : !open ? null : running ? /* @__PURE__ */ jsx(SignInProgress, {
214
+ state: flow,
215
+ submit: signIn.submit,
216
+ onCancel: signIn.cancel
217
+ }) : flow?.kind === "error" ? /* @__PURE__ */ jsxs("div", {
218
+ 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)
223
+ }), /* @__PURE__ */ jsxs("div", {
224
+ className: "flex flex-wrap items-center gap-1.5",
225
+ children: [/* @__PURE__ */ jsx("button", {
226
+ type: "button",
227
+ className: BTN_MAIN,
228
+ onClick: () => signIn.start(begin),
229
+ children: labels.authTryAgain
230
+ }), /* @__PURE__ */ jsx("button", {
231
+ type: "button",
232
+ className: BTN_OTHER,
233
+ onClick: signIn.cancel,
234
+ children: labels.authCancel
235
+ })]
236
+ })]
237
+ }) : /* @__PURE__ */ jsxs("div", {
238
+ 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)
243
+ }), /* @__PURE__ */ jsxs("div", {
244
+ className: "flex flex-wrap items-center gap-1.5",
245
+ children: [
246
+ primary === "sign-in" ? signInButton : retryButton,
247
+ primary === "sign-in" ? retryButton : signInButton,
248
+ canSwitch && /* @__PURE__ */ jsxs("button", {
249
+ type: "button",
250
+ className: BTN_OTHER,
251
+ disabled: switchBusy,
252
+ onClick: () => void switchAccount(),
253
+ children: [/* @__PURE__ */ jsx("span", {
254
+ "aria-hidden": true,
255
+ className: "i-ph-user-switch"
256
+ }), switchBusy ? labels.authSwitching(otherLabel) : labels.authUseAccount(otherLabel)]
257
+ }),
258
+ accounts?.openSettings && /* @__PURE__ */ jsxs("button", {
259
+ type: "button",
260
+ className: BTN_QUIET,
261
+ title: labels.authSettingsHint,
262
+ onClick: () => accounts.openSettings(plan.settings),
263
+ children: [/* @__PURE__ */ jsx("span", {
264
+ "aria-hidden": true,
265
+ className: "i-ph-gear"
266
+ }), labels.authSettings]
267
+ }),
268
+ /* @__PURE__ */ jsxs("button", {
269
+ type: "button",
270
+ className: BTN_QUIET,
271
+ onClick: () => void copy(),
272
+ children: [/* @__PURE__ */ jsx("span", {
273
+ "aria-hidden": true,
274
+ className: copied ? "i-ph-check" : "i-ph-copy"
275
+ }), copied ? labels.authCopied : labels.authCopyDetails]
276
+ })
277
+ ]
278
+ })]
279
+ })
280
+ ]
281
+ });
282
+ });
283
+ /** A sign-in while it runs, inside the card: where it is, the page's link, a pasted code, Cancel. */
284
+ function SignInProgress({ state, submit, onCancel }) {
285
+ const labels = useChatLabels();
286
+ const [pasted, setPasted] = useState("");
287
+ const page = state.kind === "url" || state.kind === "device" ? state : null;
288
+ const instructions = state.kind === "url" && "instructions" in state && typeof state.instructions === "string" ? state.instructions : null;
289
+ const line = state.kind === "url" ? labels.authWaiting : state.kind === "device" ? labels.authEnterCode(state.userCode) : state.kind === "prompt" || state.kind === "progress" ? state.message : labels.authOpeningBrowser;
290
+ const takesInput = submit !== void 0 && (state.kind === "url" || state.kind === "prompt");
291
+ const send = (event) => {
292
+ event.preventDefault();
293
+ if (!pasted.trim()) return;
294
+ submit?.(pasted.trim());
295
+ setPasted("");
296
+ };
297
+ return /* @__PURE__ */ jsxs("div", {
298
+ className: "flex flex-col gap-1.5",
299
+ "data-testid": "auth-sign-in",
300
+ children: [
301
+ /* @__PURE__ */ jsxs("div", {
302
+ role: "status",
303
+ "aria-live": "polite",
304
+ className: "flex items-center gap-2 min-w-0 text-[var(--zg-text)]",
305
+ children: [
306
+ /* @__PURE__ */ jsx("span", {
307
+ "aria-hidden": true,
308
+ className: "zg-spin-ring zg-loop block shrink-0 text-[var(--zg-accent)]"
309
+ }),
310
+ /* @__PURE__ */ jsx("span", {
311
+ className: "min-w-0 break-words",
312
+ children: line
313
+ }),
314
+ page && /* @__PURE__ */ jsx(RoutedLink, {
315
+ href: page.url,
316
+ source: "auth",
317
+ className: "shrink-0 text-[var(--zg-accent-hover)] underline underline-offset-2",
318
+ children: labels.authOpenPage
319
+ })
320
+ ]
321
+ }),
322
+ instructions && /* @__PURE__ */ jsx("div", {
323
+ className: "text-[var(--zg-text-muted)] break-words",
324
+ children: instructions
325
+ }),
326
+ state.kind === "prompt" && state.options && /* @__PURE__ */ jsx("ol", {
327
+ className: "m-0 pl-5 text-[var(--zg-text-muted)]",
328
+ children: state.options.map((option) => /* @__PURE__ */ jsx("li", { children: option }, option))
329
+ }),
330
+ /* @__PURE__ */ jsxs("form", {
331
+ className: "flex flex-wrap items-center gap-1.5",
332
+ onSubmit: send,
333
+ children: [takesInput && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
334
+ type: "text",
335
+ autoComplete: "off",
336
+ spellCheck: false,
337
+ "aria-label": labels.authPaste,
338
+ placeholder: state.kind === "prompt" && state.placeholder ? state.placeholder : labels.authPaste,
339
+ value: pasted,
340
+ onChange: (event) => setPasted(event.target.value),
341
+ className: `zg-well w-full h-8 px-2.5 text-zg-ui placeholder:text-[var(--zg-text-subtle)] disabled:opacity-zg-disabled flex-1 !w-auto min-w-40 h-6`
342
+ }), /* @__PURE__ */ jsx("button", {
343
+ type: "submit",
344
+ className: BTN_MAIN,
345
+ disabled: !pasted.trim(),
346
+ children: labels.authPasteSend
347
+ })] }), /* @__PURE__ */ jsx("button", {
348
+ type: "button",
349
+ className: BTN_OTHER,
350
+ onClick: onCancel,
351
+ children: labels.authCancel
352
+ })]
353
+ })
354
+ ]
355
+ });
356
+ }
357
+ //#endregion
358
+ export { AuthFailureCard };
@@ -1,9 +1,11 @@
1
1
  import { useChatLabels } from "../useChatLabels.js";
2
2
  import { ProseMarkdown } from "./ProseMarkdown.js";
3
+ import { useOptionalWorkspaceActions, useOptionalWorkspaceView } from "../../workspace/WorkspaceProvider.js";
3
4
  import { PlanBody } from "../interactions/PlanCard.js";
4
5
  import { AnsweredQuestions } from "../interactions/QuestionForm.js";
5
6
  import { TodoListView } from "../../session/TodoList.js";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { SECRETS_PANEL_ID } from "zidane/chat/pure";
7
9
  //#region src/chat/transcript/InteractionToolBody.tsx
8
10
  /**
9
11
  * The tools this body knows how to render.
@@ -20,7 +22,7 @@ function hasInteractionBody(tool) {
20
22
  function parseResult(result) {
21
23
  if (!result) return null;
22
24
  try {
23
- const parsed = JSON.parse(result);
25
+ const parsed = JSON.parse(result.split("\n\n", 1)[0]);
24
26
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
25
27
  } catch {
26
28
  return null;
@@ -109,6 +111,12 @@ function waiting(tool, label) {
109
111
  label
110
112
  }) : null;
111
113
  }
114
+ /** Opens the Secrets tab, when the workspace around offers it (`Settings.secrets` on). */
115
+ function useOpenSecrets() {
116
+ const actions = useOptionalWorkspaceActions();
117
+ const offered = useOptionalWorkspaceView()?.tabs.some((tab) => tab.id === SECRETS_PANEL_ID) ?? false;
118
+ return actions && offered ? () => actions.focusTab(SECRETS_PANEL_ID) : void 0;
119
+ }
112
120
  /**
113
121
  * The expanded body of a `present_plan`, `ask_user` or `todowrite` call (see the module comment); `null` for any other.
114
122
  *
@@ -116,6 +124,7 @@ function waiting(tool, label) {
116
124
  */
117
125
  function InteractionToolBody({ tool }) {
118
126
  const labels = useChatLabels();
127
+ const openSecrets = useOpenSecrets();
119
128
  if (!hasInteractionBody(tool)) return null;
120
129
  const input = tool.rawInput;
121
130
  const response = parseResult(tool.result);
@@ -162,7 +171,8 @@ function InteractionToolBody({ tool }) {
162
171
  answers: answers ?? {},
163
172
  instructions,
164
173
  id: tool.id,
165
- Markdown: ProseMarkdown
174
+ Markdown: ProseMarkdown,
175
+ onOpenSecrets: openSecrets
166
176
  }),
167
177
  !answers && (waiting(tool, labels.interactionWaitingAnswers) ?? (tool.result ? /* @__PURE__ */ jsx(Outcome, {
168
178
  icon: "i-ph-minus-circle",