@rexvane/piweb 0.3.21 → 0.3.22

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 (293) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +6 -4
  3. package/.next/build-manifest.json +5 -5
  4. package/.next/next-minimal-server.js.nft.json +1 -1
  5. package/.next/next-server.js.nft.json +1 -1
  6. package/.next/prerender-manifest.json +7 -7
  7. package/.next/react-loadable-manifest.json +10 -10
  8. package/.next/required-server-files.js +16 -1
  9. package/.next/required-server-files.json +16 -1
  10. package/.next/routes-manifest.json +12 -0
  11. package/.next/server/app/_global-error/page.js +2 -2
  12. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  13. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  14. package/.next/server/app/_global-error.html +1 -1
  15. package/.next/server/app/_global-error.meta +8 -0
  16. package/.next/server/app/_global-error.rsc +15 -11
  17. package/.next/server/app/_global-error.segments/_full.segment.rsc +15 -11
  18. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +20 -16
  19. package/.next/server/app/_global-error.segments/_tree.segment.rsc +3 -1
  20. package/.next/server/app/_not-found/page.js +1 -1
  21. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  22. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  23. package/.next/server/app/_not-found.html +1 -1
  24. package/.next/server/app/_not-found.meta +8 -0
  25. package/.next/server/app/_not-found.rsc +17 -13
  26. package/.next/server/app/_not-found.segments/_full.segment.rsc +17 -13
  27. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +24 -20
  28. package/.next/server/app/_not-found.segments/_tree.segment.rsc +4 -2
  29. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  30. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
  31. package/.next/server/app/api/agent/[id]/route.js +1 -1
  32. package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
  33. package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
  34. package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
  35. package/.next/server/app/api/agent/new/route.js +1 -1
  36. package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
  37. package/.next/server/app/api/config/route.js +1 -1
  38. package/.next/server/app/api/config/route.js.nft.json +1 -1
  39. package/.next/server/app/api/files/route.js +1 -1
  40. package/.next/server/app/api/files/route.js.nft.json +1 -1
  41. package/.next/server/app/api/fs/route.js +1 -1
  42. package/.next/server/app/api/fs/route.js.nft.json +1 -1
  43. package/.next/server/app/api/git/route.js +4 -4
  44. package/.next/server/app/api/git/route.js.nft.json +1 -1
  45. package/.next/server/app/api/github/route.js +5 -0
  46. package/.next/server/app/api/github/route.js.nft.json +1 -0
  47. package/.next/server/app/api/github/route_client-reference-manifest.js +1 -0
  48. package/.next/server/app/api/growth/route.js +1 -1
  49. package/.next/server/app/api/growth/route.js.nft.json +1 -1
  50. package/.next/server/app/api/health/route.js +1 -1
  51. package/.next/server/app/api/health/route.js.nft.json +1 -1
  52. package/.next/server/app/api/models/defaults/route.js +1 -0
  53. package/.next/server/app/api/models/defaults/route.js.nft.json +1 -0
  54. package/.next/server/app/api/models/defaults/route_client-reference-manifest.js +1 -0
  55. package/.next/server/app/api/models/route.js +1 -1
  56. package/.next/server/app/api/models/route.js.nft.json +1 -1
  57. package/.next/server/app/api/pi-settings/route.js +1 -1
  58. package/.next/server/app/api/pi-settings/route.js.nft.json +1 -1
  59. package/.next/server/app/api/plugins/route.js +1 -1
  60. package/.next/server/app/api/plugins/route.js.nft.json +1 -1
  61. package/.next/server/app/api/prompts/route.js +1 -1
  62. package/.next/server/app/api/prompts/route.js.nft.json +1 -1
  63. package/.next/server/app/api/remote/route.js +3 -3
  64. package/.next/server/app/api/remote/route.js.nft.json +1 -1
  65. package/.next/server/app/api/security/route.js +1 -1
  66. package/.next/server/app/api/security/route.js.nft.json +1 -1
  67. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  68. package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
  69. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  70. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  71. package/.next/server/app/api/sessions/import/route.js +2 -2
  72. package/.next/server/app/api/sessions/import/route.js.nft.json +1 -1
  73. package/.next/server/app/api/sessions/route.js +1 -1
  74. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  75. package/.next/server/app/api/skills/route.js +2 -2
  76. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  77. package/.next/server/app/api/update/route.js +2 -2
  78. package/.next/server/app/api/update/route.js.nft.json +1 -1
  79. package/.next/server/app/api/version/route.js +1 -1
  80. package/.next/server/app/api/version/route.js.nft.json +1 -1
  81. package/.next/server/app/api/web-auth/route.js +1 -1
  82. package/.next/server/app/api/web-auth/route.js.nft.json +1 -1
  83. package/.next/server/app/api/workspaces/route.js +1 -1
  84. package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  85. package/.next/server/app/icon.svg/route.js +1 -1
  86. package/.next/server/app/icon.svg/route.js.nft.json +1 -1
  87. package/.next/server/app/icon.svg.meta +1 -1
  88. package/.next/server/app/index.html +1 -1
  89. package/.next/server/app/index.meta +8 -0
  90. package/.next/server/app/index.rsc +19 -13
  91. package/.next/server/app/index.segments/__PAGE__.segment.rsc +25 -19
  92. package/.next/server/app/index.segments/_full.segment.rsc +19 -13
  93. package/.next/server/app/index.segments/_tree.segment.rsc +3 -2
  94. package/.next/server/app/login/page.js +1 -1
  95. package/.next/server/app/login/page.js.nft.json +1 -1
  96. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  97. package/.next/server/app/login.html +1 -1
  98. package/.next/server/app/login.meta +8 -0
  99. package/.next/server/app/login.rsc +23 -17
  100. package/.next/server/app/login.segments/_full.segment.rsc +23 -17
  101. package/.next/server/app/login.segments/_tree.segment.rsc +4 -2
  102. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +30 -24
  103. package/.next/server/app/page.js +1 -1
  104. package/.next/server/app/page.js.nft.json +1 -1
  105. package/.next/server/app/page_client-reference-manifest.js +1 -1
  106. package/.next/server/app-paths-manifest.json +6 -4
  107. package/.next/server/chunks/229.js +1 -1
  108. package/.next/server/chunks/421.js +1 -1
  109. package/.next/server/chunks/430.js +215 -31
  110. package/.next/server/chunks/496.js +1 -1
  111. package/.next/server/chunks/538.js +1 -1
  112. package/.next/server/chunks/662.js +2 -2
  113. package/.next/server/chunks/686.js +1 -1
  114. package/.next/server/chunks/813.js +23 -1
  115. package/.next/server/chunks/920.js +2 -2
  116. package/.next/server/chunks/924.js +1 -1
  117. package/.next/server/chunks/970.js +305 -0
  118. package/.next/server/middleware-build-manifest.js +1 -1
  119. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  120. package/.next/server/middleware.js +185 -23
  121. package/.next/server/middleware.js.nft.json +1 -1
  122. package/.next/server/pages/404.html +1 -1
  123. package/.next/server/pages/500.html +1 -1
  124. package/.next/server/preview-props.json +5 -0
  125. package/.next/server/server-reference-manifest.json +1 -1
  126. package/.next/static/WMazYvD-gbeLsCUfUxvvM/_buildManifest.js +1 -0
  127. package/.next/static/chunks/316-698d10eb465bd8ef.js +1 -0
  128. package/.next/static/chunks/3794-0978865cda773008.js +52 -0
  129. package/.next/static/chunks/4673.4cf66cbdd8364c57.js +1 -0
  130. package/.next/static/chunks/4686-09fcd0028079006c.js +1 -0
  131. package/.next/static/chunks/4778.eddd3a5813f85824.js +1 -0
  132. package/.next/static/chunks/4bd1b696-e199e788e58acf79.js +1 -0
  133. package/.next/static/chunks/{5173.91ddb803785009f8.js → 5173.dfd1cbb795b9a21c.js} +1 -1
  134. package/.next/static/chunks/618.949981da99be7182.js +4 -0
  135. package/.next/static/chunks/7411.67366dc5032a141d.js +1 -0
  136. package/.next/static/chunks/app/_global-error/page-f977af7f858990a2.js +1 -0
  137. package/.next/static/chunks/app/api/agent/[id]/events/route-f977af7f858990a2.js +1 -0
  138. package/.next/static/chunks/app/api/agent/[id]/route-f977af7f858990a2.js +1 -0
  139. package/.next/static/chunks/app/api/agent/[id]/tree/route-f977af7f858990a2.js +1 -0
  140. package/.next/static/chunks/app/api/agent/new/route-f977af7f858990a2.js +1 -0
  141. package/.next/static/chunks/app/api/config/route-f977af7f858990a2.js +1 -0
  142. package/.next/static/chunks/app/api/files/route-f977af7f858990a2.js +1 -0
  143. package/.next/static/chunks/app/api/fs/route-f977af7f858990a2.js +1 -0
  144. package/.next/static/chunks/app/api/git/route-f977af7f858990a2.js +1 -0
  145. package/.next/static/chunks/app/api/github/route-f977af7f858990a2.js +1 -0
  146. package/.next/static/chunks/app/api/growth/route-f977af7f858990a2.js +1 -0
  147. package/.next/static/chunks/app/api/health/route-f977af7f858990a2.js +1 -0
  148. package/.next/static/chunks/app/api/models/defaults/route-f977af7f858990a2.js +1 -0
  149. package/.next/static/chunks/app/api/models/route-f977af7f858990a2.js +1 -0
  150. package/.next/static/chunks/app/api/pi-settings/route-f977af7f858990a2.js +1 -0
  151. package/.next/static/chunks/app/api/plugins/route-f977af7f858990a2.js +1 -0
  152. package/.next/static/chunks/app/api/prompts/route-f977af7f858990a2.js +1 -0
  153. package/.next/static/chunks/app/api/remote/route-f977af7f858990a2.js +1 -0
  154. package/.next/static/chunks/app/api/security/route-f977af7f858990a2.js +1 -0
  155. package/.next/static/chunks/app/api/sessions/[id]/export/route-f977af7f858990a2.js +1 -0
  156. package/.next/static/chunks/app/api/sessions/[id]/route-f977af7f858990a2.js +1 -0
  157. package/.next/static/chunks/app/api/sessions/import/route-f977af7f858990a2.js +1 -0
  158. package/.next/static/chunks/app/api/sessions/route-f977af7f858990a2.js +1 -0
  159. package/.next/static/chunks/app/api/skills/route-f977af7f858990a2.js +1 -0
  160. package/.next/static/chunks/app/api/update/route-f977af7f858990a2.js +1 -0
  161. package/.next/static/chunks/app/api/version/route-f977af7f858990a2.js +1 -0
  162. package/.next/static/chunks/app/api/web-auth/route-f977af7f858990a2.js +1 -0
  163. package/.next/static/chunks/app/api/workspaces/route-f977af7f858990a2.js +1 -0
  164. package/.next/static/chunks/app/page-fc4ed2ff29b6235e.js +1 -0
  165. package/.next/static/chunks/framework-47b723d27f4a4963.js +1 -0
  166. package/.next/static/chunks/main-5403f0764579e5fe.js +5 -0
  167. package/.next/static/chunks/next/dist/client/components/builtin/app-error-f977af7f858990a2.js +1 -0
  168. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f977af7f858990a2.js +1 -0
  169. package/.next/static/chunks/next/dist/client/components/builtin/not-found-f977af7f858990a2.js +1 -0
  170. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f977af7f858990a2.js +1 -0
  171. package/.next/static/chunks/webpack-22ebffc20adb44ae.js +1 -0
  172. package/.next/static/css/6671d0d1589fdc0e.css +1 -0
  173. package/.next/static/css/{2959bd6b626b7ffe.css → f15a853af8b5127f.css} +1 -1
  174. package/.next/types/app/api/agent/[id]/events/route.ts +3 -1
  175. package/.next/types/app/api/agent/[id]/route.ts +3 -1
  176. package/.next/types/app/api/agent/[id]/tree/route.ts +3 -1
  177. package/.next/types/app/api/agent/new/route.ts +3 -1
  178. package/.next/types/app/api/config/route.ts +3 -1
  179. package/.next/types/app/api/files/route.ts +3 -1
  180. package/.next/types/app/api/fs/route.ts +3 -1
  181. package/.next/types/app/api/git/route.ts +3 -1
  182. package/.next/types/app/api/github/route.ts +355 -0
  183. package/.next/types/app/api/growth/route.ts +3 -1
  184. package/.next/types/app/api/health/route.ts +3 -1
  185. package/.next/types/app/api/models/defaults/route.ts +355 -0
  186. package/.next/types/app/api/models/route.ts +3 -1
  187. package/.next/types/app/api/pi-settings/route.ts +3 -1
  188. package/.next/types/app/api/plugins/route.ts +3 -1
  189. package/.next/types/app/api/prompts/route.ts +3 -1
  190. package/.next/types/app/api/remote/route.ts +3 -1
  191. package/.next/types/app/api/security/route.ts +3 -1
  192. package/.next/types/app/api/sessions/[id]/export/route.ts +3 -1
  193. package/.next/types/app/api/sessions/[id]/route.ts +3 -1
  194. package/.next/types/app/api/sessions/import/route.ts +3 -1
  195. package/.next/types/app/api/sessions/route.ts +3 -1
  196. package/.next/types/app/api/skills/route.ts +3 -1
  197. package/.next/types/app/api/update/route.ts +3 -1
  198. package/.next/types/app/api/version/route.ts +3 -1
  199. package/.next/types/app/api/web-auth/route.ts +3 -1
  200. package/.next/types/app/api/workspaces/route.ts +3 -1
  201. package/.next/types/app/layout.ts +4 -1
  202. package/.next/types/app/login/page.ts +4 -1
  203. package/.next/types/app/page.ts +4 -1
  204. package/.next/types/cache-life.d.ts +11 -43
  205. package/.next/types/routes.d.ts +3 -1
  206. package/.next/types/validator.ts +76 -2
  207. package/package.json +2 -2
  208. package/src/app/api/files/route.ts +5 -2
  209. package/src/app/api/github/route.ts +26 -0
  210. package/src/app/api/models/defaults/route.ts +18 -0
  211. package/src/app/api/models/route.ts +24 -1
  212. package/src/app/globals.css +186 -0
  213. package/src/components/AppShell.tsx +82 -30
  214. package/src/components/ChatInput.tsx +244 -63
  215. package/src/components/ChatWindow.tsx +18 -27
  216. package/src/components/ContextMeter.tsx +193 -143
  217. package/src/components/GitPanel.tsx +110 -40
  218. package/src/components/ProjectPanel.tsx +55 -30
  219. package/src/components/PromptPanel.tsx +2 -4
  220. package/src/components/ProviderSetupModal.module.css +20 -0
  221. package/src/components/ProviderSetupModal.tsx +134 -29
  222. package/src/components/SettingsPanel.tsx +243 -27
  223. package/src/components/TrajectoryView.tsx +4 -6
  224. package/src/components/composer/ComposerImages.tsx +306 -0
  225. package/src/hooks/useGrowth.ts +3 -0
  226. package/src/hooks/usePiWeb.ts +12 -2
  227. package/src/hooks/useWorkspaceFiles.ts +93 -0
  228. package/src/i18n.tsx +108 -2
  229. package/src/lib/agent-manager.ts +135 -104
  230. package/src/lib/files-service.ts +100 -1
  231. package/src/lib/format.ts +56 -0
  232. package/src/lib/git-service.ts +45 -13
  233. package/src/lib/github-identity.ts +245 -0
  234. package/src/lib/growth-service.ts +6 -2
  235. package/src/lib/hero-model-memory.ts +28 -0
  236. package/src/lib/model-defaults.ts +105 -0
  237. package/src/lib/model-draft.ts +257 -9
  238. package/src/lib/model-endpoint.ts +23 -0
  239. package/src/lib/model-files.ts +33 -0
  240. package/src/lib/models-service.ts +240 -78
  241. package/src/lib/pi.ts +27 -2
  242. package/src/lib/process-format.ts +3 -2
  243. package/src/lib/session/metrics.ts +31 -0
  244. package/src/lib/thinking-level.ts +39 -0
  245. package/src/lib/trajectory.ts +17 -3
  246. package/src/lib/types.ts +12 -1
  247. package/src/lib/workspace-index.ts +270 -0
  248. package/.next/server/chunks/741.js +0 -165
  249. package/.next/static/chunks/316-5ea443ee6b512aa9.js +0 -1
  250. package/.next/static/chunks/3794-3679f1c05160977c.js +0 -52
  251. package/.next/static/chunks/4673.8a5a9e6855350e34.js +0 -1
  252. package/.next/static/chunks/4686-882531aef1d2e250.js +0 -1
  253. package/.next/static/chunks/4778.305dc6abb9889627.js +0 -1
  254. package/.next/static/chunks/4bd1b696-93bf506b236d6248.js +0 -1
  255. package/.next/static/chunks/618.ee5d5bf1c647e483.js +0 -4
  256. package/.next/static/chunks/839.bfd2db36483faa3e.js +0 -1
  257. package/.next/static/chunks/app/_global-error/page-b179d9f7f6f2daf9.js +0 -1
  258. package/.next/static/chunks/app/api/agent/[id]/events/route-b179d9f7f6f2daf9.js +0 -1
  259. package/.next/static/chunks/app/api/agent/[id]/route-b179d9f7f6f2daf9.js +0 -1
  260. package/.next/static/chunks/app/api/agent/[id]/tree/route-b179d9f7f6f2daf9.js +0 -1
  261. package/.next/static/chunks/app/api/agent/new/route-b179d9f7f6f2daf9.js +0 -1
  262. package/.next/static/chunks/app/api/config/route-b179d9f7f6f2daf9.js +0 -1
  263. package/.next/static/chunks/app/api/files/route-b179d9f7f6f2daf9.js +0 -1
  264. package/.next/static/chunks/app/api/fs/route-b179d9f7f6f2daf9.js +0 -1
  265. package/.next/static/chunks/app/api/git/route-b179d9f7f6f2daf9.js +0 -1
  266. package/.next/static/chunks/app/api/growth/route-b179d9f7f6f2daf9.js +0 -1
  267. package/.next/static/chunks/app/api/health/route-b179d9f7f6f2daf9.js +0 -1
  268. package/.next/static/chunks/app/api/models/route-b179d9f7f6f2daf9.js +0 -1
  269. package/.next/static/chunks/app/api/pi-settings/route-b179d9f7f6f2daf9.js +0 -1
  270. package/.next/static/chunks/app/api/plugins/route-b179d9f7f6f2daf9.js +0 -1
  271. package/.next/static/chunks/app/api/prompts/route-b179d9f7f6f2daf9.js +0 -1
  272. package/.next/static/chunks/app/api/remote/route-b179d9f7f6f2daf9.js +0 -1
  273. package/.next/static/chunks/app/api/security/route-b179d9f7f6f2daf9.js +0 -1
  274. package/.next/static/chunks/app/api/sessions/[id]/export/route-b179d9f7f6f2daf9.js +0 -1
  275. package/.next/static/chunks/app/api/sessions/[id]/route-b179d9f7f6f2daf9.js +0 -1
  276. package/.next/static/chunks/app/api/sessions/import/route-b179d9f7f6f2daf9.js +0 -1
  277. package/.next/static/chunks/app/api/sessions/route-b179d9f7f6f2daf9.js +0 -1
  278. package/.next/static/chunks/app/api/skills/route-b179d9f7f6f2daf9.js +0 -1
  279. package/.next/static/chunks/app/api/update/route-b179d9f7f6f2daf9.js +0 -1
  280. package/.next/static/chunks/app/api/version/route-b179d9f7f6f2daf9.js +0 -1
  281. package/.next/static/chunks/app/api/web-auth/route-b179d9f7f6f2daf9.js +0 -1
  282. package/.next/static/chunks/app/api/workspaces/route-b179d9f7f6f2daf9.js +0 -1
  283. package/.next/static/chunks/app/page-c04af72e549695bd.js +0 -1
  284. package/.next/static/chunks/framework-c4e651fe89edfa91.js +0 -1
  285. package/.next/static/chunks/main-6159b22a8cb0b7c5.js +0 -5
  286. package/.next/static/chunks/next/dist/client/components/builtin/app-error-b179d9f7f6f2daf9.js +0 -1
  287. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-b179d9f7f6f2daf9.js +0 -1
  288. package/.next/static/chunks/next/dist/client/components/builtin/not-found-b179d9f7f6f2daf9.js +0 -1
  289. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-b179d9f7f6f2daf9.js +0 -1
  290. package/.next/static/chunks/webpack-9b4bb574e5817654.js +0 -1
  291. package/.next/static/css/ea27b9e30f76303f.css +0 -1
  292. package/.next/static/sNX5GQkOWuK5YEID1hT-C/_buildManifest.js +0 -1
  293. /package/.next/static/{sNX5GQkOWuK5YEID1hT-C → WMazYvD-gbeLsCUfUxvvM}/_ssgManifest.js +0 -0
