zidane-ui 9.1.4 → 9.1.6

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 (251) 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/ConversationBadges.js +16 -10
  15. package/dist/chat/composer/composer-bus.d.ts +2 -2
  16. package/dist/chat/composer/composer-bus.js +2 -2
  17. package/dist/chat/composer/use-composer-stores.js +1 -1
  18. package/dist/chat/composer/use-run-meter.js +1 -1
  19. package/dist/chat/headless/composer/conversation-badges.d.ts +8 -3
  20. package/dist/chat/headless/composer/conversation-badges.js +26 -11
  21. package/dist/chat/headless/composer/index.js +2 -2
  22. package/dist/chat/headless/composer/labels-chrome.d.ts +3 -1
  23. package/dist/chat/headless/composer/labels-chrome.js +3 -1
  24. package/dist/chat/headless/index.d.ts +6 -3
  25. package/dist/chat/headless/index.js +16 -13
  26. package/dist/chat/headless/labels.d.ts +54 -1
  27. package/dist/chat/headless/labels.js +62 -2
  28. package/dist/chat/headless/secrets.d.ts +32 -0
  29. package/dist/chat/headless/secrets.js +43 -0
  30. package/dist/chat/headless/session-list.d.ts +45 -0
  31. package/dist/chat/headless/sidebar/estimates.js +13 -1
  32. package/dist/chat/headless/sidebar/history.d.ts +71 -0
  33. package/dist/chat/headless/sidebar/history.js +174 -0
  34. package/dist/chat/headless/sidebar/index.d.ts +3 -2
  35. package/dist/chat/headless/sidebar/index.js +2 -1
  36. package/dist/chat/headless/sidebar/labels.d.ts +50 -0
  37. package/dist/chat/headless/sidebar/labels.js +1 -0
  38. package/dist/chat/headless/sidebar/query.d.ts +2 -2
  39. package/dist/chat/headless/sidebar/query.js +6 -3
  40. package/dist/chat/headless/sidebar/types.d.ts +7 -1
  41. package/dist/chat/headless/sidebar/view.js +2 -0
  42. package/dist/chat/headless/transcript/auth-failure.d.ts +67 -0
  43. package/dist/chat/headless/transcript/auth-failure.js +87 -0
  44. package/dist/chat/headless/transcript/index.d.ts +2 -1
  45. package/dist/chat/headless/transcript/index.js +2 -1
  46. package/dist/chat/headless/transcript/nesting.d.ts +3 -3
  47. package/dist/chat/headless/transcript/nesting.js +12 -4
  48. package/dist/chat/index.d.ts +4 -2
  49. package/dist/chat/index.js +3 -1
  50. package/dist/chat/interactions/InboxPanel.d.ts +6 -2
  51. package/dist/chat/interactions/InboxPanel.js +82 -44
  52. package/dist/chat/interactions/PlanCard.d.ts +2 -2
  53. package/dist/chat/interactions/PlanCard.js +1 -1
  54. package/dist/chat/interactions/QuestionField.d.ts +8 -3
  55. package/dist/chat/interactions/QuestionField.js +89 -8
  56. package/dist/chat/interactions/QuestionForm.d.ts +3 -1
  57. package/dist/chat/interactions/QuestionForm.js +48 -10
  58. package/dist/chat/interactions/SecretInput.d.ts +32 -0
  59. package/dist/chat/interactions/SecretInput.js +72 -0
  60. package/dist/chat/interactions/card-ui.d.ts +5 -3
  61. package/dist/chat/interactions/card-ui.js +5 -3
  62. package/dist/chat/interactions/index.d.ts +2 -1
  63. package/dist/chat/interactions/index.js +2 -1
  64. package/dist/chat/sidebar/SessionSidebar.js +2 -0
  65. package/dist/chat/sidebar/SidebarFilterMenu.d.ts +7 -2
  66. package/dist/chat/sidebar/SidebarFilterMenu.js +26 -2
  67. package/dist/chat/sidebar/SidebarSessionRow.d.ts +3 -1
  68. package/dist/chat/sidebar/SidebarSessionRow.js +8 -3
  69. package/dist/chat/sidebar/sidebar-live.js +8 -4
  70. package/dist/chat/transcript/AuthFailureCard.d.ts +34 -0
  71. package/dist/chat/transcript/AuthFailureCard.js +358 -0
  72. package/dist/chat/transcript/InteractionToolBody.js +12 -2
  73. package/dist/chat/transcript/actions.d.ts +24 -1
  74. package/dist/chat/transcript/index.d.ts +3 -2
  75. package/dist/chat/transcript/index.js +2 -1
  76. package/dist/chat/transcript/notices.d.ts +2 -1
  77. package/dist/chat/transcript/notices.js +13 -1
  78. package/dist/chat/transcript/script-input.d.ts +1 -1
  79. package/dist/chat/transcript/shell-block.js +1 -1
  80. package/dist/components/HowItWorks.d.ts +8 -1
  81. package/dist/components/HowItWorks.js +2 -2
  82. package/dist/components/RowActionsMenu.d.ts +6 -1
  83. package/dist/components/RowActionsMenu.js +4 -0
  84. package/dist/core.css +24 -0
  85. package/dist/dist/{index-WlE93Q6d.d.ts → index-DqCio7Nd.d.ts} +36 -3
  86. package/dist/dist/index-f-XWIoYo.d.ts +1 -0
  87. package/dist/dist/index.d.ts +6 -0
  88. package/dist/dist/sandbox-B4OW6oNx.d.ts +2 -0
  89. package/dist/dist/timeout-B5pO5I5a.d.ts +30 -0
  90. package/dist/extensions/ExtensionSettingsPage.js +1 -1
  91. package/dist/extensions/ExtensionSettingsSidebar.js +1 -1
  92. package/dist/extensions/headless/fixture-host.js +1 -1
  93. package/dist/extensions/headless/index.js +4 -4
  94. package/dist/extensions/hooks.js +1 -1
  95. package/dist/files/DiffsTab.js +1 -1
  96. package/dist/files/EditorColumn.js +1 -1
  97. package/dist/files/MediaDiff.js +1 -1
  98. package/dist/files/SearchPanel.js +121 -53
  99. package/dist/files/headless/name-match.js +29 -14
  100. package/dist/files/useEntryActions.js +1 -1
  101. package/dist/files/useOpenFiles.js +1 -1
  102. package/dist/git/WherePicker.js +2 -2
  103. package/dist/git/headless/environment.d.ts +6 -1
  104. package/dist/git/headless/environment.js +5 -2
  105. package/dist/git/headless/labels.d.ts +2 -0
  106. package/dist/git/headless/labels.js +2 -0
  107. package/dist/git/index.d.ts +2 -1
  108. package/dist/git/index.js +2 -1
  109. package/dist/git/useStartFromPanel.d.ts +22 -0
  110. package/dist/git/useStartFromPanel.js +91 -0
  111. package/dist/keybindings/KeyCommands.js +1 -1
  112. package/dist/keybindings/KeybindingsProvider.js +1 -1
  113. package/dist/keybindings/headless/catalog.d.ts +1 -1
  114. package/dist/keybindings/headless/catalog.js +14 -2
  115. package/dist/keybindings/headless/index.js +2 -2
  116. package/dist/keybindings/headless/key-scope.d.ts +4 -2
  117. package/dist/keybindings/headless/key-scope.js +17 -2
  118. package/dist/keybindings/headless/overrides.js +1 -1
  119. package/dist/machines/HostSyncPanel.js +1 -1
  120. package/dist/machines/SyncOutcomeBadge.js +1 -1
  121. package/dist/machines/headless/index.js +1 -1
  122. package/dist/onboarding/demos/features.d.ts +9 -1
  123. package/dist/onboarding/demos/features.js +107 -2
  124. package/dist/onboarding/demos/how-it-works.d.ts +5 -1
  125. package/dist/onboarding/demos/how-it-works.js +120 -2
  126. package/dist/onboarding/demos/index.js +1 -1
  127. package/dist/onboarding/headless/labels.d.ts +17 -0
  128. package/dist/onboarding/headless/labels.js +17 -0
  129. package/dist/onboarding/index.js +4 -4
  130. package/dist/onboarding/marks.d.ts +1 -2
  131. package/dist/onboarding/marks.js +4 -12
  132. package/dist/onboarding/steps/ConnectorsStep.js +1 -1
  133. package/dist/onboarding/steps/ReadyStep.js +1 -1
  134. package/dist/onboarding/steps/SkillsStep.js +1 -1
  135. package/dist/onboarding/steps/connect/ProviderPanel.js +1 -1
  136. package/dist/onboarding/tutorials.d.ts +3 -1
  137. package/dist/onboarding/tutorials.js +2 -1
  138. package/dist/palette/app-sources.js +1 -1
  139. package/dist/palette/headless/app-sources.js +10 -0
  140. package/dist/palette/headless/labels.js +2 -0
  141. package/dist/session/ArtifactsPanel.js +1 -1
  142. package/dist/session/PanelAttention.d.ts +14 -6
  143. package/dist/session/PanelAttention.js +35 -24
  144. package/dist/session/PlanTracker.d.ts +54 -0
  145. package/dist/session/PlanTracker.js +413 -0
  146. package/dist/session/ProjectHome.d.ts +15 -2
  147. package/dist/session/ProjectHome.js +158 -85
  148. package/dist/session/RemindersPanel.d.ts +25 -0
  149. package/dist/session/RemindersPanel.js +526 -0
  150. package/dist/session/SecretsPanel.d.ts +19 -0
  151. package/dist/session/SecretsPanel.js +241 -0
  152. package/dist/session/SessionProvider.d.ts +26 -5
  153. package/dist/session/SessionProvider.js +51 -6
  154. package/dist/session/StepStatusIcon.d.ts +24 -0
  155. package/dist/session/StepStatusIcon.js +50 -0
  156. package/dist/session/TodoList.d.ts +4 -3
  157. package/dist/session/TodoList.js +6 -5
  158. package/dist/session/headless/fixture-host.d.ts +32 -22
  159. package/dist/session/headless/fixture-host.js +86 -51
  160. package/dist/session/headless/fixture-plans.d.ts +57 -0
  161. package/dist/session/headless/fixture-plans.js +141 -0
  162. package/dist/session/headless/fixture-schedules.d.ts +49 -0
  163. package/dist/session/headless/fixture-schedules.js +133 -0
  164. package/dist/session/headless/home-layout.d.ts +10 -2
  165. package/dist/session/headless/home-layout.js +7 -2
  166. package/dist/session/headless/host.d.ts +85 -13
  167. package/dist/session/headless/index.d.ts +5 -3
  168. package/dist/session/headless/index.js +5 -3
  169. package/dist/session/headless/labels.d.ts +95 -12
  170. package/dist/session/headless/labels.js +67 -18
  171. package/dist/session/headless/plans.d.ts +53 -0
  172. package/dist/session/headless/plans.js +78 -0
  173. package/dist/session/headless/reminder-labels.d.ts +63 -0
  174. package/dist/session/headless/reminder-labels.js +84 -0
  175. package/dist/session/headless/schedules.d.ts +93 -0
  176. package/dist/session/headless/schedules.js +190 -0
  177. package/dist/session/headless/secrets.d.ts +28 -0
  178. package/dist/session/headless/secrets.js +48 -0
  179. package/dist/session/index.d.ts +7 -5
  180. package/dist/session/index.js +6 -4
  181. package/dist/session/testing/contract.d.ts +18 -5
  182. package/dist/session/testing/contract.js +351 -43
  183. package/dist/session/testing/index.d.ts +4 -2
  184. package/dist/session/testing/index.js +4 -2
  185. package/dist/settings/headless/catalog.js +17 -1
  186. package/dist/settings/headless/index.d.ts +2 -2
  187. package/dist/settings/headless/index.js +3 -3
  188. package/dist/settings/headless/labels.d.ts +0 -2
  189. package/dist/settings/headless/labels.js +0 -2
  190. package/dist/settings/headless/layout.js +7 -1
  191. package/dist/settings/headless/providers.d.ts +17 -1
  192. package/dist/settings/headless/providers.js +19 -1
  193. package/dist/settings/headless/search.d.ts +1 -1
  194. package/dist/settings/rows.d.ts +1 -1
  195. package/dist/settings/rows.js +2 -2
  196. package/dist/settings/sections/appearance/AppearanceSection.js +2 -2
  197. package/dist/settings/sections/claude-import/ClaudeImportDialog.js +1 -1
  198. package/dist/settings/sections/editor/EditorSection.js +1 -1
  199. package/dist/settings/sections/environments/EnvironmentsSection.js +1 -1
  200. package/dist/settings/sections/extensions/ChangeOriginDialog.js +1 -1
  201. package/dist/settings/sections/extensions/CreateExtensionDialog.js +1 -1
  202. package/dist/settings/sections/extensions/ExtensionsSection.js +1 -1
  203. package/dist/settings/sections/host-catalog/HostCatalogSection.js +1 -1
  204. package/dist/settings/sections/instructions/InstructionsSection.js +1 -1
  205. package/dist/settings/sections/keybindings/labels.d.ts +2 -0
  206. package/dist/settings/sections/keybindings/labels.js +2 -0
  207. package/dist/settings/sections/keybindings/rows.js +8 -0
  208. package/dist/settings/sections/mcp/McpSection.js +1 -1
  209. package/dist/settings/sections/mcp/McpServerRow.js +1 -1
  210. package/dist/settings/sections/models/ModelRows.js +2 -2
  211. package/dist/settings/sections/providers/ProvidersSection.js +209 -201
  212. package/dist/settings/sections/providers/ServerProvidersSection.js +1 -1
  213. package/dist/settings/sections/shared/catalog.js +1 -1
  214. package/dist/settings/sections/skills/SkillList.js +1 -1
  215. package/dist/settings/sections/skills/SkillsSection.js +2 -2
  216. package/dist/styles.css +59 -1
  217. package/dist/terminal/HostTerminalSurface.js +2 -2
  218. package/dist/workspace/PanelContentView.d.ts +22 -4
  219. package/dist/workspace/PanelContentView.js +112 -16
  220. package/dist/workspace/PanelGlyph.d.ts +21 -0
  221. package/dist/workspace/PanelGlyph.js +33 -0
  222. package/dist/workspace/PanelHome.js +5 -3
  223. package/dist/workspace/PanelStrip.js +11 -4
  224. package/dist/workspace/PanelToolbar.d.ts +32 -0
  225. package/dist/workspace/PanelToolbar.js +194 -0
  226. package/dist/workspace/WorkspaceProvider.d.ts +3 -1
  227. package/dist/workspace/WorkspaceProvider.js +6 -2
  228. package/dist/workspace/extension-tabs.js +5 -2
  229. package/dist/workspace/headless/host.d.ts +4 -0
  230. package/dist/workspace/headless/index.d.ts +3 -1
  231. package/dist/workspace/headless/index.js +4 -2
  232. package/dist/workspace/headless/labels.d.ts +10 -0
  233. package/dist/workspace/headless/labels.js +11 -1
  234. package/dist/workspace/headless/pages.d.ts +15 -0
  235. package/dist/workspace/headless/pages.js +49 -0
  236. package/dist/workspace/headless/tab-mark.d.ts +14 -0
  237. package/dist/workspace/headless/tab-mark.js +27 -0
  238. package/dist/workspace/headless/view.d.ts +7 -1
  239. package/dist/workspace/index.d.ts +3 -2
  240. package/dist/workspace/index.js +3 -2
  241. package/dist/workspace/testing/index.js +6 -0
  242. package/dist/workspace/workspace-key-commands.js +3 -3
  243. package/package.json +2 -2
  244. package/src/styles/motion.css +13 -0
  245. package/src/styles/onboarding.css +0 -1
  246. package/src/styles/primitives.css +10 -0
  247. package/src/styles/workspace.css +17 -0
  248. package/dist/session/TodosPanel.d.ts +0 -19
  249. package/dist/session/TodosPanel.js +0 -251
  250. package/dist/session/headless/todos.d.ts +0 -22
  251. package/dist/session/headless/todos.js +0 -38
