@seqyuan/annodex 0.1.10 → 0.1.12

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 (519) hide show
  1. package/app/api/agent/[id]/events/route.ts +94 -0
  2. package/app/api/agent/[id]/route.ts +83 -0
  3. package/app/api/agent/new/route.ts +53 -0
  4. package/app/api/auth/all-providers/route.ts +21 -0
  5. package/app/api/auth/api-key/[provider]/route.ts +7 -0
  6. package/app/api/auth/login/[provider]/route.ts +7 -0
  7. package/app/api/auth/login/route.ts +22 -0
  8. package/app/api/auth/logout/[provider]/route.ts +7 -0
  9. package/app/api/auth/providers/route.ts +15 -0
  10. package/app/api/auth/status/route.ts +6 -0
  11. package/app/api/default-cwd/route.ts +22 -0
  12. package/app/api/files/[...path]/route.ts +621 -0
  13. package/app/api/harness/route.ts +47 -0
  14. package/app/api/home/route.ts +6 -0
  15. package/app/api/internal/runtime/route.ts +26 -0
  16. package/app/api/models/route.ts +67 -0
  17. package/app/api/models-config/discover/route.ts +42 -0
  18. package/app/api/models-config/route.ts +152 -0
  19. package/app/api/models-config/test/route.ts +154 -0
  20. package/app/api/projects/browse/route.ts +51 -0
  21. package/app/api/projects/route.ts +83 -0
  22. package/app/api/reports/[id]/route.ts +108 -0
  23. package/app/api/search/route.ts +122 -0
  24. package/app/api/sessions/[id]/context/route.ts +23 -0
  25. package/app/api/sessions/[id]/route.ts +124 -0
  26. package/app/api/sessions/new/route.ts +5 -0
  27. package/app/api/sessions/route.ts +16 -0
  28. package/app/api/settings/route.ts +51 -0
  29. package/app/api/skills/install/route.ts +249 -0
  30. package/app/api/skills/route.ts +161 -0
  31. package/app/api/skills/search/route.ts +121 -0
  32. package/app/api/soul/route.ts +47 -0
  33. package/app/api/version/route.ts +55 -0
  34. package/app/globals.css +736 -0
  35. package/app/layout.tsx +40 -0
  36. package/app/login/page.tsx +133 -0
  37. package/app/page.tsx +10 -0
  38. package/components/AppShell.tsx +1058 -0
  39. package/components/ChatInput.tsx +1103 -0
  40. package/components/ChatMinimap.tsx +381 -0
  41. package/components/ChatWindow.tsx +576 -0
  42. package/components/CodeMirrorEditor.tsx +137 -0
  43. package/components/ConversationSearch.tsx +369 -0
  44. package/components/DataTableViewer.tsx +248 -0
  45. package/components/FileExplorer.tsx +758 -0
  46. package/components/FileIcons.tsx +241 -0
  47. package/components/FileViewer.tsx +1273 -0
  48. package/components/GlobalFileEditor.tsx +98 -0
  49. package/components/MarkdownRenderer.tsx +331 -0
  50. package/components/MermaidDiagram.tsx +80 -0
  51. package/components/MessageView.tsx +1141 -0
  52. package/components/ModelsConfig.tsx +1991 -0
  53. package/components/ProjectContext.tsx +252 -0
  54. package/components/ProjectFolderPicker.tsx +202 -0
  55. package/components/ProjectsConfig.tsx +288 -0
  56. package/components/ProviderIcons.tsx +91 -0
  57. package/components/ReportPanel.tsx +237 -0
  58. package/components/ResizeHandle.tsx +105 -0
  59. package/components/SessionSidebar.tsx +1464 -0
  60. package/components/SettingsDialog.tsx +287 -0
  61. package/components/SkillsConfig.tsx +1093 -0
  62. package/components/SubagentPanel.tsx +191 -0
  63. package/components/TabBar.tsx +115 -0
  64. package/components/ToolPanel.tsx +131 -0
  65. package/components/WidgetRenderer.tsx +505 -0
  66. package/components/viewers/DocumentToolbar.tsx +78 -0
  67. package/components/viewers/DocxViewer.tsx +97 -0
  68. package/components/viewers/PdfViewer.tsx +206 -0
  69. package/components/viewers/PptxViewer.tsx +240 -0
  70. package/components/viewers/XlsxViewer.tsx +143 -0
  71. package/hooks/useAgentSession.ts +710 -0
  72. package/hooks/useAudio.ts +50 -0
  73. package/hooks/useDragDrop.ts +52 -0
  74. package/hooks/useResizable.ts +60 -0
  75. package/hooks/useTheme.ts +85 -0
  76. package/lib/agent-client.ts +39 -0
  77. package/lib/annodex-config.ts +556 -0
  78. package/lib/auth-token.ts +74 -0
  79. package/lib/auth.ts +90 -0
  80. package/lib/brand.ts +5 -0
  81. package/lib/code-theme.ts +32 -0
  82. package/lib/codex-compat-proxy.ts +1603 -0
  83. package/lib/codex-home.ts +6 -0
  84. package/lib/codex-server.ts +796 -0
  85. package/lib/codex-session.ts +590 -0
  86. package/lib/codex-usage.ts +213 -0
  87. package/lib/file-paths.ts +34 -0
  88. package/lib/model-discovery.ts +379 -0
  89. package/lib/normalize.ts +30 -0
  90. package/lib/npx.ts +87 -0
  91. package/lib/pi-types.ts +49 -0
  92. package/lib/projects.ts +269 -0
  93. package/lib/provider-api.ts +88 -0
  94. package/lib/report-prompt.ts +61 -0
  95. package/lib/report-store.ts +597 -0
  96. package/lib/report-update-parser.ts +66 -0
  97. package/lib/rpc-manager.ts +668 -0
  98. package/lib/runtime-state.ts +117 -0
  99. package/lib/session-reader.ts +903 -0
  100. package/lib/session-runtime.ts +105 -0
  101. package/lib/subagent-progress.ts +279 -0
  102. package/lib/types.ts +241 -0
  103. package/lib/widget-export.ts +318 -0
  104. package/lib/widget-guidelines.ts +288 -0
  105. package/lib/widget-prompt.ts +76 -0
  106. package/lib/widget-utils.ts +523 -0
  107. package/package.json +23 -18
  108. package/postcss.config.mjs +8 -0
  109. package/proxy.ts +64 -0
  110. package/scripts/postinstall.cjs +25 -0
  111. package/tsconfig.json +41 -0
  112. package/.next/BUILD_ID +0 -1
  113. package/.next/app-path-routes-manifest.json +0 -39
  114. package/.next/build-manifest.json +0 -20
  115. package/.next/diagnostics/build-diagnostics.json +0 -6
  116. package/.next/diagnostics/framework.json +0 -1
  117. package/.next/export-marker.json +0 -6
  118. package/.next/images-manifest.json +0 -68
  119. package/.next/next-minimal-server.js.nft.json +0 -1
  120. package/.next/next-server.js.nft.json +0 -1
  121. package/.next/package.json +0 -1
  122. package/.next/prerender-manifest.json +0 -109
  123. package/.next/react-loadable-manifest.json +0 -2320
  124. package/.next/required-server-files.js +0 -343
  125. package/.next/required-server-files.json +0 -343
  126. package/.next/routes-manifest.json +0 -286
  127. package/.next/server/app/_global-error/page.js +0 -32
  128. package/.next/server/app/_global-error/page.js.nft.json +0 -1
  129. package/.next/server/app/_global-error/page_client-reference-manifest.js +0 -1
  130. package/.next/server/app/_global-error.html +0 -1
  131. package/.next/server/app/_global-error.meta +0 -16
  132. package/.next/server/app/_global-error.rsc +0 -14
  133. package/.next/server/app/_global-error.segments/_full.segment.rsc +0 -14
  134. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +0 -5
  135. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +0 -5
  136. package/.next/server/app/_global-error.segments/_head.segment.rsc +0 -5
  137. package/.next/server/app/_global-error.segments/_index.segment.rsc +0 -5
  138. package/.next/server/app/_global-error.segments/_tree.segment.rsc +0 -1
  139. package/.next/server/app/_not-found/page.js +0 -2
  140. package/.next/server/app/_not-found/page.js.nft.json +0 -1
  141. package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  142. package/.next/server/app/_not-found.html +0 -1
  143. package/.next/server/app/_not-found.meta +0 -16
  144. package/.next/server/app/_not-found.rsc +0 -18
  145. package/.next/server/app/_not-found.segments/_full.segment.rsc +0 -18
  146. package/.next/server/app/_not-found.segments/_head.segment.rsc +0 -6
  147. package/.next/server/app/_not-found.segments/_index.segment.rsc +0 -5
  148. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +0 -5
  149. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +0 -5
  150. package/.next/server/app/_not-found.segments/_tree.segment.rsc +0 -4
  151. package/.next/server/app/api/agent/[id]/events/route.js +0 -3
  152. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +0 -1
  153. package/.next/server/app/api/agent/[id]/events/route_client-reference-manifest.js +0 -1
  154. package/.next/server/app/api/agent/[id]/route.js +0 -1
  155. package/.next/server/app/api/agent/[id]/route.js.nft.json +0 -1
  156. package/.next/server/app/api/agent/[id]/route_client-reference-manifest.js +0 -1
  157. package/.next/server/app/api/agent/new/route.js +0 -1
  158. package/.next/server/app/api/agent/new/route.js.nft.json +0 -1
  159. package/.next/server/app/api/agent/new/route_client-reference-manifest.js +0 -1
  160. package/.next/server/app/api/auth/all-providers/route.js +0 -1
  161. package/.next/server/app/api/auth/all-providers/route.js.nft.json +0 -1
  162. package/.next/server/app/api/auth/all-providers/route_client-reference-manifest.js +0 -1
  163. package/.next/server/app/api/auth/api-key/[provider]/route.js +0 -1
  164. package/.next/server/app/api/auth/api-key/[provider]/route.js.nft.json +0 -1
  165. package/.next/server/app/api/auth/api-key/[provider]/route_client-reference-manifest.js +0 -1
  166. package/.next/server/app/api/auth/login/[provider]/route.js +0 -1
  167. package/.next/server/app/api/auth/login/[provider]/route.js.nft.json +0 -1
  168. package/.next/server/app/api/auth/login/[provider]/route_client-reference-manifest.js +0 -1
  169. package/.next/server/app/api/auth/login/route.js +0 -1
  170. package/.next/server/app/api/auth/login/route.js.nft.json +0 -1
  171. package/.next/server/app/api/auth/login/route_client-reference-manifest.js +0 -1
  172. package/.next/server/app/api/auth/logout/[provider]/route.js +0 -1
  173. package/.next/server/app/api/auth/logout/[provider]/route.js.nft.json +0 -1
  174. package/.next/server/app/api/auth/logout/[provider]/route_client-reference-manifest.js +0 -1
  175. package/.next/server/app/api/auth/providers/route.js +0 -1
  176. package/.next/server/app/api/auth/providers/route.js.nft.json +0 -1
  177. package/.next/server/app/api/auth/providers/route_client-reference-manifest.js +0 -1
  178. package/.next/server/app/api/auth/status/route.js +0 -1
  179. package/.next/server/app/api/auth/status/route.js.nft.json +0 -1
  180. package/.next/server/app/api/auth/status/route_client-reference-manifest.js +0 -1
  181. package/.next/server/app/api/default-cwd/route.js +0 -1
  182. package/.next/server/app/api/default-cwd/route.js.nft.json +0 -1
  183. package/.next/server/app/api/default-cwd/route_client-reference-manifest.js +0 -1
  184. package/.next/server/app/api/files/[...path]/route.js +0 -4
  185. package/.next/server/app/api/files/[...path]/route.js.nft.json +0 -1
  186. package/.next/server/app/api/files/[...path]/route_client-reference-manifest.js +0 -1
  187. package/.next/server/app/api/harness/route.js +0 -1
  188. package/.next/server/app/api/harness/route.js.nft.json +0 -1
  189. package/.next/server/app/api/harness/route_client-reference-manifest.js +0 -1
  190. package/.next/server/app/api/home/route.js +0 -1
  191. package/.next/server/app/api/home/route.js.nft.json +0 -1
  192. package/.next/server/app/api/home/route_client-reference-manifest.js +0 -1
  193. package/.next/server/app/api/internal/runtime/route.js +0 -1
  194. package/.next/server/app/api/internal/runtime/route.js.nft.json +0 -1
  195. package/.next/server/app/api/internal/runtime/route_client-reference-manifest.js +0 -1
  196. package/.next/server/app/api/models/route.js +0 -1
  197. package/.next/server/app/api/models/route.js.nft.json +0 -1
  198. package/.next/server/app/api/models/route_client-reference-manifest.js +0 -1
  199. package/.next/server/app/api/models-config/discover/route.js +0 -1
  200. package/.next/server/app/api/models-config/discover/route.js.nft.json +0 -1
  201. package/.next/server/app/api/models-config/discover/route_client-reference-manifest.js +0 -1
  202. package/.next/server/app/api/models-config/route.js +0 -1
  203. package/.next/server/app/api/models-config/route.js.nft.json +0 -1
  204. package/.next/server/app/api/models-config/route_client-reference-manifest.js +0 -1
  205. package/.next/server/app/api/models-config/test/route.js +0 -1
  206. package/.next/server/app/api/models-config/test/route.js.nft.json +0 -1
  207. package/.next/server/app/api/models-config/test/route_client-reference-manifest.js +0 -1
  208. package/.next/server/app/api/projects/browse/route.js +0 -1
  209. package/.next/server/app/api/projects/browse/route.js.nft.json +0 -1
  210. package/.next/server/app/api/projects/browse/route_client-reference-manifest.js +0 -1
  211. package/.next/server/app/api/projects/route.js +0 -1
  212. package/.next/server/app/api/projects/route.js.nft.json +0 -1
  213. package/.next/server/app/api/projects/route_client-reference-manifest.js +0 -1
  214. package/.next/server/app/api/reports/[id]/route.js +0 -10
  215. package/.next/server/app/api/reports/[id]/route.js.nft.json +0 -1
  216. package/.next/server/app/api/reports/[id]/route_client-reference-manifest.js +0 -1
  217. package/.next/server/app/api/search/route.js +0 -1
  218. package/.next/server/app/api/search/route.js.nft.json +0 -1
  219. package/.next/server/app/api/search/route_client-reference-manifest.js +0 -1
  220. package/.next/server/app/api/sessions/[id]/context/route.js +0 -1
  221. package/.next/server/app/api/sessions/[id]/context/route.js.nft.json +0 -1
  222. package/.next/server/app/api/sessions/[id]/context/route_client-reference-manifest.js +0 -1
  223. package/.next/server/app/api/sessions/[id]/route.js +0 -1
  224. package/.next/server/app/api/sessions/[id]/route.js.nft.json +0 -1
  225. package/.next/server/app/api/sessions/[id]/route_client-reference-manifest.js +0 -1
  226. package/.next/server/app/api/sessions/new/route.js +0 -1
  227. package/.next/server/app/api/sessions/new/route.js.nft.json +0 -1
  228. package/.next/server/app/api/sessions/new/route_client-reference-manifest.js +0 -1
  229. package/.next/server/app/api/sessions/route.js +0 -1
  230. package/.next/server/app/api/sessions/route.js.nft.json +0 -1
  231. package/.next/server/app/api/sessions/route_client-reference-manifest.js +0 -1
  232. package/.next/server/app/api/settings/route.js +0 -1
  233. package/.next/server/app/api/settings/route.js.nft.json +0 -1
  234. package/.next/server/app/api/settings/route_client-reference-manifest.js +0 -1
  235. package/.next/server/app/api/skills/install/route.js +0 -5
  236. package/.next/server/app/api/skills/install/route.js.nft.json +0 -1
  237. package/.next/server/app/api/skills/install/route_client-reference-manifest.js +0 -1
  238. package/.next/server/app/api/skills/route.js +0 -6
  239. package/.next/server/app/api/skills/route.js.nft.json +0 -1
  240. package/.next/server/app/api/skills/route_client-reference-manifest.js +0 -1
  241. package/.next/server/app/api/skills/search/route.js +0 -1
  242. package/.next/server/app/api/skills/search/route.js.nft.json +0 -1
  243. package/.next/server/app/api/skills/search/route_client-reference-manifest.js +0 -1
  244. package/.next/server/app/api/soul/route.js +0 -1
  245. package/.next/server/app/api/soul/route.js.nft.json +0 -1
  246. package/.next/server/app/api/soul/route_client-reference-manifest.js +0 -1
  247. package/.next/server/app/api/version/route.js +0 -1
  248. package/.next/server/app/api/version/route.js.nft.json +0 -1
  249. package/.next/server/app/api/version/route_client-reference-manifest.js +0 -1
  250. package/.next/server/app/index.html +0 -1
  251. package/.next/server/app/index.meta +0 -14
  252. package/.next/server/app/index.rsc +0 -17
  253. package/.next/server/app/index.segments/__PAGE__.segment.rsc +0 -6
  254. package/.next/server/app/index.segments/_full.segment.rsc +0 -17
  255. package/.next/server/app/index.segments/_head.segment.rsc +0 -6
  256. package/.next/server/app/index.segments/_index.segment.rsc +0 -5
  257. package/.next/server/app/index.segments/_tree.segment.rsc +0 -4
  258. package/.next/server/app/login/page.js +0 -2
  259. package/.next/server/app/login/page.js.nft.json +0 -1
  260. package/.next/server/app/login/page_client-reference-manifest.js +0 -1
  261. package/.next/server/app/login.html +0 -1
  262. package/.next/server/app/login.meta +0 -15
  263. package/.next/server/app/login.rsc +0 -22
  264. package/.next/server/app/login.segments/_full.segment.rsc +0 -22
  265. package/.next/server/app/login.segments/_head.segment.rsc +0 -6
  266. package/.next/server/app/login.segments/_index.segment.rsc +0 -5
  267. package/.next/server/app/login.segments/_tree.segment.rsc +0 -4
  268. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +0 -9
  269. package/.next/server/app/login.segments/login.segment.rsc +0 -5
  270. package/.next/server/app/page.js +0 -261
  271. package/.next/server/app/page.js.nft.json +0 -1
  272. package/.next/server/app/page_client-reference-manifest.js +0 -1
  273. package/.next/server/app-paths-manifest.json +0 -39
  274. package/.next/server/chunks/1048.js +0 -1
  275. package/.next/server/chunks/1367.js +0 -77
  276. package/.next/server/chunks/1381.js +0 -1
  277. package/.next/server/chunks/165.js +0 -1
  278. package/.next/server/chunks/1681.js +0 -215
  279. package/.next/server/chunks/1688.js +0 -45
  280. package/.next/server/chunks/1703.js +0 -79
  281. package/.next/server/chunks/1712.js +0 -43
  282. package/.next/server/chunks/1813.js +0 -1
  283. package/.next/server/chunks/2325.js +0 -80
  284. package/.next/server/chunks/258.js +0 -1
  285. package/.next/server/chunks/2671.js +0 -287
  286. package/.next/server/chunks/2778.js +0 -1
  287. package/.next/server/chunks/2943.js +0 -1
  288. package/.next/server/chunks/3031.js +0 -226
  289. package/.next/server/chunks/3181.js +0 -1
  290. package/.next/server/chunks/3493.js +0 -1
  291. package/.next/server/chunks/3672.js +0 -1
  292. package/.next/server/chunks/3701.js +0 -104
  293. package/.next/server/chunks/4013.js +0 -1
  294. package/.next/server/chunks/402.js +0 -2
  295. package/.next/server/chunks/4035.js +0 -80
  296. package/.next/server/chunks/4248.js +0 -153
  297. package/.next/server/chunks/4367.js +0 -1
  298. package/.next/server/chunks/4406.js +0 -141
  299. package/.next/server/chunks/4741.js +0 -18
  300. package/.next/server/chunks/4768.js +0 -1
  301. package/.next/server/chunks/4858.js +0 -148
  302. package/.next/server/chunks/4980.js +0 -1
  303. package/.next/server/chunks/5155.js +0 -5
  304. package/.next/server/chunks/5293.js +0 -166
  305. package/.next/server/chunks/5399.js +0 -8
  306. package/.next/server/chunks/5409.js +0 -1
  307. package/.next/server/chunks/5797.js +0 -93
  308. package/.next/server/chunks/5851.js +0 -36
  309. package/.next/server/chunks/6206.js +0 -1
  310. package/.next/server/chunks/6296.js +0 -1
  311. package/.next/server/chunks/63.js +0 -45
  312. package/.next/server/chunks/6346.js +0 -1
  313. package/.next/server/chunks/6406.js +0 -23
  314. package/.next/server/chunks/642.js +0 -1
  315. package/.next/server/chunks/6429.js +0 -50
  316. package/.next/server/chunks/6729.js +0 -64
  317. package/.next/server/chunks/6907.js +0 -115
  318. package/.next/server/chunks/6980.js +0 -1
  319. package/.next/server/chunks/7073.js +0 -24
  320. package/.next/server/chunks/7233.js +0 -24
  321. package/.next/server/chunks/7307.js +0 -1
  322. package/.next/server/chunks/7362.js +0 -9
  323. package/.next/server/chunks/7567.js +0 -29
  324. package/.next/server/chunks/7765.js +0 -1
  325. package/.next/server/chunks/7890.js +0 -1
  326. package/.next/server/chunks/8065.js +0 -1
  327. package/.next/server/chunks/8238.js +0 -34
  328. package/.next/server/chunks/8276.js +0 -1
  329. package/.next/server/chunks/8336.js +0 -1
  330. package/.next/server/chunks/8477.js +0 -3
  331. package/.next/server/chunks/8490.js +0 -1
  332. package/.next/server/chunks/8916.js +0 -1
  333. package/.next/server/chunks/9280.js +0 -252
  334. package/.next/server/chunks/9315.js +0 -1
  335. package/.next/server/chunks/9537.js +0 -90
  336. package/.next/server/chunks/966.js +0 -1
  337. package/.next/server/chunks/9818.js +0 -21
  338. package/.next/server/chunks/static/media/pdf.worker.min.c476e1a0.mjs +0 -6
  339. package/.next/server/functions-config-manifest.json +0 -16
  340. package/.next/server/interception-route-rewrite-manifest.js +0 -1
  341. package/.next/server/middleware-build-manifest.js +0 -1
  342. package/.next/server/middleware-manifest.json +0 -6
  343. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  344. package/.next/server/middleware.js +0 -18
  345. package/.next/server/middleware.js.nft.json +0 -1
  346. package/.next/server/next-font-manifest.js +0 -1
  347. package/.next/server/next-font-manifest.json +0 -1
  348. package/.next/server/pages/404.html +0 -1
  349. package/.next/server/pages/500.html +0 -1
  350. package/.next/server/pages-manifest.json +0 -4
  351. package/.next/server/prefetch-hints.json +0 -1
  352. package/.next/server/server-reference-manifest.js +0 -1
  353. package/.next/server/server-reference-manifest.json +0 -1
  354. package/.next/server/webpack-runtime.js +0 -1
  355. package/.next/static/6cuMSvcr0FVO-GiK5RJZh/_buildManifest.js +0 -1
  356. package/.next/static/6cuMSvcr0FVO-GiK5RJZh/_ssgManifest.js +0 -1
  357. package/.next/static/chunks/0b9a0da7.9075af772487e743.js +0 -62
  358. package/.next/static/chunks/1413.922d232de90c0c41.js +0 -115
  359. package/.next/static/chunks/1643.467a526a1f24f54d.js +0 -24
  360. package/.next/static/chunks/1852.5543122f11aa7fed.js +0 -1
  361. package/.next/static/chunks/1960.b1e26436d7a5f586.js +0 -1
  362. package/.next/static/chunks/2170a4aa.4213bb2183c9cdf9.js +0 -1
  363. package/.next/static/chunks/2274.6cd173f80a1405a2.js +0 -21
  364. package/.next/static/chunks/2419.347fdfe3c170854d.js +0 -166
  365. package/.next/static/chunks/2619.9aac8983f30c7c8a.js +0 -1
  366. package/.next/static/chunks/2623.d20fabd8e18197c6.js +0 -287
  367. package/.next/static/chunks/2729.f5365061a849d659.js +0 -34
  368. package/.next/static/chunks/2821.934bcf60fbdc28c6.js +0 -1
  369. package/.next/static/chunks/2918becc.abff2ece1de37bc1.js +0 -153
  370. package/.next/static/chunks/2947.114e51cb06d1c01a.js +0 -23
  371. package/.next/static/chunks/3079.4c511fa1144e3adf.js +0 -79
  372. package/.next/static/chunks/3274.208ca44844cd7d95.js +0 -148
  373. package/.next/static/chunks/3308.465a94263d04bfea.js +0 -73
  374. package/.next/static/chunks/3325.e4bfe1ca657f3b5b.js +0 -80
  375. package/.next/static/chunks/3506.2a7eaa08b9f55337.js +0 -90
  376. package/.next/static/chunks/363642f4-043c1475ab9af70e.js +0 -1
  377. package/.next/static/chunks/3794-123fdf632563f469.js +0 -32
  378. package/.next/static/chunks/3837.a755ccfe6f9c1c1c.js +0 -5
  379. package/.next/static/chunks/394.91597771688df6d0.js +0 -1
  380. package/.next/static/chunks/3997.1009c06025691712.js +0 -1
  381. package/.next/static/chunks/4453.91a357dc43c21745.js +0 -1
  382. package/.next/static/chunks/4491.44fdf20580ac72bd.js +0 -24
  383. package/.next/static/chunks/4829.cf1d50e43e6d9db5.js +0 -1
  384. package/.next/static/chunks/498.fe1d9da9ecad6c36.js +0 -1
  385. package/.next/static/chunks/4bd1b696-e356ca5ba0218e27.js +0 -1
  386. package/.next/static/chunks/5019.b5a1a2b8daf17525.js +0 -1
  387. package/.next/static/chunks/5034.8f16c3fa3ce75411.js +0 -1
  388. package/.next/static/chunks/5074.d16651da01ec4e02.js +0 -1
  389. package/.next/static/chunks/51fb665c.0950e1b79671348d.js +0 -45
  390. package/.next/static/chunks/532.5956ed631aff722b.js +0 -9
  391. package/.next/static/chunks/5326.69460442bdcd6cd3.js +0 -1
  392. package/.next/static/chunks/5403.ff110bf5bf600758.js +0 -64
  393. package/.next/static/chunks/547.902a733488cfe3f7.js +0 -77
  394. package/.next/static/chunks/5567.540d7fc108ad6ee5.js +0 -215
  395. package/.next/static/chunks/5590.ef62922166d308b4.js +0 -1
  396. package/.next/static/chunks/5690.9d6eb1edb1399995.js +0 -1
  397. package/.next/static/chunks/5749.25faee4a1e55b854.js +0 -226
  398. package/.next/static/chunks/58bb9007.1ccb6bba34b4c635.js +0 -80
  399. package/.next/static/chunks/6121.f3f43f1896ea0cd9.js +0 -1
  400. package/.next/static/chunks/6600.583c88eef37aa524.js +0 -1
  401. package/.next/static/chunks/6696.a41aec266e657d54.js +0 -141
  402. package/.next/static/chunks/6922.42148793782d2fe7.js +0 -1
  403. package/.next/static/chunks/7006.e191611ffc2b9528.js +0 -43
  404. package/.next/static/chunks/7343.9fbb58204d8ac681.js +0 -1
  405. package/.next/static/chunks/73972abe.25a4cffa03b2bcef.js +0 -119
  406. package/.next/static/chunks/7547.58bda8a2aabba0d4.js +0 -93
  407. package/.next/static/chunks/7648.4ae2f183b4db0353.js +0 -1
  408. package/.next/static/chunks/7874.8db6929b94cdf697.js +0 -1
  409. package/.next/static/chunks/7959.1f20a35df316216a.js +0 -104
  410. package/.next/static/chunks/83.85d62d7fc9850b75.js +0 -29
  411. package/.next/static/chunks/8436.cab94b59cca0a8ff.js +0 -1
  412. package/.next/static/chunks/8451.ff6ff72b57dc52e1.js +0 -1
  413. package/.next/static/chunks/8489.45f22859734f514f.js +0 -36
  414. package/.next/static/chunks/8568.f85d8b36fc9a9037.js +0 -1
  415. package/.next/static/chunks/8771-3e14b6810486df1f.js +0 -1
  416. package/.next/static/chunks/8863.be51033a67436277.js +0 -1
  417. package/.next/static/chunks/90542734.dc1a2723e4f6affb.js +0 -1
  418. package/.next/static/chunks/9500.1488aec06ee78127.js +0 -1
  419. package/.next/static/chunks/9633.155548b5fca6e580.js +0 -1
  420. package/.next/static/chunks/9779.673004a62d70e36a.js +0 -1
  421. package/.next/static/chunks/app/_global-error/page-cc518af6b1ffb191.js +0 -1
  422. package/.next/static/chunks/app/_not-found/page-c72daab99269beff.js +0 -1
  423. package/.next/static/chunks/app/api/agent/[id]/events/route-cc518af6b1ffb191.js +0 -1
  424. package/.next/static/chunks/app/api/agent/[id]/route-cc518af6b1ffb191.js +0 -1
  425. package/.next/static/chunks/app/api/agent/new/route-cc518af6b1ffb191.js +0 -1
  426. package/.next/static/chunks/app/api/auth/all-providers/route-cc518af6b1ffb191.js +0 -1
  427. package/.next/static/chunks/app/api/auth/api-key/[provider]/route-cc518af6b1ffb191.js +0 -1
  428. package/.next/static/chunks/app/api/auth/login/[provider]/route-cc518af6b1ffb191.js +0 -1
  429. package/.next/static/chunks/app/api/auth/login/route-cc518af6b1ffb191.js +0 -1
  430. package/.next/static/chunks/app/api/auth/logout/[provider]/route-cc518af6b1ffb191.js +0 -1
  431. package/.next/static/chunks/app/api/auth/providers/route-cc518af6b1ffb191.js +0 -1
  432. package/.next/static/chunks/app/api/auth/status/route-cc518af6b1ffb191.js +0 -1
  433. package/.next/static/chunks/app/api/default-cwd/route-cc518af6b1ffb191.js +0 -1
  434. package/.next/static/chunks/app/api/files/[...path]/route-cc518af6b1ffb191.js +0 -1
  435. package/.next/static/chunks/app/api/harness/route-cc518af6b1ffb191.js +0 -1
  436. package/.next/static/chunks/app/api/home/route-cc518af6b1ffb191.js +0 -1
  437. package/.next/static/chunks/app/api/internal/runtime/route-cc518af6b1ffb191.js +0 -1
  438. package/.next/static/chunks/app/api/models/route-cc518af6b1ffb191.js +0 -1
  439. package/.next/static/chunks/app/api/models-config/discover/route-cc518af6b1ffb191.js +0 -1
  440. package/.next/static/chunks/app/api/models-config/route-cc518af6b1ffb191.js +0 -1
  441. package/.next/static/chunks/app/api/models-config/test/route-cc518af6b1ffb191.js +0 -1
  442. package/.next/static/chunks/app/api/projects/browse/route-cc518af6b1ffb191.js +0 -1
  443. package/.next/static/chunks/app/api/projects/route-cc518af6b1ffb191.js +0 -1
  444. package/.next/static/chunks/app/api/reports/[id]/route-cc518af6b1ffb191.js +0 -1
  445. package/.next/static/chunks/app/api/search/route-cc518af6b1ffb191.js +0 -1
  446. package/.next/static/chunks/app/api/sessions/[id]/context/route-cc518af6b1ffb191.js +0 -1
  447. package/.next/static/chunks/app/api/sessions/[id]/route-cc518af6b1ffb191.js +0 -1
  448. package/.next/static/chunks/app/api/sessions/new/route-cc518af6b1ffb191.js +0 -1
  449. package/.next/static/chunks/app/api/sessions/route-cc518af6b1ffb191.js +0 -1
  450. package/.next/static/chunks/app/api/settings/route-cc518af6b1ffb191.js +0 -1
  451. package/.next/static/chunks/app/api/skills/install/route-cc518af6b1ffb191.js +0 -1
  452. package/.next/static/chunks/app/api/skills/route-cc518af6b1ffb191.js +0 -1
  453. package/.next/static/chunks/app/api/skills/search/route-cc518af6b1ffb191.js +0 -1
  454. package/.next/static/chunks/app/api/soul/route-cc518af6b1ffb191.js +0 -1
  455. package/.next/static/chunks/app/api/version/route-cc518af6b1ffb191.js +0 -1
  456. package/.next/static/chunks/app/layout-be148b7ae915b22a.js +0 -1
  457. package/.next/static/chunks/app/login/page-ebf0e6de99062783.js +0 -1
  458. package/.next/static/chunks/app/page-c45d98ea81c548ca.js +0 -260
  459. package/.next/static/chunks/d3ac728e.7964f816a1ca64e5.js +0 -1
  460. package/.next/static/chunks/framework-711ef29bc66f648c.js +0 -1
  461. package/.next/static/chunks/main-app-45a0f19af99d61b6.js +0 -1
  462. package/.next/static/chunks/main-f74964b7ae52493e.js +0 -5
  463. package/.next/static/chunks/next/dist/client/components/builtin/app-error-cc518af6b1ffb191.js +0 -1
  464. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-cc518af6b1ffb191.js +0 -1
  465. package/.next/static/chunks/next/dist/client/components/builtin/global-error-9bfa08b9491621f2.js +0 -1
  466. package/.next/static/chunks/next/dist/client/components/builtin/not-found-cc518af6b1ffb191.js +0 -1
  467. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-cc518af6b1ffb191.js +0 -1
  468. package/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  469. package/.next/static/chunks/webpack-fcf4a889ecbd753c.js +0 -1
  470. package/.next/static/css/45029451a1d7255d.css +0 -3
  471. package/.next/static/media/15605e25b523335c-s.woff2 +0 -0
  472. package/.next/static/media/1a3dce5cfb5f7760-s.woff2 +0 -0
  473. package/.next/static/media/1cdd02902f937a18-s.woff2 +0 -0
  474. package/.next/static/media/4c4b3b30b6bcb2be-s.woff2 +0 -0
  475. package/.next/static/media/641a7b8a5800ee0e-s.woff2 +0 -0
  476. package/.next/static/media/7deddc85b7ffd1dc-s.p.woff2 +0 -0
  477. package/.next/static/media/ec14413c594b3356-s.p.woff2 +0 -0
  478. package/.next/static/media/pdf.worker.min.29aaf158.mjs +0 -6
  479. package/.next/trace +0 -74
  480. package/.next/trace-build +0 -1
  481. package/.next/types/app/api/agent/[id]/events/route.ts +0 -351
  482. package/.next/types/app/api/agent/[id]/route.ts +0 -351
  483. package/.next/types/app/api/agent/new/route.ts +0 -351
  484. package/.next/types/app/api/auth/all-providers/route.ts +0 -351
  485. package/.next/types/app/api/auth/api-key/[provider]/route.ts +0 -351
  486. package/.next/types/app/api/auth/login/[provider]/route.ts +0 -351
  487. package/.next/types/app/api/auth/login/route.ts +0 -351
  488. package/.next/types/app/api/auth/logout/[provider]/route.ts +0 -351
  489. package/.next/types/app/api/auth/providers/route.ts +0 -351
  490. package/.next/types/app/api/auth/status/route.ts +0 -351
  491. package/.next/types/app/api/default-cwd/route.ts +0 -351
  492. package/.next/types/app/api/files/[...path]/route.ts +0 -351
  493. package/.next/types/app/api/harness/route.ts +0 -351
  494. package/.next/types/app/api/home/route.ts +0 -351
  495. package/.next/types/app/api/internal/runtime/route.ts +0 -351
  496. package/.next/types/app/api/models/route.ts +0 -351
  497. package/.next/types/app/api/models-config/discover/route.ts +0 -351
  498. package/.next/types/app/api/models-config/route.ts +0 -351
  499. package/.next/types/app/api/models-config/test/route.ts +0 -351
  500. package/.next/types/app/api/projects/browse/route.ts +0 -351
  501. package/.next/types/app/api/projects/route.ts +0 -351
  502. package/.next/types/app/api/reports/[id]/route.ts +0 -351
  503. package/.next/types/app/api/search/route.ts +0 -351
  504. package/.next/types/app/api/sessions/[id]/context/route.ts +0 -351
  505. package/.next/types/app/api/sessions/[id]/route.ts +0 -351
  506. package/.next/types/app/api/sessions/new/route.ts +0 -351
  507. package/.next/types/app/api/sessions/route.ts +0 -351
  508. package/.next/types/app/api/settings/route.ts +0 -351
  509. package/.next/types/app/api/skills/install/route.ts +0 -351
  510. package/.next/types/app/api/skills/route.ts +0 -351
  511. package/.next/types/app/api/skills/search/route.ts +0 -351
  512. package/.next/types/app/api/soul/route.ts +0 -351
  513. package/.next/types/app/api/version/route.ts +0 -351
  514. package/.next/types/app/layout.ts +0 -87
  515. package/.next/types/app/login/page.ts +0 -87
  516. package/.next/types/app/page.ts +0 -87
  517. package/.next/types/package.json +0 -1
  518. package/.next/types/routes.d.ts +0 -106
  519. package/.next/types/validator.ts +0 -376
