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,413 @@
1
+ import { IconButton } from "../components/IconButton.js";
2
+ import { buttonClass } from "../components/button.js";
3
+ import { MetaChip } from "../components/Form.js";
4
+ import { useMinuteTick } from "../hooks/useMinuteTick.js";
5
+ import { inboxPlans } from "./headless/plans.js";
6
+ import { useSessionHost, useSessionPlans } from "./SessionProvider.js";
7
+ import { useSessionLabels } from "./useSessionLabels.js";
8
+ import { ProseMarkdown } from "../chat/transcript/ProseMarkdown.js";
9
+ import { StepStatusIcon } from "./StepStatusIcon.js";
10
+ import { isDoneTodo } from "./TodoList.js";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ import { useEffect, useRef, useState } from "react";
13
+ import { buildPlanResumeMessage, buildStepRetryMessage, describeTime, planProgress } from "zidane/chat/pure";
14
+ //#region src/session/PlanTracker.tsx
15
+ /**
16
+ * One plan as a card, its steps live as the agent works: the Inbox's
17
+ * "In progress" card, and a "Recent" plan opened. At parity with the TUI's
18
+ * todos modal.
19
+ *
20
+ * Every edit goes to the host's plan gate (`plans.edit` / `plans.control`),
21
+ * never to a copy here: the agent reads the same plan and is told what
22
+ * changed. Only "which row is mid-edit", the add box and the drop
23
+ * confirmation are local.
24
+ *
25
+ * On an applying or stopped plan: click a step's text to rename it (Enter
26
+ * saves, Esc cancels, blur saves), retry asks the agent to redo the step,
27
+ * cancel marks it cancelled (a step is never deleted), the box adds a step,
28
+ * Stop stops the plan and the run applying it, Resume asks the agent to
29
+ * continue a stopped plan, Drop closes it after an inline confirm. A closed
30
+ * plan is read-only. Without `plans.edit` there is no add, rename or
31
+ * cancel; without `plans.control` no stop or drop; without `plans.retry` no
32
+ * retry or resume.
33
+ *
34
+ * const { current, recent } = useInboxPlans(sessionId)
35
+ * <PlanTracker sessionId={sessionId} plan={current} />
36
+ */
37
+ const INPUT_CLS = "zg-well flex-1 min-w-0 font-mono text-zg-label px-2.5 py-1 placeholder:text-[var(--zg-text-subtle)]";
38
+ const GHOST_BTN = buttonClass({
39
+ variant: "ghost",
40
+ size: "xs"
41
+ });
42
+ const ROW_ACTION_CLS = "opacity-0 group-hover:opacity-100 focus-visible:opacity-100";
43
+ /** The quiet note after a step's title: who cancelled it, or that it was added after approval. */
44
+ function stepMarker(step, labels) {
45
+ if (step.status === "cancelled" && step.cancelledBy === "user") return labels.stepCancelledByYou;
46
+ if (step.status === "cancelled" && step.cancelledBy === "agent") return labels.stepDroppedByAgent;
47
+ return step.added ? labels.stepAdded : null;
48
+ }
49
+ /**
50
+ * The tone of a plan's state chip.
51
+ *
52
+ * @param plan - The plan.
53
+ */
54
+ function planStateTone(plan) {
55
+ if (plan.state === "applying") return plan.possiblyInterrupted ? "muted" : "accent";
56
+ if (plan.state === "stopped") return "warn";
57
+ return plan.state === "done" ? "success" : "muted";
58
+ }
59
+ const NO_INBOX_PLANS = {
60
+ current: null,
61
+ recent: []
62
+ };
63
+ /**
64
+ * A session's plans for the Inbox: the one in progress and the recent ones. Reads the session from the host once.
65
+ *
66
+ * @param sessionId - The session.
67
+ */
68
+ function useInboxPlans(sessionId) {
69
+ const refresh = useSessionHost().plans?.refresh;
70
+ const snap = useSessionPlans(sessionId);
71
+ useEffect(() => {
72
+ refresh?.(sessionId);
73
+ }, [sessionId, refresh]);
74
+ return snap ? inboxPlans(snap.plans) : NO_INBOX_PLANS;
75
+ }
76
+ /**
77
+ * Renders one plan with its step edits, retry, add box, tally, and the plan's stop, resume and drop.
78
+ *
79
+ * @param props - The {@link PlanTrackerProps}.
80
+ */
81
+ function PlanTracker({ sessionId, plan, hideHeader = false, className, style }) {
82
+ const labels = useSessionLabels();
83
+ const host = useSessionHost().plans;
84
+ const edit = host?.edit;
85
+ const control = host?.control;
86
+ const retryRun = host?.retry;
87
+ const steps = plan?.steps ?? [];
88
+ const applying = plan?.state === "applying";
89
+ const stopped = plan?.state === "stopped";
90
+ const open = applying || stopped;
91
+ const canEdit = open && Boolean(edit);
92
+ const progress = planProgress(plan);
93
+ const hasActions = Boolean(open && control || stopped && retryRun);
94
+ const stopStep = plan.stoppedAt ? steps.findIndex((s) => s.id === plan.stoppedAt) + 1 : 0;
95
+ const [editingId, setEditingId] = useState(null);
96
+ const [draft, setDraft] = useState("");
97
+ const [adding, setAdding] = useState("");
98
+ const [error, setError] = useState(null);
99
+ const [confirmDrop, setConfirmDrop] = useState(false);
100
+ const editRef = useRef(null);
101
+ const planKey = `${plan.id}:${open}`;
102
+ const [shownKey, setShownKey] = useState(planKey);
103
+ if (shownKey !== planKey) {
104
+ setShownKey(planKey);
105
+ setEditingId(null);
106
+ setConfirmDrop(false);
107
+ }
108
+ useEffect(() => {
109
+ if (editingId) {
110
+ editRef.current?.focus();
111
+ editRef.current?.select();
112
+ }
113
+ }, [editingId]);
114
+ /** Runs a host call; its rejection (the gate's reason) shows under the list. */
115
+ const run = (call) => {
116
+ if (!call) return;
117
+ setError(null);
118
+ call.catch((err) => setError(err instanceof Error ? err.message : String(err)));
119
+ };
120
+ const startEdit = (step) => {
121
+ if (!canEdit) return;
122
+ setEditingId(step.id);
123
+ setDraft(step.title);
124
+ };
125
+ const saveEdit = () => {
126
+ if (!editingId) return;
127
+ const step = steps.find((s) => s.id === editingId);
128
+ const title = draft.trim();
129
+ if (step && title.length > 0 && title !== step.title) run(edit?.(sessionId, plan.id, {
130
+ kind: "rename",
131
+ stepId: step.id,
132
+ title
133
+ }));
134
+ setEditingId(null);
135
+ };
136
+ const submitAdd = () => {
137
+ const title = adding.trim();
138
+ if (title.length === 0) return;
139
+ run(edit?.(sessionId, plan.id, {
140
+ kind: "add",
141
+ title
142
+ }));
143
+ setAdding("");
144
+ };
145
+ return /* @__PURE__ */ jsxs("div", {
146
+ className: ["flex flex-col gap-2 py-2", className].filter(Boolean).join(" "),
147
+ style,
148
+ "data-plan-state": plan.state,
149
+ "data-testid": "plan-tracker",
150
+ children: [
151
+ !hideHeader && /* @__PURE__ */ jsxs("div", {
152
+ className: "flex items-center gap-2 px-2 min-w-0",
153
+ children: [
154
+ /* @__PURE__ */ jsx("span", {
155
+ className: "flex-1 min-w-0 truncate text-zg-ui font-medium text-[var(--zg-text)]",
156
+ title: plan.title || void 0,
157
+ children: plan.title || labels.planUntitled
158
+ }),
159
+ /* @__PURE__ */ jsx(MetaChip, {
160
+ tone: planStateTone(plan),
161
+ children: labels.planState[plan.state]
162
+ }),
163
+ /* @__PURE__ */ jsx("span", {
164
+ "data-testid": "todo-progress",
165
+ className: "flex shrink-0",
166
+ children: /* @__PURE__ */ jsx(MetaChip, { children: labels.todosProgress(progress.completed + progress.cancelled, progress.total) })
167
+ })
168
+ ]
169
+ }),
170
+ stopped && /* @__PURE__ */ jsx("p", {
171
+ className: "m-0 px-2 text-zg-meta text-[var(--zg-warn)]",
172
+ children: labels.planStopped(stopStep > 0 ? stopStep : null, plan.stopReason)
173
+ }),
174
+ applying && plan.possiblyInterrupted && /* @__PURE__ */ jsx("p", {
175
+ className: "m-0 px-2 text-zg-meta text-[var(--zg-text-muted)]",
176
+ children: labels.planMaybeInterrupted
177
+ }),
178
+ plan.body && /* @__PURE__ */ jsx("div", {
179
+ "data-testid": "plan-body",
180
+ className: "px-2 text-zg-ui text-[var(--zg-text)] zg-pretty",
181
+ children: /* @__PURE__ */ jsx(ProseMarkdown, { children: plan.body })
182
+ }),
183
+ steps.length === 0 && /* @__PURE__ */ jsx("p", {
184
+ className: "m-0 px-2 text-zg-meta text-[var(--zg-text-muted)]",
185
+ children: labels.planNoSteps
186
+ }),
187
+ /* @__PURE__ */ jsx("ol", {
188
+ className: "flex flex-col gap-1.5 m-0 px-2 list-none",
189
+ children: steps.map((step, i) => {
190
+ const dim = isDoneTodo(step.status);
191
+ const marker = stepMarker(step, labels);
192
+ const haltedHere = stopped && step.id === plan.stoppedAt && !dim;
193
+ return /* @__PURE__ */ jsxs("li", {
194
+ "data-status": step.status,
195
+ className: "group flex items-start gap-2 zg-tray rounded-zg-md px-2.5 py-2",
196
+ children: [
197
+ /* @__PURE__ */ jsx("span", {
198
+ className: "flex items-center h-6 shrink-0",
199
+ children: /* @__PURE__ */ jsx(StepStatusIcon, {
200
+ state: haltedHere ? "stopped" : step.status,
201
+ label: labels.todoStatus(step.status),
202
+ className: "text-zg-ui"
203
+ })
204
+ }),
205
+ /* @__PURE__ */ jsxs("span", {
206
+ className: "zg-meta leading-6 w-4 shrink-0",
207
+ children: [i + 1, "."]
208
+ }),
209
+ /* @__PURE__ */ jsxs("div", {
210
+ className: "flex-1 min-w-0 flex flex-col",
211
+ children: [
212
+ editingId === step.id ? /* @__PURE__ */ jsx("input", {
213
+ ref: editRef,
214
+ type: "text",
215
+ value: draft,
216
+ spellCheck: false,
217
+ "aria-label": labels.todoEdit,
218
+ onChange: (e) => setDraft(e.target.value),
219
+ onBlur: saveEdit,
220
+ onKeyDown: (e) => {
221
+ if (e.key === "Enter") saveEdit();
222
+ if (e.key === "Escape") setEditingId(null);
223
+ },
224
+ className: INPUT_CLS
225
+ }) : /* @__PURE__ */ jsx("button", {
226
+ type: "button",
227
+ disabled: !canEdit,
228
+ onClick: () => startEdit(step),
229
+ title: canEdit ? labels.todoEdit : step.title,
230
+ className: `min-w-0 text-left text-zg-ui leading-6 font-medium bg-transparent border-0 p-0 cursor-text disabled:cursor-default zg-balance transition-colors ${dim ? "text-[var(--zg-text-muted)]" : "text-[var(--zg-text)]"}${step.status === "cancelled" ? " line-through" : ""}`,
231
+ children: step.title
232
+ }),
233
+ step.description && /* @__PURE__ */ jsx("span", {
234
+ className: "text-zg-meta mt-0.5 text-[var(--zg-text-muted)] zg-pretty",
235
+ children: step.description
236
+ }),
237
+ step.note && /* @__PURE__ */ jsx("span", {
238
+ className: "text-zg-meta leading-4 text-[var(--zg-text-subtle)] italic zg-pretty",
239
+ children: labels.stepAgentNote(step.note)
240
+ })
241
+ ]
242
+ }),
243
+ marker && /* @__PURE__ */ jsx("span", {
244
+ className: "zg-meta shrink-0",
245
+ children: marker
246
+ }),
247
+ open && retryRun && /* @__PURE__ */ jsx(IconButton, {
248
+ size: "xs",
249
+ icon: "i-ph-arrow-clockwise",
250
+ label: labels.todoRetry,
251
+ title: labels.todoRetryHint,
252
+ onClick: () => run(retryRun(sessionId, buildStepRetryMessage(step))),
253
+ className: ROW_ACTION_CLS
254
+ }),
255
+ canEdit && !dim && /* @__PURE__ */ jsx(IconButton, {
256
+ size: "xs",
257
+ icon: "i-ph-x",
258
+ label: labels.stepCancel,
259
+ title: labels.stepCancelHint,
260
+ tone: "danger",
261
+ onClick: () => run(edit?.(sessionId, plan.id, {
262
+ kind: "cancel",
263
+ stepId: step.id
264
+ })),
265
+ className: ROW_ACTION_CLS
266
+ })
267
+ ]
268
+ }, step.id);
269
+ })
270
+ }),
271
+ (error || canEdit || hasActions) && /* @__PURE__ */ jsxs("div", {
272
+ className: "flex flex-col gap-2 px-2",
273
+ children: [
274
+ error && /* @__PURE__ */ jsx("div", {
275
+ className: "text-zg-meta text-[var(--zg-warn)]",
276
+ role: "alert",
277
+ children: error
278
+ }),
279
+ canEdit && /* @__PURE__ */ jsxs("div", {
280
+ className: "flex items-center gap-2",
281
+ children: [/* @__PURE__ */ jsx("input", {
282
+ type: "text",
283
+ placeholder: labels.todoAddPlaceholder,
284
+ "aria-label": labels.todoAddLabel,
285
+ value: adding,
286
+ spellCheck: false,
287
+ onChange: (e) => setAdding(e.target.value),
288
+ onKeyDown: (e) => {
289
+ if (e.key === "Enter") submitAdd();
290
+ },
291
+ className: INPUT_CLS
292
+ }), /* @__PURE__ */ jsx("button", {
293
+ type: "button",
294
+ className: GHOST_BTN,
295
+ disabled: adding.trim().length === 0,
296
+ onClick: submitAdd,
297
+ children: labels.todoAdd
298
+ })]
299
+ }),
300
+ hasActions && /* @__PURE__ */ jsx("div", {
301
+ className: "flex items-center justify-end gap-3 min-h-6",
302
+ children: confirmDrop && control ? /* @__PURE__ */ jsxs("span", {
303
+ className: "flex items-center gap-1.5 text-zg-meta",
304
+ children: [
305
+ /* @__PURE__ */ jsx("span", {
306
+ className: "text-[var(--zg-text-muted)]",
307
+ children: labels.planDropConfirm(applying)
308
+ }),
309
+ /* @__PURE__ */ jsx("button", {
310
+ type: "button",
311
+ className: `${GHOST_BTN} text-[var(--zg-error)]`,
312
+ onClick: () => {
313
+ run(control(sessionId, plan.id, "drop"));
314
+ setConfirmDrop(false);
315
+ },
316
+ children: labels.planDropYes
317
+ }),
318
+ /* @__PURE__ */ jsx("button", {
319
+ type: "button",
320
+ className: GHOST_BTN,
321
+ onClick: () => setConfirmDrop(false),
322
+ children: labels.planDropCancel
323
+ })
324
+ ]
325
+ }) : /* @__PURE__ */ jsxs("span", {
326
+ className: "flex items-center gap-1",
327
+ children: [
328
+ applying && control && /* @__PURE__ */ jsx("button", {
329
+ type: "button",
330
+ className: GHOST_BTN,
331
+ title: labels.planStopHint,
332
+ onClick: () => run(control(sessionId, plan.id, "stop")),
333
+ children: labels.planStop
334
+ }),
335
+ stopped && retryRun && /* @__PURE__ */ jsx("button", {
336
+ type: "button",
337
+ className: GHOST_BTN,
338
+ title: labels.planResumeHint,
339
+ onClick: () => run(retryRun(sessionId, buildPlanResumeMessage(plan))),
340
+ children: labels.planResume
341
+ }),
342
+ open && control && /* @__PURE__ */ jsx("button", {
343
+ type: "button",
344
+ className: GHOST_BTN,
345
+ title: labels.planDropHint,
346
+ onClick: () => setConfirmDrop(true),
347
+ children: labels.planDrop
348
+ })
349
+ ]
350
+ })
351
+ })
352
+ ]
353
+ })
354
+ ]
355
+ });
356
+ }
357
+ /**
358
+ * The Inbox's "Recent" plans: one line each (title, how it ended, its tally), opened in place to read its steps.
359
+ *
360
+ * @param props - The {@link RecentPlansProps}.
361
+ */
362
+ function RecentPlans({ sessionId, plans, className, style }) {
363
+ const labels = useSessionLabels();
364
+ const [open, setOpen] = useState(null);
365
+ useMinuteTick();
366
+ const now = Date.now();
367
+ return /* @__PURE__ */ jsx("ul", {
368
+ className: ["m-0 p-0 list-none flex flex-col gap-1", className].filter(Boolean).join(" "),
369
+ style,
370
+ children: plans.map((plan) => {
371
+ const progress = planProgress(plan);
372
+ const expanded = open === plan.id;
373
+ return /* @__PURE__ */ jsxs("li", {
374
+ "data-testid": "recent-plan",
375
+ "data-plan-state": plan.state,
376
+ className: "zg-raised border rounded-zg-lg overflow-hidden",
377
+ children: [/* @__PURE__ */ jsxs("button", {
378
+ type: "button",
379
+ "aria-expanded": expanded,
380
+ onClick: () => setOpen(expanded ? null : plan.id),
381
+ className: "flex items-center gap-2 w-full px-3 py-2 text-left bg-transparent border-0 cursor-pointer hover:bg-[var(--zg-row-hover)]",
382
+ children: [
383
+ /* @__PURE__ */ jsx("span", {
384
+ className: "flex-1 min-w-0 truncate text-zg-ui text-[var(--zg-text)]",
385
+ children: plan.title || labels.planUntitled
386
+ }),
387
+ /* @__PURE__ */ jsx(MetaChip, {
388
+ title: new Date(plan.createdAt).toLocaleString(),
389
+ className: "tabular-nums",
390
+ children: describeTime(plan.createdAt, now)
391
+ }),
392
+ /* @__PURE__ */ jsx(MetaChip, {
393
+ tone: planStateTone(plan),
394
+ children: labels.planState[plan.state]
395
+ }),
396
+ /* @__PURE__ */ jsx(MetaChip, { children: labels.todosProgress(progress.completed + progress.cancelled, progress.total) }),
397
+ /* @__PURE__ */ jsx("span", {
398
+ "aria-hidden": true,
399
+ className: `${expanded ? "i-ph-caret-up" : "i-ph-caret-down"} text-zg-label text-[var(--zg-text-muted)]`
400
+ })
401
+ ]
402
+ }), expanded && /* @__PURE__ */ jsx(PlanTracker, {
403
+ sessionId,
404
+ plan,
405
+ hideHeader: true,
406
+ className: "px-1 pb-2"
407
+ })]
408
+ }, plan.id);
409
+ })
410
+ });
411
+ }
412
+ //#endregion
413
+ export { PlanTracker, RecentPlans, planStateTone, useInboxPlans };
@@ -1,7 +1,15 @@
1
1
  import { WorkspacePanels } from "../workspace/headless/host.js";
