@geminilight/mindos 0.6.39 → 0.6.41

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 (759) hide show
  1. package/README.md +31 -15
  2. package/README_zh.md +31 -15
  3. package/_standalone/.mindos-build-version +1 -1
  4. package/_standalone/.next/BUILD_ID +1 -1
  5. package/_standalone/.next/app-path-routes-manifest.json +19 -18
  6. package/_standalone/.next/build-manifest.json +3 -3
  7. package/_standalone/.next/cache/.previewinfo +1 -1
  8. package/_standalone/.next/cache/.rscinfo +1 -1
  9. package/_standalone/.next/cache/config.json +3 -3
  10. package/_standalone/.next/prerender-manifest.json +3 -3
  11. package/_standalone/.next/react-loadable-manifest.json +68 -2
  12. package/_standalone/.next/routes-manifest.json +6 -0
  13. package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
  14. package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  15. package/_standalone/.next/server/app/_global-error.html +2 -2
  16. package/_standalone/.next/server/app/_global-error.rsc +1 -1
  17. package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  18. package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  19. package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  20. package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  21. package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  22. package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  23. package/_standalone/.next/server/app/_not-found/page.js +2 -2
  24. package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  25. package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  26. package/_standalone/.next/server/app/agents/[agentKey]/page.js +2 -2
  27. package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
  28. package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
  29. package/_standalone/.next/server/app/agents/page.js +3 -3
  30. package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
  31. package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
  32. package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
  33. package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
  34. package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
  35. package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
  36. package/_standalone/.next/server/app/api/acp/config/route.js +1 -1
  37. package/_standalone/.next/server/app/api/acp/config/route.js.nft.json +1 -1
  38. package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
  39. package/_standalone/.next/server/app/api/acp/detect/route.js +1 -1
  40. package/_standalone/.next/server/app/api/acp/detect/route.js.nft.json +1 -1
  41. package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
  42. package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
  43. package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
  44. package/_standalone/.next/server/app/api/acp/session/route.js +1 -1
  45. package/_standalone/.next/server/app/api/acp/session/route.js.nft.json +1 -1
  46. package/_standalone/.next/server/app/api/acp/session/route_client-reference-manifest.js +1 -1
  47. package/_standalone/.next/server/app/api/agent-activity/route.js +1 -1
  48. package/_standalone/.next/server/app/api/agent-activity/route.js.nft.json +1 -1
  49. package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
  50. package/_standalone/.next/server/app/api/ask/route.js +137 -99
  51. package/_standalone/.next/server/app/api/ask/route.js.nft.json +1 -1
  52. package/_standalone/.next/server/app/api/ask/route_client-reference-manifest.js +1 -1
  53. package/_standalone/.next/server/app/api/ask-sessions/route_client-reference-manifest.js +1 -1
  54. package/_standalone/.next/server/app/api/auth/route_client-reference-manifest.js +1 -1
  55. package/_standalone/.next/server/app/api/backlinks/route.js +1 -1
  56. package/_standalone/.next/server/app/api/backlinks/route.js.nft.json +1 -1
  57. package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
  58. package/_standalone/.next/server/app/api/bootstrap/route.js +1 -1
  59. package/_standalone/.next/server/app/api/bootstrap/route.js.nft.json +1 -1
  60. package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
  61. package/_standalone/.next/server/app/api/changes/route.js +1 -1
  62. package/_standalone/.next/server/app/api/changes/route.js.nft.json +1 -1
  63. package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
  64. package/_standalone/.next/server/app/api/export/route.js +3 -3
  65. package/_standalone/.next/server/app/api/export/route.js.nft.json +1 -1
  66. package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
  67. package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
  68. package/_standalone/.next/server/app/api/file/import/route.js +2 -19
  69. package/_standalone/.next/server/app/api/file/import/route.js.nft.json +1 -1
  70. package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
  71. package/_standalone/.next/server/app/api/file/route.js +1 -18
  72. package/_standalone/.next/server/app/api/file/route.js.nft.json +1 -1
  73. package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +1 -1
  74. package/_standalone/.next/server/app/api/files/route.js +1 -1
  75. package/_standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  76. package/_standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  77. package/_standalone/.next/server/app/api/git/route.js +1 -1
  78. package/_standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  79. package/_standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  80. package/_standalone/.next/server/app/api/graph/route.js +1 -1
  81. package/_standalone/.next/server/app/api/graph/route.js.nft.json +1 -1
  82. package/_standalone/.next/server/app/api/graph/route_client-reference-manifest.js +1 -1
  83. package/_standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  84. package/_standalone/.next/server/app/api/inbox/route.js +1 -0
  85. package/_standalone/.next/server/app/api/inbox/route.js.nft.json +1 -0
  86. package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.js +1 -0
  87. package/_standalone/.next/server/app/api/init/route.js +1 -1
  88. package/_standalone/.next/server/app/api/init/route.js.nft.json +1 -1
  89. package/_standalone/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
  90. package/_standalone/.next/server/app/api/mcp/agents/route.js +1 -1
  91. package/_standalone/.next/server/app/api/mcp/agents/route.js.nft.json +1 -1
  92. package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
  93. package/_standalone/.next/server/app/api/mcp/install/route.js +1 -1
  94. package/_standalone/.next/server/app/api/mcp/install/route.js.nft.json +1 -1
  95. package/_standalone/.next/server/app/api/mcp/install/route_client-reference-manifest.js +1 -1
  96. package/_standalone/.next/server/app/api/mcp/install-skill/route.js.nft.json +1 -1
  97. package/_standalone/.next/server/app/api/mcp/install-skill/route_client-reference-manifest.js +1 -1
  98. package/_standalone/.next/server/app/api/mcp/restart/route_client-reference-manifest.js +1 -1
  99. package/_standalone/.next/server/app/api/mcp/status/route.js +1 -1
  100. package/_standalone/.next/server/app/api/mcp/status/route.js.nft.json +1 -1
  101. package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
  102. package/_standalone/.next/server/app/api/monitoring/route.js +1 -1
  103. package/_standalone/.next/server/app/api/monitoring/route.js.nft.json +1 -1
  104. package/_standalone/.next/server/app/api/monitoring/route_client-reference-manifest.js +1 -1
  105. package/_standalone/.next/server/app/api/recent-files/route.js +1 -1
  106. package/_standalone/.next/server/app/api/recent-files/route.js.nft.json +1 -1
  107. package/_standalone/.next/server/app/api/recent-files/route_client-reference-manifest.js +1 -1
  108. package/_standalone/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
  109. package/_standalone/.next/server/app/api/search/route.js +1 -1
  110. package/_standalone/.next/server/app/api/search/route.js.nft.json +1 -1
  111. package/_standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  112. package/_standalone/.next/server/app/api/settings/list-models/route.js +1 -1
  113. package/_standalone/.next/server/app/api/settings/list-models/route.js.nft.json +1 -1
  114. package/_standalone/.next/server/app/api/settings/list-models/route_client-reference-manifest.js +1 -1
  115. package/_standalone/.next/server/app/api/settings/reset-token/route.js +1 -1
  116. package/_standalone/.next/server/app/api/settings/reset-token/route.js.nft.json +1 -1
  117. package/_standalone/.next/server/app/api/settings/reset-token/route_client-reference-manifest.js +1 -1
  118. package/_standalone/.next/server/app/api/settings/route.js +1 -1
  119. package/_standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  120. package/_standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
  121. package/_standalone/.next/server/app/api/settings/test-key/route.js +1 -1
  122. package/_standalone/.next/server/app/api/settings/test-key/route.js.nft.json +1 -1
  123. package/_standalone/.next/server/app/api/settings/test-key/route_client-reference-manifest.js +1 -1
  124. package/_standalone/.next/server/app/api/setup/check-path/route_client-reference-manifest.js +1 -1
  125. package/_standalone/.next/server/app/api/setup/check-port/route_client-reference-manifest.js +1 -1
  126. package/_standalone/.next/server/app/api/setup/generate-token/route_client-reference-manifest.js +1 -1
  127. package/_standalone/.next/server/app/api/setup/ls/route_client-reference-manifest.js +1 -1
  128. package/_standalone/.next/server/app/api/setup/route.js +1 -1
  129. package/_standalone/.next/server/app/api/setup/route.js.nft.json +1 -1
  130. package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
  131. package/_standalone/.next/server/app/api/skills/route.js +2 -2
  132. package/_standalone/.next/server/app/api/skills/route.js.nft.json +1 -1
  133. package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  134. package/_standalone/.next/server/app/api/sync/route.js +1 -1
  135. package/_standalone/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
  136. package/_standalone/.next/server/app/api/tree-version/route.js +1 -1
  137. package/_standalone/.next/server/app/api/tree-version/route.js.nft.json +1 -1
  138. package/_standalone/.next/server/app/api/tree-version/route_client-reference-manifest.js +1 -1
  139. package/_standalone/.next/server/app/api/uninstall/route_client-reference-manifest.js +1 -1
  140. package/_standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  141. package/_standalone/.next/server/app/api/update-check/route.js +1 -1
  142. package/_standalone/.next/server/app/api/update-check/route_client-reference-manifest.js +1 -1
  143. package/_standalone/.next/server/app/api/update-status/route_client-reference-manifest.js +1 -1
  144. package/_standalone/.next/server/app/api/workflows/route.js +2 -2
  145. package/_standalone/.next/server/app/api/workflows/route.js.nft.json +1 -1
  146. package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
  147. package/_standalone/.next/server/app/changes/page.js +2 -2
  148. package/_standalone/.next/server/app/changes/page.js.nft.json +1 -1
  149. package/_standalone/.next/server/app/changes/page_client-reference-manifest.js +1 -1
  150. package/_standalone/.next/server/app/echo/[segment]/page.js +6 -6
  151. package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
  152. package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
  153. package/_standalone/.next/server/app/echo/page.js +2 -2
  154. package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
  155. package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
  156. package/_standalone/.next/server/app/explore/page.js +3 -3
  157. package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
  158. package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
  159. package/_standalone/.next/server/app/help/page.js +2 -2
  160. package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
  161. package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
  162. package/_standalone/.next/server/app/login/page.js +2 -2
  163. package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
  164. package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  165. package/_standalone/.next/server/app/page.js +3 -3
  166. package/_standalone/.next/server/app/page.js.nft.json +1 -1
  167. package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  168. package/_standalone/.next/server/app/setup/page.js +2 -2
  169. package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
  170. package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  171. package/_standalone/.next/server/app/trash/page.js +3 -3
  172. package/_standalone/.next/server/app/trash/page.js.nft.json +1 -1
  173. package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
  174. package/_standalone/.next/server/app/view/[...path]/page.js +4 -4
  175. package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
  176. package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
  177. package/_standalone/.next/server/app-paths-manifest.json +19 -18
  178. package/_standalone/.next/server/chunks/1550.js +1 -1
  179. package/_standalone/.next/server/chunks/1750.js +1 -0
  180. package/_standalone/.next/server/chunks/{9414.js → 2190.js} +1 -1
  181. package/_standalone/.next/server/chunks/2536.js +52 -0
  182. package/_standalone/.next/server/chunks/5648.js +2 -0
  183. package/_standalone/.next/server/chunks/6539.js +1 -1
  184. package/_standalone/.next/server/chunks/8388.js +15 -0
  185. package/_standalone/.next/server/chunks/953.js +42 -2
  186. package/_standalone/.next/server/chunks/9539.js +219 -0
  187. package/_standalone/.next/server/functions-config-manifest.json +2 -1
  188. package/_standalone/.next/server/instrumentation.js +1 -1
  189. package/_standalone/.next/server/middleware-build-manifest.js +1 -1
  190. package/_standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  191. package/_standalone/.next/server/pages/500.html +2 -2
  192. package/_standalone/.next/server/server-reference-manifest.js +1 -1
  193. package/_standalone/.next/server/server-reference-manifest.json +1 -1
  194. package/_standalone/.next/static/Ij3PFh-a0zi5K_ANoSAW0/_buildManifest.js +1 -0
  195. package/_standalone/.next/static/chunks/1053-b70535785cc5aaee.js +29 -0
  196. package/_standalone/.next/static/chunks/1239.10a0710c2772ab34.js +1 -0
  197. package/_standalone/.next/static/chunks/{1814.e2da5460ded71d71.js → 1814.2ee1d03297c0bccd.js} +1 -1
  198. package/_standalone/.next/static/chunks/{1384-55276d40a9da4e88.js → 1880-c2a9e76201841c86.js} +2 -2
  199. package/_standalone/.next/static/chunks/{1a258343-030e4d6735874dd4.js → 1a258343-9803591e4aaee1f6.js} +1 -1
  200. package/_standalone/.next/static/chunks/2631.dc56e83472bde281.js +1 -0
  201. package/_standalone/.next/static/chunks/2872.045858d00bd8307f.js +8 -0
  202. package/_standalone/.next/static/chunks/2968.f10ccee9e7e2324d.js +2 -0
  203. package/_standalone/.next/static/chunks/3160-83a7e0b94414b3ac.js +1 -0
  204. package/_standalone/.next/static/chunks/3637.0541ac2d0ea7de1f.js +1 -0
  205. package/_standalone/.next/static/chunks/4033.6666700547b20141.js +1 -0
  206. package/_standalone/.next/static/chunks/4563-b2a2ce80aff845af.js +6 -0
  207. package/_standalone/.next/static/chunks/516.24ee058b1d4b1fed.js +8 -0
  208. package/_standalone/.next/static/chunks/5627.c4337d7289acb31f.js +1 -0
  209. package/_standalone/.next/static/chunks/5956.b445072b35915129.js +1 -0
  210. package/_standalone/.next/static/chunks/6357-c645842834c0d4cd.js +1 -0
  211. package/_standalone/.next/static/chunks/6826.7b7d94dd0fd83812.js +1 -0
  212. package/_standalone/.next/static/chunks/{8409-de5726a4a278d28f.js → 6926-4af497b83952fa87.js} +1 -1
  213. package/_standalone/.next/static/chunks/6981-3d7dcac2d12a5670.js +1 -0
  214. package/_standalone/.next/static/chunks/7144-5febf62f1a79fe64.js +1 -0
  215. package/_standalone/.next/static/chunks/7266-bb7be1128eccd48e.js +13 -0
  216. package/_standalone/.next/static/chunks/7753.63831cfc54a55fbb.js +1 -0
  217. package/_standalone/.next/static/chunks/862.9f526e964489e2e5.js +1 -0
  218. package/_standalone/.next/static/chunks/9300.118b8c840634383f.js +28 -0
  219. package/_standalone/.next/static/chunks/95247769.3b5caae1c1a76ce1.js +4 -0
  220. package/_standalone/.next/static/chunks/9602-423291fdb36396d1.js +1 -0
  221. package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/route-400c3c09b1540c14.js +1 -0
  222. package/_standalone/.next/static/chunks/app/_global-error/page-400c3c09b1540c14.js +1 -0
  223. package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-773071a99c4daac2.js +1 -0
  224. package/_standalone/.next/static/chunks/app/agents/page-6102a884b2cb3cfe.js +5 -0
  225. package/_standalone/.next/static/chunks/app/api/a2a/agents/route-400c3c09b1540c14.js +1 -0
  226. package/_standalone/.next/static/chunks/app/api/a2a/delegations/route-400c3c09b1540c14.js +1 -0
  227. package/_standalone/.next/static/chunks/app/api/a2a/discover/route-400c3c09b1540c14.js +1 -0
  228. package/_standalone/.next/static/chunks/app/api/a2a/route-400c3c09b1540c14.js +1 -0
  229. package/_standalone/.next/static/chunks/app/api/acp/config/route-400c3c09b1540c14.js +1 -0
  230. package/_standalone/.next/static/chunks/app/api/acp/detect/route-400c3c09b1540c14.js +1 -0
  231. package/_standalone/.next/static/chunks/app/api/acp/install/route-400c3c09b1540c14.js +1 -0
  232. package/_standalone/.next/static/chunks/app/api/acp/registry/route-400c3c09b1540c14.js +1 -0
  233. package/_standalone/.next/static/chunks/app/api/acp/session/route-400c3c09b1540c14.js +1 -0
  234. package/_standalone/.next/static/chunks/app/api/agent-activity/route-400c3c09b1540c14.js +1 -0
  235. package/_standalone/.next/static/chunks/app/api/ask/route-400c3c09b1540c14.js +1 -0
  236. package/_standalone/.next/static/chunks/app/api/ask-sessions/route-400c3c09b1540c14.js +1 -0
  237. package/_standalone/.next/static/chunks/app/api/auth/route-400c3c09b1540c14.js +1 -0
  238. package/_standalone/.next/static/chunks/app/api/backlinks/route-400c3c09b1540c14.js +1 -0
  239. package/_standalone/.next/static/chunks/app/api/bootstrap/route-400c3c09b1540c14.js +1 -0
  240. package/_standalone/.next/static/chunks/app/api/changes/route-400c3c09b1540c14.js +1 -0
  241. package/_standalone/.next/static/chunks/app/api/export/route-400c3c09b1540c14.js +1 -0
  242. package/_standalone/.next/static/chunks/app/api/extract-pdf/route-400c3c09b1540c14.js +1 -0
  243. package/_standalone/.next/static/chunks/app/api/file/import/route-400c3c09b1540c14.js +1 -0
  244. package/_standalone/.next/static/chunks/app/api/file/route-400c3c09b1540c14.js +1 -0
  245. package/_standalone/.next/static/chunks/app/api/files/route-400c3c09b1540c14.js +1 -0
  246. package/_standalone/.next/static/chunks/app/api/git/route-400c3c09b1540c14.js +1 -0
  247. package/_standalone/.next/static/chunks/app/api/graph/route-400c3c09b1540c14.js +1 -0
  248. package/_standalone/.next/static/chunks/app/api/health/route-400c3c09b1540c14.js +1 -0
  249. package/_standalone/.next/static/chunks/app/api/inbox/route-400c3c09b1540c14.js +1 -0
  250. package/_standalone/.next/static/chunks/app/api/init/route-400c3c09b1540c14.js +1 -0
  251. package/_standalone/.next/static/chunks/app/api/mcp/agents/route-400c3c09b1540c14.js +1 -0
  252. package/_standalone/.next/static/chunks/app/api/mcp/install/route-400c3c09b1540c14.js +1 -0
  253. package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-400c3c09b1540c14.js +1 -0
  254. package/_standalone/.next/static/chunks/app/api/mcp/restart/route-400c3c09b1540c14.js +1 -0
  255. package/_standalone/.next/static/chunks/app/api/mcp/status/route-400c3c09b1540c14.js +1 -0
  256. package/_standalone/.next/static/chunks/app/api/monitoring/route-400c3c09b1540c14.js +1 -0
  257. package/_standalone/.next/static/chunks/app/api/recent-files/route-400c3c09b1540c14.js +1 -0
  258. package/_standalone/.next/static/chunks/app/api/restart/route-400c3c09b1540c14.js +1 -0
  259. package/_standalone/.next/static/chunks/app/api/search/route-400c3c09b1540c14.js +1 -0
  260. package/_standalone/.next/static/chunks/app/api/settings/list-models/route-400c3c09b1540c14.js +1 -0
  261. package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-400c3c09b1540c14.js +1 -0
  262. package/_standalone/.next/static/chunks/app/api/settings/route-400c3c09b1540c14.js +1 -0
  263. package/_standalone/.next/static/chunks/app/api/settings/test-key/route-400c3c09b1540c14.js +1 -0
  264. package/_standalone/.next/static/chunks/app/api/setup/check-path/route-400c3c09b1540c14.js +1 -0
  265. package/_standalone/.next/static/chunks/app/api/setup/check-port/route-400c3c09b1540c14.js +1 -0
  266. package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-400c3c09b1540c14.js +1 -0
  267. package/_standalone/.next/static/chunks/app/api/setup/ls/route-400c3c09b1540c14.js +1 -0
  268. package/_standalone/.next/static/chunks/app/api/setup/route-400c3c09b1540c14.js +1 -0
  269. package/_standalone/.next/static/chunks/app/api/skills/route-400c3c09b1540c14.js +1 -0
  270. package/_standalone/.next/static/chunks/app/api/sync/route-400c3c09b1540c14.js +1 -0
  271. package/_standalone/.next/static/chunks/app/api/tree-version/route-400c3c09b1540c14.js +1 -0
  272. package/_standalone/.next/static/chunks/app/api/uninstall/route-400c3c09b1540c14.js +1 -0
  273. package/_standalone/.next/static/chunks/app/api/update/route-400c3c09b1540c14.js +1 -0
  274. package/_standalone/.next/static/chunks/app/api/update-check/route-400c3c09b1540c14.js +1 -0
  275. package/_standalone/.next/static/chunks/app/api/update-status/route-400c3c09b1540c14.js +1 -0
  276. package/_standalone/.next/static/chunks/app/api/workflows/route-400c3c09b1540c14.js +1 -0
  277. package/_standalone/.next/static/chunks/app/changes/page-350992cf5091bc5b.js +1 -0
  278. package/_standalone/.next/static/chunks/app/echo/[segment]/page-addf014fcf23fad5.js +11 -0
  279. package/_standalone/.next/static/chunks/app/echo/page-400c3c09b1540c14.js +1 -0
  280. package/_standalone/.next/static/chunks/app/explore/page-5eb2835e9e3ab4bb.js +4 -0
  281. package/_standalone/.next/static/chunks/app/help/page-2325d25b6846ca07.js +1 -0
  282. package/_standalone/.next/static/chunks/app/layout-42cdbce19f404567.js +186 -0
  283. package/_standalone/.next/static/chunks/app/login/page-24236460fa7c11d0.js +1 -0
  284. package/_standalone/.next/static/chunks/app/page-8c9643b649e01735.js +7 -0
  285. package/_standalone/.next/static/chunks/app/setup/page-d158b8cb533feb1e.js +1 -0
  286. package/_standalone/.next/static/chunks/app/trash/page-e9ab74ffeb96af41.js +1 -0
  287. package/_standalone/.next/static/chunks/app/view/[...path]/loading-400c3c09b1540c14.js +1 -0
  288. package/_standalone/.next/static/chunks/app/view/[...path]/not-found-61474670d6bb6116.js +1 -0
  289. package/_standalone/.next/static/chunks/app/view/[...path]/page-764a69a1c8bd4eef.js +12 -0
  290. package/_standalone/.next/static/chunks/e71f6c19-4df85185bf989b49.js +1 -0
  291. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-400c3c09b1540c14.js +1 -0
  292. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-400c3c09b1540c14.js +1 -0
  293. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-400c3c09b1540c14.js +1 -0
  294. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-400c3c09b1540c14.js +1 -0
  295. package/_standalone/.next/static/chunks/webpack-7b276daaa930d480.js +1 -0
  296. package/_standalone/.next/static/css/bc9179074eaf65ae.css +1 -0
  297. package/_standalone/.next/trace +63 -53
  298. package/_standalone/.next/types/routes.d.ts +2 -1
  299. package/_standalone/.next/types/validator.ts +9 -0
  300. package/_standalone/__tests__/agent/chat-mode.test.ts +103 -0
  301. package/_standalone/__tests__/agents/agents-content-dashboard.test.tsx +4 -3
  302. package/_standalone/__tests__/api/bootstrap.test.ts +0 -2
  303. package/_standalone/__tests__/api/file.test.ts +22 -1
  304. package/_standalone/__tests__/api/install-skill.test.ts +2 -2
  305. package/_standalone/__tests__/api/mcp-install.test.ts +32 -10
  306. package/_standalone/__tests__/api/setup.test.ts +2 -2
  307. package/_standalone/__tests__/api/test-key.test.ts +73 -147
  308. package/_standalone/__tests__/ask/ask-content-input-during-run.test.tsx +1 -1
  309. package/_standalone/__tests__/ask/mode-capsule.test.ts +95 -0
  310. package/_standalone/__tests__/cli/agent-routing.test.ts +232 -0
  311. package/_standalone/__tests__/cli/file-subcommands.test.ts +379 -0
  312. package/_standalone/__tests__/core/inbox.test.ts +250 -0
  313. package/_standalone/__tests__/core/skill-install-logic.test.ts +3 -3
  314. package/_standalone/__tests__/core/sync-status.test.ts +1 -1
  315. package/_standalone/__tests__/core/tools.test.ts +8 -6
  316. package/_standalone/__tests__/lib/echo-pages-visual-i18n.test.ts +2 -2
  317. package/_standalone/__tests__/lib/i18n-new-keys.test.ts +2 -2
  318. package/_standalone/__tests__/panels/agents-panel-hub.test.tsx +2 -2
  319. package/_standalone/__tests__/settings/activity-bar-update-badge.test.tsx +1 -1
  320. package/_standalone/__tests__/settings/settings-update-badge.test.tsx +1 -1
  321. package/_standalone/__tests__/settings/update-tab-availability-sync.test.tsx +1 -1
  322. package/_standalone/__tests__/settings/update-tab-browser.test.tsx +1 -1
  323. package/_standalone/__tests__/settings/update-tab-desktop.test.tsx +1 -1
  324. package/_standalone/__tests__/setup.ts +3 -5
  325. package/_standalone/app/globals.css +11 -1
  326. package/_standalone/components/ActivityBar.tsx +26 -10
  327. package/_standalone/components/AskFab.tsx +1 -1
  328. package/_standalone/components/AskModal.tsx +1 -1
  329. package/_standalone/components/Backlinks.tsx +1 -1
  330. package/_standalone/components/CreateSpaceModal.tsx +7 -55
  331. package/_standalone/components/EchoSpotlight.tsx +1 -1
  332. package/_standalone/components/ExportModal.tsx +1 -1
  333. package/_standalone/components/FileTree.tsx +66 -80
  334. package/_standalone/components/FindInPage.tsx +1 -1
  335. package/_standalone/components/GuideCard.tsx +1 -1
  336. package/_standalone/components/ImportModal.tsx +1 -1
  337. package/_standalone/components/KeyboardShortcuts.tsx +1 -1
  338. package/_standalone/components/MarkdownView.tsx +41 -16
  339. package/_standalone/components/OnboardingView.tsx +1 -1
  340. package/_standalone/components/OrganizeToast.tsx +1 -1
  341. package/_standalone/components/Panel.tsx +82 -4
  342. package/_standalone/components/QuickSuggestion.tsx +1 -1
  343. package/_standalone/components/RightAgentDetailPanel.tsx +2 -2
  344. package/_standalone/components/RightAskPanel.tsx +88 -22
  345. package/_standalone/components/SearchModal.tsx +1 -1
  346. package/_standalone/components/Sidebar.tsx +4 -4
  347. package/_standalone/components/SidebarLayout.tsx +52 -16
  348. package/_standalone/components/SpaceInitToast.tsx +1 -1
  349. package/_standalone/components/SyncStatusBar.tsx +2 -2
  350. package/_standalone/components/SystemPulse.tsx +12 -6
  351. package/_standalone/components/TableOfContents.tsx +86 -39
  352. package/_standalone/components/agents/AgentActivitySection.tsx +225 -0
  353. package/_standalone/components/agents/AgentsMcpSection.tsx +10 -16
  354. package/_standalone/components/agents/AgentsOverviewSection.tsx +28 -27
  355. package/_standalone/components/agents/AgentsPanelA2aTab.tsx +1 -1
  356. package/_standalone/components/agents/AgentsPanelSessionsTab.tsx +6 -1
  357. package/_standalone/components/agents/AgentsSkillsSection.tsx +1 -1
  358. package/_standalone/components/agents/DiscoverAgentModal.tsx +1 -1
  359. package/_standalone/components/agents/RecentActivityFeed.tsx +49 -88
  360. package/_standalone/components/agents/agent-activity-shared.tsx +110 -0
  361. package/_standalone/components/ask/AgentSelectorCapsule.tsx +1 -1
  362. package/_standalone/components/ask/AskContent.tsx +332 -486
  363. package/_standalone/components/ask/AskHeader.tsx +61 -0
  364. package/_standalone/components/ask/FileChip.tsx +9 -5
  365. package/_standalone/components/ask/MessageList.tsx +88 -21
  366. package/_standalone/components/ask/ModeCapsule.tsx +180 -0
  367. package/_standalone/components/ask/ProviderModelCapsule.tsx +284 -0
  368. package/_standalone/components/ask/SessionHistory.tsx +63 -10
  369. package/_standalone/components/ask/SessionTabBar.tsx +1 -1
  370. package/_standalone/components/ask/ThinkingBlock.tsx +1 -1
  371. package/_standalone/components/ask/ToolCallBlock.tsx +28 -24
  372. package/_standalone/components/changes/ChangesBanner.tsx +1 -1
  373. package/_standalone/components/echo/EchoInsightCollapsible.tsx +1 -1
  374. package/_standalone/components/echo/EchoSegmentNav.tsx +1 -1
  375. package/_standalone/components/home/InboxSection.tsx +268 -0
  376. package/_standalone/components/panels/AgentsPanel.tsx +3 -2
  377. package/_standalone/components/panels/AgentsPanelHubNav.tsx +2 -6
  378. package/_standalone/components/panels/DiscoverPanel.tsx +1 -1
  379. package/_standalone/components/panels/EchoPanel.tsx +1 -1
  380. package/_standalone/components/panels/EchoSidebarStats.tsx +1 -1
  381. package/_standalone/components/panels/ImportHistoryPanel.tsx +1 -1
  382. package/_standalone/components/panels/PanelHeader.tsx +1 -1
  383. package/_standalone/components/panels/PluginsPanel.tsx +1 -1
  384. package/_standalone/components/panels/SearchPanel.tsx +5 -2
  385. package/_standalone/components/panels/SyncPopover.tsx +1 -1
  386. package/_standalone/components/panels/WorkflowsPanel.tsx +1 -1
  387. package/_standalone/components/renderers/agent-inspector/AgentInspectorRenderer.tsx +18 -0
  388. package/_standalone/components/renderers/todo/TodoRenderer.tsx +489 -75
  389. package/_standalone/components/settings/AiTab.tsx +198 -127
  390. package/_standalone/components/settings/AppearanceTab.tsx +48 -50
  391. package/_standalone/components/settings/KnowledgeTab.tsx +92 -27
  392. package/_standalone/components/settings/McpAgentInstall.tsx +95 -28
  393. package/_standalone/components/settings/McpSkillsSection.tsx +2 -2
  394. package/_standalone/components/settings/McpTab.tsx +498 -216
  395. package/_standalone/components/settings/PluginsTab.tsx +1 -1
  396. package/_standalone/components/settings/SettingsContent.tsx +17 -8
  397. package/_standalone/components/settings/SyncTab.tsx +615 -230
  398. package/_standalone/components/settings/UninstallTab.tsx +1 -1
  399. package/_standalone/components/settings/UpdateTab.tsx +2 -2
  400. package/_standalone/components/settings/types.ts +7 -5
  401. package/_standalone/components/setup/StepAI.tsx +70 -49
  402. package/_standalone/components/setup/StepAgents.tsx +113 -47
  403. package/_standalone/components/setup/StepDots.tsx +1 -1
  404. package/_standalone/components/setup/StepReview.tsx +186 -31
  405. package/_standalone/components/setup/types.ts +17 -8
  406. package/_standalone/components/shared/ProviderSelect.tsx +134 -0
  407. package/_standalone/components/walkthrough/WalkthroughOverlay.tsx +2 -2
  408. package/_standalone/components/walkthrough/WalkthroughTooltip.tsx +2 -2
  409. package/_standalone/components/walkthrough/index.ts +1 -1
  410. package/_standalone/data/skills/mindos/SKILL.md +93 -93
  411. package/_standalone/data/skills/mindos/references/write-supplement.md +119 -0
  412. package/_standalone/data/skills/mindos-zh/SKILL.md +100 -104
  413. package/_standalone/data/skills/mindos-zh/references/write-supplement.md +119 -0
  414. package/_standalone/hooks/useAcpDetection.ts +1 -1
  415. package/_standalone/hooks/useAskChat.ts +248 -0
  416. package/_standalone/hooks/useAskPanel.ts +24 -4
  417. package/_standalone/hooks/useAskSession.ts +15 -0
  418. package/_standalone/lib/acp/types.ts +1 -1
  419. package/_standalone/lib/api.ts +3 -1
  420. package/_standalone/lib/core/types.ts +2 -0
  421. package/_standalone/lib/i18n/modules/ai-chat.ts +35 -13
  422. package/_standalone/lib/i18n/modules/features.ts +5 -5
  423. package/_standalone/lib/i18n/modules/knowledge.ts +86 -2
  424. package/_standalone/lib/i18n/modules/navigation.ts +6 -2
  425. package/_standalone/lib/i18n/modules/onboarding.ts +69 -29
  426. package/_standalone/lib/i18n/modules/panels.ts +78 -29
  427. package/_standalone/lib/i18n/modules/settings.ts +280 -24
  428. package/_standalone/lib/inbox-upload.ts +93 -0
  429. package/_standalone/lib/mcp-snippets.ts +5 -1
  430. package/_standalone/lib/settings-ai-client.ts +13 -12
  431. package/_standalone/lib/space-ai-init.ts +66 -0
  432. package/_standalone/lib/stores/McpStoreInit.tsx +18 -0
  433. package/_standalone/lib/stores/WalkthroughInit.tsx +20 -0
  434. package/_standalone/lib/stores/locale-store.ts +55 -0
  435. package/_standalone/lib/stores/mcp-store.ts +156 -0
  436. package/_standalone/lib/stores/walkthrough-store.ts +118 -0
  437. package/_standalone/package-lock.json +40 -8
  438. package/_standalone/package.json +3 -1
  439. package/_standalone/tsconfig.json +1 -1
  440. package/_standalone/tsconfig.tsbuildinfo +1 -1
  441. package/app/app/api/acp/detect/route.ts +29 -20
  442. package/app/app/api/agent-activity/route.ts +1 -1
  443. package/app/app/api/ask/route.ts +105 -30
  444. package/app/app/api/ask-sessions/route.ts +1 -0
  445. package/app/app/api/bootstrap/route.ts +1 -3
  446. package/app/app/api/file/route.ts +34 -4
  447. package/app/app/api/inbox/route.ts +61 -0
  448. package/app/app/api/mcp/install/route.ts +2 -1
  449. package/app/app/api/mcp/status/route.ts +14 -6
  450. package/app/app/api/settings/list-models/route.ts +73 -53
  451. package/app/app/api/settings/route.ts +46 -55
  452. package/app/app/api/settings/test-key/route.ts +57 -114
  453. package/app/app/api/setup/route.ts +31 -21
  454. package/app/app/api/sync/route.ts +122 -12
  455. package/app/app/api/update-check/route.ts +2 -2
  456. package/app/app/globals.css +11 -1
  457. package/app/app/layout.tsx +2 -3
  458. package/app/app/login/page.tsx +1 -1
  459. package/app/app/view/[...path]/ViewPageClient.tsx +22 -37
  460. package/app/app/view/[...path]/not-found.tsx +1 -1
  461. package/app/components/ActivityBar.tsx +26 -10
  462. package/app/components/AskFab.tsx +1 -1
  463. package/app/components/AskModal.tsx +1 -1
  464. package/app/components/Backlinks.tsx +1 -1
  465. package/app/components/CreateSpaceModal.tsx +7 -55
  466. package/app/components/DirView.tsx +93 -11
  467. package/app/components/EchoSpotlight.tsx +1 -1
  468. package/app/components/ExportModal.tsx +1 -1
  469. package/app/components/FileTree.tsx +66 -80
  470. package/app/components/FindInPage.tsx +1 -1
  471. package/app/components/GuideCard.tsx +1 -1
  472. package/app/components/HomeContent.tsx +21 -14
  473. package/app/components/ImportModal.tsx +1 -1
  474. package/app/components/KeyboardShortcuts.tsx +1 -1
  475. package/app/components/MarkdownView.tsx +41 -16
  476. package/app/components/OnboardingView.tsx +1 -1
  477. package/app/components/OrganizeToast.tsx +1 -1
  478. package/app/components/Panel.tsx +82 -4
  479. package/app/components/QuickSuggestion.tsx +1 -1
  480. package/app/components/RightAgentDetailPanel.tsx +2 -2
  481. package/app/components/RightAskPanel.tsx +88 -22
  482. package/app/components/SearchModal.tsx +1 -1
  483. package/app/components/Sidebar.tsx +4 -4
  484. package/app/components/SidebarLayout.tsx +52 -16
  485. package/app/components/SpaceInitToast.tsx +1 -1
  486. package/app/components/SyncStatusBar.tsx +2 -2
  487. package/app/components/SystemPulse.tsx +12 -6
  488. package/app/components/TableOfContents.tsx +86 -39
  489. package/app/components/TrashPageClient.tsx +1 -1
  490. package/app/components/UpdateOverlay.tsx +2 -2
  491. package/app/components/agents/AgentActivitySection.tsx +225 -0
  492. package/app/components/agents/AgentDetailContent.tsx +234 -3
  493. package/app/components/agents/AgentsContentPage.tsx +13 -2
  494. package/app/components/agents/AgentsMcpSection.tsx +10 -16
  495. package/app/components/agents/AgentsOverviewSection.tsx +28 -27
  496. package/app/components/agents/AgentsPanelA2aTab.tsx +1 -1
  497. package/app/components/agents/AgentsPanelSessionsTab.tsx +6 -1
  498. package/app/components/agents/AgentsSkillsSection.tsx +1 -1
  499. package/app/components/agents/DiscoverAgentModal.tsx +1 -1
  500. package/app/components/agents/RecentActivityFeed.tsx +49 -88
  501. package/app/components/agents/agent-activity-shared.tsx +110 -0
  502. package/app/components/agents/agents-content-model.ts +2 -2
  503. package/app/components/ask/AgentSelectorCapsule.tsx +1 -1
  504. package/app/components/ask/AskContent.tsx +332 -486
  505. package/app/components/ask/AskHeader.tsx +61 -0
  506. package/app/components/ask/FileChip.tsx +9 -5
  507. package/app/components/ask/MessageList.tsx +88 -21
  508. package/app/components/ask/ModeCapsule.tsx +180 -0
  509. package/app/components/ask/ProviderModelCapsule.tsx +284 -0
  510. package/app/components/ask/SessionHistory.tsx +63 -10
  511. package/app/components/ask/SessionTabBar.tsx +1 -1
  512. package/app/components/ask/ThinkingBlock.tsx +1 -1
  513. package/app/components/ask/ToolCallBlock.tsx +28 -24
  514. package/app/components/changes/ChangesBanner.tsx +1 -1
  515. package/app/components/changes/ChangesContentPage.tsx +1 -1
  516. package/app/components/echo/EchoInsightCollapsible.tsx +1 -1
  517. package/app/components/echo/EchoSegmentNav.tsx +1 -1
  518. package/app/components/echo/EchoSegmentPageClient.tsx +1 -1
  519. package/app/components/explore/ExploreContent.tsx +1 -1
  520. package/app/components/help/HelpContent.tsx +2 -1
  521. package/app/components/home/InboxSection.tsx +268 -0
  522. package/app/components/panels/AgentsPanel.tsx +3 -2
  523. package/app/components/panels/AgentsPanelHubNav.tsx +2 -6
  524. package/app/components/panels/DiscoverPanel.tsx +1 -1
  525. package/app/components/panels/EchoPanel.tsx +1 -1
  526. package/app/components/panels/EchoSidebarStats.tsx +1 -1
  527. package/app/components/panels/ImportHistoryPanel.tsx +1 -1
  528. package/app/components/panels/PanelHeader.tsx +1 -1
  529. package/app/components/panels/PluginsPanel.tsx +1 -1
  530. package/app/components/panels/SearchPanel.tsx +5 -2
  531. package/app/components/panels/SyncPopover.tsx +1 -1
  532. package/app/components/panels/WorkflowsPanel.tsx +1 -1
  533. package/app/components/renderers/agent-inspector/AgentInspectorRenderer.tsx +18 -0
  534. package/app/components/renderers/todo/TodoRenderer.tsx +489 -75
  535. package/app/components/settings/AiTab.tsx +198 -127
  536. package/app/components/settings/AppearanceTab.tsx +48 -50
  537. package/app/components/settings/KnowledgeTab.tsx +92 -27
  538. package/app/components/settings/McpAgentInstall.tsx +95 -28
  539. package/app/components/settings/McpSkillsSection.tsx +2 -2
  540. package/app/components/settings/McpTab.tsx +498 -216
  541. package/app/components/settings/PluginsTab.tsx +1 -1
  542. package/app/components/settings/SettingsContent.tsx +17 -8
  543. package/app/components/settings/SyncTab.tsx +615 -230
  544. package/app/components/settings/UninstallTab.tsx +1 -1
  545. package/app/components/settings/UpdateTab.tsx +2 -2
  546. package/app/components/settings/types.ts +7 -5
  547. package/app/components/setup/StepAI.tsx +70 -49
  548. package/app/components/setup/StepAgents.tsx +113 -47
  549. package/app/components/setup/StepDots.tsx +1 -1
  550. package/app/components/setup/StepReview.tsx +186 -31
  551. package/app/components/setup/index.tsx +83 -48
  552. package/app/components/setup/types.ts +17 -8
  553. package/app/components/shared/ProviderSelect.tsx +134 -0
  554. package/app/components/walkthrough/WalkthroughOverlay.tsx +2 -2
  555. package/app/components/walkthrough/WalkthroughTooltip.tsx +2 -2
  556. package/app/components/walkthrough/index.ts +1 -1
  557. package/app/data/skills/mindos/SKILL.md +93 -93
  558. package/app/data/skills/mindos/references/write-supplement.md +119 -0
  559. package/app/data/skills/mindos-zh/SKILL.md +100 -104
  560. package/app/data/skills/mindos-zh/references/write-supplement.md +119 -0
  561. package/app/hooks/useAcpDetection.ts +1 -1
  562. package/app/hooks/useAskChat.ts +248 -0
  563. package/app/hooks/useAskPanel.ts +24 -4
  564. package/app/hooks/useAskSession.ts +15 -0
  565. package/app/lib/acp/types.ts +1 -1
  566. package/app/lib/actions.ts +13 -0
  567. package/app/lib/agent/log.ts +2 -0
  568. package/app/lib/agent/model.ts +69 -81
  569. package/app/lib/agent/prompt.ts +27 -0
  570. package/app/lib/agent/providers.ts +299 -0
  571. package/app/lib/agent/tools.ts +26 -4
  572. package/app/lib/api.ts +3 -1
  573. package/app/lib/core/agent-audit-log.ts +7 -0
  574. package/app/lib/core/fs-ops.ts +9 -4
  575. package/app/lib/core/inbox.ts +181 -0
  576. package/app/lib/core/index.ts +4 -0
  577. package/app/lib/core/tree.ts +3 -0
  578. package/app/lib/core/types.ts +2 -0
  579. package/app/lib/fs.ts +20 -2
  580. package/app/lib/i18n/modules/ai-chat.ts +35 -13
  581. package/app/lib/i18n/modules/features.ts +5 -5
  582. package/app/lib/i18n/modules/knowledge.ts +86 -2
  583. package/app/lib/i18n/modules/navigation.ts +6 -2
  584. package/app/lib/i18n/modules/onboarding.ts +69 -29
  585. package/app/lib/i18n/modules/panels.ts +78 -29
  586. package/app/lib/i18n/modules/settings.ts +280 -24
  587. package/app/lib/inbox-upload.ts +93 -0
  588. package/app/lib/mcp-agents.ts +7 -9
  589. package/app/lib/mcp-snippets.ts +5 -1
  590. package/app/lib/settings-ai-client.ts +13 -12
  591. package/app/lib/settings.ts +48 -33
  592. package/app/lib/space-ai-init.ts +66 -0
  593. package/app/lib/stores/LocaleStoreInit.tsx +18 -0
  594. package/app/lib/stores/McpStoreInit.tsx +18 -0
  595. package/app/lib/stores/WalkthroughInit.tsx +20 -0
  596. package/app/lib/stores/locale-store.ts +55 -0
  597. package/app/lib/stores/mcp-store.ts +156 -0
  598. package/app/lib/stores/walkthrough-store.ts +118 -0
  599. package/app/lib/types.ts +20 -0
  600. package/app/package.json +3 -1
  601. package/app/tsconfig.json +1 -1
  602. package/bin/cli.js +168 -1385
  603. package/bin/commands/agent.js +156 -20
  604. package/bin/commands/api.js +14 -11
  605. package/bin/commands/ask.js +79 -68
  606. package/bin/commands/build.js +26 -0
  607. package/bin/commands/config.js +170 -0
  608. package/bin/commands/dev.js +58 -0
  609. package/bin/commands/doctor.js +205 -0
  610. package/bin/commands/file.js +558 -40
  611. package/bin/commands/gateway.js +42 -0
  612. package/bin/commands/init-skills.js +56 -0
  613. package/bin/commands/logs.js +32 -0
  614. package/bin/commands/mcp-cmd.js +57 -0
  615. package/bin/commands/onboard.js +25 -0
  616. package/bin/commands/open.js +41 -0
  617. package/bin/commands/restart.js +48 -0
  618. package/bin/commands/search.js +16 -14
  619. package/bin/commands/space.js +100 -25
  620. package/bin/commands/start.js +262 -0
  621. package/bin/commands/status.js +2 -2
  622. package/bin/commands/stop.js +14 -0
  623. package/bin/commands/sync-cmd.js +134 -0
  624. package/bin/commands/token.js +98 -0
  625. package/bin/commands/uninstall.js +154 -0
  626. package/bin/commands/update.js +286 -0
  627. package/bin/lib/build.js +1 -1
  628. package/bin/lib/colors.js +8 -7
  629. package/bin/lib/command.js +37 -96
  630. package/bin/lib/config.js +5 -0
  631. package/bin/lib/csv.js +19 -0
  632. package/bin/lib/jsonc.js +12 -0
  633. package/bin/lib/markdown.js +69 -0
  634. package/bin/lib/mcp-agents.js +27 -8
  635. package/bin/lib/mcp-build.js +1 -1
  636. package/bin/lib/mcp-install.js +13 -4
  637. package/bin/lib/one-shot.js +88 -0
  638. package/bin/lib/path-expand.js +9 -0
  639. package/bin/lib/remote.js +65 -0
  640. package/bin/lib/repl.js +167 -0
  641. package/bin/lib/{utils.js → shell.js} +10 -26
  642. package/bin/lib/skill-check.js +1 -1
  643. package/bin/lib/sse-stream.js +167 -0
  644. package/bin/lib/sync.js +140 -34
  645. package/mcp/README.md +2 -2
  646. package/mcp/dist/index.cjs +43 -43
  647. package/mcp/package.json +1 -1
  648. package/mcp/src/index.ts +77 -61
  649. package/package.json +2 -2
  650. package/scripts/setup.js +183 -121
  651. package/skills/mindos/SKILL.md +93 -93
  652. package/skills/mindos/references/preference-capture.md +4 -4
  653. package/skills/mindos/references/write-supplement.md +2 -2
  654. package/skills/mindos-zh/SKILL.md +100 -104
  655. package/skills/mindos-zh/references/preference-capture.md +4 -4
  656. package/skills/mindos-zh/references/write-supplement.md +2 -2
  657. package/templates/empty/INSTRUCTION.md +0 -1
  658. package/templates/en/INSTRUCTION.md +0 -1
  659. package/templates/template-generation-skill.md +0 -1
  660. package/templates/zh/INSTRUCTION.md +0 -1
  661. package/_standalone/.next/server/chunks/1473.js +0 -52
  662. package/_standalone/.next/server/chunks/248.js +0 -15
  663. package/_standalone/.next/server/chunks/359.js +0 -2
  664. package/_standalone/.next/server/chunks/4931.js +0 -202
  665. package/_standalone/.next/server/chunks/7670.js +0 -1
  666. package/_standalone/.next/static/chunks/1038-ed04d6651ec92312.js +0 -1
  667. package/_standalone/.next/static/chunks/1263-6df1734e4273adb1.js +0 -25
  668. package/_standalone/.next/static/chunks/275-ebcaaedabe706903.js +0 -1
  669. package/_standalone/.next/static/chunks/3637.4bcd01a4db78b894.js +0 -1
  670. package/_standalone/.next/static/chunks/5637-b97c869adf70c82e.js +0 -1
  671. package/_standalone/.next/static/chunks/5681-a53362a1cd629dc6.js +0 -1
  672. package/_standalone/.next/static/chunks/9602-35ca17b688f1a4fe.js +0 -1
  673. package/_standalone/.next/static/chunks/9670-d59e4d45ed705f58.js +0 -6
  674. package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/route-d4762cc48529e566.js +0 -1
  675. package/_standalone/.next/static/chunks/app/_global-error/page-d4762cc48529e566.js +0 -1
  676. package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-519d4da1142db5ef.js +0 -1
  677. package/_standalone/.next/static/chunks/app/agents/page-b709cf3103321609.js +0 -5
  678. package/_standalone/.next/static/chunks/app/api/a2a/agents/route-d4762cc48529e566.js +0 -1
  679. package/_standalone/.next/static/chunks/app/api/a2a/delegations/route-d4762cc48529e566.js +0 -1
  680. package/_standalone/.next/static/chunks/app/api/a2a/discover/route-d4762cc48529e566.js +0 -1
  681. package/_standalone/.next/static/chunks/app/api/a2a/route-d4762cc48529e566.js +0 -1
  682. package/_standalone/.next/static/chunks/app/api/acp/config/route-d4762cc48529e566.js +0 -1
  683. package/_standalone/.next/static/chunks/app/api/acp/detect/route-d4762cc48529e566.js +0 -1
  684. package/_standalone/.next/static/chunks/app/api/acp/install/route-d4762cc48529e566.js +0 -1
  685. package/_standalone/.next/static/chunks/app/api/acp/registry/route-d4762cc48529e566.js +0 -1
  686. package/_standalone/.next/static/chunks/app/api/acp/session/route-d4762cc48529e566.js +0 -1
  687. package/_standalone/.next/static/chunks/app/api/agent-activity/route-d4762cc48529e566.js +0 -1
  688. package/_standalone/.next/static/chunks/app/api/ask/route-d4762cc48529e566.js +0 -1
  689. package/_standalone/.next/static/chunks/app/api/ask-sessions/route-d4762cc48529e566.js +0 -1
  690. package/_standalone/.next/static/chunks/app/api/auth/route-d4762cc48529e566.js +0 -1
  691. package/_standalone/.next/static/chunks/app/api/backlinks/route-d4762cc48529e566.js +0 -1
  692. package/_standalone/.next/static/chunks/app/api/bootstrap/route-d4762cc48529e566.js +0 -1
  693. package/_standalone/.next/static/chunks/app/api/changes/route-d4762cc48529e566.js +0 -1
  694. package/_standalone/.next/static/chunks/app/api/export/route-d4762cc48529e566.js +0 -1
  695. package/_standalone/.next/static/chunks/app/api/extract-pdf/route-d4762cc48529e566.js +0 -1
  696. package/_standalone/.next/static/chunks/app/api/file/import/route-d4762cc48529e566.js +0 -1
  697. package/_standalone/.next/static/chunks/app/api/file/route-d4762cc48529e566.js +0 -1
  698. package/_standalone/.next/static/chunks/app/api/files/route-d4762cc48529e566.js +0 -1
  699. package/_standalone/.next/static/chunks/app/api/git/route-d4762cc48529e566.js +0 -1
  700. package/_standalone/.next/static/chunks/app/api/graph/route-d4762cc48529e566.js +0 -1
  701. package/_standalone/.next/static/chunks/app/api/health/route-d4762cc48529e566.js +0 -1
  702. package/_standalone/.next/static/chunks/app/api/init/route-d4762cc48529e566.js +0 -1
  703. package/_standalone/.next/static/chunks/app/api/mcp/agents/route-d4762cc48529e566.js +0 -1
  704. package/_standalone/.next/static/chunks/app/api/mcp/install/route-d4762cc48529e566.js +0 -1
  705. package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-d4762cc48529e566.js +0 -1
  706. package/_standalone/.next/static/chunks/app/api/mcp/restart/route-d4762cc48529e566.js +0 -1
  707. package/_standalone/.next/static/chunks/app/api/mcp/status/route-d4762cc48529e566.js +0 -1
  708. package/_standalone/.next/static/chunks/app/api/monitoring/route-d4762cc48529e566.js +0 -1
  709. package/_standalone/.next/static/chunks/app/api/recent-files/route-d4762cc48529e566.js +0 -1
  710. package/_standalone/.next/static/chunks/app/api/restart/route-d4762cc48529e566.js +0 -1
  711. package/_standalone/.next/static/chunks/app/api/search/route-d4762cc48529e566.js +0 -1
  712. package/_standalone/.next/static/chunks/app/api/settings/list-models/route-d4762cc48529e566.js +0 -1
  713. package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-d4762cc48529e566.js +0 -1
  714. package/_standalone/.next/static/chunks/app/api/settings/route-d4762cc48529e566.js +0 -1
  715. package/_standalone/.next/static/chunks/app/api/settings/test-key/route-d4762cc48529e566.js +0 -1
  716. package/_standalone/.next/static/chunks/app/api/setup/check-path/route-d4762cc48529e566.js +0 -1
  717. package/_standalone/.next/static/chunks/app/api/setup/check-port/route-d4762cc48529e566.js +0 -1
  718. package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-d4762cc48529e566.js +0 -1
  719. package/_standalone/.next/static/chunks/app/api/setup/ls/route-d4762cc48529e566.js +0 -1
  720. package/_standalone/.next/static/chunks/app/api/setup/route-d4762cc48529e566.js +0 -1
  721. package/_standalone/.next/static/chunks/app/api/skills/route-d4762cc48529e566.js +0 -1
  722. package/_standalone/.next/static/chunks/app/api/sync/route-d4762cc48529e566.js +0 -1
  723. package/_standalone/.next/static/chunks/app/api/tree-version/route-d4762cc48529e566.js +0 -1
  724. package/_standalone/.next/static/chunks/app/api/uninstall/route-d4762cc48529e566.js +0 -1
  725. package/_standalone/.next/static/chunks/app/api/update/route-d4762cc48529e566.js +0 -1
  726. package/_standalone/.next/static/chunks/app/api/update-check/route-d4762cc48529e566.js +0 -1
  727. package/_standalone/.next/static/chunks/app/api/update-status/route-d4762cc48529e566.js +0 -1
  728. package/_standalone/.next/static/chunks/app/api/workflows/route-d4762cc48529e566.js +0 -1
  729. package/_standalone/.next/static/chunks/app/changes/page-def5210095f8698d.js +0 -1
  730. package/_standalone/.next/static/chunks/app/echo/[segment]/page-be28eff31b1a186e.js +0 -11
  731. package/_standalone/.next/static/chunks/app/echo/page-d4762cc48529e566.js +0 -1
  732. package/_standalone/.next/static/chunks/app/explore/page-e4b8098dca200389.js +0 -4
  733. package/_standalone/.next/static/chunks/app/help/page-d5e57d73d94bad19.js +0 -1
  734. package/_standalone/.next/static/chunks/app/layout-d91cdbe2ecf135e1.js +0 -173
  735. package/_standalone/.next/static/chunks/app/login/page-321875768b70938a.js +0 -1
  736. package/_standalone/.next/static/chunks/app/page-718fdf170428b43c.js +0 -7
  737. package/_standalone/.next/static/chunks/app/setup/page-01ab1f549d636057.js +0 -1
  738. package/_standalone/.next/static/chunks/app/trash/page-89b1430cc8a16f18.js +0 -1
  739. package/_standalone/.next/static/chunks/app/view/[...path]/loading-d4762cc48529e566.js +0 -1
  740. package/_standalone/.next/static/chunks/app/view/[...path]/not-found-f22c513bbc348cc8.js +0 -1
  741. package/_standalone/.next/static/chunks/app/view/[...path]/page-6e3dc47699a01de1.js +0 -12
  742. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d4762cc48529e566.js +0 -1
  743. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d4762cc48529e566.js +0 -1
  744. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d4762cc48529e566.js +0 -1
  745. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d4762cc48529e566.js +0 -1
  746. package/_standalone/.next/static/chunks/webpack-3489a2b6c2882b0c.js +0 -1
  747. package/_standalone/.next/static/css/f16595bc58a16d5d.css +0 -1
  748. package/_standalone/.next/static/ushZ_NJ8rE3rG5hZfaYOX/_buildManifest.js +0 -1
  749. package/_standalone/components/walkthrough/WalkthroughProvider.tsx +0 -133
  750. package/_standalone/hooks/useMcpData.tsx +0 -169
  751. package/_standalone/lib/i18n-en.ts +0 -2
  752. package/_standalone/lib/i18n-zh.ts +0 -2
  753. package/_standalone/lib/types.ts +0 -70
  754. package/app/components/walkthrough/WalkthroughProvider.tsx +0 -133
  755. package/app/hooks/useMcpData.tsx +0 -169
  756. package/app/lib/LocaleContext.tsx +0 -60
  757. package/app/lib/i18n-en.ts +0 -2
  758. package/app/lib/i18n-zh.ts +0 -2
  759. /package/_standalone/.next/static/{ushZ_NJ8rE3rG5hZfaYOX → Ij3PFh-a0zi5K_ANoSAW0}/_ssgManifest.js +0 -0