@@ -0,0 +1,1093 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect, useCallback, useRef } from "react";
4
+ import type { SkillSearchResult } from "@/app/api/skills/search/route";
5
+
6
+ interface Skill {
7
+ name: string;
8
+ description: string;
9
+ filePath: string;
10
+ baseDir: string;
11
+ disableModelInvocation: boolean;
12
+ sourceInfo: {
13
+ source?: string;
14
+ scope?: string;
15
+ };
16
+ }
17
+
18
+ interface InstallStreamEvent {
19
+ type?: "progress" | "done" | "error";
20
+ stage?: string;
21
+ line?: string;
22
+ success?: boolean;
23
+ error?: string;
24
+ }
25
+
26
+ function shortenPath(p: string): string {
27
+ // Match common home dir patterns: /Users/xxx, /home/xxx
28
+ return p.replace(/^\/(?:Users|home)\/[^/]+/, "~");
29
+ }
30
+
31
+ function sourceLabel(skill: Skill): string {
32
+ const src = skill.sourceInfo?.source;
33
+ const scope = skill.sourceInfo?.scope;
34
+ if (scope === "user" || src === "user") return "global";
35
+ if (scope === "project" || src === "project") return "project";
36
+ return "path";
37
+ }
38
+
39
+ function Toggle({
40
+ enabled,
41
+ loading,
42
+ onToggle,
43
+ }: {
44
+ enabled: boolean;
45
+ loading: boolean;
46
+ onToggle: () => void;
47
+ }) {
48
+ return (
49
+ <button
50
+ onClick={onToggle}
51
+ disabled={loading}
52
+ title={
53
+ enabled
54
+ ? "Visible in model prompt — click to disable"
55
+ : "Hidden from model prompt — click to enable"
56
+ }
57
+ style={{
58
+ flexShrink: 0,
59
+ width: 40,
60
+ height: 22,
61
+ borderRadius: 11,
62
+ border: "none",
63
+ padding: 0,
64
+ cursor: loading ? "wait" : "pointer",
65
+ background: enabled ? "var(--accent)" : "var(--border)",
66
+ position: "relative",
67
+ transition: "background 0.18s",
68
+ outline: "none",
69
+ }}
70
+ >
71
+ <span
72
+ style={{
73
+ position: "absolute",
74
+ top: 3,
75
+ left: enabled ? 21 : 3,
76
+ width: 16,
77
+ height: 16,
78
+ borderRadius: "50%",
79
+ background: "var(--bg)",
80
+ boxShadow: "0 1px 4px rgba(0,0,0,0.22)",
81
+ transition: "left 0.18s cubic-bezier(.4,0,.2,1)",
82
+ }}
83
+ />
84
+ </button>
85
+ );
86
+ }
87
+
88
+ function SkillDetail({
89
+ skill,
90
+ cwd,
91
+ onToggle,
92
+ toggling,
93
+ saveError,
94
+ }: {
95
+ skill: Skill;
96
+ cwd: string;
97
+ onToggle: (skill: Skill) => void;
98
+ toggling: boolean;
99
+ saveError: string | null;
100
+ }) {
101
+ const label = sourceLabel(skill);
102
+ const enabled = !skill.disableModelInvocation;
103
+
104
+ function displayPath(p: string): string {
105
+ if (label === "project" && p.startsWith(cwd)) {
106
+ const rel = p.slice(cwd.length).replace(/^[/\\]/, "");
107
+ return `./${rel}`;
108
+ }
109
+ return shortenPath(p);
110
+ }
111
+
112
+ return (
113
+ <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
114
+ {/* Path + tag + toggle */}
115
+ <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
116
+ <span
117
+ style={{
118
+ fontSize: 10,
119
+ padding: "1px 5px",
120
+ borderRadius: 3,
121
+ flexShrink: 0,
122
+ background:
123
+ label === "project"
124
+ ? "rgba(99,102,241,0.12)"
125
+ : "rgba(120,120,120,0.12)",
126
+ color:
127
+ label === "project" ? "rgba(99,102,241,0.8)" : "var(--text-dim)",
128
+ }}
129
+ >
130
+ {label}
131
+ </span>
132
+ <span
133
+ style={{
134
+ fontFamily: "var(--font-mono)",
135
+ fontSize: 11,
136
+ color: "var(--text-dim)",
137
+ flex: 1,
138
+ overflow: "hidden",
139
+ textOverflow: "ellipsis",
140
+ whiteSpace: "nowrap",
141
+ }}
142
+ >
143
+ {displayPath(skill.filePath)}
144
+ </span>
145
+ <Toggle
146
+ enabled={enabled}
147
+ loading={toggling}
148
+ onToggle={() => onToggle(skill)}
149
+ />
150
+ {saveError && (
151
+ <span style={{ fontSize: 12, color: "#f87171", flexShrink: 0 }}>
152
+ {saveError}
153
+ </span>
154
+ )}
155
+ </div>
156
+
157
+ <div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
158
+ <span
159
+ style={{ fontSize: 12, color: "var(--text-muted)", fontWeight: 500 }}
160
+ >
161
+ Name
162
+ </span>
163
+ <span
164
+ style={{
165
+ fontFamily: "var(--font-mono)",
166
+ fontSize: 14,
167
+ color: "var(--text)",
168
+ }}
169
+ >
170
+ {skill.name}
171
+ </span>
172
+ </div>
173
+
174
+ <div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
175
+ <span
176
+ style={{ fontSize: 12, color: "var(--text-muted)", fontWeight: 500 }}
177
+ >
178
+ Description
179
+ </span>
180
+ <span
181
+ style={{ fontSize: 14, color: "var(--text-muted)", lineHeight: 1.6 }}
182
+ >
183
+ {skill.description}
184
+ </span>
185
+ </div>
186
+ </div>
187
+ );
188
+ }
189
+
190
+ function AddSkillPanel({
191
+ cwd,
192
+ onInstalled,
193
+ }: {
194
+ cwd: string;
195
+ onInstalled: () => void;
196
+ }) {
197
+ const [query, setQuery] = useState("");
198
+ const [results, setResults] = useState<SkillSearchResult[]>([]);
199
+ const [searching, setSearching] = useState(false);
200
+ const [searchError, setSearchError] = useState<string | null>(null);
201
+ const [installing, setInstalling] = useState<string | null>(null);
202
+ const [installError, setInstallError] = useState<string | null>(null);
203
+ const [installStage, setInstallStage] = useState<string | null>(null);
204
+ const [installLog, setInstallLog] = useState<string[]>([]);
205
+ const [installedPkgs, setInstalledPkgs] = useState<Set<string>>(new Set());
206
+ const [scope, setScope] = useState<"global" | "project">("global");
207
+ const inputRef = useRef<HTMLInputElement>(null);
208
+ const installAbortRef = useRef<AbortController | null>(null);
209
+
210
+ useEffect(() => {
211
+ inputRef.current?.focus();
212
+ }, []);
213
+
214
+ useEffect(() => {
215
+ return () => {
216
+ installAbortRef.current?.abort();
217
+ };
218
+ }, []);
219
+
220
+ const search = useCallback(async (q: string) => {
221
+ if (!q.trim()) return;
222
+ setSearching(true);
223
+ setSearchError(null);
224
+ setResults([]);
225
+ try {
226
+ const res = await fetch("/api/skills/search", {
227
+ method: "POST",
228
+ headers: { "Content-Type": "application/json" },
229
+ body: JSON.stringify({ query: q.trim() }),
230
+ });
231
+ const d = (await res.json()) as {
232
+ results?: SkillSearchResult[];
233
+ error?: string;
234
+ };
235
+ if (d.error) {
236
+ setSearchError(d.error);
237
+ return;
238
+ }
239
+ setResults(d.results ?? []);
240
+ if ((d.results ?? []).length === 0) setSearchError("No skills found");
241
+ } catch (e) {
242
+ setSearchError(String(e));
243
+ } finally {
244
+ setSearching(false);
245
+ }
246
+ }, []);
247
+
248
+ const install = useCallback(
249
+ async (pkg: string) => {
250
+ const controller = new AbortController();
251
+ installAbortRef.current = controller;
252
+ setInstalling(pkg);
253
+ setInstallError(null);
254
+ setInstallStage("Starting installer");
255
+ setInstallLog(["Starting installer"]);
256
+ try {
257
+ const res = await fetch("/api/skills/install", {
258
+ method: "POST",
259
+ headers: { "Content-Type": "application/json" },
260
+ body: JSON.stringify({ package: pkg, scope, cwd, stream: true }),
261
+ signal: controller.signal,
262
+ });
263
+
264
+ if (!res.ok || !res.body) {
265
+ const d = (await res.json().catch(() => null)) as { error?: string } | null;
266
+ setInstallError(d?.error ?? `HTTP ${res.status}`);
267
+ return;
268
+ }
269
+
270
+ const reader = res.body.getReader();
271
+ const decoder = new TextDecoder();
272
+ let buffer = "";
273
+ let installed = false;
274
+
275
+ const handleEvent = (event: InstallStreamEvent) => {
276
+ if (event.type === "progress") {
277
+ if (event.stage) setInstallStage(event.stage);
278
+ if (event.line) {
279
+ setInstallLog((prev) => {
280
+ const next = prev.at(-1) === event.line ? prev : [...prev, event.line!];
281
+ return next.slice(-8);
282
+ });
283
+ }
284
+ } else if (event.type === "done" && event.success) {
285
+ installed = true;
286
+ setInstallStage("Installed");
287
+ setInstallLog((prev) => [...prev, "Installed"].slice(-8));
288
+ } else if (event.type === "error") {
289
+ setInstallError(event.error ?? "Install failed");
290
+ }
291
+ };
292
+
293
+ while (true) {
294
+ const { value, done } = await reader.read();
295
+ buffer += decoder.decode(value ?? new Uint8Array(), { stream: !done });
296
+ const lines = buffer.split("\n");
297
+ buffer = lines.pop() ?? "";
298
+ for (const line of lines) {
299
+ if (!line.trim()) continue;
300
+ handleEvent(JSON.parse(line) as InstallStreamEvent);
301
+ }
302
+ if (done) break;
303
+ }
304
+
305
+ if (buffer.trim()) handleEvent(JSON.parse(buffer) as InstallStreamEvent);
306
+
307
+ if (installed) {
308
+ setInstalledPkgs((prev) => new Set(prev).add(pkg));
309
+ onInstalled();
310
+ }
311
+ } catch (e) {
312
+ if (controller.signal.aborted) {
313
+ setInstallStage("Canceled");
314
+ setInstallLog((prev) => [...prev, "Canceled"].slice(-8));
315
+ } else {
316
+ setInstallError(String(e));
317
+ }
318
+ } finally {
319
+ if (installAbortRef.current === controller) installAbortRef.current = null;
320
+ setInstalling(null);
321
+ }
322
+ },
323
+ [onInstalled, scope, cwd],
324
+ );
325
+
326
+ const cancelInstall = useCallback(() => {
327
+ installAbortRef.current?.abort();
328
+ }, []);
329
+
330
+ const installPath =
331
+ scope === "global"
332
+ ? "~/.codex/skills/"
333
+ : `${shortenPath(cwd)}/.codex/skills/`;
334
+
335
+ return (
336
+ <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
337
+ {/* ── Header area ── */}
338
+ <div
339
+ style={{
340
+ display: "flex",
341
+ flexDirection: "column",
342
+ gap: 12,
343
+ marginBottom: 20,
344
+ }}
345
+ >
346
+ <div style={{ fontSize: 14, fontWeight: 600, color: "var(--text)" }}>
347
+ Add Skill
348
+ </div>
349
+
350
+ {/* Search row */}
351
+ <div style={{ display: "flex", gap: 8 }}>
352
+ <input
353
+ ref={inputRef}
354
+ value={query}
355
+ onChange={(e) => setQuery(e.target.value)}
356
+ onKeyDown={(e) => {
357
+ if (e.key === "Enter") search(query);
358
+ }}
359
+ placeholder="e.g. react, testing, deploy"
360
+ style={{
361
+ flex: 1,
362
+ padding: "7px 10px",
363
+ fontSize: 13,
364
+ background: "var(--bg-panel)",
365
+ border: "1px solid var(--border)",
366
+ borderRadius: 6,
367
+ color: "var(--text)",
368
+ outline: "none",
369
+ }}
370
+ />
371
+ <button
372
+ onClick={() => search(query)}
373
+ disabled={searching || !query.trim()}
374
+ style={{
375
+ padding: "7px 16px",
376
+ fontSize: 13,
377
+ borderRadius: 6,
378
+ border: "none",
379
+ background: "var(--accent)",
380
+ color: "#fff",
381
+ cursor: searching || !query.trim() ? "not-allowed" : "pointer",
382
+ opacity: searching || !query.trim() ? 0.5 : 1,
383
+ flexShrink: 0,
384
+ }}
385
+ >
386
+ {searching ? "Searching…" : "Search"}
387
+ </button>
388
+ </div>
389
+
390
+ {/* Scope + install path row */}
391
+ <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
392
+ <div
393
+ style={{
394
+ display: "flex",
395
+ borderRadius: 5,
396
+ border: "1px solid var(--border)",
397
+ overflow: "hidden",
398
+ fontSize: 12,
399
+ flexShrink: 0,
400
+ }}
401
+ >
402
+ {(["global", "project"] as const).map((s) => (
403
+ <button
404
+ key={s}
405
+ onClick={() => setScope(s)}
406
+ style={{
407
+ padding: "3px 10px",
408
+ border: "none",
409
+ cursor: "pointer",
410
+ background: scope === s ? "var(--bg-selected)" : "none",
411
+ color: scope === s ? "var(--text)" : "var(--text-dim)",
412
+ fontWeight: scope === s ? 600 : 400,
413
+ borderRight:
414
+ s === "global" ? "1px solid var(--border)" : "none",
415
+ }}
416
+ >
417
+ {s}
418
+ </button>
419
+ ))}
420
+ </div>
421
+ <span
422
+ style={{
423
+ fontSize: 12,
424
+ color: "var(--text-dim)",
425
+ fontFamily: "var(--font-mono)",
426
+ overflow: "hidden",
427
+ textOverflow: "ellipsis",
428
+ whiteSpace: "nowrap",
429
+ }}
430
+ >
431
+ → {installPath}
432
+ </span>
433
+ </div>
434
+
435
+ {/* Errors */}
436
+ {searchError && (
437
+ <div style={{ fontSize: 12, color: "#f87171" }}>{searchError}</div>
438
+ )}
439
+ {installError && (
440
+ <div
441
+ style={{ fontSize: 12, color: "#f87171", wordBreak: "break-word" }}
442
+ >
443
+ {installError}
444
+ </div>
445
+ )}
446
+ {installing && (
447
+ <div
448
+ style={{
449
+ border: "1px solid var(--border)",
450
+ borderRadius: 6,
451
+ background: "var(--bg-panel)",
452
+ padding: 10,
453
+ display: "flex",
454
+ flexDirection: "column",
455
+ gap: 8,
456
+ }}
457
+ >
458
+ <div
459
+ style={{
460
+ display: "flex",
461
+ alignItems: "center",
462
+ gap: 10,
463
+ }}
464
+ >
465
+ <div
466
+ style={{
467
+ width: 10,
468
+ height: 10,
469
+ borderRadius: "50%",
470
+ border: "2px solid var(--border)",
471
+ borderTopColor: "var(--accent)",
472
+ animation: "spin 0.8s linear infinite",
473
+ flexShrink: 0,
474
+ }}
475
+ />
476
+ <div style={{ flex: 1, minWidth: 0 }}>
477
+ <div
478
+ style={{
479
+ fontSize: 12,
480
+ fontWeight: 600,
481
+ color: "var(--text)",
482
+ overflow: "hidden",
483
+ textOverflow: "ellipsis",
484
+ whiteSpace: "nowrap",
485
+ }}
486
+ >
487
+ {installStage ?? "Installing"}
488
+ </div>
489
+ <div
490
+ style={{
491
+ fontFamily: "var(--font-mono)",
492
+ fontSize: 11,
493
+ color: "var(--text-dim)",
494
+ overflow: "hidden",
495
+ textOverflow: "ellipsis",
496
+ whiteSpace: "nowrap",
497
+ }}
498
+ >
499
+ {installing}
500
+ </div>
501
+ </div>
502
+ <button
503
+ onClick={cancelInstall}
504
+ style={{
505
+ padding: "4px 9px",
506
+ fontSize: 12,
507
+ borderRadius: 5,
508
+ border: "1px solid var(--border)",
509
+ background: "none",
510
+ color: "var(--text-muted)",
511
+ cursor: "pointer",
512
+ flexShrink: 0,
513
+ }}
514
+ >
515
+ Cancel
516
+ </button>
517
+ </div>
518
+ {installLog.length > 0 && (
519
+ <div
520
+ style={{
521
+ maxHeight: 120,
522
+ overflow: "auto",
523
+ fontFamily: "var(--font-mono)",
524
+ fontSize: 11,
525
+ lineHeight: 1.6,
526
+ color: "var(--text-dim)",
527
+ borderTop: "1px solid var(--border)",
528
+ paddingTop: 8,
529
+ }}
530
+ >
531
+ {installLog.map((line, index) => (
532
+ <div key={`${index}-${line}`}>{line}</div>
533
+ ))}
534
+ </div>
535
+ )}
536
+ </div>
537
+ )}
538
+ </div>
539
+
540
+ {/* ── Results list ── */}
541
+ {results.length > 0 ? (
542
+ <div style={{ flex: 1, overflowY: "auto" }}>
543
+ {results.map((r) => {
544
+ const isInstalled = installedPkgs.has(r.package);
545
+ const isInstalling = installing === r.package;
546
+ // split "owner/repo@skill" for cleaner display
547
+ const atIdx = r.package.indexOf("@");
548
+ const repopart = atIdx > -1 ? r.package.slice(0, atIdx) : r.package;
549
+ const skillpart = atIdx > -1 ? r.package.slice(atIdx + 1) : null;
550
+ return (
551
+ <div
552
+ key={r.package}
553
+ style={{
554
+ display: "flex",
555
+ alignItems: "center",
556
+ gap: 14,
557
+ padding: "12px 0",
558
+ borderBottom: "1px solid var(--border)",
559
+ }}
560
+ >
561
+ <div style={{ flex: 1, minWidth: 0 }}>
562
+ {/* skill name prominent */}
563
+ <div
564
+ style={{
565
+ fontSize: 13,
566
+ fontWeight: 600,
567
+ color: "var(--text)",
568
+ marginBottom: 3,
569
+ }}
570
+ >
571
+ {skillpart ?? repopart}
572
+ </div>
573
+ {/* repo + installs + link row */}
574
+ <div
575
+ style={{
576
+ display: "flex",
577
+ alignItems: "center",
578
+ gap: 10,
579
+ flexWrap: "wrap",
580
+ }}
581
+ >
582
+ <span
583
+ style={{
584
+ fontFamily: "var(--font-mono)",
585
+ fontSize: 11,
586
+ color: "var(--text-dim)",
587
+ }}
588
+ >
589
+ {repopart}
590
+ </span>
591
+ <span
592
+ style={{
593
+ fontSize: 12,
594
+ color: "var(--text-muted)",
595
+ fontWeight: 500,
596
+ }}
597
+ >
598
+ {r.installs}
599
+ </span>
600
+ {r.url && (
601
+ <a
602
+ href={r.url}
603
+ target="_blank"
604
+ rel="noreferrer"
605
+ style={{
606
+ fontSize: 12,
607
+ color: "var(--accent)",
608
+ textDecoration: "none",
609
+ }}
610
+ >
611
+ skills.sh ↗
612
+ </a>
613
+ )}
614
+ </div>
615
+ </div>
616
+ <button
617
+ onClick={() => {
618
+ if (!isInstalled && installing === null) install(r.package);
619
+ }}
620
+ disabled={isInstalled || installing !== null}
621
+ style={{
622
+ flexShrink: 0,
623
+ padding: "5px 14px",
624
+ fontSize: 12,
625
+ fontWeight: 500,
626
+ borderRadius: 5,
627
+ border: "1px solid var(--border)",
628
+ cursor:
629
+ isInstalling
630
+ ? "wait"
631
+ : isInstalled || installing !== null
632
+ ? "not-allowed"
633
+ : "pointer",
634
+ background: isInstalled
635
+ ? "rgba(34,197,94,0.1)"
636
+ : isInstalling
637
+ ? "rgba(59,130,246,0.08)"
638
+ : "none",
639
+ color: isInstalled
640
+ ? "#16a34a"
641
+ : isInstalling
642
+ ? "var(--accent)"
643
+ : "var(--text-muted)",
644
+ transition: "color 0.12s",
645
+ }}
646
+ >
647
+ {isInstalled
648
+ ? "✓ Installed"
649
+ : isInstalling
650
+ ? "Installing"
651
+ : "Install"}
652
+ </button>
653
+ </div>
654
+ );
655
+ })}
656
+ </div>
657
+ ) : (
658
+ !searchError &&
659
+ !searching && (
660
+ <div
661
+ style={{ fontSize: 13, color: "var(--text-dim)", lineHeight: 1.8 }}
662
+ >
663
+ Search{" "}
664
+ <a
665
+ href="https://skills.sh"
666
+ target="_blank"
667
+ rel="noreferrer"
668
+ style={{ color: "var(--accent)", textDecoration: "none" }}
669
+ >
670
+ skills.sh
671
+ </a>{" "}
672
+ to discover and install skills for your agent.
673
+ </div>
674
+ )
675
+ )}
676
+ </div>
677
+ );
678
+ }
679
+
680
+ export function SkillsConfig({
681
+ cwd,
682
+ onClose,
683
+ embedded = false,
684
+ }: {
685
+ cwd: string;
686
+ onClose: () => void;
687
+ embedded?: boolean;
688
+ }) {
689
+ const [skills, setSkills] = useState<Skill[]>([]);
690
+ const [loading, setLoading] = useState(true);
691
+ const [error, setError] = useState<string | null>(null);
692
+ const [selected, setSelected] = useState<string | null>(null);
693
+ const [toggling, setToggling] = useState<Set<string>>(new Set());
694
+ const [saveError, setSaveError] = useState<string | null>(null);
695
+ const [addMode, setAddMode] = useState(false);
696
+
697
+ const loadSkills = useCallback(() => {
698
+ setLoading(true);
699
+ setError(null);
700
+ fetch(`/api/skills?cwd=${encodeURIComponent(cwd)}`)
701
+ .then((r) => r.json())
702
+ .then((d: { skills?: Skill[]; error?: string }) => {
703
+ if (d.error) {
704
+ setError(d.error);
705
+ return;
706
+ }
707
+ const list = d.skills ?? [];
708
+ setSkills(list);
709
+ if (list.length > 0 && !selected) setSelected(list[0].filePath);
710
+ })
711
+ .catch((e) => setError(String(e)))
712
+ .finally(() => setLoading(false));
713
+ }, [cwd, selected]);
714
+
715
+ useEffect(() => {
716
+ loadSkills();
717
+ }, [cwd]); // eslint-disable-line react-hooks/exhaustive-deps
718
+
719
+ const toggle = useCallback(async (skill: Skill) => {
720
+ const next = !skill.disableModelInvocation;
721
+ setToggling((s) => new Set(s).add(skill.filePath));
722
+ setSaveError(null);
723
+ try {
724
+ const res = await fetch("/api/skills", {
725
+ method: "PATCH",
726
+ headers: { "Content-Type": "application/json" },
727
+ body: JSON.stringify({
728
+ filePath: skill.filePath,
729
+ disableModelInvocation: next,
730
+ }),
731
+ });
732
+ const d = (await res.json()) as { success?: boolean; error?: string };
733
+ if (!res.ok || d.error) {
734
+ setSaveError(d.error ?? `HTTP ${res.status}`);
735
+ return;
736
+ }
737
+ setSkills((prev) =>
738
+ prev.map((s) =>
739
+ s.filePath === skill.filePath
740
+ ? { ...s, disableModelInvocation: next }
741
+ : s,
742
+ ),
743
+ );
744
+ } catch (e) {
745
+ setSaveError(String(e));
746
+ } finally {
747
+ setToggling((s) => {
748
+ const n = new Set(s);
749
+ n.delete(skill.filePath);
750
+ return n;
751
+ });
752
+ }
753
+ }, []);
754
+
755
+ const selectedSkill = skills.find((s) => s.filePath === selected) ?? null;
756
+
757
+ return (
758
+ <div
759
+ style={embedded
760
+ ? {
761
+ height: "100%",
762
+ minHeight: 0,
763
+ display: "flex",
764
+ alignItems: "stretch",
765
+ justifyContent: "stretch",
766
+ }
767
+ : {
768
+ position: "fixed",
769
+ inset: 0,
770
+ zIndex: 1000,
771
+ background: "rgba(0,0,0,0.35)",
772
+ display: "flex",
773
+ alignItems: "center",
774
+ justifyContent: "center",
775
+ }}
776
+ onClick={(e) => {
777
+ if (!embedded && e.target === e.currentTarget) onClose();
778
+ }}
779
+ >
780
+ <div
781
+ style={{
782
+ width: embedded ? "100%" : 860,
783
+ height: embedded ? "100%" : "78vh",
784
+ background: "var(--bg)",
785
+ border: embedded ? "none" : "1px solid var(--border)",
786
+ borderRadius: embedded ? 0 : 10,
787
+ display: "flex",
788
+ flexDirection: "column",
789
+ boxShadow: embedded ? "none" : "0 8px 32px rgba(0,0,0,0.18)",
790
+ overflow: "hidden",
791
+ }}
792
+ >
793
+ {/* Header */}
794
+ {!embedded && <div
795
+ style={{
796
+ display: "flex",
797
+ alignItems: "center",
798
+ justifyContent: "space-between",
799
+ padding: "12px 18px",
800
+ borderBottom: "1px solid var(--border)",
801
+ flexShrink: 0,
802
+ }}
803
+ >
804
+ <div style={{ display: "flex", alignItems: "baseline", gap: 10 }}>
805
+ <span
806
+ style={{ fontSize: 15, fontWeight: 700, color: "var(--text)" }}
807
+ >
808
+ Skills
809
+ </span>
810
+ <code
811
+ style={{
812
+ fontSize: 11,
813
+ color: "var(--text-muted)",
814
+ fontFamily: "var(--font-mono)",
815
+ maxWidth: 320,
816
+ overflow: "hidden",
817
+ textOverflow: "ellipsis",
818
+ whiteSpace: "nowrap",
819
+ }}
820
+ >
821
+ {shortenPath(cwd)}
822
+ </code>
823
+ </div>
824
+ <button
825
+ onClick={onClose}
826
+ style={{
827
+ background: "none",
828
+ border: "none",
829
+ color: "var(--text-muted)",
830
+ cursor: "pointer",
831
+ fontSize: 20,
832
+ lineHeight: 1,
833
+ padding: "2px 6px",
834
+ }}
835
+ >
836
+ ×
837
+ </button>
838
+ </div>}
839
+
840
+ {/* Body */}
841
+ <div style={{ flex: 1, display: "flex", overflow: "hidden" }}>
842
+ {/* Left: skill list */}
843
+ <div
844
+ style={{
845
+ width: 210,
846
+ borderRight: "1px solid var(--border)",
847
+ display: "flex",
848
+ flexDirection: "column",
849
+ flexShrink: 0,
850
+ background: "var(--bg-panel)",
851
+ }}
852
+ >
853
+ <div style={{ flex: 1, overflowY: "auto", padding: "8px 6px" }}>
854
+ {loading ? (
855
+ <div
856
+ style={{
857
+ padding: "10px 8px",
858
+ fontSize: 12,
859
+ color: "var(--text-muted)",
860
+ }}
861
+ >
862
+ Loading…
863
+ </div>
864
+ ) : error ? (
865
+ <div
866
+ style={{
867
+ padding: "10px 8px",
868
+ fontSize: 11,
869
+ color: "#f87171",
870
+ }}
871
+ >
872
+ {error}
873
+ </div>
874
+ ) : skills.length === 0 ? (
875
+ <div
876
+ style={{
877
+ padding: "10px 8px",
878
+ fontSize: 11,
879
+ color: "var(--text-dim)",
880
+ }}
881
+ >
882
+ No skills found
883
+ </div>
884
+ ) : (
885
+ (() => {
886
+ const groups: { label: string; skills: typeof skills }[] = [];
887
+ for (const grpLabel of ["project", "global", "path"]) {
888
+ const grpSkills = skills.filter(
889
+ (s) => sourceLabel(s) === grpLabel,
890
+ );
891
+ if (grpSkills.length > 0)
892
+ groups.push({ label: grpLabel, skills: grpSkills });
893
+ }
894
+ return groups.map(
895
+ ({ label: grpLabel, skills: grpSkills }) => (
896
+ <div key={grpLabel} style={{ marginBottom: 6 }}>
897
+ <div
898
+ style={{
899
+ padding: "4px 8px 3px",
900
+ fontSize: 10,
901
+ fontWeight: 600,
902
+ color: "var(--text-dim)",
903
+ textTransform: "uppercase",
904
+ letterSpacing: "0.06em",
905
+ }}
906
+ >
907
+ {grpLabel}
908
+ </div>
909
+ {grpSkills.map((skill) => {
910
+ const isSelected =
911
+ !addMode && selected === skill.filePath;
912
+ const disabled = skill.disableModelInvocation;
913
+ return (
914
+ <div
915
+ key={skill.filePath}
916
+ onClick={() => {
917
+ setSelected(skill.filePath);
918
+ setAddMode(false);
919
+ }}
920
+ style={{
921
+ display: "flex",
922
+ alignItems: "center",
923
+ gap: 7,
924
+ padding: "8px 8px",
925
+ borderRadius: 5,
926
+ cursor: "pointer",
927
+ background: isSelected
928
+ ? "var(--bg-selected)"
929
+ : "none",
930
+ }}
931
+ onMouseEnter={(e) => {
932
+ if (!isSelected)
933
+ e.currentTarget.style.background =
934
+ "var(--bg-hover)";
935
+ }}
936
+ onMouseLeave={(e) => {
937
+ if (!isSelected)
938
+ e.currentTarget.style.background = "none";
939
+ }}
940
+ >
941
+ <span
942
+ style={{
943
+ flexShrink: 0,
944
+ width: 7,
945
+ height: 7,
946
+ borderRadius: "50%",
947
+ background: disabled
948
+ ? "var(--border)"
949
+ : "var(--accent)",
950
+ boxShadow: disabled
951
+ ? "none"
952
+ : "0 0 4px var(--accent)",
953
+ transition:
954
+ "background 0.15s, box-shadow 0.15s",
955
+ }}
956
+ />
957
+ <span
958
+ style={{
959
+ fontSize: 12,
960
+ fontWeight: isSelected ? 600 : 400,
961
+ color: disabled
962
+ ? "var(--text-dim)"
963
+ : "var(--text)",
964
+ fontFamily: "var(--font-mono)",
965
+ flex: 1,
966
+ overflow: "hidden",
967
+ textOverflow: "ellipsis",
968
+ whiteSpace: "nowrap",
969
+ }}
970
+ >
971
+ {skill.name}
972
+ </span>
973
+ </div>
974
+ );
975
+ })}
976
+ </div>
977
+ ),
978
+ );
979
+ })()
980
+ )}
981
+ </div>
982
+ {/* Add skill button */}
983
+ <div
984
+ style={{
985
+ padding: "8px 6px",
986
+ borderTop: "1px solid var(--border)",
987
+ flexShrink: 0,
988
+ }}
989
+ >
990
+ <div
991
+ onClick={() => setAddMode(true)}
992
+ style={{
993
+ display: "flex",
994
+ alignItems: "center",
995
+ gap: 6,
996
+ padding: "7px 8px",
997
+ borderRadius: 5,
998
+ cursor: "pointer",
999
+ background: addMode ? "var(--bg-selected)" : "none",
1000
+ color: addMode ? "var(--accent)" : "var(--text-dim)",
1001
+ fontSize: 12,
1002
+ }}
1003
+ onMouseEnter={(e) => {
1004
+ if (!addMode)
1005
+ e.currentTarget.style.background = "var(--bg-hover)";
1006
+ }}
1007
+ onMouseLeave={(e) => {
1008
+ if (!addMode) e.currentTarget.style.background = "none";
1009
+ }}
1010
+ >
1011
+ <svg
1012
+ width="13"
1013
+ height="13"
1014
+ viewBox="0 0 24 24"
1015
+ fill="none"
1016
+ stroke="currentColor"
1017
+ strokeWidth="2"
1018
+ strokeLinecap="round"
1019
+ strokeLinejoin="round"
1020
+ >
1021
+ <line x1="12" y1="5" x2="12" y2="19" />
1022
+ <line x1="5" y1="12" x2="19" y2="12" />
1023
+ </svg>
1024
+ Add skill
1025
+ </div>
1026
+ </div>
1027
+ </div>
1028
+
1029
+ {/* Right: detail or add panel */}
1030
+ <div style={{ flex: 1, overflowY: "auto", padding: 20 }}>
1031
+ {addMode ? (
1032
+ <AddSkillPanel
1033
+ cwd={cwd}
1034
+ onInstalled={() => {
1035
+ loadSkills();
1036
+ }}
1037
+ />
1038
+ ) : loading ? null : selectedSkill ? (
1039
+ <SkillDetail
1040
+ key={selectedSkill.filePath}
1041
+ skill={selectedSkill}
1042
+ cwd={cwd}
1043
+ onToggle={toggle}
1044
+ toggling={toggling.has(selectedSkill.filePath)}
1045
+ saveError={saveError}
1046
+ />
1047
+ ) : (
1048
+ <div
1049
+ style={{
1050
+ height: "100%",
1051
+ display: "flex",
1052
+ alignItems: "center",
1053
+ justifyContent: "center",
1054
+ color: "var(--text-dim)",
1055
+ fontSize: 13,
1056
+ }}
1057
+ >
1058
+ Select a skill
1059
+ </div>
1060
+ )}
1061
+ </div>
1062
+ </div>
1063
+
1064
+ {/* Footer */}
1065
+ <div
1066
+ style={{
1067
+ display: "flex",
1068
+ alignItems: "center",
1069
+ justifyContent: "flex-end",
1070
+ padding: "10px 18px",
1071
+ borderTop: "1px solid var(--border)",
1072
+ flexShrink: 0,
1073
+ }}
1074
+ >
1075
+ <button
1076
+ onClick={onClose}
1077
+ style={{
1078
+ padding: "6px 14px",
1079
+ background: "none",
1080
+ border: "1px solid var(--border)",
1081
+ borderRadius: 6,
1082
+ color: "var(--text-muted)",
1083
+ cursor: "pointer",
1084
+ fontSize: 13,
1085
+ }}
1086
+ >
1087
+ Close
1088
+ </button>
1089
+ </div>
1090
+ </div>
1091
+ </div>
1092
+ );
1093
+ }