@dfosco/storyboard-core 4.2.0-beta.2 → 4.2.0-beta.21

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 (414) hide show
  1. package/commandpalette.config.json +109 -24
  2. package/dist/storyboard-ui.css +1 -1
  3. package/dist/storyboard-ui.js +17379 -28568
  4. package/dist/storyboard-ui.js.map +1 -1
  5. package/dist/tailwind.css +1 -1
  6. package/package.json +5 -2
  7. package/scaffold/agents/prompt-agent.agent.md +181 -0
  8. package/scaffold/agents/terminal-agent.agent.md +351 -0
  9. package/scaffold/codex/config.toml +246 -0
  10. package/scaffold/manifest.json +5 -0
  11. package/scaffold/skills/canvas/SKILL.md +5 -4
  12. package/scaffold/skills/ship/SKILL.md +1 -1
  13. package/scaffold/storyboard.config.json +14 -1
  14. package/scaffold/toolbar.config.json +1 -1
  15. package/src/ActionMenuButton.jsx +100 -0
  16. package/src/AutosyncMenuButton.css +67 -0
  17. package/src/AutosyncMenuButton.jsx +241 -0
  18. package/src/BranchSelect.jsx +29 -0
  19. package/src/BranchSelect.module.css +30 -0
  20. package/src/CanvasAgentsMenu.jsx +87 -0
  21. package/src/CanvasCreateMenu.jsx +609 -0
  22. package/src/CanvasSnap.css +27 -0
  23. package/src/CanvasSnap.jsx +51 -0
  24. package/src/CanvasUndoRedo.css +36 -0
  25. package/src/CanvasUndoRedo.jsx +62 -0
  26. package/src/CanvasZoomControl.css +53 -0
  27. package/src/CanvasZoomControl.jsx +49 -0
  28. package/src/CanvasZoomToFit.css +18 -0
  29. package/src/CanvasZoomToFit.jsx +26 -0
  30. package/src/CommandMenu.css +8 -0
  31. package/src/CommandMenu.jsx +286 -0
  32. package/src/CommandPalette.jsx +35 -0
  33. package/src/CommandPaletteTrigger.jsx +25 -0
  34. package/src/CommentsMenuButton.jsx +38 -0
  35. package/src/CoreUIBar.css +47 -0
  36. package/src/CoreUIBar.jsx +855 -0
  37. package/src/CreateMenuButton.jsx +116 -0
  38. package/src/HideChromeTrigger.jsx +40 -0
  39. package/src/InspectorPanel.css +109 -0
  40. package/src/InspectorPanel.jsx +629 -0
  41. package/src/PwaInstallBanner.css +42 -0
  42. package/src/PwaInstallBanner.jsx +124 -0
  43. package/src/SidePanel.jsx +260 -0
  44. package/src/ThemeMenuButton.jsx +136 -0
  45. package/src/autosync/server.js +202 -5
  46. package/src/autosync/server.test.js +112 -0
  47. package/src/canvas/__tests__/agent-integration.test.js +593 -0
  48. package/src/canvas/__tests__/helpers/browser.js +95 -0
  49. package/src/canvas/__tests__/helpers/canvas-api.js +129 -0
  50. package/src/canvas/__tests__/helpers/perf.js +118 -0
  51. package/src/canvas/__tests__/helpers/setup.js +176 -0
  52. package/src/canvas/__tests__/helpers/tmux.js +130 -0
  53. package/src/canvas/__tests__/helpers/transcript.js +129 -0
  54. package/src/canvas/__tests__/terminal-integration.test.js +175 -0
  55. package/src/canvas/hot-pool.js +757 -0
  56. package/src/canvas/materializer.js +31 -0
  57. package/src/canvas/materializer.test.js +56 -0
  58. package/src/canvas/selectedWidgets.js +65 -7
  59. package/src/canvas/server.js +1801 -22
  60. package/src/canvas/server.test.js +239 -0
  61. package/src/canvas/terminal-config.js +331 -0
  62. package/src/canvas/terminal-registry.js +38 -0
  63. package/src/canvas/terminal-server.js +1037 -29
  64. package/src/canvas/writeGuard.js +51 -3
  65. package/src/canvasConfig.js +67 -1
  66. package/src/canvasConfig.test.js +79 -1
  67. package/src/cli/agent.js +85 -0
  68. package/src/cli/branch.js +232 -0
  69. package/src/cli/canvasAdd.js +59 -12
  70. package/src/cli/canvasBatch.js +98 -0
  71. package/src/cli/canvasBounds.js +1 -1
  72. package/src/cli/canvasRead.js +1 -1
  73. package/src/cli/canvasUpdate.js +179 -0
  74. package/src/cli/create.js +38 -14
  75. package/src/cli/dev.js +157 -83
  76. package/src/cli/exit.js +23 -24
  77. package/src/cli/index.js +55 -2
  78. package/src/cli/proxy.js +96 -37
  79. package/src/cli/schemas.js +22 -4
  80. package/src/cli/server.js +148 -25
  81. package/src/cli/serverUrl.js +8 -3
  82. package/src/cli/sessions.js +131 -5
  83. package/src/cli/setup.js +109 -11
  84. package/src/cli/terminal-commands.js +16 -8
  85. package/src/cli/terminal-messaging.js +231 -0
  86. package/src/cli/terminal-welcome.js +365 -33
  87. package/src/commandActions.js +1 -0
  88. package/src/commandPaletteConfig.js +9 -0
  89. package/src/comments/auth.js +2 -1
  90. package/src/comments/ui/AuthModal.jsx +114 -0
  91. package/src/comments/ui/CommentWindow.jsx +329 -0
  92. package/src/comments/ui/CommentsDrawer.jsx +102 -0
  93. package/src/comments/ui/Composer.jsx +64 -0
  94. package/src/comments/ui/authModal.test.js +1 -1
  95. package/src/comments/ui/commentWindow.js +16 -17
  96. package/src/comments/ui/commentsDrawer.js +25 -26
  97. package/src/comments/ui/composer.js +23 -24
  98. package/src/comments/ui/index.js +2 -3
  99. package/src/configSchema.js +59 -1
  100. package/src/configStore.js +161 -0
  101. package/src/core-ui-colors.css +12 -0
  102. package/src/devtools.js +17 -19
  103. package/src/devtools.test.js +18 -9
  104. package/src/featureFlags.js +12 -5
  105. package/src/fuzzySearch.test.js +10 -0
  106. package/src/index.js +14 -2
  107. package/src/lib/components/ui/alert/alert-action.jsx +11 -0
  108. package/src/lib/components/ui/alert/alert-description.jsx +11 -0
  109. package/src/lib/components/ui/alert/alert-title.jsx +11 -0
  110. package/src/lib/components/ui/alert/alert.jsx +25 -0
  111. package/src/lib/components/ui/alert/index.js +15 -15
  112. package/src/lib/components/ui/avatar/avatar-badge.jsx +22 -0
  113. package/src/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
  114. package/src/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
  115. package/src/lib/components/ui/avatar/avatar-group.jsx +19 -0
  116. package/src/lib/components/ui/avatar/avatar-image.jsx +15 -0
  117. package/src/lib/components/ui/avatar/avatar.jsx +19 -0
  118. package/src/lib/components/ui/avatar/index.js +20 -20
  119. package/src/lib/components/ui/badge/badge.jsx +31 -0
  120. package/src/lib/components/ui/badge/index.js +2 -2
  121. package/src/lib/components/ui/button/button.jsx +100 -0
  122. package/src/lib/components/ui/button/index.js +9 -9
  123. package/src/lib/components/ui/card/card-action.jsx +11 -0
  124. package/src/lib/components/ui/card/card-content.jsx +11 -0
  125. package/src/lib/components/ui/card/card-description.jsx +11 -0
  126. package/src/lib/components/ui/card/card-footer.jsx +11 -0
  127. package/src/lib/components/ui/card/card-header.jsx +19 -0
  128. package/src/lib/components/ui/card/card-title.jsx +11 -0
  129. package/src/lib/components/ui/card/card.jsx +17 -0
  130. package/src/lib/components/ui/card/index.js +23 -23
  131. package/src/lib/components/ui/checkbox/checkbox.jsx +29 -0
  132. package/src/lib/components/ui/checkbox/index.js +5 -5
  133. package/src/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
  134. package/src/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
  135. package/src/lib/components/ui/collapsible/collapsible.jsx +7 -0
  136. package/src/lib/components/ui/collapsible/index.js +11 -11
  137. package/src/lib/components/ui/dialog/dialog-close.jsx +7 -0
  138. package/src/lib/components/ui/dialog/dialog-content.jsx +34 -0
  139. package/src/lib/components/ui/dialog/dialog-description.jsx +15 -0
  140. package/src/lib/components/ui/dialog/dialog-footer.jsx +23 -0
  141. package/src/lib/components/ui/dialog/dialog-header.jsx +11 -0
  142. package/src/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
  143. package/src/lib/components/ui/dialog/dialog-portal.jsx +4 -0
  144. package/src/lib/components/ui/dialog/dialog-title.jsx +15 -0
  145. package/src/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
  146. package/src/lib/components/ui/dialog/dialog.jsx +4 -0
  147. package/src/lib/components/ui/dialog/index.js +32 -32
  148. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
  149. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
  150. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
  151. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
  152. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
  153. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
  154. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
  155. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
  156. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
  157. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
  158. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
  159. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
  160. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
  161. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
  162. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
  163. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
  164. package/src/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
  165. package/src/lib/components/ui/dropdown-menu/index.js +52 -52
  166. package/src/lib/components/ui/input/index.js +5 -5
  167. package/src/lib/components/ui/input/input.jsx +19 -0
  168. package/src/lib/components/ui/label/index.js +5 -5
  169. package/src/lib/components/ui/label/label.jsx +19 -0
  170. package/src/lib/components/ui/panel/index.js +21 -21
  171. package/src/lib/components/ui/panel/panel-body.jsx +11 -0
  172. package/src/lib/components/ui/panel/panel-close.jsx +16 -0
  173. package/src/lib/components/ui/panel/panel-content.jsx +29 -0
  174. package/src/lib/components/ui/panel/panel-footer.jsx +11 -0
  175. package/src/lib/components/ui/panel/panel-header.jsx +11 -0
  176. package/src/lib/components/ui/panel/panel-title.jsx +12 -0
  177. package/src/lib/components/ui/panel/panel.jsx +4 -0
  178. package/src/lib/components/ui/popover/index.js +26 -26
  179. package/src/lib/components/ui/popover/popover-close.jsx +7 -0
  180. package/src/lib/components/ui/popover/popover-content.jsx +22 -0
  181. package/src/lib/components/ui/popover/popover-description.jsx +11 -0
  182. package/src/lib/components/ui/popover/popover-header.jsx +11 -0
  183. package/src/lib/components/ui/popover/popover-portal.jsx +4 -0
  184. package/src/lib/components/ui/popover/popover-title.jsx +11 -0
  185. package/src/lib/components/ui/popover/popover-trigger.jsx +8 -0
  186. package/src/lib/components/ui/popover/popover.jsx +4 -0
  187. package/src/lib/components/ui/searchable-list.jsx +159 -0
  188. package/src/lib/components/ui/select/index.js +35 -35
  189. package/src/lib/components/ui/select/select-content.jsx +30 -0
  190. package/src/lib/components/ui/select/select-group-heading.jsx +17 -0
  191. package/src/lib/components/ui/select/select-group.jsx +15 -0
  192. package/src/lib/components/ui/select/select-item.jsx +26 -0
  193. package/src/lib/components/ui/select/select-label.jsx +11 -0
  194. package/src/lib/components/ui/select/select-portal.jsx +4 -0
  195. package/src/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
  196. package/src/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
  197. package/src/lib/components/ui/select/select-separator.jsx +15 -0
  198. package/src/lib/components/ui/select/select-trigger.jsx +25 -0
  199. package/src/lib/components/ui/select/select.jsx +4 -0
  200. package/src/lib/components/ui/separator/index.js +5 -5
  201. package/src/lib/components/ui/separator/separator.jsx +22 -0
  202. package/src/lib/components/ui/sheet/index.js +32 -32
  203. package/src/lib/components/ui/sheet/sheet-close.jsx +7 -0
  204. package/src/lib/components/ui/sheet/sheet-content.jsx +35 -0
  205. package/src/lib/components/ui/sheet/sheet-description.jsx +15 -0
  206. package/src/lib/components/ui/sheet/sheet-footer.jsx +11 -0
  207. package/src/lib/components/ui/sheet/sheet-header.jsx +11 -0
  208. package/src/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
  209. package/src/lib/components/ui/sheet/sheet-portal.jsx +4 -0
  210. package/src/lib/components/ui/sheet/sheet-title.jsx +15 -0
  211. package/src/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
  212. package/src/lib/components/ui/sheet/sheet.jsx +4 -0
  213. package/src/lib/components/ui/textarea/index.js +5 -5
  214. package/src/lib/components/ui/textarea/textarea.jsx +18 -0
  215. package/src/lib/components/ui/toggle/index.js +6 -9
  216. package/src/lib/components/ui/toggle/toggle.jsx +36 -0
  217. package/src/lib/components/ui/toggle-group/index.js +8 -8
  218. package/src/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
  219. package/src/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
  220. package/src/lib/components/ui/tooltip/index.js +3 -3
  221. package/src/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
  222. package/src/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
  223. package/src/lib/components/ui/tooltip/tooltip.jsx +11 -0
  224. package/src/lib/components/ui/trigger-button/index.js +3 -3
  225. package/src/lib/components/ui/trigger-button/trigger-button.css +38 -0
  226. package/src/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
  227. package/src/logger/devLogger.js +238 -0
  228. package/src/logger/devLogger.test.js +193 -0
  229. package/src/modes.test.js +4 -4
  230. package/src/mountStoryboardCore.js +123 -27
  231. package/src/paletteProviders.js +3 -0
  232. package/src/paletteProviders.test.js +2 -2
  233. package/src/server/index.js +98 -36
  234. package/src/sidepanel.css +214 -0
  235. package/src/styles/tailwind.css +1 -1
  236. package/src/svelte-plugin-ui/__tests__/ModeSwitch.test.ts +8 -8
  237. package/src/svelte-plugin-ui/__tests__/ToolbarShell.test.ts +11 -10
  238. package/src/svelte-plugin-ui/components/Icon.css +11 -0
  239. package/src/svelte-plugin-ui/components/Icon.jsx +281 -0
  240. package/src/svelte-plugin-ui/components/ModeSwitch.css +90 -0
  241. package/src/svelte-plugin-ui/components/ModeSwitch.jsx +47 -0
  242. package/src/svelte-plugin-ui/components/ToolbarShell.css +80 -0
  243. package/src/svelte-plugin-ui/components/ToolbarShell.jsx +84 -0
  244. package/src/svelte-plugin-ui/components/Viewfinder.css +412 -0
  245. package/src/svelte-plugin-ui/components/Viewfinder.jsx +512 -0
  246. package/src/svelte-plugin-ui/mount.ts +12 -16
  247. package/src/toolRegistry.js +4 -4
  248. package/src/toolbarConfigStore.js +30 -0
  249. package/src/tools/handlers/autosync.js +1 -1
  250. package/src/tools/handlers/canvasAddWidget.js +1 -1
  251. package/src/tools/handlers/canvasAgents.js +19 -0
  252. package/src/tools/handlers/canvasToolbar.js +8 -8
  253. package/src/tools/handlers/commandPalette.js +9 -0
  254. package/src/tools/handlers/comments.js +1 -1
  255. package/src/tools/handlers/create.js +1 -1
  256. package/src/tools/handlers/devtools.js +16 -0
  257. package/src/tools/handlers/devtools.test.js +38 -0
  258. package/src/tools/handlers/flows.js +1 -1
  259. package/src/tools/handlers/hideChrome.js +9 -0
  260. package/src/tools/handlers/paletteTheme.js +35 -0
  261. package/src/tools/handlers/theme.js +1 -1
  262. package/src/tools/registry.js +4 -1
  263. package/src/tools/surfaces/commandList.js +3 -3
  264. package/src/tools/surfaces/mainToolbar.js +3 -3
  265. package/src/tools/surfaces/registry.js +4 -4
  266. package/src/ui/design-modes.ts +2 -2
  267. package/src/ui/viewfinder.ts +1 -1
  268. package/src/vite/server-plugin.js +242 -60
  269. package/src/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
  270. package/src/workshop/features/createCanvas/index.js +1 -1
  271. package/src/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
  272. package/src/workshop/features/createFlow/index.js +1 -1
  273. package/src/workshop/features/createPage/CreatePageForm.jsx +304 -0
  274. package/src/workshop/features/createPage/index.js +1 -1
  275. package/src/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
  276. package/src/workshop/features/createPrototype/index.js +1 -1
  277. package/src/workshop/features/createPrototype/server.js +98 -0
  278. package/src/workshop/features/createStory/CreateStoryForm.jsx +208 -0
  279. package/src/workshop/features/createStory/index.js +1 -1
  280. package/src/workshop/ui/WorkshopPanel.jsx +98 -0
  281. package/src/workshop/ui/mount.ts +1 -1
  282. package/src/worktree/port.js +48 -0
  283. package/src/worktree/serverRegistry.js +120 -0
  284. package/toolbar.config.json +93 -42
  285. package/widgets.config.json +580 -12
  286. package/src/ActionMenuButton.svelte +0 -119
  287. package/src/AutosyncMenuButton.svelte +0 -397
  288. package/src/CanvasCreateMenu.svelte +0 -295
  289. package/src/CanvasSnap.svelte +0 -87
  290. package/src/CanvasUndoRedo.svelte +0 -108
  291. package/src/CanvasZoomControl.svelte +0 -111
  292. package/src/CanvasZoomToFit.svelte +0 -52
  293. package/src/CommandMenu.svelte +0 -249
  294. package/src/CommandPalette.svelte +0 -33
  295. package/src/CommentsMenuButton.svelte +0 -53
  296. package/src/CoreUIBar.svelte +0 -847
  297. package/src/CreateMenuButton.svelte +0 -133
  298. package/src/DocPanel.svelte +0 -299
  299. package/src/InspectorPanel.svelte +0 -745
  300. package/src/PwaInstallBanner.svelte +0 -124
  301. package/src/SidePanel.svelte +0 -480
  302. package/src/ThemeMenuButton.svelte +0 -132
  303. package/src/comments/ui/AuthModal.svelte +0 -108
  304. package/src/comments/ui/CommentWindow.svelte +0 -333
  305. package/src/comments/ui/CommentsDrawer.svelte +0 -96
  306. package/src/comments/ui/Composer.svelte +0 -65
  307. package/src/lib/components/ui/alert/alert-action.svelte +0 -19
  308. package/src/lib/components/ui/alert/alert-description.svelte +0 -22
  309. package/src/lib/components/ui/alert/alert-title.svelte +0 -22
  310. package/src/lib/components/ui/alert/alert.svelte +0 -38
  311. package/src/lib/components/ui/avatar/avatar-badge.svelte +0 -25
  312. package/src/lib/components/ui/avatar/avatar-fallback.svelte +0 -20
  313. package/src/lib/components/ui/avatar/avatar-group-count.svelte +0 -22
  314. package/src/lib/components/ui/avatar/avatar-group.svelte +0 -22
  315. package/src/lib/components/ui/avatar/avatar-image.svelte +0 -17
  316. package/src/lib/components/ui/avatar/avatar.svelte +0 -24
  317. package/src/lib/components/ui/badge/badge.svelte +0 -44
  318. package/src/lib/components/ui/button/button.svelte +0 -108
  319. package/src/lib/components/ui/card/card-action.svelte +0 -21
  320. package/src/lib/components/ui/card/card-content.svelte +0 -19
  321. package/src/lib/components/ui/card/card-description.svelte +0 -19
  322. package/src/lib/components/ui/card/card-footer.svelte +0 -18
  323. package/src/lib/components/ui/card/card-header.svelte +0 -21
  324. package/src/lib/components/ui/card/card-title.svelte +0 -14
  325. package/src/lib/components/ui/card/card.svelte +0 -21
  326. package/src/lib/components/ui/checkbox/checkbox.svelte +0 -39
  327. package/src/lib/components/ui/collapsible/collapsible-content.svelte +0 -7
  328. package/src/lib/components/ui/collapsible/collapsible-trigger.svelte +0 -7
  329. package/src/lib/components/ui/collapsible/collapsible.svelte +0 -11
  330. package/src/lib/components/ui/dialog/dialog-close.svelte +0 -11
  331. package/src/lib/components/ui/dialog/dialog-content.svelte +0 -42
  332. package/src/lib/components/ui/dialog/dialog-description.svelte +0 -17
  333. package/src/lib/components/ui/dialog/dialog-footer.svelte +0 -29
  334. package/src/lib/components/ui/dialog/dialog-header.svelte +0 -19
  335. package/src/lib/components/ui/dialog/dialog-overlay.svelte +0 -17
  336. package/src/lib/components/ui/dialog/dialog-portal.svelte +0 -7
  337. package/src/lib/components/ui/dialog/dialog-title.svelte +0 -17
  338. package/src/lib/components/ui/dialog/dialog-trigger.svelte +0 -11
  339. package/src/lib/components/ui/dialog/dialog.svelte +0 -7
  340. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +0 -16
  341. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -40
  342. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -27
  343. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +0 -18
  344. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +0 -7
  345. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -24
  346. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +0 -20
  347. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +0 -7
  348. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +0 -16
  349. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +0 -34
  350. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -17
  351. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +0 -19
  352. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +0 -17
  353. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +0 -27
  354. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +0 -7
  355. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -7
  356. package/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +0 -7
  357. package/src/lib/components/ui/input/input.svelte +0 -40
  358. package/src/lib/components/ui/label/label.svelte +0 -20
  359. package/src/lib/components/ui/panel/panel-body.svelte +0 -13
  360. package/src/lib/components/ui/panel/panel-close.svelte +0 -16
  361. package/src/lib/components/ui/panel/panel-content.svelte +0 -33
  362. package/src/lib/components/ui/panel/panel-footer.svelte +0 -13
  363. package/src/lib/components/ui/panel/panel-header.svelte +0 -16
  364. package/src/lib/components/ui/panel/panel-title.svelte +0 -14
  365. package/src/lib/components/ui/panel/panel.svelte +0 -15
  366. package/src/lib/components/ui/popover/popover-close.svelte +0 -7
  367. package/src/lib/components/ui/popover/popover-content.svelte +0 -27
  368. package/src/lib/components/ui/popover/popover-description.svelte +0 -19
  369. package/src/lib/components/ui/popover/popover-header.svelte +0 -19
  370. package/src/lib/components/ui/popover/popover-portal.svelte +0 -7
  371. package/src/lib/components/ui/popover/popover-title.svelte +0 -19
  372. package/src/lib/components/ui/popover/popover-trigger.svelte +0 -17
  373. package/src/lib/components/ui/popover/popover.svelte +0 -7
  374. package/src/lib/components/ui/select/select-content.svelte +0 -40
  375. package/src/lib/components/ui/select/select-group-heading.svelte +0 -19
  376. package/src/lib/components/ui/select/select-group.svelte +0 -17
  377. package/src/lib/components/ui/select/select-item.svelte +0 -38
  378. package/src/lib/components/ui/select/select-label.svelte +0 -18
  379. package/src/lib/components/ui/select/select-portal.svelte +0 -7
  380. package/src/lib/components/ui/select/select-scroll-down-button.svelte +0 -20
  381. package/src/lib/components/ui/select/select-scroll-up-button.svelte +0 -20
  382. package/src/lib/components/ui/select/select-separator.svelte +0 -17
  383. package/src/lib/components/ui/select/select-trigger.svelte +0 -27
  384. package/src/lib/components/ui/select/select.svelte +0 -11
  385. package/src/lib/components/ui/separator/separator.svelte +0 -23
  386. package/src/lib/components/ui/sheet/sheet-close.svelte +0 -7
  387. package/src/lib/components/ui/sheet/sheet-content.svelte +0 -43
  388. package/src/lib/components/ui/sheet/sheet-description.svelte +0 -17
  389. package/src/lib/components/ui/sheet/sheet-footer.svelte +0 -18
  390. package/src/lib/components/ui/sheet/sheet-header.svelte +0 -19
  391. package/src/lib/components/ui/sheet/sheet-overlay.svelte +0 -17
  392. package/src/lib/components/ui/sheet/sheet-portal.svelte +0 -7
  393. package/src/lib/components/ui/sheet/sheet-title.svelte +0 -17
  394. package/src/lib/components/ui/sheet/sheet-trigger.svelte +0 -7
  395. package/src/lib/components/ui/sheet/sheet.svelte +0 -7
  396. package/src/lib/components/ui/textarea/textarea.svelte +0 -21
  397. package/src/lib/components/ui/toggle/toggle.svelte +0 -45
  398. package/src/lib/components/ui/toggle-group/toggle-group-item.svelte +0 -35
  399. package/src/lib/components/ui/toggle-group/toggle-group.svelte +0 -63
  400. package/src/lib/components/ui/tooltip/tooltip-content.svelte +0 -24
  401. package/src/lib/components/ui/tooltip/tooltip-trigger.svelte +0 -27
  402. package/src/lib/components/ui/tooltip/tooltip.svelte +0 -9
  403. package/src/lib/components/ui/trigger-button/trigger-button.svelte +0 -106
  404. package/src/svelte-plugin-ui/components/Icon.svelte +0 -181
  405. package/src/svelte-plugin-ui/components/ModeSwitch.svelte +0 -121
  406. package/src/svelte-plugin-ui/components/ToolbarShell.svelte +0 -150
  407. package/src/svelte-plugin-ui/components/Viewfinder.svelte +0 -1001
  408. package/src/tools/handlers/docs.js +0 -11
  409. package/src/workshop/features/createCanvas/CreateCanvasForm.svelte +0 -139
  410. package/src/workshop/features/createFlow/CreateFlowForm.svelte +0 -314
  411. package/src/workshop/features/createPage/CreatePageForm.svelte +0 -249
  412. package/src/workshop/features/createPrototype/CreatePrototypeForm.svelte +0 -287
  413. package/src/workshop/features/createStory/CreateStoryForm.svelte +0 -161
  414. package/src/workshop/ui/WorkshopPanel.svelte +0 -97