@@ -1,9 +1,10 @@
1
1
  'use client';
2
2
 
3
- import { useEffect, useLayoutEffect, useRef, useState, useCallback } from 'react';
4
- import { Sparkles, Send, StopCircle, SquarePen, History, X, Maximize2, Minimize2, PanelRight, AppWindow, Plus } from 'lucide-react';
5
- import { useLocale } from '@/lib/LocaleContext';
6
- import type { Message, ImagePart } from '@/lib/types';
3
+ import { useEffect, useLayoutEffect, useRef, useState, useCallback, useMemo } from 'react';
4
+ import { Send, StopCircle, X, Plus, FileText, ImageIcon } from 'lucide-react';
5
+ import { useLocale } from '@/lib/stores/locale-store';
6
+ import type { AskMode } from '@/lib/types';
7
+ import ModeCapsule, { getPersistedMode } from '@/components/ask/ModeCapsule';
7
8
  import { useAskSession } from '@/hooks/useAskSession';
8
9
  import { useFileUpload } from '@/hooks/useFileUpload';
9
10
  import { useImageUpload } from '@/hooks/useImageUpload';
@@ -15,10 +16,12 @@ import MentionPopover from '@/components/ask/MentionPopover';
15
16
  import SlashCommandPopover from '@/components/ask/SlashCommandPopover';
