@geminilight/mindos 0.6.40 → 0.6.42

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 (422) hide show
  1. package/_standalone/.mindos-build-version +1 -1
  2. package/_standalone/.next/BUILD_ID +1 -1
  3. package/_standalone/.next/app-path-routes-manifest.json +17 -16
  4. package/_standalone/.next/build-manifest.json +3 -3
  5. package/_standalone/.next/cache/.previewinfo +1 -1
  6. package/_standalone/.next/cache/.rscinfo +1 -1
  7. package/_standalone/.next/cache/config.json +3 -3
  8. package/_standalone/.next/prerender-manifest.json +3 -3
  9. package/_standalone/.next/react-loadable-manifest.json +5 -1
  10. package/_standalone/.next/routes-manifest.json +6 -0
  11. package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
  12. package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  13. package/_standalone/.next/server/app/_global-error.html +2 -2
  14. package/_standalone/.next/server/app/_global-error.rsc +1 -1
  15. package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  16. package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  17. package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  18. package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  19. package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  20. package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  21. package/_standalone/.next/server/app/_not-found/page.js +1 -1
  22. package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  23. package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  24. package/_standalone/.next/server/app/agents/[agentKey]/page.js +1 -1
  25. package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
  26. package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
  27. package/_standalone/.next/server/app/agents/page.js +2 -2
  28. package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
  29. package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
  30. package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
  31. package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
  32. package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
  33. package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
  34. package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
  35. package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
  36. package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
  37. package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
  38. package/_standalone/.next/server/app/api/acp/session/route_client-reference-manifest.js +1 -1
  39. package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
  40. package/_standalone/.next/server/app/api/ask/route.js +1 -1
  41. package/_standalone/.next/server/app/api/ask/route.js.nft.json +1 -1
  42. package/_standalone/.next/server/app/api/ask/route_client-reference-manifest.js +1 -1
  43. package/_standalone/.next/server/app/api/ask-sessions/route_client-reference-manifest.js +1 -1
  44. package/_standalone/.next/server/app/api/auth/route_client-reference-manifest.js +1 -1
  45. package/_standalone/.next/server/app/api/backlinks/route.js.nft.json +1 -1
  46. package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
  47. package/_standalone/.next/server/app/api/bootstrap/route.js.nft.json +1 -1
  48. package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
  49. package/_standalone/.next/server/app/api/changes/route.js.nft.json +1 -1
  50. package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
  51. package/_standalone/.next/server/app/api/export/route.js.nft.json +1 -1
  52. package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
  53. package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
  54. package/_standalone/.next/server/app/api/file/import/route.js.nft.json +1 -1
  55. package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
  56. package/_standalone/.next/server/app/api/file/route.js.nft.json +1 -1
  57. package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +1 -1
  58. package/_standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  59. package/_standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  60. package/_standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  61. package/_standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  62. package/_standalone/.next/server/app/api/graph/route.js.nft.json +1 -1
  63. package/_standalone/.next/server/app/api/graph/route_client-reference-manifest.js +1 -1
  64. package/_standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  65. package/_standalone/.next/server/app/api/inbox/route.js.nft.json +1 -1
  66. package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.js +1 -1
  67. package/_standalone/.next/server/app/api/init/route.js.nft.json +1 -1
  68. package/_standalone/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
  69. package/_standalone/.next/server/app/api/mcp/agents/route.js.nft.json +1 -1
  70. package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
  71. package/_standalone/.next/server/app/api/mcp/install/route.js +1 -1
  72. package/_standalone/.next/server/app/api/mcp/install/route_client-reference-manifest.js +1 -1
  73. package/_standalone/.next/server/app/api/mcp/install-skill/route.js.nft.json +1 -1
  74. package/_standalone/.next/server/app/api/mcp/install-skill/route_client-reference-manifest.js +1 -1
  75. package/_standalone/.next/server/app/api/mcp/restart/route_client-reference-manifest.js +1 -1
  76. package/_standalone/.next/server/app/api/mcp/status/route.js +1 -1
  77. package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
  78. package/_standalone/.next/server/app/api/mcp/uninstall/route.js +1 -0
  79. package/_standalone/.next/server/app/api/mcp/uninstall/route.js.nft.json +1 -0
  80. package/_standalone/.next/server/app/api/mcp/uninstall/route_client-reference-manifest.js +1 -0
  81. package/_standalone/.next/server/app/api/monitoring/route.js.nft.json +1 -1
  82. package/_standalone/.next/server/app/api/monitoring/route_client-reference-manifest.js +1 -1
  83. package/_standalone/.next/server/app/api/recent-files/route.js.nft.json +1 -1
  84. package/_standalone/.next/server/app/api/recent-files/route_client-reference-manifest.js +1 -1
  85. package/_standalone/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
  86. package/_standalone/.next/server/app/api/search/route.js.nft.json +1 -1
  87. package/_standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  88. package/_standalone/.next/server/app/api/settings/list-models/route_client-reference-manifest.js +1 -1
  89. package/_standalone/.next/server/app/api/settings/reset-token/route_client-reference-manifest.js +1 -1
  90. package/_standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  91. package/_standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
  92. package/_standalone/.next/server/app/api/settings/test-key/route_client-reference-manifest.js +1 -1
  93. package/_standalone/.next/server/app/api/setup/check-path/route_client-reference-manifest.js +1 -1
  94. package/_standalone/.next/server/app/api/setup/check-port/route_client-reference-manifest.js +1 -1
  95. package/_standalone/.next/server/app/api/setup/generate-token/route_client-reference-manifest.js +1 -1
  96. package/_standalone/.next/server/app/api/setup/ls/route_client-reference-manifest.js +1 -1
  97. package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
  98. package/_standalone/.next/server/app/api/skills/route.js +4 -4
  99. package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  100. package/_standalone/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
  101. package/_standalone/.next/server/app/api/tree-version/route.js.nft.json +1 -1
  102. package/_standalone/.next/server/app/api/tree-version/route_client-reference-manifest.js +1 -1
  103. package/_standalone/.next/server/app/api/uninstall/route_client-reference-manifest.js +1 -1
  104. package/_standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  105. package/_standalone/.next/server/app/api/update-check/route_client-reference-manifest.js +1 -1
  106. package/_standalone/.next/server/app/api/update-status/route_client-reference-manifest.js +1 -1
  107. package/_standalone/.next/server/app/api/workflows/route.js.nft.json +1 -1
  108. package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
  109. package/_standalone/.next/server/app/changes/page.js +1 -1
  110. package/_standalone/.next/server/app/changes/page.js.nft.json +1 -1
  111. package/_standalone/.next/server/app/changes/page_client-reference-manifest.js +1 -1
  112. package/_standalone/.next/server/app/echo/[segment]/page.js +1 -1
  113. package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
  114. package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
  115. package/_standalone/.next/server/app/echo/page.js +1 -1
  116. package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
  117. package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
  118. package/_standalone/.next/server/app/explore/page.js +1 -1
  119. package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
  120. package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
  121. package/_standalone/.next/server/app/help/page.js +2 -2
  122. package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
  123. package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
  124. package/_standalone/.next/server/app/login/page.js +1 -1
  125. package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
  126. package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  127. package/_standalone/.next/server/app/page.js +2 -2
  128. package/_standalone/.next/server/app/page.js.nft.json +1 -1
  129. package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  130. package/_standalone/.next/server/app/setup/page.js +2 -2
  131. package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
  132. package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  133. package/_standalone/.next/server/app/trash/page.js +3 -3
  134. package/_standalone/.next/server/app/trash/page.js.nft.json +1 -1
  135. package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
  136. package/_standalone/.next/server/app/view/[...path]/page.js +3 -3
  137. package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
  138. package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
  139. package/_standalone/.next/server/app-paths-manifest.json +17 -16
  140. package/_standalone/.next/server/chunks/1550.js +1 -1
  141. package/_standalone/.next/server/chunks/2190.js +11 -0
  142. package/_standalone/.next/server/chunks/{6365.js → 3262.js} +2 -2
  143. package/_standalone/.next/server/chunks/5648.js +2 -0
  144. package/_standalone/.next/server/chunks/6539.js +1 -1
  145. package/_standalone/.next/server/chunks/8388.js +1 -1
  146. package/_standalone/.next/server/chunks/953.js +1 -1
  147. package/_standalone/.next/server/chunks/9539.js +219 -0
  148. package/_standalone/.next/server/middleware-build-manifest.js +1 -1
  149. package/_standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  150. package/_standalone/.next/server/next-font-manifest.js +1 -1
  151. package/_standalone/.next/server/next-font-manifest.json +1 -1
  152. package/_standalone/.next/server/pages/500.html +2 -2
  153. package/_standalone/.next/server/server-reference-manifest.js +1 -1
  154. package/_standalone/.next/server/server-reference-manifest.json +1 -1
  155. package/_standalone/.next/static/GB-YReQ58tsvCuwlzrkMZ/_buildManifest.js +1 -0
  156. package/_standalone/.next/static/chunks/1053-67f0ce444d1227e2.js +29 -0
  157. package/_standalone/.next/static/chunks/{8663-de911d2d395622be.js → 1880-c2a9e76201841c86.js} +1 -1
  158. package/_standalone/.next/static/chunks/3637.0541ac2d0ea7de1f.js +1 -0
  159. package/_standalone/.next/static/chunks/4563-b2a2ce80aff845af.js +6 -0
  160. package/_standalone/.next/static/chunks/6981-3d7dcac2d12a5670.js +1 -0
  161. package/_standalone/.next/static/chunks/7144-5febf62f1a79fe64.js +1 -0
  162. package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/route-84943536516b00b2.js +1 -0
  163. package/_standalone/.next/static/chunks/app/_global-error/page-84943536516b00b2.js +1 -0
  164. package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-773071a99c4daac2.js +1 -0
  165. package/_standalone/.next/static/chunks/app/agents/page-eac6c5f6650dbf62.js +5 -0
  166. package/_standalone/.next/static/chunks/app/api/a2a/agents/route-84943536516b00b2.js +1 -0
  167. package/_standalone/.next/static/chunks/app/api/a2a/delegations/route-84943536516b00b2.js +1 -0
  168. package/_standalone/.next/static/chunks/app/api/a2a/discover/route-84943536516b00b2.js +1 -0
  169. package/_standalone/.next/static/chunks/app/api/a2a/route-84943536516b00b2.js +1 -0
  170. package/_standalone/.next/static/chunks/app/api/acp/config/route-84943536516b00b2.js +1 -0
  171. package/_standalone/.next/static/chunks/app/api/acp/detect/route-84943536516b00b2.js +1 -0
  172. package/_standalone/.next/static/chunks/app/api/acp/install/route-84943536516b00b2.js +1 -0
  173. package/_standalone/.next/static/chunks/app/api/acp/registry/route-84943536516b00b2.js +1 -0
  174. package/_standalone/.next/static/chunks/app/api/acp/session/route-84943536516b00b2.js +1 -0
  175. package/_standalone/.next/static/chunks/app/api/agent-activity/route-84943536516b00b2.js +1 -0
  176. package/_standalone/.next/static/chunks/app/api/ask/route-84943536516b00b2.js +1 -0
  177. package/_standalone/.next/static/chunks/app/api/ask-sessions/route-84943536516b00b2.js +1 -0
  178. package/_standalone/.next/static/chunks/app/api/auth/route-84943536516b00b2.js +1 -0
  179. package/_standalone/.next/static/chunks/app/api/backlinks/route-84943536516b00b2.js +1 -0
  180. package/_standalone/.next/static/chunks/app/api/bootstrap/route-84943536516b00b2.js +1 -0
  181. package/_standalone/.next/static/chunks/app/api/changes/route-84943536516b00b2.js +1 -0
  182. package/_standalone/.next/static/chunks/app/api/export/route-84943536516b00b2.js +1 -0
  183. package/_standalone/.next/static/chunks/app/api/extract-pdf/route-84943536516b00b2.js +1 -0
  184. package/_standalone/.next/static/chunks/app/api/file/import/route-84943536516b00b2.js +1 -0
  185. package/_standalone/.next/static/chunks/app/api/file/route-84943536516b00b2.js +1 -0
  186. package/_standalone/.next/static/chunks/app/api/files/route-84943536516b00b2.js +1 -0
  187. package/_standalone/.next/static/chunks/app/api/git/route-84943536516b00b2.js +1 -0
  188. package/_standalone/.next/static/chunks/app/api/graph/route-84943536516b00b2.js +1 -0
  189. package/_standalone/.next/static/chunks/app/api/health/route-84943536516b00b2.js +1 -0
  190. package/_standalone/.next/static/chunks/app/api/inbox/route-84943536516b00b2.js +1 -0
  191. package/_standalone/.next/static/chunks/app/api/init/route-84943536516b00b2.js +1 -0
  192. package/_standalone/.next/static/chunks/app/api/mcp/agents/route-84943536516b00b2.js +1 -0
  193. package/_standalone/.next/static/chunks/app/api/mcp/install/route-84943536516b00b2.js +1 -0
  194. package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-84943536516b00b2.js +1 -0
  195. package/_standalone/.next/static/chunks/app/api/mcp/restart/route-84943536516b00b2.js +1 -0
  196. package/_standalone/.next/static/chunks/app/api/mcp/status/route-84943536516b00b2.js +1 -0
  197. package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-84943536516b00b2.js +1 -0
  198. package/_standalone/.next/static/chunks/app/api/monitoring/route-84943536516b00b2.js +1 -0
  199. package/_standalone/.next/static/chunks/app/api/recent-files/route-84943536516b00b2.js +1 -0
  200. package/_standalone/.next/static/chunks/app/api/restart/route-84943536516b00b2.js +1 -0
  201. package/_standalone/.next/static/chunks/app/api/search/route-84943536516b00b2.js +1 -0
  202. package/_standalone/.next/static/chunks/app/api/settings/list-models/route-84943536516b00b2.js +1 -0
  203. package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-84943536516b00b2.js +1 -0
  204. package/_standalone/.next/static/chunks/app/api/settings/route-84943536516b00b2.js +1 -0
  205. package/_standalone/.next/static/chunks/app/api/settings/test-key/route-84943536516b00b2.js +1 -0
  206. package/_standalone/.next/static/chunks/app/api/setup/check-path/route-84943536516b00b2.js +1 -0
  207. package/_standalone/.next/static/chunks/app/api/setup/check-port/route-84943536516b00b2.js +1 -0
  208. package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-84943536516b00b2.js +1 -0
  209. package/_standalone/.next/static/chunks/app/api/setup/ls/route-84943536516b00b2.js +1 -0
  210. package/_standalone/.next/static/chunks/app/api/setup/route-84943536516b00b2.js +1 -0
  211. package/_standalone/.next/static/chunks/app/api/skills/route-84943536516b00b2.js +1 -0
  212. package/_standalone/.next/static/chunks/app/api/sync/route-84943536516b00b2.js +1 -0
  213. package/_standalone/.next/static/chunks/app/api/tree-version/route-84943536516b00b2.js +1 -0
  214. package/_standalone/.next/static/chunks/app/api/uninstall/route-84943536516b00b2.js +1 -0
  215. package/_standalone/.next/static/chunks/app/api/update/route-84943536516b00b2.js +1 -0
  216. package/_standalone/.next/static/chunks/app/api/update-check/route-84943536516b00b2.js +1 -0
  217. package/_standalone/.next/static/chunks/app/api/update-status/route-84943536516b00b2.js +1 -0
  218. package/_standalone/.next/static/chunks/app/api/workflows/route-84943536516b00b2.js +1 -0
  219. package/_standalone/.next/static/chunks/app/echo/page-84943536516b00b2.js +1 -0
  220. package/_standalone/.next/static/chunks/app/help/page-2325d25b6846ca07.js +1 -0
  221. package/_standalone/.next/static/chunks/app/{layout-9378c1c8d3e5761b.js → layout-7cb442df92212140.js} +55 -55
  222. package/_standalone/.next/static/chunks/app/{page-9bae420fbbdc5fff.js → page-aaee2d9bd3d3eabb.js} +1 -1
  223. package/_standalone/.next/static/chunks/app/setup/page-6132ea7632e08a9b.js +1 -0
  224. package/_standalone/.next/static/chunks/app/trash/{page-b61ef2d5cd4f8d73.js → page-7b5cbf541c315db2.js} +1 -1
  225. package/_standalone/.next/static/chunks/app/view/[...path]/loading-84943536516b00b2.js +1 -0
  226. package/_standalone/.next/static/chunks/app/view/[...path]/page-b72e4f88c8c48181.js +12 -0
  227. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-84943536516b00b2.js +1 -0
  228. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-84943536516b00b2.js +1 -0
  229. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-84943536516b00b2.js +1 -0
  230. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-84943536516b00b2.js +1 -0
  231. package/_standalone/.next/static/chunks/{webpack-c28c55d0a6021a6b.js → webpack-7b276daaa930d480.js} +1 -1
  232. package/_standalone/.next/static/css/bc9179074eaf65ae.css +1 -0
  233. package/_standalone/.next/trace +63 -63
  234. package/_standalone/.next/types/routes.d.ts +2 -1
  235. package/_standalone/.next/types/validator.ts +9 -0
  236. package/_standalone/__tests__/api/mcp-install.test.ts +23 -0
  237. package/_standalone/__tests__/cli/agent-routing.test.ts +232 -0
  238. package/_standalone/__tests__/cli/file-subcommands.test.ts +379 -0
  239. package/_standalone/__tests__/core/tools.test.ts +3 -6
  240. package/_standalone/components/FileTree.tsx +3 -2
  241. package/_standalone/components/MarkdownView.tsx +30 -15
  242. package/_standalone/components/RightAskPanel.tsx +36 -6
  243. package/_standalone/components/Sidebar.tsx +3 -3
  244. package/_standalone/components/agents/AgentsMcpSection.tsx +27 -5
  245. package/_standalone/components/settings/McpAgentInstall.tsx +94 -27
  246. package/_standalone/components/settings/McpSkillsSection.tsx +1 -1
  247. package/_standalone/components/settings/McpTab.tsx +484 -340
  248. package/_standalone/components/settings/SettingsContent.tsx +12 -6
  249. package/_standalone/components/settings/types.ts +3 -0
  250. package/_standalone/components/setup/StepAgents.tsx +113 -47
  251. package/_standalone/components/setup/StepReview.tsx +14 -27
  252. package/_standalone/components/setup/types.ts +7 -0
  253. package/_standalone/data/skills/mindos/SKILL.md +92 -92
  254. package/_standalone/data/skills/mindos/references/write-supplement.md +119 -0
  255. package/_standalone/data/skills/mindos-zh/SKILL.md +100 -104
  256. package/_standalone/data/skills/mindos-zh/references/write-supplement.md +119 -0
  257. package/_standalone/lib/i18n/modules/features.ts +4 -4
  258. package/_standalone/lib/i18n/modules/knowledge.ts +4 -0
  259. package/_standalone/lib/i18n/modules/onboarding.ts +40 -30
  260. package/_standalone/lib/i18n/modules/panels.ts +6 -2
  261. package/_standalone/lib/i18n/modules/settings.ts +78 -6
  262. package/_standalone/lib/mcp-snippets.ts +5 -1
  263. package/_standalone/tsconfig.tsbuildinfo +1 -1
  264. package/app/app/api/ask/route.ts +3 -2
  265. package/app/app/api/mcp/install/route.ts +15 -3
  266. package/app/app/api/mcp/status/route.ts +14 -6
  267. package/app/app/api/mcp/uninstall/route.ts +130 -0
  268. package/app/app/api/skills/route.ts +14 -1
  269. package/app/app/view/[...path]/ViewPageClient.tsx +12 -27
  270. package/app/components/FileTree.tsx +3 -2
  271. package/app/components/MarkdownView.tsx +30 -15
  272. package/app/components/RightAskPanel.tsx +36 -6
  273. package/app/components/Sidebar.tsx +3 -3
  274. package/app/components/agents/AgentsMcpSection.tsx +27 -5
  275. package/app/components/help/HelpContent.tsx +1 -0
  276. package/app/components/settings/McpAgentInstall.tsx +94 -27
  277. package/app/components/settings/McpSkillsSection.tsx +1 -1
  278. package/app/components/settings/McpTab.tsx +484 -340
  279. package/app/components/settings/SettingsContent.tsx +12 -6
  280. package/app/components/settings/types.ts +3 -0
  281. package/app/components/setup/StepAgents.tsx +113 -47
  282. package/app/components/setup/StepReview.tsx +14 -27
  283. package/app/components/setup/index.tsx +16 -14
  284. package/app/components/setup/types.ts +7 -0
  285. package/app/data/skills/mindos/SKILL.md +92 -92
  286. package/app/data/skills/mindos/references/write-supplement.md +119 -0
  287. package/app/data/skills/mindos-zh/SKILL.md +100 -104
  288. package/app/data/skills/mindos-zh/references/write-supplement.md +119 -0
  289. package/app/lib/fs.ts +0 -6
  290. package/app/lib/i18n/modules/features.ts +4 -4
  291. package/app/lib/i18n/modules/knowledge.ts +4 -0
  292. package/app/lib/i18n/modules/onboarding.ts +40 -30
  293. package/app/lib/i18n/modules/panels.ts +6 -2
  294. package/app/lib/i18n/modules/settings.ts +78 -6
  295. package/app/lib/mcp-agents.ts +1 -2
  296. package/app/lib/mcp-snippets.ts +5 -1
  297. package/app/lib/renderers/index.ts +2 -1
  298. package/app/lib/settings.ts +32 -0
  299. package/bin/cli.js +168 -1404
  300. package/bin/commands/agent.js +156 -20
  301. package/bin/commands/api.js +14 -11
  302. package/bin/commands/ask.js +79 -68
  303. package/bin/commands/build.js +26 -0
  304. package/bin/commands/config.js +170 -0
  305. package/bin/commands/dev.js +58 -0
  306. package/bin/commands/doctor.js +205 -0
  307. package/bin/commands/file.js +551 -36
  308. package/bin/commands/gateway.js +42 -0
  309. package/bin/commands/init-skills.js +56 -0
  310. package/bin/commands/logs.js +32 -0
  311. package/bin/commands/mcp-cmd.js +57 -0
  312. package/bin/commands/onboard.js +25 -0
  313. package/bin/commands/open.js +41 -0
  314. package/bin/commands/restart.js +48 -0
  315. package/bin/commands/search.js +16 -14
  316. package/bin/commands/space.js +96 -25
  317. package/bin/commands/start.js +272 -0
  318. package/bin/commands/status.js +2 -2
  319. package/bin/commands/stop.js +14 -0
  320. package/bin/commands/sync-cmd.js +134 -0
  321. package/bin/commands/token.js +98 -0
  322. package/bin/commands/uninstall.js +154 -0
  323. package/bin/commands/update.js +286 -0
  324. package/bin/lib/build.js +1 -1
  325. package/bin/lib/colors.js +8 -7
  326. package/bin/lib/command.js +37 -96
  327. package/bin/lib/config.js +5 -0
  328. package/bin/lib/csv.js +19 -0
  329. package/bin/lib/jsonc.js +12 -0
  330. package/bin/lib/markdown.js +69 -0
  331. package/bin/lib/mcp-agents.js +1 -6
  332. package/bin/lib/mcp-build.js +1 -1
  333. package/bin/lib/mcp-install.js +2 -1
  334. package/bin/lib/one-shot.js +88 -0
  335. package/bin/lib/path-expand.js +9 -0
  336. package/bin/lib/remote.js +65 -0
  337. package/bin/lib/repl.js +167 -0
  338. package/bin/lib/{utils.js → shell.js} +10 -26
  339. package/bin/lib/skill-check.js +116 -21
  340. package/bin/lib/sse-stream.js +167 -0
  341. package/package.json +2 -2
  342. package/scripts/setup.js +210 -120
  343. package/skills/mindos/SKILL.md +94 -95
  344. package/skills/mindos-zh/SKILL.md +103 -106
  345. package/_standalone/.next/server/chunks/1955.js +0 -11
  346. package/_standalone/.next/server/chunks/3680.js +0 -1
  347. package/_standalone/.next/server/chunks/4497.js +0 -219
  348. package/_standalone/.next/server/chunks/5560.js +0 -2
  349. package/_standalone/.next/static/chunks/1053-0adaccc98a752a58.js +0 -29
  350. package/_standalone/.next/static/chunks/3637.f9a42cca59fd5bb5.js +0 -1
  351. package/_standalone/.next/static/chunks/4563-c2afaeacb241d1d0.js +0 -6
  352. package/_standalone/.next/static/chunks/6090-c98268ca726a68d3.js +0 -1
  353. package/_standalone/.next/static/chunks/9371-575600301da5d6bb.js +0 -1
  354. package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/route-400c3c09b1540c14.js +0 -1
  355. package/_standalone/.next/static/chunks/app/_global-error/page-400c3c09b1540c14.js +0 -1
  356. package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-3e08abb495ecd5fd.js +0 -1
  357. package/_standalone/.next/static/chunks/app/agents/page-e7e0f87ad3d765ac.js +0 -5
  358. package/_standalone/.next/static/chunks/app/api/a2a/agents/route-400c3c09b1540c14.js +0 -1
  359. package/_standalone/.next/static/chunks/app/api/a2a/delegations/route-400c3c09b1540c14.js +0 -1
  360. package/_standalone/.next/static/chunks/app/api/a2a/discover/route-400c3c09b1540c14.js +0 -1
  361. package/_standalone/.next/static/chunks/app/api/a2a/route-400c3c09b1540c14.js +0 -1
  362. package/_standalone/.next/static/chunks/app/api/acp/config/route-400c3c09b1540c14.js +0 -1
  363. package/_standalone/.next/static/chunks/app/api/acp/detect/route-400c3c09b1540c14.js +0 -1
  364. package/_standalone/.next/static/chunks/app/api/acp/install/route-400c3c09b1540c14.js +0 -1
  365. package/_standalone/.next/static/chunks/app/api/acp/registry/route-400c3c09b1540c14.js +0 -1
  366. package/_standalone/.next/static/chunks/app/api/acp/session/route-400c3c09b1540c14.js +0 -1
  367. package/_standalone/.next/static/chunks/app/api/agent-activity/route-400c3c09b1540c14.js +0 -1
  368. package/_standalone/.next/static/chunks/app/api/ask/route-400c3c09b1540c14.js +0 -1
  369. package/_standalone/.next/static/chunks/app/api/ask-sessions/route-400c3c09b1540c14.js +0 -1
  370. package/_standalone/.next/static/chunks/app/api/auth/route-400c3c09b1540c14.js +0 -1
  371. package/_standalone/.next/static/chunks/app/api/backlinks/route-400c3c09b1540c14.js +0 -1
  372. package/_standalone/.next/static/chunks/app/api/bootstrap/route-400c3c09b1540c14.js +0 -1
  373. package/_standalone/.next/static/chunks/app/api/changes/route-400c3c09b1540c14.js +0 -1
  374. package/_standalone/.next/static/chunks/app/api/export/route-400c3c09b1540c14.js +0 -1
  375. package/_standalone/.next/static/chunks/app/api/extract-pdf/route-400c3c09b1540c14.js +0 -1
  376. package/_standalone/.next/static/chunks/app/api/file/import/route-400c3c09b1540c14.js +0 -1
  377. package/_standalone/.next/static/chunks/app/api/file/route-400c3c09b1540c14.js +0 -1
  378. package/_standalone/.next/static/chunks/app/api/files/route-400c3c09b1540c14.js +0 -1
  379. package/_standalone/.next/static/chunks/app/api/git/route-400c3c09b1540c14.js +0 -1
  380. package/_standalone/.next/static/chunks/app/api/graph/route-400c3c09b1540c14.js +0 -1
  381. package/_standalone/.next/static/chunks/app/api/health/route-400c3c09b1540c14.js +0 -1
  382. package/_standalone/.next/static/chunks/app/api/inbox/route-400c3c09b1540c14.js +0 -1
  383. package/_standalone/.next/static/chunks/app/api/init/route-400c3c09b1540c14.js +0 -1
  384. package/_standalone/.next/static/chunks/app/api/mcp/agents/route-400c3c09b1540c14.js +0 -1
  385. package/_standalone/.next/static/chunks/app/api/mcp/install/route-400c3c09b1540c14.js +0 -1
  386. package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-400c3c09b1540c14.js +0 -1
  387. package/_standalone/.next/static/chunks/app/api/mcp/restart/route-400c3c09b1540c14.js +0 -1
  388. package/_standalone/.next/static/chunks/app/api/mcp/status/route-400c3c09b1540c14.js +0 -1
  389. package/_standalone/.next/static/chunks/app/api/monitoring/route-400c3c09b1540c14.js +0 -1
  390. package/_standalone/.next/static/chunks/app/api/recent-files/route-400c3c09b1540c14.js +0 -1
  391. package/_standalone/.next/static/chunks/app/api/restart/route-400c3c09b1540c14.js +0 -1
  392. package/_standalone/.next/static/chunks/app/api/search/route-400c3c09b1540c14.js +0 -1
  393. package/_standalone/.next/static/chunks/app/api/settings/list-models/route-400c3c09b1540c14.js +0 -1
  394. package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-400c3c09b1540c14.js +0 -1
  395. package/_standalone/.next/static/chunks/app/api/settings/route-400c3c09b1540c14.js +0 -1
  396. package/_standalone/.next/static/chunks/app/api/settings/test-key/route-400c3c09b1540c14.js +0 -1
  397. package/_standalone/.next/static/chunks/app/api/setup/check-path/route-400c3c09b1540c14.js +0 -1
  398. package/_standalone/.next/static/chunks/app/api/setup/check-port/route-400c3c09b1540c14.js +0 -1
  399. package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-400c3c09b1540c14.js +0 -1
  400. package/_standalone/.next/static/chunks/app/api/setup/ls/route-400c3c09b1540c14.js +0 -1
  401. package/_standalone/.next/static/chunks/app/api/setup/route-400c3c09b1540c14.js +0 -1
  402. package/_standalone/.next/static/chunks/app/api/skills/route-400c3c09b1540c14.js +0 -1
  403. package/_standalone/.next/static/chunks/app/api/sync/route-400c3c09b1540c14.js +0 -1
  404. package/_standalone/.next/static/chunks/app/api/tree-version/route-400c3c09b1540c14.js +0 -1
  405. package/_standalone/.next/static/chunks/app/api/uninstall/route-400c3c09b1540c14.js +0 -1
  406. package/_standalone/.next/static/chunks/app/api/update/route-400c3c09b1540c14.js +0 -1
  407. package/_standalone/.next/static/chunks/app/api/update-check/route-400c3c09b1540c14.js +0 -1
  408. package/_standalone/.next/static/chunks/app/api/update-status/route-400c3c09b1540c14.js +0 -1
  409. package/_standalone/.next/static/chunks/app/api/workflows/route-400c3c09b1540c14.js +0 -1
  410. package/_standalone/.next/static/chunks/app/echo/page-400c3c09b1540c14.js +0 -1
  411. package/_standalone/.next/static/chunks/app/help/page-3d0e1ceaa4abc243.js +0 -1
  412. package/_standalone/.next/static/chunks/app/setup/page-99ed3d1bb6b8f4ef.js +0 -1
  413. package/_standalone/.next/static/chunks/app/view/[...path]/loading-400c3c09b1540c14.js +0 -1
  414. package/_standalone/.next/static/chunks/app/view/[...path]/page-44fa78cbea613a78.js +0 -12
  415. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-400c3c09b1540c14.js +0 -1
  416. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-400c3c09b1540c14.js +0 -1
  417. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-400c3c09b1540c14.js +0 -1
  418. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-400c3c09b1540c14.js +0 -1
  419. package/_standalone/.next/static/css/d300701f384db50d.css +0 -1
  420. package/_standalone/.next/static/rZLs1krFuduixvcVNe6q3/_buildManifest.js +0 -1
  421. package/_standalone/components/renderers/agent-inspector/manifest.ts +0 -16
  422. /package/_standalone/.next/static/{rZLs1krFuduixvcVNe6q3 → GB-YReQ58tsvCuwlzrkMZ}/_ssgManifest.js +0 -0
