@geminilight/mindos 0.6.59 → 0.6.60

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 (347) 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 +20 -19
  4. package/_standalone/.next/build-manifest.json +2 -2
  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/routes-manifest.json +6 -0
  10. package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
  11. package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/_standalone/.next/server/app/_global-error.html +2 -2
  13. package/_standalone/.next/server/app/_global-error.rsc +1 -1
  14. package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  15. package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  16. package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  17. package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  18. package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  19. package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  20. package/_standalone/.next/server/app/_not-found/page.js +1 -1
  21. package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  22. package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  23. package/_standalone/.next/server/app/agents/[agentKey]/page.js +1 -1
  24. package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
  25. package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
  26. package/_standalone/.next/server/app/agents/page.js +1 -1
  27. package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
  28. package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
  29. package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
  30. package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
  31. package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
  32. package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
  33. package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
  34. package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
  35. package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
  36. package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
  37. package/_standalone/.next/server/app/api/acp/session/route_client-reference-manifest.js +1 -1
  38. package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
  39. package/_standalone/.next/server/app/api/agents/copy-skill/route.js +1 -0
  40. package/_standalone/.next/server/app/api/agents/copy-skill/route.js.nft.json +1 -0
  41. package/_standalone/.next/server/app/api/agents/copy-skill/route_client-reference-manifest.js +1 -0
  42. package/_standalone/.next/server/app/api/agents/custom/detect/route.js +1 -1
  43. package/_standalone/.next/server/app/api/agents/custom/detect/route_client-reference-manifest.js +1 -1
  44. package/_standalone/.next/server/app/api/agents/custom/route.js +1 -1
  45. package/_standalone/.next/server/app/api/agents/custom/route_client-reference-manifest.js +1 -1
  46. package/_standalone/.next/server/app/api/ask/route.js +17 -6
  47. package/_standalone/.next/server/app/api/ask/route_client-reference-manifest.js +1 -1
  48. package/_standalone/.next/server/app/api/ask-sessions/route_client-reference-manifest.js +1 -1
  49. package/_standalone/.next/server/app/api/auth/route_client-reference-manifest.js +1 -1
  50. package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
  51. package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
  52. package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
  53. package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
  54. package/_standalone/.next/server/app/api/extract-pdf/route.js +2 -2
  55. package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
  56. package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
  57. package/_standalone/.next/server/app/api/file/raw/route_client-reference-manifest.js +1 -1
  58. package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
  61. package/_standalone/.next/server/app/api/graph/route_client-reference-manifest.js +1 -1
  62. package/_standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  63. package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.js +1 -1
  64. package/_standalone/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
  65. package/_standalone/.next/server/app/api/mcp/agents/route.js +1 -1
  66. package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
  67. package/_standalone/.next/server/app/api/mcp/install/route_client-reference-manifest.js +1 -1
  68. package/_standalone/.next/server/app/api/mcp/install-skill/route_client-reference-manifest.js +1 -1
  69. package/_standalone/.next/server/app/api/mcp/restart/route_client-reference-manifest.js +1 -1
  70. package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
  71. package/_standalone/.next/server/app/api/mcp/uninstall/route_client-reference-manifest.js +1 -1
  72. package/_standalone/.next/server/app/api/monitoring/route_client-reference-manifest.js +1 -1
  73. package/_standalone/.next/server/app/api/recent-files/route_client-reference-manifest.js +1 -1
  74. package/_standalone/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
  75. package/_standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  76. package/_standalone/.next/server/app/api/settings/list-models/route_client-reference-manifest.js +1 -1
  77. package/_standalone/.next/server/app/api/settings/reset-token/route_client-reference-manifest.js +1 -1
  78. package/_standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
  79. package/_standalone/.next/server/app/api/settings/test-key/route_client-reference-manifest.js +1 -1
  80. package/_standalone/.next/server/app/api/setup/check-path/route_client-reference-manifest.js +1 -1
  81. package/_standalone/.next/server/app/api/setup/check-port/route_client-reference-manifest.js +1 -1
  82. package/_standalone/.next/server/app/api/setup/generate-token/route_client-reference-manifest.js +1 -1
  83. package/_standalone/.next/server/app/api/setup/ls/route_client-reference-manifest.js +1 -1
  84. package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
  85. package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  86. package/_standalone/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
  87. package/_standalone/.next/server/app/api/tree-version/route_client-reference-manifest.js +1 -1
  88. package/_standalone/.next/server/app/api/uninstall/route_client-reference-manifest.js +1 -1
  89. package/_standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  90. package/_standalone/.next/server/app/api/update-check/route_client-reference-manifest.js +1 -1
  91. package/_standalone/.next/server/app/api/update-status/route_client-reference-manifest.js +1 -1
  92. package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
  93. package/_standalone/.next/server/app/changes/page.js +2 -2
  94. package/_standalone/.next/server/app/changes/page.js.nft.json +1 -1
  95. package/_standalone/.next/server/app/changes/page_client-reference-manifest.js +1 -1
  96. package/_standalone/.next/server/app/echo/[segment]/page.js +1 -1
  97. package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
  98. package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
  99. package/_standalone/.next/server/app/echo/page.js +1 -1
  100. package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
  101. package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
  102. package/_standalone/.next/server/app/explore/page.js +1 -1
  103. package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
  104. package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
  105. package/_standalone/.next/server/app/help/page.js +1 -1
  106. package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
  107. package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
  108. package/_standalone/.next/server/app/inbox/history/page.js +1 -1
  109. package/_standalone/.next/server/app/inbox/history/page.js.nft.json +1 -1
  110. package/_standalone/.next/server/app/inbox/history/page_client-reference-manifest.js +1 -1
  111. package/_standalone/.next/server/app/login/page.js +1 -1
  112. package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
  113. package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  114. package/_standalone/.next/server/app/page.js +1 -1
  115. package/_standalone/.next/server/app/page.js.nft.json +1 -1
  116. package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  117. package/_standalone/.next/server/app/setup/page.js +1 -1
  118. package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
  119. package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  120. package/_standalone/.next/server/app/trash/page.js +3 -3
  121. package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
  122. package/_standalone/.next/server/app/view/[...path]/page.js +2 -2
  123. package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
  124. package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
  125. package/_standalone/.next/server/app/wiki/page.js +1 -1
  126. package/_standalone/.next/server/app/wiki/page.js.nft.json +1 -1
  127. package/_standalone/.next/server/app/wiki/page_client-reference-manifest.js +1 -1
  128. package/_standalone/.next/server/app-paths-manifest.json +20 -19
  129. package/_standalone/.next/server/chunks/1550.js +1 -1
  130. package/_standalone/.next/server/chunks/3484.js +1 -1
  131. package/_standalone/.next/server/chunks/530.js +35 -35
  132. package/_standalone/.next/server/chunks/{8343.js → 9753.js} +2 -2
  133. package/_standalone/.next/server/pages/500.html +2 -2
  134. package/_standalone/.next/server/server-reference-manifest.js +1 -1
  135. package/_standalone/.next/server/server-reference-manifest.json +1 -1
  136. package/_standalone/.next/static/K3wZNf5bj_AFYwtqcRXIf/_buildManifest.js +1 -0
  137. package/_standalone/.next/static/chunks/1369-7d0ac5d1564eed1e.js +1 -0
  138. package/_standalone/.next/static/chunks/{5581-dac72e9f16e5ea29.js → 5581-974dfb26d1d1b38f.js} +2 -2
  139. package/_standalone/.next/static/chunks/7249-b0a9c77b9a84b11c.js +11 -0
  140. package/_standalone/.next/static/chunks/7637-904b0a381dc3ec02.js +1 -0
  141. package/_standalone/.next/static/chunks/8520-76d1b05072178b43.js +22 -0
  142. package/_standalone/.next/static/chunks/9186-ead47513192f658b.js +1 -0
  143. package/_standalone/.next/static/chunks/app/.well-known/agent-card.json/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
  144. package/_standalone/.next/static/chunks/app/_global-error/{page-2f4705aa66819b86.js → page-2ceea6eabf25b1f2.js} +1 -1
  145. package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-0ea3571c8fbae823.js +1 -0
  146. package/_standalone/.next/static/chunks/app/agents/{page-b172ea3743adb047.js → page-66858acbcd1d4bf8.js} +1 -1
  147. package/_standalone/.next/static/chunks/app/api/a2a/agents/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
  148. package/_standalone/.next/static/chunks/app/api/a2a/delegations/{route-2f4705aa66819b86.js → route-2ceea6eabf25b1f2.js} +1 -1
  149. package/_standalone/.next/static/chunks/app/api/a2a/discover/route-2ceea6eabf25b1f2.js +1 -0
  150. package/_standalone/.next/static/chunks/app/api/a2a/route-2ceea6eabf25b1f2.js +1 -0
  151. package/_standalone/.next/static/chunks/app/api/acp/config/route-2ceea6eabf25b1f2.js +1 -0
  152. package/_standalone/.next/static/chunks/app/api/acp/detect/route-2ceea6eabf25b1f2.js +1 -0
  153. package/_standalone/.next/static/chunks/app/api/acp/install/route-2ceea6eabf25b1f2.js +1 -0
  154. package/_standalone/.next/static/chunks/app/api/acp/registry/route-2ceea6eabf25b1f2.js +1 -0
  155. package/_standalone/.next/static/chunks/app/api/acp/session/route-2ceea6eabf25b1f2.js +1 -0
  156. package/_standalone/.next/static/chunks/app/api/agent-activity/route-2ceea6eabf25b1f2.js +1 -0
  157. package/_standalone/.next/static/chunks/app/api/agents/copy-skill/route-2ceea6eabf25b1f2.js +1 -0
  158. package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-2ceea6eabf25b1f2.js +1 -0
  159. package/_standalone/.next/static/chunks/app/api/agents/custom/route-2ceea6eabf25b1f2.js +1 -0
  160. package/_standalone/.next/static/chunks/app/api/ask/route-2ceea6eabf25b1f2.js +1 -0
  161. package/_standalone/.next/static/chunks/app/api/ask-sessions/route-2ceea6eabf25b1f2.js +1 -0
  162. package/_standalone/.next/static/chunks/app/api/auth/route-2ceea6eabf25b1f2.js +1 -0
  163. package/_standalone/.next/static/chunks/app/api/backlinks/route-2ceea6eabf25b1f2.js +1 -0
  164. package/_standalone/.next/static/chunks/app/api/bootstrap/route-2ceea6eabf25b1f2.js +1 -0
  165. package/_standalone/.next/static/chunks/app/api/changes/route-2ceea6eabf25b1f2.js +1 -0
  166. package/_standalone/.next/static/chunks/app/api/export/route-2ceea6eabf25b1f2.js +1 -0
  167. package/_standalone/.next/static/chunks/app/api/extract-pdf/route-2ceea6eabf25b1f2.js +1 -0
  168. package/_standalone/.next/static/chunks/app/api/file/import/route-2ceea6eabf25b1f2.js +1 -0
  169. package/_standalone/.next/static/chunks/app/api/file/raw/route-2ceea6eabf25b1f2.js +1 -0
  170. package/_standalone/.next/static/chunks/app/api/file/route-2ceea6eabf25b1f2.js +1 -0
  171. package/_standalone/.next/static/chunks/app/api/files/route-2ceea6eabf25b1f2.js +1 -0
  172. package/_standalone/.next/static/chunks/app/api/git/route-2ceea6eabf25b1f2.js +1 -0
  173. package/_standalone/.next/static/chunks/app/api/graph/route-2ceea6eabf25b1f2.js +1 -0
  174. package/_standalone/.next/static/chunks/app/api/health/route-2ceea6eabf25b1f2.js +1 -0
  175. package/_standalone/.next/static/chunks/app/api/inbox/route-2ceea6eabf25b1f2.js +1 -0
  176. package/_standalone/.next/static/chunks/app/api/init/route-2ceea6eabf25b1f2.js +1 -0
  177. package/_standalone/.next/static/chunks/app/api/mcp/agents/route-2ceea6eabf25b1f2.js +1 -0
  178. package/_standalone/.next/static/chunks/app/api/mcp/install/route-2ceea6eabf25b1f2.js +1 -0
  179. package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-2ceea6eabf25b1f2.js +1 -0
  180. package/_standalone/.next/static/chunks/app/api/mcp/restart/route-2ceea6eabf25b1f2.js +1 -0
  181. package/_standalone/.next/static/chunks/app/api/mcp/status/route-2ceea6eabf25b1f2.js +1 -0
  182. package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-2ceea6eabf25b1f2.js +1 -0
  183. package/_standalone/.next/static/chunks/app/api/monitoring/route-2ceea6eabf25b1f2.js +1 -0
  184. package/_standalone/.next/static/chunks/app/api/recent-files/route-2ceea6eabf25b1f2.js +1 -0
  185. package/_standalone/.next/static/chunks/app/api/restart/route-2ceea6eabf25b1f2.js +1 -0
  186. package/_standalone/.next/static/chunks/app/api/search/route-2ceea6eabf25b1f2.js +1 -0
  187. package/_standalone/.next/static/chunks/app/api/settings/list-models/route-2ceea6eabf25b1f2.js +1 -0
  188. package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-2ceea6eabf25b1f2.js +1 -0
  189. package/_standalone/.next/static/chunks/app/api/settings/route-2ceea6eabf25b1f2.js +1 -0
  190. package/_standalone/.next/static/chunks/app/api/settings/test-key/route-2ceea6eabf25b1f2.js +1 -0
  191. package/_standalone/.next/static/chunks/app/api/setup/check-path/route-2ceea6eabf25b1f2.js +1 -0
  192. package/_standalone/.next/static/chunks/app/api/setup/check-port/route-2ceea6eabf25b1f2.js +1 -0
  193. package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-2ceea6eabf25b1f2.js +1 -0
  194. package/_standalone/.next/static/chunks/app/api/setup/ls/route-2ceea6eabf25b1f2.js +1 -0
  195. package/_standalone/.next/static/chunks/app/api/setup/route-2ceea6eabf25b1f2.js +1 -0
  196. package/_standalone/.next/static/chunks/app/api/skills/route-2ceea6eabf25b1f2.js +1 -0
  197. package/_standalone/.next/static/chunks/app/api/sync/route-2ceea6eabf25b1f2.js +1 -0
  198. package/_standalone/.next/static/chunks/app/api/tree-version/route-2ceea6eabf25b1f2.js +1 -0
  199. package/_standalone/.next/static/chunks/app/api/uninstall/route-2ceea6eabf25b1f2.js +1 -0
  200. package/_standalone/.next/static/chunks/app/api/update/route-2ceea6eabf25b1f2.js +1 -0
  201. package/_standalone/.next/static/chunks/app/api/update-check/route-2ceea6eabf25b1f2.js +1 -0
  202. package/_standalone/.next/static/chunks/app/api/update-status/route-2ceea6eabf25b1f2.js +1 -0
  203. package/_standalone/.next/static/chunks/app/api/workflows/route-2ceea6eabf25b1f2.js +1 -0
  204. package/_standalone/.next/static/chunks/app/changes/page-dd0b00a7b81f74e2.js +1 -0
  205. package/_standalone/.next/static/chunks/app/echo/[segment]/{page-84b95256f6e38aae.js → page-bf5c290fa3ccff09.js} +1 -1
  206. package/_standalone/.next/static/chunks/app/echo/page-2ceea6eabf25b1f2.js +1 -0
  207. package/_standalone/.next/static/chunks/app/inbox/history/{page-26e71fb6f716a4c4.js → page-3279585360df132c.js} +1 -1
  208. package/_standalone/.next/static/chunks/app/{layout-b89b0d955f39a753.js → layout-6a0169582db11a08.js} +24 -24
  209. package/_standalone/.next/static/chunks/app/loading-2ceea6eabf25b1f2.js +1 -0
  210. package/_standalone/.next/static/chunks/app/{page-a8e6f085f38388bf.js → page-6a1f8d21c12b829e.js} +1 -1
  211. package/_standalone/.next/static/chunks/app/trash/page-ed7ba3b0b50223a6.js +1 -0
  212. package/_standalone/.next/static/chunks/app/view/[...path]/loading-2ceea6eabf25b1f2.js +1 -0
  213. package/_standalone/.next/static/chunks/app/view/[...path]/page-678139779971cfcb.js +12 -0
  214. package/_standalone/.next/static/chunks/app/wiki/page-194ae9af2d461481.js +1 -0
  215. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-2ceea6eabf25b1f2.js +1 -0
  216. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-2ceea6eabf25b1f2.js +1 -0
  217. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-2ceea6eabf25b1f2.js +1 -0
  218. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2ceea6eabf25b1f2.js +1 -0
  219. package/_standalone/.next/static/css/9c558c42831fae58.css +1 -0
  220. package/_standalone/.next/trace +65 -64
  221. package/_standalone/.next/types/routes.d.ts +2 -1
  222. package/_standalone/.next/types/validator.ts +9 -0
  223. package/_standalone/__tests__/api/mcp-install.test.ts +4 -2
  224. package/_standalone/components/AskFab.tsx +7 -1
  225. package/_standalone/components/FileTree.tsx +83 -1
  226. package/_standalone/components/Panel.tsx +6 -1
  227. package/_standalone/components/agents/AgentsOverviewSection.tsx +13 -11
  228. package/_standalone/components/agents/CustomAgentModal.tsx +72 -18
  229. package/_standalone/components/ask/AskContent.tsx +19 -3
  230. package/_standalone/components/ask/FileChip.tsx +93 -12
  231. package/_standalone/components/changes/ChangesBanner.tsx +1 -1
  232. package/_standalone/components/walkthrough/WalkthroughTooltip.tsx +3 -1
  233. package/_standalone/components/walkthrough/steps.ts +1 -1
  234. package/_standalone/hooks/useAskChat.ts +10 -8
  235. package/_standalone/hooks/useFileUpload.ts +97 -43
  236. package/_standalone/hooks/useImageUpload.ts +1 -1
  237. package/_standalone/lib/inbox-upload.ts +86 -0
  238. package/_standalone/package-lock.json +2 -2
  239. package/_standalone/package.json +1 -1
  240. package/_standalone/scripts/extract-pdf.cjs +110 -3
  241. package/_standalone/tsconfig.tsbuildinfo +1 -1
  242. package/app/app/api/agents/copy-skill/route.ts +110 -0
  243. package/app/app/api/agents/custom/detect/route.ts +16 -1
  244. package/app/app/api/ask/route.ts +7 -1
  245. package/app/app/api/extract-pdf/route.ts +12 -5
  246. package/app/app/api/mcp/agents/route.ts +64 -2
  247. package/app/components/AskFab.tsx +7 -1
  248. package/app/components/FileTree.tsx +83 -1
  249. package/app/components/HomeContent.tsx +14 -6
  250. package/app/components/Panel.tsx +6 -1
  251. package/app/components/agents/AgentDetailContent.tsx +58 -1
  252. package/app/components/agents/AgentsOverviewSection.tsx +13 -11
  253. package/app/components/agents/CustomAgentModal.tsx +72 -18
  254. package/app/components/ask/AskContent.tsx +19 -3
  255. package/app/components/ask/FileChip.tsx +93 -12
  256. package/app/components/changes/ChangesBanner.tsx +1 -1
  257. package/app/components/changes/ChangesContentPage.tsx +368 -168
  258. package/app/components/walkthrough/WalkthroughTooltip.tsx +3 -1
  259. package/app/components/walkthrough/steps.ts +1 -1
  260. package/app/hooks/useAskChat.ts +10 -8
  261. package/app/hooks/useFileUpload.ts +97 -43
  262. package/app/hooks/useImageUpload.ts +1 -1
  263. package/app/lib/agent/prompt.ts +15 -4
  264. package/app/lib/custom-agents.ts +109 -1
  265. package/app/lib/file-ops.ts +58 -0
  266. package/app/lib/i18n/modules/ai-chat.ts +37 -0
  267. package/app/lib/i18n/modules/knowledge.ts +2 -0
  268. package/app/lib/inbox-upload.ts +86 -0
  269. package/app/lib/mcp-agents.ts +21 -1
  270. package/app/lib/types.ts +12 -0
  271. package/app/package.json +1 -1
  272. package/app/scripts/extract-pdf.cjs +110 -3
  273. package/package.json +1 -1
  274. package/_standalone/.next/static/chunks/4237-ffc6e7c15d4007b6.js +0 -1
  275. package/_standalone/.next/static/chunks/6878-e2c5459e1c608f89.js +0 -1
  276. package/_standalone/.next/static/chunks/7249-6cf8f2b78718c59e.js +0 -11
  277. package/_standalone/.next/static/chunks/8520-56ec9ff087c15204.js +0 -22
  278. package/_standalone/.next/static/chunks/9286-5b09baa5200318c2.js +0 -1
  279. package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-35ea6de1af2be3b5.js +0 -1
  280. package/_standalone/.next/static/chunks/app/api/a2a/discover/route-2f4705aa66819b86.js +0 -1
  281. package/_standalone/.next/static/chunks/app/api/a2a/route-2f4705aa66819b86.js +0 -1
  282. package/_standalone/.next/static/chunks/app/api/acp/config/route-2f4705aa66819b86.js +0 -1
  283. package/_standalone/.next/static/chunks/app/api/acp/detect/route-2f4705aa66819b86.js +0 -1
  284. package/_standalone/.next/static/chunks/app/api/acp/install/route-2f4705aa66819b86.js +0 -1
  285. package/_standalone/.next/static/chunks/app/api/acp/registry/route-2f4705aa66819b86.js +0 -1
  286. package/_standalone/.next/static/chunks/app/api/acp/session/route-2f4705aa66819b86.js +0 -1
  287. package/_standalone/.next/static/chunks/app/api/agent-activity/route-2f4705aa66819b86.js +0 -1
  288. package/_standalone/.next/static/chunks/app/api/agents/custom/detect/route-2f4705aa66819b86.js +0 -1
  289. package/_standalone/.next/static/chunks/app/api/agents/custom/route-2f4705aa66819b86.js +0 -1
  290. package/_standalone/.next/static/chunks/app/api/ask/route-2f4705aa66819b86.js +0 -1
  291. package/_standalone/.next/static/chunks/app/api/ask-sessions/route-2f4705aa66819b86.js +0 -1
  292. package/_standalone/.next/static/chunks/app/api/auth/route-2f4705aa66819b86.js +0 -1
  293. package/_standalone/.next/static/chunks/app/api/backlinks/route-2f4705aa66819b86.js +0 -1
  294. package/_standalone/.next/static/chunks/app/api/bootstrap/route-2f4705aa66819b86.js +0 -1
  295. package/_standalone/.next/static/chunks/app/api/changes/route-2f4705aa66819b86.js +0 -1
  296. package/_standalone/.next/static/chunks/app/api/export/route-2f4705aa66819b86.js +0 -1
  297. package/_standalone/.next/static/chunks/app/api/extract-pdf/route-2f4705aa66819b86.js +0 -1
  298. package/_standalone/.next/static/chunks/app/api/file/import/route-2f4705aa66819b86.js +0 -1
  299. package/_standalone/.next/static/chunks/app/api/file/raw/route-2f4705aa66819b86.js +0 -1
  300. package/_standalone/.next/static/chunks/app/api/file/route-2f4705aa66819b86.js +0 -1
  301. package/_standalone/.next/static/chunks/app/api/files/route-2f4705aa66819b86.js +0 -1
  302. package/_standalone/.next/static/chunks/app/api/git/route-2f4705aa66819b86.js +0 -1
  303. package/_standalone/.next/static/chunks/app/api/graph/route-2f4705aa66819b86.js +0 -1
  304. package/_standalone/.next/static/chunks/app/api/health/route-2f4705aa66819b86.js +0 -1
  305. package/_standalone/.next/static/chunks/app/api/inbox/route-2f4705aa66819b86.js +0 -1
  306. package/_standalone/.next/static/chunks/app/api/init/route-2f4705aa66819b86.js +0 -1
  307. package/_standalone/.next/static/chunks/app/api/mcp/agents/route-2f4705aa66819b86.js +0 -1
  308. package/_standalone/.next/static/chunks/app/api/mcp/install/route-2f4705aa66819b86.js +0 -1
  309. package/_standalone/.next/static/chunks/app/api/mcp/install-skill/route-2f4705aa66819b86.js +0 -1
  310. package/_standalone/.next/static/chunks/app/api/mcp/restart/route-2f4705aa66819b86.js +0 -1
  311. package/_standalone/.next/static/chunks/app/api/mcp/status/route-2f4705aa66819b86.js +0 -1
  312. package/_standalone/.next/static/chunks/app/api/mcp/uninstall/route-2f4705aa66819b86.js +0 -1
  313. package/_standalone/.next/static/chunks/app/api/monitoring/route-2f4705aa66819b86.js +0 -1
  314. package/_standalone/.next/static/chunks/app/api/recent-files/route-2f4705aa66819b86.js +0 -1
  315. package/_standalone/.next/static/chunks/app/api/restart/route-2f4705aa66819b86.js +0 -1
  316. package/_standalone/.next/static/chunks/app/api/search/route-2f4705aa66819b86.js +0 -1
  317. package/_standalone/.next/static/chunks/app/api/settings/list-models/route-2f4705aa66819b86.js +0 -1
  318. package/_standalone/.next/static/chunks/app/api/settings/reset-token/route-2f4705aa66819b86.js +0 -1
  319. package/_standalone/.next/static/chunks/app/api/settings/route-2f4705aa66819b86.js +0 -1
  320. package/_standalone/.next/static/chunks/app/api/settings/test-key/route-2f4705aa66819b86.js +0 -1
  321. package/_standalone/.next/static/chunks/app/api/setup/check-path/route-2f4705aa66819b86.js +0 -1
  322. package/_standalone/.next/static/chunks/app/api/setup/check-port/route-2f4705aa66819b86.js +0 -1
  323. package/_standalone/.next/static/chunks/app/api/setup/generate-token/route-2f4705aa66819b86.js +0 -1
  324. package/_standalone/.next/static/chunks/app/api/setup/ls/route-2f4705aa66819b86.js +0 -1
  325. package/_standalone/.next/static/chunks/app/api/setup/route-2f4705aa66819b86.js +0 -1
  326. package/_standalone/.next/static/chunks/app/api/skills/route-2f4705aa66819b86.js +0 -1
  327. package/_standalone/.next/static/chunks/app/api/sync/route-2f4705aa66819b86.js +0 -1
  328. package/_standalone/.next/static/chunks/app/api/tree-version/route-2f4705aa66819b86.js +0 -1
  329. package/_standalone/.next/static/chunks/app/api/uninstall/route-2f4705aa66819b86.js +0 -1
  330. package/_standalone/.next/static/chunks/app/api/update/route-2f4705aa66819b86.js +0 -1
  331. package/_standalone/.next/static/chunks/app/api/update-check/route-2f4705aa66819b86.js +0 -1
  332. package/_standalone/.next/static/chunks/app/api/update-status/route-2f4705aa66819b86.js +0 -1
  333. package/_standalone/.next/static/chunks/app/api/workflows/route-2f4705aa66819b86.js +0 -1
  334. package/_standalone/.next/static/chunks/app/changes/page-6d2f49651c0061f7.js +0 -1
  335. package/_standalone/.next/static/chunks/app/echo/page-2f4705aa66819b86.js +0 -1
  336. package/_standalone/.next/static/chunks/app/loading-2f4705aa66819b86.js +0 -1
  337. package/_standalone/.next/static/chunks/app/trash/page-f92b728b78ac0f7e.js +0 -1
  338. package/_standalone/.next/static/chunks/app/view/[...path]/loading-2f4705aa66819b86.js +0 -1
  339. package/_standalone/.next/static/chunks/app/view/[...path]/page-f87f4901b5e1a88f.js +0 -12
  340. package/_standalone/.next/static/chunks/app/wiki/page-641edb1f3cff2f93.js +0 -1
  341. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-2f4705aa66819b86.js +0 -1
  342. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-2f4705aa66819b86.js +0 -1
  343. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-2f4705aa66819b86.js +0 -1
  344. package/_standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-2f4705aa66819b86.js +0 -1
  345. package/_standalone/.next/static/css/6c104b118d3bc9b7.css +0 -1
  346. package/_standalone/.next/static/u8p6oIRTcr_ns-ElNZ9rl/_buildManifest.js +0 -1
  347. /package/_standalone/.next/static/{u8p6oIRTcr_ns-ElNZ9rl → K3wZNf5bj_AFYwtqcRXIf}/_ssgManifest.js +0 -0