16
17
  import SessionHistory from '@/components/ask/SessionHistory';
17
18
  import SessionTabBar from '@/components/ask/SessionTabBar';
19
+ import AskHeader from '@/components/ask/AskHeader';
18
20
  import FileChip from '@/components/ask/FileChip';
19
21
  import AgentSelectorCapsule from '@/components/ask/AgentSelectorCapsule';
20
- import { consumeUIMessageStream } from '@/lib/agent/stream-consumer';
21
- import { isRetryableError, retryDelay, sleep } from '@/lib/agent/reconnect';
22
+ import ProviderModelCapsule, { getPersistedProvider } from '@/components/ask/ProviderModelCapsule';
23
+ import type { ProviderId } from '@/lib/agent/providers';
24
+ import { useAskChat } from '@/hooks/useAskChat';
22
25
  import { cn } from '@/lib/utils';
23
26
  import { useAcpDetection } from '@/hooks/useAcpDetection';
24
27
  import type { AcpAgentSelection } from '@/hooks/useAskModal';
@@ -26,23 +29,32 @@ import type { AcpAgentSelection } from '@/hooks/useAskModal';
26
29
  /** Textarea auto-grows with content up to this many visible lines, then scrolls */
27
30
  const TEXTAREA_MAX_VISIBLE_LINES = 8;