@@ -13,6 +13,7 @@ import {
13
13
  type ToolDefinition,
14
14
  SessionManager,
15
15
  SettingsManager,
16
+ bashTool,
16
17
  } from '@mariozechner/pi-coding-agent';
17
18
  import { NextRequest, NextResponse } from 'next/server';
18
19
  import fs from 'fs';
@@ -316,7 +317,7 @@ function toPiCustomToolDefinitions(tools: AgentTool<any>[]): ToolDefinition<any,
316
317
  params: args,
317
318
  result: outputText.startsWith('Error:') ? 'error' : 'ok',
318
319
  message: outputText.slice(0, 200),
319
- agentName: 'MindOS Ask',
320
+ agentName: 'MindOS',
320
321
  });
321
322
  } catch {
322
323
  // logging must never kill the stream
@@ -669,7 +670,7 @@ export async function POST(req: NextRequest) {
669
670
  resourceLoader,
670
671
  sessionManager: SessionManager.inMemory(),
671
672
  settingsManager,
672
- tools: [],
673
+ tools: askMode === 'agent' ? [bashTool] : [],
673
674
  customTools,
674
675
  });
675
676
 
@@ -2,13 +2,14 @@ export const dynamic = 'force-dynamic';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
- import { MCP_AGENTS, expandHome } from '@/lib/mcp-agents';
6
- import { readSettings } from '@/lib/settings';
5
+ import { MCP_AGENTS, expandHome, resolveSkillWorkspaceProfile } from '@/lib/mcp-agents';
6
+ import { readSettings, recordSkillInstall } from '@/lib/settings';
7
7
 
