@jetcrab/pi-desk 1.1.28-dev → 1.1.30-dev

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 (362) hide show
  1. package/docs/plugins.md +2 -2
  2. package/package.json +1 -1
  3. package/src/app/api/work-sessions/search/route.ts +1 -0
  4. package/src/app/project-preview/page.tsx +1 -3
  5. package/src/client/l1_entry/pages/l1-error-page.tsx +1 -1
  6. package/src/client/l1_entry/providers/l1-app-providers.tsx +2 -0
  7. package/src/client/l2_biz/auth/l2-login.module.css +1 -1
  8. package/src/client/l2_biz/plugin-host/l2-plugin-composer-panel.tsx +1 -1
  9. package/src/client/l2_biz/plugin-host/l2-plugin-contribution-host.tsx +1 -1
  10. package/src/client/l2_biz/plugin-host/l2-plugin-session-header-layout.ts +6 -3
  11. package/src/client/l2_biz/plugin-host/l2-plugin-session-header.tsx +75 -18
  12. package/src/client/l2_biz/project-preview/hooks/l2-use-project-preview.ts +1 -14
  13. package/src/client/l2_biz/project-preview/l2-project-preview-dialog.tsx +2 -3
  14. package/src/client/l2_biz/project-preview/l2-project-preview-page.tsx +1 -2
  15. package/src/client/l2_biz/project-preview/l2-project-preview.tsx +1 -4
  16. package/src/client/l2_biz/project-preview/views/l2-project-branch-select.tsx +42 -3
  17. package/src/client/l2_biz/settings/l2-settings.tsx +1 -1
  18. package/src/client/l2_biz/settings/l2-skills-settings.tsx +1 -1
  19. package/src/client/l2_biz/task-center/l2-task-center.tsx +1 -1
  20. package/src/client/l2_biz/workbench/file-workspace/l2-plugin-standalone-file-preview.tsx +1 -1
  21. package/src/client/l2_biz/workbench/file-workspace/l2-work-session-file-preview.tsx +1 -1
  22. package/src/client/l2_biz/workbench/git-workspace/l2-git-workspace-runtime.ts +11 -10
  23. package/src/client/l2_biz/workbench/hooks/l2-work-session-search.ts +52 -0
  24. package/src/client/l2_biz/workbench/hooks/l2-workbench-branch-picker.ts +42 -7
  25. package/src/client/l2_biz/workbench/hooks/l2-workbench-session-history.ts +143 -131
  26. package/src/client/l2_biz/workbench/hooks/l2-workbench-session-search.ts +97 -0
  27. package/src/client/l2_biz/workbench/l2-work-session-columns.tsx +8 -0
  28. package/src/client/l2_biz/workbench/l2-work-session-sidebar.tsx +129 -10
  29. package/src/client/l2_biz/workbench/l2-workbench-biz.ts +20 -2
  30. package/src/client/l2_biz/workbench/l2-workbench-branch-filter-preferences.ts +34 -0
  31. package/src/client/l2_biz/workbench/l2-workbench-branch-picker.tsx +34 -71
  32. package/src/client/l2_biz/workbench/l2-workbench-chat-input-runtime.ts +38 -1
  33. package/src/client/l2_biz/workbench/l2-workbench-chat-view.tsx +11 -1
  34. package/src/client/l2_biz/workbench/l2-workbench-picker-dialog.tsx +55 -215
  35. package/src/client/l2_biz/workbench/l2-workbench.tsx +21 -39
  36. package/src/client/l2_biz/workbench/views/l2-workbench-session-search.tsx +123 -0
  37. package/src/client/l3_modules/conversation/l3-conversation-messages.tsx +43 -4
  38. package/src/client/l3_modules/project-files/l3-markdown-preview.module.css +1 -1
  39. package/src/client/l3_modules/project-files/l3-project-document-git.ts +13 -29
  40. package/src/client/l3_modules/project-files/l3-project-document-view.tsx +1 -4
  41. package/src/client/l3_modules/project-files/l3-project-file-browser.module.css +14 -18
  42. package/src/client/l3_modules/project-files/l3-project-file-browser.tsx +52 -95
  43. package/src/client/l3_modules/project-files/l3-project-file-runtime.ts +52 -21
  44. package/src/client/l3_modules/project-files/l3-project-file-tabs.tsx +41 -62
  45. package/src/client/l3_modules/project-files/l3-project-git-runtime.ts +5 -4
  46. package/src/client/l3_modules/project-files/l3-use-project-refresh.ts +36 -0
  47. package/src/client/l3_modules/project-files/views/l3-project-search-results.tsx +2 -2
  48. package/src/client/l3_modules/project-files/views/l3-project-tree-folder.tsx +86 -0
  49. package/src/client/l4_foundation/desktop-window/l4-desktop-titlebar.tsx +188 -0
  50. package/src/client/l4_foundation/desktop-window/l4-desktop-window.css +107 -0
  51. package/src/client/l4_foundation/desktop-window/l4-desktop-window.ts +20 -0
  52. package/src/client/l4_foundation/ui/file-icons/README.md +1 -1
  53. package/src/client/l4_foundation/ui/file-icons/l4-file-icon.tsx +49 -2
  54. package/src/client/l4_foundation/ui/l4-app-dialog.tsx +2 -2
  55. package/src/common/l2_biz/pi-session/l2-pi-session-contract.ts +11 -24
  56. package/src/common/l2_biz/project-preview/l2-project-preview-navigation.ts +5 -12
  57. package/src/common/l2_biz/work-session/l2-work-session-search-contract.ts +26 -0
  58. package/src/common/l2_biz/work-session/l2-work-session-tree-contract.ts +9 -1
  59. package/src/common/l2_biz/workbench/l2-workbench-locale-messages.ts +12 -0
  60. package/src/common/l2_biz/workbench/l2-workbench-picker-messages.ts +6 -2
  61. package/src/common/l3_modules/conversation/l3-conversation-locale-messages.ts +2 -0
  62. package/src/common/l3_modules/pi/l3-pi-session-search-contract.ts +26 -0
  63. package/src/common/l4_foundation/locale/l4-host-error-messages.ts +2 -0
  64. package/src/server/l1_entry/api/l1-work-session-branch-route.ts +21 -15
  65. package/src/server/l1_entry/api/l1-work-session-search-route.ts +38 -0
  66. package/src/server/l2_biz/work-session/l2-work-session-chat-runtime.ts +4 -2
  67. package/src/server/l2_biz/work-session/l2-work-session-manage.ts +46 -10
  68. package/src/server/l3_modules/work-session/l3-work-session.ts +11 -6
  69. package/src/server/l4_foundation/pi/l4-pi-chat-worker.ts +35 -2
  70. package/src/server/l4_foundation/pi/l4-pi-session-history-catalog.ts +62 -113
  71. package/src/server/l4_foundation/pi/l4-pi-session-search.ts +166 -0
  72. package/src/server/l4_foundation/pi/l4-pi-work-session-runtime.ts +66 -5
  73. package/temp/build/pi-desk/release/.next/BUILD_ID +1 -1
  74. package/temp/build/pi-desk/release/.next/app-path-routes-manifest.json +1 -0
  75. package/temp/build/pi-desk/release/.next/build-manifest.json +3 -3
  76. package/temp/build/pi-desk/release/.next/required-server-files.js +2 -2
  77. package/temp/build/pi-desk/release/.next/required-server-files.json +2 -2
  78. package/temp/build/pi-desk/release/.next/routes-manifest.json +6 -0
  79. package/temp/build/pi-desk/release/.next/server/app/_global-error/page.js +2 -2
  80. package/temp/build/pi-desk/release/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  81. package/temp/build/pi-desk/release/.next/server/app/_global-error.html +1 -1
  82. package/temp/build/pi-desk/release/.next/server/app/_global-error.rsc +3 -3
  83. package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_full.segment.rsc +3 -3
  84. package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +3 -3
  85. package/temp/build/pi-desk/release/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  86. package/temp/build/pi-desk/release/.next/server/app/_not-found/page.js +1 -1
  87. package/temp/build/pi-desk/release/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  88. package/temp/build/pi-desk/release/.next/server/app/api/auth/login/route.js +2 -2
  89. package/temp/build/pi-desk/release/.next/server/app/api/auth/logout/route.js +1 -1
  90. package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/get/route.js +1 -1
  91. package/temp/build/pi-desk/release/.next/server/app/api/auth-settings/replace/route.js +1 -1
  92. package/temp/build/pi-desk/release/.next/server/app/api/capability-modes/get/route.js +1 -1
  93. package/temp/build/pi-desk/release/.next/server/app/api/capability-modes/replace/route.js +1 -1
  94. package/temp/build/pi-desk/release/.next/server/app/api/chat/context/get/route.js +1 -1
  95. package/temp/build/pi-desk/release/.next/server/app/api/chat/images/get/route.js +1 -1
  96. package/temp/build/pi-desk/release/.next/server/app/api/chat/messages/get/route.js +1 -1
  97. package/temp/build/pi-desk/release/.next/server/app/api/health/route.js +1 -1
  98. package/temp/build/pi-desk/release/.next/server/app/api/mcp-check/get/route.js +1 -1
  99. package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/del/route.js +1 -1
  100. package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/get/route.js +1 -1
  101. package/temp/build/pi-desk/release/.next/server/app/api/mcp-settings/replace/route.js +1 -1
  102. package/temp/build/pi-desk/release/.next/server/app/api/model-catalog/list/route.js +1 -1
  103. package/temp/build/pi-desk/release/.next/server/app/api/model-settings/get/route.js +1 -1
  104. package/temp/build/pi-desk/release/.next/server/app/api/model-settings/preview/route.js +1 -1
  105. package/temp/build/pi-desk/release/.next/server/app/api/model-settings/replace/route.js +1 -1
  106. package/temp/build/pi-desk/release/.next/server/app/api/pi/directories/list/route.js +1 -1
  107. package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-entries/list/route.js +1 -1
  108. package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-ignores/list/route.js +1 -1
  109. package/temp/build/pi-desk/release/.next/server/app/api/pi/directory-ignores/replace/route.js +1 -1
  110. package/temp/build/pi-desk/release/.next/server/app/api/pi/models/list/route.js +1 -1
  111. package/temp/build/pi-desk/release/.next/server/app/api/pi/session-user-messages/list/route.js +1 -1
  112. package/temp/build/pi-desk/release/.next/server/app/api/pi/sessions/list/route.js +1 -1
  113. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/get/route.js +1 -1
  114. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/search/route.js +1 -1
  115. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/settings-get/route.js +1 -1
  116. package/temp/build/pi-desk/release/.next/server/app/api/plugin-catalog/settings-replace/route.js +1 -1
  117. package/temp/build/pi-desk/release/.next/server/app/api/plugins/add/route.js +1 -1
  118. package/temp/build/pi-desk/release/.next/server/app/api/plugins/apply/route.js +1 -1
  119. package/temp/build/pi-desk/release/.next/server/app/api/plugins/batch/route.js +1 -1
  120. package/temp/build/pi-desk/release/.next/server/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route.js +1 -1
  121. package/temp/build/pi-desk/release/.next/server/app/api/plugins/del/route.js +1 -1
  122. package/temp/build/pi-desk/release/.next/server/app/api/plugins/enabled-set/route.js +1 -1
  123. package/temp/build/pi-desk/release/.next/server/app/api/plugins/get/route.js +1 -1
  124. package/temp/build/pi-desk/release/.next/server/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route.js +1 -1
  125. package/temp/build/pi-desk/release/.next/server/app/api/plugins/list/route.js +1 -1
  126. package/temp/build/pi-desk/release/.next/server/app/api/plugins/reload/route.js +1 -1
  127. package/temp/build/pi-desk/release/.next/server/app/api/plugins/update/route.js +1 -1
  128. package/temp/build/pi-desk/release/.next/server/app/api/project-files/get/route.js +2 -2
  129. package/temp/build/pi-desk/release/.next/server/app/api/project-files/list/route.js +1 -1
  130. package/temp/build/pi-desk/release/.next/server/app/api/project-files/reveal/route.js +1 -1
  131. package/temp/build/pi-desk/release/.next/server/app/api/project-files/search/route.js +1 -1
  132. package/temp/build/pi-desk/release/.next/server/app/api/project-git/get/route.js +2 -2
  133. package/temp/build/pi-desk/release/.next/server/app/api/project-git-branches/list/route.js +2 -2
  134. package/temp/build/pi-desk/release/.next/server/app/api/project-git-changes/list/route.js +1 -1
  135. package/temp/build/pi-desk/release/.next/server/app/api/project-git-diff/get/route.js +2 -2
  136. package/temp/build/pi-desk/release/.next/server/app/api/project-git-heads/get/route.js +1 -1
  137. package/temp/build/pi-desk/release/.next/server/app/api/project-git-log/list/route.js +2 -2
  138. package/temp/build/pi-desk/release/.next/server/app/api/project-model-default/get/route.js +1 -1
  139. package/temp/build/pi-desk/release/.next/server/app/api/project-model-default/replace/route.js +1 -1
  140. package/temp/build/pi-desk/release/.next/server/app/api/skill-files/get/route.js +1 -1
  141. package/temp/build/pi-desk/release/.next/server/app/api/skill-files/list/route.js +1 -1
  142. package/temp/build/pi-desk/release/.next/server/app/api/skill-files/replace/route.js +1 -1
  143. package/temp/build/pi-desk/release/.next/server/app/api/skills/list/route.js +1 -1
  144. package/temp/build/pi-desk/release/.next/server/app/api/task-center/images/get/route.js +1 -1
  145. package/temp/build/pi-desk/release/.next/server/app/api/task-center/messages/get/route.js +1 -1
  146. package/temp/build/pi-desk/release/.next/server/app/api/work-session-git-branch/add/route.js +1 -1
  147. package/temp/build/pi-desk/release/.next/server/app/api/work-session-git-branch/replace/route.js +1 -1
  148. package/temp/build/pi-desk/release/.next/server/app/api/work-session-tree/get/route.js +1 -1
  149. package/temp/build/pi-desk/release/.next/server/app/api/work-session-tree-entry/get/route.js +1 -1
  150. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/add/route.js +1 -1
  151. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/branch/route.js +1 -1
  152. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/del/route.js +1 -1
  153. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/rename/route.js +1 -1
  154. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/replace/route.js +1 -1
  155. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/search/route.js +1 -0
  156. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/search/route_client-reference-manifest.js +1 -0
  157. package/temp/build/pi-desk/release/.next/server/app/api/work-sessions/sort/route.js +1 -1
  158. package/temp/build/pi-desk/release/.next/server/app/favicon.ico/route.js +1 -1
  159. package/temp/build/pi-desk/release/.next/server/app/login/page.js +1 -1
  160. package/temp/build/pi-desk/release/.next/server/app/login/page_client-reference-manifest.js +1 -1
  161. package/temp/build/pi-desk/release/.next/server/app/page.js +138 -138
  162. package/temp/build/pi-desk/release/.next/server/app/page_client-reference-manifest.js +1 -1
  163. package/temp/build/pi-desk/release/.next/server/app/project-preview/page.js +1 -1
  164. package/temp/build/pi-desk/release/.next/server/app/project-preview/page_client-reference-manifest.js +1 -1
  165. package/temp/build/pi-desk/release/.next/server/app-paths-manifest.json +1 -0
  166. package/temp/build/pi-desk/release/.next/server/chunks/23054.js +2 -2
  167. package/temp/build/pi-desk/release/.next/server/chunks/25406.js +8 -8
  168. package/temp/build/pi-desk/release/.next/server/chunks/27344.js +3 -3
  169. package/temp/build/pi-desk/release/.next/server/chunks/3108.js +3 -3
  170. package/temp/build/pi-desk/release/.next/server/chunks/35985.js +3 -3
  171. package/temp/build/pi-desk/release/.next/server/chunks/41856.js +1 -0
  172. package/temp/build/pi-desk/release/.next/server/chunks/62900.js +235 -0
  173. package/temp/build/pi-desk/release/.next/server/chunks/6917.js +1 -1
  174. package/temp/build/pi-desk/release/.next/server/chunks/81363.js +1 -1
  175. package/temp/build/pi-desk/release/.next/server/chunks/81912.js +3 -0
  176. package/temp/build/pi-desk/release/.next/server/chunks/92386.js +2 -2
  177. package/temp/build/pi-desk/release/.next/server/middleware-build-manifest.js +1 -1
  178. package/temp/build/pi-desk/release/.next/server/pages/500.html +1 -1
  179. package/temp/build/pi-desk/release/.next/static/ErYBfYXAir5b-6rlacGvL/_buildManifest.js +1 -0
  180. package/temp/build/pi-desk/release/.next/static/chunks/10043-9d6c3735418ccaf9.js +238 -0
  181. package/temp/build/pi-desk/release/.next/static/chunks/11937-ac71fb0f7cef482a.js +1 -0
  182. package/temp/build/pi-desk/release/.next/static/chunks/30669-ffa76d39e0e25194.js +1 -0
  183. package/temp/build/pi-desk/release/.next/static/chunks/36643-f60e98278740073c.js +3 -0
  184. package/temp/build/pi-desk/release/.next/static/chunks/65232-f5b71cec787a30ec.js +15 -0
  185. package/temp/build/pi-desk/release/.next/static/chunks/{51474-8dc714cb76b2e60a.js → 65350-23bb961d87addf14.js} +3 -3
  186. package/temp/build/pi-desk/release/.next/static/chunks/app/_global-error/page-295cb63da5f7262f.js +1 -0
  187. package/temp/build/pi-desk/release/.next/static/chunks/app/_not-found/page-295cb63da5f7262f.js +1 -0
  188. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/login/route-295cb63da5f7262f.js +1 -0
  189. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/logout/route-295cb63da5f7262f.js +1 -0
  190. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/get/route-295cb63da5f7262f.js +1 -0
  191. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/replace/route-295cb63da5f7262f.js +1 -0
  192. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/get/route-295cb63da5f7262f.js +1 -0
  193. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/replace/route-295cb63da5f7262f.js +1 -0
  194. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/context/get/route-295cb63da5f7262f.js +1 -0
  195. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/images/get/route-295cb63da5f7262f.js +1 -0
  196. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/messages/get/route-295cb63da5f7262f.js +1 -0
  197. package/temp/build/pi-desk/release/.next/static/chunks/app/api/health/route-295cb63da5f7262f.js +1 -0
  198. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-check/get/route-295cb63da5f7262f.js +1 -0
  199. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/del/route-295cb63da5f7262f.js +1 -0
  200. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/get/route-295cb63da5f7262f.js +1 -0
  201. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/replace/route-295cb63da5f7262f.js +1 -0
  202. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-catalog/list/route-295cb63da5f7262f.js +1 -0
  203. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/get/route-295cb63da5f7262f.js +1 -0
  204. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/preview/route-295cb63da5f7262f.js +1 -0
  205. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/replace/route-295cb63da5f7262f.js +1 -0
  206. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directories/list/route-295cb63da5f7262f.js +1 -0
  207. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-entries/list/route-295cb63da5f7262f.js +1 -0
  208. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/list/route-295cb63da5f7262f.js +1 -0
  209. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/replace/route-295cb63da5f7262f.js +1 -0
  210. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/models/list/route-295cb63da5f7262f.js +1 -0
  211. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/session-user-messages/list/route-295cb63da5f7262f.js +1 -0
  212. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/sessions/list/route-295cb63da5f7262f.js +1 -0
  213. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/get/route-295cb63da5f7262f.js +1 -0
  214. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/search/route-295cb63da5f7262f.js +1 -0
  215. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-get/route-295cb63da5f7262f.js +1 -0
  216. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-replace/route-295cb63da5f7262f.js +1 -0
  217. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/add/route-295cb63da5f7262f.js +1 -0
  218. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/apply/route-295cb63da5f7262f.js +1 -0
  219. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/batch/route-295cb63da5f7262f.js +1 -0
  220. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route-295cb63da5f7262f.js +1 -0
  221. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/del/route-295cb63da5f7262f.js +1 -0
  222. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/enabled-set/route-295cb63da5f7262f.js +1 -0
  223. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/get/route-295cb63da5f7262f.js +1 -0
  224. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route-295cb63da5f7262f.js +1 -0
  225. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/list/route-295cb63da5f7262f.js +1 -0
  226. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/reload/route-295cb63da5f7262f.js +1 -0
  227. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/update/route-295cb63da5f7262f.js +1 -0
  228. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/get/route-295cb63da5f7262f.js +1 -0
  229. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/list/route-295cb63da5f7262f.js +1 -0
  230. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/reveal/route-295cb63da5f7262f.js +1 -0
  231. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/search/route-295cb63da5f7262f.js +1 -0
  232. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git/get/route-295cb63da5f7262f.js +1 -0
  233. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-branches/list/route-295cb63da5f7262f.js +1 -0
  234. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-changes/list/route-295cb63da5f7262f.js +1 -0
  235. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-diff/get/route-295cb63da5f7262f.js +1 -0
  236. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-heads/get/route-295cb63da5f7262f.js +1 -0
  237. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-log/list/route-295cb63da5f7262f.js +1 -0
  238. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/get/route-295cb63da5f7262f.js +1 -0
  239. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/replace/route-295cb63da5f7262f.js +1 -0
  240. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/get/route-295cb63da5f7262f.js +1 -0
  241. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/list/route-295cb63da5f7262f.js +1 -0
  242. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/replace/route-295cb63da5f7262f.js +1 -0
  243. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skills/list/route-295cb63da5f7262f.js +1 -0
  244. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/images/get/route-295cb63da5f7262f.js +1 -0
  245. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/messages/get/route-295cb63da5f7262f.js +1 -0
  246. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/add/route-295cb63da5f7262f.js +1 -0
  247. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/replace/route-295cb63da5f7262f.js +1 -0
  248. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree/get/route-295cb63da5f7262f.js +1 -0
  249. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree-entry/get/route-295cb63da5f7262f.js +1 -0
  250. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/add/route-295cb63da5f7262f.js +1 -0
  251. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/branch/route-295cb63da5f7262f.js +1 -0
  252. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/del/route-295cb63da5f7262f.js +1 -0
  253. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/rename/route-295cb63da5f7262f.js +1 -0
  254. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/replace/route-295cb63da5f7262f.js +1 -0
  255. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/search/route-295cb63da5f7262f.js +1 -0
  256. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/sort/route-295cb63da5f7262f.js +1 -0
  257. package/temp/build/pi-desk/release/.next/static/chunks/app/error-1ab62762c5f4144f.js +1 -0
  258. package/temp/build/pi-desk/release/.next/static/chunks/app/layout-ca5ef5994165eb2e.js +1 -0
  259. package/temp/build/pi-desk/release/.next/static/chunks/app/login/{page-0d3d4827802108e5.js → page-0df9df996aa68060.js} +1 -1
  260. package/temp/build/pi-desk/release/.next/static/chunks/app/not-found-b8b9b7ef5ccb7601.js +1 -0
  261. package/temp/build/pi-desk/release/.next/static/chunks/app/page-978906de76a8dcfe.js +158 -0
  262. package/temp/build/pi-desk/release/.next/static/chunks/app/project-preview/{page-038b6c14e03ed878.js → page-aaa845016a934245.js} +1 -1
  263. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/app-error-295cb63da5f7262f.js +1 -0
  264. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/forbidden-295cb63da5f7262f.js +1 -0
  265. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/unauthorized-295cb63da5f7262f.js +1 -0
  266. package/temp/build/pi-desk/release/.next/static/chunks/{webpack-c0b805df46fcf8b3.js → webpack-a84310d111797bef.js} +1 -1
  267. package/temp/build/pi-desk/release/.next/static/css/053a8d82c09326cd.css +1 -0
  268. package/temp/build/pi-desk/release/.next/static/css/1cc92eec583aa639.css +1 -0
  269. package/temp/build/pi-desk/release/.next/static/css/{1e780a4936aa6ba3.css → 2bb393927ba8f71d.css} +1 -1
  270. package/temp/build/pi-desk/release/.next/static/css/3a07dcc86ffdf88c.css +1 -0
  271. package/temp/build/pi-desk/release/.next/static/css/3c59ac068ae404da.css +1 -0
  272. package/temp/build/pi-desk/release/.next/trace-build +1 -1
  273. package/temp/build/pi-desk/release/.next/server/chunks/35348.js +0 -3
  274. package/temp/build/pi-desk/release/.next/server/chunks/56830.js +0 -235
  275. package/temp/build/pi-desk/release/.next/server/chunks/80780.js +0 -1
  276. package/temp/build/pi-desk/release/.next/static/bj2dB_Z10YB_CqK_VNhDx/_buildManifest.js +0 -1
  277. package/temp/build/pi-desk/release/.next/static/chunks/11937-1d0a9822f2c7995b.js +0 -1
  278. package/temp/build/pi-desk/release/.next/static/chunks/14197-3d3ddd426ac06c9c.js +0 -3
  279. package/temp/build/pi-desk/release/.next/static/chunks/37313-d5970e2d0c270d22.js +0 -238
  280. package/temp/build/pi-desk/release/.next/static/chunks/65232-ef4e5a4174f62faf.js +0 -15
  281. package/temp/build/pi-desk/release/.next/static/chunks/79267-7d21d7cdbd7cfca1.js +0 -1
  282. package/temp/build/pi-desk/release/.next/static/chunks/app/_global-error/page-9969fe0baa238786.js +0 -1
  283. package/temp/build/pi-desk/release/.next/static/chunks/app/_not-found/page-9969fe0baa238786.js +0 -1
  284. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/login/route-9969fe0baa238786.js +0 -1
  285. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth/logout/route-9969fe0baa238786.js +0 -1
  286. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/get/route-9969fe0baa238786.js +0 -1
  287. package/temp/build/pi-desk/release/.next/static/chunks/app/api/auth-settings/replace/route-9969fe0baa238786.js +0 -1
  288. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/get/route-9969fe0baa238786.js +0 -1
  289. package/temp/build/pi-desk/release/.next/static/chunks/app/api/capability-modes/replace/route-9969fe0baa238786.js +0 -1
  290. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/context/get/route-9969fe0baa238786.js +0 -1
  291. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/images/get/route-9969fe0baa238786.js +0 -1
  292. package/temp/build/pi-desk/release/.next/static/chunks/app/api/chat/messages/get/route-9969fe0baa238786.js +0 -1
  293. package/temp/build/pi-desk/release/.next/static/chunks/app/api/health/route-9969fe0baa238786.js +0 -1
  294. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-check/get/route-9969fe0baa238786.js +0 -1
  295. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/del/route-9969fe0baa238786.js +0 -1
  296. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/get/route-9969fe0baa238786.js +0 -1
  297. package/temp/build/pi-desk/release/.next/static/chunks/app/api/mcp-settings/replace/route-9969fe0baa238786.js +0 -1
  298. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-catalog/list/route-9969fe0baa238786.js +0 -1
  299. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/get/route-9969fe0baa238786.js +0 -1
  300. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/preview/route-9969fe0baa238786.js +0 -1
  301. package/temp/build/pi-desk/release/.next/static/chunks/app/api/model-settings/replace/route-9969fe0baa238786.js +0 -1
  302. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directories/list/route-9969fe0baa238786.js +0 -1
  303. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-entries/list/route-9969fe0baa238786.js +0 -1
  304. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/list/route-9969fe0baa238786.js +0 -1
  305. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/directory-ignores/replace/route-9969fe0baa238786.js +0 -1
  306. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/models/list/route-9969fe0baa238786.js +0 -1
  307. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/session-user-messages/list/route-9969fe0baa238786.js +0 -1
  308. package/temp/build/pi-desk/release/.next/static/chunks/app/api/pi/sessions/list/route-9969fe0baa238786.js +0 -1
  309. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/get/route-9969fe0baa238786.js +0 -1
  310. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/search/route-9969fe0baa238786.js +0 -1
  311. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-get/route-9969fe0baa238786.js +0 -1
  312. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugin-catalog/settings-replace/route-9969fe0baa238786.js +0 -1
  313. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/add/route-9969fe0baa238786.js +0 -1
  314. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/apply/route-9969fe0baa238786.js +0 -1
  315. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/batch/route-9969fe0baa238786.js +0 -1
  316. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/browser-resources/[resourceGroup]/[...resourcePath]/route-9969fe0baa238786.js +0 -1
  317. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/del/route-9969fe0baa238786.js +0 -1
  318. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/enabled-set/route-9969fe0baa238786.js +0 -1
  319. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/get/route-9969fe0baa238786.js +0 -1
  320. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/host-runtime/[runtimeVersion]/[...resourcePath]/route-9969fe0baa238786.js +0 -1
  321. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/list/route-9969fe0baa238786.js +0 -1
  322. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/reload/route-9969fe0baa238786.js +0 -1
  323. package/temp/build/pi-desk/release/.next/static/chunks/app/api/plugins/update/route-9969fe0baa238786.js +0 -1
  324. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/get/route-9969fe0baa238786.js +0 -1
  325. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/list/route-9969fe0baa238786.js +0 -1
  326. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/reveal/route-9969fe0baa238786.js +0 -1
  327. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-files/search/route-9969fe0baa238786.js +0 -1
  328. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git/get/route-9969fe0baa238786.js +0 -1
  329. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-branches/list/route-9969fe0baa238786.js +0 -1
  330. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-changes/list/route-9969fe0baa238786.js +0 -1
  331. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-diff/get/route-9969fe0baa238786.js +0 -1
  332. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-heads/get/route-9969fe0baa238786.js +0 -1
  333. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-git-log/list/route-9969fe0baa238786.js +0 -1
  334. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/get/route-9969fe0baa238786.js +0 -1
  335. package/temp/build/pi-desk/release/.next/static/chunks/app/api/project-model-default/replace/route-9969fe0baa238786.js +0 -1
  336. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/get/route-9969fe0baa238786.js +0 -1
  337. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/list/route-9969fe0baa238786.js +0 -1
  338. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skill-files/replace/route-9969fe0baa238786.js +0 -1
  339. package/temp/build/pi-desk/release/.next/static/chunks/app/api/skills/list/route-9969fe0baa238786.js +0 -1
  340. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/images/get/route-9969fe0baa238786.js +0 -1
  341. package/temp/build/pi-desk/release/.next/static/chunks/app/api/task-center/messages/get/route-9969fe0baa238786.js +0 -1
  342. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/add/route-9969fe0baa238786.js +0 -1
  343. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-git-branch/replace/route-9969fe0baa238786.js +0 -1
  344. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree/get/route-9969fe0baa238786.js +0 -1
  345. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-session-tree-entry/get/route-9969fe0baa238786.js +0 -1
  346. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/add/route-9969fe0baa238786.js +0 -1
  347. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/branch/route-9969fe0baa238786.js +0 -1
  348. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/del/route-9969fe0baa238786.js +0 -1
  349. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/rename/route-9969fe0baa238786.js +0 -1
  350. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/replace/route-9969fe0baa238786.js +0 -1
  351. package/temp/build/pi-desk/release/.next/static/chunks/app/api/work-sessions/sort/route-9969fe0baa238786.js +0 -1
  352. package/temp/build/pi-desk/release/.next/static/chunks/app/error-216b14b5da089ed3.js +0 -1
  353. package/temp/build/pi-desk/release/.next/static/chunks/app/layout-20718f1503910291.js +0 -1
  354. package/temp/build/pi-desk/release/.next/static/chunks/app/not-found-720cdf6a606b821a.js +0 -1
  355. package/temp/build/pi-desk/release/.next/static/chunks/app/page-ce2ebf7d8ea7a330.js +0 -158
  356. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/app-error-9969fe0baa238786.js +0 -1
  357. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/forbidden-9969fe0baa238786.js +0 -1
  358. package/temp/build/pi-desk/release/.next/static/chunks/next/dist/client/components/builtin/unauthorized-9969fe0baa238786.js +0 -1
  359. package/temp/build/pi-desk/release/.next/static/css/2bdcf40eca12b794.css +0 -1
  360. package/temp/build/pi-desk/release/.next/static/css/2c3b0c0ff1f49c68.css +0 -1
  361. package/temp/build/pi-desk/release/.next/static/css/c43b04c244a64fb4.css +0 -1
  362. /package/temp/build/pi-desk/release/.next/static/{bj2dB_Z10YB_CqK_VNhDx → ErYBfYXAir5b-6rlacGvL}/_ssgManifest.js +0 -0
