@jetcrab/pi-desk 1.1.12 → 1.1.16

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 (340) hide show
  1. package/docs/plugins.md +21 -1
  2. package/package.json +2 -2
  3. package/src/app/api/model-settings/preview/route.ts +1 -0
  4. package/src/app/api/work-sessions/rename/route.ts +1 -0
  5. package/src/client/l2_biz/auth/l2-login.tsx +1 -1
  6. package/src/client/l2_biz/plugin-host/l2-plugin-session-sidebar-tab.tsx +6 -2
  7. package/src/client/l2_biz/settings/hooks/l2-use-model-provider-settings.ts +54 -10
  8. package/src/client/l2_biz/settings/hooks/l2-use-model-settings.ts +37 -9
  9. package/src/client/l2_biz/settings/l2-auth-settings.tsx +1 -1
  10. package/src/client/l2_biz/settings/l2-model-settings-biz.ts +26 -12
  11. package/src/client/l2_biz/settings/views/l2-appearance-settings.tsx +1 -16
  12. package/src/client/l2_biz/settings/views/l2-model-provider-settings.tsx +3 -2
  13. package/src/client/l2_biz/settings/views/l2-model-replacement-preview.tsx +34 -0
  14. package/src/client/l2_biz/task-center/l2-task-center.tsx +4 -30
  15. package/src/client/l2_biz/workbench/file-workspace/l2-plugin-standalone-file-preview.tsx +45 -7
  16. package/src/client/l2_biz/workbench/hooks/l2-work-session-rename.ts +57 -0
  17. package/src/client/l2_biz/workbench/l2-work-session-columns.tsx +0 -11
  18. package/src/client/l2_biz/workbench/l2-work-session-sidebar.tsx +107 -6
  19. package/src/client/l2_biz/workbench/l2-workbench-biz.ts +5 -0
  20. package/src/client/l2_biz/workbench/l2-workbench-chat-composer.tsx +333 -350
  21. package/src/client/l2_biz/workbench/l2-workbench.tsx +46 -1
  22. package/src/client/l2_biz/workbench/views/l2-work-session-rename-dialog.tsx +88 -0
  23. package/src/client/l3_modules/project-files/l3-markdown-preview.module.css +81 -0
  24. package/src/client/l3_modules/project-files/l3-markdown-preview.tsx +52 -0
  25. package/src/client/l3_modules/project-files/l3-project-document-view.tsx +26 -8
  26. package/src/client/l3_modules/project-files/l3-project-file-runtime.ts +16 -1
  27. package/src/client/l3_modules/project-files/l3-project-text-preview.ts +5 -0
  28. package/src/client/l3_modules/work-session-visual/l3-work-session-visual-effects.module.css +0 -36
  29. package/src/client/l3_modules/work-session-visual/l3-work-session-visual-view.tsx +0 -5
  30. package/src/client/l4_foundation/plugin-host/l4-plugin-host-runtime.ts +71 -1
  31. package/src/client/l4_foundation/styles/l4-globals.css +0 -19
  32. package/src/client/l4_foundation/ui/code/l4-code-preview.tsx +2 -1
  33. package/src/client/l4_foundation/ui/l4-confirm-dialog.tsx +9 -1
  34. package/src/common/l2_biz/auth/l2-auth-contract.ts +2 -2
  35. package/src/common/l2_biz/auth/l2-auth-messages.ts +2 -2
  36. package/src/common/l2_biz/model-settings/l2-model-settings-contract.ts +23 -1
  37. package/src/common/l2_biz/settings/l2-settings-messages.ts +8 -6
  38. package/src/common/l2_biz/work-session/l2-work-session-contract.ts +9 -0
  39. package/src/common/l2_biz/workbench/l2-workbench-locale-messages.ts +6 -0
  40. package/src/common/l3_modules/project-files/l3-project-files-locale-messages.ts +4 -0
  41. package/src/common/l4_foundation/locale/l4-host-error-messages.ts +6 -0
  42. package/src/server/l1_entry/api/l1-model-settings-preview-route.ts +32 -0
  43. package/src/server/l1_entry/api/l1-work-session-rename-route.ts +52 -0
  44. package/src/server/l2_biz/model-settings/l2-model-settings.ts +9 -0
  45. package/src/server/l2_biz/plugin-management/l2-plugin-management.ts +159 -52
  46. package/src/server/l2_biz/work-session/l2-work-session-chat-runtime.ts +5 -0
  47. package/src/server/l2_biz/work-session/l2-work-session-manage.ts +13 -0
  48. package/src/server/l3_modules/work-session/l3-work-session.ts +4 -0
  49. package/src/server/l4_foundation/model-settings/l4-model-settings-store.ts +161 -38
  50. package/src/server/l4_foundation/model-settings/l4-model-settings-types.ts +11 -0
  51. package/src/server/l4_foundation/model-settings/l4-model-settings.ts +1 -0
  52. package/src/server/l4_foundation/pi/l4-pi-chat-worker.ts +12 -1
  53. package/src/server/l4_foundation/pi/l4-pi-package-maintenance-runner.mts +56 -65
  54. package/src/server/l4_foundation/pi/l4-pi-package-maintenance.ts +2 -0
  55. package/src/server/l4_foundation/pi/l4-pi-package-reinstall-runner.mts +49 -0
  56. package/src/server/l4_foundation/pi/l4-pi-package-root-consistency.ts +6 -2
  57. package/src/server/l4_foundation/pi/l4-pi-plugin-probe.ts +3 -1
  58. package/src/server/l4_foundation/pi/l4-pi-runner-process.ts +9 -0
  59. package/src/server/l4_foundation/pi/l4-pi-work-session-runtime.ts +5 -0
  60. package/temp/build/pi-desk/release/.next/BUILD_ID +1 -1
  61. package/temp/build/pi-desk/release/.next/app-path-routes-manifest.json +2 -0
  62. package/temp/build/pi-desk/release/.next/build-manifest.json +3 -3
  63. package/temp/build/pi-desk/release/.next/prerender-manifest.json +3 -3
  64. package/temp/build/pi-desk/release/.next/react-loadable-manifest.json +1 -2
  65. package/temp/build/pi-desk/release/.next/required-server-files.js +2 -2
  66. package/temp/build/pi-desk/release/.next/required-server-files.json +2 -2
  67. package/temp/build/pi-desk/release/.next/routes-manifest.json +12 -0
  68. package/temp/build/pi-desk/release/.next/server/app/_global-error/page.js +1 -1
  69. package/temp/build/pi-desk/release/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  70. package/temp/build/pi-desk/release/.next/server/app/_global-error.html +1 -1
  71. package/temp/build/pi-desk/release/.next/server/app/_global-error.rsc +1 -1
  72. package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  73. package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  74. package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  75. package/temp/build/pi-desk/release/.next/server/app/_not-found/page.js +1 -1
  76. package/temp/build/pi-desk/release/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  77. package/temp/build/pi-desk/release/.next/server/app/api/auth/login/route.js +2 -2
  78. package/temp/build/pi-desk/release/.next/server/app/api/auth/logout/route.js +1 -1
  79. package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/get/route.js +1 -1
  80. package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/replace/route.js +1 -1
  81. package/temp/build/pi-desk/release/.next/server/app/api/capability-modes/get/route.js +1 -1
  82. package/temp/build/pi-desk/release/.next/server/app/api/capability-modes/replace/route.js +1 -1
  83. package/temp/build/pi-desk/release/.next/server/app/api/chat/context/get/route.js +1 -1
  84. package/temp/build/pi-desk/release/.next/server/app/api/chat/images/get/route.js +1 -1
  85. package/temp/build/pi-desk/release/.next/server/app/api/chat/messages/get/route.js +1 -1
  86. package/temp/build/pi-desk/release/.next/server/app/api/health/route.js +1 -1
  87. package/temp/build/pi-desk/release/.next/server/app/api/mcp-check/get/route.js +1 -1
  88. package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/del/route.js +1 -1
  89. package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/get/route.js +1 -1
  90. package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/replace/route.js +1 -1
  91. package/temp/build/pi-desk/release/.next/server/app/api/model-catalog/list/route.js +1 -1
  92. package/temp/build/pi-desk/release/.next/server/app/api/model-settings/get/route.js +1 -1
  93. package/temp/build/pi-desk/release/.next/server/app/api/model-settings/preview/route.js +1 -0
  94. package/temp/build/pi-desk/release/.next/server/app/api/model-settings/preview/route_client-reference-manifest.js +1 -0
  95. package/temp/build/pi-desk/release/.next/server/app/api/model-settings/replace/route.js +1 -1
  96. package/temp/build/pi-desk/release/.next/server/app/api/pi/directories/list/route.js +1 -1
  97. package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-entries/list/route.js +1 -1
  98. package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-ignores/list/route.js +1 -1
  99. package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-ignores/replace/route.js +1 -1
  100. package/temp/build/pi-desk/release/.next/server/app/api/pi/models/list/route.js +1 -1
  101. package/temp/build/pi-desk/release/.next/server/app/api/pi/session-user-messages/list/route.js +1 -1
  102. package/temp/build/pi-desk/release/.next/server/app/api/pi/sessions/list/route.js +1 -1
  103. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/get/route.js +1 -1
  104. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/search/route.js +1 -1
  105. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/settings-get/route.js +1 -1
  106. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/settings-replace/route.js +1 -1
  107. package/temp/build/pi-desk/release/.next/server/app/api/plugins/add/route.js +1 -1
  108. package/temp/build/pi-desk/release/.next/server/app/api/plugins/apply/route.js +1 -1
  109. package/temp/build/pi-desk/release/.next/server/app/api/plugins/batch/route.js +1 -1
  110. package/temp/build/pi-desk/release/.next/server/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route.js +1 -1
  111. package/temp/build/pi-desk/release/.next/server/app/api/plugins/del/route.js +1 -1
  112. package/temp/build/pi-desk/release/.next/server/app/api/plugins/enabled-set/route.js +1 -1
  113. package/temp/build/pi-desk/release/.next/server/app/api/plugins/get/route.js +1 -1
  114. package/temp/build/pi-desk/release/.next/server/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route.js +1 -1
  115. package/temp/build/pi-desk/release/.next/server/app/api/plugins/list/route.js +1 -1
  116. package/temp/build/pi-desk/release/.next/server/app/api/plugins/reload/route.js +1 -1
  117. package/temp/build/pi-desk/release/.next/server/app/api/plugins/update/route.js +1 -1
  118. package/temp/build/pi-desk/release/.next/server/app/api/project-files/get/route.js +1 -1
  119. package/temp/build/pi-desk/release/.next/server/app/api/project-files/list/route.js +1 -1
  120. package/temp/build/pi-desk/release/.next/server/app/api/project-files/reveal/route.js +1 -1
  121. package/temp/build/pi-desk/release/.next/server/app/api/project-files/search/route.js +1 -1
  122. package/temp/build/pi-desk/release/.next/server/app/api/project-git/get/route.js +1 -1
  123. package/temp/build/pi-desk/release/.next/server/app/api/project-git-branches/list/route.js +1 -1
  124. package/temp/build/pi-desk/release/.next/server/app/api/project-git-changes/list/route.js +1 -1
  125. package/temp/build/pi-desk/release/.next/server/app/api/project-git-diff/get/route.js +1 -1
  126. package/temp/build/pi-desk/release/.next/server/app/api/project-git-heads/get/route.js +1 -1
  127. package/temp/build/pi-desk/release/.next/server/app/api/project-git-log/list/route.js +1 -1
  128. package/temp/build/pi-desk/release/.next/server/app/api/project-model-default/get/route.js +1 -1
  129. package/temp/build/pi-desk/release/.next/server/app/api/project-model-default/replace/route.js +1 -1
  130. package/temp/build/pi-desk/release/.next/server/app/api/skill-files/get/route.js +1 -1
  131. package/temp/build/pi-desk/release/.next/server/app/api/skill-files/list/route.js +1 -1
  132. package/temp/build/pi-desk/release/.next/server/app/api/skill-files/replace/route.js +1 -1
  133. package/temp/build/pi-desk/release/.next/server/app/api/skills/list/route.js +1 -1
  134. package/temp/build/pi-desk/release/.next/server/app/api/task-center/images/get/route.js +1 -1
  135. package/temp/build/pi-desk/release/.next/server/app/api/task-center/messages/get/route.js +1 -1
  136. package/temp/build/pi-desk/release/.next/server/app/api/work-session-git-branch/add/route.js +1 -1
  137. package/temp/build/pi-desk/release/.next/server/app/api/work-session-git-branch/replace/route.js +1 -1
  138. package/temp/build/pi-desk/release/.next/server/app/api/work-session-tree/get/route.js +1 -1
  139. package/temp/build/pi-desk/release/.next/server/app/api/work-session-tree-entry/get/route.js +1 -1
  140. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/add/route.js +1 -1
  141. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/branch/route.js +1 -1
  142. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/del/route.js +1 -1
  143. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/rename/route.js +1 -0
  144. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/rename/route_client-reference-manifest.js +1 -0
  145. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/replace/route.js +1 -1
  146. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/sort/route.js +1 -1
  147. package/temp/build/pi-desk/release/.next/server/app/favicon.ico/route.js +1 -1
  148. package/temp/build/pi-desk/release/.next/server/app/login/page.js +1 -1
  149. package/temp/build/pi-desk/release/.next/server/app/login/page_client-reference-manifest.js +1 -1
  150. package/temp/build/pi-desk/release/.next/server/app/page.js +72 -306
  151. package/temp/build/pi-desk/release/.next/server/app/page_client-reference-manifest.js +1 -1
  152. package/temp/build/pi-desk/release/.next/server/app-paths-manifest.json +2 -0
  153. package/temp/build/pi-desk/release/.next/server/chunks/23054.js +1 -1
  154. package/temp/build/pi-desk/release/.next/server/chunks/25406.js +8 -8
  155. package/temp/build/pi-desk/release/.next/server/chunks/33658.js +296 -0
  156. package/temp/build/pi-desk/release/.next/server/chunks/35985.js +5 -5
  157. package/temp/build/pi-desk/release/.next/server/chunks/48180.js +1 -1
  158. package/temp/build/pi-desk/release/.next/server/chunks/49900.js +2 -2
  159. package/temp/build/pi-desk/release/.next/server/chunks/50520.js +5 -5
  160. package/temp/build/pi-desk/release/.next/server/chunks/6917.js +1 -1
  161. package/temp/build/pi-desk/release/.next/server/chunks/78262.js +3 -3
  162. package/temp/build/pi-desk/release/.next/server/chunks/82499.js +6 -6
  163. package/temp/build/pi-desk/release/.next/server/chunks/92386.js +3 -3
  164. package/temp/build/pi-desk/release/.next/server/chunks/94296.js +2 -2
  165. package/temp/build/pi-desk/release/.next/server/middleware-build-manifest.js +1 -1
  166. package/temp/build/pi-desk/release/.next/server/middleware-react-loadable-manifest.js +1 -1
  167. package/temp/build/pi-desk/release/.next/server/pages/500.html +1 -1
  168. package/temp/build/pi-desk/release/.next/server/server-reference-manifest.json +1 -1
  169. package/temp/build/pi-desk/release/.next/static/DqamF28k0ShQLbNVzXDIj/_buildManifest.js +1 -0
  170. package/temp/build/pi-desk/release/.next/static/chunks/31087-ba426d09d6f68bfd.js +1 -0
  171. package/temp/build/pi-desk/release/.next/static/chunks/39654-b5fedd762ea0312e.js +238 -0
  172. package/temp/build/pi-desk/release/.next/static/chunks/49516-cc4dcd84d64ab4fe.js +81 -0
  173. package/temp/build/pi-desk/release/.next/static/chunks/75130-d2ca74894aff8085.js +13 -0
  174. package/temp/build/pi-desk/release/.next/static/chunks/app/_global-error/page-9969fe0baa238786.js +1 -0
  175. package/temp/build/pi-desk/release/.next/static/chunks/app/_not-found/page-9969fe0baa238786.js +1 -0
  176. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/login/route-9969fe0baa238786.js +1 -0
  177. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/logout/route-9969fe0baa238786.js +1 -0
  178. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/get/route-9969fe0baa238786.js +1 -0
  179. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/replace/route-9969fe0baa238786.js +1 -0
  180. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/get/route-9969fe0baa238786.js +1 -0
  181. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/replace/route-9969fe0baa238786.js +1 -0
  182. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/context/get/route-9969fe0baa238786.js +1 -0
  183. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/images/get/route-9969fe0baa238786.js +1 -0
  184. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/messages/get/route-9969fe0baa238786.js +1 -0
  185. package/temp/build/pi-desk/release/.next/static/chunks/app/api/health/route-9969fe0baa238786.js +1 -0
  186. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-check/get/route-9969fe0baa238786.js +1 -0
  187. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/del/route-9969fe0baa238786.js +1 -0
  188. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/get/route-9969fe0baa238786.js +1 -0
  189. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/replace/route-9969fe0baa238786.js +1 -0
  190. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-catalog/list/route-9969fe0baa238786.js +1 -0
  191. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/get/route-9969fe0baa238786.js +1 -0
  192. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/preview/route-9969fe0baa238786.js +1 -0
  193. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/replace/route-9969fe0baa238786.js +1 -0
  194. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directories/list/route-9969fe0baa238786.js +1 -0
  195. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-entries/list/route-9969fe0baa238786.js +1 -0
  196. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/list/route-9969fe0baa238786.js +1 -0
  197. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/replace/route-9969fe0baa238786.js +1 -0
  198. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/models/list/route-9969fe0baa238786.js +1 -0
  199. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/session-user-messages/list/route-9969fe0baa238786.js +1 -0
  200. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/sessions/list/route-9969fe0baa238786.js +1 -0
  201. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/get/route-9969fe0baa238786.js +1 -0
  202. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/search/route-9969fe0baa238786.js +1 -0
  203. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-get/route-9969fe0baa238786.js +1 -0
  204. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-replace/route-9969fe0baa238786.js +1 -0
  205. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/add/route-9969fe0baa238786.js +1 -0
  206. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/apply/route-9969fe0baa238786.js +1 -0
  207. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/batch/route-9969fe0baa238786.js +1 -0
  208. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route-9969fe0baa238786.js +1 -0
  209. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/del/route-9969fe0baa238786.js +1 -0
  210. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/enabled-set/route-9969fe0baa238786.js +1 -0
  211. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/get/route-9969fe0baa238786.js +1 -0
  212. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route-9969fe0baa238786.js +1 -0
  213. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/list/route-9969fe0baa238786.js +1 -0
  214. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/reload/route-9969fe0baa238786.js +1 -0
  215. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/update/route-9969fe0baa238786.js +1 -0
  216. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/get/route-9969fe0baa238786.js +1 -0
  217. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/list/route-9969fe0baa238786.js +1 -0
  218. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/reveal/route-9969fe0baa238786.js +1 -0
  219. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/search/route-9969fe0baa238786.js +1 -0
  220. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git/get/route-9969fe0baa238786.js +1 -0
  221. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-branches/list/route-9969fe0baa238786.js +1 -0
  222. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-changes/list/route-9969fe0baa238786.js +1 -0
  223. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-diff/get/route-9969fe0baa238786.js +1 -0
  224. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-heads/get/route-9969fe0baa238786.js +1 -0
  225. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-log/list/route-9969fe0baa238786.js +1 -0
  226. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/get/route-9969fe0baa238786.js +1 -0
  227. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/replace/route-9969fe0baa238786.js +1 -0
  228. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/get/route-9969fe0baa238786.js +1 -0
  229. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/list/route-9969fe0baa238786.js +1 -0
  230. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/replace/route-9969fe0baa238786.js +1 -0
  231. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skills/list/route-9969fe0baa238786.js +1 -0
  232. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/images/get/route-9969fe0baa238786.js +1 -0
  233. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/messages/get/route-9969fe0baa238786.js +1 -0
  234. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/add/route-9969fe0baa238786.js +1 -0
  235. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/replace/route-9969fe0baa238786.js +1 -0
  236. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree/get/route-9969fe0baa238786.js +1 -0
  237. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree-entry/get/route-9969fe0baa238786.js +1 -0
  238. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/add/route-9969fe0baa238786.js +1 -0
  239. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/branch/route-9969fe0baa238786.js +1 -0
  240. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/del/route-9969fe0baa238786.js +1 -0
  241. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/rename/route-9969fe0baa238786.js +1 -0
  242. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/replace/route-9969fe0baa238786.js +1 -0
  243. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/sort/route-9969fe0baa238786.js +1 -0
  244. package/temp/build/pi-desk/release/.next/static/chunks/app/layout-c0e1c5cef8620cf8.js +3 -0
  245. package/temp/build/pi-desk/release/.next/static/chunks/app/login/page-84892b06243891f0.js +1 -0
  246. package/temp/build/pi-desk/release/.next/static/chunks/app/page-0069319a4fb97211.js +158 -0
  247. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/app-error-9969fe0baa238786.js +1 -0
  248. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/forbidden-9969fe0baa238786.js +1 -0
  249. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/unauthorized-9969fe0baa238786.js +1 -0
  250. package/temp/build/pi-desk/release/.next/static/chunks/webpack-40a782fc8a3535b9.js +1 -0
  251. package/temp/build/pi-desk/release/.next/static/css/6427d02b6edf406f.css +1 -0
  252. package/temp/build/pi-desk/release/.next/static/css/{adb1d4e48dd43c0a.css → 949d0d1a99d5de92.css} +1 -1
  253. package/temp/build/pi-desk/release/.next/trace-build +1 -1
  254. package/src/client/l2_biz/workbench/hooks/l2-work-session-column-motion.ts +0 -87
  255. package/src/client/l3_modules/work-session-visual/l3-work-session-status-border.tsx +0 -66
  256. package/src/client/l4_foundation/ui/l4-power-saving.ts +0 -45
  257. package/src/client/l4_foundation/ui/l4-window-reveal.ts +0 -30
  258. package/temp/build/pi-desk/release/.next/server/chunks/56284.js +0 -62
  259. package/temp/build/pi-desk/release/.next/static/96geGVI-j_dC6I3k-XFCB/_buildManifest.js +0 -1
  260. package/temp/build/pi-desk/release/.next/static/chunks/31087-333cae396a52f232.js +0 -1
  261. package/temp/build/pi-desk/release/.next/static/chunks/45992-92d8b8b10fcfbb6b.js +0 -13
  262. package/temp/build/pi-desk/release/.next/static/chunks/47340-c1c09c77c1a88514.js +0 -318
  263. package/temp/build/pi-desk/release/.next/static/chunks/57208-d6d38167dabb91e4.js +0 -1
  264. package/temp/build/pi-desk/release/.next/static/chunks/app/_global-error/page-dde4fd973791f7f7.js +0 -1
  265. package/temp/build/pi-desk/release/.next/static/chunks/app/_not-found/page-dde4fd973791f7f7.js +0 -1
  266. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/login/route-dde4fd973791f7f7.js +0 -1
  267. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/logout/route-dde4fd973791f7f7.js +0 -1
  268. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/get/route-dde4fd973791f7f7.js +0 -1
  269. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/replace/route-dde4fd973791f7f7.js +0 -1
  270. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/get/route-dde4fd973791f7f7.js +0 -1
  271. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/replace/route-dde4fd973791f7f7.js +0 -1
  272. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/context/get/route-dde4fd973791f7f7.js +0 -1
  273. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/images/get/route-dde4fd973791f7f7.js +0 -1
  274. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/messages/get/route-dde4fd973791f7f7.js +0 -1
  275. package/temp/build/pi-desk/release/.next/static/chunks/app/api/health/route-dde4fd973791f7f7.js +0 -1
  276. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-check/get/route-dde4fd973791f7f7.js +0 -1
  277. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/del/route-dde4fd973791f7f7.js +0 -1
  278. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/get/route-dde4fd973791f7f7.js +0 -1
  279. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/replace/route-dde4fd973791f7f7.js +0 -1
  280. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-catalog/list/route-dde4fd973791f7f7.js +0 -1
  281. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/get/route-dde4fd973791f7f7.js +0 -1
  282. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/replace/route-dde4fd973791f7f7.js +0 -1
  283. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directories/list/route-dde4fd973791f7f7.js +0 -1
  284. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-entries/list/route-dde4fd973791f7f7.js +0 -1
  285. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/list/route-dde4fd973791f7f7.js +0 -1
  286. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/replace/route-dde4fd973791f7f7.js +0 -1
  287. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/models/list/route-dde4fd973791f7f7.js +0 -1
  288. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/session-user-messages/list/route-dde4fd973791f7f7.js +0 -1
  289. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/sessions/list/route-dde4fd973791f7f7.js +0 -1
  290. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/get/route-dde4fd973791f7f7.js +0 -1
  291. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/search/route-dde4fd973791f7f7.js +0 -1
  292. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-get/route-dde4fd973791f7f7.js +0 -1
  293. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-replace/route-dde4fd973791f7f7.js +0 -1
  294. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/add/route-dde4fd973791f7f7.js +0 -1
  295. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/apply/route-dde4fd973791f7f7.js +0 -1
  296. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/batch/route-dde4fd973791f7f7.js +0 -1
  297. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route-dde4fd973791f7f7.js +0 -1
  298. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/del/route-dde4fd973791f7f7.js +0 -1
  299. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/enabled-set/route-dde4fd973791f7f7.js +0 -1
  300. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/get/route-dde4fd973791f7f7.js +0 -1
  301. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route-dde4fd973791f7f7.js +0 -1
  302. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/list/route-dde4fd973791f7f7.js +0 -1
  303. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/reload/route-dde4fd973791f7f7.js +0 -1
  304. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/update/route-dde4fd973791f7f7.js +0 -1
  305. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/get/route-dde4fd973791f7f7.js +0 -1
  306. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/list/route-dde4fd973791f7f7.js +0 -1
  307. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/reveal/route-dde4fd973791f7f7.js +0 -1
  308. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/search/route-dde4fd973791f7f7.js +0 -1
  309. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git/get/route-dde4fd973791f7f7.js +0 -1
  310. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-branches/list/route-dde4fd973791f7f7.js +0 -1
  311. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-changes/list/route-dde4fd973791f7f7.js +0 -1
  312. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-diff/get/route-dde4fd973791f7f7.js +0 -1
  313. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-heads/get/route-dde4fd973791f7f7.js +0 -1
  314. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-log/list/route-dde4fd973791f7f7.js +0 -1
  315. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/get/route-dde4fd973791f7f7.js +0 -1
  316. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/replace/route-dde4fd973791f7f7.js +0 -1
  317. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/get/route-dde4fd973791f7f7.js +0 -1
  318. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/list/route-dde4fd973791f7f7.js +0 -1
  319. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/replace/route-dde4fd973791f7f7.js +0 -1
  320. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skills/list/route-dde4fd973791f7f7.js +0 -1
  321. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/images/get/route-dde4fd973791f7f7.js +0 -1
  322. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/messages/get/route-dde4fd973791f7f7.js +0 -1
  323. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/add/route-dde4fd973791f7f7.js +0 -1
  324. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/replace/route-dde4fd973791f7f7.js +0 -1
  325. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree/get/route-dde4fd973791f7f7.js +0 -1
  326. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree-entry/get/route-dde4fd973791f7f7.js +0 -1
  327. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/add/route-dde4fd973791f7f7.js +0 -1
  328. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/branch/route-dde4fd973791f7f7.js +0 -1
  329. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/del/route-dde4fd973791f7f7.js +0 -1
  330. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/replace/route-dde4fd973791f7f7.js +0 -1
  331. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/sort/route-dde4fd973791f7f7.js +0 -1
  332. package/temp/build/pi-desk/release/.next/static/chunks/app/layout-839162b6cfae8347.js +0 -3
  333. package/temp/build/pi-desk/release/.next/static/chunks/app/login/page-4532a3bbee48e219.js +0 -1
  334. package/temp/build/pi-desk/release/.next/static/chunks/app/page-4b6367cde5c04597.js +0 -158
  335. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/app-error-dde4fd973791f7f7.js +0 -1
  336. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/forbidden-dde4fd973791f7f7.js +0 -1
  337. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/unauthorized-dde4fd973791f7f7.js +0 -1
  338. package/temp/build/pi-desk/release/.next/static/chunks/webpack-735430d61da52e9d.js +0 -1
  339. package/temp/build/pi-desk/release/.next/static/css/4a5dda7ff3a82c4a.css +0 -1
  340. /package/temp/build/pi-desk/release/.next/static/{96geGVI-j_dC6I3k-XFCB → DqamF28k0ShQLbNVzXDIj}/_ssgManifest.js +0 -0