@@ -0,0 +1,110 @@
1
+ export const dynamic = 'force-dynamic';
2
+
3
+ import { NextRequest, NextResponse } from 'next/server';
4
+ import path from 'path';
5
+ import os from 'os';
6
+ import { copyDir, dirExists } from '@/lib/file-ops';
7
+ import { getMindRoot } from '@/lib/fs';
8
+
9
+ /**
10
+ * Find the source path of a skill from the standard search directories.
11
+ */
12
+ function findSkillSourcePath(skillName: string): string | null {
13
+ const mindRoot = getMindRoot();
14
+ const projectRoot = process.env.MINDOS_PROJECT_ROOT || path.resolve(process.cwd(), '..');
15
+
16
+ // Search in order of priority
17
+ const searchDirs = [
18
+ path.join(projectRoot, 'app', 'data', 'skills', skillName),
19
+ path.join(projectRoot, 'skills', skillName),
20
+ path.join(mindRoot, '.skills', skillName),
21
+ path.join(os.homedir(), '.mindos', 'skills', skillName),
22
+ ];
23
+
24
+ for (const dir of searchDirs) {
25
+ if (dirExists(dir)) {
26
+ return dir;
27
+ }
28
+ }
29
+
30
+ return null;
31
+ }
32
+
33
+ /**
34
+ * POST — Copy a skill to a target agent's skill directory.
35
+ *
36
+ * Request body:
37
+ * {
38
+ * skillName: string; // Name of the skill to copy
39
+ * targetPath: string; // Target directory (e.g., "~/.qclaw/skills/")
40
+ * }
41
+ */
42
+ export async function POST(req: NextRequest) {
43
+ try {
44
+ const body = await req.json();
45
+ const { skillName, targetPath } = body as { skillName?: string; targetPath?: string };
46
+
47
+ if (!skillName?.trim()) {
48
+ return NextResponse.json({ error: 'skillName is required' }, { status: 400 });
49
+ }
50
+
51
+ if (!targetPath?.trim()) {
52
+ return NextResponse.json({ error: 'targetPath is required' }, { status: 400 });
53
+ }
54
+
55
+ // Validate skill name (prevent path traversal)
56
+ if (skillName.includes('/') || skillName.includes('\\') || skillName.includes('..')) {
57
+ return NextResponse.json({ error: 'Invalid skill name' }, { status: 400 });
58
+ }
59
+
60
+ // Validate target path (must be absolute or ~/ and no path traversal)
61
+ const trimmedTarget = targetPath.trim();
62
+ if (trimmedTarget.includes('..')) {
63
+ return NextResponse.json({ error: 'Invalid target path' }, { status: 400 });
64
+ }
65
+ if (!trimmedTarget.startsWith('~/') && !trimmedTarget.startsWith('/')) {
66
+ return NextResponse.json(
67
+ { error: 'Target path must be absolute (starting with / or ~/)' },
68
+ { status: 400 },
69
+ );
70
+ }
71
+
72
+ // Find source skill
73
+ const sourcePath = findSkillSourcePath(skillName);
74
+ if (!sourcePath) {
75
+ return NextResponse.json(
76
+ { error: `Skill "${skillName}" not found` },
77
+ { status: 404 },
78
+ );
79
+ }
80
+
81
+ // Expand target path (support ~/)
82
+ let expandedTargetPath = trimmedTarget.startsWith('~/')
83
+ ? path.join(os.homedir(), trimmedTarget.slice(2))
84
+ : trimmedTarget;
85
+
86
+ // Ensure trailing slash stripped for joining
87
+ expandedTargetPath = expandedTargetPath.replace(/\/$/, '');
88
+ const targetSkillPath = path.join(expandedTargetPath, skillName);
89
+
90
+ // Check target doesn't already exist
91
+ if (dirExists(targetSkillPath)) {
92
+ return NextResponse.json(
93
+ { error: `Skill "${skillName}" already exists in target directory` },
94
+ { status: 409 },
95
+ );
96
+ }
97
+
98
+ // Copy skill
99
+ await copyDir(sourcePath, targetSkillPath);
100
+
101
+ return NextResponse.json({
102
+ success: true,
103
+ skillName,
104
+ targetPath: targetSkillPath,
105
+ });
106
+ } catch (err) {
107
+ const message = err instanceof Error ? err.message : String(err);
108
+ return NextResponse.json({ error: message }, { status: 500 });
109
+ }
110
+ }
@@ -1,7 +1,7 @@
1
1
  export const dynamic = 'force-dynamic';
