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
@@ -1,8 +1,8 @@
1
1
  import { writable } from "../chat/headless/store.js";
2
- import { ExtensionsHostError } from "../extensions/headless/host.js";
3
2
  import { createServerWebviewSources } from "./extension-modules.js";
4
3
  import { createDialogQueue } from "../extensions/headless/dialog-queue.js";
5
4
  import { createUiEffectChannel } from "../extensions/headless/effect-channel.js";
5
+ import { ExtensionsHostError } from "../extensions/headless/host.js";
6
6
  import { EXTENSION_TOKENS } from "../extensions/headless/wire.js";
7
7
  import { IpcErrorCode, ServerCallError, ServerConnectionError, createExtensionsClient } from "zidane/ipc/browser";
8
8
  //#region src/adapters/server-extensions-host.ts
@@ -42,7 +42,8 @@ function toSidebarListSession(row) {
42
42
  ...row.isMain ? { isMain: true } : {},
43
43
  ...row.favorite ? { favorite: true } : {},
44
44
  ...row.agentId ? { agentId: row.agentId } : {},
45
- ...row.facets && Object.keys(row.facets).length > 0 ? { facets: row.facets } : {}
45
+ ...row.facets && Object.keys(row.facets).length > 0 ? { facets: row.facets } : {},
46
+ ...row.scheduleId ? { scheduleId: row.scheduleId } : {}
46
47
  };
47
48
  }
48
49
  /**
@@ -1,5 +1,5 @@
1
- import { machinesError } from "../machines/headless/host.js";
2
1
  import { closableClient } from "./closable-client.js";
2
+ import { machinesError } from "../machines/headless/host.js";
3
3
  import { createPresenceStore } from "../machines/headless/presence.js";
4
4
  import { createMachineLists, createOnlineMachines, lazyReadable } from "../machines/headless/stores.js";
5
5
  import { createHostSyncReads } from "../machines/headless/sync.js";
@@ -1,7 +1,9 @@
1
1
  import { createArtifactsState, groupArtifactRows, plainArtifactRow } from "../session/headless/artifacts.js";
2
2
  import { createQueueState } from "../session/headless/queue.js";
3
3
  import { createRunningWorkState } from "../session/headless/running-work.js";
4
- import { createTodosState } from "../session/headless/todos.js";
4
+ import { createSchedulesState } from "../session/headless/schedules.js";
5
+ import { createPlansState } from "../session/headless/plans.js";
6
+ import { createSecretsState } from "../session/headless/secrets.js";
5
7
  //#region src/adapters/server-session-host.ts
6
8
  /**
7
9
  * Creates a {@link SessionHost} over a zidane-server client.
@@ -10,7 +12,7 @@ import { createTodosState } from "../session/headless/todos.js";
10
12
  */