@@ -5,21 +5,67 @@
5
5
  * Runs inside tmux, presents a Clack select prompt, loops back after
6
6
  * the chosen program exits.
7
7
  *
8
+ * When called with --startup <cmd>, auto-launches that command on the first
9
+ * iteration, then falls back to the interactive menu on subsequent iterations
10
+ * (i.e. when the command exits). This makes the welcome screen the universal
11
+ * supervisor for all terminal widget sessions.
12
+ *
8
13
  * Usage (called automatically by terminal-server for new sessions):
9
14
  * storyboard terminal-welcome [--branch <name>] [--canvas <name>]
15
+ * storyboard terminal-welcome --startup "copilot --agent terminal-agent" [--branch <name>] [--canvas <name>]
10
16
  */
11
17
 
12
18
  import * as p from '@clack/prompts'
13
19
  import { execSync, spawn } from 'node:child_process'
20
+ import { readFileSync, existsSync } from 'node:fs'
21
+ import { resolve, join } from 'node:path'
14
22
  import { parseFlags } from './flags.js'
15
23
  import { dim, cyan, bold } from './intro.js'
24
+ import { takePendingMessages } from '../canvas/terminal-config.js'
16
25
 
17
26
  const blue = (s) => `\x1b[34m${s}\x1b[0m`