8
- /** Parse JSONC — strips single-line (//) and block comments before JSON.parse */
8
+ /** Parse JSONC — strips comments before JSON.parse. Returns {} for empty/whitespace-only input. */
9
9
  function parseJsonc(text: string): Record<string, unknown> {
10
10
  let stripped = text.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*$)/gm, (m, g) => g ? '' : m);
11
11
  stripped = stripped.replace(/\/\*[\s\S]*?\*\//g, '');
12
+ if (!stripped.trim()) return {};
12
13
  return JSON.parse(stripped);
13
14
  }
14
15
 
@@ -203,6 +204,17 @@ export async function POST(req: NextRequest) {
203
204
 
204
205
  const result: typeof results[number] = { agent: key, status: 'ok', path: configPath, transport: effectiveTransport };
205
206
 
207
+ // Record skill install path for auto-update on future version bumps
208
+ try {
209
+ const skillProfile = resolveSkillWorkspaceProfile(key);
210
+ const settings = readSettings();
211
+ const activeSkill = settings.disabledSkills?.includes('mindos') ? 'mindos-zh' : 'mindos';
212
+ const skillPath = path.join(skillProfile.workspacePath, activeSkill, 'SKILL.md');
213
+ if (fs.existsSync(skillPath)) {
214
+ recordSkillInstall(key, activeSkill, skillPath);
215
+ }
216
+ } catch { /* best-effort, don't fail the install */ }
217
+
206
218
  // Verify http connections
207
219
  if (effectiveTransport === 'http') {
208
220
  const mcpUrl = (entry as Record<string, unknown>).url as string;
@@ -2,18 +2,29 @@ export const dynamic = 'force-dynamic';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
  import { readSettings } from '@/lib/settings';
4
4
  import { maskToken } from '@/lib/format';
5
+ import { networkInterfaces } from 'os';
5
6
 
6
7
  /** Parse hostname from Host header, handling IPv6 brackets */
7
8
  function parseHostname(host: string): string {
8
- // IPv6: [::1]:3003 → [::1]
9
9
  if (host.includes(']')) {
10
10
  return host.slice(0, host.lastIndexOf(']') + 1);
11
11
  }
12
- // IPv4/hostname: 192.168.1.1:3003 → 192.168.1.1
13
12
  const colonIdx = host.lastIndexOf(':');
14
13
  return colonIdx > 0 ? host.slice(0, colonIdx) : host;
15
14
  }
16
15
 
16
+ /** Get first non-internal IPv4 address */
17
+ function getLocalIP(): string | null {
18
+ try {
19
+ for (const ifaces of Object.values(networkInterfaces())) {
20
+ for (const iface of ifaces ?? []) {
21
+ if (iface.family === 'IPv4' && !iface.internal) return iface.address;
22
+ }
23
+ }
24
+ } catch { /* ignore */ }
25
+ return null;
26
+ }
27
+
17
28
  export async function GET(req: NextRequest) {
18
29
  try {
19
30
  const settings = readSettings();
@@ -52,12 +63,9 @@ export async function GET(req: NextRequest) {
52
63
  port,
53
64
  toolCount: running ? 24 : 0,
54
65
  authConfigured,
55
- // Masked for display; full token only used server-side in snippet generation
56
66
  maskedToken: authConfigured ? maskToken(token) : undefined,
57
- // Full token for config snippet copy — this API is protected by proxy.ts middleware
58
- // (same-origin or bearer token required). Consistent with /api/settings which also
59
- // exposes the token to authenticated users.
60
67
  authToken: authConfigured ? token : undefined,
68
+ localIP: getLocalIP(),
61
69
  });
62
70
  } catch (err) {
63
71
  return NextResponse.json({ error: String(err) }, { status: 500 });
@@ -0,0 +1,130 @@
1
+ export const dynamic = 'force-dynamic';
2
+ import { NextRequest, NextResponse } from 'next/server';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { MCP_AGENTS, expandHome } from '@/lib/mcp-agents';
6
+
7
+ /** Parse JSONC — strips comments before JSON.parse. Returns {} for empty/whitespace-only input. */
8
+ function parseJsonc(text: string): Record<string, unknown> {
9
+ let stripped = text.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*$)/gm, (m, g) => g ? '' : m);
10
+ stripped = stripped.replace(/\/\*[\s\S]*?\*\//g, '');
11
+ if (!stripped.trim()) return {};
12
+ return JSON.parse(stripped);
13
+ }
14
+
15
+ /** Navigate a dot-path (e.g. "mcp.servers") and return the leaf container, or null. */
16
+ function getNestedPath(obj: Record<string, unknown>, dotPath: string): Record<string, unknown> | null {
17
+ const parts = dotPath.split('.').filter(Boolean);
18
+ let current: unknown = obj;
19
+ for (const part of parts) {
20
+ if (!current || typeof current !== 'object') return null;
21
+ current = (current as Record<string, unknown>)[part];
22
+ }
23
+ return (current && typeof current === 'object') ? current as Record<string, unknown> : null;
24
+ }
25
+
26
+ /** Remove a [section.server] block from a TOML file */
27
+ function removeTomlEntry(existing: string, sectionKey: string, serverName: string): string {
28
+ const sectionHeader = `[${sectionKey}.${serverName}]`;
29
+ const envHeader = `[${sectionKey}.${serverName}.env]`;
30
+ const headersHeader = `[${sectionKey}.${serverName}.headers]`;
31
+
32
+ const lines = existing.split('\n');
33
+ const result: string[] = [];
34
+ let skipping = false;
35
+
36
+ for (const line of lines) {
37
+ const trimmed = line.trim();
38
+ if (trimmed === sectionHeader || trimmed === envHeader || trimmed === headersHeader) {
39
+ skipping = true;
40
+ continue;
41
+ }
42
+ if (skipping && trimmed.startsWith('[')) {
43
+ skipping = false;
44
+ }
45
+ if (!skipping) {
46
+ result.push(line);
47
+ }
48
+ }
49
+
50
+ // Clean up consecutive blank lines
51
+ const cleaned: string[] = [];
52
+ for (const line of result) {
53
+ if (line.trim() === '' && cleaned.length > 0 && cleaned[cleaned.length - 1].trim() === '') continue;
54
+ cleaned.push(line);
55
+ }
56
+
57
+ return cleaned.join('\n');
58
+ }
59
+
60
+ interface UninstallRequest {
61
+ agents: Array<{
62
+ key: string;
63
+ scope: 'project' | 'global';
64
+ }>;
65
+ }
66
+
67
+ export async function POST(req: NextRequest) {
68
+ try {
69
+ const body = (await req.json()) as UninstallRequest;
70
+ const { agents } = body;
71
+ const results: Array<{
72
+ agent: string;
73
+ status: string;
74
+ path?: string;
75
+ message?: string;
76
+ }> = [];
77
+
78
+ for (const item of agents) {
79
+ const { key, scope } = item;
80
+ const agent = MCP_AGENTS[key];
81
+ if (!agent) {
82
+ results.push({ agent: key, status: 'error', message: `Unknown agent: ${key}` });
83
+ continue;
84
+ }
85
+
86
+ const isGlobal = scope === 'global';
87
+ const configPath = isGlobal ? agent.global : agent.project;
88
+ if (!configPath) {
89
+ results.push({ agent: key, status: 'error', message: `${agent.name} does not support ${scope} scope` });
90
+ continue;
91
+ }
92
+
93
+ const absPath = expandHome(configPath);
94
+
95
+ if (!fs.existsSync(absPath)) {
96
+ results.push({ agent: key, status: 'ok', message: 'Config file does not exist' });
97
+ continue;
98
+ }
99
+
100
+ try {
101
+ if (agent.format === 'toml') {
102
+ const existing = fs.readFileSync(absPath, 'utf-8');
103
+ const updated = removeTomlEntry(existing, agent.key, 'mindos');
104
+ fs.writeFileSync(absPath, updated, 'utf-8');
105
+ } else {
106
+ const config = parseJsonc(fs.readFileSync(absPath, 'utf-8'));
107
+
108
+ // Handle nested keys (e.g. VS Code: mcp.servers)
109
+ const useNestedKey = isGlobal && agent.globalNestedKey;
110
+ const container = useNestedKey
111
+ ? getNestedPath(config, agent.globalNestedKey!)
112
+ : (config[agent.key] as Record<string, unknown> | undefined);
113
+
114
+ if (container && 'mindos' in container) {
115
+ delete container.mindos;
116
+ fs.writeFileSync(absPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
117
+ }
118
+ }
119
+
120
+ results.push({ agent: key, status: 'ok', path: configPath });
121
+ } catch (err) {
122
+ results.push({ agent: key, status: 'error', message: String(err) });
123
+ }
124
+ }
125
+
126
+ return NextResponse.json({ results });
127
+ } catch (err) {
128
+ return NextResponse.json({ error: String(err) }, { status: 500 });
129
+ }
130
+ }
@@ -32,7 +32,7 @@ export async function POST(req: NextRequest) {
32
32
  try {
33
33
  const body = await req.json();
34
34
  const { action, name, description, content, enabled, sourcePath } = body as {
35
- action: 'create' | 'update' | 'delete' | 'toggle' | 'read' | 'read-native';
35
+ action: 'create' | 'update' | 'delete' | 'toggle' | 'read' | 'read-native' | 'record-install';
36
36
  name?: string;
37
37
  description?: string;
38
38
  content?: string;
@@ -130,6 +130,19 @@ export async function POST(req: NextRequest) {
130
130
  return NextResponse.json({ content: nativeContent, description: nativeDesc });
131
131
  }
132
132
 
133
+ case 'record-install': {
134
+ // Record that a skill was installed to a specific agent (for auto-update tracking)
135
+ const agentKey = (body as { agentKey?: string }).agentKey;
136
+ const skillName = name;
137
+ const installPath = (body as { installPath?: string }).installPath;
138
+ if (!agentKey || !skillName || !installPath) {
139
+ return NextResponse.json({ error: 'agentKey, name, and installPath are required' }, { status: 400 });
140
+ }
141
+ const { recordSkillInstall } = await import('@/lib/settings');
142
+ recordSkillInstall(agentKey, skillName, installPath);
143
+ return NextResponse.json({ ok: true });
144
+ }
145
+
133
146
  default:
134
147
  return NextResponse.json({ error: `Unknown action: ${action}` }, { status: 400 });
135
148
  }
@@ -58,8 +58,8 @@ export default function ViewPageClient({
58
58
  );
59
59
 
60
60
  const [useRaw, setUseRaw] = useRendererState<boolean>('_raw', filePath, false);
61
- // Global graph mode — shared across all md files (not per-file)
62
- const [graphMode, setGraphMode] = useRendererState<boolean>('_graphMode', '_global', false);
61
+ // Graph mode — per-view, resets when navigating to a different file
62
+ const [graphMode, setGraphMode] = useState(false);
63
63
  const router = useRouter();
64
64
  const [editing, setEditing] = useState(initialEditing || content === '');
65
65
  const [editContent, setEditContent] = useState(content);
@@ -167,7 +167,7 @@ export default function ViewPageClient({
167
167
  setGraphMode(prev => !prev);
168
168
  }, [setGraphMode]);
169
169
 
170
- const effectiveGraphMode = hydrated ? graphMode : false;
170
+ const effectiveGraphMode = graphMode;
171
171
 
172
172
  // Resolve renderer: for md files, graph mode overrides normal resolution
173
173
  const registryRenderer = resolveRenderer(filePath, extension);
@@ -383,22 +383,6 @@ export default function ViewPageClient({
383
383
  <span className="text-xs text-error hidden sm:inline">{saveError}</span>
384
384
  )}
385
385
 
386
- {/* Graph toggle — only for md files, hidden when graph plugin is disabled */}
387
- {extension === 'md' && !editing && !isDraft && isRendererEnabled('graph') && (
388
- <button
389
- onClick={handleToggleGraph}
390
- className="flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-colors font-display"
391
- style={{
392
- background: effectiveGraphMode ? `${'var(--amber)'}22` : 'var(--muted)',
393
- color: effectiveGraphMode ? 'var(--amber)' : 'var(--muted-foreground)',
394
- }}
395
- title={effectiveGraphMode ? 'Switch to document view' : 'Switch to Wiki Graph'}
396
- >
397
- {effectiveGraphMode ? <FileText size={13} /> : <Share2 size={13} />}
398
- <span className="hidden sm:inline">{effectiveGraphMode ? 'Doc' : 'Graph'}</span>
399
- </button>
400
- )}
401
-
402
386
  {/* Renderer toggle — only shown when a custom renderer exists (excludes graph-mode override) */}
403
387
  {registryRenderer && !editing && !isDraft && !graphRenderer && (
404
388
  <button
@@ -463,14 +447,6 @@ export default function ViewPageClient({
463
447
  >
464
448
  <Star size={16} className={pinned ? 'fill-[var(--amber)] text-[var(--amber)]' : ''} />
465
449
  </button>
466
- <button
467
- type="button"
468
- onClick={() => setExportOpen(true)}
469
- className="p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
470
- title={t.fileTree.export}
471
- >
472
- <Download size={16} />
473
- </button>
474
450
  <button
475
451
  ref={moreRef}
476
452
  type="button"
@@ -485,6 +461,15 @@ export default function ViewPageClient({
485
461
  ref={moreMenuRef}
486
462
  className="absolute right-0 top-full mt-1 z-50 min-w-[160px] rounded-lg border border-border bg-card shadow-lg py-1"
487
463
  >
464
+ {extension === 'md' && !editing && !isDraft && isRendererEnabled('graph') && (
465
+ <button className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-muted transition-colors text-left" onClick={() => { setMoreOpen(false); handleToggleGraph(); }}>
466
+ {effectiveGraphMode ? <FileText size={14} className="shrink-0" /> : <Share2 size={14} className="shrink-0" />}
467
+ {effectiveGraphMode ? (t.view?.switchToDoc ?? 'Document view') : (t.view?.switchToGraph ?? 'Wiki Graph')}
468
+ </button>
469
+ )}
470
+ <button className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-muted transition-colors text-left" onClick={() => { setMoreOpen(false); setExportOpen(true); }}>
471
+ <Download size={14} className="shrink-0" /> {t.fileTree?.export ?? 'Export'}
472
+ </button>
488
473
  <button className="w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-muted transition-colors text-left" onClick={handleCopyPath}>
489
474
  <Copy size={14} className="shrink-0" /> {t.view?.copyPath ?? t.fileTree?.copyPath ?? 'Copy Path'}
490
475
  </button>
@@ -77,11 +77,12 @@ function countContentFiles(node: FileNode): number {
77
77
  return (node.children ?? []).reduce((sum, c) => sum + countContentFiles(c), 0);
78
78
  }
79
79
 
80
- /** Filter out system files and dot-entries that shouldn't appear by default. */
80
+ /** Filter out hidden entries (dot-files at root, system files) when show-hidden is off. */
81
81
  function filterHiddenNodes(nodes: FileNode[], isRoot: boolean): FileNode[] {
82
82
  return nodes.filter(node => {
83
83
  if (isRoot && node.name.startsWith('.')) return false;
84
84
  if (node.type === 'file' && SYSTEM_FILES.has(node.name)) return false;
85
+ if (node.type === 'directory' && node.name.startsWith('.')) return false;
85
86
  return true;
86
87
  });
87
88
  }
@@ -426,7 +427,7 @@ function DirectoryNode({ node, depth, currentPath, onNavigate, maxOpenDepth, onI
426
427
  onClick={toggle}
427
428
  className="shrink-0 p-1 rounded hover:bg-muted text-muted-foreground transition-colors"
428
429
  style={{ marginLeft: `${depth * 12 + 4}px` }}
429
- aria-label={open ? 'Collapse' : 'Expand'}
430
+ aria-label={open ? `Collapse ${node.name}` : `Expand ${node.name}`}
430
431
  >
431
432
  <span className="block transition-transform duration-150" style={{ transform: open ? 'rotate(0deg)' : 'rotate(-90deg)' }}>
432
433
  <ChevronDown size={13} />
@@ -51,11 +51,18 @@ function CopyButton({ code }: { code: string }) {
51
51
  );
52
52
  }
53
53
 
54
- // Heading components with suppressHydrationWarning to prevent
55
- // rehype-slug + emoji hydration mismatches between server and client
54
+ // react-markdown passes an AST `node` prop to custom components;
55
+ // strip it (and any other non-DOM keys) before forwarding to the real element.
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ function stripNonDom(props: Record<string, any>): Record<string, any> {
58
+ const { node, inline, ordered, depth, isHeader, ...domProps } = props;
59
+ return domProps;
60
+ }
61
+
56
62
  function makeHeading(Tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6') {
57
- const HeadingComponent = ({ children, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
58
- <Tag {...props} suppressHydrationWarning>{children}</Tag>
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ const HeadingComponent = ({ children, ...props }: any) => (
65
+ <Tag {...stripNonDom(props)} suppressHydrationWarning>{children}</Tag>
59
66
  );
60
67
  HeadingComponent.displayName = Tag;
61
68
  return HeadingComponent;
@@ -68,11 +75,12 @@ const components: Components = {
68
75
  h4: makeHeading('h4'),
69
76
  h5: makeHeading('h5'),
70
77
  h6: makeHeading('h6'),
71
- code({ children, ...props }) {
72
- return <code {...props} suppressHydrationWarning>{children}</code>;
78
+ code({ children, node, ...rest }) {
79
+ void node;
80
+ return <code {...stripNonDom(rest)} suppressHydrationWarning>{children}</code>;
73
81
  },
74
- pre({ children, ...props }) {
75
- // Extract code string from children
82
+ pre({ children, node, ...rest }) {
83
+ void node;
76
84
  let codeString = '';
77
85
  if (children && typeof children === 'object' && 'props' in children) {
78
86
  const codeEl = children as React.ReactElement<{ children?: React.ReactNode }>;
@@ -80,31 +88,38 @@ const components: Components = {
80
88
  }
81
89
  return (
82
90
  <div className="relative group">
83
- <pre {...props} suppressHydrationWarning>{children}</pre>
91
+ <pre {...stripNonDom(rest)} suppressHydrationWarning>{children}</pre>
84
92
  <CopyButton code={codeString} />
85
93
  </div>
86
94
  );
87
95
  },
88
- li({ children, ...props }) {
89
- return <li {...props} suppressHydrationWarning>{children}</li>;
96
+ li({ children, node, ...rest }) {
97
+ void node;
98
+ return <li {...stripNonDom(rest)} suppressHydrationWarning>{children}</li>;
99
+ },
100
+ p({ children, node, ...rest }) {
101
+ void node;
102
+ return <p {...stripNonDom(rest)} suppressHydrationWarning>{children}</p>;
90
103
  },
91
- a({ href, children, ...props }) {
104
+ a({ href, children, node, ...rest }) {
105
+ void node;
92
106
  const isExternal = href?.startsWith('http');
93
107
  return (
94
108
  <a
95
109
  href={href}
96
110
  target={isExternal ? '_blank' : undefined}
97
111
  rel={isExternal ? 'noopener noreferrer' : undefined}
98
- {...props}
112
+ {...stripNonDom(rest)}
99
113
  >
100
114
  {children}
101
115
  </a>
102
116
  );
103
117
  },
104
- img({ src, alt, ...props }) {
118
+ img({ src, alt, node, ...rest }) {
119
+ void node;
105
120
  if (!src) return null;
106
121
  // eslint-disable-next-line @next/next/no-img-element
107
- return <img src={src} alt={alt ?? ''} {...props} />;
122
+ return <img src={src} alt={alt ?? ''} {...stripNonDom(rest)} />;
108
123
  },
109
124
  };
110
125
 
@@ -9,7 +9,9 @@ import { useResizeDrag } from '@/hooks/useResizeDrag';
9
9
  const DEFAULT_WIDTH = 420;
10
10
  const MIN_WIDTH = 400;
11
11
  const MAX_WIDTH_ABS = 4000;
12
- const FOCUS_SNAP_THRESHOLD = 80;
12
+ const ENTER_SNAP_THRESHOLD = 80;
13
+ const EXIT_SNAP_THRESHOLD = 16;
14
+ const MIN_CONTENT_WIDTH = 360;
13
15
 
14
16
  import type { AcpAgentSelection } from '@/hooks/useAskModal';
15
17
 
@@ -37,6 +39,7 @@ export default function RightAskPanel({
37
39
  maximized = false, onMaximize, sidebarOffset = 0,
38
40
  }: RightAskPanelProps) {
39
41
  const snapFiredRef = useRef(false);
42
+ const justExitedMaxRef = useRef(false);
40
43
 
41
44
  const maxAvailable = typeof window !== 'undefined'
42
45
  ? window.innerWidth - sidebarOffset
@@ -45,12 +48,28 @@ export default function RightAskPanel({
45
48
  const handleResize = useCallback((w: number) => {
46
49
  if (snapFiredRef.current) return;
47
50
  const clamped = Math.min(w, maxAvailable);
48
- if (maximized && clamped < maxAvailable - FOCUS_SNAP_THRESHOLD && onMaximize) {
51
+
52
+ // Exit maximized: user drags right even a little (16px) → exit immediately
53
+ if (maximized && clamped < maxAvailable - EXIT_SNAP_THRESHOLD && onMaximize) {
54
+ justExitedMaxRef.current = true;
49
55
  onMaximize();
50
- onWidthChange(clamped);
56
+ const maxPanelForContent = typeof window !== 'undefined'
57
+ ? window.innerWidth - sidebarOffset - MIN_CONTENT_WIDTH
58
+ : clamped;
59
+ onWidthChange(Math.min(clamped, maxPanelForContent));
51
60
  return;
52
61
  }
53
- if (!maximized && clamped >= maxAvailable - FOCUS_SNAP_THRESHOLD && onMaximize) {
62
+
63
+ // Snap to fullscreen: panel near max edge OR content squeezed below minimum.
64
+ // Suppress content-based snap while justExitedMaxRef is true (user recently
65
+ // exited fullscreen and panel is still wide); only re-enable once the panel
66
+ // has been shrunk enough that content is comfortable (reset in handleMouseDown).
67
+ const contentRemaining = typeof window !== 'undefined'
68
+ ? window.innerWidth - sidebarOffset - clamped
69
+ : Infinity;
70
+ const shouldSnap = clamped >= maxAvailable - ENTER_SNAP_THRESHOLD
71
+ || (!justExitedMaxRef.current && contentRemaining < MIN_CONTENT_WIDTH);
72
+ if (!maximized && shouldSnap && onMaximize) {
54
73
  snapFiredRef.current = true;
55
74
  onMaximize();
56
75
  return;
@@ -58,7 +77,7 @@ export default function RightAskPanel({
58
77
  if (!maximized) {
59
78
  onWidthChange(clamped);
60
79
  }
61
- }, [maxAvailable, onMaximize, maximized, onWidthChange]);
80
+ }, [maxAvailable, sidebarOffset, onMaximize, maximized, onWidthChange]);
62
81
 
63
82
  const handleResizeEnd = useCallback((w: number) => {
64
83
  if (snapFiredRef.current) return;
@@ -77,8 +96,19 @@ export default function RightAskPanel({
77
96
 
78
97
  const handleMouseDown = useCallback((e: React.MouseEvent) => {
79
98
  snapFiredRef.current = false;
99
+ // Only re-enable content-based snap once the panel has been shrunk enough
100
+ // that content is comfortably above minimum. This prevents the bounce:
101
+ // exit fullscreen → new drag → immediately re-snap because panel still wide.
102
+ if (justExitedMaxRef.current) {
103
+ const currentContent = typeof window !== 'undefined'
104
+ ? window.innerWidth - sidebarOffset - width
105
+ : Infinity;
106
+ if (currentContent >= MIN_CONTENT_WIDTH) {
107
+ justExitedMaxRef.current = false;
108
+ }
109
+ }
80
110
  rawMouseDown(e);
81
- }, [rawMouseDown]);
111
+ }, [rawMouseDown, sidebarOffset, width]);
82
112
 
83
113
  const effectiveWidth = maximized
84
114
  ? `calc(100vw - ${sidebarOffset}px)`
@@ -102,13 +102,13 @@ export default function Sidebar({ fileTree, collapsed = false, onCollapse, onExp
102
102
  </button>
103
103
  {/* Desktop action buttons — trimmed to 4 */}
104
104
  <div className="hidden md:flex items-center gap-1">
105
- <button onClick={() => setSearchOpen(true)} className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={t.sidebar.searchTitle} aria-label={t.sidebar.searchTitle}>
105
+ <button onClick={() => setSearchOpen(true)} className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={t.sidebar.searchTitle} aria-hidden="true" tabIndex={-1}>
106
106
  <Search size={15} />
107
107
  </button>
108
- <button onClick={() => setSettingsOpen(true)} className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={t.sidebar.settingsTitle} aria-label={t.sidebar.settingsTitle}>
108
+ <button onClick={() => setSettingsOpen(true)} className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={t.sidebar.settingsTitle} aria-hidden="true" tabIndex={-1}>
109
109
  <Settings size={15} />
110
110
  </button>
111
- <button onClick={onCollapse} className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={t.sidebar.collapseTitle} aria-label={t.sidebar.collapseTitle}>
111
+ <button onClick={onCollapse} className="p-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors" title={t.sidebar.collapseTitle} aria-hidden="true" tabIndex={-1}>
112
112
  <PanelLeftClose size={15} />
113
113
  </button>
114
114
  </div>
@@ -3,6 +3,7 @@
3
3
  import { useCallback, useMemo, useState } from 'react';
4
4
  import Link from 'next/link';
5
5
  import { RefreshCw, Search, Server } from 'lucide-react';
6
+ import { apiFetch } from '@/lib/api';
6
7
  import type { McpContextValue } from '@/lib/stores/mcp-store';
7
8
  import type { AgentBuckets, AgentStatusFilter, AgentTransportFilter } from './agents-content-model';
8
9
  import {
@@ -58,6 +59,8 @@ export default function AgentsMcpSection({
58
59
  cancel: string;
59
60
  noAvailableAgents: string;
60
61
  manualRemoveHint: string;
62
+ removeSuccess: string;
63
+ removeFailed: string;
61
64
  reconnectAllInServer: string;
62
65
  reconnectAllRunning: string;
63
66
  reconnectAllDone: (ok: number, failed: number) => string;
@@ -339,6 +342,9 @@ function ByAgentView({
339
342
  variant="primary"
340
343
  />
341
344
  )}
345
+ {!agent.installed && (
346
+ <span className="text-2xs text-muted-foreground/60">or CLI Skill</span>
347
+ )}
342
348
  </div>
343
349
  </div>
344
350
 
@@ -380,7 +386,7 @@ function ByServerView({
380
386
  onReconnect: (agent: ReturnType<typeof sortAgentsByStatus>[number]) => Promise<void>;
381
387
  }) {
382
388
  const [pickerServer, setPickerServer] = useState<string | null>(null);
383
- const [confirmState, setConfirmState] = useState<{ agentName: string; serverName: string } | null>(null);
389
+ const [confirmState, setConfirmState] = useState<{ agentKey: string; agentName: string; serverName: string } | null>(null);
384
390
  const [hintMessage, setHintMessage] = useState<string | null>(null);
385
391
  const [reconnectingServer, setReconnectingServer] = useState<string | null>(null);
386
392
  const [reconnectMsg, setReconnectMsg] = useState<Record<string, string>>({});
@@ -393,11 +399,27 @@ function ByServerView({
393
399
  [onInstallMindos],
394
400
  );
395
401
 
396
- const handleConfirmRemove = useCallback(() => {
402
+ const handleConfirmRemove = useCallback(async () => {
403
+ if (!confirmState) return;
404
+ const { agentKey } = confirmState;
397
405
  setConfirmState(null);
398
- setHintMessage(copy.manualRemoveHint);
406
+
407
+ // Find agent info to determine scope
408
+ const agent = allAgents.find(a => a.key === agentKey);
409
+ const scope = agent?.scope === 'project' ? 'project' : 'global';
410
+
411
+ try {
412
+ await apiFetch('/api/mcp/uninstall', {
413
+ method: 'POST',
414
+ headers: { 'Content-Type': 'application/json' },
415
+ body: JSON.stringify({ agents: [{ key: agentKey, scope }] }),
416
+ });
417
+ setHintMessage(copy.removeSuccess ?? 'Removed. Restart your agent to apply.');
418
+ } catch {
419
+ setHintMessage(copy.removeFailed ?? 'Failed to remove. Try editing the config file manually.');
420
+ }
399
421
  setTimeout(() => setHintMessage(null), 4000);
400
- }, [copy.manualRemoveHint]);
422
+ }, [confirmState, allAgents, copy]);
401
423
 
402
424
  const handleReconnectAllInServer = useCallback(
403
425
  async (serverName: string, agents: typeof allAgents) => {
@@ -517,7 +539,7 @@ function ByServerView({
517
539
  <AgentAvatar
518
540
  name={agent.name}
519
541
  status={agentStatus}
520
- onRemove={() => setConfirmState({ agentName: agent.name, serverName: srv.serverName })}
542
+ onRemove={() => setConfirmState({ agentKey: agent.key, agentName: agent.name, serverName: srv.serverName })}
521
543
  />
522
544
  </Link>
523
545
  );
@@ -18,6 +18,7 @@ function Section({ id, icon, title, defaultOpen = false, children }: {
18
18
 
19
19
  return (
20
20
  <div id={id} className="bg-card border border-border rounded-lg overflow-hidden scroll-mt-4">
21
+ <h2 className="sr-only">{title}</h2>
21
22
  <button
22
23
  onClick={() => setOpen(v => !v)}
23
24
  className="w-full flex items-center gap-3 px-5 py-4 text-left hover:bg-muted/50 transition-colors focus-visible:ring-2 focus-visible:ring-ring"