@@ -1712,6 +1712,192 @@ body[data-pebrel-theme="pebrel"][data-ds-dark-theme] {
1712
1712
  pointer-events: none;
1713
1713
  }
1714
1714
 
1715
+ /* 输入卡待发送图片:平铺缩略图 / 牌堆 / 扇形(src/components/composer/ComposerImages.tsx) */
1716
+ .pw-image-thumb {
1717
+ position: relative;
1718
+ flex: none;
1719
+ }
1720
+ .pw-image-thumb img {
1721
+ display: block;
1722
+ box-shadow: 0 0 0 0.5px var(--dsw-border-l2);
1723
+ }
1724
+ .pw-image-fan {
1725
+ position: relative;
1726
+ flex: none;
1727
+ transition: width 320ms cubic-bezier(0.2, 0.8, 0.2, 1), height 320ms cubic-bezier(0.2, 0.8, 0.2, 1);
1728
+ }
1729
+ .pw-image-card {
1730
+ position: absolute;
1731
+ left: 0;
1732
+ top: 0;
1733
+ width: 96px;
1734
+ height: 96px;
1735
+ transition: transform 360ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 200ms ease;
1736
+ }
1737
+ .pw-image-card[data-hidden="true"] {
1738
+ opacity: 0;
1739
+ pointer-events: none;
1740
+ }
1741
+ .pw-image-face {
1742
+ display: block;
1743
+ width: 100%;
1744
+ height: 100%;
1745
+ overflow: hidden;
1746
+ border-radius: 10px;
1747
+ /* 不透明的底:长图上下留白的地方不能透出后面那张 */
1748
+ background: linear-gradient(var(--dsw-selector), var(--dsw-selector)), var(--dsw-glass-input);
1749
+ box-shadow: 0 0 0 0.5px var(--dsw-border-l3), 0 1px 3px rgba(0, 0, 0, 0.12);
1750
+ transition: box-shadow var(--ds-duration-fast) var(--ds-ease-in-out);
1751
+ }
1752
+ .pw-image-card[data-lifted="true"] .pw-image-face {
1753
+ box-shadow: 0 0 0 0.5px var(--dsw-border-l4), 0 10px 24px rgba(0, 0, 0, 0.22);
1754
+ }
1755
+ .pw-image-face img {
1756
+ transition: opacity 240ms ease;
1757
+ }
1758
+ /* 牌堆里后面几张只露空白卡边,一眼看出是一叠;扇开时图淡入 */
1759
+ .pw-image-fan:not([data-expanded="true"]) .pw-image-card + .pw-image-card .pw-image-face img {
1760
+ opacity: 0;
1761
+ }
1762
+ .pw-image-face:focus-visible {
1763
+ outline: 2px solid var(--dsw-accent);
1764
+ outline-offset: 2px;
1765
+ }
1766
+ /* 张数多、露出的条带太窄:删除按钮只在悬停 / 聚焦那张上出现,免得挤成一排 */
1767
+ .pw-image-fan[data-crowded="true"] .pw-image-delete {
1768
+ opacity: 0;
1769
+ pointer-events: none;
1770
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-in-out);
1771
+ }
1772
+ .pw-image-fan[data-crowded="true"] .pw-image-card:hover .pw-image-delete,
1773
+ .pw-image-fan[data-crowded="true"] .pw-image-card:focus-within .pw-image-delete {
1774
+ opacity: 1;
1775
+ pointer-events: auto;
1776
+ }
1777
+ .pw-image-delete {
1778
+ position: absolute;
1779
+ top: -6px;
1780
+ right: -6px;
1781
+ display: flex;
1782
+ align-items: center;
1783
+ justify-content: center;
1784
+ width: 22px;
1785
+ height: 22px;
1786
+ border-radius: 999px;
1787
+ font-size: 11px;
1788
+ background: var(--dsw-label-primary);
1789
+ color: var(--dsw-bg-base);
1790
+ /* 一圈底色描边:压在别的图片上也看得清 */
1791
+ box-shadow: 0 0 0 1.5px var(--dsw-glass-input);
1792
+ }
1793
+ .pw-image-delete:disabled {
1794
+ opacity: 0.4;
1795
+ }
1796
+ /* 放大预览 */
1797
+ .pw-viewer {
1798
+ position: fixed;
1799
+ inset: 0;
1800
+ z-index: 200;
1801
+ display: flex;
1802
+ align-items: center;
1803
+ justify-content: center;
1804
+ padding: 56px 16px 24px;
1805
+ background: rgba(0, 0, 0, 0.78);
1806
+ }
1807
+ .pw-viewer-bar {
1808
+ position: absolute;
1809
+ top: 12px;
1810
+ left: 16px;
1811
+ right: 16px;
1812
+ display: flex;
1813
+ align-items: center;
1814
+ gap: 8px;
1815
+ }
1816
+ .pw-viewer-count {
1817
+ flex: 1;
1818
+ font-size: 13px;
1819
+ font-variant-numeric: tabular-nums;
1820
+ color: rgba(255, 255, 255, 0.78);
1821
+ }
1822
+ .pw-viewer-btn {
1823
+ height: 30px;
1824
+ min-width: 30px;
1825
+ padding: 0 12px;
1826
+ border-radius: 999px;
1827
+ font-size: 13px;
1828
+ color: #fff;
1829
+ background: rgba(255, 255, 255, 0.14);
1830
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1831
+ }
1832
+ .pw-viewer-btn:hover {
1833
+ background: rgba(255, 255, 255, 0.24);
1834
+ }
1835
+ .pw-viewer-btn:disabled {
1836
+ opacity: 0.4;
1837
+ }
1838
+ .pw-viewer-image {
1839
+ max-width: 100%;
1840
+ max-height: 100%;
1841
+ object-fit: contain;
1842
+ border-radius: 12px;
1843
+ }
1844
+ .pw-viewer-nav {
1845
+ position: absolute;
1846
+ top: 50%;
1847
+ width: 40px;
1848
+ height: 40px;
1849
+ margin-top: -20px;
1850
+ border-radius: 999px;
1851
+ font-size: 26px;
1852
+ line-height: 38px;
1853
+ color: #fff;
1854
+ background: rgba(255, 255, 255, 0.14);
1855
+ transition: background var(--ds-duration-fast) var(--ds-ease-in-out);
1856
+ }
1857
+ .pw-viewer-nav:hover {
1858
+ background: rgba(255, 255, 255, 0.24);
1859
+ }
1860
+ .pw-viewer-nav[data-side="prev"] {
1861
+ left: 16px;
1862
+ }
1863
+ .pw-viewer-nav[data-side="next"] {
1864
+ right: 16px;
1865
+ }
1866
+ .pw-viewer-btn:focus-visible,
1867
+ .pw-viewer-nav:focus-visible {
1868
+ outline: 2px solid #fff;
1869
+ outline-offset: 2px;
1870
+ }
1871
+ @media (prefers-reduced-motion: reduce) {
1872
+ .pw-image-fan,
1873
+ .pw-image-card {
1874
+ transition: none;
1875
+ }
1876
+ }
1877
+
1878
+ /* 设置页模型体检卡片里的小输入框 / 下拉(容量、视觉) */
1879
+ .pw-audit-field {
1880
+ width: 100%;
1881
+ height: 30px;
1882
+ padding: 0 8px;
1883
+ border: 0.5px solid var(--dsw-border-l2);
1884
+ border-radius: 9px;
1885
+ background: var(--dsw-glass-input);
1886
+ color: var(--dsw-label-primary);
1887
+ font-size: 12.5px;
1888
+ transition: border-color var(--ds-duration-fast) var(--ds-ease-in-out), box-shadow var(--ds-duration-fast) var(--ds-ease-in-out);
1889
+ }
1890
+ .pw-audit-field:focus {
1891
+ border-color: var(--dsw-accent);
1892
+ box-shadow: 0 0 0 2px var(--dsw-accent-soft);
1893
+ }
1894
+ .pw-audit-field[aria-invalid="true"] {
1895
+ border-color: var(--dsw-danger);
1896
+ }
1897
+ .pw-audit-field:disabled {
1898
+ opacity: 0.55;
1899
+ }
1900
+
1715
1901
  /* 项目栏 */