28
31
 
32
+ /** Per-element cached metrics to avoid getComputedStyle on every keystroke */
33
+ const _metricsCache = new WeakMap<HTMLTextAreaElement, { maxH: number }>();
34
+
29
35
  /** Auto-size textarea height to fit content, capped at maxVisibleLines */
30
36
  function syncTextareaToContent(el: HTMLTextAreaElement, maxVisibleLines: number): void {
31
- const style = getComputedStyle(el);
32
- const parsedLh = parseFloat(style.lineHeight);
33
- const parsedFs = parseFloat(style.fontSize);
34
- const fontSize = Number.isFinite(parsedFs) ? parsedFs : 14;
35
- const lineHeight = Number.isFinite(parsedLh) ? parsedLh : fontSize * 1.375;
36
- const pad =
37
- (Number.isFinite(parseFloat(style.paddingTop)) ? parseFloat(style.paddingTop) : 0) +
38
- (Number.isFinite(parseFloat(style.paddingBottom)) ? parseFloat(style.paddingBottom) : 0);
39
- const maxH = lineHeight * maxVisibleLines + pad;
40
- if (!Number.isFinite(maxH) || maxH <= 0) return;
41
- el.style.height = '0px';
42
- const next = Math.min(el.scrollHeight, maxH);
43
- el.style.height = `${Number.isFinite(next) ? next : maxH}px`;
44
- // Only show scrollbar when content exceeds max height
45
- el.style.overflowY = el.scrollHeight > maxH ? 'auto' : 'hidden';
37
+ let cached = _metricsCache.get(el);
38
+ if (!cached) {
39
+ const style = getComputedStyle(el);
40
+ const parsedLh = parseFloat(style.lineHeight);
41
+ const parsedFs = parseFloat(style.fontSize);
42
+ const fontSize = Number.isFinite(parsedFs) ? parsedFs : 14;
43
+ const lineHeight = Number.isFinite(parsedLh) ? parsedLh : fontSize * 1.375;
44
+ const pad =
45
+ (Number.isFinite(parseFloat(style.paddingTop)) ? parseFloat(style.paddingTop) : 0) +
46
+ (Number.isFinite(parseFloat(style.paddingBottom)) ? parseFloat(style.paddingBottom) : 0);
47
+ const maxH = lineHeight * maxVisibleLines + pad;
48
+ if (!Number.isFinite(maxH) || maxH <= 0) return;
49
+ cached = { maxH };
50
+ _metricsCache.set(el, cached);
51
+ }
52
+ const { maxH } = cached;
53
+ el.style.height = 'auto';
54
+ const contentH = el.scrollHeight;
55
+ const next = Math.min(contentH, maxH);
56
+ el.style.height = `${next}px`;
57
+ el.style.overflowY = contentH > maxH ? 'auto' : 'hidden';
46
58
  }