18
27
 
28
+ // Prepend .storyboard/terminals/bin/ to PATH so `start`, `copilot`, etc.
29
+ // are available in child shells. Done once at startup; child shells inherit it.
30
+ const binDir = join(process.cwd(), '.storyboard', 'terminals', 'bin')
31
+ if (existsSync(binDir) && !process.env.PATH?.includes(binDir)) {
32
+ process.env.PATH = `${binDir}:${process.env.PATH || ''}`
33
+ }
34
+
35
+ /**
36
+ * Read agents config from storyboard.config.json.
37
+ * Returns an array of { id, label, startupCommand, resumeCommand } entries.
38
+ */
39
+ function loadAgents() {
40
+ try {
41
+ const raw = readFileSync(resolve(process.cwd(), 'storyboard.config.json'), 'utf8')
42
+ const config = JSON.parse(raw)
43
+ const agents = config?.canvas?.agents
44
+ if (!agents || typeof agents !== 'object') return []
45
+ return Object.entries(agents).map(([id, cfg]) => ({
46
+ id,
47
+ label: cfg.label || id,
48
+ startupCommand: cfg.startupCommand || null,
49
+ resumeCommand: cfg.resumeCommand || null,
50
+ readinessSignal: cfg.readinessSignal || null,
51
+ postStartup: cfg.postStartup || null,
52
+ })).filter(a => a.startupCommand)
53
+ } catch { return [] }
54
+ }
55
+
56
+ const agents = loadAgents()
57
+
58
+ // Enable/disable tmux mouse — must be off during Clack prompts (mouse
59
+ // events crash Clack), on during shell/copilot sessions (for scrolling).
60
+ function setMouse(on) {
61
+ try { execSync(`tmux set-option mouse ${on ? 'on' : 'off'} 2>/dev/null`, { stdio: 'ignore' }) } catch {}
62
+ }
63
+
19
64
  const flagSchema = {
20
65
  branch: { type: 'string', description: 'Current branch name' },
21
66
  canvas: { type: 'string', description: 'Current canvas name' },
22
67
  name: { type: 'string', description: 'Terminal pretty name' },
68
+ startup: { type: 'string', description: 'Auto-launch this command on first iteration' },
23
69
  }