1716
1902
  .pw-project {
1717
1903
  background: var(--dsw-sidebar-fill);
@@ -41,6 +41,9 @@ import { useFileViewer } from "@/hooks/useFileViewer";
41
41
  import type { TreeNode } from "@/lib/growth-tree";
42
42
  import { syncPebrelTheme } from "@/lib/theme";
43
43
  import type { ModelChoice } from "@/components/ModelSelector";
44
+ import type { NewSessionDefaults } from "@/lib/model-defaults";
45
+ import { readRememberedHeroModel, writeRememberedHeroModel } from "@/lib/hero-model-memory";
46
+ import { newSessionThinkingLevel } from "@/lib/thinking-level";
44
47
  import type { ImageAttachment, TrajEntry } from "@/lib/types";
45
48
 
46
49
  // dsh ui-layout columns.ts 几何常量
@@ -164,6 +167,8 @@ export function AppShell() {
164
167
  const growthSelectLatest = useRef<() => void>(() => {});
165
168
  const [heroCwd, setHeroCwd] = useState("");
166
169
  const [heroModel, setHeroModel] = useState<{ provider: string; id: string } | null>(null);
170
+ /** 当前工作区的新会话默认值(pi 的初始模型规则 + 设置里的思考档位),切换工作区时重新取 */
171
+ const [heroDefaults, setHeroDefaults] = useState<NewSessionDefaults | null>(null);
167
172
  const [heroThinking, setHeroThinking] = useState("");
168
173
  const [isNarrow, setIsNarrow] = useState(false);
169
174
  const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
@@ -173,6 +178,29 @@ export function AppShell() {
173
178
  setSidebarCollapsed(localStorage.getItem("piweb.sidebarCollapsed") === "1");
174
179
  setDrawerOpen(localStorage.getItem("piweb.drawerOpen") === "1");
175
180
  }, []);
181
+ /** 新会话时加载用户之前的选择,或使用系统建议(第一个认证的) */
182
+ useEffect(() => {
183
+ if (!heroCwd) {
184
+ setHeroModel(null);
185
+ return;
186
+ }
187
+ // 只认这个工作区自己记住的模型;没有就不预选,输入框等用户在新会话页选
188
+ setHeroModel(readRememberedHeroModel(localStorage, heroCwd));
189
+ }, [heroCwd]);
190
+ useEffect(() => {
191
+ setHeroDefaults(null);
192
+ if (!heroCwd) return;
193
+ let stale = false;
194
+ fetch(`/api/models/defaults?cwd=${encodeURIComponent(heroCwd)}`)
195
+ .then((r) => r.json() as Promise<{ success?: boolean; data?: NewSessionDefaults }>)
196
+ .then((json) => {
197
+ if (!stale && json.success && json.data) setHeroDefaults(json.data);
198
+ })
199
+ .catch(() => undefined);
200
+ return () => {
201
+ stale = true;
202
+ };
203
+ }, [heroCwd]);
176
204
  /** 右侧抽屉开关(项目栏降级成抽屉入口后,它是"最右一列是否打开"唯一的开关) */
177
205
  const toggleDrawer = useCallback((next?: boolean) => {
178
206
  setDrawerOpen((cur) => {
@@ -280,11 +308,28 @@ export function AppShell() {
280
308
  })),
281
309
  [models],
282
310
  );
283
- const defaultModel = useMemo(() => modelChoices.find((m) => authByProvider[m.provider]), [modelChoices, authByProvider]);
311
+ // 新会话页当前选中的模型:只有在这个工作区选过(或记住过)才有;没有就是 undefined,输入框保持禁用
312
+ const heroChoice = useMemo(
313
+ () => (heroModel ? modelChoices.find((m) => m.provider === heroModel.provider && m.id === heroModel.id) : undefined),
314
+ [heroModel, modelChoices],
315
+ );
284
316
  const heroModelLevels = useMemo(
285
- () => (heroModel ? modelChoices.find((m) => m.provider === heroModel.provider && m.id === heroModel.id) : defaultModel)?.thinkingLevels ?? ["off", "minimal", "low", "medium", "high", "xhigh", "max"],
286
- [heroModel, modelChoices, defaultModel],
317
+ () => heroChoice?.thinkingLevels ?? ["off", "minimal", "low", "medium", "high", "xhigh", "max"],
318
+ [heroChoice],
287
319
  );
320
+ /**
321
+ * 新会话实际会用的思考档位:用户显式选过才算选择(下发时才带上);界面平时只显示这里算出的生效值,
322
+ * 不把它当作选择发给服务端。
323
+ */
324
+ const heroEffectiveThinking = useMemo(() => {
325
+ const choice = heroChoice;
326
+ return newSessionThinkingLevel({
327
+ supported: heroModelLevels,
328
+ requested: heroThinking,
329
+ modelOverride: choice ? heroDefaults?.modelThinkingLevels[`${choice.provider}/${choice.id}`] : undefined,
330
+ defaultLevel: heroDefaults?.defaultThinkingLevel,
331
+ });
332
+ }, [heroChoice, heroModelLevels, heroThinking, heroDefaults]);
288
333
 
289
334
 
290
335
  // ---------- 拖拽 ----------
@@ -462,12 +507,14 @@ export function AppShell() {
462
507
  setError(t.pickWorkspaceFirst);
463
508
  return { success: false };
464
509
  }
465
- // 用户没手动选过模型时也要把界面显示的默认模型显式下发,
466
- // 否则后端不 setModel、SDK 自选的默认与界面显示不一致。
467
- const effective = heroModel ?? (defaultModel ? { provider: defaultModel.provider, id: defaultModel.id } : null);
510
+ // 没选模型不建会话:输入框本来就禁用,这里再拦一次;模型一律显式下发,不让 SDK 自选
511
+ if (!heroChoice) {
512
+ setError(t.blockedComposer);
513
+ return { success: false };
514
+ }
468
515
  const p = await newSession(cwd, {
469
- provider: effective?.provider,
470
- modelId: effective?.id,
516
+ provider: heroChoice.provider,
517
+ modelId: heroChoice.id,
471
518
  thinking: heroThinking || undefined,
472
519
  });
473
520
  if (!p) return { success: false };
@@ -519,7 +566,7 @@ export function AppShell() {
519
566
  void sendCommand({ cmd: "fork" }).then((r) => {
520
567
  if (r.success && r.data?.sessionPath) openSession(r.data.sessionPath);
521
568
  });
522
- } else if (name === "reload") void sendCommand({ cmd: "reload" });
569
+ } else if (name === "reload") void sendCommand({ cmd: "reload" }).then(() => refreshModels());
523
570
  else setError(t.cmdUnknown.replace("{name}", name));
524
571
  },