47
59
 
48
60
  interface AskContentProps {
@@ -70,42 +82,83 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
70
82
 
71
83
  const inputRef = useRef<HTMLTextAreaElement>(null);
72
84
  const imageInputRef = useRef<HTMLInputElement>(null);
73
- const abortRef = useRef<AbortController | null>(null);
74
- const firstMessageFired = useRef(false);
75
85
  const { t } = useLocale();
76
86
  const [mounted, setMounted] = useState(false);
77
87
  useEffect(() => setMounted(true), []);
78
88
 
79
89
  const [input, setInput] = useState('');
80
- const [isLoading, setIsLoading] = useState(false);
81
- const [loadingPhase, setLoadingPhase] = useState<'connecting' | 'thinking' | 'streaming' | 'reconnecting'>('connecting');
82
- const [reconnectAttempt, setReconnectAttempt] = useState(0);
83
- const reconnectMaxRef = useRef(3);
90
+ const inputValueRef = useRef('');
91
+ inputValueRef.current = input;
84
92
  const [attachedFiles, setAttachedFiles] = useState<string[]>([]);
93
+ const attachedFilesRef = useRef(attachedFiles);
94
+ attachedFilesRef.current = attachedFiles;
85
95
  const [showHistory, setShowHistory] = useState(false);
86
96
  const [isDragOver, setIsDragOver] = useState(false);
87
97
  const [showAttachMenu, setShowAttachMenu] = useState(false);
88
98
 
89
99
  const [selectedSkill, setSelectedSkill] = useState<SlashItem | null>(null);
100
+ const selectedSkillRef = useRef(selectedSkill);
101
+ selectedSkillRef.current = selectedSkill;
90
102
  const [selectedAcpAgent, setSelectedAcpAgent] = useState<AcpAgentSelection | null>(null);
103
+ const selectedAcpAgentRef = useRef(selectedAcpAgent);
104
+ selectedAcpAgentRef.current = selectedAcpAgent;
105
+ const [chatMode, setChatMode] = useState<AskMode>('agent');
106
+ const [providerOverride, setProviderOverride] = useState<ProviderId | null>(null);
107
+
108
+ useEffect(() => {
109
+ setChatMode(getPersistedMode());
110
+ setProviderOverride(getPersistedProvider());
111
+ }, []);
91
112
 
92
113
  const session = useAskSession(currentFile);
114
+ const sessionRef = useRef(session);
115
+ sessionRef.current = session;
93
116
  const upload = useFileUpload();
117
+ const uploadRef = useRef(upload);
118
+ uploadRef.current = upload;
94
119
  const imageUpload = useImageUpload();
95
120
  const mention = useMention();
96
121
  const slash = useSlashCommand();
97
122
  const acpDetection = useAcpDetection();
98
123
 
124
+ const imageUploadRef = useRef(imageUpload);
125
+ imageUploadRef.current = imageUpload;
126
+ const mentionRef = useRef(mention);
127
+ mentionRef.current = mention;
128
+ const slashRef = useRef(slash);
129
+ slashRef.current = slash;
130
+
131
+ const resetInputState = useCallback(() => {
132
+ setInput('');
133
+ setSelectedSkill(null);
134
+ setSelectedAcpAgent(null);
135
+ setAttachedFiles(currentFile ? [currentFile] : []);
136
+ }, [currentFile]);
137
+
138
+ const chatRefs = useRef({ inputValueRef, mentionRef, slashRef, imageUploadRef, sessionRef, uploadRef, selectedSkillRef, selectedAcpAgentRef, attachedFilesRef });
139
+ const chat = useAskChat({
140
+ currentFile,
141
+ chatMode,
142
+ providerOverride,
143
+ onFirstMessage,
144
+ refs: chatRefs.current,
145
+ errorLabels: { noResponse: t.ask.errorNoResponse, stopped: t.ask.stopped },
146
+ resetInputState,
147
+ });
148
+ const { isLoading, loadingPhase, reconnectAttempt, reconnectMaxRef } = chat;
149
+ const handleSubmit = chat.submit;
150
+ const handleStop = chat.stop;
151
+
99
152
  useEffect(() => {
100
153
  const handler = (e: Event) => {
101
154
  const files = (e as CustomEvent).detail?.files;
102
155
  if (Array.isArray(files) && files.length > 0) {
103
- upload.injectFiles(files);
156
+ uploadRef.current.injectFiles(files);
104
157
  }
105
158
  };
106
159
  window.addEventListener('mindos:inject-ask-files', handler);
107
160
  return () => window.removeEventListener('mindos:inject-ask-files', handler);
108
- }, [upload]);
161
+ }, []);
109
162
 
110
163
  // Focus and init session when becoming visible (edge-triggered for panel, level-triggered for modal)
111
164
  const prevVisibleRef = useRef(false);
@@ -122,7 +175,7 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
122
175
  setTimeout(() => inputRef.current?.focus(), 50);
123
176
  void session.initSessions();
124
177
  setInput(initialMessage || '');
125
- firstMessageFired.current = false;
178
+ chat.firstMessageFired.current = false;
126
179
  setAttachedFiles(currentFile ? [currentFile] : []);
127
180
  upload.clearAttachments();
128
181
  imageUpload.clearImages();
@@ -136,7 +189,7 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
136
189
  setAttachedFiles(currentFile ? [currentFile] : []);
137
190
  } else if (!visible && variant === 'modal') {
138
191
  // Modal: abort streaming on close
139
- abortRef.current?.abort();
192
+ chat.abortRef.current?.abort();
140
193
  }