package/docs/plugins.md CHANGED
@@ -180,10 +180,10 @@ plugin.registerSessionHeaderItem('session-info', {
180
180
  ```
181
181
 
182
182
  - `action` 只接受固定 `icon`、`label`、`onSelect({ source, host, signal })`,不提供动态图标、文字或状态订阅。宿主显示图标加文字,异步操作期间防止重复点击;失败记录局部错误,失效后的回调不得继续使用旧 Host。信号属于该展示生命周期,不会回滚服务端已经产生的副作用。
183
- - `custom` 只提供 `load()`,宿主不包装点击回调。inline custom 必须额外声明正数 `minWidthRem`,单位为 `rem`;宿主按此预留可用宽度,不通过重复挂载业务视图测量。自定义内容应适应获得的容器,不能靠超宽 DOM 挤占标题。overflow custom 不声明宽度。
183
+ - `custom` 只提供 `load()`,宿主不包装点击回调。inline custom 必须额外声明正数 `minWidthRem`,单位为 `rem`;有内容时才按此分配宽度。加载中和空内容不占宽度或间距,宿主只观察当前真实挂载,不复制业务视图测量。自定义内容应适应获得的容器,不能靠超宽 DOM 挤占标题。overflow custom 不声明宽度,加载中和空内容也不预留空行。
184
184
  - 自定义 Target 为 `{ kind: 'session-header-item', source, presentation: 'inline' | 'overflow' }`。两种表现可以使用不同模块,也可以复用同一个 `{ mount }`;loader 分别按表现缓存和重试。可复用上面的 `session-info.js`,或使用公共 React/UI 构建交互视图。
185
185
  - 标题项按插件名和注册名稳定排列;宽度不足时从末尾收进更多,宿主保留标题及必要操作。普通按钮选择后关闭更多;自定义区域内点击不会被转发,也不会自动关闭更多。Escape 或外部点击关闭浮层,键盘与触控均可操作。
186
- - 收纳会卸载 inline 自定义视图;只有更多打开时才挂载 overflow 自定义视图,关闭后释放。动态状态与运行/停止等复杂交互由自定义视图自行实现;业务状态归插件运行态,不归 mount,也不能只存于会被卸载的组件局部状态。卸载只清理视图资源,不停止项目进程。
186
+ - inline 自定义视图先静默挂载,内容出现后参与宽度计算;收纳会卸载该视图。只有更多打开时才挂载 overflow 自定义视图,关闭后释放。动态状态与运行/停止等复杂交互由自定义视图自行实现;业务状态归插件运行态,不归 mount,也不能只存于会被卸载的组件局部状态。卸载只清理视图资源,不停止项目进程。
187
187
 
188
188
  两种注册均限定 Browser Entry 同步阶段,名称规则与其他贡献相同。它们需要支持对应方法的宿主和 SDK;旧宿主缺少能力时禁用这项入口,不使用 `registerContribution` 别名或访问宿主 DOM 代替。现有 `composer-panel` 仍是人工打开的会话弹窗,不是上下方挂件。
189
189
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jetcrab/pi-desk",
3
- "version": "1.1.28-dev",
3
+ "version": "1.1.30-dev",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1 @@
1
+ export { POST } from '@server/l1_entry/api/l1-work-session-search-route'
@@ -2,7 +2,6 @@ import { Suspense } from 'react'
2
2
  import type { Metadata } from 'next'
3
3
  import { L1ProjectPreviewPage } from '@client/l1_entry/pages/l1-project-preview-page'
4
4
  import { buildL2ProjectPreviewTitle } from '@common/l2_biz/project-preview/l2-project-preview-navigation'
5
- import { getL4HostSettingsStore } from '@server/l4_foundation/l4-host-settings-store'
6
5
 
7
6
  export async function generateMetadata({
8
7
  searchParams
@@ -10,8 +9,7 @@ export async function generateMetadata({
10
9
  searchParams: Promise<{ cwd?: string | string[] }>
11
10
  }): Promise<Metadata> {
12
11
  const { cwd } = await searchParams
13
- const { region } = getL4HostSettingsStore().getSnapshot()
14
- return { title: buildL2ProjectPreviewTitle(Array.isArray(cwd) ? cwd[0] : cwd, region.locale) }
12
+ return { title: buildL2ProjectPreviewTitle(Array.isArray(cwd) ? cwd[0] : cwd) }
15
13
  }
16
14
 
17
15
  export default function ProjectPreview(): React.JSX.Element {
@@ -13,7 +13,7 @@ export function L1ErrorPage({
13
13
  }): React.JSX.Element {
14
14
  const { t } = useTranslation('common')
15
15
  return (
16
- <main className="flex min-h-dvh items-center justify-center bg-background p-4 text-foreground">
16
+ <main className="flex min-h-[var(--pi-desk-content-height)] items-center justify-center bg-background p-4 text-foreground">
17
17
  <div className="w-full max-w-md space-y-4 text-center">
18
18
  <h1 className="text-xl font-semibold">{t(notFound ? 'notFound' : 'pageError')}</h1>
19
19
  <div className="flex flex-wrap items-center justify-center gap-2">
@@ -24,6 +24,7 @@ import { L4AppToastProvider } from '@client/l4_foundation/ui/l4-app-toast'
24
24
  import { TooltipProvider } from '@client/l4_foundation/ui/shadcn/tooltip'
25
25
  import { createL4BrowserUuid } from '@client/l4_foundation/lib/l4-browser-uuid'
26
26
  import { L4ClientIdContext } from '@client/l4_foundation/lib/l4-client-id'
27
+ import { L4DesktopTitlebar } from '@client/l4_foundation/desktop-window/l4-desktop-titlebar'
27
28
 
28
29
  const resources = {
29
30
  en: {
@@ -76,6 +77,7 @@ export function L1AppProviders({
76
77
  <L4CodePreferencesProvider>
77
78
  <L4RegionProvider resources={resources} initialSettings={initialSettings}>
78
79
  <L4AppToastProvider>
80
+ <L4DesktopTitlebar />
79
81
  <L4RegionNotice />
80
82
  <TooltipProvider>{children}</TooltipProvider>
81
83
  </L4AppToastProvider>
@@ -1,7 +1,7 @@
1
1
  .page {
2
2
  display: grid;
3
3
  grid-template-rows: auto 1fr;
4
- min-height: 100dvh;
4
+ min-height: var(--pi-desk-content-height, 100dvh);
5
5
  padding: max(24px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right))
6
6
  max(24px, env(safe-area-inset-bottom)) max(24px, env(safe-area-inset-left));
7
7
  background: var(--background);
@@ -35,7 +35,7 @@ export function L2PluginComposerPanel({
35
35
  <L4AppDialogRoot open onOpenChange={(open) => !open && onClose()}>
36
36
  <L4AppDialogContent
37
37
  finalFocus={false}
38
- className="h-[min(720px,calc(100dvh-2rem))] max-w-4xl max-sm:h-dvh max-sm:max-h-dvh max-sm:w-full max-sm:max-w-none max-sm:rounded-none max-sm:border-0"
38
+ className="h-[min(720px,calc(100dvh-2rem))] max-w-4xl max-sm:h-[var(--pi-desk-content-height)] max-sm:max-h-[var(--pi-desk-content-height)] max-sm:w-full max-sm:max-w-none max-sm:rounded-none max-sm:border-0"
39
39
  >
40
40
  <L4AppDialogHeader className="border-b px-4 py-3 pr-12">
41
41
  <div className="flex min-w-0 items-center gap-3">
@@ -237,7 +237,7 @@ export function L2PluginContributionHost({
237
237
  state.status === 'error' && 'hidden'
238
238
  )}
239
239
  />
240
- {state.status === 'loading' ? (
240
+ {state.status === 'loading' && kind !== 'widget' && kind !== 'session-header-item' ? (
241
241
  <div
242
242
  role="status"
243
243
  className={cn(
@@ -4,14 +4,17 @@ export function calculateL2PluginSessionHeaderInlineCount(
4
4
  moreWidth: number,
5
5
  gap: number
6
6
  ): number {
7
- const total = widths.reduce((sum, width) => sum + width, 0) + Math.max(0, widths.length - 1) * gap
7
+ const occupiedCount = widths.filter((width) => width > 0).length
8
+ const total = widths.reduce((sum, width) => sum + width, 0) + Math.max(0, occupiedCount - 1) * gap
8
9
  if (total <= availableWidth) return widths.length
9
10
 
10
11
  let used = moreWidth
11
12
  let count = 0
12
13
  for (const width of widths) {
13
- if (used + gap + width > availableWidth) break
14
- used += gap + width
14
+ if (width > 0) {
15
+ if (used + gap + width > availableWidth) break
16
+ used += gap + width
17
+ }
15
18
  count += 1
16
19
  }
17
20
  return count
@@ -1,7 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import { EllipsisIcon } from 'lucide-react'
4
- import { useLayoutEffect, useMemo, useRef, useState, type ReactNode } from 'react'
4
+ import { useCallback, useLayoutEffect, useMemo, useRef, useState, type ReactNode } from 'react'
5
5
  import { useTranslation } from 'react-i18next'
6
6
  import type { BrowserSessionHeaderItemTarget, PluginSource } from '@jetcrab/pi-desk-sdk/browser'
7
7
  import { useL4PluginRegistry } from '@client/l4_foundation/plugin-host/l4-plugin-host-context'
@@ -14,6 +14,7 @@ import {
14
14
  PopoverTitle,
15
15
  PopoverTrigger
16
16
  } from '@client/l4_foundation/ui/shadcn/popover'
17
+ import { cn } from '@client/l4_foundation/lib/l4-utils'
17
18
  import { L2PluginContributionHost } from './l2-plugin-contribution-host'
18
19
  import { calculateL2PluginSessionHeaderInlineCount } from './l2-plugin-session-header-layout'
19
20
  import { L2PluginSessionHeaderAction } from './views/l2-plugin-session-header-action'
@@ -36,12 +37,14 @@ function HeaderItemView({
36
37
  item,
37
38
  source,
38
39
  presentation,
39
- onSelected
40
+ onSelected,
41
+ onContentChange
40
42
  }: {
41
43
  item: HeaderItem
42
44
  source: PluginSource
43
45
  presentation: 'inline' | 'overflow'
44
46
  onSelected?: () => void
47
+ onContentChange?: (item: HeaderItem, hasContent: boolean) => void
45
48
  }): React.JSX.Element {
46
49
  const definition = item.descriptor[presentation]
47
50
  const target = useMemo<BrowserSessionHeaderItemTarget>(
@@ -49,6 +52,22 @@ function HeaderItemView({
49
52
  [presentation, source]
50
53
  )
51
54
  const sourceKey = JSON.stringify([source.workId, source.sessionId, source.branchId, presentation])
55
+ const contentRef = useRef<HTMLDivElement>(null)
56
+ const [hasContent, setHasContent] = useState(false)
57
+
58
+ useLayoutEffect(() => {
59
+ const content = contentRef.current
60
+ if (!content) return
61
+ const measure = (): void => {
62
+ const visible = content.getBoundingClientRect().height > 0
63
+ setHasContent(visible)
64
+ onContentChange?.(item, visible)
65
+ }
66
+ const observer = new ResizeObserver(measure)
67
+ observer.observe(content)
68
+ return () => observer.disconnect()
69
+ }, [item, onContentChange, sourceKey])
70
+
52
71
  if (definition.type === 'action') {
53
72
  return (
54
73
  <L2PluginSessionHeaderAction
@@ -68,21 +87,29 @@ function HeaderItemView({
68
87
  data-plugin-name={item.pluginName}
69
88
  data-contribution-name={item.descriptor.contributionName}
70
89
  data-presentation={presentation}
71
- className="min-w-0 shrink-0"
90
+ className={cn(
91
+ 'min-w-0 shrink-0',
92
+ presentation === 'overflow' && 'w-full',
93
+ !hasContent && 'pointer-events-none invisible absolute'
94
+ )}
95
+ aria-hidden={!hasContent}
96
+ inert={!hasContent}
72
97
  style={
73
98
  presentation === 'inline' && item.descriptor.inline.type === 'custom'
74
99
  ? { width: `${item.descriptor.inline.minWidthRem}rem` }
75
100
  : undefined
76
101
  }
77
102
  >
78
- <L2PluginContributionHost
79
- pluginName={item.pluginName}
80
- kind="session-header-item"
81
- contributionName={item.descriptor.contributionName}
82
- target={target}
83
- targetKey={sourceKey}
84
- layout="inline"
85
- />
103
+ <div ref={contentRef}>
104
+ <L2PluginContributionHost
105
+ pluginName={item.pluginName}
106
+ kind="session-header-item"
107
+ contributionName={item.descriptor.contributionName}
108
+ target={target}
109
+ targetKey={sourceKey}
110
+ layout="inline"
111
+ />
112
+ </div>
86
113
  </div>
87
114
  )
88
115
  }
@@ -106,16 +133,31 @@ export function L2PluginSessionHeader({
106
133
  )
107
134
  const rootRef = useRef<HTMLDivElement>(null)
108
135
  const measurementsRef = useRef<HTMLDivElement>(null)
136
+ const customContentRef = useRef(new Map<HeaderItem, boolean>())
137
+ const measureRef = useRef<(() => void) | null>(null)
138
+ const onContentChange = useCallback((item: HeaderItem, hasContent: boolean): void => {
139
+ if (customContentRef.current.get(item) === hasContent) return
140
+ customContentRef.current.set(item, hasContent)
141
+ measureRef.current?.()
142
+ }, [])
109
143
  const [measurement, setMeasurement] = useState<{
110
144
  items: readonly HeaderItem[]
111
145
  count: number
146
+ occupied: boolean
112
147
  } | null>(null)
113
148
  const [open, setOpen] = useState(false)
114
- const count = measurement?.items === items ? measurement.count : 0
149
+ const count = measurement?.items === items ? measurement.count : items.length
150
+ const occupied =
151
+ measurement?.items === items
152
+ ? measurement.occupied
153
+ : items.some((item) => item.descriptor.inline.type === 'action')
115
154
  const inlineItems = items.slice(0, count)
116
155
  const overflowItems = items.slice(count)
117
156
 
118
157
  useLayoutEffect(() => {
158
+ for (const item of customContentRef.current.keys()) {
159
+ if (!items.includes(item)) customContentRef.current.delete(item)
160
+ }
119
161
  const root = rootRef.current
120
162
  const measurements = measurementsRef.current
121
163
  if (!root || !measurements || items.length === 0) return
@@ -127,42 +169,57 @@ export function L2PluginSessionHeader({
127
169
  const gap = gapProbe.getBoundingClientRect().width
128
170
  const available =
129
171
  root.getBoundingClientRect().width - titleProbe.getBoundingClientRect().width - gap
172
+ const widths = probes.map((probe, index) =>
173
+ items[index].descriptor.inline.type === 'custom' &&
174
+ !customContentRef.current.get(items[index])
175
+ ? 0
176
+ : probe.getBoundingClientRect().width
177
+ )
130
178
  const nextCount = calculateL2PluginSessionHeaderInlineCount(
131
- probes.map((probe) => probe.getBoundingClientRect().width),
179
+ widths,
132
180
  available,
133
181
  moreProbe.getBoundingClientRect().width,
134
182
  gap
135
183
  )
184
+ const nextOccupied = widths.some((width) => width > 0)
136
185
  if (nextCount === items.length) setOpen(false)
137
186
  setMeasurement((current) =>
138
- current?.items === items && current.count === nextCount
187
+ current?.items === items && current.count === nextCount && current.occupied === nextOccupied
139
188
  ? current
140
- : { items, count: nextCount }
189
+ : { items, count: nextCount, occupied: nextOccupied }
141
190
  )
142
191
  }
192
+ measureRef.current = measure
143
193
  const observer = new ResizeObserver(measure)
144
194
  observer.observe(root)
145
195
  for (const probe of [...probes, titleProbe, moreProbe, gapProbe]) observer.observe(probe)
146
196
  measure()
147
- return () => observer.disconnect()
197
+ return () => {
198
+ measureRef.current = null
199
+ observer.disconnect()
200
+ }
148
201
  }, [items])
149
202
 
150
203
  return (
151
204
  <div
152
205
  ref={rootRef}
153
- className="relative flex min-w-0 flex-1 items-center gap-1"
206
+ className="relative flex min-w-0 flex-1 items-center"
154
207
  data-testid="plugin-session-header"
155
208
  >
156
209
  <div className="min-w-[3rem] flex-1">{title}</div>
157
210
  {items.length > 0 ? (
158
211
  <>
159
- <div className="flex shrink-0 items-center gap-1" data-testid="session-header-items">
212
+ <div
213
+ className={cn('flex shrink-0 items-center gap-1', occupied && 'ml-1')}
214
+ data-testid="session-header-items"
215
+ >
160
216
  {inlineItems.map((item) => (
161
217
  <HeaderItemView
162
218
  key={itemKey(item)}
163
219
  item={item}
164
220
  source={source}
165
221
  presentation="inline"
222
+ onContentChange={onContentChange}
166
223
  />
167
224
  ))}
168
225
  {overflowItems.length > 0 ? (
@@ -45,7 +45,6 @@ interface PreviewState extends Pick<L2ProjectPreviewOwner, 'files' | 'git' | 'hi
45
45
  export function useL2ProjectPreview(
46
46
  clientId: string,
47
47
  cwd: string,
48
- refreshOnFocus: boolean,
49
48
  onUnauthorized?: () => void
50
49
  ): PreviewState {
51
50
  const toast = useL4AppToast()
@@ -63,7 +62,7 @@ export function useL2ProjectPreview(
63
62
  (text) => toast.show({ level: 'info', title: text }),
64
63
  saved,
65
64
  initialGlobal,
66
- { lazyHistory: !refreshOnFocus, onUnauthorized }
65
+ { lazyHistory: true, onUnauthorized }
67
66
  )
68
67
  )
69
68
  const { files, git, history } = owner
@@ -155,18 +154,6 @@ export function useL2ProjectPreview(
155
154
  }
156
155
  }, [cwd, files, git, owner])
157
156
 
158
- useEffect(() => {
159
- if (!refreshOnFocus) return
160
- let lastFocus = Date.now()
161
- const focus = (): void => {
162
- if (Date.now() - lastFocus < 5000) return
163
- lastFocus = Date.now()
164
- void git.refreshSnapshot(cwd)
165
- }
166
- window.addEventListener('focus', focus)
167
- return () => window.removeEventListener('focus', focus)
168
- }, [cwd, git, refreshOnFocus])
169
-
170
157
  useEffect(() => {
171
158
  if (!container) return
172
159
  const measure = (): void =>
@@ -41,8 +41,8 @@ export function L2ProjectPreviewDialog({
41
41
  data-testid="project-preview-dialog"
42
42
  className={cn(
43
43
  'h-[min(94dvh,1080px)] w-[min(96dvw,1600px)] max-w-none gap-0 p-0',
44
- maximized && 'h-dvh max-h-none w-dvw rounded-none',
45
- 'max-sm:h-dvh max-sm:max-h-none max-sm:w-dvw max-sm:rounded-none'
44
+ maximized && 'h-[var(--pi-desk-content-height)] max-h-none w-dvw rounded-none',
45
+ 'max-sm:h-[var(--pi-desk-content-height)] max-sm:max-h-none max-sm:w-dvw max-sm:rounded-none'
46
46
  )}
47
47
  >
48
48
  <L4AppDialogDescription className="sr-only">
@@ -51,7 +51,6 @@ export function L2ProjectPreviewDialog({
51
51
  <L2ProjectPreview
52
52
  clientId={clientId}
53
53
  cwd={cwd}
54
- refreshOnFocus
55
54
  onEscape={onClose}
56
55
  title={
57
56
  <L4AppDialogTitle className="truncate text-sm" title={cwd}>
@@ -34,7 +34,7 @@ export function L2ProjectPreviewPage({
34
34
  const { t } = useTranslation('projectHistory')
35
35
  return (
36
36
  <main
37
- className="flex h-dvh min-w-0 flex-col overflow-hidden bg-background text-foreground"
37
+ className="flex h-[var(--pi-desk-content-height)] min-w-0 flex-col overflow-hidden bg-background text-foreground"
38
38
  data-testid="project-preview-page"
39
39
  >
40
40
  {cwd ? (
@@ -42,7 +42,6 @@ export function L2ProjectPreviewPage({
42
42
  key={cwd}
43
43
  clientId={clientId}
44
44
  cwd={cwd}
45
- refreshOnFocus={false}
46
45
  onUnauthorized={onUnauthorized}
47
46
  actions={
48
47
  <Button size="sm" variant="ghost" onClick={() => onSelect(null)}>
@@ -33,7 +33,6 @@ const ignoreEscape = (): void => {}
33
33
  export function L2ProjectPreview({
34
34
  clientId,
35
35
  cwd,
36
- refreshOnFocus,
37
36
  title,
38
37
  actions,
39
38
  onEscape = ignoreEscape,
@@ -41,7 +40,6 @@ export function L2ProjectPreview({
41
40
  }: {
42
41
  clientId: string
43
42
  cwd: string
44
- refreshOnFocus: boolean
45
43
  title?: ReactNode
46
44
  actions?: ReactNode
47
45
  onEscape?: () => void
@@ -66,7 +64,7 @@ export function L2ProjectPreview({
66
64
  changeRowHeight,
67
65
  openGit,
68
66
  refresh
69
- } = useL2ProjectPreview(clientId, cwd, refreshOnFocus, onUnauthorized)
67
+ } = useL2ProjectPreview(clientId, cwd, onUnauthorized)
70
68
  const { directoryOpen, gitOpen, gitMaximized } = global
71
69
  const projectName = cwd.replaceAll('\\', '/').split('/').filter(Boolean).at(-1) ?? cwd
72
70
  const gitState = git.getWorkspace(cwd)!
@@ -88,7 +86,6 @@ export function L2ProjectPreview({
88
86
  runtime={files}
89
87
  gitRuntime={git}
90
88
  compact={width < 1100}
91
- refreshOnFocus={refreshOnFocus}
92
89
  onEscape={onEscape}
93
90
  renderHeader={(actions) => (
94
91
  <L3ProjectFileTabs
@@ -2,7 +2,16 @@
2
2
 
3
3
  import { useId, useMemo, useRef, useState, type KeyboardEvent } from 'react'
4
4
  import { useTranslation } from 'react-i18next'
5
- import { CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronsUpDownIcon } from 'lucide-react'
5
+ import {
6
+ CheckIcon,
7
+ ChevronDownIcon,
8
+ ChevronRightIcon,
9
+ ChevronsUpDownIcon,
10
+ FolderIcon,
11
+ FolderOpenIcon,
12
+ GitBranchIcon,
13
+ GitCommitHorizontalIcon
14
+ } from 'lucide-react'
6
15
  import type { L4GitReadBranches } from '@common/l4_foundation/git/l4-git-history-contract'
7
16
  import {
8
17
  buildL3GitBranchTree,
@@ -239,8 +248,26 @@ export function L2ProjectBranchSelect({
239
248
  className
240
249
  )}
241
250
  >
242
- <span className={cn('min-w-0 truncate', !value && 'text-muted-foreground')}>
243
- {selectedLabel || placeholder || common('selectPlaceholder')}
251
+ <span
252
+ className={cn(
253
+ 'flex min-w-0 flex-1 items-center gap-2',
254
+ !value && 'text-muted-foreground'
255
+ )}
256
+ >
257
+ {value === 'HEAD' ? (
258
+ <GitCommitHorizontalIcon
259
+ aria-hidden="true"
260
+ className="size-4 shrink-0 text-muted-foreground"
261
+ />
262
+ ) : (
263
+ <GitBranchIcon
264
+ aria-hidden="true"
265
+ className="size-4 shrink-0 text-muted-foreground"
266
+ />
267
+ )}
268
+ <span className="min-w-0 truncate">
269
+ {selectedLabel || placeholder || common('selectPlaceholder')}
270
+ </span>
244
271
  </span>
245
272
  <ChevronsUpDownIcon className="text-muted-foreground" />
246
273
  </Button>
@@ -282,6 +309,15 @@ export function L2ProjectBranchSelect({
282
309
  {rows.map((row) => {
283
310
  const selected = !row.expandable && row.key === value
284
311
  const expandedRow = row.expandable ? expanded.has(row.key) : undefined
312
+ const RowIcon = row.expandable
313
+ ? row.level === 1
314
+ ? null
315
+ : expandedRow
316
+ ? FolderOpenIcon
317
+ : FolderIcon
318
+ : row.key === 'HEAD'
319
+ ? GitCommitHorizontalIcon
320
+ : GitBranchIcon
285
321
  return (
286
322
  <button
287
323
  key={row.key}
@@ -325,6 +361,9 @@ export function L2ProjectBranchSelect({
325
361
  ) : (
326
362
  <span aria-hidden="true" className="size-3.5 shrink-0" />
327
363
  )}
364
+ {RowIcon ? (
365
+ <RowIcon aria-hidden="true" className="size-4 shrink-0 text-muted-foreground" />
366
+ ) : null}
328
367
  <span className="min-w-0 flex-1 break-all">{row.label}</span>
329
368
  {selected ? <CheckIcon aria-hidden="true" className="size-3.5 shrink-0" /> : null}
330
369
  </button>
@@ -281,7 +281,7 @@ export function L2Settings({
281
281
  }}
282
282
  >
283
283
  <L4AppDialogContent
284
- className="h-[min(48rem,calc(100dvh-2rem))] max-w-6xl max-sm:h-dvh max-sm:max-h-dvh max-sm:w-dvw max-sm:max-w-none max-sm:rounded-none max-sm:border-0"
284
+ className="h-[min(48rem,calc(100dvh-2rem))] max-w-6xl max-sm:h-[var(--pi-desk-content-height)] max-sm:max-h-[var(--pi-desk-content-height)] max-sm:w-dvw max-sm:max-w-none max-sm:rounded-none max-sm:border-0"
285
285
  finalFocus={false}
286
286
  showCloseButton={!guardPending}
287
287
  >
@@ -209,7 +209,7 @@ export function L2SkillsSettings({
209
209
  </div>
210
210
  <L4AppDialogRoot open={drawerOpen} onOpenChange={setDrawerOpen}>
211
211
  <L4AppDialogContent
212
- className="left-0 top-0 z-[130] h-dvh max-h-dvh w-[min(360px,calc(100dvw-2rem))] max-w-none translate-x-0 translate-y-0 rounded-l-none"
212
+ className="left-0 top-[var(--pi-desk-window-inset)] z-[130] h-[var(--pi-desk-content-height)] max-h-[var(--pi-desk-content-height)] w-[min(360px,calc(100dvw-2rem))] max-w-none translate-x-0 translate-y-0 rounded-l-none"
213
213
  finalFocus={false}
214
214
  >
215
215
  <L4AppDialogHeader className="shrink-0 border-b px-4 py-3 pr-12">
@@ -468,7 +468,7 @@ function TaskCenterPanel({
468
468
  <L4AppDialogContent
469
469
  aria-label={t('title')}
470
470
  showCloseButton={false}
471
- className="h-[calc(100dvh-2rem)] max-w-[70rem] flex-row bg-background max-lg:h-dvh max-lg:max-h-dvh max-lg:w-dvw max-lg:max-w-none max-lg:rounded-none max-lg:border-0"
471
+ className="h-[calc(100dvh-2rem)] max-w-[70rem] flex-row bg-background max-lg:h-[var(--pi-desk-content-height)] max-lg:max-h-[var(--pi-desk-content-height)] max-lg:w-dvw max-lg:max-w-none max-lg:rounded-none max-lg:border-0"
472
472
  >
473
473
  <div
474
474
  className={cn(
@@ -152,7 +152,7 @@ export function L2PluginStandaloneFilePreview({
152
152
  <L4AppDialogContent
153
153
  className={
154
154
  mobile
155
- ? 'inset-0 h-dvh max-h-none w-dvw max-w-none translate-x-0 translate-y-0 rounded-none border-0 ring-0'
155
+ ? 'inset-x-0 top-[var(--pi-desk-window-inset)] bottom-0 h-[var(--pi-desk-content-height)] max-h-none w-dvw max-w-none translate-x-0 translate-y-0 rounded-none border-0 ring-0'
156
156
  : 'h-[min(94dvh,1080px)] w-[min(96dvw,1600px)] max-w-none'
157
157
  }
158
158
  >
@@ -75,7 +75,7 @@ export function L2WorkSessionFilePreview({
75
75
  }}
76
76
  className={
77
77
  mobile
78
- ? 'inset-0 h-dvh max-h-none w-dvw max-w-none translate-x-0 translate-y-0 rounded-none border-0 ring-0'
78
+ ? 'inset-x-0 top-[var(--pi-desk-window-inset)] bottom-0 h-[var(--pi-desk-content-height)] max-h-none w-dvw max-w-none translate-x-0 translate-y-0 rounded-none border-0 ring-0'
79
79
  : 'h-[min(94dvh,1080px)] w-[min(96dvw,1600px)] max-w-none'
80
80
  }
81
81
  finalFocus={() => {
@@ -147,11 +147,11 @@ export class L2GitWorkspaceRuntime {
147
147
  if (workspace.snapshot.status === 'ready' || workspace.snapshot.status === 'loading') {
148
148
  return Promise.resolve()
149
149
  }
150
- return this.loadSnapshot(cwd, false)
150
+ return this.loadSnapshot(cwd)
151
151
  }
152
152
 
153
153
  refreshSnapshot(cwd: string): Promise<void> {
154
- return this.loadSnapshot(cwd, true)
154
+ return this.loadSnapshot(cwd)
155
155
  }
156
156
 
157
157
  async refreshHeads(cwd: string): Promise<void> {
@@ -332,9 +332,9 @@ export class L2GitWorkspaceRuntime {
332
332
  this.listeners.clear()
333
333
  }
334
334
 
335
- private async loadSnapshot(cwd: string, force: boolean): Promise<void> {
335
+ private async loadSnapshot(cwd: string): Promise<void> {
336
336
  const workspace = this.workspaceFor(cwd)
337
- if (workspace.snapshotRequest && !force) return
337
+ if (workspace.snapshotRequest) return
338
338
  const project = this.projectRefs.get(cwd)
339
339
  if (!project) {
340
340
  workspace.snapshot = {
@@ -346,16 +346,17 @@ export class L2GitWorkspaceRuntime {
346
346
  return
347
347
  }
348
348
 
349
- workspace.snapshotRequest?.controller.abort()
350
349
  const controller = new AbortController()
351
350
  const token = {}
352
351
  workspace.snapshotRequest = { controller, token }
353
- workspace.snapshot = {
354
- status: 'loading',
355
- repositories: workspace.snapshot.repositories,
356
- error: null
352
+ if (workspace.snapshot.status !== 'ready') {
353
+ workspace.snapshot = {
354
+ status: 'loading',
355
+ repositories: workspace.snapshot.repositories,
356
+ error: null
357
+ }
358
+ this.publish()
357
359
  }
358
- this.publish()
359
360
 
360
361
  try {
361
362
  const result = await this.biz.get({ workId: project.workId, cwd }, controller.signal)
@@ -0,0 +1,52 @@
1
+ 'use client'
2
+
3
+ import { useCallback, useState } from 'react'
4
+ import { useTranslation } from 'react-i18next'
5
+ import type { L2WorkSessionListItem } from '@common/l2_biz/work-session/l2-work-session-contract'
6
+ import type { L2WorkSessionSearchResponse } from '@common/l2_biz/work-session/l2-work-session-search-contract'
7
+ import type {
8
+ L3PiSessionSearchQuery,
9
+ L3PiSessionSearchScope
10
+ } from '@common/l3_modules/pi/l3-pi-session-search-contract'
11
+ import type { L2WorkbenchBiz } from '../l2-workbench-biz'
12
+ import {
13
+ L2_WORKBENCH_DEFAULT_SEARCH_IN,
14
+ useL2WorkbenchSessionSearch,
15
+ type L2WorkbenchSessionSearchResult
16
+ } from './l2-workbench-session-search'
17
+
18
+ export interface L2WorkSessionSearch extends L2WorkbenchSessionSearchResult<L2WorkSessionSearchResponse> {
19
+ query: string
20
+ searchIn: readonly L3PiSessionSearchScope[]
21
+ setQuery: (query: string) => void
22
+ setSearchIn: (searchIn: readonly L3PiSessionSearchScope[]) => void
23
+ }
24
+
25
+ export function useL2WorkSessionSearch({
26
+ active,
27
+ workSessions,
28
+ searchWorkSessions
29
+ }: {
30
+ active: boolean
31
+ workSessions: readonly L2WorkSessionListItem[]
32
+ searchWorkSessions: L2WorkbenchBiz['searchWorkSessions']
33
+ }): L2WorkSessionSearch {
34
+ const { t } = useTranslation('workbench')
35
+ const [query, setQuery] = useState('')
36
+ const [searchIn, setSearchIn] = useState<readonly L3PiSessionSearchScope[]>(
37
+ L2_WORKBENCH_DEFAULT_SEARCH_IN
38
+ )
39
+ const request = useCallback(
40
+ (input: L3PiSessionSearchQuery, signal: AbortSignal) => searchWorkSessions(input, signal),
41
+ [searchWorkSessions]
42
+ )
43
+ const search = useL2WorkbenchSessionSearch({
44
+ active: active && query.trim().length > 0,
45
+ scope: workSessions,
46
+ query,
47
+ searchIn,
48
+ request,
49
+ failureMessage: t('sessionSearchFailed')
50
+ })
51
+ return { ...search, query, searchIn, setQuery, setSearchIn }
52
+ }