525
572
  [sendCommand, currentId, closeSession, openSession, setError, t],
@@ -588,7 +635,9 @@ export function AppShell() {
588
635
  if (!path) return;
589
636
  updateDraft(draftKey, (previous) => {
590
637
  const references = previous.references ?? [];
591
- if (references.includes(path)) return previous;
638
+ // 目录在 @ 选择器里存成 `src/lib/`:去重按去掉尾斜杠比较,避免同一目录两条
639
+ const samePath = (a: string, b: string) => a.replace(/[\\/]+$/, "") === b.replace(/[\\/]+$/, "");
640
+ if (references.some((existing) => samePath(existing, path))) return previous;
592
641
  return { ...previous, references: [...references, path] };
593
642
  });
594
643
  requestAnimationFrame(() => document.querySelector<HTMLTextAreaElement>('[data-testid="composer"] textarea')?.focus());
@@ -823,15 +872,17 @@ export function AppShell() {
823
872
  providerNames={providerNames}
824
873
  authByProvider={authByProvider}
825
874
  addWorkspaceByPicker={addWorkspaceByPicker}
826
- heroModel={heroModel}
875
+ heroChoice={heroChoice}
827
876
  onSelectHeroModel={(provider, id) => {
828
- setHeroModel({ provider, id });
877
+ const choice = { provider, id };
878
+ setHeroModel(choice);
879
+ // 只记在当前工作区名下
880
+ if (heroCwd) writeRememberedHeroModel(localStorage, heroCwd, choice);
829
881
  const levels = modelChoices.find((model) => model.provider === provider && model.id === id)?.thinkingLevels ?? [];
830
882
  if (heroThinking && !levels.includes(heroThinking)) setHeroThinking("");
831
883
  }}
832
- defaultModel={defaultModel}
833
884
  heroModelLevels={heroModelLevels}
834
- heroThinking={heroThinking}
885
+ heroEffectiveThinking={heroEffectiveThinking}
835
886
  onSelectHeroThinking={setHeroThinking}
836
887
  />
837
888
  {/* 草稿阶段的错误行内显示(不再弹右下角) */}
@@ -962,6 +1013,7 @@ export function AppShell() {
962
1013
  authByProvider={authByProvider}
963
1014
  queue={snapshot?.queue ?? { steering: [], followUp: [] }}
964
1015
  commands={slashCommands}
1016
+ cwd={panelCwd}
965
1017
  onCommand={runSlashCommand}
966
1018
  onSend={sendPrompt}
967
1019
  onSteer={(text, images) => sendCommand({ cmd: "prompt", text, images, behavior: "steer" })}
@@ -1113,11 +1165,10 @@ function Hero({
1113
1165
  providerNames,
1114
1166
  authByProvider,
1115
1167
  addWorkspaceByPicker,
1116
- heroModel,
1168
+ heroChoice,
1117
1169
  onSelectHeroModel,
1118
- defaultModel,
1119
1170
  heroModelLevels,
1120
- heroThinking,
1171
+ heroEffectiveThinking,
1121
1172
  onSelectHeroThinking,
1122
1173
  }: {
1123
1174
  draft: ChatDraft;
@@ -1139,11 +1190,10 @@ function Hero({
1139
1190
  providerNames: Record<string, string>;
1140
1191
  authByProvider: Record<string, boolean>;
1141
1192
  addWorkspaceByPicker: () => Promise<string | null>;
1142
- heroModel: { provider: string; id: string } | null;
1193
+ heroChoice?: ModelChoice;
1143
1194
  onSelectHeroModel: (provider: string, id: string) => void;
1144
- defaultModel?: ModelChoice;
1145
1195
  heroModelLevels: string[];
1146
- heroThinking: string;
1196
+ heroEffectiveThinking: string;
1147
1197
  onSelectHeroThinking: (level: string) => void;
1148
1198
  }) {
1149
1199
  const { t } = useI18n();
@@ -1237,14 +1287,16 @@ function Hero({
1237
1287
 
1238
1288
  {/* 输入卡 */}
1239
1289
  <ChatInput
1240
- draft={draft}
1241
- onDraftChange={onDraftChange}
1242
- onUploadError={onUploadError}
1243
- onUploadProgress={onUploadProgress}
1244
- uploadFailure={uploadFailure}
1245
- pendingUploadCount={pendingUploadCount}
1246
- pendingSend={pendingSend}
1247
- onSendPendingChange={onSendPendingChange}
1290
+ draft={draft}
1291
+ onDraftChange={onDraftChange}
1292
+ onUploadError={onUploadError}
1293
+ onUploadProgress={onUploadProgress}
1294
+ uploadFailure={uploadFailure}
1295
+ pendingUploadCount={pendingUploadCount}
1296
+ pendingSend={pendingSend}
1297
+ onSendPendingChange={onSendPendingChange}
1298
+ // 新会话也能 @ 引用:候选来自上面选中的工作区
1299
+ cwd={cwd}
1248
1300
  commands={commands}
1249
1301
  onCommand={onCommand}
1250
1302
  isStreaming={false}
@@ -1252,8 +1304,8 @@ function Hero({
1252
1304
  contextTokens={null}
1253
1305
  contextWindow={null}
1254
1306
  contextVisible={false}
1255
- model={heroModel ? models.find((m) => m.provider === heroModel.provider && m.id === heroModel.id) ?? { provider: heroModel.provider, id: heroModel.id, name: heroModel.id, reasoning: false, contextWindow: 0 } : defaultModel}
1256
- thinkingLevel={heroThinking || undefined}
1307
+ model={heroChoice}
1308
+ thinkingLevel={heroEffectiveThinking}
1257
1309
  thinkingLevels={heroModelLevels}
1258
1310
  models={models}
1259
1311
  providerNames={providerNames}