@pi-harness/pi-harness 0.1.10 → 0.1.12

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 (250) hide show
  1. package/apps/web/dist/assets/index-D6dtMTPb.js +20 -0
  2. package/apps/web/dist/assets/index-De8Rm01Z.css +2 -0
  3. package/apps/web/dist/assets/{react-vendor-BD7-wQo9.js → react-vendor-BxoMtjVy.js} +1 -1
  4. package/apps/web/dist/index.html +3 -3
  5. package/apps/web/package.json +6 -6
  6. package/apps/web/src/style.css +30 -30
  7. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
  8. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  9. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
  10. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  11. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
  12. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  13. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  14. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
  15. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
  16. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
  17. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  18. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
  19. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
  20. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
  21. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
  22. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
  23. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +1 -1
  24. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
  25. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
  26. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
  27. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
  28. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
  29. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
  30. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
  31. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
  32. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
  33. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
  34. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
  35. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  36. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
  37. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  38. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  39. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  40. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  41. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
  42. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  43. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  44. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
  45. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  46. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  47. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
  48. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  49. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  50. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
  51. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
  52. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  53. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
  54. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
  55. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
  56. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  57. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  58. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  59. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  60. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
  61. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  62. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  63. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
  64. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  65. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  66. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
  67. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
  68. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  69. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  70. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  71. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  72. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
  73. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  74. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
  75. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
  76. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  77. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
  78. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  79. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  80. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
  81. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
  82. package/node_modules/@pi-harness/api-gateway/package.json +1 -1
  83. package/node_modules/@pi-harness/cli/package.json +1 -1
  84. package/node_modules/@pi-harness/core/package.json +1 -1
  85. package/node_modules/@pi-harness/host-webserver/package.json +1 -1
  86. package/node_modules/@pi-harness/web-app/package.json +1 -1
  87. package/package.json +8 -7
  88. package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
  89. package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  90. package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
  91. package/packages/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  92. package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
  93. package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  94. package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  95. package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
  96. package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
  97. package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
  98. package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  99. package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
  100. package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
  101. package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
  102. package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
  103. package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
  104. package/packages/api-gateway/dist/marketplace-entries/official/context.json +1 -1
  105. package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
  106. package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
  107. package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
  108. package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
  109. package/packages/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
  110. package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
  111. package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
  112. package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
  113. package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
  114. package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
  115. package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
  116. package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  117. package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
  118. package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  119. package/packages/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  120. package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  121. package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  122. package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
  123. package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  124. package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  125. package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
  126. package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  127. package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  128. package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
  129. package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  130. package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  131. package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
  132. package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
  133. package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  134. package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
  135. package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
  136. package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
  137. package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  138. package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  139. package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  140. package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  141. package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
  142. package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  143. package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  144. package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
  145. package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  146. package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  147. package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
  148. package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
  149. package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  150. package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  151. package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  152. package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  153. package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
  154. package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  155. package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
  156. package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
  157. package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  158. package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
  159. package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  160. package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  161. package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
  162. package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
  163. package/packages/api-gateway/package.json +1 -1
  164. package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +1 -1
  165. package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +1 -1
  166. package/packages/api-gateway/src/marketplace-entries/official/annotation.json +1 -1
  167. package/packages/api-gateway/src/marketplace-entries/official/archify.json +1 -1
  168. package/packages/api-gateway/src/marketplace-entries/official/at-file.json +1 -1
  169. package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +1 -1
  170. package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +1 -1
  171. package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +1 -1
  172. package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +1 -1
  173. package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +1 -1
  174. package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +1 -1
  175. package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +1 -1
  176. package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +1 -1
  177. package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +1 -1
  178. package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +1 -1
  179. package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +1 -1
  180. package/packages/api-gateway/src/marketplace-entries/official/context.json +1 -1
  181. package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +1 -1
  182. package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +1 -1
  183. package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +1 -1
  184. package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +1 -1
  185. package/packages/api-gateway/src/marketplace-entries/official/genui.json +1 -1
  186. package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +1 -1
  187. package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +1 -1
  188. package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +1 -1
  189. package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +1 -1
  190. package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +1 -1
  191. package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +1 -1
  192. package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +1 -1
  193. package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +1 -1
  194. package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +1 -1
  195. package/packages/api-gateway/src/marketplace-entries/official/memory.json +1 -1
  196. package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +1 -1
  197. package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +1 -1
  198. package/packages/api-gateway/src/marketplace-entries/official/modlens.json +1 -1
  199. package/packages/api-gateway/src/marketplace-entries/official/module-search.json +1 -1
  200. package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +1 -1
  201. package/packages/api-gateway/src/marketplace-entries/official/openpets.json +1 -1
  202. package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +1 -1
  203. package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +1 -1
  204. package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +1 -1
  205. package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +1 -1
  206. package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +1 -1
  207. package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +1 -1
  208. package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +1 -1
  209. package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +1 -1
  210. package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +1 -1
  211. package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +1 -1
  212. package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +1 -1
  213. package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +1 -1
  214. package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +1 -1
  215. package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +1 -1
  216. package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +1 -1
  217. package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +1 -1
  218. package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
  219. package/packages/api-gateway/src/marketplace-entries/official/session-export.json +1 -1
  220. package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +1 -1
  221. package/packages/api-gateway/src/marketplace-entries/official/session-search.json +1 -1
  222. package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +1 -1
  223. package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +1 -1
  224. package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +1 -1
  225. package/packages/api-gateway/src/marketplace-entries/official/synapse.json +1 -1
  226. package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +1 -1
  227. package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +1 -1
  228. package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +1 -1
  229. package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +1 -1
  230. package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +1 -1
  231. package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +1 -1
  232. package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +1 -1
  233. package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +1 -1
  234. package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +1 -1
  235. package/packages/api-gateway/src/marketplace-entries/official/web-research.json +1 -1
  236. package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +1 -1
  237. package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +1 -1
  238. package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +1 -1
  239. package/packages/api-gateway/test/release-package.test.ts +1 -0
  240. package/packages/bundle-web-app/package.json +1 -1
  241. package/packages/cli/package.json +1 -1
  242. package/packages/client-web/dist/react-room.d.ts.map +1 -1
  243. package/packages/client-web/dist/react-room.js +199 -59
  244. package/packages/client-web/dist/react-room.js.map +1 -1
  245. package/packages/client-web/package.json +1 -1
  246. package/packages/client-web/src/react-room.tsx +350 -187
  247. package/packages/core/package.json +1 -1
  248. package/packages/host-webserver/package.json +1 -1
  249. package/apps/web/dist/assets/index-CW3u-pEm.css +0 -2
  250. package/apps/web/dist/assets/index-DNYYxKc7.js +0 -20
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { createPortal } from "react-dom";
3
4
  import { createClientApi, failedRefreshLabels, } from "./control-room.js";
4
5
  import { getPromptCompletion, replacePromptCompletion } from "./prompt-completion.js";
5
6
  import { compactThinkingEvents } from "./runtime-events.js";
@@ -356,9 +357,20 @@ function ConfirmDialog({ title, description, target, confirmLabel, busy, onClose
356
357
  onClose();
357
358
  }, children: _jsxs("div", { "aria-label": title, "aria-modal": "true", className: "session-dialog", onClick: (event) => event.stopPropagation(), ref: dialogRef, role: "dialog", tabIndex: -1, children: [_jsxs("header", { className: "session-dialog-header", children: [_jsxs("div", { children: [_jsx("strong", { children: title }), _jsx("small", { children: description })] }), _jsx("button", { "aria-label": "\u5173\u95ED", disabled: busy, onClick: onClose, type: "button", children: "\u00D7" })] }), target && _jsx("div", { className: "session-dialog-target", children: target }), _jsxs("footer", { className: "session-dialog-actions", children: [_jsx("button", { "data-dialog-initial-focus": true, disabled: busy, onClick: onClose, type: "button", children: "\u53D6\u6D88" }), _jsx("button", { className: "danger", disabled: busy, onClick: onConfirm, type: "button", children: busy ? "处理中…" : confirmLabel })] })] }) }));
