@blade-hq/agent-kit 1.0.25 → 1.0.27

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 (281) hide show
  1. package/dist/{chunk-M45K3554.js → chunk-34GDDOWY.js} +5 -3
  2. package/dist/chunk-34GDDOWY.js.map +1 -0
  3. package/dist/chunk-7LEKQI47.js +32 -0
  4. package/dist/chunk-7LEKQI47.js.map +1 -0
  5. package/dist/{chunk-WPLEMYL7.js → chunk-C2FKVGJU.js} +2 -2
  6. package/dist/{chunk-4D4EXLVT.js → chunk-DQCXSPHP.js} +2 -2
  7. package/dist/{chunk-QODAKTG5.js → chunk-JCJFFJ42.js} +2 -31
  8. package/dist/chunk-JCJFFJ42.js.map +1 -0
  9. package/dist/{chunk-VJY6RLYU.js → chunk-JU5SL4HP.js} +2 -2
  10. package/dist/chunk-M72OL7ZJ.js +23 -0
  11. package/dist/chunk-M72OL7ZJ.js.map +1 -0
  12. package/dist/{chunk-WVXXQ3KM.js → chunk-SBASG3M2.js} +132 -102
  13. package/dist/chunk-SBASG3M2.js.map +1 -0
  14. package/dist/{chunk-XCIDE3JW.js → chunk-TE6G6NVX.js} +7 -7
  15. package/dist/{chunk-3I4ZURKH.js → chunk-X2NJKKXR.js} +15 -15
  16. package/dist/client/auth.d.ts +8 -0
  17. package/dist/client/blade-client.d.ts +80 -0
  18. package/dist/client/index.d.ts +22 -15348
  19. package/dist/client/index.js +1 -1
  20. package/dist/client/resources/api-keys.d.ts +28 -0
  21. package/dist/client/resources/auth.d.ts +26 -0
  22. package/dist/client/resources/env-buckets.d.ts +20 -0
  23. package/dist/client/resources/gis.d.ts +8 -0
  24. package/dist/client/resources/headless.d.ts +33 -0
  25. package/dist/client/resources/memories.d.ts +63 -0
  26. package/dist/client/resources/models.d.ts +23 -0
  27. package/dist/client/resources/published-apps.d.ts +8 -0
  28. package/dist/client/resources/registry.d.ts +58 -0
  29. package/dist/client/resources/runs.d.ts +8 -0
  30. package/dist/client/resources/scenarios.d.ts +49 -0
  31. package/dist/client/resources/sessions.d.ts +253 -0
  32. package/dist/client/resources/skills.d.ts +38 -0
  33. package/dist/client/resources/solutions.d.ts +31 -0
  34. package/dist/client/resources/user-preferences.d.ts +26 -0
  35. package/dist/client/rest.d.ts +19 -0
  36. package/dist/client/socket.d.ts +9 -0
  37. package/dist/client/types/index.d.ts +8 -0
  38. package/dist/client/types/rest.d.ts +15335 -0
  39. package/dist/client/types/sdk-profile.d.ts +47 -0
  40. package/dist/client/types/socket-events.d.ts +503 -0
  41. package/dist/react/api/api-keys.d.ts +6 -0
  42. package/dist/react/api/auth.d.ts +7 -0
  43. package/dist/react/api/client.d.ts +8 -0
  44. package/dist/react/api/env-buckets.d.ts +10 -0
  45. package/dist/react/api/gis-api.d.ts +4 -0
  46. package/dist/react/api/memories.d.ts +14 -0
  47. package/dist/react/api/models.d.ts +11 -0
  48. package/dist/react/api/partner-skill.d.ts +2 -0
  49. package/dist/react/api/prod-solution.d.ts +456 -0
  50. package/dist/react/api/published-apps.d.ts +21 -0
  51. package/dist/react/api/published-apps.js +14 -0
  52. package/dist/react/api/published-apps.js.map +1 -0
  53. package/dist/react/api/registry.d.ts +46 -0
  54. package/dist/react/api/scenarios.d.ts +9 -0
  55. package/dist/react/api/scheduled-tasks.d.ts +24 -0
  56. package/dist/react/api/session-skill.d.ts +2 -0
  57. package/dist/react/api/sessions.d.ts +109 -0
  58. package/dist/react/api/sessions.js +93 -0
  59. package/dist/react/api/sessions.js.map +1 -0
  60. package/dist/react/api/skills.d.ts +27 -0
  61. package/dist/react/api/socket.d.ts +5 -0
  62. package/dist/react/api/solutions.d.ts +11 -0
  63. package/dist/react/api/user-preferences.d.ts +8 -0
  64. package/dist/react/asr/VoiceWaveform.d.ts +10 -0
  65. package/dist/react/asr/use-tiptap-voice-input.d.ts +29 -0
  66. package/dist/react/asr/use-voice-input.d.ts +17 -0
  67. package/dist/react/asr/voice-input-support.d.ts +5 -0
  68. package/dist/react/bootstrap.d.ts +4 -0
  69. package/dist/react/cards/register.d.ts +1 -2
  70. package/dist/react/cards/register.js +3 -2
  71. package/dist/react/cards/register.js.map +1 -1
  72. package/dist/react/components/ai-elements/file-tree.d.ts +26 -0
  73. package/dist/react/components/ai-elements/reasoning.d.ts +32 -0
  74. package/dist/react/components/ai-elements/shimmer.d.ts +11 -0
  75. package/dist/react/components/card/CardCodeBlock.d.ts +5 -0
  76. package/dist/react/components/card/CardContext.d.ts +7 -0
  77. package/dist/react/components/card/CardRenderer.d.ts +7 -0
  78. package/dist/react/components/card/CardStates.d.ts +8 -0
  79. package/dist/react/components/card/cards/attraction-card.d.ts +2 -0
  80. package/dist/react/components/card/cards/cite-card.d.ts +10 -0
  81. package/dist/react/components/card/cards/comprehensive-analysis-card.d.ts +2 -0
  82. package/dist/react/components/card/cards/conflict-detection-card.d.ts +4 -0
  83. package/dist/react/components/card/cards/counter.d.ts +2 -0
  84. package/dist/react/components/card/cards/damage-effect-card.d.ts +4 -0
  85. package/dist/react/components/card/cards/destination-card.d.ts +2 -0
  86. package/dist/react/components/card/cards/diff-card.d.ts +2 -0
  87. package/dist/react/components/card/cards/execution-order-card.d.ts +2 -0
  88. package/dist/react/components/card/cards/experience-card-with-options.d.ts +4 -0
  89. package/dist/react/components/card/cards/flight-card.d.ts +2 -0
  90. package/dist/react/components/card/cards/hotel-card.d.ts +2 -0
  91. package/dist/react/components/card/cards/kill-chain-card.d.ts +2 -0
  92. package/dist/react/components/card/cards/kill-chain-types.d.ts +157 -0
  93. package/dist/react/components/card/cards/map-card.d.ts +2 -0
  94. package/dist/react/components/card/cards/order-status-card.d.ts +2 -0
  95. package/dist/react/components/card/cards/patch-card.d.ts +15 -0
  96. package/dist/react/components/card/cards/product-recommendation-card.d.ts +2 -0
  97. package/dist/react/components/card/cards/reflection-optimization-card.d.ts +2 -0
  98. package/dist/react/components/card/cards/resolution-modifications-card.d.ts +2 -0
  99. package/dist/react/components/card/cards/resolution-summary-card.d.ts +2 -0
  100. package/dist/react/components/card/cards/restaurant-card.d.ts +2 -0
  101. package/dist/react/components/card/cards/shopping-list-card.d.ts +2 -0
  102. package/dist/react/components/card/cards/simulation-event-card.d.ts +4 -0
  103. package/dist/react/components/card/cards/survival-effect-card.d.ts +4 -0
  104. package/dist/react/components/card/cards/travel-itinerary-card.d.ts +2 -0
  105. package/dist/react/components/card/register.d.ts +1 -0
  106. package/dist/react/components/chat/AgentLoopBlock.d.ts +8 -0
  107. package/dist/react/components/chat/AskUserQuestionBlock.d.ts +32 -0
  108. package/dist/react/components/chat/AssistantTurnBlock.d.ts +28 -0
  109. package/dist/react/components/chat/AttachmentPreviewDialog.d.ts +26 -0
  110. package/dist/react/components/chat/BackgroundTasksPill.d.ts +3 -0
  111. package/dist/react/components/chat/ChatInput.d.ts +94 -0
  112. package/dist/react/components/chat/ChatView.d.ts +16 -0
  113. package/dist/react/components/chat/CompactionCard.d.ts +6 -0
  114. package/dist/react/components/chat/ConnectionBanner.d.ts +1 -0
  115. package/dist/react/components/chat/FileCompletionMenu.d.ts +13 -0
  116. package/dist/react/components/chat/FileSizeLimitDialog.d.ts +9 -0
  117. package/dist/react/components/chat/ImageLightbox.d.ts +11 -0
  118. package/dist/react/components/chat/MessageActions.d.ts +6 -0
  119. package/dist/react/components/chat/MessageContextPills.d.ts +6 -0
  120. package/dist/react/components/chat/MessageFileAttachmentList.d.ts +13 -0
  121. package/dist/react/components/chat/MessageList.d.ts +13 -0
  122. package/dist/react/components/chat/ProgressCircle.d.ts +12 -0
  123. package/dist/react/components/chat/RenderErrorBoundary.d.ts +19 -0
  124. package/dist/react/components/chat/ResourceIframe.d.ts +5 -0
  125. package/dist/react/components/chat/Shimmer.d.ts +6 -0
  126. package/dist/react/components/chat/SkillCompletionMenu.d.ts +9 -0
  127. package/dist/react/components/chat/SkillStatusBar.d.ts +8 -0
  128. package/dist/react/components/chat/StickyStatusBar.d.ts +10 -0
  129. package/dist/react/components/chat/TextAttachmentPills.d.ts +10 -0
  130. package/dist/react/components/chat/ThinkingToggle.d.ts +7 -0
  131. package/dist/react/components/chat/ToolCallBlock.d.ts +18 -0
  132. package/dist/react/components/chat/TurnNavRail.d.ts +11 -0
  133. package/dist/react/components/chat/UserMessageBubble.d.ts +20 -0
  134. package/dist/react/components/chat/WhatIfUserBubble.d.ts +13 -0
  135. package/dist/react/components/chat/customization.d.ts +82 -0
  136. package/dist/react/components/chat/display-utils.d.ts +35 -0
  137. package/dist/react/components/chat/extensions/file-mention.d.ts +12 -0
  138. package/dist/react/components/chat/extensions/skill-mention.d.ts +25 -0
  139. package/dist/react/components/chat/index.d.ts +16 -115
  140. package/dist/react/components/chat/index.js +8 -7
  141. package/dist/react/components/chat/tool-renderers/BashRenderer.d.ts +2 -0
  142. package/dist/react/components/chat/tool-renderers/FileEditRenderer.d.ts +2 -0
  143. package/dist/react/components/chat/tool-renderers/FileReadRenderer.d.ts +2 -0
  144. package/dist/react/components/chat/tool-renderers/SearchRenderer.d.ts +2 -0
  145. package/dist/react/components/chat/tool-renderers/SubmitResultRenderer.d.ts +2 -0
  146. package/dist/react/components/chat/tool-renderers/registry.d.ts +9 -0
  147. package/dist/react/components/chat/tool-renderers/shared.d.ts +26 -0
  148. package/dist/react/components/chat/whatif-quote-context.d.ts +15 -0
  149. package/dist/react/components/markdown/ExternalLinkDialog.d.ts +8 -0
  150. package/dist/react/components/markdown/FileCardComponent.d.ts +10 -0
  151. package/dist/react/components/markdown/MarkdownContent.d.ts +19 -0
  152. package/dist/react/components/model/ModelSelector.d.ts +9 -0
  153. package/dist/react/components/plan/PlanSummaryCard.d.ts +8 -0
  154. package/dist/react/components/plan/PlanVisualization.d.ts +13 -0
  155. package/dist/react/components/plan/debug-log.d.ts +21 -0
  156. package/dist/react/components/plan/extract-plan-messages.d.ts +2 -0
  157. package/dist/react/components/plan/index.d.ts +6 -110
  158. package/dist/react/components/plan/index.js +7 -6
  159. package/dist/react/components/plan/index.js.map +1 -1
  160. package/dist/react/components/plan/parse-plan-messages.d.ts +10 -0
  161. package/dist/react/components/plan/parse-plan-tree.d.ts +16 -0
  162. package/dist/react/components/plan/phases/PlanMindMap.d.ts +8 -0
  163. package/dist/react/components/plan/phases/PlanStatusIcon.d.ts +5 -0
  164. package/dist/react/components/plan/phases/PlanTree.d.ts +8 -0
  165. package/dist/react/components/plan/phases/SkillAnalysis.d.ts +7 -0
  166. package/dist/react/components/plan/phases/SkillDiscovery.d.ts +10 -0
  167. package/dist/react/components/plan/types.d.ts +56 -0
  168. package/dist/react/components/session/SessionDetail.d.ts +8 -0
  169. package/dist/react/components/session/SessionList.d.ts +9 -0
  170. package/dist/react/components/session/SessionListItem.d.ts +8 -0
  171. package/dist/react/components/session/StatusBadge.d.ts +3 -0
  172. package/dist/react/components/session/index.d.ts +5 -53
  173. package/dist/react/components/session/index.js +6 -5
  174. package/dist/react/components/session/index.js.map +1 -1
  175. package/dist/react/components/session/session-utils.d.ts +19 -0
  176. package/dist/react/components/ui/collapsible.d.ts +5 -0
  177. package/dist/react/components/workspace/FileTree.d.ts +21 -0
  178. package/dist/react/components/workspace/WorkspaceFilesPanel.d.ts +30 -0
  179. package/dist/react/components/workspace/file-icon-assets.d.ts +3 -0
  180. package/dist/react/components/workspace/index.d.ts +2 -59
  181. package/dist/react/components/workspace/index.js +6 -5
  182. package/dist/react/components/workspace/index.js.map +1 -1
  183. package/dist/react/context.d.ts +2 -0
  184. package/dist/react/devtools/bridge-devtools/BridgeDevtoolsFab.d.ts +1 -0
  185. package/dist/react/devtools/bridge-devtools/index.d.ts +3 -36
  186. package/dist/react/devtools/bridge-devtools/mount.d.ts +1 -0
  187. package/dist/react/devtools/bridge-devtools/store.d.ts +15 -0
  188. package/dist/react/devtools/bridge-devtools/tap.d.ts +5 -0
  189. package/dist/react/devtools/bridge-devtools/types.d.ts +29 -0
  190. package/dist/react/hooks/use-background-tasks.d.ts +7 -0
  191. package/dist/react/hooks/use-card-state.d.ts +1 -0
  192. package/dist/react/hooks/use-chat.d.ts +13 -0
  193. package/dist/react/hooks/use-check-skill-file.d.ts +4 -0
  194. package/dist/react/hooks/use-check-solution-file.d.ts +4 -0
  195. package/dist/react/hooks/use-context-stats.d.ts +7 -0
  196. package/dist/react/hooks/use-gis.d.ts +17 -0
  197. package/dist/react/hooks/use-global-skill-stats.d.ts +6 -0
  198. package/dist/react/hooks/use-input-history.d.ts +7 -0
  199. package/dist/react/hooks/use-model-preferences.d.ts +17 -0
  200. package/dist/react/hooks/use-registry.d.ts +53 -0
  201. package/dist/react/hooks/use-resolved-model.d.ts +5 -0
  202. package/dist/react/hooks/use-session.d.ts +10 -0
  203. package/dist/react/hooks/use-skill-stats.d.ts +7 -0
  204. package/dist/react/hooks/use-skills.d.ts +6 -0
  205. package/dist/react/hooks/use-token-pressure.d.ts +6 -0
  206. package/dist/react/index.d.ts +121 -2034
  207. package/dist/react/index.js +47 -52
  208. package/dist/react/index.js.map +1 -1
  209. package/dist/react/lib/analytics.d.ts +7 -0
  210. package/dist/react/lib/attachment-upload.d.ts +10 -0
  211. package/dist/react/lib/card-registry.d.ts +35 -0
  212. package/dist/react/lib/chat.d.ts +48 -0
  213. package/dist/react/lib/code-highlight.d.ts +9 -0
  214. package/dist/react/lib/html-element-selection.d.ts +140 -0
  215. package/dist/react/lib/html-source-locator.d.ts +16 -0
  216. package/dist/react/lib/open-session-file.d.ts +2 -0
  217. package/dist/react/lib/parent-bridge.d.ts +22 -0
  218. package/dist/react/lib/preview-dispatch.d.ts +24 -0
  219. package/dist/react/lib/resource-bridge.d.ts +11 -0
  220. package/dist/react/lib/session-file-preview.d.ts +8 -0
  221. package/dist/react/lib/step-ranges.d.ts +42 -0
  222. package/dist/react/lib/tool-preview.d.ts +2 -0
  223. package/dist/react/lib/ui-meta.d.ts +9 -0
  224. package/dist/react/lib/utils.d.ts +3 -0
  225. package/dist/react/lib/whatif-prompt.d.ts +45 -0
  226. package/dist/react/projection/builder.d.ts +59 -0
  227. package/dist/react/projection/helpers.d.ts +34 -0
  228. package/dist/react/projection/index.d.ts +2 -0
  229. package/dist/react/projection/state.d.ts +22 -0
  230. package/dist/react/provider.d.ts +8 -0
  231. package/dist/react/routes.d.ts +1 -0
  232. package/dist/react/schemas/background.d.ts +16 -0
  233. package/dist/react/schemas/event.d.ts +51 -0
  234. package/dist/react/schemas/gis.d.ts +50 -0
  235. package/dist/{AskUserQuestionBlock---kOTouk.d.ts → react/schemas/message.d.ts} +15 -48
  236. package/dist/react/schemas/partner-skill.d.ts +46 -0
  237. package/dist/{projection-BWYEFYNn.d.ts → react/schemas/projection.d.ts} +12 -10
  238. package/dist/react/schemas/published-apps.d.ts +38 -0
  239. package/dist/react/schemas/scheduled-task.d.ts +32 -0
  240. package/dist/react/schemas/session.d.ts +121 -0
  241. package/dist/react/schemas/skill.d.ts +50 -0
  242. package/dist/react/schemas/studio/agent.d.ts +12 -0
  243. package/dist/react/schemas/studio/database.d.ts +39 -0
  244. package/dist/react/schemas/studio/env.d.ts +7 -0
  245. package/dist/react/schemas/studio/knowledge.d.ts +18 -0
  246. package/dist/react/schemas/studio/resource-base.d.ts +7 -0
  247. package/dist/react/schemas/studio/scene.d.ts +12 -0
  248. package/dist/react/schemas/studio/tool.d.ts +25 -0
  249. package/dist/react/schemas/task.d.ts +12 -0
  250. package/dist/react/sockets/event-bridge.d.ts +115 -0
  251. package/dist/react/sockets/socket-state.d.ts +4 -0
  252. package/dist/react/stores/answer-callback-store.d.ts +9 -0
  253. package/dist/react/stores/auth-store.d.ts +38 -0
  254. package/dist/react/stores/background-store.d.ts +13 -0
  255. package/dist/react/stores/card-state-store.d.ts +10 -0
  256. package/dist/react/stores/chat-store.d.ts +34 -0
  257. package/dist/react/stores/client-aware.d.ts +7 -0
  258. package/dist/react/stores/connection-store.d.ts +14 -0
  259. package/dist/react/stores/gis-store.d.ts +19 -0
  260. package/dist/react/stores/index.d.ts +14 -0
  261. package/dist/react/stores/runtime-features-store.d.ts +21 -0
  262. package/dist/react/stores/runtime-store.d.ts +18 -0
  263. package/dist/react/stores/session-store.d.ts +44 -0
  264. package/dist/react/stores/task-store.d.ts +9 -0
  265. package/dist/react/stores/ui-bridge-store.d.ts +32 -0
  266. package/dist/react/stores/ui-store.d.ts +69 -0
  267. package/dist/react/types/index.d.ts +7 -0
  268. package/dist/react/types/solution.d.ts +101 -0
  269. package/package.json +41 -11
  270. package/dist/SkillStatusBar-U6fbQxMu.d.ts +0 -340
  271. package/dist/blade-client-qTOovekU.d.ts +0 -1609
  272. package/dist/chunk-M45K3554.js.map +0 -1
  273. package/dist/chunk-QODAKTG5.js.map +0 -1
  274. package/dist/chunk-WVXXQ3KM.js.map +0 -1
  275. package/dist/session-CNnotR90.d.ts +0 -227
  276. package/dist/sessions-BvfLGbjw.d.ts +0 -177
  277. /package/dist/{chunk-WPLEMYL7.js.map → chunk-C2FKVGJU.js.map} +0 -0
  278. /package/dist/{chunk-4D4EXLVT.js.map → chunk-DQCXSPHP.js.map} +0 -0
  279. /package/dist/{chunk-VJY6RLYU.js.map → chunk-JU5SL4HP.js.map} +0 -0
  280. /package/dist/{chunk-XCIDE3JW.js.map → chunk-TE6G6NVX.js.map} +0 -0
  281. /package/dist/{chunk-3I4ZURKH.js.map → chunk-X2NJKKXR.js.map} +0 -0
