@baique/pi-web-sky 0.1.55 → 0.1.56

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 (361) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +8 -4
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +2 -2
  5. package/.next/react-loadable-manifest.json +2 -2
  6. package/.next/required-server-files.js +1 -1
  7. package/.next/required-server-files.json +1 -1
  8. package/.next/routes-manifest.json +28 -0
  9. package/.next/server/app/_global-error/page.js +2 -2
  10. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/.next/server/app/_global-error.html +1 -1
  12. package/.next/server/app/_global-error.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/.next/server/app/_not-found/page.js +1 -1
  17. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +4 -3
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +4 -3
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +4 -3
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +3 -2
  23. package/.next/server/app/api/agent/[id]/bash-output/route.js +2 -2
  24. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  25. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
  26. package/.next/server/app/api/agent/[id]/route.js +1 -1
  27. package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
  28. package/.next/server/app/api/agent/new/route.js +1 -1
  29. package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
  30. package/.next/server/app/api/agent/running/route.js +1 -1
  31. package/.next/server/app/api/agent/running/route.js.nft.json +1 -1
  32. package/.next/server/app/api/app-update/route.js +1 -1
  33. package/.next/server/app/api/auth/all-providers/route.js +1 -1
  34. package/.next/server/app/api/auth/api-key/[provider]/route.js +1 -1
  35. package/.next/server/app/api/auth/login/[provider]/route.js +1 -1
  36. package/.next/server/app/api/auth/logout/[provider]/route.js +1 -1
  37. package/.next/server/app/api/auth/providers/route.js +1 -1
  38. package/.next/server/app/api/board-assets/[...path]/route.js +2 -2
  39. package/.next/server/app/api/board-assets/route.js +2 -2
  40. package/.next/server/app/api/boards/[id]/add-session/route.js +1 -0
  41. package/.next/server/app/api/boards/[id]/add-session/route.js.nft.json +1 -0
  42. package/.next/server/app/api/boards/[id]/add-session/route_client-reference-manifest.js +1 -0
  43. package/.next/server/app/api/boards/[id]/reconcile/route.js +1 -1
  44. package/.next/server/app/api/boards/[id]/route.js +1 -1
  45. package/.next/server/app/api/boards/reorder/route.js +2 -2
  46. package/.next/server/app/api/boards/route.js +1 -1
  47. package/.next/server/app/api/cwd/browse/route.js +1 -1
  48. package/.next/server/app/api/cwd/validate/route.js +2 -2
  49. package/.next/server/app/api/default-cwd/route.js +2 -2
  50. package/.next/server/app/api/file-index/route.js +2 -2
  51. package/.next/server/app/api/files/[...path]/route.js +3 -3
  52. package/.next/server/app/api/git/diff/route.js +1 -1
  53. package/.next/server/app/api/git/status/route.js +1 -1
  54. package/.next/server/app/api/home/route.js +1 -1
  55. package/.next/server/app/api/mcp/route.js +2 -2
  56. package/.next/server/app/api/models/route.js +2 -2
  57. package/.next/server/app/api/models-config/catalog/route.js +1 -1
  58. package/.next/server/app/api/models-config/discover/route.js +1 -1
  59. package/.next/server/app/api/models-config/route.js +1 -1
  60. package/.next/server/app/api/models-config/test/route.js +1 -1
  61. package/.next/server/app/api/plugins/route.js +2 -2
  62. package/.next/server/app/api/project-trust/route.js +1 -1
  63. package/.next/server/app/api/project-trust/route.js.nft.json +1 -1
  64. package/.next/server/app/api/quota/route.js +1 -1
  65. package/.next/server/app/api/search/route.js +2 -2
  66. package/.next/server/app/api/sessions/[id]/auto-name/route.js +2 -2
  67. package/.next/server/app/api/sessions/[id]/auto-name/route.js.nft.json +1 -1
  68. package/.next/server/app/api/sessions/[id]/context/route.js +1 -1
  69. package/.next/server/app/api/sessions/[id]/context/route.js.nft.json +1 -1
  70. package/.next/server/app/api/sessions/[id]/entries/[entryId]/thinking/route.js +2 -2
  71. package/.next/server/app/api/sessions/[id]/export/route.js +2 -2
  72. package/.next/server/app/api/sessions/[id]/minimap/route.js +1 -1
  73. package/.next/server/app/api/sessions/[id]/minimap/route.js.nft.json +1 -1
  74. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  75. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  76. package/.next/server/app/api/sessions/[id]/state/route.js +1 -1
  77. package/.next/server/app/api/sessions/[id]/state/route.js.nft.json +1 -1
  78. package/.next/server/app/api/sessions/[id]/todos/route.js +1 -1
  79. package/.next/server/app/api/sessions/[id]/todos/route.js.nft.json +1 -1
  80. package/.next/server/app/api/sessions/route.js +1 -1
  81. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  82. package/.next/server/app/api/sessions/summary/route.js +2 -2
  83. package/.next/server/app/api/skills/check/route.js +1 -1
  84. package/.next/server/app/api/skills/install/route.js +2 -2
  85. package/.next/server/app/api/skills/route.js +1 -1
  86. package/.next/server/app/api/skills/search/route.js +1 -1
  87. package/.next/server/app/api/skills/update/route.js +1 -1
  88. package/.next/server/app/api/subagents/[id]/route.js +1 -0
  89. package/.next/server/app/api/subagents/[id]/route.js.nft.json +1 -0
  90. package/.next/server/app/api/subagents/[id]/route_client-reference-manifest.js +1 -0
  91. package/.next/server/app/api/subagents/profiles/route.js +30 -0
  92. package/.next/server/app/api/subagents/profiles/route.js.nft.json +1 -0
  93. package/.next/server/app/api/subagents/profiles/route_client-reference-manifest.js +1 -0
  94. package/.next/server/app/api/subagents/settings/route.js +1 -0
  95. package/.next/server/app/api/subagents/settings/route.js.nft.json +1 -0
  96. package/.next/server/app/api/subagents/settings/route_client-reference-manifest.js +1 -0
  97. package/.next/server/app/api/task-card-questions/[id]/answer/route.js +2 -2
  98. package/.next/server/app/api/task-card-questions/route.js +2 -2
  99. package/.next/server/app/api/task-cards/[id]/route.js +1 -1
  100. package/.next/server/app/api/task-cards/route.js +1 -1
  101. package/.next/server/app/api/task-cards/unbind/route.js +3 -3
  102. package/.next/server/app/api/task-scheduler/status/route.js +1 -1
  103. package/.next/server/app/api/task-scheduler/status/route.js.nft.json +1 -1
  104. package/.next/server/app/api/tasks/[id]/assign-session/route.js +2 -2
  105. package/.next/server/app/api/tasks/[id]/board/route.js +1 -1
  106. package/.next/server/app/api/tasks/[id]/route.js +1 -1
  107. package/.next/server/app/api/tasks/[id]/route.js.nft.json +1 -1
  108. package/.next/server/app/api/tasks/reorder/route.js +2 -2
  109. package/.next/server/app/api/tasks/route.js +3 -3
  110. package/.next/server/app/api/terminal/[id]/events/route.js +2 -2
  111. package/.next/server/app/api/terminal/[id]/route.js +2 -2
  112. package/.next/server/app/api/terminal/route.js +2 -2
  113. package/.next/server/app/api/worktrees/route.js +2 -2
  114. package/.next/server/app/api/yjs-version/route.js +1 -1
  115. package/.next/server/app/favicon.ico/route.js +1 -1
  116. package/.next/server/app/index.html +1 -1
  117. package/.next/server/app/index.rsc +6 -5
  118. package/.next/server/app/index.segments/__PAGE__.segment.rsc +6 -5
  119. package/.next/server/app/index.segments/_full.segment.rsc +6 -5
  120. package/.next/server/app/index.segments/_tree.segment.rsc +3 -2
  121. package/.next/server/app/manifest.webmanifest/route.js +2 -2
  122. package/.next/server/app/page.js +175 -8
  123. package/.next/server/app/page_client-reference-manifest.js +1 -1
  124. package/.next/server/app-paths-manifest.json +8 -4
  125. package/.next/server/chunks/1937.js +1 -1
  126. package/.next/server/chunks/3379.js +1 -1
  127. package/.next/server/chunks/402.js +12 -2
  128. package/.next/server/chunks/426.js +14 -0
  129. package/.next/server/chunks/4367.js +1 -1
  130. package/.next/server/chunks/4457.js +2 -2
  131. package/.next/server/chunks/4980.js +1 -1
  132. package/.next/server/chunks/542.js +23 -4
  133. package/.next/server/chunks/5794.js +1 -1
  134. package/.next/server/chunks/6337.js +1 -1
  135. package/.next/server/chunks/6429.js +15 -2
  136. package/.next/server/chunks/6525.js +12 -2
  137. package/.next/server/chunks/7048.js +6 -0
  138. package/.next/server/instrumentation.js +1 -1
  139. package/.next/server/middleware-build-manifest.js +1 -1
  140. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  141. package/.next/server/middleware.js +3 -3
  142. package/.next/server/pages/404.html +1 -1
  143. package/.next/server/pages/500.html +1 -1
  144. package/.next/static/chunks/{752.0ad92735d5f38143.js → 752.adce8bc3ebbaf4b6.js} +1 -1
  145. package/.next/static/chunks/8088.0cad1ff2e09fd8ff.js +1 -0
  146. package/.next/static/chunks/app/_global-error/page-ad6e695deb9de65c.js +1 -0
  147. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-ad6e695deb9de65c.js +1 -0
  148. package/.next/static/chunks/app/api/agent/[id]/events/route-ad6e695deb9de65c.js +1 -0
  149. package/.next/static/chunks/app/api/agent/[id]/route-ad6e695deb9de65c.js +1 -0
  150. package/.next/static/chunks/app/api/agent/new/route-ad6e695deb9de65c.js +1 -0
  151. package/.next/static/chunks/app/api/agent/running/route-ad6e695deb9de65c.js +1 -0
  152. package/.next/static/chunks/app/api/app-update/route-ad6e695deb9de65c.js +1 -0
  153. package/.next/static/chunks/app/api/auth/all-providers/route-ad6e695deb9de65c.js +1 -0
  154. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-ad6e695deb9de65c.js +1 -0
  155. package/.next/static/chunks/app/api/auth/login/[provider]/route-ad6e695deb9de65c.js +1 -0
  156. package/.next/static/chunks/app/api/auth/logout/[provider]/route-ad6e695deb9de65c.js +1 -0
  157. package/.next/static/chunks/app/api/auth/providers/route-ad6e695deb9de65c.js +1 -0
  158. package/.next/static/chunks/app/api/board-assets/[...path]/route-ad6e695deb9de65c.js +1 -0
  159. package/.next/static/chunks/app/api/board-assets/route-ad6e695deb9de65c.js +1 -0
  160. package/.next/static/chunks/app/api/boards/[id]/add-session/route-ad6e695deb9de65c.js +1 -0
  161. package/.next/static/chunks/app/api/boards/[id]/reconcile/route-ad6e695deb9de65c.js +1 -0
  162. package/.next/static/chunks/app/api/boards/[id]/route-ad6e695deb9de65c.js +1 -0
  163. package/.next/static/chunks/app/api/boards/reorder/route-ad6e695deb9de65c.js +1 -0
  164. package/.next/static/chunks/app/api/boards/route-ad6e695deb9de65c.js +1 -0
  165. package/.next/static/chunks/app/api/cwd/browse/route-ad6e695deb9de65c.js +1 -0
  166. package/.next/static/chunks/app/api/cwd/validate/route-ad6e695deb9de65c.js +1 -0
  167. package/.next/static/chunks/app/api/default-cwd/route-ad6e695deb9de65c.js +1 -0
  168. package/.next/static/chunks/app/api/file-index/route-ad6e695deb9de65c.js +1 -0
  169. package/.next/static/chunks/app/api/files/[...path]/route-ad6e695deb9de65c.js +1 -0
  170. package/.next/static/chunks/app/api/git/diff/route-ad6e695deb9de65c.js +1 -0
  171. package/.next/static/chunks/app/api/git/status/route-ad6e695deb9de65c.js +1 -0
  172. package/.next/static/chunks/app/api/home/route-ad6e695deb9de65c.js +1 -0
  173. package/.next/static/chunks/app/api/mcp/route-ad6e695deb9de65c.js +1 -0
  174. package/.next/static/chunks/app/api/models/route-ad6e695deb9de65c.js +1 -0
  175. package/.next/static/chunks/app/api/models-config/catalog/route-ad6e695deb9de65c.js +1 -0
  176. package/.next/static/chunks/app/api/models-config/discover/route-ad6e695deb9de65c.js +1 -0
  177. package/.next/static/chunks/app/api/models-config/route-ad6e695deb9de65c.js +1 -0
  178. package/.next/static/chunks/app/api/models-config/test/route-ad6e695deb9de65c.js +1 -0
  179. package/.next/static/chunks/app/api/plugins/route-ad6e695deb9de65c.js +1 -0
  180. package/.next/static/chunks/app/api/project-trust/route-ad6e695deb9de65c.js +1 -0
  181. package/.next/static/chunks/app/api/quota/route-ad6e695deb9de65c.js +1 -0
  182. package/.next/static/chunks/app/api/search/route-ad6e695deb9de65c.js +1 -0
  183. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-ad6e695deb9de65c.js +1 -0
  184. package/.next/static/chunks/app/api/sessions/[id]/context/route-ad6e695deb9de65c.js +1 -0
  185. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-ad6e695deb9de65c.js +1 -0
  186. package/.next/static/chunks/app/api/sessions/[id]/export/route-ad6e695deb9de65c.js +1 -0
  187. package/.next/static/chunks/app/api/sessions/[id]/minimap/route-ad6e695deb9de65c.js +1 -0
  188. package/.next/static/chunks/app/api/sessions/[id]/route-ad6e695deb9de65c.js +1 -0
  189. package/.next/static/chunks/app/api/sessions/[id]/state/route-ad6e695deb9de65c.js +1 -0
  190. package/.next/static/chunks/app/api/sessions/[id]/todos/route-ad6e695deb9de65c.js +1 -0
  191. package/.next/static/chunks/app/api/sessions/route-ad6e695deb9de65c.js +1 -0
  192. package/.next/static/chunks/app/api/sessions/summary/route-ad6e695deb9de65c.js +1 -0
  193. package/.next/static/chunks/app/api/skills/check/route-ad6e695deb9de65c.js +1 -0
  194. package/.next/static/chunks/app/api/skills/install/route-ad6e695deb9de65c.js +1 -0
  195. package/.next/static/chunks/app/api/skills/route-ad6e695deb9de65c.js +1 -0
  196. package/.next/static/chunks/app/api/skills/search/route-ad6e695deb9de65c.js +1 -0
  197. package/.next/static/chunks/app/api/skills/update/route-ad6e695deb9de65c.js +1 -0
  198. package/.next/static/chunks/app/api/subagents/[id]/route-ad6e695deb9de65c.js +1 -0
  199. package/.next/static/chunks/app/api/subagents/profiles/route-ad6e695deb9de65c.js +1 -0
  200. package/.next/static/chunks/app/api/subagents/settings/route-ad6e695deb9de65c.js +1 -0
  201. package/.next/static/chunks/app/api/task-card-questions/[id]/answer/route-ad6e695deb9de65c.js +1 -0
  202. package/.next/static/chunks/app/api/task-card-questions/route-ad6e695deb9de65c.js +1 -0
  203. package/.next/static/chunks/app/api/task-cards/[id]/route-ad6e695deb9de65c.js +1 -0
  204. package/.next/static/chunks/app/api/task-cards/route-ad6e695deb9de65c.js +1 -0
  205. package/.next/static/chunks/app/api/task-cards/unbind/route-ad6e695deb9de65c.js +1 -0
  206. package/.next/static/chunks/app/api/task-scheduler/status/route-ad6e695deb9de65c.js +1 -0
  207. package/.next/static/chunks/app/api/tasks/[id]/assign-session/route-ad6e695deb9de65c.js +1 -0
  208. package/.next/static/chunks/app/api/tasks/[id]/board/route-ad6e695deb9de65c.js +1 -0
  209. package/.next/static/chunks/app/api/tasks/[id]/route-ad6e695deb9de65c.js +1 -0
  210. package/.next/static/chunks/app/api/tasks/reorder/route-ad6e695deb9de65c.js +1 -0
  211. package/.next/static/chunks/app/api/tasks/route-ad6e695deb9de65c.js +1 -0
  212. package/.next/static/chunks/app/api/terminal/[id]/events/route-ad6e695deb9de65c.js +1 -0
  213. package/.next/static/chunks/app/api/terminal/[id]/route-ad6e695deb9de65c.js +1 -0
  214. package/.next/static/chunks/app/api/terminal/route-ad6e695deb9de65c.js +1 -0
  215. package/.next/static/chunks/app/api/worktrees/route-ad6e695deb9de65c.js +1 -0
  216. package/.next/static/chunks/app/api/yjs-version/route-ad6e695deb9de65c.js +1 -0
  217. package/.next/static/chunks/app/layout-87087b955e0c9507.js +1 -0
  218. package/.next/static/chunks/app/manifest.webmanifest/route-ad6e695deb9de65c.js +1 -0
  219. package/.next/static/chunks/app/page-efca6bf51a5f8ccb.js +256 -0
  220. package/.next/static/chunks/next/dist/client/components/builtin/app-error-ad6e695deb9de65c.js +1 -0
  221. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-ad6e695deb9de65c.js +1 -0
  222. package/.next/static/chunks/next/dist/client/components/builtin/not-found-ad6e695deb9de65c.js +1 -0
  223. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-ad6e695deb9de65c.js +1 -0
  224. package/.next/static/chunks/{webpack-b0effde51c1651b8.js → webpack-4de8e8dd9f2f3173.js} +1 -1
  225. package/.next/static/css/bb9361c7f832a89d.css +1 -0
  226. package/.next/static/css/c6d32b6031181be7.css +1 -0
  227. package/.next/static/k8ZFqwz7d-bnK0ZiUVgCc/_buildManifest.js +1 -0
  228. package/.next/trace +7 -7
  229. package/.next/trace-build +1 -1
  230. package/.next/types/app/api/boards/[id]/add-session/route.ts +353 -0
  231. package/.next/types/app/api/subagents/[id]/route.ts +353 -0
  232. package/.next/types/app/api/subagents/profiles/route.ts +353 -0
  233. package/.next/types/app/api/subagents/settings/route.ts +353 -0
  234. package/.next/types/routes.d.ts +5 -1
  235. package/.next/types/validator.ts +36 -0
  236. package/lib/api-types.ts +10 -0
  237. package/lib/board-reconcile.test.mjs +20 -0
  238. package/lib/board-reconcile.ts +54 -0
  239. package/lib/chat-lazy-load.test.mjs +0 -62
  240. package/lib/chat-lazy-load.ts +0 -13
  241. package/lib/chat-only.ts +23 -0
  242. package/lib/draft-stash.ts +4 -5
  243. package/lib/file-types.ts +16 -1
  244. package/lib/i18n/messages/en.ts +91 -0
  245. package/lib/i18n/messages/zh-CN.ts +91 -0
  246. package/lib/id.test.mjs +38 -0
  247. package/lib/id.ts +17 -0
  248. package/lib/message-text.ts +24 -0
  249. package/lib/models-cache.ts +1 -1
  250. package/lib/pi-types.ts +19 -1
  251. package/lib/pin-store.ts +85 -0
  252. package/lib/powershell-settings.ts +106 -0
  253. package/lib/quoted-selection.ts +4 -0
  254. package/lib/rpc-manager.ts +208 -22
  255. package/lib/session-family.test.mjs +49 -0
  256. package/lib/session-family.ts +80 -0
  257. package/lib/session-index-scanner.ts +39 -0
  258. package/lib/session-time-group.test.mjs +38 -0
  259. package/lib/session-time-group.ts +55 -0
  260. package/lib/settings-navigation.ts +124 -0
  261. package/lib/subagent-extension.test.mjs +424 -0
  262. package/lib/subagent-extension.ts +309 -0
  263. package/lib/subagent-input.test.mjs +63 -0
  264. package/lib/subagent-input.ts +71 -0
  265. package/lib/subagent-isolation.test.mjs +51 -0
  266. package/lib/subagent-profile-precedence.ts +20 -0
  267. package/lib/subagent-prompt.test.mjs +64 -0
  268. package/lib/subagent-prompt.ts +31 -0
  269. package/lib/subagent-queue.test.mjs +35 -0
  270. package/lib/subagent-queue.ts +74 -0
  271. package/lib/subagent-runtime.test.mjs +150 -0
  272. package/lib/subagent-runtime.ts +587 -0
  273. package/lib/subagent-settings.test.mjs +50 -0
  274. package/lib/subagent-settings.ts +93 -0
  275. package/lib/subagents.test.mjs +601 -0
  276. package/lib/subagents.ts +602 -0
  277. package/lib/tool-presets.ts +4 -0
  278. package/lib/types.ts +19 -0
  279. package/package.json +1 -1
  280. package/.next/static/bsW3fla0-BlBHVMKtAM5I/_buildManifest.js +0 -1
  281. package/.next/static/chunks/8088.53d9cdaf15634d4b.js +0 -1
  282. package/.next/static/chunks/app/_global-error/page-2d5f6296c7e693c6.js +0 -1
  283. package/.next/static/chunks/app/api/agent/[id]/bash-output/route-2d5f6296c7e693c6.js +0 -1
  284. package/.next/static/chunks/app/api/agent/[id]/events/route-2d5f6296c7e693c6.js +0 -1
  285. package/.next/static/chunks/app/api/agent/[id]/route-2d5f6296c7e693c6.js +0 -1
  286. package/.next/static/chunks/app/api/agent/new/route-2d5f6296c7e693c6.js +0 -1
  287. package/.next/static/chunks/app/api/agent/running/route-2d5f6296c7e693c6.js +0 -1
  288. package/.next/static/chunks/app/api/app-update/route-2d5f6296c7e693c6.js +0 -1
  289. package/.next/static/chunks/app/api/auth/all-providers/route-2d5f6296c7e693c6.js +0 -1
  290. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-2d5f6296c7e693c6.js +0 -1
  291. package/.next/static/chunks/app/api/auth/login/[provider]/route-2d5f6296c7e693c6.js +0 -1
  292. package/.next/static/chunks/app/api/auth/logout/[provider]/route-2d5f6296c7e693c6.js +0 -1
  293. package/.next/static/chunks/app/api/auth/providers/route-2d5f6296c7e693c6.js +0 -1
  294. package/.next/static/chunks/app/api/board-assets/[...path]/route-2d5f6296c7e693c6.js +0 -1
  295. package/.next/static/chunks/app/api/board-assets/route-2d5f6296c7e693c6.js +0 -1
  296. package/.next/static/chunks/app/api/boards/[id]/reconcile/route-2d5f6296c7e693c6.js +0 -1
  297. package/.next/static/chunks/app/api/boards/[id]/route-2d5f6296c7e693c6.js +0 -1
  298. package/.next/static/chunks/app/api/boards/reorder/route-2d5f6296c7e693c6.js +0 -1
  299. package/.next/static/chunks/app/api/boards/route-2d5f6296c7e693c6.js +0 -1
  300. package/.next/static/chunks/app/api/cwd/browse/route-2d5f6296c7e693c6.js +0 -1
  301. package/.next/static/chunks/app/api/cwd/validate/route-2d5f6296c7e693c6.js +0 -1
  302. package/.next/static/chunks/app/api/default-cwd/route-2d5f6296c7e693c6.js +0 -1
  303. package/.next/static/chunks/app/api/file-index/route-2d5f6296c7e693c6.js +0 -1
  304. package/.next/static/chunks/app/api/files/[...path]/route-2d5f6296c7e693c6.js +0 -1
  305. package/.next/static/chunks/app/api/git/diff/route-2d5f6296c7e693c6.js +0 -1
  306. package/.next/static/chunks/app/api/git/status/route-2d5f6296c7e693c6.js +0 -1
  307. package/.next/static/chunks/app/api/home/route-2d5f6296c7e693c6.js +0 -1
  308. package/.next/static/chunks/app/api/mcp/route-2d5f6296c7e693c6.js +0 -1
  309. package/.next/static/chunks/app/api/models/route-2d5f6296c7e693c6.js +0 -1
  310. package/.next/static/chunks/app/api/models-config/catalog/route-2d5f6296c7e693c6.js +0 -1
  311. package/.next/static/chunks/app/api/models-config/discover/route-2d5f6296c7e693c6.js +0 -1
  312. package/.next/static/chunks/app/api/models-config/route-2d5f6296c7e693c6.js +0 -1
  313. package/.next/static/chunks/app/api/models-config/test/route-2d5f6296c7e693c6.js +0 -1
  314. package/.next/static/chunks/app/api/plugins/route-2d5f6296c7e693c6.js +0 -1
  315. package/.next/static/chunks/app/api/project-trust/route-2d5f6296c7e693c6.js +0 -1
  316. package/.next/static/chunks/app/api/quota/route-2d5f6296c7e693c6.js +0 -1
  317. package/.next/static/chunks/app/api/search/route-2d5f6296c7e693c6.js +0 -1
  318. package/.next/static/chunks/app/api/sessions/[id]/auto-name/route-2d5f6296c7e693c6.js +0 -1
  319. package/.next/static/chunks/app/api/sessions/[id]/context/route-2d5f6296c7e693c6.js +0 -1
  320. package/.next/static/chunks/app/api/sessions/[id]/entries/[entryId]/thinking/route-2d5f6296c7e693c6.js +0 -1
  321. package/.next/static/chunks/app/api/sessions/[id]/export/route-2d5f6296c7e693c6.js +0 -1
  322. package/.next/static/chunks/app/api/sessions/[id]/minimap/route-2d5f6296c7e693c6.js +0 -1
  323. package/.next/static/chunks/app/api/sessions/[id]/route-2d5f6296c7e693c6.js +0 -1
  324. package/.next/static/chunks/app/api/sessions/[id]/state/route-2d5f6296c7e693c6.js +0 -1
  325. package/.next/static/chunks/app/api/sessions/[id]/todos/route-2d5f6296c7e693c6.js +0 -1
  326. package/.next/static/chunks/app/api/sessions/route-2d5f6296c7e693c6.js +0 -1
  327. package/.next/static/chunks/app/api/sessions/summary/route-2d5f6296c7e693c6.js +0 -1
  328. package/.next/static/chunks/app/api/skills/check/route-2d5f6296c7e693c6.js +0 -1
  329. package/.next/static/chunks/app/api/skills/install/route-2d5f6296c7e693c6.js +0 -1
  330. package/.next/static/chunks/app/api/skills/route-2d5f6296c7e693c6.js +0 -1
  331. package/.next/static/chunks/app/api/skills/search/route-2d5f6296c7e693c6.js +0 -1
  332. package/.next/static/chunks/app/api/skills/update/route-2d5f6296c7e693c6.js +0 -1
  333. package/.next/static/chunks/app/api/task-card-questions/[id]/answer/route-2d5f6296c7e693c6.js +0 -1
  334. package/.next/static/chunks/app/api/task-card-questions/route-2d5f6296c7e693c6.js +0 -1
  335. package/.next/static/chunks/app/api/task-cards/[id]/route-2d5f6296c7e693c6.js +0 -1
  336. package/.next/static/chunks/app/api/task-cards/route-2d5f6296c7e693c6.js +0 -1
  337. package/.next/static/chunks/app/api/task-cards/unbind/route-2d5f6296c7e693c6.js +0 -1
  338. package/.next/static/chunks/app/api/task-scheduler/status/route-2d5f6296c7e693c6.js +0 -1
  339. package/.next/static/chunks/app/api/tasks/[id]/assign-session/route-2d5f6296c7e693c6.js +0 -1
  340. package/.next/static/chunks/app/api/tasks/[id]/board/route-2d5f6296c7e693c6.js +0 -1
  341. package/.next/static/chunks/app/api/tasks/[id]/route-2d5f6296c7e693c6.js +0 -1
  342. package/.next/static/chunks/app/api/tasks/reorder/route-2d5f6296c7e693c6.js +0 -1
  343. package/.next/static/chunks/app/api/tasks/route-2d5f6296c7e693c6.js +0 -1
  344. package/.next/static/chunks/app/api/terminal/[id]/events/route-2d5f6296c7e693c6.js +0 -1
  345. package/.next/static/chunks/app/api/terminal/[id]/route-2d5f6296c7e693c6.js +0 -1
  346. package/.next/static/chunks/app/api/terminal/route-2d5f6296c7e693c6.js +0 -1
  347. package/.next/static/chunks/app/api/worktrees/route-2d5f6296c7e693c6.js +0 -1
  348. package/.next/static/chunks/app/api/yjs-version/route-2d5f6296c7e693c6.js +0 -1
  349. package/.next/static/chunks/app/layout-dace09825b2d3857.js +0 -1
  350. package/.next/static/chunks/app/manifest.webmanifest/route-2d5f6296c7e693c6.js +0 -1
  351. package/.next/static/chunks/app/page-64b9f4b3567a2f73.js +0 -89
  352. package/.next/static/chunks/next/dist/client/components/builtin/app-error-2d5f6296c7e693c6.js +0 -1
  353. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-2d5f6296c7e693c6.js +0 -1
  354. package/.next/static/chunks/next/dist/client/components/builtin/not-found-2d5f6296c7e693c6.js +0 -1
  355. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2d5f6296c7e693c6.js +0 -1
  356. package/.next/static/css/fd25673802257262.css +0 -1
  357. package/lib/extension-command.test.mjs +0 -63
  358. package/lib/extension-command.ts +0 -81
  359. package/lib/subagent-widget.test.mjs +0 -87
  360. package/lib/subagent-widget.ts +0 -109
  361. /package/.next/static/{bsW3fla0-BlBHVMKtAM5I → k8ZFqwz7d-bnK0ZiUVgCc}/_ssgManifest.js +0 -0