2
2
  import { PanelOpenEvent } from "../workspace/PanelContentView.js";
3
3
  import { CSSProperties, ReactNode } from "react";
4
+ import { PanelStartSession } from "zidane/chat/pure";
4
5
  //#region src/session/ProjectHome.d.ts
6
+ /** What a block row's start answered: done, or why not in words. */
7
+ type ProjectHomeStartResult = {
8
+ ok: true;
9
+ } | {
10
+ ok: false;
11
+ message: string;
12
+ };
5
13
  /** The project a home is for. */
6
14
  interface ProjectHomeProject {
7
15
  /** Its name (the folder's). */
@@ -57,6 +65,11 @@ interface ProjectHomeProps {
57
65
  onOpenSession?: (sessionId: string) => void;
58
66
  /** Opens a block row's path. */
59
67
  onOpenPath?: (path: string, event?: PanelOpenEvent) => void;
68
+ /**
69
+ * A block row's "start a session" (a pull request's Open in worktree, a ticket's Open here): sets up the new-chat
70
+ * draft (`useStartFromPanel`, `zidane-ui/git`). A failure shows on the block. Absent: those buttons are not offered.
71
+ */
72
+ onStartSession?: (start: PanelStartSession) => Promise<ProjectHomeStartResult>;
60
73
  /** A click on the repository chip (its web page, or the working tree). Absent: the chip is plain text. */
61
74
  onOpenRepo?: () => void;
62
75
  /** A click on the project's path chip: open the Files panel. Absent: the chip is plain text. */
@@ -77,6 +90,6 @@ interface ProjectHomeProps {
77
90
  *
78
91
  * @param props - The {@link ProjectHomeProps}.
79
92
  */
80
- declare function ProjectHome({ panels, cwd, projectKey, project, switcher, blocksUnavailable, defaultBlocks, onOpenSession, onOpenPath, onOpenRepo, onOpenFiles, onRevealPath, onOpenInEditor, now: nowProp, className, style }: ProjectHomeProps): import("react").JSX.Element;
93
+ declare function ProjectHome({ panels, cwd, projectKey, project, switcher, blocksUnavailable, defaultBlocks, onOpenSession, onOpenPath, onStartSession, onOpenRepo, onOpenFiles, onRevealPath, onOpenInEditor, now: nowProp, className, style }: ProjectHomeProps): import("react").JSX.Element;
81
94
  //#endregion
82
- export { ProjectHome, ProjectHomeProject, ProjectHomeProps, ProjectHomeRepo, ProjectHomeSwitcher };
95
+ export { ProjectHome, ProjectHomeProject, ProjectHomeProps, ProjectHomeRepo, ProjectHomeStartResult, ProjectHomeSwitcher };