24
70
 
25
71
  const { flags } = parseFlags(process.argv.slice(3), flagSchema)
@@ -27,27 +73,284 @@ const branch = flags.branch || 'unknown'
27
73
  const canvas = flags.canvas || 'unknown'
28
74
  const prettyName = flags.name || null
29
75
  const canvasShort = canvas === 'unknown' ? canvas : canvas.split('/').pop()
76
+ const startupCmd = flags.startup || null
77
+
78
+ /**
79
+ * Reset terminal state after a child process exits.
80
+ * Children (especially TUI apps) may leave the terminal in raw mode,
81
+ * alternate screen, or with the cursor hidden.
82
+ */
83
+ function resetTerminal() {
84
+ // Leave alternate screen, show cursor, reset attributes
85
+ process.stdout.write('\x1b[?1049l\x1b[?25h\x1b[0m')
86
+ try { execSync('stty sane 2>/dev/null', { stdio: 'ignore' }) } catch {}
87
+ }
88
+
89
+ /**
90
+ * Spawn an interactive shell with the storyboard bin dir on PATH.
91
+ * zsh re-initializes PATH from .zshrc/.zprofile, so we inject an
92
+ * `export PATH=...` via tmux send-keys after the shell initializes.
93
+ */
94
+ function spawnShell() {
95
+ const shell = process.env.SHELL || '/bin/zsh'
96
+ const child = spawn(shell, [], { stdio: 'inherit' })
97
+
98
+ // Inject PATH after shell init so `start`, `copilot`, etc. are available
99
+ if (existsSync(binDir)) {
100
+ setTimeout(() => {
101
+ try {
102
+ execSync(`tmux send-keys -l ${JSON.stringify(`export PATH="${binDir}:$PATH"`)}`, { stdio: 'ignore' })
103
+ execSync(`tmux send-keys Enter`, { stdio: 'ignore' })
104
+ setTimeout(() => {
105
+ try {
106
+ execSync(`tmux send-keys -l "clear"`, { stdio: 'ignore' })
107
+ execSync(`tmux send-keys Enter`, { stdio: 'ignore' })
108
+ } catch {}
109
+ }, 200)
110
+ } catch {}
111
+ }, 500)
112
+ }
113
+
114
+ return new Promise((resolve) => {
115
+ child.on('close', resolve)
116
+ child.on('error', resolve)
117
+ })
118
+ }
119
+
120
+ /**
121
+ * Get the current tmux session name (safe — returns null outside tmux).
122
+ */
123
+ function getTmuxName() {
124
+ try {
125
+ return execSync('tmux display-message -p "#{session_name}"', { encoding: 'utf8', timeout: 1000 }).trim() || null
126
+ } catch { return null }
127
+ }
128
+
129
+ /**
130
+ * Inject [System] identity message into the running agent via tmux send-keys.
131
+ * Mirrors the identity injection in terminal-server.js so agents launched from
132
+ * the welcome menu receive the same initial context.
133
+ */
134
+ function injectIdentityMessage(tmuxName) {
135
+ const widgetId = process.env.STORYBOARD_WIDGET_ID
136
+ if (!tmuxName || !widgetId) return
137
+
138
+ const canvasId = process.env.STORYBOARD_CANVAS_ID || canvas
139
+ const serverUrl = process.env.STORYBOARD_SERVER_URL || ''
140
+ const displayName = prettyName || widgetId
141
+ const configFile = `.storyboard/terminals/${widgetId}.json`
142
+
143
+ const msg = `[System] Your terminal identity has been set. widgetId=${widgetId} displayName=${displayName} canvasId=${canvasId} configFile=${configFile} serverUrl=${serverUrl} — this is a configuration step, no response needed.`
144
+ try {
145
+ execSync(`tmux send-keys -t "${tmuxName}" -l ${JSON.stringify(msg)}`, { stdio: 'ignore' })
146
+ execSync(`tmux send-keys -t "${tmuxName}" Enter`, { stdio: 'ignore' })
147
+ } catch {}
148
+ }
149
+
150
+ /**
151
+ * Deliver pending messages to the running agent via tmux send-keys.
152
+ * Uses takePendingMessages for atomic read+clear.
153
+ */
154
+ function deliverPendingMessages(tmuxName) {
155
+ const widgetId = process.env.STORYBOARD_WIDGET_ID
156
+ if (!tmuxName || !widgetId) return
157
+
158
+ const messages = takePendingMessages(widgetId)
159
+ messages.forEach((msg, i) => {
160
+ setTimeout(() => {
161
+ try {
162
+ const excerpt = msg.message.length > 200 ? msg.message.slice(0, 200) + '…' : msg.message
163
+ const formatted = `📩 [${msg.fromName || msg.from || 'unknown'} → you]\n\`\`\`\n${excerpt}\n\`\`\`${msg.from ? `\nFull context: cat .storyboard/terminals/${msg.from}.json | jq '.latestOutput.content'` : ''}`
164
+ execSync(`tmux send-keys -t "${tmuxName}" -l ${JSON.stringify(formatted)}`, { stdio: 'ignore' })
165
+ execSync(`tmux send-keys -t "${tmuxName}" Enter`, { stdio: 'ignore' })
166
+ } catch {}
167
+ }, i * 1500)
168
+ })
169
+ }
170
+
171
+ /**
172
+ * Launch an agent by spawning its startupCommand via the user's shell.
173
+ * After the agent reaches readiness, injects identity context and pending
174
+ * messages — same treatment as the terminal-server cold path.
175
+ *
176
+ * @param {Object} agent - Agent config with label, startupCommand, readinessSignal, postStartup
177
+ * @param {Object} [opts]
178
+ * @param {boolean} [opts.isInitialStartup=false] - Skip context injection on the first
179
+ * --startup iteration (terminal-server.js handles it independently).
180
+ */
181
+ async function launchAgent(agent, { isInitialStartup = false } = {}) {
182
+ // Show metadata after selection
183
+ const meta = [
184
+ prettyName ? `${dim('name:')} ${blue(prettyName)}` : null,
185
+ `${dim('branch:')} ${blue(branch)}`,
186
+ `${dim('canvas:')} ${blue(canvasShort)}`,
187
+ ].filter(Boolean).join(' ')
188
+ p.log.info(meta)
189
+ p.outro(dim(`Starting ${agent.label}...`))
190
+ setMouse(true)
191
+
192
+ try {
193
+ const shell = process.env.SHELL || '/bin/zsh'
194
+ const child = spawn(shell, ['-lc', agent.startupCommand], { stdio: 'inherit' })
195
+
196
+ // Context injection — inject identity, postStartup, and pending messages
197
+ // after the agent reaches readiness. Skip on initial --startup since
198
+ // terminal-server.js handles that path independently.
199
+ let pollInterval = null
200
+ const tmuxName = !isInitialStartup ? getTmuxName() : null
201
+ const widgetId = process.env.STORYBOARD_WIDGET_ID
202
+
203
+ if (tmuxName && widgetId) {
204
+ const readinessSignal = agent.readinessSignal
205
+ const firstWord = agent.startupCommand.trim().split(/\s+/)[0]
206
+
207
+ if (readinessSignal) {
208
+ let contextSent = false
209
+ pollInterval = setInterval(() => {
210
+ if (contextSent) { clearInterval(pollInterval); pollInterval = null; return }
211
+ try {
212
+ const paneContent = execSync(
213
+ `tmux capture-pane -t "${tmuxName}" -p`,
214
+ { encoding: 'utf8', timeout: 1000 }
215
+ )
216
+ // Check configured readiness signal + copilot prompt fallback
217
+ const isReady = paneContent.includes(readinessSignal) ||
218
+ (firstWord === 'copilot' && paneContent.match(/^[>❯]\s*$/m))
219
+ if (isReady) {
220
+ contextSent = true
221
+ clearInterval(pollInterval)
222
+ pollInterval = null
223
+ setTimeout(() => {
224
+ if (agent.postStartup) {
225
+ try {
226
+ execSync(`tmux send-keys -t "${tmuxName}" -l ${JSON.stringify(agent.postStartup)}`, { stdio: 'ignore' })
227
+ execSync(`tmux send-keys -t "${tmuxName}" Enter`, { stdio: 'ignore' })
228
+ } catch {}
229
+ }
230
+ injectIdentityMessage(tmuxName)
231
+ setTimeout(() => deliverPendingMessages(tmuxName), 2000)
232
+ }, 500)
233
+ }
234
+ } catch {}
235
+ }, 2000)
236
+ // Timeout after 30s — don't wait forever
237
+ setTimeout(() => {
238
+ if (!contextSent) {
239
+ contextSent = true
240
+ if (pollInterval) { clearInterval(pollInterval); pollInterval = null }
241
+ }
242
+ }, 30000)
243
+ } else {
244
+ // No readiness signal configured — inject after a delay
245
+ const delayTimer = setTimeout(() => {
246
+ injectIdentityMessage(tmuxName)
247
+ setTimeout(() => deliverPendingMessages(tmuxName), 2000)
248
+ }, 5000)
249
+ // Store reference for cleanup
250
+ pollInterval = { clear: () => clearTimeout(delayTimer) }
251
+ }
252
+ }
253
+
254
+ await new Promise((resolve) => {
255
+ child.on('close', () => {
256
+ if (pollInterval) {
257
+ if (typeof pollInterval.clear === 'function') pollInterval.clear()
258
+ else clearInterval(pollInterval)
259
+ }
260
+ resolve()
261
+ })
262
+ child.on('error', () => {
263
+ if (pollInterval) {
264
+ if (typeof pollInterval.clear === 'function') pollInterval.clear()
265
+ else clearInterval(pollInterval)
266
+ }
267
+ resolve()
268
+ })
269
+ })
270
+ } catch {
271
+ p.log.error(`Failed to start ${agent.label}. Is it installed?`)
272
+ await new Promise(r => setTimeout(r, 2000))
273
+ }
274
+ }
30
275
 