package/lib/file-types.ts CHANGED
@@ -26,7 +26,14 @@ export const AUDIO_EXT_TO_MIME: Record<string, string> = {
26
26
  aac: "audio/aac",
27
27
  flac: "audio/flac",
28
28
  weba: "audio/webm",
29
- webm: "audio/webm",
29
+ };
30
+
31
+ export const VIDEO_EXT_TO_MIME: Record<string, string> = {
32
+ mp4: "video/mp4",
33
+ m4v: "video/mp4",
34
+ webm: "video/webm",
35
+ mov: "video/quicktime",
36
+ ogv: "video/ogg",
30
37
  };
31
38
 
32
39
  export const DOCUMENT_EXT_TO_MIME: Record<DocumentPreviewKind, string> = {
@@ -50,6 +57,10 @@ export function getAudioMime(filePath: string): string | null {
50
57
  return AUDIO_EXT_TO_MIME[getFileExt(filePath)] ?? null;
51
58
  }
52
59
 
60
+ export function getVideoMime(filePath: string): string | null {
61
+ return VIDEO_EXT_TO_MIME[getFileExt(filePath)] ?? null;
62
+ }
63
+
53
64
  export function getDocumentMime(filePath: string): string | null {
54
65
  return DOCUMENT_EXT_TO_MIME[getFileExt(filePath) as DocumentPreviewKind] ?? null;
55
66
  }
@@ -68,6 +79,10 @@ export function isAudioPath(filePath: string): boolean {
68
79
  return getAudioMime(filePath) !== null;
69
80
  }
70
81
 
82
+ export function isVideoPath(filePath: string): boolean {
83
+ return getVideoMime(filePath) !== null;
84
+ }
85
+
71
86
  export function isDocumentPreviewPath(filePath: string): boolean {
72
87
  return documentPreviewKind(filePath) !== null;
73
88
  }
@@ -10,6 +10,8 @@ export const enLocale: LocalePlugin = {
10
10
  "common.models": "Models",
11
11
  "common.skills": "Skills",
12
12
  "common.plugins": "Plugins",
13
+ "common.settings": "Settings",
14
+ "common.agents": "Agents",
13
15
  "appUpdate.releaseNotes": "Pi Web v{version} is available. View release notes",
14
16
  "sidebar.hide": "Hide sidebar",
15
17
  "sidebar.show": "Show sidebar",
@@ -146,6 +148,11 @@ export const enLocale: LocalePlugin = {
146
148
  "sidebar.filesTab": "Files",
147
149
  "sidebar.tasks": "Tasks",
148
150
  "sidebar.tempSessions": "Chat",
151
+ "sidebar.timeToday": "Today",
152
+ "sidebar.timeYesterday": "Yesterday",
153
+ "sidebar.timeThisWeek": "This week",
154
+ "sidebar.timeThisMonth": "Last 30 days",
155
+ "sidebar.timeOlder": "Older",
149
156
  "sidebar.newTask": "New task…",
150
157
  "sidebar.taskName": "Task name",
151
158
  "sidebar.newTaskSession": "New task session",
@@ -300,6 +307,17 @@ export const enLocale: LocalePlugin = {
300
307
  "chat.steer": "Steer",
301
308
  "chat.followUp": "Follow-up",
302
309
  "chat.send": "Send",
310
+ "chat.askSelection": "Ask about selected text",
311
+ "chat.askInCurrent": "Ask here",
312
+ "chat.askInNewChat": "Ask in new chat",
313
+ "chat.newQuoteChat": "New chat about selected text",
314
+ "chat.quoteIntro": "About this passage:",
315
+ "chat.quoteQuestion": "My question:",
316
+ "chat.quoteForkFailed": "Failed to create quoted chat",
317
+ "chat.quoteSelectionToggle": "Show an ask menu after selecting text",
318
+ "chat.sendQuestion": "Send question",
319
+ "chat.imageNotSupportedTitle": "The selected model does not support images",
320
+ "chat.imageNotSupportedBody": "Model {model} accepts text input only; attached images will not be sent. Switch to a vision-capable model or remove the attachments.",
303
321
  "chat.attachImage": "Attach image",
304
322
  "chat.previewImage": "Preview image",
305
323
  "chat.filterModels": "Filter models…",
@@ -360,6 +378,79 @@ export const enLocale: LocalePlugin = {
360
378
  "chat.commandCopy": "Copy the last assistant message",
361
379
  "chat.compacted": "Compacted",
362
380
  "chat.tokensSaved": "{saved} saved",
381
+ "settings.chatContentWidth": "Chat content width",
382
+ "settings.chatContentWidthDescription": "Set the maximum width of message content and the input box.",
383
+ "settings.chatContentFontSize": "Chat font size",
384
+ "settings.preferences": "Preferences",
385
+ "settings.title": "Settings",
386
+ "settings.general": "General",
387
+ "settings.appearance": "Appearance",
388
+ "settings.chat": "Chat",
389
+ "settings.quoteSelection": "Ask about selected text",
390
+ "settings.resetChatContentWidth": "Reset chat width",
391
+ "settings.resetChatContentFontSize": "Reset chat font size",
392
+ "settings.projectRequired": "Project required",
393
+ "settings.themeLight": "Light",
394
+ "settings.themeDark": "Dark",
395
+ "tools.title": "Tools enabled in the current session",
396
+ "tools.details": "Tool definition details",
397
+ "tools.load": "Tool definitions have not loaded yet",
398
+ "tools.loading": "Loading tool definitions…",
399
+ "tools.noTools": "No active tools",
400
+ "tools.description": "Description",
401
+ "tools.parameters": "Parameters",
402
+ "tools.parameterCount": "{count} parameters",
403
+ "tools.noParameters": "No parameters",
404
+ "tools.required": "Required",
405
+ "tools.optional": "Optional",
406
+ "tools.allowedValues": "Allowed",
407
+ "tools.defaultValue": "Default",
408
+ "tools.guidelines": "Prompt guidelines",
409
+
410
+ "tools.label": "Tools",
411
+ "agents.close": "Close",
412
+ "agents.builtInTitle": "Enable Pi Web built-in sub-agents",
413
+ "agents.builtInDescription": "Provides Pi Web's integrated Agent tools and disables a conflicting pi-subagents extension.",
414
+ "agents.reloadRequired": "Reload the current session to apply this change.",
415
+ "agents.reloadSession": "Reload session",
416
+ "agents.maxConcurrent": "Concurrent sub-agents",
417
+ "agents.maxConcurrentDescription": "Maximum prompts running at once per parent session.",
418
+ "agents.reloading": "Reloading...",
419
+ "agents.loading": "Loading sub-agents...",
420
+ "agents.new": "New sub-agent",
421
+ "agents.empty": "Select or create a sub-agent profile",
422
+ "agents.saveScope": "Save to",
423
+ "agents.name": "Sub-agent ID",
424
+ "agents.displayName": "Display name",
425
+ "agents.description": "Description",
426
+ "agents.prompt": "System instructions",
427
+ "agents.tools": "Tools",
428
+ "agents.resources": "Resources",
429
+ "agents.loadSkills": "Load skills",
430
+ "agents.loadExtensions": "Load extensions",
431
+ "agents.model": "Model override",
432
+ "agents.modelsLoading": "Loading models...",
433
+ "agents.modelUnavailable": "{model} (unavailable)",
434
+ "agents.thinking": "Thinking",
435
+ "agents.maxTurns": "Max turns",
436
+ "agents.inherit": "Parent default",
437
+ "agents.enable": "Enable sub-agent",
438
+ "agents.disable": "Disable sub-agent",
439
+ "agents.builtinPath": "Built-in profile",
440
+ "agents.inheritContext": "Inherit parent context",
441
+ "agents.background": "Run in background by default",
442
+ "agents.duplicate": "Duplicate",
443
+ "agents.copyName": "{name} copy",
444
+ "agents.delete": "Delete",
445
+ "agents.deleteConfirm": "Delete {name}?",
446
+ "agents.save": "Save",
447
+ "agents.saving": "Saving...",
448
+ "agents.scope.builtin": "built-in",
449
+ "agents.scope.global": "global",
450
+ "agents.scope.workspace": "workspace",
451
+ "agents.scope.project": "project",
452
+ "agents.overridden": "Overridden",
453
+
363
454
  "i18n.close": "Close",
364
455
  "i18n.copy": "Copy",
365
456
  "i18n.pin": "Pin",
@@ -11,6 +11,8 @@ export const zhCNLocale: LocalePlugin = {
11
11
  "common.models": "模型",
12
12
  "common.skills": "技能",
13
13
  "common.plugins": "插件",
14
+ "common.settings": "设置",
15
+ "common.agents": "代理",
14
16
  "appUpdate.releaseNotes": "Pi Web v{version} 可用,查看更新说明",
15
17
  "sidebar.hide": "隐藏侧边栏",
16
18
  "sidebar.show": "显示侧边栏",
@@ -147,6 +149,11 @@ export const zhCNLocale: LocalePlugin = {
147
149
  "sidebar.filesTab": "文件",
148
150
  "sidebar.tasks": "任务",
149
151
  "sidebar.tempSessions": "聊天",
152
+ "sidebar.timeToday": "今天",
153
+ "sidebar.timeYesterday": "昨天",
154
+ "sidebar.timeThisWeek": "本周",
155
+ "sidebar.timeThisMonth": "近一月",
156
+ "sidebar.timeOlder": "更久之前",
150
157
  "sidebar.newTask": "新建任务…",
151
158
  "sidebar.taskName": "任务名称",
152
159
  "sidebar.newTaskSession": "新建任务会话",
@@ -301,6 +308,17 @@ export const zhCNLocale: LocalePlugin = {
301
308
  "chat.steer": "引导",
302
309
  "chat.followUp": "后续消息",
303
310
  "chat.send": "发送",
311
+ "chat.askSelection": "询问选中的文字",
312
+ "chat.askInCurrent": "在当前对话询问",
313
+ "chat.askInNewChat": "在新对话询问",
314
+ "chat.newQuoteChat": "关于选中文字的新对话",
315
+ "chat.quoteIntro": "关于这段内容:",
316
+ "chat.quoteQuestion": "我的问题是:",
317
+ "chat.quoteForkFailed": "无法创建引用对话",
318
+ "chat.quoteSelectionToggle": "选中文字后显示询问菜单",
319
+ "chat.sendQuestion": "发送问题",
320
+ "chat.imageNotSupportedTitle": "当前模型不支持图片",
321
+ "chat.imageNotSupportedBody": "模型 {model} 的输入只支持文本,图片不会被发送。请更换支持图片的模型或移除附件。",
304
322
  "chat.attachImage": "附加图片",
305
323
  "chat.previewImage": "预览图片",
306
324
  "chat.filterModels": "筛选模型…",
@@ -361,6 +379,79 @@ export const zhCNLocale: LocalePlugin = {
361
379
  "chat.commandCopy": "复制最后一条助手消息",
362
380
  "chat.compacted": "已压缩",
363
381
  "chat.tokensSaved": "节省 {saved}",
382
+ "settings.chatContentWidth": "聊天内容宽度",
383
+ "settings.chatContentWidthDescription": "设置消息内容和输入框的最大宽度。",
384
+ "settings.chatContentFontSize": "聊天字体大小",
385
+ "settings.preferences": "偏好",
386
+ "settings.title": "设置",
387
+ "settings.general": "通用",
388
+ "settings.appearance": "外观",
389
+ "settings.chat": "聊天",
390
+ "settings.quoteSelection": "选中文字后询问",
391
+ "settings.resetChatContentWidth": "重置聊天宽度",
392
+ "settings.resetChatContentFontSize": "重置聊天字号",
393
+ "settings.projectRequired": "需要项目",
394
+ "settings.themeLight": "浅色",
395
+ "settings.themeDark": "深色",
396
+ "tools.title": "当前会话启用的工具",
397
+ "tools.details": "工具定义详情",
398
+ "tools.load": "工具定义尚未加载",
399
+ "tools.loading": "正在加载工具定义…",
400
+ "tools.noTools": "没有启用的工具",
401
+ "tools.description": "描述",
402
+ "tools.parameters": "参数",
403
+ "tools.parameterCount": "{count} 个参数",
404
+ "tools.noParameters": "无参数",
405
+ "tools.required": "必填",
406
+ "tools.optional": "可选",
407
+ "tools.allowedValues": "可选值",
408
+ "tools.defaultValue": "默认值",
409
+ "tools.guidelines": "提示词规则",
410
+
411
+ "tools.label": "工具",
412
+ "agents.close": "关闭",
413
+ "agents.builtInTitle": "启用 Pi Web 内置子代理",
414
+ "agents.builtInDescription": "提供 Pi Web 集成的 Agent 工具,并停用发生冲突的 pi-subagents 扩展。",
415
+ "agents.reloadRequired": "重新加载当前会话后生效。",
416
+ "agents.reloadSession": "重新加载会话",
417
+ "agents.maxConcurrent": "并发子代理数",
418
+ "agents.maxConcurrentDescription": "每个父会话同时运行的最大任务数。",
419
+ "agents.reloading": "正在重新加载...",
420
+ "agents.loading": "正在加载子代理...",
421
+ "agents.new": "新建子代理",
422
+ "agents.empty": "选择或创建一个子代理配置",
423
+ "agents.saveScope": "保存到",
424
+ "agents.name": "子代理 ID",
425
+ "agents.displayName": "显示名称",
426
+ "agents.description": "描述",
427
+ "agents.prompt": "系统指令",
428
+ "agents.tools": "工具",
429
+ "agents.resources": "资源",
430
+ "agents.loadSkills": "加载技能",
431
+ "agents.loadExtensions": "加载扩展",
432
+ "agents.model": "指定模型",
433
+ "agents.modelsLoading": "正在加载模型...",
434
+ "agents.modelUnavailable": "{model}(不可用)",
435
+ "agents.thinking": "思考级别",
436
+ "agents.maxTurns": "最大轮次",
437
+ "agents.inherit": "跟随父会话",
438
+ "agents.enable": "启用子代理",
439
+ "agents.disable": "停用子代理",
440
+ "agents.builtinPath": "内置配置",
441
+ "agents.inheritContext": "继承父会话上下文",
442
+ "agents.background": "默认在后台运行",
443
+ "agents.duplicate": "创建副本",
444
+ "agents.copyName": "{name} 副本",
445
+ "agents.delete": "删除",
446
+ "agents.deleteConfirm": "删除 {name}?",
447
+ "agents.save": "保存",
448
+ "agents.saving": "正在保存...",
449
+ "agents.scope.builtin": "内置",
450
+ "agents.scope.global": "全局",
451
+ "agents.scope.workspace": "工作区",
452
+ "agents.scope.project": "项目",
453
+ "agents.overridden": "被覆盖",
454
+
364
455
  "i18n.close": "关闭",
365
456
  "i18n.copy": "复制",
366
457
  "i18n.pin": "钉",
@@ -0,0 +1,38 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { createJiti } from "jiti";
4
+
5
+ const jiti = createJiti(import.meta.url, { tsconfigPaths: true });
6
+ const { newId } = await jiti.import("./id.ts");
7
+
8
+ // 服务端 /api/agent/new 的会话 id 校验(SESSION_ID_RE):兜底 id 必须也能当会话 id 用
9
+ const SESSION_ID_RE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
10
+
11
+ const realCrypto = globalThis.crypto;
12
+
13
+ test.afterEach(() => {
14
+ Object.defineProperty(globalThis, "crypto", { value: realCrypto, configurable: true, writable: true });
15
+ });
16
+
17
+ test("prefers crypto.randomUUID when the secure-context API exists", () => {
18
+ Object.defineProperty(globalThis, "crypto", { value: { randomUUID: () => "0b6f2f2e-1111-2222-3333-444455556666" }, configurable: true, writable: true });
19
+ assert.equal(newId(), "0b6f2f2e-1111-2222-3333-444455556666");
20
+ });
21
+
22
+ test("falls back on insecure origins where randomUUID is missing", () => {
23
+ // http://<LAN-IP>:30143 → crypto 在、randomUUID 不在(裸调会 TypeError)
24
+ Object.defineProperty(globalThis, "crypto", { value: { getRandomValues: (a) => a }, configurable: true, writable: true });
25
+ const id = newId();
26
+ assert.match(id, SESSION_ID_RE, `fallback id must be a valid session id, got ${id}`);
27
+ });
28
+
29
+ test("falls back when crypto itself is unavailable", () => {
30
+ Object.defineProperty(globalThis, "crypto", { value: undefined, configurable: true, writable: true });
31
+ assert.match(newId(), SESSION_ID_RE);
32
+ });
33
+
34
+ test("fallback ids stay unique across rapid calls", () => {
35
+ Object.defineProperty(globalThis, "crypto", { value: {}, configurable: true, writable: true });
36
+ const ids = new Set(Array.from({ length: 200 }, () => newId()));
37
+ assert.equal(ids.size, 200);
38
+ });
package/lib/id.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 前端 id 生成(会话 id / 画布节点 id / 草稿 id / 通知 id 等)。
3
+ *
4
+ * **一律用它,别裸调 `crypto.randomUUID()`**:该方法只在**安全上下文**存在
5
+ * (https / localhost)。局域网访问(`npm run dev:lan` → `http://192.168.x.x:30143`)
6
+ * 或老浏览器里它是 undefined,裸调直接抛 “crypto.randomUUID is not a function”
7
+ * —— 任务行「新建会话」2026-09-14 就栽在这里(同一批调用里有的做了兜底、有的漏了)。
8
+ *
9
+ * 退化实现产出的 id 仍是 `[A-Za-z0-9-]`,满足服务端会话 id 校验
10
+ * (`SESSION_ID_RE`,见 `app/api/agent/new/route.ts`),可直接当会话 id 用。
11
+ */
12
+ export function newId(): string {
13
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
14
+ return crypto.randomUUID();
15
+ }
16
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
17
+ }
@@ -0,0 +1,24 @@
1
+ import type { AgentMessage } from "@/lib/types";
2
+
3
+ /**
4
+ * 从消息中提取可渲染的 markdown 文本(钉卡快照用)。
5
+ * 只取 text 块,忽略 thinking / 工具调用 / 图片等结构 —— 钉卡只渲染内容,与消息气泡解耦。
6
+ */
7
+ export function extractMessageMarkdown(message: AgentMessage): string {
8
+ const content = (message as unknown as { content?: unknown }).content;
9
+ const parts: string[] = [];
10
+ const push = (c: unknown): void => {
11
+ if (typeof c === "string") {
12
+ parts.push(c);
13
+ } else if (Array.isArray(c)) {
14
+ for (const b of c) {
15
+ if (b && typeof b === "object") {
16
+ const t = b as { type?: string; text?: string };
17
+ if (t.type === "text" && typeof t.text === "string") parts.push(t.text);
18
+ }
19
+ }
20
+ }
21
+ };
22
+ push(content);
23
+ return parts.join("\n\n").trim();
24
+ }
@@ -1,6 +1,6 @@
1
1
  export interface ModelsData {
2
2
  models: Record<string, string>;
3
- modelList: { id: string; name: string; provider: string }[];
3
+ modelList: { id: string; name: string; provider: string; input?: string[] }[];
4
4
  defaultModel: { provider: string; modelId: string } | null;
5
5
  thinkingLevels: Record<string, string[]>;
6
6
  thinkingLevelMaps: Record<string, Record<string, string | null>>;
package/lib/pi-types.ts CHANGED
@@ -6,7 +6,12 @@ import type {
6
6
  SlashCommandInfo,
7
7
  Theme,
8
8
  } from "@earendil-works/pi-coding-agent";
9
- import type { AgentMessage as PiAgentMessage } from "@earendil-works/pi-agent-core";
9
+ import type {
10
+ AgentLoopTurnUpdate,
11
+ AgentMessage as PiAgentMessage,
12
+ PrepareNextTurnContext,
13
+ } from "@earendil-works/pi-agent-core";
14
+ import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
10
15
 
11
16
  export interface ContextUsage {
12
17
  percent: number | null;
@@ -138,6 +143,10 @@ export interface AgentSessionLike {
138
143
  thinkingLevel?: string;
139
144
  streamingMessage?: PiAgentMessage;
140
145
  };
146
+ prepareNextTurnWithContext?: (
147
+ context: PrepareNextTurnContext,
148
+ signal?: AbortSignal,
149
+ ) => Promise<AgentLoopTurnUpdate | undefined> | AgentLoopTurnUpdate | undefined;
141
150
  };
142
151
  readonly extensionRunner: ExtensionRunnerLike;
143
152
  readonly promptTemplates: readonly PromptTemplateLike[];
@@ -153,6 +162,15 @@ export interface AgentSessionLike {
153
162
  source?: "interactive" | "rpc";
154
163
  preflightResult?: (success: boolean) => void;
155
164
  }): Promise<void>;
165
+ sendCustomMessage<T = unknown>(message: {
166
+ customType: string;
167
+ content: string | (TextContent | ImageContent)[];
168
+ display: boolean;
169
+ details?: T;
170
+ }, options?: {
171
+ triggerTurn?: boolean;
172
+ deliverAs?: "steer" | "followUp" | "nextTurn";
173
+ }): Promise<void>;
156
174
  abort(): Promise<void>;
157
175
  executeBash(command: string, onChunk?: (chunk: string) => void, options?: {
158
176
  excludeFromContext?: boolean;
@@ -0,0 +1,85 @@
1
+ "use client";
2
+
3
+ import { useSyncExternalStore } from "react";
4
+
5
+ export interface PinnedMessageItem {
6
+ id: string;
7
+ /** 快照内容(markdown 文本)——钉卡只渲染内容,与消息气泡/会话解耦 */
8
+ content: string;
9
+ x: number;
10
+ y: number;
11
+ w: number;
12
+ /** 高度:undefined = 初始随内容自适应;缩放/resize 后变为固定值 */
13
+ h?: number;
14
+ }
15
+
16
+ type Listener = () => void;
17
+
18
+ /**
19
+ * 全局钉 store:pins 存活在模块级(与任何会话组件无关)。
20
+ * 跨会话/看板切换保留;刷新页面不持久化(内存态,符合设计)。
21
+ */
22
+ let pins: PinnedMessageItem[] = [];
23
+ const listeners = new Set<Listener>();
24
+
25
+ function emit() {
26
+ for (const l of listeners) l();
27
+ }
28
+
29
+ function subscribe(listener: Listener) {
30
+ listeners.add(listener);
31
+ return () => {
32
+ listeners.delete(listener);
33
+ };
34
+ }
35
+
36
+ function getSnapshot() {
37
+ return pins;
38
+ }
39
+
40
+ let pinCount = 0;
41
+
42
+ /** 钉住内容:卡片出现在鼠标下方,多张级联偏移,clamp 视口内 */
43
+ export function pin(content: string, clientX: number, clientY: number) {
44
+ const vw = window.innerWidth;
45
+ const vh = window.innerHeight;
46
+ const w = Math.min(340, Math.max(240, vw - 40));
47
+ const offset = (pinCount % 8) * 22;
48
+ pinCount += 1;
49
+ const item: PinnedMessageItem = {
50
+ id: `pin-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
51
+ content,
52
+ x: Math.min(Math.max(0, clientX + offset), Math.max(0, vw - w - 4)),
53
+ y: Math.min(Math.max(0, clientY + 14 + offset), Math.max(0, vh - 48)),
54
+ w,
55
+ };
56
+ pins = [...pins, item];
57
+ emit();
58
+ }
59
+
60
+ export function closePin(id: string) {
61
+ pins = pins.filter((p) => p.id !== id);
62
+ emit();
63
+ }
64
+
65
+ export function movePin(id: string, patch: Partial<Pick<PinnedMessageItem, "x" | "y" | "w" | "h">>) {
66
+ pins = pins.map((p) => (p.id === id ? { ...p, ...patch } : p));
67
+ emit();
68
+ }
69
+
70
+ /** 激活置顶:把卡片移到数组末尾(zIndex 最高) */
71
+ export function activatePin(id: string) {
72
+ if (pins.length <= 1) return;
73
+ const idx = pins.findIndex((p) => p.id === id);
74
+ if (idx === -1 || idx === pins.length - 1) return;
75
+ const next = [...pins];
76
+ const [item] = next.splice(idx, 1);
77
+ next.push(item);
78
+ pins = next;
79
+ emit();
80
+ }
81
+
82
+ /** 订阅 pins 快照(组件用) */
83
+ export function usePins(): PinnedMessageItem[] {
84
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
85
+ }
@@ -0,0 +1,106 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
4
+ import lockfile from "proper-lockfile";
5
+
6
+ const DEFAULT_TOOLS = ["read", "bash", "edit", "write"];
7
+ const SHELL_TOOLS = new Set(["bash", "powershell"]);
8
+
9
+ function isRecord(value: unknown): value is Record<string, unknown> {
10
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11
+ }
12
+
13
+ export function isPowerShellToolEnabled(
14
+ defaultTools: readonly string[] | undefined,
15
+ platform: NodeJS.Platform = process.platform,
16
+ ): boolean {
17
+ return platform === "win32"
18
+ && defaultTools?.includes("powershell") === true
19
+ && !defaultTools.includes("bash");
20
+ }
21
+
22
+ export function replaceShellTool(
23
+ toolNames: readonly string[],
24
+ usePowerShell: boolean,
25
+ ): string[] {
26
+ const shell = usePowerShell ? "powershell" : "bash";
27
+ const result: string[] = [];
28
+ for (const name of toolNames) {
29
+ const next = SHELL_TOOLS.has(name) ? shell : name;
30
+ if (!result.includes(next)) result.push(next);
31
+ }
32
+ return result;
33
+ }
34
+
35
+ export function resolveShellTools(
36
+ toolNames: readonly string[],
37
+ defaultTools: readonly string[] | undefined,
38
+ platform: NodeJS.Platform = process.platform,
39
+ ): string[] {
40
+ return replaceShellTool(toolNames, isPowerShellToolEnabled(defaultTools, platform));
41
+ }
42
+
43
+ export function getPowerShellSettingsPath(agentDir = getAgentDir()): string {
44
+ return join(agentDir, "settings.json");
45
+ }
46
+
47
+ function parseSettings(path: string): Record<string, unknown> {
48
+ if (!existsSync(path)) return {};
49
+ const parsed: unknown = JSON.parse(readFileSync(path, "utf8"));
50
+ if (!isRecord(parsed)) throw new Error("Invalid settings.json: expected an object");
51
+ return parsed;
52
+ }
53
+
54
+ function configuredTools(settings: Record<string, unknown>): string[] | undefined {
55
+ if (settings.defaultTools === undefined) return undefined;
56
+ if (
57
+ !Array.isArray(settings.defaultTools)
58
+ || settings.defaultTools.some((name) => typeof name !== "string")
59
+ ) {
60
+ throw new Error("Invalid settings.json: defaultTools must be an array of strings");
61
+ }
62
+ return settings.defaultTools as string[];
63
+ }
64
+
65
+ export async function readPowerShellToolEnabled(
66
+ settingsPath = getPowerShellSettingsPath(),
67
+ platform: NodeJS.Platform = process.platform,
68
+ ): Promise<boolean> {
69
+ if (!existsSync(settingsPath)) return false;
70
+ const release = await lockfile.lock(settingsPath, { realpath: false, retries: 10 });
71
+ try {
72
+ return isPowerShellToolEnabled(configuredTools(parseSettings(settingsPath)), platform);
73
+ } finally {
74
+ await release();
75
+ }
76
+ }
77
+
78
+ export async function writePowerShellToolEnabled(
79
+ enabled: boolean,
80
+ settingsPath = getPowerShellSettingsPath(),
81
+ platform: NodeJS.Platform = process.platform,
82
+ ): Promise<boolean> {
83
+ if (platform !== "win32") throw new Error("PowerShell tool settings are only available on Windows");
84
+
85
+ mkdirSync(dirname(settingsPath), { recursive: true });
86
+ try {
87
+ writeFileSync(settingsPath, "{}", { flag: "wx", mode: 0o600 });
88
+ } catch (error) {
89
+ if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
90
+ }
91
+ const release = await lockfile.lock(settingsPath, { realpath: false, retries: 10 });
92
+ try {
93
+ const settings = parseSettings(settingsPath);
94
+ const currentTools = configuredTools(settings) ?? DEFAULT_TOOLS;
95
+ const nextTools = replaceShellTool(currentTools, enabled);
96
+ if (!currentTools.some((name) => SHELL_TOOLS.has(name))) {
97
+ nextTools.push(enabled ? "powershell" : "bash");
98
+ }
99
+ settings.defaultTools = nextTools;
100
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf8");
101
+ chmodSync(settingsPath, 0o600);
102
+ } finally {
103
+ await release();
104
+ }
105
+ return enabled;
106
+ }
@@ -0,0 +1,4 @@
1
+ export function buildQuotedSelection(text: string, intro: string, question: string): string {
2
+ const quote = text.trim().split("\n").map((line) => `> ${line}`).join("\n");
3
+ return `${intro}\n\n${quote}\n\n${question}`;
4
+ }