11
13
  function createServerSessionHost(options) {
12
14
  const { client, saveExport } = options;
13
- const todos = createTodosState((sessionId) => client.call("todos.get", { sessionId }));
15
+ const plans = createPlansState((sessionId) => client.call("plans.get", { sessionId }));
14
16
  const queue = createQueueState({
15
17
  list: (sessionId) => client.call("queue.list", { sessionId }),
16
18
  remove: (sessionId, id) => client.call("queue.remove", {
@@ -26,10 +28,15 @@ function createServerSessionHost(options) {
26
28
  });
27
29
  const work = createRunningWorkState((sessionId) => client.call("chat.listWork", { sessionId }));
28
30
  const artifacts = createArtifactsState(async (sessionId) => groupArtifactRows((await client.call("sessions.artifacts", { sessionId })).map(plainArtifactRow)));
31
+ const secrets = createSecretsState((sessionId) => client.call("secrets.list", { sessionId }));
32
+ const schedules = client.can("schedules.status") ? createSchedulesState({
33
+ status: () => client.call("schedules.status", {}),
34
+ list: () => client.call("schedules.list", {})
35
+ }) : null;
29
36
  const onSignal = (signal) => {
30
37
  switch (signal.kind) {
31
- case "todos:snapshot":
32
- todos.push(signal.sessionId, signal.snapshot);
38
+ case "plans:snapshot":
39
+ plans.push(signal.sessionId, signal.snapshot);
33
40
  break;
34
41
  case "queue:changed":
35
42
  queue.replace(signal.sessionId, signal.items);
@@ -41,20 +48,43 @@ function createServerSessionHost(options) {
41
48
  case "work:snapshot":
42
49
  work.push(signal.sessionId, signal.items);
43
50
  break;
44
- case "sessions:changed": if (signal.op === "delete") todos.forget(signal.sessionId);
51
+ case "secrets:changed":
52
+ secrets.wakeAll();
53
+ break;
54
+ case "schedules:changed":
55
+ case "settings:changed":
56
+ schedules?.wake();
57
+ break;
58
+ case "sessions:changed": if (signal.op === "delete") {
59
+ plans.forget(signal.sessionId);
60
+ secrets.forget(signal.sessionId);
61
+ }
45
62
  }
46
63
  };
47
64
  const unsubscribe = [client.onSignal(onSignal), client.onOpen((_hello, reconnected) => {
48
- if (reconnected) queue.reset(true);
65
+ if (reconnected) {
66
+ queue.reset(true);
67
+ schedules?.wake();
68
+ }
49
69
  })];
50
70
  return {
51
- todos: {
52
- snapshot: todos.snapshot,
53
- refresh: todos.refresh,
54
- set: async (sessionId, items) => await client.call("todos.set", {
55
- sessionId,
56
- items
57
- }) !== null,
71
+ plans: {
72
+ snapshot: plans.snapshot,
73
+ refresh: plans.refresh,
74
+ ...client.can("plans.edit") ? { edit: async (sessionId, planId, op) => {
75
+ plans.push(sessionId, await client.call("plans.edit", {
76
+ sessionId,
77
+ planId,
78
+ op
79
+ }));
80
+ } } : {},
81
+ ...client.can("plans.control") ? { control: async (sessionId, planId, action) => {
82
+ plans.push(sessionId, await client.call("plans.control", {
83
+ sessionId,
84
+ planId,
85
+ action
86
+ }));
87
+ } } : {},
58
88
  retry: async (sessionId, message) => {
59
89
  await client.call("chat.pushQueued", {
60
90
  sessionId,
@@ -190,6 +220,50 @@ function createServerSessionHost(options) {
190
220
  if (signal.kind === "sessions:changed" && signal.op === "update") onChange(signal.sessionId);
191
221
  })
192
222
  } } : {},
223
+ ...client.can("secrets.list") ? { secrets: {
224
+ entries: secrets.entries,
225
+ refresh: secrets.refresh,
226
+ ...client.can("secrets.save") ? { save: (sessionId, input) => client.call("secrets.save", {
227
+ sessionId,
228
+ name: input.name,
229
+ value: input.value,
230
+ ttl: input.ttl
231
+ }) } : {},
232
+ ...client.can("secrets.revoke") ? { revoke: async (sessionId, name) => (await client.call("secrets.revoke", {
233
+ sessionId,
234
+ name
235
+ })).removed } : {}
236
+ } } : {},
237
+ ...schedules ? { schedules: {
238
+ status: schedules.status,
239
+ all: schedules.all,
240
+ forSession: schedules.forSession,
241
+ refresh: schedules.refresh,
242
+ ensure: schedules.ensure,
243
+ async create(input) {
244
+ const created = await client.call("schedules.create", input);
245
+ schedules.apply(created);
246
+ return created;
247
+ },
248
+ async update(id, patch) {
249
+ const updated = await client.call("schedules.update", {
250
+ id,
251
+ patch
252
+ });
253
+ schedules.apply(updated);
254
+ return updated;
255
+ },
256
+ async remove(id) {
257
+ const removed = await client.call("schedules.delete", { id });
258
+ schedules.drop(id);
259
+ return removed;
260
+ },
261
+ runNow: (id) => client.call("schedules.runNow", { id }),
262
+ fires: (id, limit) => client.call("schedules.fires", {
263
+ id,
264
+ ...limit !== void 0 ? { limit } : {}
265
+ })
266
+ } } : {},
193
267
  close() {
194
268
  for (const off of unsubscribe) off();
195
269
  }
@@ -1,6 +1,6 @@
1
1
  import { writable } from "../chat/headless/store.js";
2
- import { DEFAULT_SETTINGS } from "../settings/headless/catalog.js";
3
2
  import { closableClient } from "./closable-client.js";
3
+ import { DEFAULT_SETTINGS } from "../settings/headless/catalog.js";
4
4
  import { serverSettingsSections } from "./server-settings-sections.js";
5
5
  import { serverSettingsAccounts } from "./server-settings-accounts.js";
6
6
  import { serverSettingsModels } from "./server-settings-models.js";
@@ -3,11 +3,11 @@ import { shikiThemeFor } from "../code/shiki-theme.js";
3
3
  import { derivePalette } from "../theme/derive.js";
4
4
  import { seedFromTheme } from "../theme/from-theme.js";
5
5
  import { BUILTIN_THEMES, DEFAULT_THEME, resolveTheme } from "../theme/themes.js";
6
+ import { DEFAULT_APPEARANCE, activeThemeId, resolveMotion } from "./headless/prefs.js";
7
+ import { fontsToCssVars } from "./headless/fonts.js";
6
8
  import { constant, useReadable } from "../chat/headless/store.js";
7
9
  import { codeThemeTypeOf } from "../code/code-themes.js";
8
10
  import { applyPalette } from "./apply.js";
9
- import { fontsToCssVars } from "./headless/fonts.js";
10
- import { DEFAULT_APPEARANCE, activeThemeId, resolveMotion } from "./headless/prefs.js";
11
11
  import { jsx } from "react/jsx-runtime";
12
12
  import { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore } from "react";
13
13
  //#region src/appearance/AppearanceProvider.tsx
@@ -1,5 +1,5 @@
1
- import { CURATED_FONTS, FONT_STACKS, availableCuratedFonts, cssFamily, fontStack, fontsToCssVars, guessKind, isFontAvailable, queryInstalledFonts } from "./fonts.js";
2
1
  import { DEFAULT_APPEARANCE, LIMITS, activeThemeId, parseAppearance, resolveMotion, stepInterfaceScale } from "./prefs.js";
3
2
  import { APPEARANCE_STORAGE_KEY, BOOT_SNAPSHOT_KEY, createStorageAppearancePrefs, createStorageBoot } from "./storage.js";
3
+ import { CURATED_FONTS, FONT_STACKS, availableCuratedFonts, cssFamily, fontStack, fontsToCssVars, guessKind, isFontAvailable, queryInstalledFonts } from "./fonts.js";
4
4
  import { zoomKeyCommands } from "./zoom-commands.js";
5
5
  export { APPEARANCE_STORAGE_KEY, BOOT_SNAPSHOT_KEY, CURATED_FONTS, DEFAULT_APPEARANCE, FONT_STACKS, LIMITS, activeThemeId, availableCuratedFonts, createStorageAppearancePrefs, createStorageBoot, cssFamily, fontStack, fontsToCssVars, guessKind, isFontAvailable, parseAppearance, queryInstalledFonts, resolveMotion, stepInterfaceScale, zoomKeyCommands };
@@ -1,6 +1,6 @@
1
- import { createApprovalHeads } from "./heads.js";
2
- import { DEFAULT_APPROVALS_LABELS } from "./labels.js";
3
1
  import { createPendingApprovals } from "./pending.js";
4
2
  import { createSafelist } from "./safelist.js";
3
+ import { createApprovalHeads } from "./heads.js";
4
+ import { DEFAULT_APPROVALS_LABELS } from "./labels.js";
5
5
  import { FILE_EDIT_TOOLS, allowDecision, approvalPath, approvalPreview, initialHunkMask, isFileEditApproval } from "./preview.js";
6
6
  export { DEFAULT_APPROVALS_LABELS, FILE_EDIT_TOOLS, allowDecision, approvalPath, approvalPreview, createApprovalHeads, createPendingApprovals, createSafelist, initialHunkMask, isFileEditApproval };
@@ -1,3 +1,5 @@
1
+ import { AuthSettingsTarget } from "./headless/transcript/auth-failure.js";
2
+ import "./headless/transcript/index.js";
1
3
  import { TranscriptProps } from "./Transcript.js";
2
4
  //#region src/chat/HostTranscript.d.ts
3
5
  /** Props for {@link HostTranscript}: the {@link TranscriptProps} minus the ones the host supplies (`events`, `streaming`, `sessionId`), plus `sessionId` and `onOpenSession`. */
@@ -8,12 +10,14 @@ interface HostTranscriptProps extends Omit<TranscriptProps, 'events' | 'streamin
8
10
  onOpenSession?(sessionId: string): void;
9
11
  /** Opens a new terminal of the session and types `input` into it (a reply's shell block). Absent: blocks offer no Run in a terminal. */
10
12
  onRunInTerminal?(input: string): void;
13
+ /** Opens Settings on the account (or MCP server) a failed sign-in names. Absent: its card has no Settings button. */
14
+ onOpenSettings?(target: AuthSettingsTarget): void;
11
15
  }
12
16
  /**
13
17
  * Renders a session's transcript from the {@link ChatHost} in context, with loading, earlier-messages, and row actions wired to the host.
14
18
  *
15
19
  * @param props - The {@link HostTranscriptProps}; other props pass through to {@link Transcript}.
16
20
  */
17
- declare function HostTranscript({ sessionId, onOpenSession, onRunInTerminal, ...props }: HostTranscriptProps): import("react").JSX.Element;
21
+ declare function HostTranscript({ sessionId, onOpenSession, onRunInTerminal, onOpenSettings, ...props }: HostTranscriptProps): import("react").JSX.Element;
18
22
  //#endregion
19
23
  export { HostTranscript, HostTranscriptProps };
@@ -1,5 +1,6 @@
1
1
  import { useReadable } from "./headless/store.js";
2
2
  import { useChatHost } from "./ChatProvider.js";
3
+ import { useSettingsHost } from "../settings/SettingsProvider.js";
3
4
  import { useChatLabels } from "./useChatLabels.js";
4
5
  import { TranscriptActionsProvider } from "./transcript/actions.js";
5
6
  import { DEFAULT_TRANSCRIPT_OPTIONS, Transcript } from "./Transcript.js";
@@ -11,7 +12,8 @@ import { useMemo } from "react";
11
12
  * shows a loading line until its history has arrived, an "Earlier messages"
12
13
  * control while older events exist, and binds the rows' actions to the host
13
14
  * (full tool output, stopping a call, continuing a failed run through
14
- * `send`). An action the host leaves out hides its control.
15
+ * `send`, fixing a failed sign-in over the nearest settings host's accounts).
16
+ * An action the host leaves out hides its control.
15
17
  *
16
18
  * <ChatProvider host={host}>
17
19
  * <HostTranscript sessionId={id} onOpenSession={setActive} />
@@ -26,8 +28,9 @@ const RING_STYLE = {
26
28
  *
27
29
  * @param props - The {@link HostTranscriptProps}; other props pass through to {@link Transcript}.
28
30
  */
29
- function HostTranscript({ sessionId, onOpenSession, onRunInTerminal, ...props }) {
31
+ function HostTranscript({ sessionId, onOpenSession, onRunInTerminal, onOpenSettings, ...props }) {
30
32
  const host = useChatHost();
33
+ const { providers, mcp } = useSettingsHost();
31
34
  const labels = useChatLabels();
32
35
  const transcript = useMemo(() => host.transcript(sessionId), [host, sessionId]);
33
36
  const state = useReadable(transcript);
@@ -40,12 +43,21 @@ function HostTranscript({ sessionId, onOpenSession, onRunInTerminal, ...props })
40
43
  sessionId,
41
44
  prompt
42
45
  }) } : {},
43
- ...onRunInTerminal ? { runInTerminal: onRunInTerminal } : {}
46
+ ...onRunInTerminal ? { runInTerminal: onRunInTerminal } : {},
47
+ ...providers || mcp?.signIn || onOpenSettings ? { accounts: {
48
+ cwd: "",
49
+ ...providers ? { providers } : {},
50
+ ...mcp?.signIn ? { mcp } : {},
51
+ ...onOpenSettings ? { openSettings: onOpenSettings } : {}
52
+ } } : {}
44
53
  }), [
45
54
  host,
46
55
  sessionId,
47
56
  onOpenSession,
48
- onRunInTerminal
57
+ onRunInTerminal,
58
+ providers,
59
+ mcp,
60
+ onOpenSettings
49
61
  ]);
50
62
  if (!state.hydrated) return /* @__PURE__ */ jsx("div", {
51
63
  role: "status",
@@ -27,7 +27,7 @@ declare function RunEstimatesProvider({ store, children }: RunEstimatesProviderP
27
27
  declare function useRunEstimate(sessionId: string | undefined, label?: string, store?: RunEstimatesStore): RunEstimateView | undefined;
28
28
  /** Props of {@link RunEstimateChip}. */
29
29
  interface RunEstimateChipProps {
30
- /** The estimate to count down. */
30
+ /** The estimate to count down, or the problem that keeps the run from having one. */
31
31
  estimate: RunEstimateView;
32
32
  /**
33
33
  * A line after the chip's own in its tooltip. A function is read when the
@@ -44,10 +44,12 @@ interface RunEstimateChipProps {
44
44
  * The time a run has left, counting down (`~11m`), in the info tint;
45
45
  * `almost done` once the estimate is spent, dimmed while the run waits on
46
46
  * the user, and `over` in the warning tint once the run is past its
47
- * estimate.
47
+ * estimate. A run the host could not estimate, for a reason that will not go
48
+ * away by itself (a rejected request, missing credentials), shows a muted
49
+ * warning mark whose tooltip says why.
48
50
  *
49
51
  * @param props - The `estimate`, a tooltip `detail`, `className` and `style`.
50
52
  */
51
- declare function RunEstimateChip({ estimate, detail, className, style }: RunEstimateChipProps): import("react").JSX.Element;
53
+ declare function RunEstimateChip(props: RunEstimateChipProps): import("react").JSX.Element;
52
54
  //#endregion
53
55
  export { RunEstimateChip, RunEstimateChipProps, RunEstimatesProvider, RunEstimatesProviderProps, useRunEstimate };
@@ -2,7 +2,7 @@ import { useChatLabels } from "./useChatLabels.js";
2
2
  import { pickRunEstimate } from "./headless/sidebar/estimates.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { createContext, useCallback, useContext, useEffect, useState, useSyncExternalStore } from "react";
5
- import { estimateReadout, formatEstimate } from "zidane/chat/pure";
5
+ import { estimateReadout, formatEstimate, isRunEstimated } from "zidane/chat/pure";
6
6
  //#region src/chat/RunEstimateChip.tsx
7
7
  /**
8
8
  * Run time estimates in a component (`Settings.runEstimates`): the app's
@@ -85,11 +85,41 @@ const TONE = {
85
85
  * The time a run has left, counting down (`~11m`), in the info tint;
86
86
  * `almost done` once the estimate is spent, dimmed while the run waits on
87
87
  * the user, and `over` in the warning tint once the run is past its
88
- * estimate.
88
+ * estimate. A run the host could not estimate, for a reason that will not go
89
+ * away by itself (a rejected request, missing credentials), shows a muted
90
+ * warning mark whose tooltip says why.
89
91
  *
90
92
  * @param props - The `estimate`, a tooltip `detail`, `className` and `style`.
91
93
  */
92
- function RunEstimateChip({ estimate, detail, className, style }) {
94
+ function RunEstimateChip(props) {
95
+ const { estimate } = props;
96
+ return isRunEstimated(estimate) ? /* @__PURE__ */ jsx(TimingChip, {
97
+ ...props,
98
+ estimate
99
+ }) : /* @__PURE__ */ jsx(ProblemMark, {
100
+ problem: estimate,
101
+ ...props.className ? { className: props.className } : {},
102
+ ...props.style ? { style: props.style } : {}
103
+ });
104
+ }
105
+ /** A run with no estimate, and why. */
106
+ function ProblemMark({ problem, className, style }) {
107
+ const title = useChatLabels().estimateProblemTitle(problem.problem.reason, problem.problem.message);
108
+ return /* @__PURE__ */ jsx("span", {
109
+ "data-testid": "run-estimate",
110
+ "data-state": "problem",
111
+ role: "img",
112
+ title,
113
+ "aria-label": title,
114
+ className: ["shrink-0 inline-flex self-center text-[var(--zg-text-subtle)]", className].filter(Boolean).join(" "),
115
+ style,
116
+ children: /* @__PURE__ */ jsx("span", {
117
+ "aria-hidden": true,
118
+ className: "i-ph-warning-circle text-zg-meta"
119
+ })
120
+ });
121
+ }
122
+ function TimingChip({ estimate, detail, className, style }) {
93
123
  const labels = useChatLabels();
94
124
  const { state, text } = useEstimateShown(estimate);
95
125
  const [readDetail, setReadDetail] = useState();
@@ -1,10 +1,10 @@
1
+ import { firstRowId } from "./headless/transcript/rows.js";
1
2
  import { useExtensionItems } from "../extensions/ExtensionsProvider.js";
2
3
  import { LinkSessionScope } from "../extensions/links.js";
3
4
  import { CvRow, TranscriptSettling } from "./transcript/LazyRow.js";
4
5
  import { MarkdownDiagrams } from "./transcript/markdown.js";
5
6
  import { useTranscriptActions } from "./transcript/actions.js";
6
7
  import { RowIconsContext } from "./transcript/frame.js";
7
- import { firstRowId } from "./headless/transcript/rows.js";
8
8
  import { ExtensionSlot } from "../extensions/ExtensionSlot.js";
9
9
  import { rowTurnIds, stopForRow } from "./headless/transcript/select-stops.js";
10
10
  import { rowCvStyle, rowEstimatePx } from "./transcript/row-estimate.js";
@@ -2,8 +2,8 @@ import { plainTextToDocJson } from "./prompt-history-nav.js";
2
2
  import { suggestionExtension } from "./suggestion-extension.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { useLayoutEffect } from "react";
5
- import Placeholder from "@tiptap/extension-placeholder";
6
5
  import { EditorContent, useEditor } from "@tiptap/react";
6
+ import Placeholder from "@tiptap/extension-placeholder";
7
7
  import StarterKit from "@tiptap/starter-kit";
8
8
  //#region src/chat/composer/ComposerEditor.tsx
9
9
  /**
@@ -1,6 +1,7 @@
1
+ import { remindersSummary } from "../../session/headless/schedules.js";
1
2
  import { useComposerLabels } from "./ComposerHostProvider.js";
2
3
  import { useExtensionItems, useExtensionsHost } from "../../extensions/ExtensionsProvider.js";
3
- import { useSessionHost, useSessionQueue, useSessionRunningWork, useSessionTodos } from "../../session/SessionProvider.js";
4
+ import { useSessionHost, useSessionPlans, useSessionQueue, useSessionRunningWork, useSessionSchedules } from "../../session/SessionProvider.js";
4
5
  import { slotItems } from "../../extensions/headless/select.js";
5
6
  import { ComposerBadges } from "./ComposerBadges.js";
6
7
  import { mergeBadgeOrder, orderComposerBadges } from "./badge-order.js";
@@ -13,13 +14,14 @@ import { memo, useCallback, useEffect, useMemo, useRef } from "react";
13
14
  /**
14
15
  * The composer's badge strip for one conversation (`ComposerBadges`, drawn
15
16
  * at the top of the composer's tray): what waits in the inbox, the todos'
16
- * progress, the queued messages, the running work you can stop, and what
17
+ * progress, the queued messages, the reminders that will fire (zidane's
18
+ * schedules, a click opens the Reminders tab), the running work you can stop, and what
17
19
  * extensions show with the session: their `composer.badges` slot items
18
20
  * (`ExtensionsHost`, a click runs the item's command or opens its panel).
19
21
  * What goes in, in which default order
20
22
  * and how many per extension, is `conversationBadges` (`zidane-ui/chat/headless`).
21
23
  *
22
- * The session's todos, queue and running work come from the `SessionHost`
24
+ * The session's plan, queue and running work come from the `SessionHost`
23
25
  * (`zidane-ui/session`), its pending requests from the `ChatHost`
24
26
  * (`interactions`). Running opens the app's Running work view
25
27
  * (`onOpenRunningWork`); it shows once a call has run a moment and stays a
@@ -36,16 +38,18 @@ const NO_ORDER = [];
36
38
  const ConversationBadges = memo(function ConversationBadges({ sessionId, showTodos = true, panels, onScreen = null, onOpenPanel, onClosePanel, order = NO_ORDER, onOrderChange, onOpenRunningWork, className, style }) {
37
39
  const labels = useComposerLabels();
38
40
  const interactions = usePendingInteractions(sessionId);
39
- const todos = useSessionTodos(sessionId);
40
- const fetchTodos = useSessionHost().todos?.refresh;
41
+ const plans = useSessionPlans(sessionId);
42
+ const fetchPlans = useSessionHost().plans?.refresh;
41
43
  const queued = useSessionQueue(sessionId).length;
42
44
  const slots = useExtensionItems("slot");
43
45
  const slotBadges = useMemo(() => slotItems(slots, "composer.badges", sessionId ?? void 0), [slots, sessionId]);
44
46
  const runCommand = useExtensionsHost()?.commands?.run;
45
47
  const work = useSustainedWork(sessionId, useSessionRunningWork(sessionId));
48
+ const scheduled = useSessionSchedules(sessionId);
49
+ const reminders = useMemo(() => remindersSummary(scheduled), [scheduled]);
46
50
  useEffect(() => {
47
- if (sessionId) fetchTodos?.(sessionId);
48
- }, [sessionId, fetchTodos]);
51
+ if (sessionId) fetchPlans?.(sessionId);
52
+ }, [sessionId, fetchPlans]);
49
53
  const head = interactions[0] ?? null;
50
54
  const waiting = interactions.length;
51
55
  const data = useMemo(() => conversationBadges({
@@ -54,21 +58,23 @@ const ConversationBadges = memo(function ConversationBadges({ sessionId, showTod
54
58
  head: head.request,
55
59
  live: head.live !== false
56
60
  } : null,
57
- todos,
61
+ plans,
58
62
  showTodos,
59
63
  queued,
60
64
  work,
61
65
  slotBadges,
62
- panels
66
+ panels,
67
+ reminders
63
68
  }, labels), [
64
69
  head,
65
70
  waiting,
66
- todos,
71
+ plans,
67
72
  showTodos,
68
73
  queued,
69
74
  work,
70
75
  slotBadges,
71
76
  panels,
77
+ reminders,
72
78
  labels
73
79
  ]);
74
80
  const shown = useRef(onScreen);
@@ -134,9 +134,9 @@ interface ComposerDraft {
134
134
  * REPLACE the composer's draft (Edit message): the editor holds `text`, the
135
135
  * staged attachments become `attachments`, and the caret lands at the end.
136
136
  *
137
- * @param draft - The draft, and the scope of the composer it is for.
137
+ * @param draft - The draft, and the scope of the composer it is for (absent: the window's).
138
138
  */
139
- declare function pushComposerDraft({ scopeKey, text, attachments }: ComposerDraft & ComposerTarget): void;
139
+ declare function pushComposerDraft({ scopeKey, text, attachments }: ComposerDraft & Partial<ComposerTarget>): void;
140
140
  /**
141
141
  * Takes the drafts pushed to a composer.
142
142
  *
@@ -223,13 +223,13 @@ function onComposerPrompt(scopeKey, handler) {
223
223
  * REPLACE the composer's draft (Edit message): the editor holds `text`, the
224
224
  * staged attachments become `attachments`, and the caret lands at the end.
225
225
  *
226
- * @param draft - The draft, and the scope of the composer it is for.
226
+ * @param draft - The draft, and the scope of the composer it is for (absent: the window's).
227
227
  */
228
228
  function pushComposerDraft({ scopeKey, text, attachments }) {
229
229
  dispatch(DRAFT_EVENT, {
230
230
  text,
231
231
  attachments
232
- }, { scopeKey });
232
+ }, scopeKey === void 0 ? void 0 : { scopeKey });
233
233
  }
234
234
  /**
235
235
  * Takes the drafts pushed to a composer.
@@ -1,6 +1,6 @@
1
- import { useComposerHost } from "./ComposerHostProvider.js";
2
1
  import { IDLE_RESOURCE } from "../../app/headless/resource.js";
3
2
  import { createModelPickerPrefs } from "../headless/composer/model-picker-prefs.js";
3
+ import { useComposerHost } from "./ComposerHostProvider.js";
4
4
  import { modelKnobsOf } from "../headless/composer/model-knobs.js";
5
5
  import { modelNamesOf } from "../headless/composer/model-names.js";
6
6
  import { useEffect, useMemo, useSyncExternalStore } from "react";
@@ -1,5 +1,5 @@
1
- import { useComposerHost } from "./ComposerHostProvider.js";
2
1
  import { EMPTY_RUN_METER } from "../headless/composer/run-meter.js";
2
+ import { useComposerHost } from "./ComposerHostProvider.js";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  //#region src/chat/composer/use-run-meter.ts
5
5
  /**
@@ -1,6 +1,7 @@
1
1
  import { ExtensionItem } from "../../../extensions/headless/wire.js";
2
2
  import { ComposerChromeLabels } from "./labels-chrome.js";
3
- import { InteractionRequest, TodosSnapshot } from "zidane/chat";
3
+ import { RemindersSummary } from "../../../session/headless/schedules.js";
4
+ import { InteractionRequest, PlansSnapshot } from "zidane/chat";
4
5
  import { RunningWorkItem } from "zidane/ipc";
5
6
  //#region src/chat/headless/composer/conversation-badges.d.ts
6
7
  /** One badge of the strip, as data (the kit's `ComposerBadge` without its click). */
@@ -48,8 +49,8 @@ interface InboxSummary {
48
49
  interface ConversationBadgeInput {
49
50
  /** The pending requests, `null` for none. */
50
51
  inbox: InboxSummary | null;
51
- /** The agent's todo list. */
52
- todos: TodosSnapshot | null;
52
+ /** The session's plans: the badge follows the plan worth a glance (`active`: applying, else stopped). */
53
+ plans: PlansSnapshot | null;
53
54
  /** `Settings.showTodoIndicator`. */
54
55
  showTodos: boolean;
55
56
  /** Messages in the conversation's queue. */
@@ -60,6 +61,10 @@ interface ConversationBadgeInput {
60
61
  slotBadges?: readonly ExtensionItem<'slot'>[];
61
62
  /** The conversation's panels (the catalog's ids): an extension badge opens one of them or nothing. */
62
63
  panels: ReadonlySet<string>;
64
+ /** The conversation's reminders that will fire (`remindersSummary`), `null` for none. */
65
+ reminders?: RemindersSummary | null;
66
+ /** The clock, for the next reminder's day words. @default Date.now() */
67
+ now?: number;
63
68
  }
64
69
  /** How many badges one extension shows in one composer (zidane's `MAX_COMPOSER_BADGES`). */
65
70
  declare const MAX_EXTENSION_COMPOSER_BADGES = 8;
@@ -1,10 +1,11 @@
1
- import { INBOX_PANEL_ID, QUEUE_PANEL_ID, TODOS_PANEL_ID } from "zidane/chat/pure";
1
+ import { INBOX_PANEL_ID, QUEUE_PANEL_ID, REMINDERS_PANEL_ID, describeTime, planProgressLabel } from "zidane/chat/pure";
2
2
  //#region src/chat/headless/composer/conversation-badges.ts
3
3
  /** Default slots: the built-ins lead, extensions sit at the kit's default (100). */
4
4
  const BADGE_ORDER = {
5
5
  inbox: 0,
6
6
  todos: 10,
7
7
  queue: 20,
8
+ reminders: 25,
8
9
  work: 30
9
10
  };
10
11
  /** How many badges one extension shows in one composer (zidane's `MAX_COMPOSER_BADGES`). */
@@ -19,7 +20,7 @@ const MAX_EXTENSION_COMPOSER_BADGES = 8;
19
20
  function conversationBadges(input, labels) {
20
21
  const out = [];
21
22
  if (input.inbox) out.push(inboxBadge(input.inbox, labels));
22
- const todos = input.showTodos && input.todos ? todosBadge(input.todos, labels) : null;
23
+ const todos = input.showTodos && input.plans ? todosBadge(input.plans, labels) : null;
23
24
  if (todos) out.push(todos);
24
25
  if (input.queued > 0) out.push({
25
26
  id: "queue",
@@ -30,6 +31,19 @@ function conversationBadges(input, labels) {
30
31
  order: BADGE_ORDER.queue,
31
32
  panel: QUEUE_PANEL_ID
32
33
  });
34
+ if (input.reminders) {
35
+ const when = describeTime(input.reminders.next, input.now ?? Date.now());
36
+ const short = when.startsWith("today ") ? when.slice(6) : when;
37
+ out.push({
38
+ id: "reminders",
39
+ label: labels.badgeReminders(short),
40
+ icon: "i-ph-alarm",
41
+ count: String(input.reminders.count),
42
+ title: labels.badgeRemindersTitle(input.reminders.count, when),
43
+ order: BADGE_ORDER.reminders,
44
+ panel: input.panels.has(REMINDERS_PANEL_ID) ? REMINDERS_PANEL_ID : null
45
+ });
46
+ }
33
47
  if (input.work.length > 0) out.push(workBadge(input.work, labels));
34
48
  const shown = /* @__PURE__ */ new Map();
35
49
  const room = (extension) => {
@@ -79,20 +93,21 @@ function inboxBadge({ count, head, live }, labels) {
79
93
  };
80
94
  }
81
95
  function todosBadge(snap, labels) {
82
- const archived = snap.todos.length === 0;
83
- const list = archived ? snap.archive : snap.todos;
84
- if (list.length === 0) return null;
85
- const done = list.filter((t) => t.status === "completed" || t.status === "cancelled").length;
86
- const progress = labels.badgeTodosProgress(done, list.length);
87
- const current = archived ? null : snap.inProgress ?? list.find((t) => t.status === "in_progress") ?? list.find((t) => t.status === "pending");
96
+ const active = snap.active;
97
+ if (!active || active.state !== "applying" && active.state !== "stopped") return null;
98
+ const count = planProgressLabel(active.progress);
99
+ if (!count) return null;
100
+ const { completed, cancelled, total, activeIndex } = active.progress;
101
+ const progress = labels.badgeTodosProgress(completed + cancelled, total);
102
+ const current = active.state === "applying" && activeIndex >= 0 ? snap.plans.find((p) => p.id === active.planId)?.steps[activeIndex] : void 0;
88
103
  return {
89
104
  id: "todos",
90
105
  label: labels.badgeTodos,
91
106
  icon: "i-ph-list-checks",
92
- count: `${done}/${list.length}`,
93
- title: current ? labels.badgeTodosCurrent(current.content, progress) : labels.badgeTodosLast(progress),
107
+ count,
108
+ title: active.state === "stopped" ? labels.badgeTodosStopped(progress) : current ? labels.badgeTodosCurrent(current.title, progress) : progress,
94
109
  order: BADGE_ORDER.todos,
95
- panel: TODOS_PANEL_ID
110
+ panel: INBOX_PANEL_ID
96
111
  };
97
112
  }
98
113
  function slotBadge(entry, panels) {
@@ -1,8 +1,8 @@
1
+ import { DEFAULT_MODEL_PICKER_PREFS, MODEL_PICKER_STORAGE_KEY, createModelPickerPrefs, parseModelPickerPrefs } from "./model-picker-prefs.js";
2
+ import { EMPTY_RUN_METER, createRunMeter } from "./run-meter.js";
1
3
  import { DEFAULT_COMPOSER_CHROME_LABELS } from "./labels-chrome.js";
2
4
  import { DEFAULT_COMPOSER_LABELS } from "./labels.js";
3
5
  import { findCommand } from "./commands.js";
4
- import { DEFAULT_MODEL_PICKER_PREFS, MODEL_PICKER_STORAGE_KEY, createModelPickerPrefs, parseModelPickerPrefs } from "./model-picker-prefs.js";
5
- import { EMPTY_RUN_METER, createRunMeter } from "./run-meter.js";
6
6
  import { composeLiveCost, formatSessionCostLabel } from "./live-cost.js";
7
7
  import { createModelKnobs, modelKnobsOf } from "./model-knobs.js";
8
8
  import { createModelNames, modelNamesOf, namerFor } from "./model-names.js";
@@ -16,7 +16,9 @@ declare const DEFAULT_COMPOSER_CHROME_LABELS: {
16
16
  badgeTodos: string;
17
17
  badgeTodosProgress: (done: number, total: number) => string;
18
18
  badgeTodosCurrent: (content: string, progress: string) => string;
19
- badgeTodosLast: (progress: string) => string;
19
+ badgeTodosStopped: (progress: string) => string;
20
+ badgeReminders: (when: string) => string;
21
+ badgeRemindersTitle: (n: number, when: string) => string;
20
22
  /** The archived session's banner. */
21
23
  archivedNotice: string;
22
24
  unarchive: string;