358
359
  }
359
- function SessionActionMenu({ busy, onRename, onFork, onArchive, onDelete, }) {
360
- return (_jsxs("div", { className: "session-row-menu-popover", onClick: (event) => event.stopPropagation(), children: [_jsx("button", { disabled: busy, onClick: onRename, type: "button", children: "\u91CD\u547D\u540D" }), _jsx("button", { disabled: busy, onClick: onFork, type: "button", children: "\u590D\u5236\u4F1A\u8BDD" }), _jsx("button", { disabled: busy, onClick: onArchive, type: "button", children: "\u5F52\u6863\u4F1A\u8BDD" }), _jsx("button", { className: "danger", disabled: busy, onClick: onDelete, type: "button", children: "\u5220\u9664\u4F1A\u8BDD" })] }));
360
+ function SessionActionMenu({ busy, position, onRename, onFork, onArchive, onDelete, }) {
361
+ return createPortal(_jsxs("div", { className: "session-row-menu-popover", "data-session-popover": true, onClick: (event) => event.stopPropagation(), role: "menu", style: position, children: [_jsx("button", { autoFocus: true, disabled: busy, onClick: onRename, role: "menuitem", type: "button", children: "\u91CD\u547D\u540D" }), _jsx("button", { disabled: busy, onClick: onFork, role: "menuitem", type: "button", children: "\u590D\u5236\u4F1A\u8BDD" }), _jsx("button", { disabled: busy, onClick: onArchive, role: "menuitem", type: "button", children: "\u5F52\u6863\u4F1A\u8BDD" }), _jsx("button", { className: "danger", disabled: busy, onClick: onDelete, role: "menuitem", type: "button", children: "\u5220\u9664\u4F1A\u8BDD" })] }), document.body);
361
362
  }
363
+ const sidebarPopoverPosition = (trigger, width, estimatedHeight, placement) => {
364
+ const rect = trigger.getBoundingClientRect();
365
+ const gutter = 8;
366
+ const spaceOnRight = window.innerWidth - rect.right - gutter;
367
+ const left = spaceOnRight >= width ? rect.right + gutter : Math.max(gutter, rect.left - width - gutter);
368
+ const preferredTop = placement === "below" ? rect.bottom + 6 : rect.top - 4;
369
+ return {
370
+ left: Math.round(left),
371
+ top: Math.round(Math.min(Math.max(gutter, preferredTop), Math.max(gutter, window.innerHeight - estimatedHeight - gutter))),
372
+ };
373
+ };
362
374
  function PromptError({ message }) {
363
375
  const everyApiAuth = /No API key found for everyapi/i.test(message);
364
376
  const requiresAuth = everyApiAuth || /No API key found|authentication|未配置认证/i.test(message);
@@ -1386,7 +1398,7 @@ function PromptCompletionPopover({ kind, commands, files, query, activeIndex, on
1386
1398
  const items = kind === "command"
1387
1399
  ? filterCommands(commands, query).slice(0, 12)
1388
1400
  : files.filter((file) => `${file.path} ${file.label} ${file.status}`.toLowerCase().includes(query.trim().toLowerCase())).slice(0, 12);
1389
- return (_jsxs("div", { "aria-label": kind === "command" ? "命令补全" : "文件补全", className: "prompt-completion", id: "prompt-completion-list", role: "listbox", children: [_jsx("small", { children: kind === "command" ? "命令" : "文件" }), items.length ? (items.slice(0, 12).map((item, index) => {
1401
+ return (_jsxs("div", { "aria-label": kind === "command" ? "命令补全" : "文件补全", className: "prompt-completion", "data-prompt-completion": true, id: "prompt-completion-list", role: "listbox", children: [_jsx("small", { children: kind === "command" ? "命令" : "文件" }), items.length ? (items.slice(0, 12).map((item, index) => {
1390
1402
  const label = kind === "command" ? `/${item.invocationName}` : `@${item.path}`;
1391
1403
  const detail = kind === "command" ? (item.description ?? item.source ?? "由当前运行时注册") : item.status;
1392
1404
  return (_jsxs("button", { "aria-selected": index === activeIndex, id: `prompt-completion-option-${index}`, onClick: () => onUse(label), onMouseEnter: () => onActiveIndexChange(index), role: "option", type: "button", children: [_jsx("strong", { children: label }), _jsx("span", { children: detail })] }, `${kind}:${label}`));
@@ -1490,9 +1502,12 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
1490
1502
  const [commandIndex, setCommandIndex] = useState(0);
1491
1503
  const [sessionMenuOpen, setSessionMenuOpen] = useState(false);
1492
1504
  const [sessionMenuPath, setSessionMenuPath] = useState();
1505
+ const [sessionMenuPosition, setSessionMenuPosition] = useState();
1493
1506
  const [sessionToolsOpen, setSessionToolsOpen] = useState(false);
1507
+ const [sessionToolsPosition, setSessionToolsPosition] = useState();
1494
1508
  const [sessionSelectionMode, setSessionSelectionMode] = useState(false);
1495
1509
  const [sessionDialog, setSessionDialog] = useState();
1510
+ const [sessionActionTarget, setSessionActionTarget] = useState();
1496
1511
  const [sessionNameDraft, setSessionNameDraft] = useState("");
1497
1512
  const [workspaceChooserOpen, setWorkspaceChooserOpen] = useState(false);
1498
1513
  const [workspaceError, setWorkspaceError] = useState("");
@@ -1518,7 +1533,6 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
1518
1533
  const [installedPluginMetadata, setInstalledPluginMetadata] = useState();
1519
1534
  const [marketplacePage, setMarketplacePage] = useState(initialQueryState.marketplacePage);
1520
1535
  const [permission, setPermission] = useState(true);
1521
- const [contextExpanded, setContextExpanded] = useState(false);
1522
1536
  const [promptError, setPromptError] = useState("");
1523
1537
  const [promptBusy, setPromptBusy] = useState(false);
1524
1538
  const [pendingPrompt, setPendingPrompt] = useState("");
@@ -1529,6 +1543,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
1529
1543
  const [sessionHasNext, setSessionHasNext] = useState(false);
1530
1544
  const [selectedSessionPaths, setSelectedSessionPaths] = useState(new Set());
1531
1545
  const importInputRef = useRef(null);
1546
+ const sessionPopoverTriggerRef = useRef(null);
1532
1547
  const [streamingAssistant, setStreamingAssistant] = useState();
1533
1548
  const promptInputRef = useRef(null);
1534
1549
  const chatScrollRef = useRef(null);
@@ -1580,6 +1595,86 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
1580
1595
  useEffect(() => {
1581
1596
  setPromptCompletionIndex(0);
1582
1597
  }, [promptCompletion?.kind, promptCompletion?.query]);
1598
+ useEffect(() => {
1599
+ if (!sessionMenuOpen && !sessionToolsOpen)
1600
+ return;
1601
+ const dismissOnPointerDown = (event) => {
1602
+ if (event.target instanceof Element && event.target.closest("[data-session-popover]"))
1603
+ return;
1604
+ setSessionMenuOpen(false);
1605
+ setSessionMenuPath(undefined);
1606
+ setSessionMenuPosition(undefined);
1607
+ setSessionToolsOpen(false);
1608
+ setSessionToolsPosition(undefined);
1609
+ setSessionActionTarget(undefined);
1610
+ };
1611
+ const dismissOnEscape = (event) => {
1612
+ if (event.key !== "Escape")
1613
+ return;
1614
+ event.preventDefault();
1615
+ event.stopPropagation();
1616
+ setSessionMenuOpen(false);
1617
+ setSessionMenuPath(undefined);
1618
+ setSessionMenuPosition(undefined);
1619
+ setSessionToolsOpen(false);
1620
+ setSessionToolsPosition(undefined);
1621
+ setSessionActionTarget(undefined);
1622
+ sessionPopoverTriggerRef.current?.focus();
1623
+ };
1624
+ const dismissOnViewportChange = () => {
1625
+ setSessionMenuOpen(false);
1626
+ setSessionMenuPath(undefined);
1627
+ setSessionMenuPosition(undefined);
1628
+ setSessionToolsOpen(false);
1629
+ setSessionToolsPosition(undefined);
1630
+ setSessionActionTarget(undefined);
1631
+ };
1632
+ document.addEventListener("pointerdown", dismissOnPointerDown);
1633
+ document.addEventListener("keydown", dismissOnEscape);
1634
+ document.addEventListener("scroll", dismissOnViewportChange, true);
1635
+ window.addEventListener("resize", dismissOnViewportChange);
1636
+ return () => {
1637
+ document.removeEventListener("pointerdown", dismissOnPointerDown);
1638
+ document.removeEventListener("keydown", dismissOnEscape);
1639
+ document.removeEventListener("scroll", dismissOnViewportChange, true);
1640
+ window.removeEventListener("resize", dismissOnViewportChange);
1641
+ };
1642
+ }, [sessionMenuOpen, sessionToolsOpen]);
1643
+ useEffect(() => {
1644
+ if (!commandOpen && !promptCompletionOpen)
1645
+ return;
1646
+ const dismissTransientLists = (event) => {
1647
+ const target = event.target instanceof Element ? event.target : undefined;
1648
+ if (commandOpen && !target?.closest("[data-command-palette]")) {
1649
+ setCommandOpen(false);
1650
+ setCommandQuery("");
1651
+ }
1652
+ if (promptCompletionOpen && !target?.closest("[data-prompt-completion]"))
1653
+ setPromptCompletionSuppressed(true);
1654
+ };
1655
+ document.addEventListener("pointerdown", dismissTransientLists);
1656
+ return () => document.removeEventListener("pointerdown", dismissTransientLists);
1657
+ }, [commandOpen, promptCompletionOpen]);
1658
+ useEffect(() => {
1659
+ const dismissProviderModels = (event) => {
1660
+ if (event instanceof KeyboardEvent && event.key !== "Escape")
1661
+ return;
1662
+ const target = event.target instanceof Element ? event.target : undefined;
1663
+ document.querySelectorAll("details.provider-models-details[open]").forEach((details) => {
1664
+ if (event instanceof PointerEvent && target && details.contains(target))
1665
+ return;
1666
+ details.removeAttribute("open");
1667
+ if (event instanceof KeyboardEvent)
1668
+ details.querySelector("summary")?.focus();
1669
+ });
1670
+ };
1671
+ document.addEventListener("pointerdown", dismissProviderModels);
1672
+ document.addEventListener("keydown", dismissProviderModels);
1673
+ return () => {
1674
+ document.removeEventListener("pointerdown", dismissProviderModels);
1675
+ document.removeEventListener("keydown", dismissProviderModels);
1676
+ };
1677
+ }, []);
1583
1678
  useEffect(() => {
1584
1679
  if (typeof window === "undefined")
1585
1680
  return;
@@ -2024,7 +2119,10 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2024
2119
  setSelectedSessionPaths(new Set());
2025
2120
  setSessionMenuOpen(false);
2026
2121
  setSessionMenuPath(undefined);
2122
+ setSessionMenuPosition(undefined);
2027
2123
  setSessionToolsOpen(false);
2124
+ setSessionToolsPosition(undefined);
2125
+ setSessionActionTarget(undefined);
2028
2126
  setSessionSelectionMode(false);
2029
2127
  setSessionDialog(undefined);
2030
2128
  }
@@ -2046,16 +2144,25 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2046
2144
  return next;
2047
2145
  });
2048
2146
  };
2049
- const openSessionMenu = (path, name) => {
2147
+ const openSessionMenu = (path, name, trigger) => {
2148
+ if (sessionMenuOpen && sessionMenuPath === path) {
2149
+ closeSessionMenu();
2150
+ setSessionActionTarget(undefined);
2151
+ return;
2152
+ }
2050
2153
  setSessionToolsOpen(false);
2051
- setSelectedSessionPath(path);
2154
+ setSessionToolsPosition(undefined);
2155
+ sessionPopoverTriggerRef.current = trigger;
2052
2156
  setSessionNameDraft(name ?? "");
2157
+ setSessionActionTarget({ name: name || "未命名会话", path });
2053
2158
  setSessionMenuPath(path);
2159
+ setSessionMenuPosition(sidebarPopoverPosition(trigger, 142, 190, "beside"));
2054
2160
  setSessionMenuOpen(true);
2055
2161
  };
2056
2162
  const closeSessionMenu = () => {
2057
2163
  setSessionMenuOpen(false);
2058
2164
  setSessionMenuPath(undefined);
2165
+ setSessionMenuPosition(undefined);
2059
2166
  };
2060
2167
  const pushInstalledPluginRoute = (pluginId) => {
2061
2168
  const params = new URLSearchParams(window.location.search);
@@ -2156,7 +2263,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2156
2263
  })) : (_jsx(Workspace, { status: data.status, workspaces: data.workspaces, onCreate: (workspace) => void createNewSession(workspace), onStarter: setDraft, onToml: () => {
2157
2264
  setDetails(undefined);
2158
2265
  setSettings("toml");
2159
- } })), streamingAssistant && data.status?.status === "running" && (_jsxs("article", { className: "turn text streaming-turn", "aria-live": "polite", children: [streamingAssistant.thinking && (_jsxs("details", { className: "reasoning message-reasoning", children: [_jsx("summary", { className: "reasoning-head", children: "\u601D\u8003\u4E2D\u2026" }), _jsx("div", { className: "reasoning-body", children: _jsx(MarkdownMessage, { text: streamingAssistant.thinking }) })] })), !streamingAssistant.thinking && !streamingAssistant.text && _jsx("div", { className: "streaming-placeholder", children: "\u6B63\u5728\u751F\u6210\u2026" }), streamingAssistant.text && _jsx(MarkdownMessage, { onMouseUp: captureAnnotationSelection, text: streamingAssistant.text })] })), pendingPrompt && !data.session?.messages.some((message) => message.role === "user" && messageText(message) === pendingPrompt) && (_jsx("article", { className: "turn user pending-turn", children: _jsx(UserMessageBubble, { text: pendingPrompt }) }))] }), _jsxs("div", { className: "composer-wrap", children: [_jsxs("div", { className: "context-line", children: [_jsx("span", { className: "context-label", children: "\u5B9E\u65F6\u4E0A\u4E0B\u6587" }), _jsxs("div", { className: "context-metrics", children: [_jsxs("span", { children: [_jsx("b", { children: data.status?.messages ?? 0 }), " \u6761\u6D88\u606F"] }), _jsxs("span", { children: [_jsx("b", { children: data.status?.events ?? events.length }), " \u4E2A\u4E8B\u4EF6"] }), _jsx("span", { children: _jsx("b", { children: value(data.status?.model) }) })] }), _jsx("button", { "aria-expanded": contextExpanded, onClick: () => setContextExpanded((current) => !current), type: "button", children: contextExpanded ? "收起" : "展开" })] }), contextExpanded && (_jsxs("div", { className: "context-breakdown", role: "status", children: [_jsxs("span", { children: ["\u6D88\u606F ", _jsx("b", { children: data.status?.messages ?? 0 })] }), _jsxs("span", { children: ["\u8FD0\u884C\u65F6\u4E8B\u4EF6 ", _jsx("b", { children: data.status?.events ?? events.length })] }), _jsxs("span", { children: ["\u6A21\u578B ", _jsx("b", { children: value(data.status?.model) })] })] })), _jsxs("div", { className: "composer-stack", children: [promptError && _jsx(PromptError, { message: promptError }), annotationSelection ? (_jsxs("div", { "aria-label": "\u6DFB\u52A0\u6279\u6CE8", className: "rounded-lg border border-[#cdddf8] bg-[#f6f8ff] px-3 py-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 shrink-0 rounded bg-[#dce9ff] px-1.5 py-0.5 text-[10px] text-[#315fb8]", children: "\u9009\u4E2D\u7247\u6BB5" }), _jsx("p", { className: "max-h-16 flex-1 overflow-auto whitespace-pre-wrap text-[11px] text-[#30343b]", children: annotationSelection }), _jsx("button", { "aria-label": "\u53D6\u6D88\u6279\u6CE8", className: "text-[12px] text-[#687381]", onClick: () => setAnnotationSelection(""), type: "button", children: "\u00D7" })] }), _jsxs("div", { className: "mt-2 flex items-center gap-2", children: [_jsx("input", { "aria-label": "\u6279\u6CE8\u5907\u6CE8", className: "min-w-0 flex-1 rounded-md border border-[#dce5f5] bg-white px-2 py-1.5 text-[11px] outline-none", onChange: (event) => setAnnotationNote(event.target.value), placeholder: "\u5907\u6CE8\uFF08\u53EF\u9009\uFF09", value: annotationNote }), _jsx("button", { className: "rounded-md bg-[#3565c5] px-3 py-1.5 text-[11px] font-medium text-white", onClick: addAnnotation, type: "button", children: "\u52A0\u5165\u6279\u6CE8" })] })] })) : null, annotations.length > 0 ? (_jsxs("div", { className: "flex items-center gap-2 overflow-x-auto text-[10px]", children: [_jsxs("span", { className: "shrink-0 rounded-md bg-[#edf3fe] px-2 py-1 font-medium text-[#315fb8]", children: ["\u6279\u6CE8 \u00D7", annotations.length] }), annotations.map((annotation) => (_jsxs("button", { className: "max-w-48 shrink-0 truncate rounded-md border border-[#dce5f5] bg-white px-2 py-1 text-left text-[#65707b]", onClick: () => setAnnotations((current) => current.filter((item) => item.id !== annotation.id)), title: "\u70B9\u51FB\u79FB\u9664\u6279\u6CE8", type: "button", children: ["#", annotation.id, " ", annotation.quote] }, annotation.id))), _jsx("button", { className: "shrink-0 text-[#687381]", onClick: () => setAnnotations([]), type: "button", children: "\u6E05\u7A7A" })] })) : null, _jsxs("form", { className: "composer", onSubmit: submit, children: [_jsx("textarea", { "aria-activedescendant": promptCompletionOpen ? `prompt-completion-option-${promptCompletionActiveIndex}` : undefined, "aria-autocomplete": "list", "aria-controls": promptCompletionOpen ? "prompt-completion-list" : undefined, "aria-expanded": promptCompletionOpen, "aria-haspopup": "listbox", "aria-label": "Prompt", onChange: (event) => {
2266
+ } })), streamingAssistant && data.status?.status === "running" && (_jsxs("article", { className: "turn text streaming-turn", "aria-live": "polite", children: [streamingAssistant.thinking && (_jsxs("details", { className: "reasoning message-reasoning", children: [_jsx("summary", { className: "reasoning-head", children: "\u601D\u8003\u4E2D\u2026" }), _jsx("div", { className: "reasoning-body", children: _jsx(MarkdownMessage, { text: streamingAssistant.thinking }) })] })), !streamingAssistant.thinking && !streamingAssistant.text && _jsx("div", { className: "streaming-placeholder", children: "\u6B63\u5728\u751F\u6210\u2026" }), streamingAssistant.text && _jsx(MarkdownMessage, { onMouseUp: captureAnnotationSelection, text: streamingAssistant.text })] })), pendingPrompt && !data.session?.messages.some((message) => message.role === "user" && messageText(message) === pendingPrompt) && (_jsx("article", { className: "turn user pending-turn", children: _jsx(UserMessageBubble, { text: pendingPrompt }) }))] }), _jsxs("div", { className: "composer-wrap", children: [_jsx("div", { className: "context-shell", children: _jsxs("div", { className: "context-line", children: [_jsx("span", { className: "context-label", children: "\u5B9E\u65F6\u4E0A\u4E0B\u6587" }), _jsxs("div", { className: "context-metrics", children: [_jsxs("span", { children: [_jsx("b", { children: data.status?.messages ?? 0 }), " \u6761\u6D88\u606F"] }), _jsxs("span", { children: [_jsx("b", { children: data.status?.events ?? events.length }), " \u4E2A\u4E8B\u4EF6"] }), _jsx("span", { children: _jsx("b", { children: value(data.status?.model) }) })] })] }) }), _jsxs("div", { className: "composer-stack", children: [promptError && _jsx(PromptError, { message: promptError }), annotationSelection ? (_jsxs("div", { "aria-label": "\u6DFB\u52A0\u6279\u6CE8", className: "rounded-lg border border-[#cdddf8] bg-[#f6f8ff] px-3 py-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 shrink-0 rounded bg-[#dce9ff] px-1.5 py-0.5 text-[10px] text-[#315fb8]", children: "\u9009\u4E2D\u7247\u6BB5" }), _jsx("p", { className: "max-h-16 flex-1 overflow-auto whitespace-pre-wrap text-[11px] text-[#30343b]", children: annotationSelection }), _jsx("button", { "aria-label": "\u53D6\u6D88\u6279\u6CE8", className: "text-[12px] text-[#687381]", onClick: () => setAnnotationSelection(""), type: "button", children: "\u00D7" })] }), _jsxs("div", { className: "mt-2 flex items-center gap-2", children: [_jsx("input", { "aria-label": "\u6279\u6CE8\u5907\u6CE8", className: "min-w-0 flex-1 rounded-md border border-[#dce5f5] bg-white px-2 py-1.5 text-[11px] outline-none", onChange: (event) => setAnnotationNote(event.target.value), placeholder: "\u5907\u6CE8\uFF08\u53EF\u9009\uFF09", value: annotationNote }), _jsx("button", { className: "rounded-md bg-[#3565c5] px-3 py-1.5 text-[11px] font-medium text-white", onClick: addAnnotation, type: "button", children: "\u52A0\u5165\u6279\u6CE8" })] })] })) : null, annotations.length > 0 ? (_jsxs("div", { className: "flex items-center gap-2 overflow-x-auto text-[10px]", children: [_jsxs("span", { className: "shrink-0 rounded-md bg-[#edf3fe] px-2 py-1 font-medium text-[#315fb8]", children: ["\u6279\u6CE8 \u00D7", annotations.length] }), annotations.map((annotation) => (_jsxs("button", { className: "max-w-48 shrink-0 truncate rounded-md border border-[#dce5f5] bg-white px-2 py-1 text-left text-[#65707b]", onClick: () => setAnnotations((current) => current.filter((item) => item.id !== annotation.id)), title: "\u70B9\u51FB\u79FB\u9664\u6279\u6CE8", type: "button", children: ["#", annotation.id, " ", annotation.quote] }, annotation.id))), _jsx("button", { className: "shrink-0 text-[#687381]", onClick: () => setAnnotations([]), type: "button", children: "\u6E05\u7A7A" })] })) : null, _jsxs("form", { className: "composer", onSubmit: submit, children: [_jsx("textarea", { "aria-activedescendant": promptCompletionOpen ? `prompt-completion-option-${promptCompletionActiveIndex}` : undefined, "aria-autocomplete": "list", "aria-controls": promptCompletionOpen ? "prompt-completion-list" : undefined, "aria-expanded": promptCompletionOpen, "aria-haspopup": "listbox", "aria-label": "Prompt", onChange: (event) => {
2160
2267
  setDraft(event.target.value);
2161
2268
  setPromptCaret(event.currentTarget.selectionStart ?? event.target.value.length);
2162
2269
  setPromptCompletionSuppressed(false);
@@ -2212,7 +2319,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2212
2319
  event.currentTarget.blur();
2213
2320
  setWorkspaceChooserOpen(true);
2214
2321
  }
2215
- }, placeholder: workspaceReady ? "描述要做的改动,⌘↵ 发送;@ 引用文件,/ 调用命令" : "先选择工作区,再描述要做的改动", readOnly: !workspaceReady, ref: promptInputRef, rows: 2, value: draft }), promptCompletionOpen && promptCompletion && (_jsx(PromptCompletionPopover, { activeIndex: promptCompletionActiveIndex, commands: data.commands, files: data.files, kind: promptCompletion.kind, onActiveIndexChange: setPromptCompletionIndex, onUse: (value) => {
2322
+ }, placeholder: workspaceReady ? "描述要做的改动,⌘↵ 发送;@ 引用文件,/ 调用命令" : "先选择工作区,再描述要做的改动", readOnly: !workspaceReady, ref: promptInputRef, rows: 2, "data-prompt-completion": true, value: draft }), promptCompletionOpen && promptCompletion && (_jsx(PromptCompletionPopover, { activeIndex: promptCompletionActiveIndex, commands: data.commands, files: data.files, kind: promptCompletion.kind, onActiveIndexChange: setPromptCompletionIndex, onUse: (value) => {
2216
2323
  const replacement = replacePromptCompletion(draft, promptCompletion, `${value} `);
2217
2324
  setDraft(replacement.text);
2218
2325
  setPromptCaret(replacement.caret);
@@ -2263,7 +2370,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2263
2370
  setCommandOpen(false);
2264
2371
  setCommandQuery("");
2265
2372
  };
2266
- return (_jsxs("div", { className: "app-frame", "data-theme": activeTheme, style: themeStyle, children: [_jsxs("aside", { className: "sidebar", children: [_jsxs("header", { className: "brand-row", children: [_jsx("span", { className: "pi-mark", "aria-hidden": "true", children: _jsx("img", { src: "/icons/svg/mark-white.svg", alt: "" }) }), _jsx("strong", { children: "pi harness" }), appVersion ? _jsx("span", { className: "version", children: appVersion }) : null] }), _jsxs("div", { className: "sidebar-actions", children: [_jsx("button", { className: "new-session", onClick: beginNewSession, type: "button", "aria-expanded": workspaceChooserOpen, children: "\uFF0B \u65B0\u5EFA\u4F1A\u8BDD" }), _jsxs("div", { className: "session-search", children: [_jsx("input", { "aria-controls": commandOpen ? "command-menu" : undefined, "aria-expanded": commandOpen, "aria-label": commandOpen ? "搜索命令" : "搜索会话", onChange: (event) => {
2373
+ return (_jsxs("div", { className: "app-frame", "data-theme": activeTheme, style: themeStyle, children: [_jsxs("aside", { className: "sidebar", children: [_jsxs("header", { className: "brand-row", children: [_jsx("span", { className: "pi-mark", "aria-hidden": "true", children: _jsx("img", { src: "/icons/svg/mark-white.svg", alt: "" }) }), _jsx("strong", { children: "pi harness" }), appVersion ? _jsx("span", { className: "version", children: appVersion }) : null] }), _jsxs("div", { className: "sidebar-actions", children: [_jsx("button", { className: "new-session", onClick: beginNewSession, type: "button", "aria-expanded": workspaceChooserOpen, children: "\uFF0B \u65B0\u5EFA\u4F1A\u8BDD" }), _jsxs("div", { className: "session-search", "data-command-palette": true, children: [_jsx("input", { "aria-controls": commandOpen ? "command-menu" : undefined, "aria-expanded": commandOpen, "aria-label": commandOpen ? "搜索命令" : "搜索会话", onChange: (event) => {
2267
2374
  const next = event.target.value;
2268
2375
  if (!commandOpen && next.startsWith("/")) {
2269
2376
  setCommandOpen(true);
@@ -2304,25 +2411,42 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2304
2411
  setSelectedSessionPaths(new Set());
2305
2412
  setSessionToolsOpen(false);
2306
2413
  closeSessionMenu();
2307
- }, type: "button", children: sessionSelectionMode ? "完成" : "选择" }), _jsxs("div", { className: "session-tools-wrap", children: [_jsx("button", { "aria-expanded": sessionToolsOpen, "aria-label": "\u4F1A\u8BDD\u5DE5\u5177", className: "session-tool-button icon", onClick: () => {
2414
+ }, type: "button", children: sessionSelectionMode ? "完成" : "选择" }), _jsxs("div", { className: "session-tools-wrap", "data-session-popover": true, children: [_jsx("button", { "aria-expanded": sessionToolsOpen, "aria-haspopup": "menu", "aria-label": "\u4F1A\u8BDD\u5DE5\u5177", className: "session-tool-button icon", onClick: (event) => {
2308
2415
  closeSessionMenu();
2309
- setSessionToolsOpen((current) => !current);
2310
- }, type: "button", children: "\u22EF" }), sessionToolsOpen && (_jsxs("div", { className: "session-tools-popover", children: [_jsx("button", { onClick: () => window.location.reload(), type: "button", children: "\u5237\u65B0\u5217\u8868" }), _jsx("button", { onClick: () => importInputRef.current?.click(), type: "button", children: "\u5BFC\u5165\u4F1A\u8BDD" }), _jsx("button", { disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2311
- if (!activeSessionPath)
2312
- return;
2313
- void sessionAction(async () => {
2314
- const blob = await api.exportSession(activeSessionPath);
2315
- const link = document.createElement("a");
2316
- link.href = URL.createObjectURL(blob);
2317
- link.download = `${data.session?.sessionId ?? "session"}.jsonl`;
2318
- link.click();
2319
- URL.revokeObjectURL(link.href);
2320
- });
2321
- }, type: "button", children: "\u5BFC\u51FA\u5F53\u524D\u4F1A\u8BDD" }), _jsx("button", { onClick: () => {
2322
- setIncludeArchivedSessions((current) => !current);
2323
- setSessionToolsOpen(false);
2324
- void refresh();
2325
- }, type: "button", children: includeArchivedSessions ? "隐藏归档会话" : "显示归档会话" })] }))] })] })] }), sessionSelectionMode && selectedSessionPaths.size > 0 && (_jsxs("div", { className: "session-batch-bar", children: [_jsxs("span", { children: [selectedSessionPaths.size, " \u4E2A\u5DF2\u9009\u62E9"] }), _jsx("button", { onClick: () => void sessionAction(() => api.batchSessions("archive", [...selectedSessionPaths]).then(() => undefined)), type: "button", children: "\u5F52\u6863" }), _jsx("button", { onClick: () => void sessionAction(() => api.batchSessions("pin", [...selectedSessionPaths]).then(() => undefined)), type: "button", children: "\u7F6E\u9876" }), _jsx("button", { className: "danger", onClick: () => {
2416
+ sessionPopoverTriggerRef.current = event.currentTarget;
2417
+ setSessionActionTarget(undefined);
2418
+ if (sessionToolsOpen) {
2419
+ setSessionToolsOpen(false);
2420
+ setSessionToolsPosition(undefined);
2421
+ }
2422
+ else {
2423
+ setSessionToolsPosition(sidebarPopoverPosition(event.currentTarget, 150, 190, "below"));
2424
+ setSessionToolsOpen(true);
2425
+ }
2426
+ }, type: "button", children: "\u22EF" }), sessionToolsOpen &&
2427
+ sessionToolsPosition &&
2428
+ createPortal(_jsxs("div", { className: "session-tools-popover", "data-session-popover": true, role: "menu", style: sessionToolsPosition, children: [_jsx("button", { autoFocus: true, onClick: () => window.location.reload(), role: "menuitem", type: "button", children: "\u5237\u65B0\u5217\u8868" }), _jsx("button", { onClick: () => {
2429
+ setSessionToolsOpen(false);
2430
+ setSessionToolsPosition(undefined);
2431
+ importInputRef.current?.click();
2432
+ }, role: "menuitem", type: "button", children: "\u5BFC\u5165\u4F1A\u8BDD" }), _jsx("button", { disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2433
+ if (!activeSessionPath)
2434
+ return;
2435
+ void sessionAction(async () => {
2436
+ const blob = await api.exportSession(activeSessionPath);
2437
+ const link = document.createElement("a");
2438
+ link.href = URL.createObjectURL(blob);
2439
+ link.download = `${data.session?.sessionId ?? "session"}.jsonl`;
2440
+ link.click();
2441
+ URL.revokeObjectURL(link.href);
2442
+ });
2443
+ }, role: "menuitem", type: "button", children: "\u5BFC\u51FA\u5F53\u524D\u4F1A\u8BDD" }), _jsx("button", { onClick: () => {
2444
+ setIncludeArchivedSessions((current) => !current);
2445
+ setSessionToolsOpen(false);
2446
+ setSessionToolsPosition(undefined);
2447
+ void refresh();
2448
+ }, role: "menuitem", type: "button", children: includeArchivedSessions ? "隐藏归档会话" : "显示归档会话" })] }), document.body)] })] })] }), sessionSelectionMode && selectedSessionPaths.size > 0 && (_jsxs("div", { className: "session-batch-bar", children: [_jsxs("span", { children: [selectedSessionPaths.size, " \u4E2A\u5DF2\u9009\u62E9"] }), _jsx("button", { onClick: () => void sessionAction(() => api.batchSessions("archive", [...selectedSessionPaths]).then(() => undefined)), type: "button", children: "\u5F52\u6863" }), _jsx("button", { onClick: () => void sessionAction(() => api.batchSessions("pin", [...selectedSessionPaths]).then(() => undefined)), type: "button", children: "\u7F6E\u9876" }), _jsx("button", { className: "danger", onClick: () => {
2449
+ setSessionActionTarget(undefined);
2326
2450
  setSessionDialog("batch-delete");
2327
2451
  }, type: "button", children: "\u5220\u9664" })] })), _jsxs("div", { className: "sidebar-scroll", children: [showCurrentSession && data.session && (_jsxs("div", { className: "session-group", children: [_jsx("div", { className: "group-label", children: "\u5F53\u524D" }), _jsxs("div", { className: "session-row-wrap current-session-row", children: [sessionSelectionMode && (_jsx("input", { "aria-label": "\u9009\u62E9\u5F53\u524D\u4F1A\u8BDD", checked: activeSessionPath ? selectedSessionPaths.has(activeSessionPath) : false, onChange: () => activeSessionPath && toggleSessionSelection(activeSessionPath), type: "checkbox" })), _jsxs("button", { className: "session-row active", onClick: () => {
2328
2452
  setSettings(undefined);
@@ -2333,7 +2457,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2333
2457
  setDetails(undefined);
2334
2458
  setSessionMenuOpen(false);
2335
2459
  void refresh();
2336
- }, type: "button", children: [_jsx("span", { className: "session-dot ok" }), _jsxs("span", { className: "session-copy", children: [_jsx("strong", { children: data.session.messages.length ? data.session.sessionId.slice(0, 12) : "新会话" }), _jsxs("small", { children: [data.session.messages.length, " \u6761\u6D88\u606F"] })] })] }), !sessionSelectionMode && activeSessionPath && (_jsx("button", { "aria-label": "\u5F53\u524D\u4F1A\u8BDD\u64CD\u4F5C", className: "session-row-more", onClick: () => openSessionMenu(activeSessionPath, data.session?.messages.length ? data.session?.sessionId.slice(0, 12) : "新会话"), type: "button", children: "\u22EF" })), !sessionSelectionMode && activeSessionPath && sessionMenuPath === activeSessionPath && sessionMenuOpen && (_jsx(SessionActionMenu, { busy: sessionActionBusy, onArchive: () => {
2460
+ }, type: "button", children: [_jsx("span", { className: "session-dot ok" }), _jsxs("span", { className: "session-copy", children: [_jsx("strong", { children: data.session.messages.length ? data.session.sessionId.slice(0, 12) : "新会话" }), _jsxs("small", { children: [data.session.messages.length, " \u6761\u6D88\u606F"] })] })] }), !sessionSelectionMode && activeSessionPath && (_jsx("button", { "aria-expanded": sessionMenuOpen && sessionMenuPath === activeSessionPath, "aria-haspopup": "menu", "aria-label": "\u5F53\u524D\u4F1A\u8BDD\u64CD\u4F5C", className: "session-row-more", "data-session-popover": true, onClick: (event) => openSessionMenu(activeSessionPath, data.session?.messages.length ? data.session?.sessionId.slice(0, 12) : "新会话", event.currentTarget), type: "button", children: "\u22EF" })), !sessionSelectionMode && activeSessionPath && sessionMenuPath === activeSessionPath && sessionMenuOpen && sessionMenuPosition && (_jsx(SessionActionMenu, { busy: sessionActionBusy, position: sessionMenuPosition, onArchive: () => {
2337
2461
  closeSessionMenu();
2338
2462
  setSessionDialog("archive");
2339
2463
  }, onDelete: () => {
@@ -2351,10 +2475,14 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2351
2475
  } }))] })] })), groups.length ? (groups.map(([label, sessions]) => (_jsxs("div", { className: "session-group", children: [_jsx("div", { className: "group-label", children: label }), sessions.map((session, index) => (_jsxs("div", { className: "session-row-wrap", children: [sessionSelectionMode && (_jsx("input", { "aria-label": `选择会话 ${value(session.name ?? session.firstMessage, "未命名会话")}`, checked: typeof session.path === "string" && selectedSessionPaths.has(session.path), onChange: () => {
2352
2476
  if (typeof session.path === "string")
2353
2477
  toggleSessionSelection(session.path);
2354
- }, type: "checkbox" })), _jsxs("button", { className: `session-row ${session.sessionId === data.session?.sessionId ? "active" : ""}`, onClick: () => openSession(session), type: "button", children: [_jsx("span", { className: "session-dot ok" }), _jsxs("span", { className: "session-copy", children: [_jsx("strong", { children: value(session.name ?? session.firstMessage, "未命名会话") }), _jsxs("small", { children: [value(session.messageCount, "0"), " \u6761\u6D88\u606F", session.pinned === true ? " · 已置顶" : "", session.archived === true ? " · 已归档" : ""] })] })] }), !sessionSelectionMode && typeof session.path === "string" && (_jsx("button", { "aria-label": `会话操作 ${value(session.name ?? session.firstMessage, "未命名会话")}`, className: "session-row-more", onClick: (event) => {
2478
+ }, type: "checkbox" })), _jsxs("button", { className: `session-row ${session.sessionId === data.session?.sessionId ? "active" : ""}`, onClick: () => openSession(session), type: "button", children: [_jsx("span", { className: "session-dot ok" }), _jsxs("span", { className: "session-copy", children: [_jsx("strong", { children: value(session.name ?? session.firstMessage, "未命名会话") }), _jsxs("small", { children: [value(session.messageCount, "0"), " \u6761\u6D88\u606F", session.pinned === true ? " · 已置顶" : "", session.archived === true ? " · 已归档" : ""] })] })] }), !sessionSelectionMode && typeof session.path === "string" && (_jsx("button", { "aria-expanded": sessionMenuOpen && sessionMenuPath === session.path, "aria-haspopup": "menu", "aria-label": `会话操作 ${value(session.name ?? session.firstMessage, "未命名会话")}`, className: "session-row-more", "data-session-popover": true, onClick: (event) => {
2355
2479
  event.stopPropagation();
2356
- openSessionMenu(session.path, value(session.name ?? session.firstMessage, ""));
2357
- }, type: "button", children: "\u22EF" })), !sessionSelectionMode && typeof session.path === "string" && sessionMenuPath === session.path && sessionMenuOpen && (_jsx(SessionActionMenu, { busy: sessionActionBusy, onArchive: () => {
2480
+ openSessionMenu(session.path, value(session.name ?? session.firstMessage, ""), event.currentTarget);
2481
+ }, type: "button", children: "\u22EF" })), !sessionSelectionMode &&
2482
+ typeof session.path === "string" &&
2483
+ sessionMenuPath === session.path &&
2484
+ sessionMenuOpen &&
2485
+ sessionMenuPosition && (_jsx(SessionActionMenu, { busy: sessionActionBusy, position: sessionMenuPosition, onArchive: () => {
2358
2486
  closeSessionMenu();
2359
2487
  setSessionDialog("archive");
2360
2488
  }, onDelete: () => {
@@ -2384,7 +2512,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2384
2512
  setSessionMenuPath(undefined);
2385
2513
  setDetails(undefined);
2386
2514
  setSettings("general");
2387
- }, title: "\u8BBE\u7F6E", type: "button", children: ["\u2699 ", _jsx("span", { children: "\u8BBE\u7F6E" })] })] })] }), _jsxs("section", { className: "main-pane", children: [_jsxs("header", { className: "main-header", children: [_jsxs("div", { className: "active-heading", children: [_jsx("strong", { children: settings
2515
+ }, title: "\u8BBE\u7F6E", type: "button", children: ["\u2699 ", _jsx("span", { children: "\u8BBE\u7F6E" })] })] })] }), _jsxs("section", { className: "main-pane", children: [_jsxs("header", { className: `main-header ${!settings && page === "session" ? "session-track" : ""}`, children: [_jsxs("div", { className: "active-heading", children: [_jsx("strong", { children: settings
2388
2516
  ? "设置"
2389
2517
  : page === "plugins"
2390
2518
  ? installedPluginId
@@ -2415,41 +2543,53 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
2415
2543
  }, type: "button", children: "\u505C\u6B62" })] })), !settings && page === "session" && (_jsx("div", { "aria-label": "\u4F1A\u8BDD\u89C6\u56FE", className: "view-tabs", children: ["chat", "trajectory", "files"].map((item) => (_jsx("button", { "aria-pressed": view === item, className: `view-tab ${view === item ? "active" : ""}`, onClick: () => {
2416
2544
  setView(item);
2417
2545
  setDetails(undefined);
2418
- }, type: "button", children: item === "chat" ? "对话" : item === "trajectory" ? "轨迹" : "产出" }, item))) })), !settings && page === "session" && _jsx("span", { "aria-hidden": "true", className: "header-divider" }), !settings && page === "session" && (_jsxs(_Fragment, { children: [_jsx("button", { className: "session-menu", onClick: () => {
2419
- setSessionMenuPath(undefined);
2420
- setSessionMenuOpen((current) => !current);
2421
- }, type: "button", "aria-label": "\u4F1A\u8BDD\u64CD\u4F5C", children: "\u22EF" }), _jsxs("button", { "aria-label": details !== undefined ? "关闭详情" : "打开详情", "aria-pressed": details !== undefined, className: "details-toggle", onClick: () => setDetails(details ? undefined : {}), type: "button", children: [_jsx("span", { "aria-hidden": "true", children: "\u25E8" }), " ", _jsx("span", { className: "details-toggle-label", children: "\u8BE6\u60C5" })] })] })), !settings && page === "session" && sessionMenuOpen && !sessionMenuPath && (_jsxs("div", { className: "session-menu-popover compact-session-menu", children: [_jsxs("button", { className: "session-action", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2422
- setSessionNameDraft(data.session?.sessionId?.slice(0, 12) ?? "");
2423
- setSessionDialog("rename");
2424
- setSessionMenuOpen(false);
2425
- }, type: "button", children: [_jsx("strong", { children: "\u91CD\u547D\u540D" }), _jsx("small", { children: "\u8BBE\u7F6E\u4E00\u4E2A\u5BB9\u6613\u8BC6\u522B\u7684\u540D\u79F0" })] }), _jsxs("button", { className: "session-action", disabled: !activeSessionPath || sessionActionBusy, onClick: () => void sessionAction(async () => {
2426
- const result = await api.forkSession(activeSessionPath);
2427
- if (result.sessionFile) {
2428
- setSelectedSessionPath(result.sessionFile);
2429
- await api.openSession(result.sessionFile);
2430
- }
2431
- }), type: "button", children: [_jsx("strong", { children: "\u590D\u5236\u4F1A\u8BDD" }), _jsx("small", { children: "\u590D\u5236\u4E0A\u4E0B\u6587\u5E76\u6253\u5F00\u526F\u672C" })] }), _jsxs("button", { className: "session-action", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2432
- setSessionMenuOpen(false);
2433
- setSessionDialog("archive");
2434
- }, type: "button", children: [_jsx("strong", { children: "\u5F52\u6863\u4F1A\u8BDD" }), _jsx("small", { children: "\u4ECE\u9ED8\u8BA4\u5217\u8868\u9690\u85CF" })] }), _jsxs("button", { className: "session-action danger", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2435
- setSessionMenuOpen(false);
2436
- setSessionDialog("delete");
2437
- }, type: "button", children: [_jsx("strong", { children: "\u5220\u9664\u4F1A\u8BDD" }), _jsx("small", { children: "\u6C38\u4E45\u5220\u9664\u672C\u5730\u8BB0\u5F55" })] })] }))] }), refreshIssues.length > 0 && (_jsxs("div", { "aria-live": "polite", className: "refresh-warning", role: "status", children: [_jsxs("span", { children: [_jsx("strong", { children: "\u90E8\u5206\u6570\u636E\u5237\u65B0\u5931\u8D25" }), refreshIssues.join("、"), "\u53EF\u80FD\u4E3A\u7A7A\u6216\u663E\u793A\u4E0A\u6B21\u7ED3\u679C\u3002"] }), _jsx("button", { onClick: () => void refresh(), type: "button", children: "\u91CD\u8BD5" })] })), _jsx("div", { className: "view-host", children: initialRefreshPending ? (_jsxs("div", { "aria-live": "polite", className: "initial-loading", role: "status", children: [_jsx("span", { "aria-hidden": "true" }), "\u6B63\u5728\u8FDE\u63A5 Pi runtime\u2026"] })) : (content) })] }), !settings && page === "session" && details !== undefined && (_jsxs(_Fragment, { children: [_jsx("button", { "aria-label": "\u5173\u95ED\u8BE6\u60C5", className: "details-backdrop", onClick: () => setDetails(undefined), type: "button" }), _jsx(Details, { event: Object.keys(details).length ? details : undefined, onClose: () => setDetails(undefined), onCopy: () => void navigator.clipboard?.writeText(JSON.stringify(details, null, 2)) })] })), globalSearchOpen && (_jsx(GlobalSearch, { commands: data.commands, files: data.files, onClose: () => setGlobalSearchOpen(false), onOpenFile: (file) => {
2546
+ }, type: "button", children: item === "chat" ? "对话" : item === "trajectory" ? "轨迹" : "产出" }, item))) })), !settings && page === "session" && _jsx("span", { "aria-hidden": "true", className: "header-divider" }), !settings && page === "session" && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "session-menu-wrap", "data-session-popover": true, children: [_jsx("button", { "aria-expanded": sessionMenuOpen && !sessionMenuPath, "aria-haspopup": "menu", className: "session-menu", onClick: (event) => {
2547
+ const closeCurrentMenu = sessionMenuOpen && !sessionMenuPath;
2548
+ setSessionMenuPath(undefined);
2549
+ setSessionMenuPosition(undefined);
2550
+ sessionPopoverTriggerRef.current = event.currentTarget;
2551
+ setSessionActionTarget(!closeCurrentMenu && activeSessionPath
2552
+ ? { name: data.session?.sessionId?.slice(0, 12) || "当前会话", path: activeSessionPath }
2553
+ : undefined);
2554
+ setSessionMenuOpen(!closeCurrentMenu);
2555
+ }, type: "button", "aria-label": "\u4F1A\u8BDD\u64CD\u4F5C", children: "\u22EF" }), sessionMenuOpen && !sessionMenuPath && (_jsxs("div", { className: "session-menu-popover compact-session-menu", role: "menu", children: [_jsxs("button", { className: "session-action", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2556
+ setSessionNameDraft(data.session?.sessionId?.slice(0, 12) ?? "");
2557
+ setSessionDialog("rename");
2558
+ setSessionMenuOpen(false);
2559
+ }, role: "menuitem", type: "button", children: [_jsx("strong", { children: "\u91CD\u547D\u540D" }), _jsx("small", { children: "\u8BBE\u7F6E\u4E00\u4E2A\u5BB9\u6613\u8BC6\u522B\u7684\u540D\u79F0" })] }), _jsxs("button", { className: "session-action", disabled: !activeSessionPath || sessionActionBusy, onClick: () => void sessionAction(async () => {
2560
+ const result = await api.forkSession(activeSessionPath);
2561
+ if (result.sessionFile) {
2562
+ setSelectedSessionPath(result.sessionFile);
2563
+ await api.openSession(result.sessionFile);
2564
+ }
2565
+ }), role: "menuitem", type: "button", children: [_jsx("strong", { children: "\u590D\u5236\u4F1A\u8BDD" }), _jsx("small", { children: "\u590D\u5236\u4E0A\u4E0B\u6587\u5E76\u6253\u5F00\u526F\u672C" })] }), _jsxs("button", { className: "session-action", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2566
+ setSessionMenuOpen(false);
2567
+ setSessionDialog("archive");
2568
+ }, role: "menuitem", type: "button", children: [_jsx("strong", { children: "\u5F52\u6863\u4F1A\u8BDD" }), _jsx("small", { children: "\u4ECE\u9ED8\u8BA4\u5217\u8868\u9690\u85CF" })] }), _jsxs("button", { className: "session-action danger", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
2569
+ setSessionMenuOpen(false);
2570
+ setSessionDialog("delete");
2571
+ }, role: "menuitem", type: "button", children: [_jsx("strong", { children: "\u5220\u9664\u4F1A\u8BDD" }), _jsx("small", { children: "\u6C38\u4E45\u5220\u9664\u672C\u5730\u8BB0\u5F55" })] })] }))] }), _jsxs("button", { "aria-label": details !== undefined ? "关闭详情" : "打开详情", "aria-pressed": details !== undefined, className: "details-toggle", onClick: () => setDetails(details ? undefined : {}), type: "button", children: [_jsx("span", { "aria-hidden": "true", children: "\u25E8" }), " ", _jsx("span", { className: "details-toggle-label", children: "\u8BE6\u60C5" })] })] }))] }), refreshIssues.length > 0 && (_jsxs("div", { "aria-live": "polite", className: "refresh-warning", role: "status", children: [_jsxs("span", { children: [_jsx("strong", { children: "\u90E8\u5206\u6570\u636E\u5237\u65B0\u5931\u8D25" }), refreshIssues.join("、"), "\u53EF\u80FD\u4E3A\u7A7A\u6216\u663E\u793A\u4E0A\u6B21\u7ED3\u679C\u3002"] }), _jsx("button", { onClick: () => void refresh(), type: "button", children: "\u91CD\u8BD5" })] })), _jsx("div", { className: "view-host", children: initialRefreshPending ? (_jsxs("div", { "aria-live": "polite", className: "initial-loading", role: "status", children: [_jsx("span", { "aria-hidden": "true" }), "\u6B63\u5728\u8FDE\u63A5 Pi runtime\u2026"] })) : (content) })] }), !settings && page === "session" && details !== undefined && (_jsxs(_Fragment, { children: [_jsx("button", { "aria-label": "\u5173\u95ED\u8BE6\u60C5", className: "details-backdrop", onClick: () => setDetails(undefined), type: "button" }), _jsx(Details, { event: Object.keys(details).length ? details : undefined, onClose: () => setDetails(undefined), onCopy: () => void navigator.clipboard?.writeText(JSON.stringify(details, null, 2)) })] })), globalSearchOpen && (_jsx(GlobalSearch, { commands: data.commands, files: data.files, onClose: () => setGlobalSearchOpen(false), onOpenFile: (file) => {
2438
2572
  setPage("session");
2439
2573
  setView("files");
2440
2574
  setDetails({ type: "file", path: file.path, status: file.status });
2441
- }, onOpenSession: openSession, onUse: setDraft, sessions: data.sessions })), workspaceChooserOpen && (_jsx(WorkspaceChooser, { error: workspaceError, onClose: () => setWorkspaceChooserOpen(false), onPickDirectory: openDirectory, onSelect: (workspace) => void createNewSession(workspace), workspaces: data.workspaces })), sessionDialog && (_jsx(SessionDialog, { busy: sessionActionBusy, count: sessionDialog === "batch-delete" ? selectedSessionPaths.size : undefined, kind: sessionDialog, name: sessionDialog === "rename" ? undefined : value(data.session?.sessionId, "当前会话"), onChange: setSessionNameDraft, onClose: () => setSessionDialog(undefined), onConfirm: () => {
2442
- if (sessionDialog === "rename" && activeSessionPath) {
2443
- void sessionAction(() => api.renameSession(activeSessionPath, sessionNameDraft.trim()).then(() => undefined));
2575
+ }, onOpenSession: openSession, onUse: setDraft, sessions: data.sessions })), workspaceChooserOpen && (_jsx(WorkspaceChooser, { error: workspaceError, onClose: () => setWorkspaceChooserOpen(false), onPickDirectory: openDirectory, onSelect: (workspace) => void createNewSession(workspace), workspaces: data.workspaces })), sessionDialog && (_jsx(SessionDialog, { busy: sessionActionBusy, count: sessionDialog === "batch-delete" ? selectedSessionPaths.size : undefined, kind: sessionDialog, name: sessionDialog === "rename" || sessionDialog === "batch-delete"
2576
+ ? undefined
2577
+ : (sessionActionTarget?.name ?? value(data.session?.sessionId, "当前会话")), onChange: setSessionNameDraft, onClose: () => {
2578
+ setSessionDialog(undefined);
2579
+ setSessionActionTarget(undefined);
2580
+ }, onConfirm: () => {
2581
+ const targetPath = sessionActionTarget?.path ?? activeSessionPath;
2582
+ if (sessionDialog === "rename" && targetPath) {
2583
+ void sessionAction(() => api.renameSession(targetPath, sessionNameDraft.trim()).then(() => undefined));
2444
2584
  }
2445
- else if (sessionDialog === "archive" && activeSessionPath) {
2585
+ else if (sessionDialog === "archive" && targetPath) {
2446
2586
  void sessionAction(async () => {
2447
- await api.setSessionMetadata(activeSessionPath, { archived: true });
2587
+ await api.setSessionMetadata(targetPath, { archived: true });
2448
2588
  });
2449
2589
  }
2450
- else if (sessionDialog === "delete" && activeSessionPath) {
2590
+ else if (sessionDialog === "delete" && targetPath) {
2451
2591
  void sessionAction(async () => {
2452
- await api.deleteSession(activeSessionPath);
2592
+ await api.deleteSession(targetPath);
2453
2593
  });
2454
2594
  }
2455
2595
  else if (sessionDialog === "batch-delete") {