@@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next'
16
16
  import type {
17
17
  BrowserFilePreviewMode,
18
18
  BrowserFilePreviewOptions,
19
+ BrowserSessionSidebarHeaderAction,
19
20
  PluginSource
20
21
  } from '@jetcrab/pi-desk-sdk/browser'
21
22
  import {
@@ -110,6 +111,8 @@ import {
110
111
  type L2WorkSessionArrangement
111
112
  } from './l2-work-session-sidebar-order'
112
113
  import { useL2WorkbenchBranchPicker } from './hooks/l2-workbench-branch-picker'
114
+ import { useL2WorkSessionRename } from './hooks/l2-work-session-rename'
115
+ import { L2WorkSessionRenameDialog } from './views/l2-work-session-rename-dialog'
113
116
  import { useL2WorkbenchPluginHealth } from './hooks/l2-workbench-plugin-health'
114
117
  import { useL2WorkbenchSessionHistory } from './hooks/l2-workbench-session-history'
115
118
  import {
@@ -194,6 +197,7 @@ interface L2WorkbenchProps extends L2WorkbenchComposerSlots {
194
197
  cwd: string
195
198
  onPreviewFile: (path: string, options?: BrowserFilePreviewOptions) => void
196
199
  onRevealFile: (path: string) => Promise<void>
200
+ onHeaderActionsChange: (actions: readonly BrowserSessionSidebarHeaderAction[]) => void
197
201
  }) => ReactNode
198
202
  renderSettings: (input: {
199
203
  open: boolean
@@ -298,6 +302,10 @@ export function L2Workbench({
298
302
  setMobileDrawerOpen(false)
299
303
  }, [])
300
304
  const [sidebarMode, setSidebarMode] = useState<L2WorkSessionSidebarMode>('sessions')
305
+ const [pluginHeaderActions, setPluginHeaderActions] = useState<{
306
+ targetKey: string
307
+ actions: readonly BrowserSessionSidebarHeaderAction[]
308
+ } | null>(null)
301
309
  const [fileBrowserMounted, setFileBrowserMounted] = useState(false)
302
310
  const [settingsOpen, setSettingsOpen] = useState(false)
303
311
  const [settingsInitialPage, setSettingsInitialPage] = useState<'model-presets' | undefined>()
@@ -317,6 +325,7 @@ export function L2Workbench({
317
325
  }, [])
318
326
  const [loadPhase, setLoadPhase] = useState<'initial' | 'refresh' | 'ready'>('initial')
319
327
  const loading = loadPhase !== 'ready'
328
+ const renameSession = useL2WorkSessionRename(workbenchBiz, loading)
320
329
  const [ordering, setOrdering] = useState(false)
321
330
  const [deletingWorkId, setDeletingWorkId] = useState<string | null>(null)
322
331
  const [directoryDialogOpen, setDirectoryDialogOpen] = useState(false)
@@ -472,6 +481,25 @@ export function L2Workbench({
472
481
  branchId: activePluginBranchId
473
482
  }
474
483
  : null
484
+ const pluginSidebarTargetKey = JSON.stringify([
485
+ sidebarMode,
486
+ activePluginWorkId,
487
+ activePluginSessionId,
488
+ activePluginBranchId,
489
+ activeCwd
490
+ ])
491
+ const updatePluginHeaderActions = useCallback(
492
+ (actions: readonly BrowserSessionSidebarHeaderAction[]): void => {
493
+ setPluginHeaderActions((current) =>
494
+ actions.length > 0
495
+ ? { targetKey: pluginSidebarTargetKey, actions }
496
+ : current?.targetKey === pluginSidebarTargetKey
497
+ ? null
498
+ : current
499
+ )
500
+ },
501
+ [pluginSidebarTargetKey]
502
+ )
475
503
  const activeFileWorkspace = fileRuntime.getWorkspace(activeWorkId)
476
504
 
477
505
  useEffect(() => {
@@ -1848,7 +1876,8 @@ export function L2Workbench({
1848
1876
  source: activePluginSource,
1849
1877
  cwd: activeWorkSession.cwd,
1850
1878
  onPreviewFile: previewPluginFile,
1851
- onRevealFile: revealPluginFile
1879
+ onRevealFile: revealPluginFile,
1880
+ onHeaderActionsChange: updatePluginHeaderActions
1852
1881
  }}
1853
1882
  />
1854
1883
  ) : null
@@ -1858,6 +1887,11 @@ export function L2Workbench({
1858
1887
  mobile={mobile}
1859
1888
  fileBrowser={fileBrowser}
1860
1889
  pluginTabContent={pluginTabContent}
1890
+ pluginHeaderActions={
1891
+ sidebarOpen && pluginHeaderActions?.targetKey === pluginSidebarTargetKey
1892
+ ? pluginHeaderActions.actions
1893
+ : []
1894
+ }
1861
1895
  pluginSessionTabs={pluginSessionTabs}
1862
1896
  fileRefreshLoading={activeFileWorkspace?.directories.get('')?.status === 'loading'}
1863
1897
  canBrowseFiles={activeCwd !== null}
@@ -1893,6 +1927,7 @@ export function L2Workbench({
1893
1927
  onSelect={selectSidebarWorkSession}
1894
1928
  onTogglePin={togglePinnedWorkSession}
1895
1929
  onDelete={requestDeleteWorkSession}
1930
+ onRename={renameSession.show}
1896
1931
  onArrangementChange={requestArrangementUpdate}
1897
1932
  />
1898
1933
  )
@@ -2057,6 +2092,16 @@ export function L2Workbench({
2057
2092
  onBeforeReload: () => chatInputRuntime.prepareForPageReload()
2058
2093
  }}
2059
2094
  />
2095
+ <L2WorkSessionRenameDialog
2096
+ open={renameSession.open}
2097
+ title={renameSession.title}
2098
+ saving={renameSession.saving}
2099
+ disabled={loading}
2100
+ error={renameSession.error}
2101
+ onTitleChange={renameSession.setTitle}
2102
+ onSave={() => void renameSession.save()}
2103
+ onClose={renameSession.close}
2104
+ />
2060
2105
  <L2WorkbenchPickerDialog
2061
2106
  open={directoryDialogOpen}
2062
2107
  pickerMode={pickerMode}
@@ -0,0 +1,88 @@
1
+ 'use client'
2
+
3
+ import { useId, useRef } from 'react'
4
+ import { useTranslation } from 'react-i18next'
5
+ import { LoaderCircleIcon } from 'lucide-react'
6
+ import {
7
+ L4AppDialogContent,
8
+ L4AppDialogRoot,
9
+ L4AppDialogTitle
10
+ } from '@client/l4_foundation/ui/l4-app-dialog'
11
+ import { Button } from '@client/l4_foundation/ui/shadcn/button'
12
+ import { Input } from '@client/l4_foundation/ui/shadcn/input'
13
+
14
+ interface Props {
15
+ open: boolean
16
+ title: string
17
+ saving: boolean
18
+ disabled: boolean
19
+ error: string | null
20
+ onTitleChange: (title: string) => void
21
+ onSave: () => void
22
+ onClose: () => void
23
+ }
24
+
25
+ export function L2WorkSessionRenameDialog({
26
+ open,
27
+ title,
28
+ saving,
29
+ disabled,
30
+ error,
31
+ onTitleChange,
32
+ onSave,
33
+ onClose
34
+ }: Props): React.JSX.Element {
35
+ const { t } = useTranslation('workbench')
36
+ const inputId = useId()
37
+ const inputRef = useRef<HTMLInputElement>(null)
38
+ return (
39
+ <L4AppDialogRoot open={open} onOpenChange={(nextOpen) => !nextOpen && onClose()}>
40
+ <L4AppDialogContent
41
+ data-testid="work-session-rename-dialog"
42
+ showCloseButton={false}
43
+ initialFocus={inputRef}
44
+ className="max-w-sm"
45
+ >
46
+ <form
47
+ className="flex flex-col gap-4 overflow-y-auto p-4"
48
+ onSubmit={(event) => {
49
+ event.preventDefault()
50
+ onSave()
51
+ }}
52
+ >
53
+ <L4AppDialogTitle>{t('renameSessionTitle')}</L4AppDialogTitle>
54
+ <div className="flex flex-col gap-2">
55
+ <label htmlFor={inputId} className="font-medium">
56
+ {t('sessionTitleLabel')}
57
+ </label>
58
+ <Input
59
+ ref={inputRef}
60
+ id={inputId}
61
+ value={title}
62
+ disabled={saving}
63
+ onChange={(event) => onTitleChange(event.currentTarget.value)}
64
+ onFocus={(event) => event.currentTarget.select()}
65
+ onKeyDown={(event) => {
66
+ if (event.key === 'Enter' && event.nativeEvent.isComposing) event.preventDefault()
67
+ }}
68
+ />
69
+ </div>
70
+ {error ? (
71
+ <p role="alert" className="break-words text-destructive">
72
+ {error}
73
+ </p>
74
+ ) : null}
75
+ <div className="flex justify-end gap-2">
76
+ <Button type="button" variant="outline" disabled={saving} onClick={onClose}>
77
+ {t('cancel', { ns: 'common' })}
78
+ </Button>
79
+ <Button type="submit" disabled={disabled || saving || !title.trim()} aria-busy={saving}>
80
+ {saving ? <LoaderCircleIcon className="size-4 animate-spin" /> : null}
81
+ {t('save', { ns: 'common' })}
82
+ </Button>
83
+ </div>
84
+ </form>
85
+ </L4AppDialogContent>
86
+ </L4AppDialogRoot>
87
+ )
88
+ }
@@ -0,0 +1,81 @@
1
+ .document {
2
+ box-sizing: border-box;
3
+ width: 100%;
4
+ max-width: 80ch;
5
+ min-width: 0;
6
+ margin-inline: auto;
7
+ padding: 1.5rem;
8
+ color: var(--foreground);
9
+ font-size: 1rem;
10
+ line-height: 1.8;
11
+ overflow-wrap: anywhere;
12
+ }
13
+
14
+ .document > * {
15
+ margin-block: 0;
16
+ }
17
+
18
+ .document > * + * {
19
+ margin-block-start: 1rem;
20
+ }
21
+
22
+ .document :is(h1, h2, h3, h4, h5, h6) {
23
+ font-weight: 600;
24
+ line-height: 1.4;
25
+ }
26
+
27
+ .document :is(h1, h2, h3, h4, h5, h6):not(:first-child) {
28
+ margin-block-start: 1.75rem;
29
+ }
30
+
31
+ .document h1 {
32
+ font-size: 1.75rem;
33
+ }
34
+
35
+ .document h2 {
36
+ font-size: 1.375rem;
37
+ }
38
+
39
+ .document h3 {
40
+ font-size: 1.125rem;
41
+ }
42
+
43
+ .document a {
44
+ color: inherit;
45
+ text-decoration: underline;
46
+ text-underline-offset: 3px;
47
+ }
48
+
49
+ .document :global([data-streamdown='code-block']) {
50
+ /* 保持真实高度,避免离屏代码块进入视口时改变文档长度。 */
51
+ content-visibility: visible !important;
52
+ contain-intrinsic-size: none !important;
53
+ }
54
+
55
+ .document :global([data-streamdown='code-block-body']) {
56
+ overflow-x: auto;
57
+ font-size: 0.875rem;
58
+ line-height: 1.6;
59
+ }
60
+
61
+ .document :global([data-streamdown='code-block-body']) :is(pre, code) {
62
+ font-size: inherit;
63
+ line-height: inherit;
64
+ white-space: pre;
65
+ overflow-wrap: normal;
66
+ }
67
+
68
+ .document :global([data-streamdown='code-block-body']) code > span {
69
+ display: block;
70
+ }
71
+
72
+ .document :global([data-streamdown='table-wrapper']) {
73
+ max-width: 100%;
74
+ min-width: 0;
75
+ }
76
+
77
+ @media (max-width: 640px) {
78
+ .document {
79
+ padding: 1rem;
80
+ }
81
+ }
@@ -0,0 +1,52 @@
1
+ 'use client'
2
+
3
+ import { cjk } from '@streamdown/cjk'
4
+ import { code } from '@streamdown/code'
5
+ import { memo, useLayoutEffect, useRef } from 'react'
6
+ import { Streamdown } from 'streamdown'
7
+ import styles from './l3-markdown-preview.module.css'
8
+
9
+ const plugins = { cjk, code }
10
+
11
+ export const L3MarkdownPreview = memo(function L3MarkdownPreview({
12
+ content,
13
+ label,
14
+ savedScrollTop,
15
+ onScroll
16
+ }: {
17
+ content: string
18
+ label: string
19
+ savedScrollTop: number
20
+ onScroll: (scrollTop: number) => void
21
+ }): React.JSX.Element {
22
+ const viewportRef = useRef<HTMLDivElement>(null)
23
+ const initialScrollTop = useRef(savedScrollTop)
24
+
25
+ useLayoutEffect(() => {
26
+ if (viewportRef.current) viewportRef.current.scrollTop = initialScrollTop.current
27
+ }, [])
28
+
29
+ return (
30
+ <div
31
+ ref={viewportRef}
32
+ data-testid="markdown-preview"
33
+ role="region"
34
+ aria-label={label}
35
+ tabIndex={0}
36
+ className="h-full min-h-0 overflow-auto overscroll-contain bg-background outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
37
+ onScroll={(event) => onScroll(event.currentTarget.scrollTop)}
38
+ >
39
+ <Streamdown
40
+ className={styles.document}
41
+ mode="static"
42
+ parseIncompleteMarkdown={false}
43
+ isAnimating={false}
44
+ controls={false}
45
+ lineNumbers={false}
46
+ plugins={plugins}
47
+ >
48
+ {content}
49
+ </Streamdown>
50
+ </div>
51
+ )
52
+ })
@@ -37,6 +37,8 @@ import type { L3ProjectGitBrowser } from './l3-project-git-runtime'
37
37
  import { useL3ProjectDocumentGit } from './l3-project-document-git'
38
38
  import { L3CodeSurfaceToolbarButton } from './l3-code-surface-toolbar-button'
39
39
  import { buildL3FilePreviewHtml } from './l3-file-preview-html'
40
+ import { L3MarkdownPreview } from './l3-markdown-preview'
41
+ import { getL3ProjectTextPreviewKind } from './l3-project-text-preview'
40
42
 
41
43
  function fileName(path: string): string {
42
44
  return path.replaceAll('\\', '/').split('/').at(-1) ?? path
@@ -67,8 +69,8 @@ export function L3ProjectDocumentView({
67
69
  useSyncExternalStore(runtime.subscribe, runtime.getRevision, runtime.getRevision)
68
70
  const { activeDiff, activePath } = runtime.state
69
71
  const document = !activeDiff && activePath ? runtime.state.documents.get(activePath) : null
70
- const isHtml = Boolean(activePath && /\.html?$/i.test(activePath))
71
- const showSource = document?.status === 'text' && (!isHtml || document.viewMode === 'source')
72
+ const previewKind = activePath ? getL3ProjectTextPreviewKind(activePath) : null
73
+ const showSource = document?.status === 'text' && (!previewKind || document.viewMode === 'source')
72
74
  const hostRef = useRef<HTMLDivElement>(null)
73
75
  const previewRef = useRef<L4CodePreviewHandle>(null)
74
76
  const diffRef = useRef<L4CodeDiffHandle>(null)
@@ -80,10 +82,12 @@ export function L3ProjectDocumentView({
80
82
  () => ({
81
83
  focus(): void {
82
84
  if (showSource) previewRef.current?.focus()
83
- else diffRef.current?.focus()
85
+ else if (activeDiff) diffRef.current?.focus()
86
+ else
87
+ hostRef.current?.querySelector<HTMLElement>('[data-testid="markdown-preview"]')?.focus()
84
88
  }
85
89
  }),
86
- [showSource]
90
+ [activeDiff, showSource]
87
91
  )
88
92
  useEffect(() => {
89
93
  const receive = (event: MessageEvent): void => {
@@ -150,7 +154,9 @@ export function L3ProjectDocumentView({
150
154
  onFocus={(event) => {
151
155
  if (event.target !== event.currentTarget) return
152
156
  if (showSource) previewRef.current?.focus()
153
- else diffRef.current?.focus()
157
+ else if (activeDiff) diffRef.current?.focus()
158
+ else
159
+ hostRef.current?.querySelector<HTMLElement>('[data-testid="markdown-preview"]')?.focus()
154
160
  }}
155
161
  >
156
162
  {activeDiff || activePath ? (
@@ -215,8 +221,12 @@ export function L3ProjectDocumentView({
215
221
  </>
216
222
  ) : (
217
223
  <>
218
- {isHtml && document?.status === 'text' && activePath ? (
219
- <div className="mr-auto flex shrink-0" role="group" aria-label={t('htmlMode')}>
224
+ {previewKind && document?.status === 'text' && activePath ? (
225
+ <div
226
+ className="mr-auto flex shrink-0"
227
+ role="group"
228
+ aria-label={t(previewKind === 'markdown' ? 'markdownMode' : 'htmlMode')}
229
+ >
220
230
  {(['preview', 'source'] as const).map((mode) => (
221
231
  <Button
222
232
  key={mode}
@@ -372,7 +382,15 @@ export function L3ProjectDocumentView({
372
382
  slides={[{ src: document.objectUrl, alt: activePath }]}
373
383
  ariaLabel={t('imageViewer', { name: fileName(activePath) })}
374
384
  />
375
- ) : isHtml && document.viewMode === 'preview' ? (
385
+ ) : previewKind === 'markdown' && document.viewMode === 'preview' ? (
386
+ <L3MarkdownPreview
387
+ key={activePath}
388
+ content={document.content}
389
+ label={t('markdownPreview', { name: activePath })}
390
+ savedScrollTop={document.previewScrollTop}
391
+ onScroll={(scrollTop) => runtime.savePreviewScrollTop(activePath, scrollTop)}
392
+ />
393
+ ) : previewKind === 'html' && document.viewMode === 'preview' ? (
376
394
  <iframe
377
395
  ref={iframeRef}
378
396
  className="block size-full border-0 bg-white"
@@ -11,6 +11,7 @@ import type { L4CodePreviewState } from '@client/l4_foundation/ui/code/l4-code-p
11
11
  import type { L4CodeDiffState } from '@client/l4_foundation/ui/code/l4-code-diff'
12
12
  import { saveL4CodePreferences } from '@client/l4_foundation/ui/code/l4-code-preferences'
13
13
  import { L3ProjectRequestError, type L3ProjectFileReader } from './l3-project-reader'
14
+ import { getL3ProjectTextPreviewKind } from './l3-project-text-preview'
14
15
  import type { L3ProjectRevealTargetType } from '@common/l3_modules/project-files/l3-project-files-contract'
15
16
  import {
16
17
  compactL3ProjectDirectory,
@@ -41,6 +42,7 @@ export type L3FileDocument =
41
42
  size: number
42
43
  editorState: L4CodePreviewState | null
43
44
  viewMode: 'source' | 'preview'
45
+ previewScrollTop: number
44
46
  comparison?: L3FileComparison
45
47
  }
46
48
  | { status: 'image'; mimeType: L4ProjectFileImageMimeType; size: number; objectUrl: string }
@@ -146,6 +148,7 @@ export class L3ProjectFileRuntime {
146
148
  private readonly restoredTabs = new Set<string>()
147
149
  private readonly restoredEditorStates = new Map<string, L4CodePreviewState>()
148
150
  private readonly restoredFileViewModes = new Map<string, 'source' | 'preview'>()
151
+ private readonly restoredPreviewScrollTops = new Map<string, number>()
149
152
  private searchRequest: AbortController | null = null
150
153
  private diffRequest: AbortController | null = null
151
154
  private revision = 0
@@ -430,6 +433,7 @@ export class L3ProjectFileRuntime {
430
433
  state.documents.delete(path)
431
434
  this.restoredEditorStates.delete(path)
432
435
  this.restoredFileViewModes.delete(path)
436
+ this.restoredPreviewScrollTops.delete(path)
433
437
  this.closeMissing.delete(path)
434
438
  this.restoredTabs.delete(path)
435
439
  }
@@ -478,7 +482,11 @@ export class L3ProjectFileRuntime {
478
482
  editorState: this.restoredEditorStates.get(path) ?? null,
479
483
  viewMode:
480
484
  this.restoredFileViewModes.get(path) ??
481
- (this.options.htmlPreview && /\.html?$/i.test(path) ? 'preview' : 'source')
485
+ (getL3ProjectTextPreviewKind(path) === 'markdown' ||
486
+ (this.options.htmlPreview && getL3ProjectTextPreviewKind(path) === 'html')
487
+ ? 'preview'
488
+ : 'source'),
489
+ previewScrollTop: this.restoredPreviewScrollTops.get(path) ?? 0
482
490
  }
483
491
  : {
484
492
  status: 'image',
@@ -634,6 +642,11 @@ export class L3ProjectFileRuntime {
634
642
  const document = this.state.documents.get(path)
635
643
  if (document?.status === 'text') document.editorState = state
636
644
  }
645
+ savePreviewScrollTop(path: string, scrollTop: number): void {
646
+ const document = this.state.documents.get(path)
647
+ if (document?.status !== 'text') return
648
+ document.previewScrollTop = scrollTop
649
+ }
637
650
  setWrapLines(path: string, wrapLines: boolean): void {
638
651
  if (this.state.documents.get(path)?.status === 'text') saveL4CodePreferences({ wrapLines })
639
652
  }
@@ -654,6 +667,7 @@ export class L3ProjectFileRuntime {
654
667
  this.clearDiff()
655
668
  for (const document of this.state.documents.values()) this.releaseDocument(document)
656
669
  this.state.documents.clear()
670
+ this.restoredPreviewScrollTops.clear()
657
671
  this.listeners.clear()
658
672
  }
659
673
  private async ensureDiff(): Promise<void> {
@@ -704,6 +718,7 @@ export class L3ProjectFileRuntime {
704
718
  if (document?.status === 'text') {
705
719
  if (document.editorState) this.restoredEditorStates.set(path, document.editorState)
706
720
  this.restoredFileViewModes.set(path, document.viewMode)
721
+ this.restoredPreviewScrollTops.set(path, document.previewScrollTop)
707
722
  }
708
723
  this.releaseDocument(document)
709
724
  this.state.documents.set(path, { status: 'unloaded' })
@@ -0,0 +1,5 @@
1
+ export function getL3ProjectTextPreviewKind(path: string): 'markdown' | 'html' | null {
2
+ if (/\.(md|markdown)$/i.test(path)) return 'markdown'
3
+ if (/\.html?$/i.test(path)) return 'html'
4
+ return null
5
+ }
@@ -6,39 +6,3 @@
6
6
  .identity {
7
7
  color: var(--pi-desk-project-color);
8
8
  }
9
-
10
- .statusBorder {
11
- position: absolute;
12
- z-index: 2;
13
- inset: -1px;
14
- width: calc(100% + 2px);
15
- height: calc(100% + 2px);
16
- overflow: visible;
17
- border-radius: inherit;
18
- pointer-events: none;
19
- color: var(--foreground);
20
- opacity: 0.48;
21
- }
22
-
23
- .statusBorder rect {
24
- rx: calc(var(--radius-xl) - 1px);
25
- width: calc(100% - 2px);
26
- height: calc(100% - 2px);
27
- fill: none;
28
- stroke: currentColor;
29
- stroke-width: 1;
30
- stroke-linecap: round;
31
- stroke-dasharray: 14 86;
32
- stroke-dashoffset: 14;
33
- }
34
-
35
- .statusBorder[data-state='completed'] {
36
- color: var(--pi-desk-project-color);
37
- opacity: 0.85;
38
- }
39
-
40
- .statusBorder[data-state='completed'] rect {
41
- stroke-width: 1.5;
42
- stroke-dasharray: 30 70;
43
- stroke-dashoffset: 30;
44
- }
@@ -4,11 +4,6 @@ import type { CSSProperties } from 'react'
4
4
  import { getL3WorkSessionProjectColor } from './l3-work-session-visual'
5
5
  import styles from './l3-work-session-visual-effects.module.css'
6
6
 
7
- export {
8
- L3WorkSessionStatusBorder,
9
- type L3WorkSessionVisualState
10
- } from './l3-work-session-status-border'
11
-
12
7
  interface L3WorkSessionPresentation {
13
8
  className: string
14
9
  style: CSSProperties
@@ -27,6 +27,7 @@ import {
27
27
  type BrowserPluginGlobalStateHost,
28
28
  type BrowserPluginHost,
29
29
  type BrowserPluginNotificationEventListener,
30
+ type BrowserSessionSidebarHeaderAction,
30
31
  type BrowserSessionSidebarTabContributionDefinition,
31
32
  type BrowserSessionSidebarTabTarget,
32
33
  type BrowserSettingsPageContributionDefinition,
@@ -759,6 +760,75 @@ export class L4PluginHostRuntime {
759
760
  const cancelled = new Promise<void>((resolve) => {
760
761
  controller.signal.addEventListener('abort', () => resolve(), { once: true })
761
762
  })
763
+ let target = input.target
764
+ if (target.kind === 'session-sidebar-tab' && target.setHeaderActions) {
765
+ const publishActions = target.setHeaderActions
766
+ let currentActions: readonly BrowserSessionSidebarHeaderAction[] = []
767
+ controller.signal.addEventListener(
768
+ 'abort',
769
+ () => {
770
+ currentActions = []
771
+ publishActions([])
772
+ },
773
+ { once: true }
774
+ )
775
+ target = {
776
+ ...target,
777
+ setHeaderActions: (actions) => {
778
+ if (controller.signal.aborted || !registration.owner.active) return
779
+ if (!Array.isArray(actions)) throw new Error('侧栏操作必须为数组')
780
+ const nextActions: BrowserSessionSidebarHeaderAction[] = actions.map((action) => {
781
+ const label = parseLabel(action.label, 'Sidebar action label')
782
+ const icon = cloneIcon(action.icon)
783
+ const disabled = action.disabled === true
784
+ const busy = action.busy === true
785
+ const onSelect = action.onSelect
786
+ if (typeof onSelect !== 'function') throw new Error('侧栏操作缺少 onSelect 回调')
787
+ let running = false
788
+ return {
789
+ label,
790
+ icon,
791
+ disabled,
792
+ busy,
793
+ onSelect: () => {
794
+ if (
795
+ controller.signal.aborted ||
796
+ !registration.owner.active ||
797
+ currentActions !== nextActions ||
798
+ disabled ||
799
+ busy ||
800
+ running
801
+ )
802
+ return
803
+ running = true
804
+ runPluginCallback(
805
+ async () => {
806
+ try {
807
+ await onSelect()
808
+ } catch (cause) {
809
+ if (!controller.signal.aborted && registration.owner.active) {
810
+ registration.owner.host.notify({
811
+ level: 'error',
812
+ title: label,
813
+ description: cause instanceof Error ? cause.message : String(cause)
814
+ })
815
+ }
816
+ throw cause
817
+ } finally {
818
+ running = false
819
+ }
820
+ },
821
+ `sidebar-action:${label}`,
822
+ input.pluginName
823
+ )
824
+ }
825
+ }
826
+ })
827
+ currentActions = nextActions
828
+ publishActions(nextActions)
829
+ }
830
+ }
831
+ }
762
832
  const mounting = Promise.resolve().then(async () => {
763
833
  if (controller.signal.aborted) throw new Error('插件视图已关闭')
764
834
  const implementation = await this.loadContribution(registration)
@@ -768,7 +838,7 @@ export class L4PluginHostRuntime {
768
838
  const mount = implementation.mount as unknown as BrowserMount<L4PluginContributionTarget>
769
839
  const result = await mount({
770
840
  container: input.container,
771
- target: input.target,
841
+ target,
772
842
  host: registration.owner.host,
773
843
  signal: controller.signal
774
844
  })
@@ -447,25 +447,6 @@ body:has(.pi-desk-workbench) {
447
447
  background: color-mix(in oklab, var(--muted-foreground) 70%, transparent);
448
448
  }
449
449
 
450
- @keyframes pi-desk-chat-send-flight {
451
- from {
452
- transform: translate(-1px, 1px);
453
- }
454
- to {
455
- transform: translate(2px, -2px);
456
- }
457
- }
458
-
459
- .pi-desk-chat-send-icon {
460
- animation: pi-desk-chat-send-flight 0.72s ease-in-out infinite alternate;
461
- }
462
-
463
- @media (prefers-reduced-motion: reduce) {
464
- .pi-desk-chat-send-icon {
465
- animation: none;
466
- }
467
- }
468
-
469
450
  @layer base {
470
451
  * {
471
452
  @apply border-border outline-ring/50;
@@ -156,7 +156,8 @@ function L4CodePreviewComponent(
156
156
  minimap: { enabled: false },
157
157
  stickyScroll: { enabled: false },
158
158
  scrollBeyondLastLine: false,
159
- smoothScrolling: true,
159
+ // 只读预览避免把每格滚轮输入扩展为多帧重绘。
160
+ smoothScrolling: false,
160
161
  wordWrap: wrapLinesRef.current ? 'on' : 'off',
161
162
  wrappingIndent: 'same',
162
163
  ...getL4MonacoTypography(),