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
@@ -0,0 +1,54 @@
1
+ import { InboxPlans } from "./headless/plans.js";
2
+ import { CSSProperties } from "react";
3
+ import { PlanView } from "zidane/chat";
4
+ //#region src/session/PlanTracker.d.ts
5
+ /** Props for {@link PlanTracker}. */
6
+ interface PlanTrackerProps {
7
+ /** The session the plan belongs to. */
8
+ sessionId: string;
9
+ /** The plan to show. */
10
+ plan: PlanView;
11
+ /** Leave out the title row (a "Recent" row opened already shows it). */
12
+ hideHeader?: boolean;
13
+ /** Extra classes on the root element. */
14
+ className?: string;
15
+ /** Inline styles on the root element. */
16
+ style?: CSSProperties;
17
+ }
18
+ /**
19
+ * The tone of a plan's state chip.
20
+ *
21
+ * @param plan - The plan.
22
+ */
23
+ declare function planStateTone(plan: PlanView): 'accent' | 'warn' | 'success' | 'muted';
24
+ /**
25
+ * A session's plans for the Inbox: the one in progress and the recent ones. Reads the session from the host once.
26
+ *
27
+ * @param sessionId - The session.
28
+ */
29
+ declare function useInboxPlans(sessionId: string): InboxPlans;
30
+ /**
31
+ * Renders one plan with its step edits, retry, add box, tally, and the plan's stop, resume and drop.
32
+ *
33
+ * @param props - The {@link PlanTrackerProps}.
34
+ */
35
+ declare function PlanTracker({ sessionId, plan, hideHeader, className, style }: PlanTrackerProps): import("react").JSX.Element;
36
+ /** Props for {@link RecentPlans}. */
37
+ interface RecentPlansProps {
38
+ /** The session the plans belong to. */
39
+ sessionId: string;
40
+ /** Closed plans, newest first (`useInboxPlans`). */
41
+ plans: readonly PlanView[];
42
+ /** Extra classes on the root element. */
43
+ className?: string;
44
+ /** Inline styles on the root element. */
45
+ style?: CSSProperties;
46
+ }
47
+ /**
48
+ * The Inbox's "Recent" plans: one line each (title, how it ended, its tally), opened in place to read its steps.
49
+ *
50
+ * @param props - The {@link RecentPlansProps}.
51
+ */
52
+ declare function RecentPlans({ sessionId, plans, className, style }: RecentPlansProps): import("react").JSX.Element;
53
+ //#endregion
54
+ export { PlanTracker, PlanTrackerProps, RecentPlans, RecentPlansProps, planStateTone, useInboxPlans };
@@ -0,0 +1,412 @@
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
+ children: /* @__PURE__ */ jsx(MetaChip, { children: labels.todosProgress(progress.completed + progress.cancelled, progress.total) })
166
+ })
167
+ ]
168
+ }),
169
+ stopped && /* @__PURE__ */ jsx("p", {
170
+ className: "m-0 px-2 text-zg-meta text-[var(--zg-warn)]",
171
+ children: labels.planStopped(stopStep > 0 ? stopStep : null, plan.stopReason)
172
+ }),
173
+ applying && plan.possiblyInterrupted && /* @__PURE__ */ jsx("p", {
174
+ className: "m-0 px-2 text-zg-meta text-[var(--zg-text-muted)]",
175
+ children: labels.planMaybeInterrupted
176
+ }),
177
+ plan.body && /* @__PURE__ */ jsx("div", {
178
+ "data-testid": "plan-body",
179
+ className: "px-2 text-zg-ui text-[var(--zg-text)] zg-pretty",
180
+ children: /* @__PURE__ */ jsx(ProseMarkdown, { children: plan.body })
181
+ }),
182
+ steps.length === 0 && /* @__PURE__ */ jsx("p", {
183
+ className: "m-0 px-2 text-zg-meta text-[var(--zg-text-muted)]",
184
+ children: labels.planNoSteps
185
+ }),
186
+ /* @__PURE__ */ jsx("ol", {
187
+ className: "flex flex-col gap-1.5 m-0 px-2 list-none",
188
+ children: steps.map((step, i) => {
189
+ const dim = isDoneTodo(step.status);
190
+ const marker = stepMarker(step, labels);
191
+ const haltedHere = stopped && step.id === plan.stoppedAt && !dim;
192
+ return /* @__PURE__ */ jsxs("li", {
193
+ "data-status": step.status,
194
+ className: "group flex items-start gap-2 zg-tray rounded-zg-md px-2.5 py-2",
195
+ children: [
196
+ /* @__PURE__ */ jsx("span", {
197
+ className: "flex items-center h-6 shrink-0",
198
+ children: /* @__PURE__ */ jsx(StepStatusIcon, {
199
+ state: haltedHere ? "stopped" : step.status,
200
+ label: labels.todoStatus(step.status),
201
+ className: "text-zg-ui"
202
+ })
203
+ }),
204
+ /* @__PURE__ */ jsxs("span", {
205
+ className: "zg-meta leading-6 w-4 shrink-0",
206
+ children: [i + 1, "."]
207
+ }),
208
+ /* @__PURE__ */ jsxs("div", {
209
+ className: "flex-1 min-w-0 flex flex-col",
210
+ children: [
211
+ editingId === step.id ? /* @__PURE__ */ jsx("input", {
212
+ ref: editRef,
213
+ type: "text",
214
+ value: draft,
215
+ spellCheck: false,
216
+ "aria-label": labels.todoEdit,
217
+ onChange: (e) => setDraft(e.target.value),
218
+ onBlur: saveEdit,
219
+ onKeyDown: (e) => {
220
+ if (e.key === "Enter") saveEdit();
221
+ if (e.key === "Escape") setEditingId(null);
222
+ },
223
+ className: INPUT_CLS
224
+ }) : /* @__PURE__ */ jsx("button", {
225
+ type: "button",
226
+ disabled: !canEdit,
227
+ onClick: () => startEdit(step),
228
+ title: canEdit ? labels.todoEdit : step.title,
229
+ 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" : ""}`,
230
+ children: step.title
231
+ }),
232
+ step.description && /* @__PURE__ */ jsx("span", {
233
+ className: "text-zg-meta mt-0.5 text-[var(--zg-text-muted)] zg-pretty",
234
+ children: step.description
235
+ }),
236
+ step.note && /* @__PURE__ */ jsx("span", {
237
+ className: "text-zg-meta leading-4 text-[var(--zg-text-subtle)] italic zg-pretty",
238
+ children: labels.stepAgentNote(step.note)
239
+ })
240
+ ]
241
+ }),
242
+ marker && /* @__PURE__ */ jsx("span", {
243
+ className: "zg-meta shrink-0",
244
+ children: marker
245
+ }),
246
+ open && retryRun && /* @__PURE__ */ jsx(IconButton, {
247
+ size: "xs",
248
+ icon: "i-ph-arrow-clockwise",
249
+ label: labels.todoRetry,
250
+ title: labels.todoRetryHint,
251
+ onClick: () => run(retryRun(sessionId, buildStepRetryMessage(step))),
252
+ className: ROW_ACTION_CLS
253
+ }),
254
+ canEdit && !dim && /* @__PURE__ */ jsx(IconButton, {
255
+ size: "xs",
256
+ icon: "i-ph-x",
257
+ label: labels.stepCancel,
258
+ title: labels.stepCancelHint,
259
+ tone: "danger",
260
+ onClick: () => run(edit?.(sessionId, plan.id, {
261
+ kind: "cancel",
262
+ stepId: step.id
263
+ })),
264
+ className: ROW_ACTION_CLS
265
+ })
266
+ ]
267
+ }, step.id);
268
+ })
269
+ }),
270
+ (error || canEdit || hasActions) && /* @__PURE__ */ jsxs("div", {
271
+ className: "flex flex-col gap-2 px-2",
272
+ children: [
273
+ error && /* @__PURE__ */ jsx("div", {
274
+ className: "text-zg-meta text-[var(--zg-warn)]",
275
+ role: "alert",
276
+ children: error
277
+ }),
278
+ canEdit && /* @__PURE__ */ jsxs("div", {
279
+ className: "flex items-center gap-2",
280
+ children: [/* @__PURE__ */ jsx("input", {
281
+ type: "text",
282
+ placeholder: labels.todoAddPlaceholder,
283
+ "aria-label": labels.todoAddLabel,
284
+ value: adding,
285
+ spellCheck: false,
286
+ onChange: (e) => setAdding(e.target.value),
287
+ onKeyDown: (e) => {
288
+ if (e.key === "Enter") submitAdd();
289
+ },
290
+ className: INPUT_CLS
291
+ }), /* @__PURE__ */ jsx("button", {
292
+ type: "button",
293
+ className: GHOST_BTN,
294
+ disabled: adding.trim().length === 0,
295
+ onClick: submitAdd,
296
+ children: labels.todoAdd
297
+ })]
298
+ }),
299
+ hasActions && /* @__PURE__ */ jsx("div", {
300
+ className: "flex items-center justify-end gap-3 min-h-6",
301
+ children: confirmDrop && control ? /* @__PURE__ */ jsxs("span", {
302
+ className: "flex items-center gap-1.5 text-zg-meta",
303
+ children: [
304
+ /* @__PURE__ */ jsx("span", {
305
+ className: "text-[var(--zg-text-muted)]",
306
+ children: labels.planDropConfirm(applying)
307
+ }),
308
+ /* @__PURE__ */ jsx("button", {
309
+ type: "button",
310
+ className: `${GHOST_BTN} text-[var(--zg-error)]`,
311
+ onClick: () => {
312
+ run(control(sessionId, plan.id, "drop"));
313
+ setConfirmDrop(false);
314
+ },
315
+ children: labels.planDropYes
316
+ }),
317
+ /* @__PURE__ */ jsx("button", {
318
+ type: "button",
319
+ className: GHOST_BTN,
320
+ onClick: () => setConfirmDrop(false),
321
+ children: labels.planDropCancel
322
+ })
323
+ ]
324
+ }) : /* @__PURE__ */ jsxs("span", {
325
+ className: "flex items-center gap-1",
326
+ children: [
327
+ applying && control && /* @__PURE__ */ jsx("button", {
328
+ type: "button",
329
+ className: GHOST_BTN,
330
+ title: labels.planStopHint,
331
+ onClick: () => run(control(sessionId, plan.id, "stop")),
332
+ children: labels.planStop
333
+ }),
334
+ stopped && retryRun && /* @__PURE__ */ jsx("button", {
335
+ type: "button",
336
+ className: GHOST_BTN,
337
+ title: labels.planResumeHint,
338
+ onClick: () => run(retryRun(sessionId, buildPlanResumeMessage(plan))),
339
+ children: labels.planResume
340
+ }),
341
+ open && control && /* @__PURE__ */ jsx("button", {
342
+ type: "button",
343
+ className: GHOST_BTN,
344
+ title: labels.planDropHint,
345
+ onClick: () => setConfirmDrop(true),
346
+ children: labels.planDrop
347
+ })
348
+ ]
349
+ })
350
+ })
351
+ ]
352
+ })
353
+ ]
354
+ });
355
+ }
356
+ /**
357
+ * The Inbox's "Recent" plans: one line each (title, how it ended, its tally), opened in place to read its steps.
358
+ *
359
+ * @param props - The {@link RecentPlansProps}.
360
+ */
361
+ function RecentPlans({ sessionId, plans, className, style }) {
362
+ const labels = useSessionLabels();
363
+ const [open, setOpen] = useState(null);
364
+ useMinuteTick();
365
+ const now = Date.now();
366
+ return /* @__PURE__ */ jsx("ul", {
367
+ className: ["m-0 p-0 list-none flex flex-col gap-1", className].filter(Boolean).join(" "),
368
+ style,
369
+ children: plans.map((plan) => {
370
+ const progress = planProgress(plan);
371
+ const expanded = open === plan.id;
372
+ return /* @__PURE__ */ jsxs("li", {
373
+ "data-testid": "recent-plan",
374
+ "data-plan-state": plan.state,
375
+ className: "zg-raised border rounded-zg-lg overflow-hidden",
376
+ children: [/* @__PURE__ */ jsxs("button", {
377
+ type: "button",
378
+ "aria-expanded": expanded,
379
+ onClick: () => setOpen(expanded ? null : plan.id),
380
+ 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)]",
381
+ children: [
382
+ /* @__PURE__ */ jsx("span", {
383
+ className: "flex-1 min-w-0 truncate text-zg-ui text-[var(--zg-text)]",
384
+ children: plan.title || labels.planUntitled
385
+ }),
386
+ /* @__PURE__ */ jsx(MetaChip, {
387
+ title: new Date(plan.createdAt).toLocaleString(),
388
+ className: "tabular-nums",
389
+ children: describeTime(plan.createdAt, now)
390
+ }),
391
+ /* @__PURE__ */ jsx(MetaChip, {
392
+ tone: planStateTone(plan),
393
+ children: labels.planState[plan.state]
394
+ }),
395
+ /* @__PURE__ */ jsx(MetaChip, { children: labels.todosProgress(progress.completed + progress.cancelled, progress.total) }),
396
+ /* @__PURE__ */ jsx("span", {
397
+ "aria-hidden": true,
398
+ className: `${expanded ? "i-ph-caret-up" : "i-ph-caret-down"} text-zg-label text-[var(--zg-text-muted)]`
399
+ })
400
+ ]
401
+ }), expanded && /* @__PURE__ */ jsx(PlanTracker, {
402
+ sessionId,
403
+ plan,
404
+ hideHeader: true,
405
+ className: "px-1 pb-2"
406
+ })]
407
+ }, plan.id);
408
+ })
409
+ });
410
+ }
411
+ //#endregion
412
+ 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 };