2
2
 
3
3
  import { NextRequest, NextResponse } from 'next/server';
4
- import { detectBaseDir } from '@/lib/custom-agents';
4
+ import { detectBaseDir, detectCustomAgentProfile } from '@/lib/custom-agents';
5
5
 
6
6
  /** POST — Auto-detect config files in a baseDir. */
7
7
  export async function POST(req: NextRequest) {
@@ -24,6 +24,21 @@ export async function POST(req: NextRequest) {
24
24
  }
25
25
 
26
26
  const result = detectBaseDir(dir);
27
+
28
+ // Enhanced detection: if we detected a config, read detailed MCP and skill info
29
+ if (result.detectedConfig && result.detectedConfigKey) {
30
+ const profile = detectCustomAgentProfile(
31
+ dir,
32
+ result.detectedConfig,
33
+ result.detectedConfigKey
34
+ );
35
+ result.mcpServers = profile.mcpServers;
36
+ result.skillNames = profile.skillNames;
37
+ if (profile.parseError) {
38
+ result.mcpParseError = profile.parseError;
39
+ }
40
+ }
41
+
27
42
  return NextResponse.json(result);
28
43
  } catch (err) {
29
44
  return NextResponse.json({ error: String(err) }, { status: 500 });
@@ -735,11 +735,17 @@ export async function POST(req: NextRequest) {
735
735
  const contextStrategy = agentConfig.contextStrategy ?? 'auto';
736
736
 
737
737
  // Uploaded files — shared by all modes
738
+ // These are already truncated client-side (80K limit), so only apply a generous
739
+ // server-side cap to guard against malformed requests.
740
+ const UPLOADED_FILE_MAX = 100_000;
738
741
  const uploadedParts: string[] = [];
739
742
  if (Array.isArray(uploadedFiles) && uploadedFiles.length > 0) {
740
743
  for (const f of uploadedFiles.slice(0, 8)) {
741
744
  if (!f || typeof f.name !== 'string' || typeof f.content !== 'string') continue;
742
- uploadedParts.push(`### ${f.name}\n\n${truncate(f.content)}`);
745
+ const content = f.content.length > UPLOADED_FILE_MAX
746
+ ? f.content.slice(0, UPLOADED_FILE_MAX) + '\n\n[...truncated]'
747
+ : f.content;
748
+ uploadedParts.push(`### ${f.name}\n\n${content}`);
743
749
  }
744
750
  }
745
751
 
@@ -7,12 +7,15 @@ import os from 'os';
7
7
 
8
8
  export const runtime = 'nodejs';
9
9
 
10
- const MAX_TEXT_CHARS = 30_000;
10
+ const MAX_TEXT_CHARS = 100_000;
11
11
  const MAX_BYTES = 12 * 1024 * 1024; // 12MB
12
12
 
13
- function truncateText(text: string): string {
14
- if (text.length <= MAX_TEXT_CHARS) return text;
15
- return `${text.slice(0, MAX_TEXT_CHARS)}\n\n[...truncated from PDF]`;
13
+ function truncateText(text: string): { result: string; truncated: boolean } {
14
+ if (text.length <= MAX_TEXT_CHARS) return { result: text, truncated: false };
15
+ return {
16
+ result: `${text.slice(0, MAX_TEXT_CHARS)}\n\n[...content truncated — only first ~${Math.round(MAX_TEXT_CHARS / 1000)}K characters included]`,
17
+ truncated: true,
18
+ };
16
19
  }
17
20
 
18
21
  /**
@@ -67,11 +70,15 @@ export async function POST(req: NextRequest) {
67
70
 
68
71
  const { text: rawText, pages } = extractPdf(raw);
69
72
  const text = rawText.replace(/\u0000/g, '').trim();
73
+ const totalChars = text.length;
74
+ const { result: finalText, truncated } = truncateText(text);
70
75
 
71
76
  return NextResponse.json({
72
77
  name,
73
- text: truncateText(text),
78
+ text: finalText,
74
79
  extracted: text.length > 0,
80
+ truncated,
81
+ totalChars,
75
82
  pagesParsed: pages,
76
83
  });
77
84
  } catch (err) {
@@ -13,8 +13,9 @@ import {
13
13
  detectAgentConfiguredMcpServers,
14
14
  detectAgentInstalledSkills,
15
15
  resolveSkillWorkspaceProfile,
16
+ parseJsonc,
16
17
  } from '@/lib/mcp-agents';
17
- import { getAllAgents, loadCustomAgents, scanCustomAgentSkills } from '@/lib/custom-agents';
18
+ import { getAllAgents, loadCustomAgents, scanCustomAgentSkills, toAgentDef } from '@/lib/custom-agents';
18
19
  import { readSettings } from '@/lib/settings';
19
20
  import { scanSkillDirs } from '@/lib/pi-integration/skills';
20
21
  import { getMindRoot } from '@/lib/fs';
@@ -60,6 +61,67 @@ function enrichMindOsAgent(agent: Record<string, unknown>) {
60
61
  agent.hiddenRootPresent = true;
61
62
  }
62
63
 
64
+ /**
65
+ * Detect configured MCP servers for a custom agent.
66
+ */
67
+ function detectCustomAgentConfiguredMcp(
68
+ customDef: Parameters<typeof toAgentDef>[0],
69
+ ): { servers: string[]; sources: string[] } {
70
+ const globalPath = expandHome(customDef.global);
71
+ if (!fs.existsSync(globalPath)) {
72
+ return { servers: [], sources: [] };
73
+ }
74
+
75
+ try {
76
+ const content = fs.readFileSync(globalPath, 'utf-8');
77
+ const config = customDef.format === 'toml'
78
+ ? parseTomlForServers(content, customDef.configKey)
79
+ : parseJsonForServers(content, customDef.configKey);
80
+ return {
81
+ servers: config,
82
+ sources: config.length > 0 ? [`local:${globalPath}`] : [],
83
+ };
84
+ } catch {
85
+ return { servers: [], sources: [] };
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Parse JSON config for MCP servers.
91
+ */
92
+ function parseJsonForServers(content: string, key: string): string[] {
93
+ try {
94
+ const config = parseJsonc(content);
95
+ const servers = config[key];
96
+ if (servers && typeof servers === 'object') {
97
+ return Object.keys(servers).sort();
98
+ }
99
+ } catch {}
100
+ return [];
101
+ }
102
+
103
+ /**
104
+ * Parse TOML config for MCP servers.
105
+ */
106
+ function parseTomlForServers(content: string, sectionKey: string): string[] {
107
+ const names = new Set<string>();
108
+ const lines = content.split('\n');
109
+ const sectionPrefix = `${sectionKey}.`;
110
+
111
+ for (const line of lines) {
112
+ const trimmed = line.trim();
113
+ if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
114
+ const section = trimmed.slice(1, -1).trim();
115
+ if (section.startsWith(sectionPrefix)) {
116
+ const name = section.slice(sectionPrefix.length).split('.')[0];
117
+ if (name) names.add(name);
118
+ }
119
+ }
120
+ }
121
+
122
+ return [...names].sort();
123
+ }
124
+
63
125
  export async function GET() {
64
126
  try {
65
127
  const allAgents = getAllAgents();
@@ -112,7 +174,7 @@ export async function GET() {
112
174
  ? { hiddenRootPath: '', hiddenRootPresent: false, conversationSignal: false, usageSignal: false, lastActivityAt: undefined }
113
175
  : detectAgentRuntimeSignals(key);
114
176
  const configuredMcp = isCustom
115
- ? { servers: [] as string[], sources: [] as string[] }
177
+ ? detectCustomAgentConfiguredMcp(customByKey[key])
116
178
  : detectAgentConfiguredMcpServers(key);
117
179
  const installedSkills = isCustom
118
180
  ? scanCustomAgentSkills(customByKey[key])
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { Sparkles } from 'lucide-react';
4
4
  import { useLocale } from '@/lib/stores/locale-store';
5
+ import { usePathname } from 'next/navigation';
5
6
 
6
7
  interface AskFabProps {
7
8
  /** Toggle the right-side Ask AI panel */
@@ -12,8 +13,13 @@ interface AskFabProps {
12
13
 
13
14
  export default function AskFab({ onToggle, askPanelOpen }: AskFabProps) {
14
15
  const { t } = useLocale();
16
+ const pathname = usePathname();
15
17
  const label = `${t.ask?.fabLabel ?? 'Ask AI'} (⌘/)`;
16
18
 
19
+ // Hide on home page — it already has an inline chatbot
20
+ const isHome = pathname === '/' || pathname === '';
21
+ const hidden = askPanelOpen || isHome;
22
+
17
23
  return (
18
24
  <button
19
25
  onClick={onToggle}
@@ -28,7 +34,7 @@ export default function AskFab({ onToggle, askPanelOpen }: AskFabProps) {
28
34
  transition-all duration-200 ease-out
29
35
  hover:shadow-lg hover:shadow-[var(--amber)]/20
30
36
  active:scale-95 cursor-pointer overflow-hidden
31
- ${askPanelOpen ? 'opacity-0 pointer-events-none translate-y-2' : 'opacity-100 translate-y-0'}
37
+ ${hidden ? 'opacity-0 pointer-events-none translate-y-2' : 'opacity-100 translate-y-0'}
32
38
  `}
33
39
  style={{
34
40
  background: 'var(--amber)',
@@ -12,6 +12,7 @@ import {
12
12
  import { createFileAction, deleteFileAction, renameFileAction, renameSpaceAction, deleteSpaceAction, convertToSpaceAction, deleteFolderAction, undoDeleteAction } from '@/lib/actions';
13
13
  import { toast } from '@/lib/toast';
14
14
  import { useLocale } from '@/lib/stores/locale-store';
15
+ import { quickDropToDirectory } from '@/lib/inbox-upload';
15
16
  import { ConfirmDialog } from '@/components/agents/AgentsPrimitives';
16
17
  import { usePinnedFiles } from '@/lib/hooks/usePinnedFiles';
17
18
  import { checkAiAvailable, triggerSpaceAiInit } from '@/lib/space-ai-init';
@@ -318,6 +319,81 @@ function DirectoryNode({ node, depth, currentPath, onNavigate, maxOpenDepth, onI
318
319
  const [deleteConfirm, setDeleteConfirm] = useState<null | 'space' | 'folder'>(null);
319
320
  const [isPendingDelete, startDeleteTransition] = useTransition();
320
321
 
322
+ // ── External file drop target ──
323
+ const [isDragTarget, setIsDragTarget] = useState(false);
324
+ const autoExpandTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
325
+ const dragLeaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
326
+
327
+ const clearAutoExpand = useCallback(() => {
328
+ if (autoExpandTimerRef.current) {
329
+ clearTimeout(autoExpandTimerRef.current);
330
+ autoExpandTimerRef.current = null;
331
+ }
332
+ }, []);
333
+
334
+ // Use dragOver (fires continuously while hovering) for highlight.
335
+ // Clear highlight with a short delay on dragLeave — if dragOver fires again
336
+ // within the delay, the highlight stays. This avoids flicker from nested elements.
337
+ const handleRowDragOver = useCallback((e: React.DragEvent) => {
338
+ if (!e.dataTransfer.types.includes('Files')) return;
339
+ e.preventDefault();
340
+ e.stopPropagation();
341
+ e.dataTransfer.dropEffect = 'copy';
342
+ if (dragLeaveTimerRef.current) {
343
+ clearTimeout(dragLeaveTimerRef.current);
344
+ dragLeaveTimerRef.current = null;
345
+ }
346
+ if (!isDragTarget) setIsDragTarget(true);
347
+ }, [isDragTarget]);
348
+
349
+ const handleRowDragEnter = useCallback((e: React.DragEvent) => {
350
+ if (!e.dataTransfer.types.includes('Files')) return;
351
+ e.preventDefault();
352
+ e.stopPropagation();
353
+ setIsDragTarget(true);
354
+ // Auto-expand collapsed directory after 500ms hover
355
+ clearAutoExpand();
356
+ if (!open) {
357
+ autoExpandTimerRef.current = setTimeout(() => {
358
+ setOpen(true);
359
+ autoExpandTimerRef.current = null;
360
+ }, 500);
361
+ }
362
+ }, [open, clearAutoExpand]);
363
+
364
+ const handleRowDragLeave = useCallback((e: React.DragEvent) => {
365
+ if (!e.dataTransfer.types.includes('Files')) return;
366
+ e.stopPropagation();
367
+ // Delay clearing so dragOver on the same row can cancel it
368
+ dragLeaveTimerRef.current = setTimeout(() => {
369
+ setIsDragTarget(false);
370
+ clearAutoExpand();
371
+ dragLeaveTimerRef.current = null;
372
+ }, 50);
373
+ }, [clearAutoExpand]);
374
+
375
+ const handleRowDrop = useCallback((e: React.DragEvent) => {
376
+ e.preventDefault();
377
+ e.stopPropagation();
378
+ setIsDragTarget(false);
379
+ clearAutoExpand();
380
+ if (dragLeaveTimerRef.current) {
381
+ clearTimeout(dragLeaveTimerRef.current);
382
+ dragLeaveTimerRef.current = null;
383
+ }
384
+ const files = e.dataTransfer.files;
385
+ if (files.length > 0) {
386
+ void quickDropToDirectory(Array.from(files), node.path, t);
387
+ }
388
+ }, [node.path, t, clearAutoExpand]);
389
+
390
+ useEffect(() => {
391
+ return () => {
392
+ clearAutoExpand();
393
+ if (dragLeaveTimerRef.current) clearTimeout(dragLeaveTimerRef.current);
394
+ };
395
+ }, [clearAutoExpand]);
396
+
321
397
  const toggle = useCallback(() => setOpen(v => !v), []);
322
398
 
323
399
  const prevMaxOpenDepth = useRef<number | null | undefined>(undefined);
@@ -421,8 +497,14 @@ function DirectoryNode({ node, depth, currentPath, onNavigate, maxOpenDepth, onI
421
497
  return (
422
498
  <div>
423
499
  <div
424
- className="relative group/dir flex items-center"
500
+ className={`relative group/dir flex items-center transition-colors duration-100 ${
501
+ isDragTarget ? 'bg-[var(--amber)]/10 rounded-md' : ''
502
+ }`}
425
503
  onContextMenu={handleContextMenu}
504
+ onDragEnter={handleRowDragEnter}
505
+ onDragOver={handleRowDragOver}
506
+ onDragLeave={handleRowDragLeave}
507
+ onDrop={handleRowDrop}
426
508
  >
427
509
  <button
428
510
  onClick={toggle}
@@ -77,13 +77,21 @@ export default function HomeContent({ recent, existingFiles, spaces }: { recent:
77
77
  )}
78
78
 
79
79
  {/* ── Chatbot area: always mounted, layout changes with maximized ── */}
80
- <div className={
81
- maximized
82
- ? 'flex-1 min-h-0 flex flex-col overflow-hidden'
83
- : 'flex-shrink-0 px-4 md:px-6 flex justify-center'
84
- }>
80
+ <div
81
+ className={
82
+ maximized
83
+ ? 'flex-1 min-h-0 flex flex-col overflow-hidden'
84
+ : 'flex-shrink-0 px-4 md:px-6 flex justify-center'
85
+ }
86
+ onDragOver={(e) => { if (e.dataTransfer.types.includes('Files')) { e.preventDefault(); e.stopPropagation(); } }}
87
+ onDragEnter={(e) => { if (e.dataTransfer.types.includes('Files')) { e.stopPropagation(); } }}
88
+ onDrop={(e) => { e.stopPropagation(); }}
89
+ >
85
90
  <div className={maximized ? 'flex-1 min-h-0 flex flex-col overflow-hidden' : 'w-full max-w-4xl'}>
86
- <div className={maximized ? 'flex-1 min-h-0 flex flex-col overflow-hidden' : 'rounded-xl border border-border/50 shadow-sm overflow-hidden flex flex-col max-h-[50vh]'}>
91
+ <div
92
+ data-walkthrough="ask-button"
93
+ className={maximized ? 'flex-1 min-h-0 flex flex-col overflow-hidden' : 'rounded-xl border border-border/70 shadow-sm overflow-hidden flex flex-col max-h-[50vh]'}
94
+ >
87
95
  <AskContent
88
96
  visible={true}
89
97
  variant="home"
@@ -316,7 +316,12 @@ export default function Panel({
316
316
  </div>
317
317
  </div>
318
318
  </PanelHeader>
319
- <div className="flex-1 overflow-y-auto min-h-0 px-2 py-2">
319
+ <div
320
+ className="flex-1 overflow-y-auto min-h-0 px-2 py-2"
321
+ onDragEnter={(e) => { if (e.dataTransfer.types.includes('Files')) e.stopPropagation(); }}
322
+ onDragOver={(e) => { if (e.dataTransfer.types.includes('Files')) { e.preventDefault(); e.stopPropagation(); } }}
323
+ onDrop={(e) => { if (e.dataTransfer.types.includes('Files')) { e.preventDefault(); e.stopPropagation(); } }}
324
+ >
320
325
  <FileTree nodes={fileTree} onNavigate={onNavigate} maxOpenDepth={maxOpenDepth} onImport={onImport} />
321
326
  </div>
322
327
  <SyncStatusBar collapsed={false} onOpenSyncSettings={onOpenSyncSettings} />
@@ -4,7 +4,7 @@ import Link from 'next/link';
4
4
  import { useCallback, useEffect, useMemo, useState } from 'react';
5
5
  import {
6
6
  ArrowLeft, Activity, Globe, Key, Loader2, MoreHorizontal, Pencil, Server, Search,
7
- Shield, ShieldCheck, Trash2, Wifi, WifiOff, Zap,
7
+ Shield, ShieldCheck, Trash2, Wifi, WifiOff, Zap, Copy, AlertTriangle,
8
8
  FileEdit, FilePlus, Clock, Terminal, CheckCircle2, AlertCircle, ChevronDown, BookOpen,
9
9
  } from 'lucide-react';
10
10
  import { useLocale } from '@/lib/stores/locale-store';
@@ -196,6 +196,35 @@ export default function AgentDetailContent({ agentKey }: { agentKey: string }) {
196
196
  }
197
197
  }, [a.detail.skillDeleteSuccess, a.detail.skillDeleteFailed, mcp]);
198
198
 
199
+ const handleCopySkillToAgent = useCallback(async (skillName: string) => {
200
+ if (!agent?.skillWorkspacePath) return;
201
+ setSkillBusy(skillName);
202
+ setEditError(null);
203
+ try {
204
+ const res = await apiFetch<{ success: boolean; targetPath?: string }>(
205
+ '/api/agents/copy-skill',
206
+ {
207
+ method: 'POST',
208
+ headers: { 'Content-Type': 'application/json' },
209
+ body: JSON.stringify({
210
+ skillName,
211
+ targetPath: agent.skillWorkspacePath,
212
+ }),
213
+ }
214
+ );
215
+ if (res.success) {
216
+ toast.success(`Skill "${skillName}" copied to ${agent.name}`);
217
+ await mcp.refresh();
218
+ }
219
+ } catch (err: unknown) {
220
+ const msg = err instanceof Error ? err.message : 'Failed to copy skill';
221
+ setEditError(msg);
222
+ toast.error(msg);
223
+ } finally {
224
+ setSkillBusy(null);
225
+ }
226
+ }, [agent, mcp]);
227
+
199
228
  const handleCopySnippet = useCallback(async () => {
200
229
  const ok = await copyToClipboard(snippet.snippet);
201
230
  if (ok) toast.copy();
@@ -460,6 +489,22 @@ export default function AgentDetailContent({ agentKey }: { agentKey: string }) {
460
489
  </div>
461
490
  )}
462
491
 
492
+ {/* Unsupported Skill Installation Notice (for agents like QClaw, WorkBuddy) */}
493
+ {agent?.skillMode === 'unsupported' && (
494
+ <div className="rounded-lg border border-[var(--amber)]/20 bg-[var(--amber-dim)] p-3 mb-2">
495
+ <p className="text-sm font-medium text-foreground mb-2 flex items-center gap-1.5">
496
+ <AlertTriangle size={14} className="text-[var(--amber)] shrink-0" aria-hidden="true" />
497
+ Manual Skill Installation
498
+ </p>
499
+ <p className="text-xs text-muted-foreground mb-3">
500
+ This agent doesn&apos;t support <code className="bg-background px-1 py-0.5 rounded text-xs font-mono">npx skills</code>. Copy skills manually:
501
+ </p>
502
+ <div className="bg-background rounded-md px-3 py-2 font-mono text-xs overflow-x-auto border border-border/50 select-all">
503
+ cp -r ~/.mindos/skills/&lt;skill-name&gt; {agent.skillWorkspacePath || '~/.agent/skills/'}
504
+ </div>
505
+ </div>
506
+ )}
507
+
463
508
  {/* MindOS Skills */}
464
509
  {filteredSkills.length > 0 && (
465
510
  <div>
@@ -510,6 +555,18 @@ export default function AgentDetailContent({ agentKey }: { agentKey: string }) {
510
555
  </button>
511
556
  </>
512
557
  )}
558
+ {agent?.skillMode === 'unsupported' && (
559
+ <button
560
+ type="button"
561
+ onClick={() => void handleCopySkillToAgent(skill.name)}
562
+ disabled={skillBusy === skill.name}
563
+ className="inline-flex items-center justify-center min-h-[28px] px-1.5 rounded-md text-muted-foreground hover:text-[var(--amber)] cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-150"
564
+ title={`Copy ${skill.name} to ${agent.name}`}
565
+ aria-label={`Copy ${skill.name} to ${agent.name}`}
566
+ >
567
+ <Copy size={13} />
568
+ </button>
569
+ )}
513
570
  </div>
514
571
  </div>
515
572
 
@@ -223,17 +223,7 @@ export default function AgentsOverviewSection({
223
223
  </span>
224
224
  </div>
225
225
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
226
- {sortedAgents.map((agent, i) => (
227
- <AgentCard
228
- key={agent.key}
229
- agent={agent}
230
- copy={copy}
231
- index={i}
232
- mcpEnabled={mcpEnabled}
233
- onEdit={agent.isCustom ? onEditCustomAgent : undefined}
234
- onRemove={agent.isCustom ? onRemoveCustomAgent : undefined}
235
- />
236
- ))}
226
+ {/* Add Custom Agent Button — Always First */}
237
227
  {onAddCustomAgent && (
238
228
  <button
239
229
  type="button"
@@ -254,6 +244,18 @@ export default function AgentsOverviewSection({
254
244
  </span>
255
245
  </button>
256
246
  )}
247
+ {/* Agent Cards */}
248
+ {sortedAgents.map((agent, i) => (
249
+ <AgentCard
250
+ key={agent.key}
251
+ agent={agent}
252
+ copy={copy}
253
+ index={i}
254
+ mcpEnabled={mcpEnabled}
255
+ onEdit={agent.isCustom ? onEditCustomAgent : undefined}
256
+ onRemove={agent.isCustom ? onRemoveCustomAgent : undefined}
257
+ />
258
+ ))}
257
259
  </div>
258
260
  </section>
259
261
  ) : (