141
194
  prevVisibleRef.current = visible;
142
195
  prevFileRef.current = currentFile;
@@ -147,28 +200,32 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
147
200
  useEffect(() => {
148
201
  if (!visible || !session.activeSessionId) return;
149
202
  const msgs = session.messages;
150
- if (isLoading && msgs.length > 0) {
203
+ if (chat.isLoading && msgs.length > 0) {
151
204
  const last = msgs[msgs.length - 1];
152
205
  if (last.role === 'assistant' && !last.content.trim() && (!last.parts || last.parts.length === 0)) return;
153
206
  }
154
207
  session.persistSession(msgs, session.activeSessionId);
155
208
  return () => session.clearPersistTimer();
156
209
  // eslint-disable-next-line react-hooks/exhaustive-deps
157
- }, [visible, session.messages, session.activeSessionId, isLoading]);
210
+ }, [visible, session.messages, session.activeSessionId, chat.isLoading]);
158
211
 
159
- // Esc to close modal only
212
+ // Esc to close modal or exit focus mode
160
213
  useEffect(() => {
161
- if (variant !== 'modal' || !visible || !onClose) return;
214
+ if (!visible) return;
215
+ const isModal = variant === 'modal';
216
+ const isFocused = variant === 'panel' && maximized;
217
+ if (!isModal && !isFocused) return;
162
218
  const handler = (e: KeyboardEvent) => {
163
219
  if (e.key === 'Escape') {
164
- if (mention.mentionQuery !== null) { mention.resetMention(); return; }
165
- if (slash.slashQuery !== null) { slash.resetSlash(); return; }
166
- onClose();
220
+ if (mentionRef.current.mentionQuery !== null) { mentionRef.current.resetMention(); return; }
221
+ if (slashRef.current.slashQuery !== null) { slashRef.current.resetSlash(); return; }
222
+ if (isFocused && onMaximize) { onMaximize(); return; }
223
+ if (isModal && onClose) { onClose(); }
167
224
  }
168
225
  };
169
226
  window.addEventListener('keydown', handler);
170
227
  return () => window.removeEventListener('keydown', handler);
171
- }, [variant, visible, onClose, mention, slash]);
228
+ }, [variant, visible, onClose, maximized, onMaximize]);
172
229
 
173
230
  // Close attach menu on any outside click
174
231
  useEffect(() => {
@@ -188,6 +245,14 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
188
245
  syncTextareaToContent(el, TEXTAREA_MAX_VISIBLE_LINES);
189
246
  }, [input, isLoading, visible]);
190
247
 
248
+ useEffect(() => {
249
+ const el = inputRef.current;
250
+ if (!el) return;
251
+ const handler = () => _metricsCache.delete(el);
252
+ window.addEventListener('resize', handler);
253
+ return () => window.removeEventListener('resize', handler);
254
+ }, []);
255
+
191
256
  const mentionTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
192
257
  const slashTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
193
258
  const handleInputChange = useCallback((val: string, cursorPos?: number) => {
@@ -195,9 +260,9 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
195
260
  const pos = cursorPos ?? val.length;
196
261
  if (mentionTimerRef.current) clearTimeout(mentionTimerRef.current);
197
262
  if (slashTimerRef.current) clearTimeout(slashTimerRef.current);
198
- mentionTimerRef.current = setTimeout(() => mention.updateMentionFromInput(val, pos), 80);
199
- slashTimerRef.current = setTimeout(() => slash.updateSlashFromInput(val, pos), 80);
200
- }, [mention, slash]);
263
+ mentionTimerRef.current = setTimeout(() => mentionRef.current.updateMentionFromInput(val, pos), 80);
264
+ slashTimerRef.current = setTimeout(() => slashRef.current.updateSlashFromInput(val, pos), 80);
265
+ }, []);
201
266
 
202
267
  useEffect(() => {
203
268
  return () => {
@@ -208,273 +273,111 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
208
273
 
209
274
  const selectMention = useCallback((filePath: string) => {
210
275
  const el = inputRef.current;
211
- const cursorPos = el?.selectionStart ?? input.length;
212
- const before = input.slice(0, cursorPos);
276
+ const val = inputValueRef.current;
277
+ const cursorPos = el?.selectionStart ?? val.length;
278
+ const before = val.slice(0, cursorPos);
213
279
  const atIdx = before.lastIndexOf('@');
214
- const newVal = input.slice(0, atIdx) + input.slice(cursorPos);
280
+ const newVal = val.slice(0, atIdx) + val.slice(cursorPos);
215
281
  setInput(newVal);
216
- mention.resetMention();
217
- if (!attachedFiles.includes(filePath)) {
282
+ mentionRef.current.resetMention();
283
+ if (!attachedFilesRef.current.includes(filePath)) {
218
284
  setAttachedFiles(prev => [...prev, filePath]);
219
285
  }
220
286
  setTimeout(() => {
221
287
  inputRef.current?.focus();
222
288
  inputRef.current?.setSelectionRange(atIdx, atIdx);
223
289
  }, 0);
224
- }, [input, attachedFiles, mention]);
290
+ }, []);
225
291
 
226
292
  const selectSlashCommand = useCallback((item: SlashItem) => {
227
293
  const el = inputRef.current;
228
- const cursorPos = el?.selectionStart ?? input.length;
229
- const before = input.slice(0, cursorPos);
294
+ const val = inputValueRef.current;
295
+ const cursorPos = el?.selectionStart ?? val.length;
296
+ const before = val.slice(0, cursorPos);
230
297
  const slashIdx = before.lastIndexOf('/');
231
- const newVal = input.slice(0, slashIdx) + input.slice(cursorPos);
298
+ const newVal = val.slice(0, slashIdx) + val.slice(cursorPos);
232
299
  setInput(newVal);
233
300
  setSelectedSkill(item);
234
- slash.resetSlash();
301
+ slashRef.current.resetSlash();
235
302
  setTimeout(() => {
236
303
  inputRef.current?.focus();
237
304
  inputRef.current?.setSelectionRange(slashIdx, slashIdx);
238
305
  }, 0);
239
- }, [input, slash]);
306
+ }, []);
307
+
308
+ const selectMentionRef = useRef(selectMention);
309
+ selectMentionRef.current = selectMention;
310
+ const selectSlashRef = useRef(selectSlashCommand);
311
+ selectSlashRef.current = selectSlashCommand;
240
312
 
241
313
  const handleInputKeyDown = useCallback(
242
314
  (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
243
- if (mention.mentionQuery !== null) {
315
+ const m = mentionRef.current;
316
+ const s = slashRef.current;
317
+ if (m.mentionQuery !== null) {
244
318
  if (e.key === 'Escape') {
245
319
  e.preventDefault();
246
- mention.resetMention();
320
+ m.resetMention();
247
321
  return;
248
322
  }
249
323
  if (e.key === 'ArrowDown') {
250
324
  e.preventDefault();
251
- mention.navigateMention('down');
325
+ m.navigateMention('down');
252
326
  } else if (e.key === 'ArrowUp') {
253
327
  e.preventDefault();
254
- mention.navigateMention('up');
328
+ m.navigateMention('up');
255
329
  } else if (e.key === 'Enter' || e.key === 'Tab') {
256
330
  if (e.key === 'Enter' && (e.shiftKey || e.nativeEvent.isComposing)) return;
257
- if (mention.mentionResults.length > 0) {
331
+ if (m.mentionResults.length > 0) {
258
332
  e.preventDefault();
259
- selectMention(mention.mentionResults[mention.mentionIndex]);
333
+ selectMentionRef.current(m.mentionResults[m.mentionIndex]);
260
334
  }
261
335
  }
262
336
  return;
263
337
  }
264
- if (slash.slashQuery !== null) {
338
+ if (s.slashQuery !== null) {
265
339
  if (e.key === 'Escape') {
266
340
  e.preventDefault();
267
- slash.resetSlash();
341
+ s.resetSlash();
268
342
  return;
269
343
  }
270
344
  if (e.key === 'ArrowDown') {
271
345
  e.preventDefault();
272
- slash.navigateSlash('down');
346
+ s.navigateSlash('down');
273
347
  } else if (e.key === 'ArrowUp') {
274
348
  e.preventDefault();
275
- slash.navigateSlash('up');
349
+ s.navigateSlash('up');
276
350
  } else if (e.key === 'Enter' || e.key === 'Tab') {
277
351
  if (e.key === 'Enter' && (e.shiftKey || e.nativeEvent.isComposing)) return;
278
- if (slash.slashResults.length > 0) {
352
+ if (s.slashResults.length > 0) {
279
353
  e.preventDefault();
280
- selectSlashCommand(slash.slashResults[slash.slashIndex]);
354
+ selectSlashRef.current(s.slashResults[s.slashIndex]);
281
355
  }
282
356
  }
283
357
  return;
284
358
  }
285
- if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing && !isLoading && (input.trim() || imageUpload.images.length > 0)) {
359
+ if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing && !chat.isLoadingRef.current && (inputValueRef.current.trim() || imageUploadRef.current.images.length > 0)) {
286
360
  e.preventDefault();
287
361
  (e.currentTarget as HTMLTextAreaElement).form?.requestSubmit();
288
362
  }
289
363
  },
290
- [mention, selectMention, slash, selectSlashCommand, isLoading, input, imageUpload.images],
364
+ [],
291
365
  );
292
366
 
293
- const handleStop = useCallback(() => { abortRef.current?.abort(); }, []);
294
-
295
- const handleSubmit = useCallback(async (e: React.FormEvent) => {
296
- e.preventDefault();
297
- if (mention.mentionQuery !== null || slash.slashQuery !== null) return;
298
- const text = input.trim();
299
- if ((!text && imageUpload.images.length === 0) || isLoading) return;
300
-
301
- const pendingImages = imageUpload.images.length > 0 ? [...imageUpload.images] : undefined;
302
- const userMsg: Message = {
303
- role: 'user',
304
- content: text, // No [ACP:] prefix — pass clean text
305
- timestamp: Date.now(),
306
- ...(selectedSkill && { skillName: selectedSkill.name }),
307
- ...(pendingImages && { images: pendingImages }),
308
- };
309
- imageUpload.clearImages();
310
- const requestMessages = [...session.messages, userMsg];
311
- session.setMessages([...requestMessages, { role: 'assistant', content: '', timestamp: Date.now() }]);
312
- setInput('');
313
- setSelectedSkill(null);
314
- setSelectedAcpAgent(null);
315
- if (onFirstMessage && !firstMessageFired.current) {
316
- firstMessageFired.current = true;
317
- onFirstMessage();
318
- }
319
- setAttachedFiles(currentFile ? [currentFile] : []);
320
- setIsLoading(true);
321
- setLoadingPhase('connecting');
322
- setReconnectAttempt(0);
323
-
324
- const controller = new AbortController();
325
- abortRef.current = controller;
326
-
327
- let maxRetries = 3;
328
- try {
329
- const stored = localStorage.getItem('mindos-reconnect-retries');
330
- if (stored !== null) { const n = parseInt(stored, 10); if (Number.isFinite(n)) maxRetries = Math.max(0, Math.min(10, n)); }
331
- } catch { /* localStorage unavailable */ }
332
- reconnectMaxRef.current = maxRetries;
333
-
334
- const requestBody = JSON.stringify({
335
- messages: requestMessages,
336
- currentFile,
337
- attachedFiles,
338
- uploadedFiles: upload.localAttachments.map(f => ({
339
- name: f.name,
340
- content: f.content.length > 20_000
341
- ? f.content.slice(0, 20_000) + '\n\n[...truncated to first ~20000 chars]'
342
- : f.content,
343
- })),
344
- selectedAcpAgent, // Send structured field instead of text prefix
345
- });
346
-
347
- const doFetch = async (): Promise<{ finalMessage: Message }> => {
348
- const res = await fetch('/api/ask', {
349
- method: 'POST',
350
- headers: { 'Content-Type': 'application/json' },
351
- body: requestBody,
352
- signal: controller.signal,
353
- });
354
-
355
- if (!res.ok) {
356
- let errorMsg = `Request failed (${res.status})`;
357
- try {
358
- const errBody = await res.json() as { error?: { message?: string } | string; message?: string };
359
- if (typeof errBody?.error === 'string' && errBody.error.trim()) {
360
- errorMsg = errBody.error;
361
- } else if (typeof errBody?.error === 'object' && typeof errBody.error?.message === 'string' && errBody.error.message.trim()) {
362
- errorMsg = errBody.error.message;
363
- } else if (typeof errBody?.message === 'string' && errBody.message.trim()) {
364
- errorMsg = errBody.message;
365
- }
366
- } catch (err) { console.warn("[AskContent] error body parse failed:", err); }
367
- const err = new Error(errorMsg);
368
- (err as Error & { httpStatus?: number }).httpStatus = res.status;
369
- throw err;
370
- }
371
-
372
- if (!res.body) throw new Error('No response body');
373
-
374
- setLoadingPhase('thinking');
375
-
376
- const finalMessage = await consumeUIMessageStream(
377
- res.body,
378
- (msg) => {
379
- setLoadingPhase('streaming');
380
- session.setMessages(prev => {
381
- const updated = [...prev];
382
- updated[updated.length - 1] = msg;
383
- return updated;
384
- });
385
- },
386
- controller.signal,
387
- );
388
- return { finalMessage };
389
- };
390
-
391
- try {
392
- let lastError: Error | null = null;
393
-
394
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
395
- if (controller.signal.aborted) break;
396
-
397
- if (attempt > 0) {
398
- setReconnectAttempt(attempt);
399
- setLoadingPhase('reconnecting');
400
- session.setMessages(prev => {
401
- const updated = [...prev];
402
- updated[updated.length - 1] = { role: 'assistant', content: '', timestamp: Date.now() };
403
- return updated;
404
- });
405
- await sleep(retryDelay(attempt - 1), controller.signal);
406
- setLoadingPhase('connecting');
407
- }
408
-
409
- try {
410
- const { finalMessage } = await doFetch();
411
- if (!finalMessage.content.trim() && (!finalMessage.parts || finalMessage.parts.length === 0)) {
412
- session.setMessages(prev => {
413
- const updated = [...prev];
414
- updated[updated.length - 1] = { role: 'assistant', content: `__error__${t.ask.errorNoResponse}` };
415
- return updated;
416
- });
417
- }
418
- return;
419
- } catch (err) {
420
- lastError = err instanceof Error ? err : new Error(String(err));
421
- const httpStatus = (err as Error & { httpStatus?: number }).httpStatus;
422
- if (!isRetryableError(err, httpStatus) || attempt >= maxRetries) break;
423
- }
424
- }
425
-
426
- if (lastError) throw lastError;
427
- } catch (err) {
428
- if ((err as Error).name === 'AbortError') {
429
- session.setMessages(prev => {
430
- const updated = [...prev];
431
- const lastIdx = updated.length - 1;
432
- if (lastIdx >= 0 && updated[lastIdx].role === 'assistant') {
433
- const last = updated[lastIdx];
434
- const hasContent = last.content.trim() || (last.parts && last.parts.length > 0);
435
- if (!hasContent) {
436
- updated[lastIdx] = { role: 'assistant', content: `__error__${t.ask.stopped}` };
437
- }
438
- }
439
- return updated;
440
- });
441
- } else {
442
- const errMsg = err instanceof Error ? err.message : 'Something went wrong';
443
- session.setMessages(prev => {
444
- const updated = [...prev];
445
- const lastIdx = updated.length - 1;
446
- if (lastIdx >= 0 && updated[lastIdx].role === 'assistant') {
447
- const last = updated[lastIdx];
448
- const hasContent = last.content.trim() || (last.parts && last.parts.length > 0);
449
- if (!hasContent) {
450
- updated[lastIdx] = { role: 'assistant', content: `__error__${errMsg}` };
451
- return updated;
452
- }
453
- }
454
- return [...updated, { role: 'assistant', content: `__error__${errMsg}` }];
455
- });
456
- }
457
- } finally {
458
- setIsLoading(false);
459
- setReconnectAttempt(0);
460
- abortRef.current = null;
461
- }
462
- }, [input, session, isLoading, currentFile, attachedFiles, upload.localAttachments, imageUpload.images, imageUpload.clearImages, mention.mentionQuery, slash.slashQuery, selectedSkill, selectedAcpAgent, t.ask.errorNoResponse, t.ask.stopped, onFirstMessage]);
463
-
464
367
  const handleResetSession = useCallback(() => {
465
- if (isLoading) return;
466
- session.resetSession();
368
+ if (chat.isLoadingRef.current) return;
369
+ sessionRef.current.resetSession();
467
370
  setInput('');
468
371
  setAttachedFiles(currentFile ? [currentFile] : []);
469
- upload.clearAttachments();
470
- imageUpload.clearImages();
471
- mention.resetMention();
472
- slash.resetSlash();
372
+ uploadRef.current.clearAttachments();
373
+ imageUploadRef.current.clearImages();
374
+ mentionRef.current.resetMention();
375
+ slashRef.current.resetSlash();
473
376
  setSelectedSkill(null);
474
377
  setSelectedAcpAgent(null);
475
378
  setShowHistory(false);
476
379
  setTimeout(() => inputRef.current?.focus(), 0);
477
- }, [isLoading, currentFile, session, upload, imageUpload, mention, slash]);
380
+ }, [currentFile]);
478
381
 