@@ -0,0 +1,526 @@
1
+ import { IconButton } from "../components/IconButton.js";
2
+ import { buttonClass } from "../components/button.js";
3
+ import { Segmented } from "../components/Segmented.js";
4
+ import { MetaChip } from "../components/Form.js";
5
+ import { PanelEmpty, PanelLoading } from "../components/PanelEmpty.js";
6
+ import { PANEL_ROW, PANEL_ROW_HOVER } from "../components/PanelRows.js";
7
+ import { useMinuteTick } from "../hooks/useMinuteTick.js";
8
+ import { constant, useReadable } from "../chat/headless/store.js";
9
+ import { canKeepSchedule, isScheduleFinished, readReminderWhen, sortSchedules } from "./headless/schedules.js";
10
+ import { useOptionalChatHost } from "../chat/ChatProvider.js";
11
+ import { useAllSchedules, useSchedulesStatus, useSessionHost, useSessionSchedules } from "./SessionProvider.js";
12
+ import { useSessionLabels } from "./useSessionLabels.js";
13
+ import { OpenSessionContext } from "../chat/transcript/markdown-context.js";
14
+ import { BTN_GHOST, BTN_PRIMARY, CardError, INPUT } from "../chat/interactions/card-ui.js";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ import { useContext, useEffect, useId, useMemo, useState } from "react";
17
+ import { describeTime, describeTrigger, scheduleLabel, scheduleTargetSession } from "zidane/chat/pure";
18
+ //#region src/session/RemindersPanel.tsx
19
+ /**
20
+ * The Reminders panel body (zidane's schedules): the prompts set to reach a
21
+ * session at a set time, once or on a repeat. It lists this session's
22
+ * reminders or all of them, each with when it fires, its next time, who set
23
+ * it and why it is off; it pauses, resumes, runs now, deletes, keeps an
24
+ * agent's repeat for good, and shows a reminder's history. The form reads
25
+ * the time words (`in 20m`, `tomorrow 9:00`, `weekdays 9:00`) in this
26
+ * client's time zone, shows what they mean as you type, and sends the exact
27
+ * trigger.
28
+ *
29
+ * It reads `SessionHost.schedules` and hides itself without it; while the
30
+ * Reminders setting is off it says so. The list follows the host's change
31
+ * signal (`schedules:changed`).
32
+ */
33
+ const errorText = (err) => err instanceof Error ? err.message : String(err);
34
+ /** The time words follow the clock: the minute tick re-renders, and each render reads it. */
35
+ const readClock = () => Date.now();
36
+ /** A quick time pick under the When field. */
37
+ const PICK = `${buttonClass({
38
+ variant: "secondary",
39
+ size: "xs"
40
+ })} font-mono text-zg-meta`;
41
+ const NO_SESSIONS = constant([]);
42
+ /**
43
+ * The title of the session a reminder goes to, from the chat host's list. `null` when the list does not hold it.
44
+ *
45
+ * @param sessionId - The session (`null`: none).
46
+ */
47
+ function useTargetTitle(sessionId) {
48
+ const sessions = useReadable(useOptionalChatHost()?.sessions?.list ?? NO_SESSIONS);
49
+ if (sessionId === null) return null;
50
+ return sessions.find((s) => s.id === sessionId)?.title || null;
51
+ }
52
+ /** Seconds in every time the panel writes, so you know when a reminder goes out. */
53
+ const TO_THE_SECOND = { seconds: true };
54
+ /**
55
+ * Re-renders once a second while `active` and the window shows, for countdowns; returns the time to read.
56
+ *
57
+ * @param active - Whether anything on screen counts down.
58
+ */
59
+ function useSecondClock(active) {
60
+ const [, setTick] = useState(0);
61
+ useEffect(() => {
62
+ if (!active) return;
63
+ const timer = setInterval(() => {
64
+ if (document.visibilityState !== "hidden") setTick((n) => n + 1);
65
+ }, 1e3);
66
+ return () => clearInterval(timer);
67
+ }, [active]);
68
+ return readClock();
69
+ }
70
+ /**
71
+ * Renders the reminders of a session, or all of them, with the create form.
72
+ *
73
+ * @param props - The `sessionId`, `initialScope`, `className` and `style`.
74
+ */
75
+ function RemindersPanel({ sessionId, initialScope = "session", onOpenSession, className = "", style }) {
76
+ const labels = useSessionLabels();
77
+ const contextOpen = useContext(OpenSessionContext);
78
+ const openSession = onOpenSession ?? contextOpen ?? void 0;
79
+ const host = useSessionHost().schedules;
80
+ const status = useSchedulesStatus();
81
+ const [scope, setScope] = useState(initialScope);
82
+ const mine = useSessionSchedules(sessionId);
83
+ const all = useAllSchedules();
84
+ const [error, setError] = useState(null);
85
+ useMinuteTick();
86
+ const list = scope === "session" ? mine : all;
87
+ const sorted = useMemo(() => list ? sortSchedules(list) : null, [list]);
88
+ const live = sorted?.filter((s) => !isScheduleFinished(s)) ?? [];
89
+ const finished = sorted?.filter(isScheduleFinished) ?? [];
90
+ const now = useSecondClock(live.some((s) => s.enabled && s.nextFireAt !== null));
91
+ if (!host) return null;
92
+ const root = `flex-1 min-h-0 flex flex-col ${className}`;
93
+ if (status === null) return /* @__PURE__ */ jsx("div", {
94
+ className: root,
95
+ style,
96
+ "aria-label": labels.remindersLabel,
97
+ children: /* @__PURE__ */ jsx(PanelLoading, {})
98
+ });
99
+ if (!status.enabled) return /* @__PURE__ */ jsx("div", {
100
+ className: root,
101
+ style,
102
+ "aria-label": labels.remindersLabel,
103
+ children: /* @__PURE__ */ jsx(PanelEmpty, {
104
+ icon: "i-ph-alarm",
105
+ title: labels.remindersOff,
106
+ hint: status.supported ? labels.remindersOffHint : labels.remindersUnsupported
107
+ })
108
+ });
109
+ const act = (run) => {
110
+ setError(null);
111
+ run().catch((err) => setError(errorText(err)));
112
+ };
113
+ return /* @__PURE__ */ jsxs("div", {
114
+ className: root,
115
+ style,
116
+ "aria-label": labels.remindersLabel,
117
+ children: [
118
+ /* @__PURE__ */ jsxs("div", {
119
+ className: "shrink-0 flex items-center gap-2 px-3 pt-3",
120
+ children: [/* @__PURE__ */ jsx(Segmented, {
121
+ size: "sm",
122
+ ariaLabel: labels.remindersScopeLabel,
123
+ value: scope,
124
+ onChange: setScope,
125
+ options: [{
126
+ value: "session",
127
+ label: labels.remindersScopeSession
128
+ }, {
129
+ value: "all",
130
+ label: labels.remindersScopeAll
131
+ }]
132
+ }), sorted && sorted.length > 0 && /* @__PURE__ */ jsx("span", {
133
+ className: "zg-meta",
134
+ children: labels.remindersCount(sorted.length)
135
+ })]
136
+ }),
137
+ /* @__PURE__ */ jsxs("div", {
138
+ className: "flex-1 min-h-0 flex flex-col overflow-y-auto px-3 pt-2 pb-3",
139
+ children: [error && /* @__PURE__ */ jsx("div", {
140
+ className: "text-xs text-[var(--zg-warn)] mb-2",
141
+ role: "alert",
142
+ children: error
143
+ }), sorted === null ? /* @__PURE__ */ jsx(PanelLoading, {}) : sorted.length === 0 ? /* @__PURE__ */ jsx(PanelEmpty, {
144
+ icon: "i-ph-alarm",
145
+ title: scope === "session" ? labels.remindersEmpty : labels.remindersEmptyAll,
146
+ ...host.create ? { hint: labels.remindersEmptyHint } : {}
147
+ }) : /* @__PURE__ */ jsxs("div", {
148
+ className: "flex flex-col gap-3",
149
+ children: [live.length > 0 && /* @__PURE__ */ jsx("ul", {
150
+ className: "m-0 p-0 list-none flex flex-col gap-0.5",
151
+ "aria-label": labels.remindersListLabel,
152
+ children: live.map((schedule) => /* @__PURE__ */ jsx(ReminderRow, {
153
+ schedule,
154
+ sessionId,
155
+ now,
156
+ act,
157
+ openSession
158
+ }, schedule.id))
159
+ }), finished.length > 0 && /* @__PURE__ */ jsxs("section", {
160
+ className: "flex flex-col gap-1",
161
+ "aria-label": labels.remindersFinished,
162
+ children: [live.length > 0 && /* @__PURE__ */ jsx("h3", {
163
+ className: "zg-section-label m-0 px-0.5",
164
+ children: labels.remindersFinished
165
+ }), /* @__PURE__ */ jsx("ul", {
166
+ className: "m-0 p-0 list-none flex flex-col gap-0.5",
167
+ children: finished.map((schedule) => /* @__PURE__ */ jsx(ReminderRow, {
168
+ schedule,
169
+ sessionId,
170
+ now,
171
+ act,
172
+ openSession
173
+ }, schedule.id))
174
+ })]
175
+ })]
176
+ })]
177
+ }),
178
+ host.create && /* @__PURE__ */ jsx(ReminderForm, { sessionId })
179
+ ]
180
+ });
181
+ }
182
+ /** One fact of a reminder's meta line: a small glyph, then the words. */
183
+ function Fact({ icon, className = "", children }) {
184
+ return /* @__PURE__ */ jsxs("span", {
185
+ className: `inline-flex items-center gap-1 min-w-0 ${className}`,
186
+ children: [/* @__PURE__ */ jsx("span", {
187
+ "aria-hidden": true,
188
+ className: `${icon} shrink-0 opacity-70`
189
+ }), /* @__PURE__ */ jsx("span", {
190
+ className: "truncate",
191
+ children
192
+ })]
193
+ });
194
+ }
195
+ const CREATOR_ICON = {
196
+ user: "i-ph-user",
197
+ agent: "i-ph-robot",
198
+ extension: "i-ph-puzzle-piece"
199
+ };
200
+ /** The chip at the end of a reminder's meta line: the countdown, Off or Done. */
201
+ function ReminderStatus({ schedule, now }) {
202
+ const labels = useSessionLabels();
203
+ if (!schedule.enabled) return /* @__PURE__ */ jsxs(MetaChip, {
204
+ tone: "warn",
205
+ title: schedule.disabledReason,
206
+ children: [/* @__PURE__ */ jsx("span", {
207
+ "aria-hidden": true,
208
+ className: "i-ph-pause"
209
+ }), labels.reminderOff]
210
+ });
211
+ if (schedule.nextFireAt === null) return /* @__PURE__ */ jsxs(MetaChip, { children: [/* @__PURE__ */ jsx("span", {
212
+ "aria-hidden": true,
213
+ className: "i-ph-check"
214
+ }), labels.reminderDone] });
215
+ return /* @__PURE__ */ jsx(MetaChip, {
216
+ tone: "accent",
217
+ className: "tabular-nums",
218
+ children: labels.reminderCountdown(schedule.nextFireAt - now)
219
+ });
220
+ }
221
+ function ReminderRow({ schedule, sessionId, now, act, openSession }) {
222
+ const labels = useSessionLabels();
223
+ const host = useSessionHost().schedules;
224
+ const [open, setOpen] = useState(false);
225
+ const historyId = useId();
226
+ const label = scheduleLabel(schedule);
227
+ const target = scheduleTargetSession(schedule.action);
228
+ const other = target !== void 0 && target !== sessionId ? target : null;
229
+ const otherTitle = useTargetTitle(other);
230
+ const where = schedule.action.kind === "extension" ? labels.reminderTargetExtension(schedule.action.extensionId) : "newSession" in schedule.action ? labels.reminderTargetNew(schedule.action.newSession.cwd) : null;
231
+ const { update, runNow, remove, fires } = host;
232
+ const once = schedule.trigger.kind === "at";
233
+ const finished = isScheduleFinished(schedule);
234
+ const sentAt = schedule.lastFire?.firedAt;
235
+ const time = schedule.nextFireAt !== null ? labels.reminderNext(describeTime(schedule.nextFireAt, now, TO_THE_SECOND)) : sentAt !== void 0 ? labels.reminderLastSent(describeTime(sentAt, now, TO_THE_SECOND)) : null;
236
+ const live = schedule.enabled && !finished;
237
+ return /* @__PURE__ */ jsxs("li", {
238
+ className: `${PANEL_ROW} ${PANEL_ROW_HOVER} group flex-col !items-stretch !gap-1 !py-2`,
239
+ "data-schedule-id": schedule.id,
240
+ children: [/* @__PURE__ */ jsxs("div", {
241
+ className: "flex items-start gap-2.5",
242
+ children: [/* @__PURE__ */ jsx("span", {
243
+ "aria-hidden": true,
244
+ className: `zg-track-chip !rounded-zg-md shrink-0 size-7 flex items-center justify-center ${live ? "text-[var(--zg-accent)]" : "text-[var(--zg-text-muted)]"}`,
245
+ children: /* @__PURE__ */ jsx("span", { className: once ? "i-ph-alarm" : "i-ph-repeat" })
246
+ }), /* @__PURE__ */ jsxs("div", {
247
+ className: "flex-1 min-w-0 flex flex-col gap-0.5",
248
+ children: [
249
+ /* @__PURE__ */ jsxs("div", {
250
+ className: "flex items-center gap-2 min-h-6",
251
+ children: [/* @__PURE__ */ jsx("span", {
252
+ className: `flex-1 min-w-0 truncate text-zg-ui ${live ? "text-[var(--zg-text)]" : "text-[var(--zg-text-muted)]"}`,
253
+ title: label,
254
+ children: label
255
+ }), /* @__PURE__ */ jsxs("div", {
256
+ className: `shrink-0 flex items-center transition-opacity ${open ? "" : "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100"}`,
257
+ children: [
258
+ update && canKeepSchedule(schedule) && /* @__PURE__ */ jsx(IconButton, {
259
+ size: "sm",
260
+ icon: "i-ph-push-pin",
261
+ label: labels.reminderKeep(label),
262
+ onClick: () => act(() => update(schedule.id, { expiresAt: null }))
263
+ }),
264
+ update && !finished && /* @__PURE__ */ jsx(IconButton, {
265
+ size: "sm",
266
+ icon: schedule.enabled ? "i-ph-pause" : "i-ph-play",
267
+ label: schedule.enabled ? labels.reminderPause(label) : labels.reminderResume(label),
268
+ onClick: () => act(() => update(schedule.id, { enabled: !schedule.enabled }))
269
+ }),
270
+ runNow && /* @__PURE__ */ jsx(IconButton, {
271
+ size: "sm",
272
+ icon: "i-ph-paper-plane-tilt",
273
+ label: labels.reminderRunNow(label),
274
+ onClick: () => act(() => runNow(schedule.id))
275
+ }),
276
+ fires && /* @__PURE__ */ jsx(IconButton, {
277
+ size: "sm",
278
+ icon: "i-ph-clock-counter-clockwise",
279
+ label: open ? labels.reminderHistoryHide(label) : labels.reminderHistoryShow(label),
280
+ active: open,
281
+ "aria-expanded": open,
282
+ "aria-controls": historyId,
283
+ onClick: () => setOpen((v) => !v)
284
+ }),
285
+ remove && /* @__PURE__ */ jsx(IconButton, {
286
+ size: "sm",
287
+ icon: "i-ph-trash",
288
+ label: labels.reminderDelete(label),
289
+ onClick: () => act(() => remove(schedule.id))
290
+ })
291
+ ]
292
+ })]
293
+ }),
294
+ /* @__PURE__ */ jsxs("div", {
295
+ className: "flex items-center gap-2 min-w-0",
296
+ children: [/* @__PURE__ */ jsxs("span", {
297
+ className: "flex-1 min-w-0 flex flex-wrap items-center gap-x-3 gap-y-0.5 zg-meta",
298
+ children: [
299
+ time && /* @__PURE__ */ jsx(Fact, {
300
+ icon: "i-ph-clock",
301
+ children: time
302
+ }),
303
+ !once && /* @__PURE__ */ jsx(Fact, {
304
+ icon: "i-ph-calendar-blank",
305
+ children: describeTrigger(schedule.trigger, now)
306
+ }),
307
+ /* @__PURE__ */ jsx(Fact, {
308
+ icon: CREATOR_ICON[schedule.createdBy.kind],
309
+ children: labels.reminderCreator(schedule.createdBy)
310
+ }),
311
+ where && /* @__PURE__ */ jsx(Fact, {
312
+ icon: "i-ph-arrow-bend-up-right",
313
+ children: where
314
+ }),
315
+ other !== null && /* @__PURE__ */ jsx(Fact, {
316
+ icon: "i-ph-arrow-bend-up-right",
317
+ className: "max-w-full",
318
+ children: openSession ? /* @__PURE__ */ jsx("button", {
319
+ type: "button",
320
+ onClick: () => openSession(other),
321
+ title: labels.reminderTargetOpen(otherTitle ?? labels.reminderTargetUntitled),
322
+ className: "max-w-full truncate bg-transparent border-0 p-0 m-0 [font:inherit] text-inherit text-left cursor-pointer rounded-sm hover:text-[var(--zg-text)] hover:underline underline-offset-2 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--zg-ring)]",
323
+ children: otherTitle ?? labels.reminderTargetUntitled
324
+ }) : otherTitle ?? labels.reminderTargetOther
325
+ })
326
+ ]
327
+ }), /* @__PURE__ */ jsx(ReminderStatus, {
328
+ schedule,
329
+ now
330
+ })]
331
+ }),
332
+ !schedule.enabled && schedule.disabledReason && /* @__PURE__ */ jsx("span", {
333
+ className: "zg-meta !text-zg-warn",
334
+ children: labels.reminderOffReason(schedule.disabledReason)
335
+ }),
336
+ schedule.expiresAt !== void 0 && schedule.enabled && /* @__PURE__ */ jsx("span", {
337
+ className: "zg-meta",
338
+ children: labels.reminderExpires(describeTime(schedule.expiresAt, now, TO_THE_SECOND))
339
+ })
340
+ ]
341
+ })]
342
+ }), fires && open && /* @__PURE__ */ jsx(FireHistory, {
343
+ id: historyId,
344
+ scheduleId: schedule.id,
345
+ label,
346
+ version: schedule.lastFire?.id ?? "",
347
+ load: fires
348
+ })]
349
+ });
350
+ }
351
+ function FireHistory({ id, scheduleId, label, version, load }) {
352
+ const labels = useSessionLabels();
353
+ const [fires, setFires] = useState(null);
354
+ const [error, setError] = useState(null);
355
+ useEffect(() => {
356
+ let live = true;
357
+ load(scheduleId, 20).then((list) => live && setFires(list), (err) => live && setError(errorText(err)));
358
+ return () => {
359
+ live = false;
360
+ };
361
+ }, [
362
+ load,
363
+ scheduleId,
364
+ version
365
+ ]);
366
+ const now = readClock();
367
+ return /* @__PURE__ */ jsx("div", {
368
+ id,
369
+ className: "ml-[38px] mt-1 pl-3 border-l border-[var(--zg-hairline)]",
370
+ children: error ? /* @__PURE__ */ jsx(CardError, { error }) : fires === null ? null : fires.length === 0 ? /* @__PURE__ */ jsx("span", {
371
+ className: "zg-meta",
372
+ children: labels.reminderNoFires
373
+ }) : /* @__PURE__ */ jsx("ul", {
374
+ className: "m-0 p-0 list-none flex flex-col gap-0.5",
375
+ "aria-label": labels.reminderHistoryLabel(label),
376
+ children: fires.map((fire) => /* @__PURE__ */ jsxs("li", {
377
+ className: "flex flex-wrap gap-x-2 zg-meta",
378
+ children: [
379
+ /* @__PURE__ */ jsx("span", {
380
+ className: "tabular-nums",
381
+ children: describeTime(fire.firedAt, now, TO_THE_SECOND)
382
+ }),
383
+ /* @__PURE__ */ jsx("span", {
384
+ className: fire.outcome === "failed" ? "text-[var(--zg-danger)]" : void 0,
385
+ children: labels.reminderFireOutcome(fire.outcome)
386
+ }),
387
+ fire.late && /* @__PURE__ */ jsx("span", { children: labels.reminderFireLate }),
388
+ fire.error && /* @__PURE__ */ jsx("span", {
389
+ className: "truncate",
390
+ children: fire.error
391
+ })
392
+ ]
393
+ }, fire.id))
394
+ })
395
+ });
396
+ }
397
+ function ReminderForm({ sessionId }) {
398
+ const labels = useSessionLabels();
399
+ const create = useSessionHost().schedules?.create;
400
+ const id = useId();
401
+ const [when, setWhen] = useState("");
402
+ const [text, setText] = useState("");
403
+ const [busy, setBusy] = useState(false);
404
+ const [error, setError] = useState(null);
405
+ useMinuteTick();
406
+ const now = useSecondClock(readReminderWhen(when, readClock()).ok);
407
+ const parsed = readReminderWhen(when, now);
408
+ const ready = parsed.ok && text.trim() !== "";
409
+ const submit = async (event) => {
410
+ event.preventDefault();
411
+ if (!create || busy || !ready) return;
412
+ const fresh = readReminderWhen(when, readClock());
413
+ if (!fresh.ok) return;
414
+ setBusy(true);
415
+ setError(null);
416
+ try {
417
+ await create({
418
+ trigger: fresh.trigger,
419
+ action: {
420
+ kind: "prompt",
421
+ sessionId,
422
+ text: text.trim()
423
+ }
424
+ });
425
+ setWhen("");
426
+ setText("");
427
+ } catch (err) {
428
+ setError(errorText(err));
429
+ } finally {
430
+ setBusy(false);
431
+ }
432
+ };
433
+ const invalid = when.trim() !== "" && !parsed.ok;
434
+ const preview = parsed.ok ? labels.reminderPreview(describeTrigger(parsed.trigger, now, TO_THE_SECOND)) : null;
435
+ return /* @__PURE__ */ jsxs("form", {
436
+ className: "zg-raised border shrink-0 mx-3 mb-3 flex flex-col gap-2 rounded-zg-lg p-2.5",
437
+ "aria-label": labels.reminderNew,
438
+ onSubmit: (e) => void submit(e),
439
+ children: [
440
+ /* @__PURE__ */ jsx("label", {
441
+ htmlFor: `${id}-text`,
442
+ className: "sr-only",
443
+ children: labels.reminderPromptLabel
444
+ }),
445
+ /* @__PURE__ */ jsx("textarea", {
446
+ id: `${id}-text`,
447
+ value: text,
448
+ onChange: (e) => setText(e.target.value),
449
+ placeholder: labels.reminderPromptPlaceholder,
450
+ rows: 2,
451
+ className: `${INPUT} py-2 resize-none`
452
+ }),
453
+ /* @__PURE__ */ jsx("label", {
454
+ htmlFor: `${id}-when`,
455
+ className: "sr-only",
456
+ children: labels.reminderWhenLabel
457
+ }),
458
+ /* @__PURE__ */ jsxs("div", {
459
+ className: "relative",
460
+ children: [/* @__PURE__ */ jsx("span", {
461
+ "aria-hidden": true,
462
+ className: `i-ph-alarm absolute left-2.5 top-1/2 -translate-y-1/2 pointer-events-none ${invalid ? "text-zg-danger" : "text-[var(--zg-text-subtle)]"}`
463
+ }), /* @__PURE__ */ jsx("input", {
464
+ id: `${id}-when`,
465
+ value: when,
466
+ onChange: (e) => setWhen(e.target.value),
467
+ placeholder: labels.reminderWhenPlaceholder,
468
+ autoComplete: "off",
469
+ spellCheck: false,
470
+ "aria-invalid": invalid ? true : void 0,
471
+ title: invalid && !parsed.ok ? labels.reminderWhenError(parsed.reason) : void 0,
472
+ "aria-describedby": `${id}-when-hint`,
473
+ className: `${INPUT} h-8 !pl-8`
474
+ })]
475
+ }),
476
+ /* @__PURE__ */ jsx("div", {
477
+ className: "flex flex-wrap items-center gap-1",
478
+ children: labels.reminderWhenPicks.map((words) => /* @__PURE__ */ jsx("button", {
479
+ type: "button",
480
+ "aria-label": labels.reminderWhenPick(words),
481
+ "aria-pressed": when.trim() === words,
482
+ onClick: () => setWhen(words),
483
+ className: `${PICK} ${when.trim() === words ? "!text-[var(--zg-accent)]" : ""}`,
484
+ children: words
485
+ }, words))
486
+ }),
487
+ /* @__PURE__ */ jsx(CardError, { error }),
488
+ /* @__PURE__ */ jsxs("div", {
489
+ className: "flex items-center gap-2",
490
+ children: [
491
+ /* @__PURE__ */ jsxs("span", {
492
+ id: `${id}-when-hint`,
493
+ "aria-live": "polite",
494
+ className: "flex-1 min-w-0 flex items-center gap-1 zg-meta tabular-nums",
495
+ children: [preview !== null && /* @__PURE__ */ jsx("span", {
496
+ "aria-hidden": true,
497
+ className: "i-ph-clock shrink-0"
498
+ }), /* @__PURE__ */ jsx("span", {
499
+ className: "truncate",
500
+ children: preview
501
+ })]
502
+ }),
503
+ (when !== "" || text !== "") && /* @__PURE__ */ jsx("button", {
504
+ type: "button",
505
+ className: BTN_GHOST,
506
+ disabled: busy,
507
+ onClick: () => {
508
+ setWhen("");
509
+ setText("");
510
+ setError(null);
511
+ },
512
+ children: labels.reminderCancel
513
+ }),
514
+ /* @__PURE__ */ jsx("button", {
515
+ type: "submit",
516
+ className: BTN_PRIMARY,
517
+ disabled: busy || !ready,
518
+ children: labels.reminderCreate
519
+ })
520
+ ]
521
+ })
522
+ ]
523
+ });
524
+ }
525
+ //#endregion
526
+ export { RemindersPanel };
@@ -0,0 +1,19 @@
1
+ import { CSSProperties } from "react";
2
+ //#region src/session/SecretsPanel.d.ts
3
+ /** Props for {@link SecretsPanel}. */
4
+ interface SecretsPanelProps {
5
+ /** The session whose project's secrets to list. */
6
+ sessionId: string;
7
+ /** Extra classes on the root. */
8
+ className?: string;
9
+ /** Inline styles on the root. */
10
+ style?: CSSProperties;
11
+ }
12
+ /**
13
+ * Renders a session project's saved secrets, with revoke, replace and add.
14
+ *
15
+ * @param props - The `sessionId`, `className` and `style`.
16
+ */
17
+ declare function SecretsPanel({ sessionId, className, style }: SecretsPanelProps): import("react").JSX.Element;
18
+ //#endregion
19
+ export { SecretsPanel, SecretsPanelProps };