31
276
  async function welcomeLoop() {
277
+ let firstIteration = true
278
+
32
279
  while (true) {
280
+ // On first iteration with --startup, auto-launch the command
281
+ if (firstIteration && startupCmd) {
282
+ firstIteration = false
283
+
284
+ if (startupCmd === 'shell') {
285
+ // Plain shell — spawn interactive shell, return to welcome on exit
286
+ setMouse(true)
287
+ try { await spawnShell() } catch {}
288
+ resetTerminal()
289
+ continue
290
+ }
291
+
292
+ // Try to match against a configured agent for label resolution
293
+ const matchedAgent = agents.find(a =>
294
+ startupCmd.startsWith(a.startupCommand?.split(' ')[0])
295
+ )
296
+ const agent = matchedAgent || { label: startupCmd.split(/\s+/)[0], startupCommand: startupCmd }
297
+ await launchAgent(agent, { isInitialStartup: true })
298
+ resetTerminal()
299
+ continue
300
+ }
301
+ firstIteration = false
302
+
303
+ resetTerminal()
304
+ setMouse(false)
33
305
  console.clear()
34
306
  p.intro(`${bold('storyboard terminal')}`)
35
307
 
308
+ // Build the first option based on number of configured agents
309
+ const agentOption = agents.length > 1
310
+ ? { value: 'agents', label: '✦ Start a new agent session' }
311
+ : { value: 'copilot', label: `✦ Start a new ${agents[0]?.label || 'Copilot'} session` }
312
+
36
313
  const action = await p.select({
37
314
  message: 'How would you like to start?',
38
315
  options: [
39
- { value: 'copilot', label: '✦ Start a new Copilot session' },
316
+ agentOption,
40
317
  { value: 'shell', label: '▸ Start a new terminal session' },
41
318
  { value: 'sessions', label: '⊞ Browse existing sessions' },
42
319
  ],
43
320
  })
44
321
 
45
322
  if (p.isCancel(action)) {
46
- p.outro(dim('Opening shell...'))
47
- break
323
+ // Don't exit to shell on cancel — loop back to welcome
324
+ continue
325
+ }
326
+
327
+ if (action === 'agents') {
328
+ // Multi-agent sub-select
329
+ const agentChoice = await p.select({
330
+ message: 'Which agent?',
331
+ options: agents.map(a => ({
332
+ value: a.id,
333
+ label: `✦ Start a new ${a.label} session`,
334
+ })),
335
+ })
336
+
337
+ if (p.isCancel(agentChoice)) continue
338
+
339
+ const agent = agents.find(a => a.id === agentChoice)
340
+ if (agent) {
341
+ await launchAgent(agent)
342
+ }
343
+ continue
48
344
  }
49
345
 
50
- // Show metadata after selection
346
+ if (action === 'copilot') {
347
+ // Single agent — launch directly
348
+ const agent = agents[0] || { label: 'Copilot', startupCommand: 'copilot --agent terminal-agent' }
349
+ await launchAgent(agent)
350
+ continue
351
+ }
352
+
353
+ // Show metadata for non-agent actions (shell, sessions)
51
354
  const meta = [
52
355
  prettyName ? `${dim('name:')} ${blue(prettyName)}` : null,
53
356
  `${dim('branch:')} ${blue(branch)}`,
@@ -56,40 +359,69 @@ async function welcomeLoop() {
56
359
  p.log.info(meta)
57
360
 
58
361
  if (action === 'shell') {
59
- p.outro(dim('Opening shell...'))
60
- break
61
- }
62
-
63
- if (action === 'copilot') {
64
- p.outro(dim('Starting Copilot...'))
65
- // Run copilot as a child process, wait for it to exit, then loop back
66
- try {
67
- const child = spawn('copilot', [], { stdio: 'inherit' })
68
- await new Promise((resolve) => {
69
- child.on('close', resolve)
70
- child.on('error', resolve)
71
- })
72
- } catch {
73
- p.log.error('Failed to start Copilot. Is it installed?')
74
- await new Promise(r => setTimeout(r, 2000))
75
- }
76
- // Loop back to welcome prompt
362
+ p.outro(dim('Opening shell... Enter any command below.'))
363
+ setMouse(true)
364
+ // Spawn an interactive shell; when it exits, loop back to welcome
365
+ try { await spawnShell() } catch {}
77
366
  continue
78
367
  }
79
368
 
80
369
  if (action === 'sessions') {
81
- p.outro(dim('Loading sessions...'))
82
- try {
83
- const child = spawn('storyboard', ['terminal'], { stdio: 'inherit' })
84
- await new Promise((resolve) => {
85
- child.on('close', resolve)
86
- child.on('error', resolve)
87
- })
88
- } catch {
89
- p.log.error('Failed to load sessions.')
90
- await new Promise(r => setTimeout(r, 2000))
370
+ // Sub-menu: pick which agent's sessions to browse, or terminal sessions
371
+ const resumableAgents = agents.filter(a => a.resumeCommand)
372
+
373
+ const sessionOptions = [
374
+ ...resumableAgents.map(a => ({
375
+ value: `agent:${a.id}`,
376
+ label: `✦ ${a.label} sessions`,
377
+ })),
378
+ { value: 'terminal', label: '⊞ Terminal sessions' },
379
+ ]
380
+
381
+ const sessionChoice = await p.select({
382
+ message: 'Browse sessions',
383
+ options: sessionOptions,
384
+ })
385
+
386
+ if (p.isCancel(sessionChoice)) continue
387
+
388
+ if (sessionChoice === 'terminal') {
389
+ p.outro(dim('Loading terminal sessions...'))
390
+ try {
391
+ const child = spawn('storyboard', ['terminal'], { stdio: 'inherit' })
392
+ await new Promise((resolve) => {
393
+ child.on('close', resolve)
394
+ child.on('error', resolve)
395
+ })
396
+ } catch {
397
+ p.log.error('Failed to load sessions.')
398
+ await new Promise(r => setTimeout(r, 2000))
399
+ }
400
+ continue
91
401
  }
92
- // Loop back to welcome prompt
402
+
403
+ // Agent resume — spawn the resume command interactively
404
+ if (sessionChoice.startsWith('agent:')) {
405
+ const agentId = sessionChoice.replace('agent:', '')
406
+ const agent = resumableAgents.find(a => a.id === agentId)
407
+ if (agent) {
408
+ p.outro(dim(`Loading ${agent.label} sessions...`))
409
+ setMouse(true)
410
+ try {
411
+ const shell = process.env.SHELL || '/bin/zsh'
412
+ const child = spawn(shell, ['-lc', agent.resumeCommand], { stdio: 'inherit' })
413
+ await new Promise((resolve) => {
414
+ child.on('close', resolve)
415
+ child.on('error', resolve)
416
+ })
417
+ } catch {
418
+ p.log.error(`Failed to load ${agent.label} sessions.`)
419
+ await new Promise(r => setTimeout(r, 2000))
420
+ }
421
+ }
422
+ continue
423
+ }
424
+
93
425
  continue
94
426
  }
95
427
  }
@@ -194,6 +194,7 @@ export function getActionsForMode(mode) {
194
194
  url: a.url || null,
195
195
  toolKey: a.toolKey || null,
196
196
  localOnly: a.localOnly || false,
197
+ hideFromCommandPaletteSearch: a.hideFromCommandPaletteSearch || false,
197
198
  handler,
198
199
  active,
199
200
  }
@@ -3,6 +3,8 @@
3
3
  * Framework-agnostic (zero npm dependencies).
4
4
  */
5
5
 
6
+ import { getConfig } from './configStore.js'
7
+
6
8
  let _config = { sections: [] }
7
9
 
8
10
  /**
@@ -15,8 +17,15 @@ export function initCommandPaletteConfig(config) {
15
17
 
16
18
  /**
17
19
  * Get the current command palette config.
20
+ * Falls back to the unified config store if the legacy store wasn't initialized.
18
21
  * @returns {{ sections: Array }}
19
22
  */
20
23
  export function getCommandPaletteConfig() {
24
+ if (_config.sections.length === 0) {
25
+ const uc = getConfig('commandPalette')
26
+ if (uc?.sections?.length > 0) {
27
+ _config = { sections: [], ...uc }
28
+ }
29
+ }
21
30
  return _config
22
31
  }
@@ -73,7 +73,8 @@ export async function validateToken(token) {
73
73
  }
74
74
 
75
75
  const user = await res.json()
76
- const userInfo = { login: user.login, avatarUrl: user.avatar_url }
76
+ const scopes = (res.headers.get('x-oauth-scopes') || '').split(',').map(s => s.trim()).filter(Boolean)
77
+ const userInfo = { login: user.login, avatarUrl: user.avatar_url, scopes }
77
78
 
78
79
  // 2. Verify the token can access repository discussions
79
80
  await validateTokenPermissions(token)
@@ -0,0 +1,114 @@
1
+ /**
2
+ * AuthModal — PAT entry modal for comments authentication.
3
+ * Uses shadcn Button, Input, Label, Alert, Avatar.
4
+ */
5
+
6
+ import { useState, useEffect, useRef } from 'react'
7
+ import { setToken, validateToken } from '../auth.js'
8
+ import { getCommentsConfig } from '../config.js'
9
+ import { Button } from '../../lib/components/ui/button/index.js'
10
+ import { Input } from '../../lib/components/ui/input/index.js'
11
+ import { Label } from '../../lib/components/ui/label/index.js'
12
+ import * as Alert from '../../lib/components/ui/alert/index.js'
13
+ import * as Avatar from '../../lib/components/ui/avatar/index.js'
14
+
15
+ export default function AuthModal({ onDone, onClose, initialError = null }) {
16
+ const [token, setTokenValue] = useState('')
17
+ const [submitting, setSubmitting] = useState(false)
18
+ const [error, setError] = useState(null)
19
+ const [user, setUser] = useState(null)
20
+ const inputRef = useRef(null)
21
+
22
+ const commentsConfig = getCommentsConfig()
23
+ const repoOwner = commentsConfig?.repo?.owner || 'github'
24
+ const repoName = commentsConfig?.repo?.name || 'storyboard'
25
+ const repoSlug = `${repoOwner}/${repoName}`
26
+ const tokenTemplateName = 'Storyboard Comments'
27
+ const tokenTemplateDescription =
28
+ `Token for enabling comments on ${repoSlug} prototype. Configure as:\n\n` +
29
+ `Owner: ${repoOwner}\n` +
30
+ 'Expiration: 366 days (recommended)\n' +
31
+ `Repository access: Only select repositories > ${repoSlug}\n` +
32
+ 'Permissions: Repositories > Discussions > Access: Read and Write'
33
+ const tokenCreateUrl =
34
+ `https://github.com/settings/personal-access-tokens/new?` +
35
+ new URLSearchParams({
36
+ name: tokenTemplateName,
37
+ description: tokenTemplateDescription,
38
+ }).toString()
39
+
40
+ useEffect(() => {
41
+ setError(initialError)
42
+ inputRef.current?.focus()
43
+ }, [])
44
+
45
+ async function submit() {
46
+ const val = token.trim()
47
+ if (!val) return
48
+ setSubmitting(true); setError(null)
49
+ try { const result = await validateToken(val); setToken(val); setUser(result) }
50
+ catch (err) { setError(err.message) }
51
+ finally { setSubmitting(false) }
52
+ }
53
+
54
+ function done() { if (user) onDone?.(user) }
55
+
56
+ function handleKeydown(e) {
57
+ if (e.key === 'Enter' && !user) submit()
58
+ }
59
+
60
+ return (
61
+ <div className="bg-popover text-popover-foreground border border-border rounded-lg shadow-lg overflow-hidden max-w-[600px] w-full font-sans">
62
+ <div className="flex items-center justify-between px-4 py-3 border-b border-border">
63
+ <h2 className="text-medium font-semibold">Sign in for comments</h2>
64
+ <Button variant="ghost" size="icon" onClick={onClose} aria-label="Close" className="h-7 w-7 text-muted-foreground">&#215;</Button>
65
+ </div>
66
+ <div className="p-4 space-y-3">
67
+ {error && <Alert.Root variant="destructive"><Alert.Description>{error}</Alert.Description></Alert.Root>}
68
+ <p className="text-sm text-muted-foreground leading-relaxed">
69
+ Leave comments for other users to see and respond, and react to! Storyboard comments use Discussions as a back-end and require a GitHub PAT to be enabled.
70
+ </p>
71
+ <p className="text-sm text-muted-foreground leading-relaxed">
72
+ Create a <a className="text-primary underline" href={tokenCreateUrl} target="_blank" rel="noopener">GitHub Fine-Grained Personal Access Token</a> with the settings below to get started:
73
+ </p>
74
+ <div className="px-3 py-2 bg-muted border border-border rounded text-xs text-muted-foreground leading-relaxed">
75
+ <div className="mb-1"><strong className="text-foreground">Fine-grained Personal Access Token</strong></div>
76
+ <div>Owner: <code className="px-1 bg-background rounded font-mono text-foreground">{repoOwner}</code></div>
77
+ <div>Expiration: <code className="px-1 bg-background rounded font-mono text-foreground">366 days</code> (recommended)</div>
78
+ <div>Repository access: <code className="px-1 bg-background rounded font-mono text-foreground">Only select repositories &gt; {repoSlug}</code></div>
79
+ <div>Permissions: <code className="px-1 bg-background rounded font-mono text-foreground">Repositories &gt; Discussions &gt; Access: Read and Write</code></div>
80
+ </div>
81
+ <div className="space-y-1">
82
+ <Label htmlFor="sb-auth-token-input">Personal Access Token</Label>
83
+ <Input
84
+ id="sb-auth-token-input"
85
+ type="password"
86
+ placeholder="github_pat_… or ghp_…"
87
+ autoComplete="off"
88
+ spellCheck={false}
89
+ className="font-mono"
90
+ value={token}
91
+ onChange={(e) => setTokenValue(e.target.value)}
92
+ ref={inputRef}
93
+ onKeyDown={handleKeydown}
94
+ />
95
+ </div>
96
+ {user && (
97
+ <div className="flex items-center py-1 gap-3">
98
+ <Avatar.Root className="h-10 w-10"><Avatar.Image src={user.avatarUrl} alt={user.login} /><Avatar.Fallback>{user.login[0]?.toUpperCase()}</Avatar.Fallback></Avatar.Root>
99
+ <div className="text-sm"><span className="text-foreground">{user.login}</span><span className="block text-xs text-success mt-0.5">&#10003; Signed in</span></div>
100
+ </div>
101
+ )}
102
+ <Alert.Root variant="warning" className="bg-amber-100 border-amber-300">
103
+ <Alert.Description className="text-amber-700">
104
+ ⚠️ Comments are an experimental feature and may be unstable.
105
+ </Alert.Description>
106
+ </Alert.Root>
107
+ </div>
108
+ <div className="flex items-center justify-end px-4 py-3 border-t border-border gap-2">
109
+ <Button variant="outline" size="sm" onClick={onClose}>Cancel</Button>
110
+ <Button size="sm" disabled={submitting} onClick={user ? done : submit}>{user ? 'Done' : (submitting ? 'Validating\u2026' : 'Sign in')}</Button>
111
+ </div>
112
+ </div>
113
+ )
114
+ }