479
382
  const handleDragOver = useCallback((e: React.DragEvent) => {
480
383
  // Accept mindos file paths and image drops
@@ -490,84 +393,67 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
490
393
  const handleDrop = useCallback(async (e: React.DragEvent) => {
491
394
  e.preventDefault();
492
395
  setIsDragOver(false);
493
- // Try mindos file path first
494
396
  const filePath = e.dataTransfer.getData('text/mindos-path');
495
- if (filePath && !attachedFiles.includes(filePath)) {
496
- setAttachedFiles(prev => [...prev, filePath]);
397
+ if (filePath) {
398
+ const pathType = e.dataTransfer.getData('text/mindos-type');
399
+ const key = pathType === 'directory' ? filePath.replace(/\/?$/, '/') : filePath;
400
+ if (!attachedFilesRef.current.includes(key)) {
401
+ setAttachedFiles(prev => [...prev, key]);
402
+ }
497
403
  return;
498
404
  }
499
- // Try image drop
500
- await imageUpload.handleDrop(e);
501
- }, [attachedFiles, imageUpload]);
405
+ await imageUploadRef.current.handleDrop(e);
406
+ }, []);
502
407
 
503
- /** Handle paste — intercept images before normal text paste */
504
408
  const handlePaste = useCallback((e: React.ClipboardEvent) => {
505
409
  const items = e.clipboardData?.items;
506
410
  if (!items) return;
507
- // Check synchronously for image items — must preventDefault before awaiting
508
411
  const hasImageItem = Array.from(items).some(
509
412
  item => item.kind === 'file' && item.type.startsWith('image/')
510
413
  );
511
414
  if (hasImageItem) {
512
415
  e.preventDefault();
513
- void imageUpload.handlePaste(e);
416
+ void imageUploadRef.current.handlePaste(e);
514
417
  }
515
- }, [imageUpload]);
418
+ }, []);
516
419
 
517
420
  const handleLoadSession = useCallback((id: string) => {
518
- session.loadSession(id);
421
+ sessionRef.current.loadSession(id);
519
422
  setShowHistory(false);
520
423
  setInput('');
521
424
  setAttachedFiles(currentFile ? [currentFile] : []);
522
- upload.clearAttachments();
523
- imageUpload.clearImages();
524
- mention.resetMention();
525
- slash.resetSlash();
425
+ uploadRef.current.clearAttachments();
426
+ imageUploadRef.current.clearImages();
427
+ mentionRef.current.resetMention();
428
+ slashRef.current.resetSlash();
526
429
  setSelectedSkill(null);
527
430
  setSelectedAcpAgent(null);
528
431
  setTimeout(() => inputRef.current?.focus(), 0);
529
- }, [session, currentFile, upload, imageUpload, mention, slash]);
432
+ }, [currentFile]);
530
433
 
531
- const iconSize = isPanel ? 13 : 14;
434
+ const toggleHistory = useCallback(() => setShowHistory(v => !v), []);
532
435
  const inputIconSize = 15;
436
+ const messageLabels = useMemo(() => ({
437
+ connecting: t.ask.connecting,
438
+ thinking: t.ask.thinking,
439
+ generating: t.ask.generating,
440
+ reconnecting: reconnectAttempt > 0 ? t.ask.reconnecting(reconnectAttempt, reconnectMaxRef.current) : undefined,
441
+ }), [t, reconnectAttempt]);
533
442
 