@@ -0,0 +1,15 @@
1
+ import { type ReactNode } from "react";
2
+ interface WhatIfQuoteContextValue {
3
+ onJumpToStep?: (stepNumber: number) => void;
4
+ }
5
+ /**
6
+ * Provide a callback used by `WhatIfUserBubble`'s quote chip to navigate to
7
+ * the corresponding step card. Host apps (ship-attack) mount this provider
8
+ * near the chat view and wire it to their step selector.
9
+ */
10
+ export declare function WhatIfQuoteProvider({ onJumpToStep, children, }: {
11
+ onJumpToStep?: (stepNumber: number) => void;
12
+ children: ReactNode;
13
+ }): import("react/jsx-runtime").JSX.Element;
14
+ export declare function useWhatIfQuoteContext(): WhatIfQuoteContextValue;
15
+ export {};
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ isOpen: boolean;
3
+ onClose: () => void;
4
+ onConfirm: () => void;
5
+ url: string;
6
+ }
7
+ export declare function ExternalLinkDialog({ isOpen, onClose, onConfirm, url }: Props): import("react").ReactPortal | null;
8
+ export {};
@@ -0,0 +1,10 @@
1
+ import { type ComponentPropsWithRef } from "react";
2
+ import type { ExtraProps } from "streamdown";
3
+ type FileCardProps = ComponentPropsWithRef<"span"> & ExtraProps & {
4
+ "data-rel-path"?: string;
5
+ "data-name"?: string;
6
+ dataRelPath?: string;
7
+ dataName?: string;
8
+ };
9
+ export declare function FileCardComponent({ node, "data-rel-path": dataRelPathAttribute, "data-name": dataNameAttribute, dataRelPath, dataName, children, className, ...props }: FileCardProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,19 @@
1
+ import { type ComponentProps } from "react";
2
+ import { type ExtraProps, Streamdown } from "streamdown";
3
+ type StreamdownProps = ComponentProps<typeof Streamdown>;
4
+ export declare function resolveCollapsedContent({ dataKeyAttribute, dataRawAttribute, dataKey, dataRaw, node, children, }: {
5
+ dataKeyAttribute?: string;
6
+ dataRawAttribute?: string;
7
+ dataKey?: string;
8
+ dataRaw?: string;
9
+ node?: ExtraProps["node"];
10
+ children?: unknown;
11
+ }): string;
12
+ export declare function collapseMediaTags(children: string, sessionId: string): string;
13
+ export declare function collapseInlineToolCalls(children: string): string;
14
+ type MarkdownContentProps = StreamdownProps & {
15
+ /** 当提供时,markdown 中相对路径的 <img> src 会解析为 session 工作区文件 URL */
16
+ sessionId?: string;
17
+ };
18
+ export declare function MarkdownContent({ allowedTags, children, components, mode, plugins, sessionId, ...props }: MarkdownContentProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,9 @@
1
+ type ModelSelectorProps = {
2
+ value: string;
3
+ onValueChange: (model: string) => void;
4
+ disabled?: boolean;
5
+ compact?: boolean;
6
+ placement?: "top" | "bottom";
7
+ };
8
+ export declare function ModelSelector({ value, onValueChange, disabled, compact, placement, }: ModelSelectorProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { ChatMessage } from "../../schemas/message.js";
2
+ interface Props {
3
+ messages: ChatMessage[];
4
+ sessionStatus?: string;
5
+ onConfirmPlan?: (action: "execute" | "revise", text?: string) => void;
6
+ }
7
+ export declare function PlanSummaryCard({ messages, sessionStatus, onConfirmPlan, }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { ChatMessage } from "../../schemas/message.js";
2
+ import { type AskUserAnswerData } from "../chat/AskUserQuestionBlock.js";
3
+ import type { SkillCatalogItem } from "./types.js";
4
+ interface Props {
5
+ messages: ChatMessage[];
6
+ /** All skill names from the registry, used as word cloud background in Phase 1 */
7
+ allSkillNames?: SkillCatalogItem[];
8
+ onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
9
+ sessionStatus?: string;
10
+ isStreaming?: boolean;
11
+ }
12
+ export declare function PlanVisualization({ messages: rawMessages, allSkillNames: rawAllSkillNames, onAnswer, sessionStatus, isStreaming, }: Props): import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Debug logger for Plan timeline events.
3
+ * Stores events in memory with timestamps for debugging animation timing
4
+ * in real conversation environments.
5
+ *
6
+ * Events are stored in window.__planTimelineLog and can be exported as JSON.
7
+ */
8
+ export interface PlanTimelineEvent {
9
+ /** ISO timestamp */
10
+ ts: string;
11
+ /** Milliseconds since first event in this session */
12
+ elapsed: number;
13
+ /** Event type */
14
+ event: string;
15
+ /** Additional data */
16
+ data?: Record<string, unknown>;
17
+ }
18
+ export declare function logPlanEvent(event: string, data?: Record<string, unknown>): void;
19
+ export declare function clearPlanLog(): void;
20
+ export declare function exportPlanLog(): PlanTimelineEvent[];
21
+ export declare function downloadPlanLog(): void;
@@ -0,0 +1,2 @@
1
+ import type { ChatMessage } from "../../schemas/message.js";
2
+ export declare function extractLatestPlanMessages(messages: ChatMessage[]): ChatMessage[];
@@ -1,110 +1,6 @@
1
- import { C as ChatMessage, A as AskUserAnswerData } from '../../../AskUserQuestionBlock---kOTouk.js';
2
- import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import '../../../projection-BWYEFYNn.js';
4
-
5
- /**
6
- * Debug logger for Plan timeline events.
7
- * Stores events in memory with timestamps for debugging animation timing
8
- * in real conversation environments.
9
- *
10
- * Events are stored in window.__planTimelineLog and can be exported as JSON.
11
- */
12
- interface PlanTimelineEvent {
13
- /** ISO timestamp */
14
- ts: string;
15
- /** Milliseconds since first event in this session */
16
- elapsed: number;
17
- /** Event type */
18
- event: string;
19
- /** Additional data */
20
- data?: Record<string, unknown>;
21
- }
22
- declare function exportPlanLog(): PlanTimelineEvent[];
23
- declare function downloadPlanLog(): void;
24
-
25
- declare function extractLatestPlanMessages(messages: ChatMessage[]): ChatMessage[];
26
-
27
- interface Props$1 {
28
- messages: ChatMessage[];
29
- sessionStatus?: string;
30
- onConfirmPlan?: (action: "execute" | "revise", text?: string) => void;
31
- }
32
- declare function PlanSummaryCard({ messages, sessionStatus, onConfirmPlan, }: Props$1): react_jsx_runtime.JSX.Element;
33
-
34
- interface SkillInfo {
35
- skillId: string;
36
- displayName?: string;
37
- description: string;
38
- content?: string;
39
- references?: string[];
40
- }
41
- interface SkillCatalogItem {
42
- skillId: string;
43
- displayName?: string;
44
- }
45
- interface PlanNode {
46
- id: string;
47
- label: string;
48
- skillRef: string | null;
49
- children: PlanNode[];
50
- depth: number;
51
- status: "pending" | "running" | "done" | "failed";
52
- }
53
- type Phase = "discovering" | "analyzing" | "generating";
54
- interface PlanData {
55
- intent: string;
56
- /** All skills returned by search_skills (candidates) */
57
- searchResults: SkillInfo[];
58
- /** Skills selected via get_skill_content (subset of searchResults, with content populated) */
59
- selectedSkills: SkillInfo[];
60
- plan: {
61
- root: PlanNode;
62
- notes: string[];
63
- } | null;
64
- /** Raw plan YAML content (non-empty even if parsePlanTree yields no plan) */
65
- hasPlanContent: boolean;
66
- /** PLAN.yaml exists but failed to parse/validate for UI rendering */
67
- parseError: string | null;
68
- /** AskUserQuestion tool calls found in planning messages */
69
- askQuestions: Array<{
70
- toolCallId: string;
71
- data: {
72
- questions: Array<{
73
- question: string;
74
- options: Array<{
75
- label: string;
76
- description: string;
77
- }>;
78
- multiSelect?: boolean;
79
- }>;
80
- };
81
- }>;
82
- /** File paths from Read tool calls (with status) */
83
- readFiles: Array<{
84
- path: string;
85
- status: "pending" | "done" | "error" | "cancelled" | "awaiting_answer";
86
- }>;
87
- /** The last pause-triggering tool in this phase: determines what UI to show */
88
- lastPauseTool: "AskUserQuestion" | "ExitPlanMode" | null;
89
- }
90
-
91
- interface Props {
92
- messages: ChatMessage[];
93
- /** All skill names from the registry, used as word cloud background in Phase 1 */
94
- allSkillNames?: SkillCatalogItem[];
95
- onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
96
- sessionStatus?: string;
97
- isStreaming?: boolean;
98
- }
99
- declare function PlanVisualization({ messages: rawMessages, allSkillNames: rawAllSkillNames, onAnswer, sessionStatus, isStreaming, }: Props): react_jsx_runtime.JSX.Element;
100
-
101
- /**
102
- * Extract structured plan data from planning phase messages.
103
- *
104
- * Expects messages between planning-mode mode_change markers containing:
105
- * - ReadSkill tool calls (技能调研:成功结果 = 选定技能,歧义 candidates = 候选列表)
106
- * - Write tool call to PLAN.yaml with plan YAML
107
- */
108
- declare function parsePlanMessages(allMessages: ChatMessage[]): PlanData;
109
-
110
- export { type Phase, type PlanData, type PlanNode, PlanSummaryCard, PlanVisualization, type SkillCatalogItem, type SkillInfo, downloadPlanLog, exportPlanLog, extractLatestPlanMessages, parsePlanMessages };
1
+ export { downloadPlanLog, exportPlanLog } from "./debug-log.js";
2
+ export { extractLatestPlanMessages } from "./extract-plan-messages.js";
3
+ export { PlanSummaryCard } from "./PlanSummaryCard.js";
4
+ export { PlanVisualization } from "./PlanVisualization.js";
5
+ export { parsePlanMessages } from "./parse-plan-messages.js";
6
+ export type { Phase, PlanData, PlanNode, SkillCatalogItem, SkillInfo } from "./types.js";
@@ -3,15 +3,16 @@ import {
3
3
  PlanSummaryCard,
4
4
  extractLatestPlanMessages,
5
5
  parsePlanMessages
6
- } from "../../../chunk-XCIDE3JW.js";
6
+ } from "../../../chunk-TE6G6NVX.js";
7
+ import "../../../chunk-C2FKVGJU.js";
7
8
  import "../../../chunk-2UP7MG3J.js";
8
- import "../../../chunk-WPLEMYL7.js";
9
- import "../../../chunk-WVXXQ3KM.js";
10
- import "../../../chunk-M45K3554.js";
9
+ import "../../../chunk-SBASG3M2.js";
10
+ import "../../../chunk-J3XVFPOV.js";
11
+ import "../../../chunk-34GDDOWY.js";
11
12
  import {
12
13
  cn
13
- } from "../../../chunk-QODAKTG5.js";
14
- import "../../../chunk-J3XVFPOV.js";
14
+ } from "../../../chunk-7LEKQI47.js";
15
+ import "../../../chunk-JCJFFJ42.js";
15
16
  import "../../../chunk-PZ5AY32C.js";
16
17
 
17
18
  // src/react/components/plan/debug-log.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/react/components/plan/debug-log.ts","../../../../src/react/components/plan/PlanVisualization.tsx","../../../../src/react/components/plan/phases/PlanTree.tsx","../../../../src/react/components/plan/phases/PlanMindMap.tsx","../../../../src/react/components/plan/phases/PlanStatusIcon.tsx","../../../../src/react/components/plan/phases/SkillAnalysis.tsx","../../../../src/react/components/plan/phases/SkillDiscovery.tsx"],"sourcesContent":["/**\n * Debug logger for Plan timeline events.\n * Stores events in memory with timestamps for debugging animation timing\n * in real conversation environments.\n *\n * Events are stored in window.__planTimelineLog and can be exported as JSON.\n */\n\nexport interface PlanTimelineEvent {\n /** ISO timestamp */\n ts: string\n /** Milliseconds since first event in this session */\n elapsed: number\n /** Event type */\n event: string\n /** Additional data */\n data?: Record<string, unknown>\n}\n\nlet events: PlanTimelineEvent[] = []\nlet startTime: number | null = null\n\n/** Set to true to enable console logging. Defaults to true in dev (localhost). */\nconst verbose =\n typeof window !== \"undefined\" &&\n (window.location?.hostname === \"localhost\" || window.location?.hostname === \"127.0.0.1\")\n\nexport function logPlanEvent(event: string, data?: Record<string, unknown>) {\n const now = Date.now()\n if (startTime === null) startTime = now\n\n const entry: PlanTimelineEvent = {\n ts: new Date(now).toISOString(),\n elapsed: now - startTime,\n event,\n data,\n }\n events.push(entry)\n\n if (verbose) {\n // Store on window for devtools access\n ;(window as unknown as Record<string, unknown>).__planTimelineLog = events\n console.log(`[PlanTimeline] +${entry.elapsed}ms ${event}`, data ?? \"\")\n }\n}\n\nexport function clearPlanLog() {\n events = []\n startTime = null\n}\n\nexport function exportPlanLog(): PlanTimelineEvent[] {\n return [...events]\n}\n\nexport function downloadPlanLog() {\n const blob = new Blob([JSON.stringify(events, null, 2)], { type: \"application/json\" })\n const url = URL.createObjectURL(blob)\n const a = document.createElement(\"a\")\n a.href = url\n a.download = `plan-timeline-${new Date().toISOString().slice(0, 19).replace(/:/g, \"-\")}.json`\n a.click()\n URL.revokeObjectURL(url)\n}\n","import { BookOpen, GitBranch, Search } from \"lucide-react\"\nimport { useMemo, useRef, useState } from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport type { ChatMessage } from \"../../schemas/message\"\nimport { AskUserQuestionBlock, type AskUserAnswerData } from \"../chat/AskUserQuestionBlock\"\nimport { parsePlanMessages } from \"./parse-plan-messages\"\nimport { PlanTree } from \"./phases/PlanTree\"\nimport { SkillAnalysis } from \"./phases/SkillAnalysis\"\nimport { SkillDiscovery } from \"./phases/SkillDiscovery\"\nimport type { Phase, PlanData, SkillCatalogItem } from \"./types\"\n\ninterface Props {\n messages: ChatMessage[]\n /** All skill names from the registry, used as word cloud background in Phase 1 */\n allSkillNames?: SkillCatalogItem[]\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n sessionStatus?: string\n isStreaming?: boolean\n}\n\nconst PHASE_LABELS: { key: Phase; label: string; icon: typeof Search }[] = [\n { key: \"discovering\", label: \"技能发现\", icon: Search },\n { key: \"analyzing\", label: \"技能分析\", icon: BookOpen },\n { key: \"generating\", label: \"计划生成\", icon: GitBranch },\n]\n\nfunction getLatestPhaseIndex(data: PlanData): number {\n if (data.plan != null || data.hasPlanContent) return 2\n if (data.selectedSkills.length > 0) return 1\n if (data.searchResults.length > 0) return 0\n return -1\n}\n\nexport function PlanVisualization({\n messages: rawMessages,\n allSkillNames: rawAllSkillNames = [],\n onAnswer,\n sessionStatus,\n isStreaming = false,\n}: Props) {\n const messages = Array.isArray(rawMessages) ? rawMessages : []\n const allSkillNames = Array.isArray(rawAllSkillNames) ? rawAllSkillNames : []\n const data = useMemo(() => parsePlanMessages(messages), [messages])\n const latestIdx = getLatestPhaseIndex(data)\n const isWaitingForInput = sessionStatus === \"waiting_for_input\"\n const hasError = sessionStatus === \"failed\"\n const isInterrupted = sessionStatus === \"interrupted\"\n const isSessionActive =\n isStreaming ||\n sessionStatus === \"created\" ||\n sessionStatus === \"running\" ||\n sessionStatus === \"waiting_for_input\"\n const activeStatusIdx = latestIdx >= 0 ? latestIdx : 0\n const latestAskQuestion = data.askQuestions[data.askQuestions.length - 1]\n const hasPhaseData = latestIdx >= 0\n\n // Determine which interactive surface to show based on the last pause tool\n const showAskQuestion =\n latestAskQuestion &&\n isWaitingForInput &&\n data.lastPauseTool === \"AskUserQuestion\" &&\n onAnswer\n\n const [selectedTab, setSelectedTab] = useState<number | null>(null)\n // Reset manual selection when a new planning cycle starts (latestIdx drops backward)\n const prevLatestRef = useRef(latestIdx)\n if (latestIdx < prevLatestRef.current) {\n setSelectedTab(null)\n }\n prevLatestRef.current = latestIdx\n const activeSelectedTab = selectedTab != null && selectedTab <= latestIdx ? selectedTab : null\n const viewIdx = activeSelectedTab ?? latestIdx\n\n return (\n <div className=\"flex flex-col gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.4)] p-5\">\n {hasPhaseData && (\n <>\n {/* Phase indicator bar */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-1\">\n {PHASE_LABELS.map((p, i) => {\n const Icon = p.icon\n const isViewing = viewIdx === i\n const isDone = latestIdx > i\n const isStatusPhase = i === activeStatusIdx && (hasError || isInterrupted)\n const tabHasData =\n (i === 0 && data.searchResults.length > 0) ||\n (i === 1 && data.selectedSkills.length > 0) ||\n (i === 2 && (data.plan != null || data.hasPlanContent))\n const isReachable = i <= latestIdx || tabHasData\n return (\n <div key={p.key} className=\"flex items-center\">\n {i > 0 && (\n <div\n className={cn(\n \"mx-1.5 h-px w-6 transition-colors duration-300\",\n isDone && !isStatusPhase\n ? \"bg-[hsl(var(--primary))]\"\n : \"bg-[hsl(var(--border))]\",\n )}\n />\n )}\n <button\n type=\"button\"\n disabled={!isReachable}\n onClick={() => isReachable && setSelectedTab(i === latestIdx ? null : i)}\n className={cn(\n \"flex items-center gap-2 rounded-full px-3.5 py-2 text-sm font-medium transition-all duration-300\",\n isViewing && \"bg-[hsl(var(--primary)/0.15)] text-[hsl(var(--primary))]\",\n !isViewing &&\n isDone &&\n \"text-[hsl(var(--primary)/0.6)] hover:bg-[hsl(var(--primary)/0.08)]\",\n !isReachable && \"cursor-default text-[hsl(var(--muted-foreground))]\",\n isReachable &&\n !isViewing &&\n !isDone &&\n tabHasData &&\n \"text-[hsl(var(--primary)/0.5)] hover:bg-[hsl(var(--primary)/0.08)]\",\n isReachable &&\n !isViewing &&\n !isDone &&\n !tabHasData &&\n \"text-[hsl(var(--muted-foreground))]\",\n )}\n >\n <Icon size={12} />\n {p.label}\n {latestIdx === i && isSessionActive && activeSelectedTab === null && (\n <span\n className={cn(\n \"h-1.5 w-1.5 animate-pulse rounded-full\",\n hasError\n ? \"bg-[hsl(var(--destructive))]\"\n : isInterrupted\n ? \"bg-orange-400\"\n : \"bg-[hsl(var(--primary))]\",\n )}\n />\n )}\n {isStatusPhase && latestIdx !== i && (\n <span\n className={cn(\n \"h-1.5 w-1.5 rounded-full\",\n hasError ? \"bg-[hsl(var(--destructive))]\" : \"bg-orange-400\",\n )}\n />\n )}\n </button>\n </div>\n )\n })}\n </div>\n\n {/* Controls */}\n <div className=\"flex items-center gap-1\">\n {hasError && (\n <span className=\"rounded-full bg-[hsl(var(--destructive)/0.12)] px-2.5 py-1 text-xs font-medium text-[hsl(var(--destructive))]\">\n 出错\n </span>\n )}\n {isInterrupted && (\n <span className=\"rounded-full bg-orange-500/10 px-2.5 py-1 text-xs font-medium text-orange-300\">\n 已中断\n </span>\n )}\n </div>\n </div>\n\n {/* Phase content — conditional rendering instead of absolute overlay */}\n <div className=\"min-h-0\">\n {viewIdx === 0 && (\n <SkillDiscovery\n intent={data.intent}\n searchResults={data.searchResults}\n selectedSkills={data.selectedSkills}\n allSkillNames={allSkillNames}\n active\n />\n )}\n {viewIdx === 1 && (\n <SkillAnalysis skills={data.selectedSkills} active />\n )}\n {viewIdx === 2 &&\n (data.plan != null ? (\n <PlanTree root={data.plan.root} notes={data.plan.notes} active />\n ) : data.parseError ? (\n <div className=\"flex min-h-[240px] items-center justify-center rounded-xl border border-[hsl(var(--destructive)/0.35)] bg-[hsl(var(--destructive)/0.08)] px-6 text-sm text-[hsl(var(--destructive))]\">\n {data.parseError}\n </div>\n ) : data.hasPlanContent ? (\n <div className=\"flex min-h-[240px] items-center justify-center rounded-xl border border-dashed border-[hsl(var(--border))] bg-[hsl(var(--card)/0.3)] px-6 text-sm text-[hsl(var(--muted-foreground))]\">\n 计划解析中...\n </div>\n ) : null)}\n </div>\n </>\n )}\n\n {/* AskUserQuestion standalone card (when no phase data) */}\n {!hasPhaseData && showAskQuestion && (\n <AskUserQuestionBlock data={latestAskQuestion.data} answered={false} toolCallId={latestAskQuestion.toolCallId} sessionStatus={sessionStatus ?? \"\"} onAnswer={onAnswer} />\n )}\n\n {hasPhaseData && showAskQuestion && (\n <AskUserQuestionBlock data={latestAskQuestion.data} answered={false} toolCallId={latestAskQuestion.toolCallId} sessionStatus={sessionStatus ?? \"\"} onAnswer={onAnswer} />\n )}\n\n </div>\n )\n}\n","import {\n CheckSquare,\n ChevronRight,\n GitBranch,\n List,\n Workflow,\n} from \"lucide-react\"\nimport { useCallback, useMemo, useState } from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { PlanNode } from \"../types\"\nimport { PlanMindMap } from \"./PlanMindMap\"\nimport { PlanStatusIcon } from \"./PlanStatusIcon\"\n\ntype ViewMode = \"mindmap\" | \"tree\"\n\n/** Collect node ids up to (and including) a given depth. */\nfunction collectIdsToDepth(node: PlanNode, maxDepth: number, out: Set<string>) {\n if (node.depth > maxDepth) return\n out.add(node.id)\n for (const child of node.children ?? []) collectIdsToDepth(child, maxDepth, out)\n}\n\ninterface Props {\n root: PlanNode\n notes: string[]\n active: boolean\n}\n\n/** Recursively fingerprint the full tree so key changes on any structural/label change. */\nfunction treeFinger(node: PlanNode): string {\n const children = node.children ?? []\n if (children.length === 0) return node.label\n return `${node.label}[${children.map(treeFinger).join(\",\")}]`\n}\n\nexport function PlanTree({ root, notes, active }: Props) {\n return <PlanTreeContent key={treeFinger(root)} root={root} notes={notes ?? []} active={active} />\n}\n\nfunction PlanTreeContent({ root, notes, active }: Props) {\n const [viewMode, setViewMode] = useState<ViewMode>(\"mindmap\")\n\n // Compute default expanded set: root + depth-1 children\n const defaultExpanded = useMemo(() => {\n const ids = new Set<string>()\n collectIdsToDepth(root, 1, ids)\n return ids\n }, [root])\n\n const [expandedIds, setExpandedIds] = useState<Set<string>>(defaultExpanded)\n\n const toggle = useCallback((id: string) => {\n setExpandedIds((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }, [])\n\n return (\n <div className={cn(!active && \"pointer-events-none opacity-0\")}>\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center justify-end\">\n <div className=\"flex items-center gap-0.5 rounded-lg border border-[hsl(var(--border))] p-0.5\">\n <button\n type=\"button\"\n onClick={() => setViewMode(\"mindmap\")}\n className={cn(\n \"rounded-md p-1.5 transition-colors\",\n viewMode === \"mindmap\"\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]\",\n )}\n title=\"思维导图\"\n >\n <GitBranch size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode(\"tree\")}\n className={cn(\n \"rounded-md p-1.5 transition-colors\",\n viewMode === \"tree\"\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]\",\n )}\n title=\"列表视图\"\n >\n <List size={14} />\n </button>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.5)] px-3 py-3\">\n {viewMode === \"mindmap\" ? (\n <PlanMindMap root={root} expandedIds={expandedIds} onToggle={toggle} />\n ) : (\n <TreeNode node={root} />\n )}\n </div>\n\n {notes.length > 0 && (\n <div className=\"rounded-xl border border-[hsl(var(--border)/0.5)] bg-[hsl(var(--card)/0.5)] px-4 py-3 text-sm text-[hsl(var(--muted-foreground))]\">\n {notes.map((note, i) => (\n <p key={i} className=\"py-0.5\">\n <span className=\"mr-1.5 text-[hsl(var(--primary)/0.6)]\">{i + 1}.</span>\n {note}\n </p>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nfunction TreeNode({ node }: { node: PlanNode }) {\n const children = node.children ?? []\n const hasChildren = children.length > 0\n\n return (\n <div>\n <div\n className=\"group flex min-w-0 items-center gap-2 rounded-md px-2 py-2 hover:bg-[hsl(var(--accent)/0.5)]\"\n style={{ paddingLeft: `${node.depth * 24 + 10}px` }}\n >\n {hasChildren ? (\n <ChevronRight\n size={16}\n className=\"shrink-0 rotate-90 text-[hsl(var(--muted-foreground)/0.6)]\"\n />\n ) : (\n <span className=\"w-4 shrink-0\" />\n )}\n\n <PlanStatusIcon status={node.status} />\n\n {node.skillRef ? (\n <Workflow size={15} className=\"shrink-0 text-[hsl(var(--primary))]\" />\n ) : (\n <CheckSquare size={15} className=\"shrink-0 text-[hsl(var(--muted-foreground))]\" />\n )}\n\n <span className=\"min-w-0 flex-1 truncate text-[15px] font-medium text-[hsl(var(--foreground))]\">\n {node.label}\n </span>\n\n {node.skillRef && (\n <span className=\"ml-auto max-w-[160px] shrink-0 truncate rounded bg-[hsl(var(--primary)/0.1)] px-2 py-0.5 text-sm font-medium text-[hsl(var(--primary)/0.8)]\">\n {node.skillRef}\n </span>\n )}\n </div>\n\n {hasChildren && (\n <div className=\"relative\">\n <div\n className=\"absolute bottom-1 top-0 w-px bg-[hsl(var(--border)/0.4)]\"\n style={{ left: `${node.depth * 24 + 18}px` }}\n />\n {children.map((child) => (\n <TreeNode key={child.id} node={child} />\n ))}\n </div>\n )}\n </div>\n )\n}\n","import { ChevronRight, Workflow } from \"lucide-react\"\nimport type { ReactNode } from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { PlanNode } from \"../types\"\nimport { PlanStatusIcon } from \"./PlanStatusIcon\"\n\ninterface Props {\n root: PlanNode\n expandedIds: Set<string>\n onToggle: (id: string) => void\n}\n\nexport function PlanMindMap({ root, expandedIds, onToggle }: Props) {\n return (\n <div className=\"overflow-x-auto py-2\">\n <MindMapSubtree node={root} expandedIds={expandedIds} onToggle={onToggle} isRoot />\n </div>\n )\n}\n\nfunction MindMapSubtree({\n node,\n expandedIds,\n onToggle,\n isRoot = false,\n}: {\n node: PlanNode\n expandedIds: Set<string>\n onToggle: (id: string) => void\n isRoot?: boolean\n}) {\n const children = node.children ?? []\n const hasChildren = children.length > 0\n const isExpanded = expandedIds.has(node.id)\n const visibleChildren = hasChildren && isExpanded ? children : []\n\n return (\n <div className=\"flex items-center\">\n {/* Node bubble */}\n <div\n role={hasChildren ? \"button\" : undefined}\n tabIndex={hasChildren ? 0 : undefined}\n aria-expanded={hasChildren ? isExpanded : undefined}\n onClick={hasChildren ? () => onToggle(node.id) : undefined}\n onKeyDown={\n hasChildren\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault()\n onToggle(node.id)\n }\n }\n : undefined\n }\n className={cn(\n \"relative z-10 shrink-0 rounded-lg border px-3 py-1.5 text-sm font-medium whitespace-nowrap select-none\",\n hasChildren && \"cursor-pointer\",\n isRoot\n ? \"border-[hsl(var(--primary))] bg-[hsl(var(--primary)/0.15)] text-[hsl(var(--primary))]\"\n : node.skillRef\n ? \"border-[hsl(var(--primary)/0.4)] bg-[hsl(var(--primary)/0.08)] text-[hsl(var(--foreground))]\"\n : \"border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]\",\n )}\n >\n <span className=\"flex items-center gap-1.5\">\n <PlanStatusIcon status={node.status} size={14} />\n {node.skillRef && <Workflow size={12} className=\"text-[hsl(var(--primary))]\" />}\n {node.label}\n {hasChildren && (\n <ChevronRight\n size={14}\n className={cn(\n \"text-[hsl(var(--muted-foreground))] transition-transform duration-150\",\n isExpanded && \"rotate-90\",\n )}\n />\n )}\n {hasChildren && !isExpanded && (\n <span className=\"ml-0.5 rounded-full bg-[hsl(var(--muted))] px-1.5 py-px text-[10px] text-[hsl(var(--muted-foreground))]\">\n +{children.length}\n </span>\n )}\n </span>\n </div>\n\n {/* Connector + Children */}\n {visibleChildren.length > 0 && (\n <>\n {/* Horizontal line from node to vertical rail */}\n <div className=\"h-px w-6 shrink-0 bg-[hsl(var(--border))]\" />\n\n <VerticalRail count={visibleChildren.length}>\n {visibleChildren.map((child) => (\n <div key={child.id} className=\"flex items-center\">\n {/* Horizontal branch line */}\n <div className=\"h-px w-4 shrink-0 bg-[hsl(var(--border))]\" />\n <MindMapSubtree node={child} expandedIds={expandedIds} onToggle={onToggle} />\n </div>\n ))}\n </VerticalRail>\n </>\n )}\n </div>\n )\n}\n\n/**\n * Draws a vertical rail from the center of the first child to the center\n * of the last child. Uses absolute-positioned segments per row:\n * - first: top 50% → bottom 0\n * - middle: top 0 → bottom 0\n * - last: top 0 → bottom 50%\n */\nfunction VerticalRail({ count, children }: { count: number; children: ReactNode[] }) {\n if (count <= 1) {\n return <div className=\"flex flex-col\">{children}</div>\n }\n\n return (\n <div className=\"flex flex-col\">\n {children.map((child, i) => (\n <div key={i} className={cn(\"relative\", i > 0 && \"pt-1.5\")}>\n <div\n className=\"absolute left-0 w-px bg-[hsl(var(--border))]\"\n style={{\n top: i === 0 ? \"50%\" : 0,\n bottom: i === count - 1 ? \"50%\" : 0,\n }}\n />\n {child}\n </div>\n ))}\n </div>\n )\n}\n","import { CheckCircle2, Circle, Loader2, XCircle } from \"lucide-react\"\nimport type { PlanNode } from \"../types\"\n\nexport function PlanStatusIcon({\n status,\n size = 16,\n}: {\n status: PlanNode[\"status\"]\n size?: number\n}) {\n if (status === \"pending\") {\n return (\n <Circle\n size={size}\n className=\"shrink-0 text-[hsl(var(--muted-foreground))] transition-transform duration-300\"\n />\n )\n }\n\n if (status === \"running\") {\n return (\n <Loader2\n size={size}\n className=\"shrink-0 animate-spin text-[hsl(var(--primary))] transition-transform duration-300\"\n />\n )\n }\n\n if (status === \"done\") {\n return (\n <CheckCircle2\n size={size}\n className=\"shrink-0 scale-105 text-green-500 transition-transform duration-300\"\n />\n )\n }\n\n return (\n <XCircle\n size={size}\n className=\"shrink-0 text-destructive transition-transform duration-300\"\n />\n )\n}\n","import { BookOpen, Link2 } from \"lucide-react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { SkillInfo } from \"../types\"\n\ninterface Props {\n skills: SkillInfo[]\n active: boolean\n}\n\nfunction planSkillDisplayName(skill: SkillInfo) {\n return skill.displayName?.trim() || skill.skillId\n}\n\n/** Extract numbered steps from markdown content (e.g. \"1. foo\\n2. bar\") */\nfunction extractSteps(content: string): string[] {\n return content\n .split(\"\\n\")\n .filter((line) => /^\\d+\\.\\s/.test(line.trim()))\n .map((line) => line.trim().replace(/^\\d+\\.\\s*/, \"\"))\n .slice(0, 5)\n}\n\nexport function SkillAnalysis({ skills: rawSkills, active }: Props) {\n const skills = Array.isArray(rawSkills) ? rawSkills : []\n return (\n <div\n className={cn(\n \"transition-opacity duration-500\",\n active ? \"opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n >\n <div className=\"columns-2 gap-4\">\n {skills.map((skill) => {\n const steps = skill.content ? extractSteps(skill.content) : []\n return (\n <div\n key={skill.skillId}\n className=\"mb-4 break-inside-avoid overflow-hidden rounded-xl border border-[hsl(var(--primary)/0.4)] bg-[hsl(var(--card))] shadow-lg shadow-[hsl(var(--primary)/0.05)] transition-all duration-500\"\n >\n <div className=\"flex items-center gap-2 px-4 py-3\">\n <BookOpen size={15} className=\"shrink-0 text-[hsl(var(--primary))]\" />\n <span className=\"min-w-0 truncate text-[15px] font-semibold text-[hsl(var(--foreground))]\">\n {planSkillDisplayName(skill)}\n </span>\n </div>\n\n <div className=\"border-t border-[hsl(var(--border)/0.5)] px-4 py-2.5\">\n <p className=\"text-sm leading-relaxed text-[hsl(var(--muted-foreground))]\">\n {skill.description}\n </p>\n </div>\n\n <div className=\"border-t border-[hsl(var(--border)/0.5)] px-4 py-2.5\">\n {skill.references && skill.references.length > 0 && (\n <div className=\"mb-2 flex flex-wrap gap-1.5\">\n {skill.references.map((ref, refIdx) => (\n <span\n key={`${refIdx}-${ref}`}\n className=\"inline-flex items-center gap-1 rounded-md bg-[hsl(var(--primary)/0.1)] px-2 py-0.5 text-xs text-[hsl(var(--primary))]\"\n >\n <Link2 size={10} />\n {ref}\n </span>\n ))}\n </div>\n )}\n {steps.length > 0 && (\n <ol className=\"list-inside list-decimal space-y-0.5 text-sm leading-relaxed text-[hsl(var(--muted-foreground)/0.8)]\">\n {steps.map((step, idx) => (\n <li key={idx}>{step}</li>\n ))}\n </ol>\n )}\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n","import { CheckCircle2, Search, Sparkles } from \"lucide-react\"\nimport { useMemo } from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { SkillCatalogItem, SkillInfo } from \"../types\"\n\ninterface Props {\n intent: string\n searchResults: SkillInfo[]\n selectedSkills: SkillInfo[]\n allSkillNames: SkillCatalogItem[]\n active: boolean\n}\n\n/** Stable pseudo-random size class for word cloud variety */\nfunction sizeClass(name: string): string {\n const hash = name.split(\"\").reduce((acc, c) => acc + c.charCodeAt(0), 0)\n const sizes = [\"text-xs\", \"text-sm\", \"text-[15px]\"]\n return sizes[hash % sizes.length]\n}\n\nfunction planSkillDisplayName(skill: { skillId: string; displayName?: string }) {\n return skill.displayName?.trim() || skill.skillId\n}\n\nexport function SkillDiscovery({\n intent,\n searchResults: rawSearchResults,\n selectedSkills: rawSelectedSkills,\n allSkillNames: rawAllSkillNames,\n active,\n}: Props) {\n const searchResults = Array.isArray(rawSearchResults) ? rawSearchResults : []\n const selectedSkills = Array.isArray(rawSelectedSkills) ? rawSelectedSkills : []\n const allSkillNames = Array.isArray(rawAllSkillNames) ? rawAllSkillNames : []\n const searchNames = useMemo(() => new Set(searchResults.map((s) => s.skillId)), [searchResults])\n const selectedNames = useMemo(\n () => new Set(selectedSkills.map((s) => s.skillId)),\n [selectedSkills],\n )\n\n const cloudItems = useMemo(() => {\n const bgItems = allSkillNames\n .filter((skill) => !searchNames.has(skill.skillId))\n .map((skill) => ({\n name: planSkillDisplayName(skill),\n key: `bg:${skill.skillId}`,\n isSearch: false,\n isSelected: false,\n }))\n const searchItems = searchResults.map((s) => ({\n name: planSkillDisplayName(s),\n key: `search:${s.skillId}`,\n isSearch: true,\n isSelected: selectedNames.has(s.skillId),\n }))\n\n const result = [...bgItems]\n for (let i = 0; i < searchItems.length; i++) {\n const insertAt = Math.round(((i + 1) / (searchItems.length + 1)) * result.length)\n result.splice(insertAt, 0, searchItems[i])\n }\n return result\n }, [allSkillNames, searchNames, searchResults, selectedNames])\n\n return (\n <div\n className={cn(\n \"flex h-full flex-col gap-6 transition-opacity duration-500\",\n active ? \"opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n >\n <div className=\"flex shrink-0 max-w-md self-center flex-col items-center gap-2.5 rounded-2xl border border-[hsl(var(--primary)/0.4)] bg-[hsl(var(--primary)/0.08)] px-6 py-5 text-center shadow-lg shadow-[hsl(var(--primary)/0.1)]\">\n <Sparkles size={20} className=\"text-[hsl(var(--primary))]\" />\n <p className=\"break-words text-[15px] leading-relaxed text-[hsl(var(--foreground))]\">\n {intent}\n </p>\n </div>\n\n <div className=\"flex min-h-0 flex-1 flex-wrap content-start items-start justify-center gap-x-4 gap-y-3 overflow-y-auto px-6 pb-6\">\n {cloudItems.map((item) => {\n if (item.isSearch && item.isSelected) {\n return (\n <span\n key={item.key}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-[hsl(var(--primary)/0.5)] bg-[hsl(var(--primary)/0.12)] px-3 py-1.5 text-[15px] font-medium text-[hsl(var(--primary))] shadow-md shadow-[hsl(var(--primary)/0.15)] transition-all duration-500\"\n >\n <CheckCircle2 size={14} className=\"shrink-0\" />\n {item.name}\n </span>\n )\n }\n\n if (item.isSearch) {\n return (\n <span\n key={item.key}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-[hsl(var(--foreground)/0.3)] bg-[hsl(var(--foreground)/0.08)] px-3 py-1.5 text-[15px] font-medium text-[hsl(var(--foreground))] transition-all duration-500\"\n >\n <Search size={14} className=\"shrink-0\" />\n {item.name}\n </span>\n )\n }\n\n return (\n <span\n key={item.key}\n className={cn(\n \"select-none font-medium text-[hsl(var(--foreground)/0.45)] transition-all duration-500\",\n sizeClass(item.name),\n )}\n >\n {item.name}\n </span>\n )\n })}\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":["BookOpen","GitBranch","Search","useMemo","useState","ChevronRight","Workflow","jsx","jsx","jsxs","ChevronRight","Workflow","jsx","jsxs","CheckCircle2","useMemo","jsx","jsxs","planSkillDisplayName","useMemo","CheckCircle2","Fragment","jsx","jsxs","Search","BookOpen","GitBranch","useMemo","useState"]}
1
+ {"version":3,"sources":["../../../../src/react/components/plan/debug-log.ts","../../../../src/react/components/plan/PlanVisualization.tsx","../../../../src/react/components/plan/phases/PlanTree.tsx","../../../../src/react/components/plan/phases/PlanMindMap.tsx","../../../../src/react/components/plan/phases/PlanStatusIcon.tsx","../../../../src/react/components/plan/phases/SkillAnalysis.tsx","../../../../src/react/components/plan/phases/SkillDiscovery.tsx"],"sourcesContent":["/**\n * Debug logger for Plan timeline events.\n * Stores events in memory with timestamps for debugging animation timing\n * in real conversation environments.\n *\n * Events are stored in window.__planTimelineLog and can be exported as JSON.\n */\n\nexport interface PlanTimelineEvent {\n /** ISO timestamp */\n ts: string\n /** Milliseconds since first event in this session */\n elapsed: number\n /** Event type */\n event: string\n /** Additional data */\n data?: Record<string, unknown>\n}\n\nlet events: PlanTimelineEvent[] = []\nlet startTime: number | null = null\n\n/** Set to true to enable console logging. Defaults to true in dev (localhost). */\nconst verbose =\n typeof window !== \"undefined\" &&\n (window.location?.hostname === \"localhost\" || window.location?.hostname === \"127.0.0.1\")\n\nexport function logPlanEvent(event: string, data?: Record<string, unknown>) {\n const now = Date.now()\n if (startTime === null) startTime = now\n\n const entry: PlanTimelineEvent = {\n ts: new Date(now).toISOString(),\n elapsed: now - startTime,\n event,\n data,\n }\n events.push(entry)\n\n if (verbose) {\n // Store on window for devtools access\n ;(window as unknown as Record<string, unknown>).__planTimelineLog = events\n console.log(`[PlanTimeline] +${entry.elapsed}ms ${event}`, data ?? \"\")\n }\n}\n\nexport function clearPlanLog() {\n events = []\n startTime = null\n}\n\nexport function exportPlanLog(): PlanTimelineEvent[] {\n return [...events]\n}\n\nexport function downloadPlanLog() {\n const blob = new Blob([JSON.stringify(events, null, 2)], { type: \"application/json\" })\n const url = URL.createObjectURL(blob)\n const a = document.createElement(\"a\")\n a.href = url\n a.download = `plan-timeline-${new Date().toISOString().slice(0, 19).replace(/:/g, \"-\")}.json`\n a.click()\n URL.revokeObjectURL(url)\n}\n","import { BookOpen, GitBranch, Search } from \"lucide-react\"\nimport { useMemo, useRef, useState } from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport type { ChatMessage } from \"../../schemas/message\"\nimport { AskUserQuestionBlock, type AskUserAnswerData } from \"../chat/AskUserQuestionBlock\"\nimport { parsePlanMessages } from \"./parse-plan-messages\"\nimport { PlanTree } from \"./phases/PlanTree\"\nimport { SkillAnalysis } from \"./phases/SkillAnalysis\"\nimport { SkillDiscovery } from \"./phases/SkillDiscovery\"\nimport type { Phase, PlanData, SkillCatalogItem } from \"./types\"\n\ninterface Props {\n messages: ChatMessage[]\n /** All skill names from the registry, used as word cloud background in Phase 1 */\n allSkillNames?: SkillCatalogItem[]\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n sessionStatus?: string\n isStreaming?: boolean\n}\n\nconst PHASE_LABELS: { key: Phase; label: string; icon: typeof Search }[] = [\n { key: \"discovering\", label: \"技能发现\", icon: Search },\n { key: \"analyzing\", label: \"技能分析\", icon: BookOpen },\n { key: \"generating\", label: \"计划生成\", icon: GitBranch },\n]\n\nfunction getLatestPhaseIndex(data: PlanData): number {\n if (data.plan != null || data.hasPlanContent) return 2\n if (data.selectedSkills.length > 0) return 1\n if (data.searchResults.length > 0) return 0\n return -1\n}\n\nexport function PlanVisualization({\n messages: rawMessages,\n allSkillNames: rawAllSkillNames = [],\n onAnswer,\n sessionStatus,\n isStreaming = false,\n}: Props) {\n const messages = Array.isArray(rawMessages) ? rawMessages : []\n const allSkillNames = Array.isArray(rawAllSkillNames) ? rawAllSkillNames : []\n const data = useMemo(() => parsePlanMessages(messages), [messages])\n const latestIdx = getLatestPhaseIndex(data)\n const isWaitingForInput = sessionStatus === \"waiting_for_input\"\n const hasError = sessionStatus === \"failed\"\n const isInterrupted = sessionStatus === \"interrupted\"\n const isSessionActive =\n isStreaming ||\n sessionStatus === \"created\" ||\n sessionStatus === \"running\" ||\n sessionStatus === \"waiting_for_input\"\n const activeStatusIdx = latestIdx >= 0 ? latestIdx : 0\n const latestAskQuestion = data.askQuestions[data.askQuestions.length - 1]\n const hasPhaseData = latestIdx >= 0\n\n // Determine which interactive surface to show based on the last pause tool\n const showAskQuestion =\n latestAskQuestion &&\n isWaitingForInput &&\n data.lastPauseTool === \"AskUserQuestion\" &&\n onAnswer\n\n const [selectedTab, setSelectedTab] = useState<number | null>(null)\n // Reset manual selection when a new planning cycle starts (latestIdx drops backward)\n const prevLatestRef = useRef(latestIdx)\n if (latestIdx < prevLatestRef.current) {\n setSelectedTab(null)\n }\n prevLatestRef.current = latestIdx\n const activeSelectedTab = selectedTab != null && selectedTab <= latestIdx ? selectedTab : null\n const viewIdx = activeSelectedTab ?? latestIdx\n\n return (\n <div className=\"flex flex-col gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.4)] p-5\">\n {hasPhaseData && (\n <>\n {/* Phase indicator bar */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-1\">\n {PHASE_LABELS.map((p, i) => {\n const Icon = p.icon\n const isViewing = viewIdx === i\n const isDone = latestIdx > i\n const isStatusPhase = i === activeStatusIdx && (hasError || isInterrupted)\n const tabHasData =\n (i === 0 && data.searchResults.length > 0) ||\n (i === 1 && data.selectedSkills.length > 0) ||\n (i === 2 && (data.plan != null || data.hasPlanContent))\n const isReachable = i <= latestIdx || tabHasData\n return (\n <div key={p.key} className=\"flex items-center\">\n {i > 0 && (\n <div\n className={cn(\n \"mx-1.5 h-px w-6 transition-colors duration-300\",\n isDone && !isStatusPhase\n ? \"bg-[hsl(var(--primary))]\"\n : \"bg-[hsl(var(--border))]\",\n )}\n />\n )}\n <button\n type=\"button\"\n disabled={!isReachable}\n onClick={() => isReachable && setSelectedTab(i === latestIdx ? null : i)}\n className={cn(\n \"flex items-center gap-2 rounded-full px-3.5 py-2 text-sm font-medium transition-all duration-300\",\n isViewing && \"bg-[hsl(var(--primary)/0.15)] text-[hsl(var(--primary))]\",\n !isViewing &&\n isDone &&\n \"text-[hsl(var(--primary)/0.6)] hover:bg-[hsl(var(--primary)/0.08)]\",\n !isReachable && \"cursor-default text-[hsl(var(--muted-foreground))]\",\n isReachable &&\n !isViewing &&\n !isDone &&\n tabHasData &&\n \"text-[hsl(var(--primary)/0.5)] hover:bg-[hsl(var(--primary)/0.08)]\",\n isReachable &&\n !isViewing &&\n !isDone &&\n !tabHasData &&\n \"text-[hsl(var(--muted-foreground))]\",\n )}\n >\n <Icon size={12} />\n {p.label}\n {latestIdx === i && isSessionActive && activeSelectedTab === null && (\n <span\n className={cn(\n \"h-1.5 w-1.5 animate-pulse rounded-full\",\n hasError\n ? \"bg-[hsl(var(--destructive))]\"\n : isInterrupted\n ? \"bg-orange-400\"\n : \"bg-[hsl(var(--primary))]\",\n )}\n />\n )}\n {isStatusPhase && latestIdx !== i && (\n <span\n className={cn(\n \"h-1.5 w-1.5 rounded-full\",\n hasError ? \"bg-[hsl(var(--destructive))]\" : \"bg-orange-400\",\n )}\n />\n )}\n </button>\n </div>\n )\n })}\n </div>\n\n {/* Controls */}\n <div className=\"flex items-center gap-1\">\n {hasError && (\n <span className=\"rounded-full bg-[hsl(var(--destructive)/0.12)] px-2.5 py-1 text-xs font-medium text-[hsl(var(--destructive))]\">\n 出错\n </span>\n )}\n {isInterrupted && (\n <span className=\"rounded-full bg-orange-500/10 px-2.5 py-1 text-xs font-medium text-orange-300\">\n 已中断\n </span>\n )}\n </div>\n </div>\n\n {/* Phase content — conditional rendering instead of absolute overlay */}\n <div className=\"min-h-0\">\n {viewIdx === 0 && (\n <SkillDiscovery\n intent={data.intent}\n searchResults={data.searchResults}\n selectedSkills={data.selectedSkills}\n allSkillNames={allSkillNames}\n active\n />\n )}\n {viewIdx === 1 && (\n <SkillAnalysis skills={data.selectedSkills} active />\n )}\n {viewIdx === 2 &&\n (data.plan != null ? (\n <PlanTree root={data.plan.root} notes={data.plan.notes} active />\n ) : data.parseError ? (\n <div className=\"flex min-h-[240px] items-center justify-center rounded-xl border border-[hsl(var(--destructive)/0.35)] bg-[hsl(var(--destructive)/0.08)] px-6 text-sm text-[hsl(var(--destructive))]\">\n {data.parseError}\n </div>\n ) : data.hasPlanContent ? (\n <div className=\"flex min-h-[240px] items-center justify-center rounded-xl border border-dashed border-[hsl(var(--border))] bg-[hsl(var(--card)/0.3)] px-6 text-sm text-[hsl(var(--muted-foreground))]\">\n 计划解析中...\n </div>\n ) : null)}\n </div>\n </>\n )}\n\n {/* AskUserQuestion standalone card (when no phase data) */}\n {!hasPhaseData && showAskQuestion && (\n <AskUserQuestionBlock data={latestAskQuestion.data} answered={false} toolCallId={latestAskQuestion.toolCallId} sessionStatus={sessionStatus ?? \"\"} onAnswer={onAnswer} />\n )}\n\n {hasPhaseData && showAskQuestion && (\n <AskUserQuestionBlock data={latestAskQuestion.data} answered={false} toolCallId={latestAskQuestion.toolCallId} sessionStatus={sessionStatus ?? \"\"} onAnswer={onAnswer} />\n )}\n\n </div>\n )\n}\n","import {\n CheckSquare,\n ChevronRight,\n GitBranch,\n List,\n Workflow,\n} from \"lucide-react\"\nimport { useCallback, useMemo, useState } from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { PlanNode } from \"../types\"\nimport { PlanMindMap } from \"./PlanMindMap\"\nimport { PlanStatusIcon } from \"./PlanStatusIcon\"\n\ntype ViewMode = \"mindmap\" | \"tree\"\n\n/** Collect node ids up to (and including) a given depth. */\nfunction collectIdsToDepth(node: PlanNode, maxDepth: number, out: Set<string>) {\n if (node.depth > maxDepth) return\n out.add(node.id)\n for (const child of node.children ?? []) collectIdsToDepth(child, maxDepth, out)\n}\n\ninterface Props {\n root: PlanNode\n notes: string[]\n active: boolean\n}\n\n/** Recursively fingerprint the full tree so key changes on any structural/label change. */\nfunction treeFinger(node: PlanNode): string {\n const children = node.children ?? []\n if (children.length === 0) return node.label\n return `${node.label}[${children.map(treeFinger).join(\",\")}]`\n}\n\nexport function PlanTree({ root, notes, active }: Props) {\n return <PlanTreeContent key={treeFinger(root)} root={root} notes={notes ?? []} active={active} />\n}\n\nfunction PlanTreeContent({ root, notes, active }: Props) {\n const [viewMode, setViewMode] = useState<ViewMode>(\"mindmap\")\n\n // Compute default expanded set: root + depth-1 children\n const defaultExpanded = useMemo(() => {\n const ids = new Set<string>()\n collectIdsToDepth(root, 1, ids)\n return ids\n }, [root])\n\n const [expandedIds, setExpandedIds] = useState<Set<string>>(defaultExpanded)\n\n const toggle = useCallback((id: string) => {\n setExpandedIds((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }, [])\n\n return (\n <div className={cn(!active && \"pointer-events-none opacity-0\")}>\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center justify-end\">\n <div className=\"flex items-center gap-0.5 rounded-lg border border-[hsl(var(--border))] p-0.5\">\n <button\n type=\"button\"\n onClick={() => setViewMode(\"mindmap\")}\n className={cn(\n \"rounded-md p-1.5 transition-colors\",\n viewMode === \"mindmap\"\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]\",\n )}\n title=\"思维导图\"\n >\n <GitBranch size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode(\"tree\")}\n className={cn(\n \"rounded-md p-1.5 transition-colors\",\n viewMode === \"tree\"\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]\",\n )}\n title=\"列表视图\"\n >\n <List size={14} />\n </button>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.5)] px-3 py-3\">\n {viewMode === \"mindmap\" ? (\n <PlanMindMap root={root} expandedIds={expandedIds} onToggle={toggle} />\n ) : (\n <TreeNode node={root} />\n )}\n </div>\n\n {notes.length > 0 && (\n <div className=\"rounded-xl border border-[hsl(var(--border)/0.5)] bg-[hsl(var(--card)/0.5)] px-4 py-3 text-sm text-[hsl(var(--muted-foreground))]\">\n {notes.map((note, i) => (\n <p key={i} className=\"py-0.5\">\n <span className=\"mr-1.5 text-[hsl(var(--primary)/0.6)]\">{i + 1}.</span>\n {note}\n </p>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n\nfunction TreeNode({ node }: { node: PlanNode }) {\n const children = node.children ?? []\n const hasChildren = children.length > 0\n\n return (\n <div>\n <div\n className=\"group flex min-w-0 items-center gap-2 rounded-md px-2 py-2 hover:bg-[hsl(var(--accent)/0.5)]\"\n style={{ paddingLeft: `${node.depth * 24 + 10}px` }}\n >\n {hasChildren ? (\n <ChevronRight\n size={16}\n className=\"shrink-0 rotate-90 text-[hsl(var(--muted-foreground)/0.6)]\"\n />\n ) : (\n <span className=\"w-4 shrink-0\" />\n )}\n\n <PlanStatusIcon status={node.status} />\n\n {node.skillRef ? (\n <Workflow size={15} className=\"shrink-0 text-[hsl(var(--primary))]\" />\n ) : (\n <CheckSquare size={15} className=\"shrink-0 text-[hsl(var(--muted-foreground))]\" />\n )}\n\n <span className=\"min-w-0 flex-1 truncate text-[15px] font-medium text-[hsl(var(--foreground))]\">\n {node.label}\n </span>\n\n {node.skillRef && (\n <span className=\"ml-auto max-w-[160px] shrink-0 truncate rounded bg-[hsl(var(--primary)/0.1)] px-2 py-0.5 text-sm font-medium text-[hsl(var(--primary)/0.8)]\">\n {node.skillRef}\n </span>\n )}\n </div>\n\n {hasChildren && (\n <div className=\"relative\">\n <div\n className=\"absolute bottom-1 top-0 w-px bg-[hsl(var(--border)/0.4)]\"\n style={{ left: `${node.depth * 24 + 18}px` }}\n />\n {children.map((child) => (\n <TreeNode key={child.id} node={child} />\n ))}\n </div>\n )}\n </div>\n )\n}\n","import { ChevronRight, Workflow } from \"lucide-react\"\nimport type { ReactNode } from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { PlanNode } from \"../types\"\nimport { PlanStatusIcon } from \"./PlanStatusIcon\"\n\ninterface Props {\n root: PlanNode\n expandedIds: Set<string>\n onToggle: (id: string) => void\n}\n\nexport function PlanMindMap({ root, expandedIds, onToggle }: Props) {\n return (\n <div className=\"overflow-x-auto py-2\">\n <MindMapSubtree node={root} expandedIds={expandedIds} onToggle={onToggle} isRoot />\n </div>\n )\n}\n\nfunction MindMapSubtree({\n node,\n expandedIds,\n onToggle,\n isRoot = false,\n}: {\n node: PlanNode\n expandedIds: Set<string>\n onToggle: (id: string) => void\n isRoot?: boolean\n}) {\n const children = node.children ?? []\n const hasChildren = children.length > 0\n const isExpanded = expandedIds.has(node.id)\n const visibleChildren = hasChildren && isExpanded ? children : []\n\n return (\n <div className=\"flex items-center\">\n {/* Node bubble */}\n <div\n role={hasChildren ? \"button\" : undefined}\n tabIndex={hasChildren ? 0 : undefined}\n aria-expanded={hasChildren ? isExpanded : undefined}\n onClick={hasChildren ? () => onToggle(node.id) : undefined}\n onKeyDown={\n hasChildren\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault()\n onToggle(node.id)\n }\n }\n : undefined\n }\n className={cn(\n \"relative z-10 shrink-0 rounded-lg border px-3 py-1.5 text-sm font-medium whitespace-nowrap select-none\",\n hasChildren && \"cursor-pointer\",\n isRoot\n ? \"border-[hsl(var(--primary))] bg-[hsl(var(--primary)/0.15)] text-[hsl(var(--primary))]\"\n : node.skillRef\n ? \"border-[hsl(var(--primary)/0.4)] bg-[hsl(var(--primary)/0.08)] text-[hsl(var(--foreground))]\"\n : \"border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]\",\n )}\n >\n <span className=\"flex items-center gap-1.5\">\n <PlanStatusIcon status={node.status} size={14} />\n {node.skillRef && <Workflow size={12} className=\"text-[hsl(var(--primary))]\" />}\n {node.label}\n {hasChildren && (\n <ChevronRight\n size={14}\n className={cn(\n \"text-[hsl(var(--muted-foreground))] transition-transform duration-150\",\n isExpanded && \"rotate-90\",\n )}\n />\n )}\n {hasChildren && !isExpanded && (\n <span className=\"ml-0.5 rounded-full bg-[hsl(var(--muted))] px-1.5 py-px text-[10px] text-[hsl(var(--muted-foreground))]\">\n +{children.length}\n </span>\n )}\n </span>\n </div>\n\n {/* Connector + Children */}\n {visibleChildren.length > 0 && (\n <>\n {/* Horizontal line from node to vertical rail */}\n <div className=\"h-px w-6 shrink-0 bg-[hsl(var(--border))]\" />\n\n <VerticalRail count={visibleChildren.length}>\n {visibleChildren.map((child) => (\n <div key={child.id} className=\"flex items-center\">\n {/* Horizontal branch line */}\n <div className=\"h-px w-4 shrink-0 bg-[hsl(var(--border))]\" />\n <MindMapSubtree node={child} expandedIds={expandedIds} onToggle={onToggle} />\n </div>\n ))}\n </VerticalRail>\n </>\n )}\n </div>\n )\n}\n\n/**\n * Draws a vertical rail from the center of the first child to the center\n * of the last child. Uses absolute-positioned segments per row:\n * - first: top 50% → bottom 0\n * - middle: top 0 → bottom 0\n * - last: top 0 → bottom 50%\n */\nfunction VerticalRail({ count, children }: { count: number; children: ReactNode[] }) {\n if (count <= 1) {\n return <div className=\"flex flex-col\">{children}</div>\n }\n\n return (\n <div className=\"flex flex-col\">\n {children.map((child, i) => (\n <div key={i} className={cn(\"relative\", i > 0 && \"pt-1.5\")}>\n <div\n className=\"absolute left-0 w-px bg-[hsl(var(--border))]\"\n style={{\n top: i === 0 ? \"50%\" : 0,\n bottom: i === count - 1 ? \"50%\" : 0,\n }}\n />\n {child}\n </div>\n ))}\n </div>\n )\n}\n","import { CheckCircle2, Circle, Loader2, XCircle } from \"lucide-react\"\nimport type { PlanNode } from \"../types\"\n\nexport function PlanStatusIcon({\n status,\n size = 16,\n}: {\n status: PlanNode[\"status\"]\n size?: number\n}) {\n if (status === \"pending\") {\n return (\n <Circle\n size={size}\n className=\"shrink-0 text-[hsl(var(--muted-foreground))] transition-transform duration-300\"\n />\n )\n }\n\n if (status === \"running\") {\n return (\n <Loader2\n size={size}\n className=\"shrink-0 animate-spin text-[hsl(var(--primary))] transition-transform duration-300\"\n />\n )\n }\n\n if (status === \"done\") {\n return (\n <CheckCircle2\n size={size}\n className=\"shrink-0 scale-105 text-green-500 transition-transform duration-300\"\n />\n )\n }\n\n return (\n <XCircle\n size={size}\n className=\"shrink-0 text-destructive transition-transform duration-300\"\n />\n )\n}\n","import { BookOpen, Link2 } from \"lucide-react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { SkillInfo } from \"../types\"\n\ninterface Props {\n skills: SkillInfo[]\n active: boolean\n}\n\nfunction planSkillDisplayName(skill: SkillInfo) {\n return skill.displayName?.trim() || skill.skillId\n}\n\n/** Extract numbered steps from markdown content (e.g. \"1. foo\\n2. bar\") */\nfunction extractSteps(content: string): string[] {\n return content\n .split(\"\\n\")\n .filter((line) => /^\\d+\\.\\s/.test(line.trim()))\n .map((line) => line.trim().replace(/^\\d+\\.\\s*/, \"\"))\n .slice(0, 5)\n}\n\nexport function SkillAnalysis({ skills: rawSkills, active }: Props) {\n const skills = Array.isArray(rawSkills) ? rawSkills : []\n return (\n <div\n className={cn(\n \"transition-opacity duration-500\",\n active ? \"opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n >\n <div className=\"columns-2 gap-4\">\n {skills.map((skill) => {\n const steps = skill.content ? extractSteps(skill.content) : []\n return (\n <div\n key={skill.skillId}\n className=\"mb-4 break-inside-avoid overflow-hidden rounded-xl border border-[hsl(var(--primary)/0.4)] bg-[hsl(var(--card))] shadow-lg shadow-[hsl(var(--primary)/0.05)] transition-all duration-500\"\n >\n <div className=\"flex items-center gap-2 px-4 py-3\">\n <BookOpen size={15} className=\"shrink-0 text-[hsl(var(--primary))]\" />\n <span className=\"min-w-0 truncate text-[15px] font-semibold text-[hsl(var(--foreground))]\">\n {planSkillDisplayName(skill)}\n </span>\n </div>\n\n <div className=\"border-t border-[hsl(var(--border)/0.5)] px-4 py-2.5\">\n <p className=\"text-sm leading-relaxed text-[hsl(var(--muted-foreground))]\">\n {skill.description}\n </p>\n </div>\n\n <div className=\"border-t border-[hsl(var(--border)/0.5)] px-4 py-2.5\">\n {skill.references && skill.references.length > 0 && (\n <div className=\"mb-2 flex flex-wrap gap-1.5\">\n {skill.references.map((ref, refIdx) => (\n <span\n key={`${refIdx}-${ref}`}\n className=\"inline-flex items-center gap-1 rounded-md bg-[hsl(var(--primary)/0.1)] px-2 py-0.5 text-xs text-[hsl(var(--primary))]\"\n >\n <Link2 size={10} />\n {ref}\n </span>\n ))}\n </div>\n )}\n {steps.length > 0 && (\n <ol className=\"list-inside list-decimal space-y-0.5 text-sm leading-relaxed text-[hsl(var(--muted-foreground)/0.8)]\">\n {steps.map((step, idx) => (\n <li key={idx}>{step}</li>\n ))}\n </ol>\n )}\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n","import { CheckCircle2, Search, Sparkles } from \"lucide-react\"\nimport { useMemo } from \"react\"\nimport { cn } from \"../../../lib/utils\"\nimport type { SkillCatalogItem, SkillInfo } from \"../types\"\n\ninterface Props {\n intent: string\n searchResults: SkillInfo[]\n selectedSkills: SkillInfo[]\n allSkillNames: SkillCatalogItem[]\n active: boolean\n}\n\n/** Stable pseudo-random size class for word cloud variety */\nfunction sizeClass(name: string): string {\n const hash = name.split(\"\").reduce((acc, c) => acc + c.charCodeAt(0), 0)\n const sizes = [\"text-xs\", \"text-sm\", \"text-[15px]\"]\n return sizes[hash % sizes.length]\n}\n\nfunction planSkillDisplayName(skill: { skillId: string; displayName?: string }) {\n return skill.displayName?.trim() || skill.skillId\n}\n\nexport function SkillDiscovery({\n intent,\n searchResults: rawSearchResults,\n selectedSkills: rawSelectedSkills,\n allSkillNames: rawAllSkillNames,\n active,\n}: Props) {\n const searchResults = Array.isArray(rawSearchResults) ? rawSearchResults : []\n const selectedSkills = Array.isArray(rawSelectedSkills) ? rawSelectedSkills : []\n const allSkillNames = Array.isArray(rawAllSkillNames) ? rawAllSkillNames : []\n const searchNames = useMemo(() => new Set(searchResults.map((s) => s.skillId)), [searchResults])\n const selectedNames = useMemo(\n () => new Set(selectedSkills.map((s) => s.skillId)),\n [selectedSkills],\n )\n\n const cloudItems = useMemo(() => {\n const bgItems = allSkillNames\n .filter((skill) => !searchNames.has(skill.skillId))\n .map((skill) => ({\n name: planSkillDisplayName(skill),\n key: `bg:${skill.skillId}`,\n isSearch: false,\n isSelected: false,\n }))\n const searchItems = searchResults.map((s) => ({\n name: planSkillDisplayName(s),\n key: `search:${s.skillId}`,\n isSearch: true,\n isSelected: selectedNames.has(s.skillId),\n }))\n\n const result = [...bgItems]\n for (let i = 0; i < searchItems.length; i++) {\n const insertAt = Math.round(((i + 1) / (searchItems.length + 1)) * result.length)\n result.splice(insertAt, 0, searchItems[i])\n }\n return result\n }, [allSkillNames, searchNames, searchResults, selectedNames])\n\n return (\n <div\n className={cn(\n \"flex h-full flex-col gap-6 transition-opacity duration-500\",\n active ? \"opacity-100\" : \"pointer-events-none opacity-0\",\n )}\n >\n <div className=\"flex shrink-0 max-w-md self-center flex-col items-center gap-2.5 rounded-2xl border border-[hsl(var(--primary)/0.4)] bg-[hsl(var(--primary)/0.08)] px-6 py-5 text-center shadow-lg shadow-[hsl(var(--primary)/0.1)]\">\n <Sparkles size={20} className=\"text-[hsl(var(--primary))]\" />\n <p className=\"break-words text-[15px] leading-relaxed text-[hsl(var(--foreground))]\">\n {intent}\n </p>\n </div>\n\n <div className=\"flex min-h-0 flex-1 flex-wrap content-start items-start justify-center gap-x-4 gap-y-3 overflow-y-auto px-6 pb-6\">\n {cloudItems.map((item) => {\n if (item.isSearch && item.isSelected) {\n return (\n <span\n key={item.key}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-[hsl(var(--primary)/0.5)] bg-[hsl(var(--primary)/0.12)] px-3 py-1.5 text-[15px] font-medium text-[hsl(var(--primary))] shadow-md shadow-[hsl(var(--primary)/0.15)] transition-all duration-500\"\n >\n <CheckCircle2 size={14} className=\"shrink-0\" />\n {item.name}\n </span>\n )\n }\n\n if (item.isSearch) {\n return (\n <span\n key={item.key}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-[hsl(var(--foreground)/0.3)] bg-[hsl(var(--foreground)/0.08)] px-3 py-1.5 text-[15px] font-medium text-[hsl(var(--foreground))] transition-all duration-500\"\n >\n <Search size={14} className=\"shrink-0\" />\n {item.name}\n </span>\n )\n }\n\n return (\n <span\n key={item.key}\n className={cn(\n \"select-none font-medium text-[hsl(var(--foreground)/0.45)] transition-all duration-500\",\n sizeClass(item.name),\n )}\n >\n {item.name}\n </span>\n )\n })}\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":["BookOpen","GitBranch","Search","useMemo","useState","ChevronRight","Workflow","jsx","jsx","jsxs","ChevronRight","Workflow","jsx","jsxs","CheckCircle2","useMemo","jsx","jsxs","planSkillDisplayName","useMemo","CheckCircle2","Fragment","jsx","jsxs","Search","BookOpen","GitBranch","useMemo","useState"]}
@@ -0,0 +1,10 @@
1
+ import type { ChatMessage } from "../../schemas/message.js";
2
+ import type { PlanData } from "./types.js";
3
+ /**
4
+ * Extract structured plan data from planning phase messages.
5
+ *
6
+ * Expects messages between planning-mode mode_change markers containing:
7
+ * - ReadSkill tool calls (技能调研:成功结果 = 选定技能,歧义 candidates = 候选列表)
8
+ * - Write tool call to PLAN.yaml with plan YAML
9
+ */
10
+ export declare function parsePlanMessages(allMessages: ChatMessage[]): PlanData;
@@ -0,0 +1,16 @@
1
+ import type { PlanNode } from "./types.js";
2
+ interface ParsedPlanResult {
3
+ plan: {
4
+ root: PlanNode;
5
+ notes: string[];
6
+ } | null;
7
+ error: string | null;
8
+ }
9
+ export type PlanStatusMap = Record<string, PlanNode["status"]>;
10
+ export declare function parsePlanTree(content: string): {
11
+ root: PlanNode;
12
+ notes: string[];
13
+ } | null;
14
+ export declare function applyPlanStatusesById(root: PlanNode, statuses: PlanStatusMap): PlanNode;
15
+ export declare function parsePlanTreeResult(content: string): ParsedPlanResult;
16
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { PlanNode } from "../types.js";
2
+ interface Props {
3
+ root: PlanNode;
4
+ expandedIds: Set<string>;
5
+ onToggle: (id: string) => void;
6
+ }
7
+ export declare function PlanMindMap({ root, expandedIds, onToggle }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { PlanNode } from "../types.js";
2
+ export declare function PlanStatusIcon({ status, size, }: {
3
+ status: PlanNode["status"];
4
+ size?: number;
5
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import type { PlanNode } from "../types.js";
2
+ interface Props {
3
+ root: PlanNode;
4
+ notes: string[];
5
+ active: boolean;
6
+ }
7
+ export declare function PlanTree({ root, notes, active }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { SkillInfo } from "../types.js";
2
+ interface Props {
3
+ skills: SkillInfo[];
4
+ active: boolean;
5
+ }
6
+ export declare function SkillAnalysis({ skills: rawSkills, active }: Props): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { SkillCatalogItem, SkillInfo } from "../types.js";
2
+ interface Props {
3
+ intent: string;
4
+ searchResults: SkillInfo[];
5
+ selectedSkills: SkillInfo[];
6
+ allSkillNames: SkillCatalogItem[];
7
+ active: boolean;
8
+ }
9
+ export declare function SkillDiscovery({ intent, searchResults: rawSearchResults, selectedSkills: rawSelectedSkills, allSkillNames: rawAllSkillNames, active, }: Props): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,56 @@
1
+ export interface SkillInfo {
2
+ skillId: string;
3
+ displayName?: string;
4
+ description: string;
5
+ content?: string;
6
+ references?: string[];
7
+ }
8
+ export interface SkillCatalogItem {
9
+ skillId: string;
10
+ displayName?: string;
11
+ }
12
+ export interface PlanNode {
13
+ id: string;
14
+ label: string;
15
+ skillRef: string | null;
16
+ children: PlanNode[];
17
+ depth: number;
18
+ status: "pending" | "running" | "done" | "failed";
19
+ }
20
+ export type Phase = "discovering" | "analyzing" | "generating";
21
+ export interface PlanData {
22
+ intent: string;
23
+ /** All skills returned by search_skills (candidates) */
24
+ searchResults: SkillInfo[];
25
+ /** Skills selected via get_skill_content (subset of searchResults, with content populated) */
26
+ selectedSkills: SkillInfo[];
27
+ plan: {
28
+ root: PlanNode;
29
+ notes: string[];
30
+ } | null;
31
+ /** Raw plan YAML content (non-empty even if parsePlanTree yields no plan) */
32
+ hasPlanContent: boolean;
33
+ /** PLAN.yaml exists but failed to parse/validate for UI rendering */
34
+ parseError: string | null;
35
+ /** AskUserQuestion tool calls found in planning messages */
36
+ askQuestions: Array<{
37
+ toolCallId: string;
38
+ data: {
39
+ questions: Array<{
40
+ question: string;
41
+ options: Array<{
42
+ label: string;
43
+ description: string;
44
+ }>;
45
+ multiSelect?: boolean;
46
+ }>;
47
+ };
48
+ }>;
49
+ /** File paths from Read tool calls (with status) */
50
+ readFiles: Array<{
51
+ path: string;
52
+ status: "pending" | "done" | "error" | "cancelled" | "awaiting_answer";
53
+ }>;
54
+ /** The last pause-triggering tool in this phase: determines what UI to show */
55
+ lastPauseTool: "AskUserQuestion" | "ExitPlanMode" | null;
56
+ }