534
443
  return (
535
444
  <>
536
- {/* Header */}
537
- <div className="flex items-center justify-between px-4 py-3 border-b border-border shrink-0">
538
- {!isPanel && (
539
- <div className="absolute top-2 left-1/2 -translate-x-1/2 w-8 h-1 rounded-full bg-muted-foreground/20 md:hidden" />
540
- )}
541
- <div className="flex items-center gap-2 text-sm font-medium text-foreground">
542
- <Sparkles size={isPanel ? 14 : 15} className="text-[var(--amber)]" />
543
- <span className={isPanel ? 'font-display text-xs uppercase tracking-wider text-muted-foreground' : 'font-display'}>
544
- {isPanel ? 'MindOS Agent' : t.ask.title}
545
- </span>
546
- </div>
547
- <div className="flex items-center gap-1 shrink-0">
548
- <button type="button" onClick={(e) => { e.stopPropagation(); setShowHistory(v => !v); }} aria-pressed={showHistory} className={`p-2 rounded transition-colors ${showHistory ? 'bg-muted text-foreground' : 'text-muted-foreground hover:text-foreground hover:bg-muted'}`} title={t.hints.sessionHistory}>
549
- <History size={iconSize} />
550
- </button>
551
- <button type="button" onClick={(e) => { e.stopPropagation(); handleResetSession(); }} disabled={isLoading} className="p-2 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors disabled:opacity-40" title={t.hints.newSession}>
552
- <SquarePen size={iconSize} />
553
- </button>
554
- {isPanel && onMaximize && (
555
- <button type="button" onClick={(e) => { e.stopPropagation(); onMaximize(); }} className="p-2 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={maximized ? t.hints.restorePanel : t.hints.maximizePanel}>
556
- {maximized ? <Minimize2 size={iconSize} /> : <Maximize2 size={iconSize} />}
557
- </button>
558
- )}
559
- {onModeSwitch && (
560
- <button type="button" onClick={(e) => { e.stopPropagation(); onModeSwitch(); }} className="p-2 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={askMode === 'popup' ? t.hints.dockToSide : t.hints.openAsPopup}>
561
- {askMode === 'popup' ? <PanelRight size={iconSize} /> : <AppWindow size={iconSize} />}
562
- </button>
563
- )}
564
- {onClose && (
565
- <button type="button" onClick={(e) => { e.stopPropagation(); onClose(); }} className="p-2 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={t.hints.closePanel} aria-label="Close">
566
- <X size={isPanel ? iconSize : 15} />
567
- </button>
568
- )}
569
- </div>
570
- </div>
445
+ <AskHeader
446
+ isPanel={isPanel}
447
+ showHistory={showHistory}
448
+ onToggleHistory={toggleHistory}
449
+ onReset={handleResetSession}
450
+ isLoading={isLoading}
451
+ maximized={maximized}
452
+ onMaximize={onMaximize}
453
+ askMode={askMode}
454
+ onModeSwitch={onModeSwitch}
455
+ onClose={onClose}
456
+ />
571
457
 
572
458
  {/* Session tabs — panel variant only */}
573
459
  {isPanel && session.sessions.length > 0 && (
@@ -586,12 +472,14 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
586
472
  activeSessionId={session.activeSessionId}
587
473
  onLoad={handleLoadSession}
588
474
  onDelete={session.deleteSession}
475
+ onRename={session.renameSession}
589
476
  onClearAll={session.clearAllSessions}
590
477
  labels={{
591
478
  title: t.ask.sessionHistory ?? 'Session History',
592
479
  clearAll: t.ask.clearAll ?? 'Clear all',
593
480
  confirmClear: t.ask.confirmClear ?? 'Confirm clear?',
594
481
  noSessions: t.ask.noSessions ?? 'No saved sessions.',
482
+ rename: t.ask.renameSession ?? 'Rename',
595
483
  }}
596
484
  />
597
485
  )}
@@ -602,14 +490,10 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
602
490
  isLoading={isLoading}
603
491
  loadingPhase={loadingPhase}
604
492
  emptyPrompt={t.ask.emptyPrompt}
493
+ emptyHint={t.ask.emptyHint}
605
494
  suggestions={t.ask.suggestions}
606
495
  onSuggestionClick={setInput}
607
- labels={{
608
- connecting: t.ask.connecting,
609
- thinking: t.ask.thinking,
610
- generating: t.ask.generating,
611
- reconnecting: reconnectAttempt > 0 ? t.ask.reconnecting(reconnectAttempt, reconnectMaxRef.current) : undefined,
612
- }}
496
+ labels={messageLabels}
613
497
  />
614
498
 
615
499
  {/* Popovers — flex children so they stay within overflow boundary (absolute positioning would be clipped by RightAskPanel's overflow-hidden) */}
@@ -635,196 +519,158 @@ export default function AskContent({ visible, currentFile, initialMessage, initi
635
519
  </div>
636
520
  )}
637
521
 
638
- {/* Input areaauto-height composer, no manual resize */}
639
- <div
640
- className={cn(
641
- 'shrink-0 border-t border-border',
642
- isDragOver && 'ring-2 ring-[var(--amber)] ring-inset bg-[var(--amber-dim)]',
643
- )}
644
- onDragOver={handleDragOver}
645
- onDragLeave={handleDragLeave}
646
- onDrop={handleDrop}
647
- >
648
-
649
- {/* Unified context chip flow */}
650
- {(attachedFiles.length > 0 || upload.localAttachments.length > 0 || imageUpload.images.length > 0 || selectedSkill || selectedAcpAgent || upload.uploadError || imageUpload.imageError) && (
651
- <div className={cn('shrink-0 px-3 pt-2 pb-1', isPanel ? 'max-h-24 overflow-y-auto' : 'max-h-28 overflow-y-auto')}>
652
- <div className="flex flex-wrap gap-1.5">
653
- {/* KB files (@ attached) */}
654
- {attachedFiles.map(f => (
655
- <FileChip key={f} path={f} variant="kb" onRemove={() => setAttachedFiles(prev => prev.filter(x => x !== f))} />
656
- ))}
657
- {/* Uploaded files */}
658
- {upload.localAttachments.map((f, idx) => (
659
- <FileChip key={`up-${f.name}-${idx}`} path={f.name} variant="upload" onRemove={() => upload.removeAttachment(idx)} />
660
- ))}
661
- {/* Images (name chip + hover preview) */}
662
- {imageUpload.images.map((img, idx) => (
663
- <FileChip
664
- key={`img-${idx}`}
665
- path={`Image ${idx + 1}`}
666
- variant="image"
667
- imageData={img.data}
668
- imageMime={img.mimeType}
669
- onRemove={() => imageUpload.removeImage(idx)}
670
- />
671
- ))}
672
- {/* Skill */}
673
- {selectedSkill && (
674
- <FileChip
675
- path={selectedSkill.name}
676
- variant="skill"
677
- onRemove={() => { setSelectedSkill(null); inputRef.current?.focus(); }}
678
- />
522
+ {/* Composer cardunified input area with rounded container */}
523
+ <div className="shrink-0 px-3 pb-2 pt-1">
524
+ <div
525
+ className={cn(
526
+ 'rounded-xl border border-border/60 bg-card shadow-sm transition-shadow',
527
+ isDragOver && 'ring-2 ring-[var(--amber)] bg-[var(--amber-dim)]',
528
+ )}
529
+ onDragOver={handleDragOver}
530
+ onDragLeave={handleDragLeave}
531
+ onDrop={handleDrop}
532
+ >
533
+ {/* Unified context chip flow */}
534
+ {(attachedFiles.length > 0 || upload.localAttachments.length > 0 || imageUpload.images.length > 0 || selectedSkill || selectedAcpAgent || upload.uploadError || imageUpload.imageError) && (
535
+ <div className={cn('px-3 pt-2.5 pb-1', isPanel ? 'max-h-24 overflow-y-auto' : 'max-h-28 overflow-y-auto')}>
536
+ <div className="flex flex-wrap gap-1.5">
537
+ {attachedFiles.map(f => (
538
+ <FileChip key={f} path={f} variant="kb" onRemove={() => setAttachedFiles(prev => prev.filter(x => x !== f))} />
539
+ ))}
540
+ {upload.localAttachments.map((f, idx) => (
541
+ <FileChip key={`up-${f.name}-${idx}`} path={f.name} variant="upload" onRemove={() => upload.removeAttachment(idx)} />
542
+ ))}
543
+ {imageUpload.images.map((img, idx) => (
544
+ <FileChip
545
+ key={`img-${idx}`}
546
+ path={`Image ${idx + 1}`}
547
+ variant="image"
548
+ imageData={img.data}
549
+ imageMime={img.mimeType}
550
+ onRemove={() => imageUpload.removeImage(idx)}
551
+ />
552
+ ))}
553
+ {selectedSkill && (
554
+ <FileChip
555
+ path={selectedSkill.name}
556
+ variant="skill"
557
+ onRemove={() => { setSelectedSkill(null); inputRef.current?.focus(); }}
558
+ />
559
+ )}
560
+ </div>
561
+ {(upload.uploadError || imageUpload.imageError) && (
562
+ <div className="mt-1 text-xs text-error">{upload.uploadError || imageUpload.imageError}</div>
679
563
  )}
680
- {/* Agent */}
681
- {selectedAcpAgent && (
682
- <FileChip
683
- path={selectedAcpAgent.name}
684
- variant="agent"
685
- onRemove={() => { setSelectedAcpAgent(null); inputRef.current?.focus(); }}
686
- />
564
+ </div>
565
+ )}
566
+
567
+ {/* Input form */}
568
+ <form
569
+ ref={formRef}
570
+ onSubmit={handleSubmit}
571
+ className="flex items-end gap-1 px-1.5 py-1.5"
572
+ >
573
+ {/* + attach button with mini menu */}
574
+ <div className="relative shrink-0">
575
+ <button
576
+ type="button"
577
+ onClick={() => setShowAttachMenu(v => !v)}
578
+ className="p-1.5 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/60 transition-colors"
579
+ title={t.hints.attachFile}
580
+ >
581
+ <Plus size={inputIconSize} />
582
+ </button>
583
+ {showAttachMenu && (
584
+ <div className="absolute bottom-full left-0 mb-1 py-1 rounded-lg border border-border bg-card shadow-lg z-50 min-w-[140px]">
585
+ <button
586
+ type="button"
587
+ className="flex w-full items-center gap-2 px-3 py-1.5 text-xs hover:bg-muted transition-colors text-left"
588
+ onClick={() => { setShowAttachMenu(false); upload.uploadInputRef.current?.click(); }}
589
+ >
590
+ <FileText size={12} className="shrink-0 text-muted-foreground" />
591
+ {t.ask.attachFileLabel}
592
+ </button>
593
+ <button
594
+ type="button"
595
+ className="flex w-full items-center gap-2 px-3 py-1.5 text-xs hover:bg-muted transition-colors text-left"
596
+ onClick={() => { setShowAttachMenu(false); imageInputRef.current?.click(); }}
597
+ >
598
+ <ImageIcon size={12} className="shrink-0 text-muted-foreground" />
599
+ {t.ask.attachImageLabel}
600
+ </button>
601
+ </div>
687
602
  )}
688
603
  </div>
689
- {/* Errors (merged) */}
690
- {(upload.uploadError || imageUpload.imageError) && (
691
- <div className="mt-1 text-xs text-error">{upload.uploadError || imageUpload.imageError}</div>
692
- )}
693
- </div>
694
- )}
695
-
696
- {/* Agent selector — only when no agent selected but agents available (mounted guard for hydration) */}
697
- {mounted && !selectedAcpAgent && acpDetection.installedAgents.length > 0 && (
698
- <div className="px-3 pt-1 pb-0.5">
699
- <AgentSelectorCapsule
700
- selectedAgent={null}
701
- onSelect={setSelectedAcpAgent}
702
- installedAgents={acpDetection.installedAgents}
703
- loading={acpDetection.loading}
604
+
605
+ <input
606
+ ref={upload.uploadInputRef}
607
+ type="file"
608
+ className="hidden"
609
+ multiple
610
+ accept=".txt,.md,.markdown,.csv,.json,.yaml,.yml,.xml,.html,.htm,.pdf,text/plain,text/markdown,text/csv,application/json,application/pdf"
611
+ onChange={async (e) => {
612
+ const inputEl = e.currentTarget;
613
+ await upload.pickFiles(inputEl.files);
614
+ inputEl.value = '';
615
+ }}
616
+ />
617
+ <input
618
+ ref={imageInputRef}
619
+ type="file"
620
+ className="hidden"
621
+ multiple
622
+ accept="image/png,image/jpeg,image/gif,image/webp"
623
+ onChange={async (e) => {
624
+ const inputEl = e.currentTarget;
625
+ await imageUpload.handleFileSelect(inputEl.files);
626
+ inputEl.value = '';
627
+ }}
704
628
  />
705
- </div>
706
- )}
707
629
 
708
- {/* Input form */}
709
- <form
710
- ref={formRef}
711
- onSubmit={handleSubmit}
712
- className="flex items-end gap-1.5 px-3 py-2"
713
- >
714
- {/* + attach button with mini menu */}
715
- <div className="relative shrink-0">
716
- <button
717
- type="button"
718
- onClick={() => setShowAttachMenu(v => !v)}
719
- className="p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
720
- title={t.hints.attachFile}
721
- >
722
- <Plus size={inputIconSize} />
723
- </button>
724
- {showAttachMenu && (
725
- <div className="absolute bottom-full left-0 mb-1 py-1 rounded-lg border border-border bg-card shadow-lg z-50 min-w-[140px]">
726
- <button
727
- type="button"
728
- className="flex w-full items-center gap-2 px-3 py-1.5 text-xs hover:bg-muted transition-colors text-left"
729
- onClick={() => { setShowAttachMenu(false); upload.uploadInputRef.current?.click(); }}
730
- >
731
- File
732
- </button>
733
- <button
734
- type="button"
735
- className="flex w-full items-center gap-2 px-3 py-1.5 text-xs hover:bg-muted transition-colors text-left"
736
- onClick={() => { setShowAttachMenu(false); imageInputRef.current?.click(); }}
737
- >
738
- Image
739
- </button>
740
- </div>
630
+ <textarea
631
+ ref={(el) => {
632
+ inputRef.current = el;
633
+ }}
634
+ value={input}
635
+ onChange={e => handleInputChange(e.target.value, e.target.selectionStart ?? undefined)}
636
+ onKeyDown={handleInputKeyDown}
637
+ onPaste={handlePaste}
638
+ placeholder={t.ask.placeholder}
639
+ rows={1}
640
+ className="min-w-0 flex-1 resize-none overflow-y-hidden bg-transparent py-1.5 text-sm leading-snug text-foreground placeholder:text-muted-foreground outline-none focus-visible:ring-0"
641
+ />
642
+
643
+ {isLoading ? (
644
+ <button type="button" onClick={handleStop} className="p-1.5 rounded-lg transition-colors shrink-0 text-muted-foreground hover:text-foreground hover:bg-muted/60" title={loadingPhase === 'reconnecting' ? t.ask.cancelReconnect : t.ask.stopTitle}>
645
+ {loadingPhase === 'reconnecting' ? <X size={inputIconSize} /> : <StopCircle size={inputIconSize} />}
646
+ </button>
647
+ ) : (
648
+ <button type="submit" disabled={!input.trim() && imageUpload.images.length === 0} className="p-1.5 rounded-lg disabled:opacity-40 disabled:cursor-not-allowed transition-opacity shrink-0 bg-[var(--amber)] text-[var(--amber-foreground)]">
649
+ <Send size={14} />
650
+ </button>
651
+ )}
652
+ </form>
653
+
654
+ {/* Mode + Agent + Provider selector row — inside card bottom */}
655
+ <div className="flex items-center gap-1.5 px-3 pb-2 pt-0.5 border-t border-border/30">
656
+ <ModeCapsule mode={chatMode} onChange={setChatMode} disabled={isLoading} />
657
+ {mounted && acpDetection.installedAgents.length > 0 && (
658
+ <AgentSelectorCapsule
659
+ selectedAgent={selectedAcpAgent}
660
+ onSelect={setSelectedAcpAgent}
661
+ installedAgents={acpDetection.installedAgents}
662
+ loading={acpDetection.loading}
663
+ />
664
+ )}
665
+ {mounted && (
666
+ <ProviderModelCapsule
667
+ value={providerOverride}
668
+ onChange={setProviderOverride}
669
+ disabled={isLoading}
670
+ />
741
671
  )}
742
672
  </div>
743
-
744
- <input
745
- ref={upload.uploadInputRef}
746
- type="file"
747
- className="hidden"
748
- multiple
749
- accept=".txt,.md,.markdown,.csv,.json,.yaml,.yml,.xml,.html,.htm,.pdf,text/plain,text/markdown,text/csv,application/json,application/pdf"
750
- onChange={async (e) => {
751
- const inputEl = e.currentTarget;
752
- await upload.pickFiles(inputEl.files);
753
- inputEl.value = '';
754
- }}
755
- />
756
- <input
757
- ref={imageInputRef}
758
- type="file"
759
- className="hidden"
760
- multiple
761
- accept="image/png,image/jpeg,image/gif,image/webp"
762
- onChange={async (e) => {
763
- const inputEl = e.currentTarget;
764
- await imageUpload.handleFileSelect(inputEl.files);
765
- inputEl.value = '';
766
- }}
767
- />
768
-
769
- <textarea
770
- ref={(el) => {
771
- inputRef.current = el;
772
- }}
773
- value={input}
774
- onChange={e => handleInputChange(e.target.value, e.target.selectionStart ?? undefined)}
775
- onKeyDown={handleInputKeyDown}
776
- onPaste={handlePaste}
777
- placeholder={t.ask.placeholder}
778
- rows={1}
779
- className="min-w-0 flex-1 resize-none overflow-y-hidden bg-transparent py-1.5 text-sm leading-snug text-foreground placeholder:text-muted-foreground outline-none focus-visible:ring-0"
780
- />
781
-
782
- {isLoading ? (
783
- <button type="button" onClick={handleStop} className="p-1.5 rounded-md transition-colors shrink-0 text-muted-foreground hover:text-foreground hover:bg-muted" title={loadingPhase === 'reconnecting' ? t.ask.cancelReconnect : t.ask.stopTitle}>
784
- {loadingPhase === 'reconnecting' ? <X size={inputIconSize} /> : <StopCircle size={inputIconSize} />}
785
- </button>
786
- ) : (
787
- <button type="submit" disabled={!input.trim() && imageUpload.images.length === 0} className="p-1.5 rounded-md disabled:opacity-40 disabled:cursor-not-allowed transition-opacity shrink-0 bg-[var(--amber)] text-[var(--amber-foreground)]">
788
- <Send size={14} />
789
- </button>
790
- )}
791
- </form>
792
- </div>
793
-
794
- {/* Footer hints — panel: compact 3 items; modal: full set */}
795
- <div
796
- className={cn(
797
- 'flex shrink-0 items-center flex-wrap px-3 pb-1.5',
798
- isPanel
799
- ? 'gap-x-3 gap-y-1 text-[10px] text-muted-foreground/40'
800
- : 'gap-x-3 gap-y-1 text-[10px] md:text-xs text-muted-foreground/50',
801
- )}
802
- >
803
- <span suppressHydrationWarning>
804
- <kbd className="font-mono">↵</kbd> {t.ask.send}
805
- </span>
806
- {!isPanel && (
807
- <span suppressHydrationWarning>
808
- <kbd className="font-mono">⇧</kbd>
809
- <kbd className="font-mono ml-0.5">↵</kbd> {t.ask.newlineHint}
810
- </span>
811
- )}
812
- <span suppressHydrationWarning>
813
- <kbd className="font-mono">@</kbd> {t.ask.attachFile}
814
- </span>
815
- <span suppressHydrationWarning>
816
- <kbd className="font-mono">/</kbd> {t.ask.skillsHint}
817
- </span>
818
- {!isPanel && (
819
- <span suppressHydrationWarning>
820
- <kbd className="font-mono">ESC</kbd> {t.search.close}
821
- </span>
822
- )}
823
- {isLoading && input.trim() && (
824
- <span className="text-[10px] text-[var(--amber)]/80">
825
- {t.ask.draftingHint}
826
- </span>
827
- )}
673
+ </div>
828
674
  </div>
829
675
  </>
830
676
  );